mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-03-28 17:43:05 +01:00
Be more gentle with frontend typing + go back to fire-and-forget for cracked room creation
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""Typed WebSocket event contracts and serialization helpers."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, Literal
|
||||
|
||||
from pydantic import TypeAdapter
|
||||
@@ -9,6 +10,8 @@ from typing_extensions import NotRequired, TypedDict
|
||||
from app.models import Channel, Contact, Message, MessagePath, RawPacketBroadcast
|
||||
from app.routers.health import HealthResponse
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
WsEventType = Literal[
|
||||
"health",
|
||||
"message",
|
||||
@@ -82,9 +85,16 @@ def dump_ws_event(event_type: str, data: Any) -> str:
|
||||
if adapter is None:
|
||||
return json.dumps({"type": event_type, "data": data})
|
||||
|
||||
try:
|
||||
validated = adapter.validate_python(data)
|
||||
payload = adapter.dump_python(validated, mode="json")
|
||||
return json.dumps({"type": event_type, "data": payload})
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"Failed to validate WebSocket payload for event %s; falling back to raw JSON envelope",
|
||||
event_type,
|
||||
)
|
||||
return json.dumps({"type": event_type, "data": data})
|
||||
|
||||
|
||||
def dump_ws_event_payload(event_type: str, data: Any) -> Any:
|
||||
|
||||
@@ -188,7 +188,9 @@ export function useAppShellProps({
|
||||
key_type: 'channel',
|
||||
channel_key: created.key,
|
||||
});
|
||||
await fetchUndecryptedCount();
|
||||
void fetchUndecryptedCount().catch((error) => {
|
||||
console.error('Failed to refresh undecrypted count after cracked channel create:', error);
|
||||
});
|
||||
},
|
||||
[fetchUndecryptedCount, setChannels]
|
||||
);
|
||||
|
||||
@@ -186,4 +186,40 @@ describe('useAppShellProps', () => {
|
||||
});
|
||||
expect(args.fetchUndecryptedCount).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('does not fail cracked channel creation when undecrypted count refresh rejects', async () => {
|
||||
mocks.api.createChannel.mockResolvedValue({
|
||||
key: '22'.repeat(16),
|
||||
name: 'Found',
|
||||
is_hashtag: false,
|
||||
});
|
||||
mocks.api.getChannels.mockResolvedValue([
|
||||
publicChannel,
|
||||
{ ...publicChannel, key: '22'.repeat(16), name: 'Found' },
|
||||
]);
|
||||
mocks.api.decryptHistoricalPackets.mockResolvedValue({ decrypted_count: 4 });
|
||||
|
||||
const args = createArgs({
|
||||
fetchUndecryptedCount: vi.fn(async () => {
|
||||
throw new Error('refresh failed');
|
||||
}),
|
||||
});
|
||||
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const { result } = renderHook(() => useAppShellProps(args));
|
||||
|
||||
await act(async () => {
|
||||
await result.current.crackerProps.onChannelCreate('Found', '22'.repeat(16));
|
||||
});
|
||||
|
||||
expect(mocks.api.decryptHistoricalPackets).toHaveBeenCalledWith({
|
||||
key_type: 'channel',
|
||||
channel_key: '22'.repeat(16),
|
||||
});
|
||||
expect(consoleError).toHaveBeenCalledWith(
|
||||
'Failed to refresh undecrypted count after cracked channel create:',
|
||||
expect.any(Error)
|
||||
);
|
||||
|
||||
consoleError.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,7 +5,6 @@ import json
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from app.websocket import SEND_TIMEOUT_SECONDS, WebSocketManager
|
||||
|
||||
@@ -262,8 +261,12 @@ class TestTypedEventSerialization:
|
||||
"data": {"message_id": 7, "ack_count": 2},
|
||||
}
|
||||
|
||||
def test_dump_ws_event_validates_supported_payloads(self):
|
||||
def test_dump_ws_event_falls_back_to_raw_payload_when_validation_fails(self):
|
||||
from app.events import dump_ws_event
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
dump_ws_event("message_acked", {"ack_count": 2})
|
||||
serialized = dump_ws_event("message_acked", {"ack_count": 2})
|
||||
|
||||
assert json.loads(serialized) == {
|
||||
"type": "message_acked",
|
||||
"data": {"ack_count": 2},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user