Update AGENTS.md and add tests for broadcast payload shape

This commit is contained in:
Jack Kingsman
2026-02-23 23:20:35 -08:00
parent cc12128041
commit 033af4027d
2 changed files with 71 additions and 2 deletions

View File

@@ -92,8 +92,8 @@ frontend/src/
├── useConversationMessages.test.ts
├── useConversationMessages.race.test.ts
├── useRepeaterMode.test.ts
├── useWebSocket.lifecycle.test.ts
└── websocket.test.ts
├── useWebSocket.dispatch.test.ts
└── useWebSocket.lifecycle.test.ts
```
## Architecture Notes

View File

@@ -323,6 +323,75 @@ class TestContactMessageCLIFiltering:
assert payload["acked"] is not False # Ensure it's int, not bool
assert isinstance(payload["acked"], int)
@pytest.mark.asyncio
async def test_broadcast_message_payload_matches_frontend_type(self, test_db):
"""Broadcast payload keys must match the frontend Message interface in types.ts."""
from app.event_handlers import on_contact_message
# Keys the frontend Message interface expects (see frontend/src/types.ts)
EXPECTED_MESSAGE_KEYS = {
"id",
"type",
"conversation_key",
"text",
"sender_timestamp",
"received_at",
"paths",
"txt_type",
"signature",
"outgoing",
"acked",
}
with (
patch("app.event_handlers.broadcast_event") as mock_broadcast,
patch("app.bot.run_bot_for_message", new_callable=AsyncMock),
):
class MockEvent:
payload = {
"pubkey_prefix": "abc123def456",
"text": "shape test",
"txt_type": 0,
"sender_timestamp": 1700000000,
}
await on_contact_message(MockEvent())
mock_broadcast.assert_called_once()
event_type, payload = mock_broadcast.call_args[0]
assert event_type == "message"
assert set(payload.keys()) == EXPECTED_MESSAGE_KEYS
@pytest.mark.asyncio
async def test_broadcast_ack_payload_matches_frontend_type(self, test_db):
"""Broadcast payload keys for message_acked must match frontend expectations."""
from app.event_handlers import on_ack
msg_id = await MessageRepository.create(
msg_type="PRIV",
text="ack shape test",
received_at=1700000000,
conversation_key="bb" * 32,
sender_timestamp=1700000000,
)
track_pending_ack("ackshape", message_id=msg_id, timeout_ms=10000)
# Keys the frontend expects (see frontend/src/useWebSocket.ts:111-114)
EXPECTED_ACK_KEYS = {"message_id", "ack_count"}
with patch("app.event_handlers.broadcast_event") as mock_broadcast:
class MockEvent:
payload = {"code": "ackshape"}
await on_ack(MockEvent())
mock_broadcast.assert_called_once()
event_type, payload = mock_broadcast.call_args[0]
assert event_type == "message_acked"
assert set(payload.keys()) == EXPECTED_ACK_KEYS
@pytest.mark.asyncio
async def test_missing_txt_type_defaults_to_normal(self, test_db):
"""Messages without txt_type field are treated as normal (not filtered)."""