mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-08-06 08:43:36 +02:00
Add on-receive packet analyzer for canonical copy. Closes #97.
This commit is contained in:
@@ -1131,7 +1131,7 @@ class TestMessageAckedBroadcastShape:
|
||||
# Frontend MessageAckedEvent keys (from useWebSocket.ts:113-117)
|
||||
# The 'paths' key is optional in the TypeScript interface
|
||||
REQUIRED_KEYS = {"message_id", "ack_count"}
|
||||
OPTIONAL_KEYS = {"paths"}
|
||||
OPTIONAL_KEYS = {"paths", "packet_id"}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_outgoing_echo_broadcast_shape(self, test_db, captured_broadcasts):
|
||||
@@ -1177,6 +1177,7 @@ class TestMessageAckedBroadcastShape:
|
||||
assert isinstance(payload["ack_count"], int)
|
||||
assert payload["message_id"] == msg_id
|
||||
assert payload["ack_count"] == 1
|
||||
assert payload["packet_id"] == pkt_id
|
||||
|
||||
# paths should be a list of dicts with path and received_at keys
|
||||
assert isinstance(payload["paths"], list)
|
||||
@@ -1228,6 +1229,7 @@ class TestMessageAckedBroadcastShape:
|
||||
assert payload_keys >= self.REQUIRED_KEYS
|
||||
assert payload_keys <= (self.REQUIRED_KEYS | self.OPTIONAL_KEYS)
|
||||
assert payload["ack_count"] == 0 # Not outgoing, no ack increment
|
||||
assert payload["packet_id"] == pkt1
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_dm_echo_broadcast_shape(self, test_db, captured_broadcasts):
|
||||
@@ -1283,3 +1285,4 @@ class TestMessageAckedBroadcastShape:
|
||||
assert isinstance(payload["message_id"], int)
|
||||
assert isinstance(payload["ack_count"], int)
|
||||
assert payload["ack_count"] == 0 # Outgoing DM duplicates no longer count as delivery
|
||||
assert payload["packet_id"] == pkt1
|
||||
|
||||
@@ -384,6 +384,7 @@ class TestContactMessageCLIFiltering:
|
||||
"acked",
|
||||
"sender_name",
|
||||
"channel_name",
|
||||
"packet_id",
|
||||
}
|
||||
|
||||
with patch("app.event_handlers.broadcast_event") as mock_broadcast:
|
||||
|
||||
@@ -56,6 +56,48 @@ class TestUndecryptedCount:
|
||||
assert response.json()["count"] == 3
|
||||
|
||||
|
||||
class TestGetRawPacket:
|
||||
"""Test GET /api/packets/{id}."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_returns_404_when_missing(self, test_db, client):
|
||||
response = await client.get("/api/packets/999999")
|
||||
|
||||
assert response.status_code == 404
|
||||
assert "not found" in response.json()["detail"].lower()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_returns_linked_packet_details(self, test_db, client):
|
||||
channel_key = "DEADBEEF" * 4
|
||||
await ChannelRepository.upsert(key=channel_key, name="#ops", is_hashtag=False)
|
||||
packet_id, _ = await RawPacketRepository.create(b"\x09\x00test-packet", 1700000000)
|
||||
msg_id = await MessageRepository.create(
|
||||
msg_type="CHAN",
|
||||
text="Alice: hello",
|
||||
conversation_key=channel_key,
|
||||
sender_timestamp=1700000000,
|
||||
received_at=1700000000,
|
||||
sender_name="Alice",
|
||||
)
|
||||
assert msg_id is not None
|
||||
await RawPacketRepository.mark_decrypted(packet_id, msg_id)
|
||||
|
||||
response = await client.get(f"/api/packets/{packet_id}")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["id"] == packet_id
|
||||
assert data["timestamp"] == 1700000000
|
||||
assert data["data"] == "0900746573742d7061636b6574"
|
||||
assert data["decrypted"] is True
|
||||
assert data["decrypted_info"] == {
|
||||
"channel_name": "#ops",
|
||||
"sender": "Alice",
|
||||
"channel_key": channel_key,
|
||||
"contact_key": None,
|
||||
}
|
||||
|
||||
|
||||
class TestDecryptHistoricalPackets:
|
||||
"""Test POST /api/packets/decrypt/historical."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user