""" Unit tests for routes/help.py — the public "Was this page helpful?" endpoint. Firestore is mocked; these check validation, what is stored, and rate limiting. """ from unittest.mock import MagicMock, patch import pytest from fastapi import HTTPException from pydantic import ValidationError from routes import help as help_routes from routes.help import FeedbackIn, submit_feedback @pytest.fixture(autouse=True) def _reset_limits(): help_routes._hits.clear() def _body(**over): base = dict(pageId="your-account/reset-password", pageVersion="13 October 2026", vote="no", reason="steps_failed", comment=" the link expired ", sessionId="sess-1", device="mobile") base.update(over) return FeedbackIn(**base) def test_stores_vote_without_any_user_identity(): db = MagicMock() with patch.object(help_routes.firestore, "client", return_value=db): assert submit_feedback(_body()) == {"success": True} stored = db.collection.return_value.add.call_args[0][0] assert stored["vote"] == "no" and stored["reason"] == "steps_failed" assert stored["comment"] == "the link expired" assert stored["deidentified"] is False and stored["deidentifyAfter"] > 0 assert not ({"uid", "email", "name"} & set(stored)) def test_unknown_reason_is_dropped(): db = MagicMock() with patch.object(help_routes.firestore, "client", return_value=db): submit_feedback(_body(reason="made-up")) assert db.collection.return_value.add.call_args[0][0]["reason"] is None def test_rejects_bad_page_id_and_long_comment(): with pytest.raises(ValidationError): _body(pageId="../etc/passwd") with pytest.raises(ValidationError): _body(comment="x" * 1001) def test_rate_limits_a_single_session(): db = MagicMock() with patch.object(help_routes.firestore, "client", return_value=db): for _ in range(help_routes.PER_SESSION_LIMIT[0]): submit_feedback(_body()) with pytest.raises(HTTPException) as exc: submit_feedback(_body()) assert exc.value.status_code == 429