"""Tests for news API input validation (PR #1939). Verifies: - Limit parameter clamped to [1, 200] - JSON body validation via @require_json_body decorator """ import inspect class TestLimitClamping: """Verify limit parameters are clamped to safe range.""" def test_get_news_feed_clamps_limit(self): from local_deep_research.web.routes.news_routes import get_news_feed source = inspect.getsource(get_news_feed) assert "max(1, min(limit, 200))" in source def test_get_subscription_history_clamps_limit(self): from local_deep_research.web.routes.news_routes import ( get_subscription_history, ) source = inspect.getsource(get_subscription_history) assert "max(1, min(limit, 200))" in source class TestJSONBodyValidation: """Verify endpoints reject missing/empty JSON body. These endpoints use the @require_json_body decorator which validates that the request body is a JSON dict before the handler runs. """ def _check_has_json_guard(self, func_name): """Verify the endpoint is protected by @require_json_body.""" import local_deep_research.web.routes.news_routes as mod func = getattr(mod, func_name) # The decorator wraps the function, so check the decorator chain. # inspect.getsource on the module-level function includes decorators. source = inspect.getsource(func) # Either protected by @require_json_body decorator or inline check has_decorator = "@require_json_body" in source has_inline = ( "if data is None" in source or "if preferences is None" in source ) assert has_decorator or has_inline, ( f"{func_name} is missing JSON body validation — " f"add @require_json_body or an inline 'if data is None' check" ) def test_create_subscription_validates_json(self): self._check_has_json_guard("create_subscription") def test_update_subscription_validates_json(self): self._check_has_json_guard("update_subscription") def test_submit_feedback_validates_json(self): self._check_has_json_guard("submit_feedback") def test_research_news_item_validates_json(self): self._check_has_json_guard("research_news_item") def test_save_preferences_validates_json(self): self._check_has_json_guard("save_preferences")