# #region TestAgentChat.ModelFixtures [C:2] [TYPE Module] [SEMANTICS test,agent,fixtures,model] # @BRIEF Materialize model fixtures from JSON — verify fixture structure matches expected. # @RELATION BINDS_TO -> [AgentChat.Model] import json from pathlib import Path import pytest FIXTURES_DIR = Path(__file__).resolve().parent.parent.parent.parent / "specs" / "033-gradio-agent-chat" / "fixtures" / "model" # #region TestAgentChat.ModelFixtures.SendMessageValid [C:2] [TYPE Function] [SEMANTICS test,fixture,send] # @BRIEF FX_AgentChat.Model.SendMessage.Valid — verify fixture structure. def test_fixture_send_message_valid(): """Load send_message_valid fixture and verify structural integrity.""" fixture_path = FIXTURES_DIR / "send_message_valid.json" assert fixture_path.exists(), f"Fixture not found: {fixture_path}" with open(fixture_path) as f: fixture = json.load(f) assert fixture["fixture_id"] == "FX_AgentChat.Model.SendMessage.Valid" assert fixture["verifies"] == "AgentChat.Model" assert fixture["invariant"] == "StreamingStateGatesInput" assert fixture["input"]["action"] == "sendMessage" assert fixture["input"]["state_before"]["streamingState"] == "idle" assert fixture["expected"]["state_after"]["streamingState"] == "streaming" assert fixture["expected"]["state_after"]["isInputLocked"] is True assert fixture["expected"]["state_after"]["error"] is None # #endregion TestAgentChat.ModelFixtures.SendMessageValid # #region TestAgentChat.ModelFixtures.CancelGeneration [C:2] [TYPE Function] [SEMANTICS test,fixture,cancel] # @BRIEF FX_AgentChat.Model.CancelGeneration — verify cancel fixture structure. def test_fixture_cancel_generation(): """Load cancel_generation fixture and verify structural integrity.""" fixture_path = FIXTURES_DIR / "cancel_generation.json" assert fixture_path.exists(), f"Fixture not found: {fixture_path}" with open(fixture_path) as f: fixture = json.load(f) assert fixture["fixture_id"] == "FX_AgentChat.Model.CancelGeneration" assert fixture["edge"] == "cancel_during_streaming" assert fixture["input"]["action"] == "cancelGeneration" expected = fixture["expected"]["state_after"] assert expected["streamingState"] == "idle" assert expected["isInputLocked"] is False assert "partialText" in expected # #endregion TestAgentChat.ModelFixtures.CancelGeneration # #region TestAgentChat.ModelFixtures.ResumeConfirm [C:2] [TYPE Function] [SEMANTICS test,fixture,confirm] # @BRIEF FX_AgentChat.Model.ResumeConfirm — verify resume confirm fixture. def test_fixture_resume_confirm(): """Load resume_confirm fixture and verify structural integrity.""" fixture_path = FIXTURES_DIR / "resume_confirm.json" assert fixture_path.exists(), f"Fixture not found: {fixture_path}" with open(fixture_path) as f: fixture = json.load(f) assert fixture["fixture_id"] == "FX_AgentChat.Model.ResumeConfirm" assert fixture["edge"] == "confirm_from_awaiting" assert fixture["input"]["action"] == "resumeConfirm" assert fixture["input"]["args"] == ["confirm"] expected = fixture["expected"]["state_after"] assert expected["streamingState"] == "streaming" assert expected["pendingThreadId"] is None # #endregion TestAgentChat.ModelFixtures.ResumeConfirm # #region TestAgentChat.ModelFixtures.ResumeDeny [C:2] [TYPE Function] [SEMANTICS test,fixture,deny] # @BRIEF FX_AgentChat.Model.ResumeDeny — verify resume deny fixture. def test_fixture_resume_deny(): """Load resume_deny fixture and verify structural integrity.""" fixture_path = FIXTURES_DIR / "resume_deny.json" assert fixture_path.exists(), f"Fixture not found: {fixture_path}" with open(fixture_path) as f: fixture = json.load(f) assert fixture["fixture_id"] == "FX_AgentChat.Model.ResumeDeny" assert fixture["edge"] == "deny_from_awaiting" assert fixture["input"]["action"] == "resumeConfirm" assert fixture["input"]["args"] == ["deny"] expected = fixture["expected"]["state_after"] assert expected["streamingState"] == "idle" assert expected["pendingThreadId"] is None # #endregion TestAgentChat.ModelFixtures.ResumeDeny # #region TestAgentChat.ModelFixtures.RejectedWebSocket [C:2] [TYPE Function] [SEMANTICS test,fixture,rejected] # @BRIEF FX_AgentChat.Model.RejectedPath — verify no WebSocket resurrection. def test_fixture_rejected_websocket(): """Verify no WebSocket resurrection in AgentChatModel.""" fixture_path = FIXTURES_DIR / "rejected_websocket.json" assert fixture_path.exists(), f"Fixture not found: {fixture_path}" with open(fixture_path) as f: fixture = json.load(f) assert fixture["fixture_id"] == "FX_AgentChat.Model.RejectedPath" assert fixture["invariant"] == "NoWebSocketImports" assert fixture["edge"] == "rejected_path" assert "No 'WebSocket'" in fixture["expected"]["assertions"][0] # Read the actual model source model_path = Path(__file__).resolve().parent.parent.parent.parent / "frontend" / "src" / "lib" / "models" / "AgentChatModel.svelte.ts" source = model_path.read_text() # Verify no WebSocket imports (not just the word — it's in comments as @REJECTED) assertions = fixture["expected"]["assertions"] for assertion in assertions: if "WebSocket" in assertion: # Check for actual WebSocket import (import WebSocket, from ... import ... WebSocket) for line in source.split("\n"): stripped = line.strip() if stripped.startswith("import") and "WebSocket" in stripped: pytest.fail(f"FAIL: {assertion} — found WebSocket import: {stripped}") if stripped.startswith("from") and "WebSocket" in stripped: pytest.fail(f"FAIL: {assertion} — found WebSocket import: {stripped}") if "tabRole" in assertion: assert "tabRole" not in source, f"FAIL: {assertion}" if "follower_notify" in assertion: assert "follower_notify" not in source, f"FAIL: {assertion}" if "takeoverSession" in assertion: assert "takeoverSession" not in source, f"FAIL: {assertion}" # #endregion TestAgentChat.ModelFixtures.RejectedWebSocket # #endregion TestAgentChat.ModelFixtures