"""Unit tests for src/connectors/hive.py.""" from unittest.mock import MagicMock, patch import httpx import pytest from src.connectors import hive def _mock_client_post(response_json=None, raise_error=None): """Return a mock httpx.Client context manager that yields a mock POST response.""" mock_response = MagicMock() if raise_error: mock_response.raise_for_status.side_effect = raise_error else: mock_response.raise_for_status.return_value = None mock_response.json.return_value = response_json mock_client_instance = MagicMock() mock_client_instance.__enter__ = MagicMock(return_value=mock_client_instance) mock_client_instance.__exit__ = MagicMock(return_value=False) mock_client_instance.post.return_value = mock_response return mock_client_instance @patch("src.connectors.hive.httpx_retries.RetryTransport") @patch("httpx.Client") def test_run_task_success(mock_client, mock_transport, hive_success_response): """run_task returns block_text extracted from a successful Hive API response.""" mock_client.return_value = _mock_client_post(response_json=hive_success_response) result = hive.run_task("http://example.com/asset.jpg") assert result == "Sample extracted text from image" mock_client.return_value.post.assert_called_once() @patch("src.connectors.hive.httpx_retries.RetryTransport") @patch("httpx.Client") def test_run_task_raises_on_http_error(mock_client, mock_transport): """run_task raises HTTPStatusError when the API responds with an error status.""" http_error = httpx.HTTPStatusError( "Server Error", request=MagicMock(), response=MagicMock() ) mock_client.return_value = _mock_client_post(raise_error=http_error) with pytest.raises(httpx.HTTPStatusError): hive.run_task("http://example.com/asset.jpg") @patch("src.connectors.hive.httpx_retries.RetryTransport") @patch("httpx.Client") def test_run_task_returns_empty_string_block_text( mock_client, mock_transport, hive_empty_string_response ): """run_task accepts an empty string block_text as a valid OCR result.""" mock_client.return_value = _mock_client_post( response_json=hive_empty_string_response ) result = hive.run_task("http://example.com/asset.jpg") assert result == "" @patch("src.connectors.hive.httpx_retries.RetryTransport") @patch("httpx.Client") def test_run_task_raises_on_none_block_text( mock_client, mock_transport, hive_none_block_text_response ): """run_task raises when Hive returns an explicit null block_text.""" mock_client.return_value = _mock_client_post( response_json=hive_none_block_text_response ) with pytest.raises(Exception, match="Unexpected Hive text recognition result"): hive.run_task("http://example.com/asset.jpg") @patch("src.connectors.hive.httpx_retries.RetryTransport") @patch("httpx.Client") def test_run_task_raises_on_empty_output( mock_client, mock_transport, hive_empty_output_response ): """run_task raises Exception when the response contains no output entries.""" mock_client.return_value = _mock_client_post( response_json=hive_empty_output_response ) with pytest.raises(Exception, match="Unexpected Hive text recognition result"): hive.run_task("http://example.com/asset.jpg") @patch("src.connectors.hive.httpx_retries.RetryTransport") @patch("httpx.Client") def test_run_task_raises_on_missing_status(mock_client, mock_transport): """run_task raises Exception when the response has no 'status' key.""" mock_client.return_value = _mock_client_post(response_json={}) with pytest.raises(Exception, match="Unexpected Hive text recognition result"): hive.run_task("http://example.com/asset.jpg") @patch("src.connectors.hive.httpx_retries.RetryTransport") @patch("httpx.Client") def test_run_task_sends_correct_payload( mock_client, mock_transport, hive_success_response ): """run_task POSTs the asset URL to the Hive sync endpoint.""" asset_url = "http://example.com/asset.jpg" mock_client.return_value = _mock_client_post(response_json=hive_success_response) hive.run_task(asset_url) _, call_kwargs = mock_client.return_value.post.call_args assert call_kwargs["json"] == {"url": asset_url}