import os import unittest from unittest.mock import patch from app.search_provider import ProviderConfigError, provider_status, search class SearchProviderTests(unittest.TestCase): def tearDown(self): for key in ("SEARCH_PROVIDER_URL", "SEARCH_PROVIDER_ALLOWED_HOSTS", "SEARCH_PROVIDER_API_KEY"): os.environ.pop(key, None) def test_not_configured_is_fail_closed(self): self.assertEqual(provider_status()["status"], "not_configured") with self.assertRaisesRegex(ProviderConfigError, "not_configured"): search({"keywords": ["solar"]}, 5) def test_unsafe_provider_is_rejected(self): os.environ["SEARCH_PROVIDER_URL"] = "http://search.example.test/query" os.environ["SEARCH_PROVIDER_ALLOWED_HOSTS"] = "search.example.test" self.assertEqual(provider_status()["status"], "unsafe_configured") with self.assertRaisesRegex(ProviderConfigError, "unsafe_provider"): search({}, 5) def test_successful_mocked_search_returns_bounded_https_urls(self): os.environ["SEARCH_PROVIDER_URL"] = "https://search.example.test/query" os.environ["SEARCH_PROVIDER_ALLOWED_HOSTS"] = "search.example.test" response = type("Response", (), {"__enter__": lambda self: self, "__exit__": lambda self, *args: None, "read": lambda self, *_: b'{"results":[{"url":"https://acme.test"},{"url":"http://bad.test"},{"url":"https://acme.test"}]}'})() with patch("app.search_provider.urlopen", return_value=response), patch("app.search_provider.validate_url", side_effect=lambda url, **_: url): self.assertEqual(search({"keywords": ["solar"]}, 5), ["https://acme.test"]) def test_limit_is_bounded_and_sent_to_provider(self): os.environ["SEARCH_PROVIDER_URL"] = "https://search.example.test/query" os.environ["SEARCH_PROVIDER_ALLOWED_HOSTS"] = "search.example.test" response = type("Response", (), {"__enter__": lambda self: self, "__exit__": lambda self, *args: None, "read": lambda self, *_: b'{"results":[]}'})() with patch("app.search_provider.urlopen", return_value=response) as opened: self.assertEqual(search({}, 500), []) self.assertEqual(opened.call_args.kwargs["timeout"], 8) request = opened.call_args.args[0] self.assertIn(b'"limit":50', request.data) if __name__ == "__main__": unittest.main()