mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-09-14 23:25:35 +00:00
Typing in a conversation got progressively slower as its history grew.
The cause was not the input: every packet the node overhears was stored
in App state, so each one re-rendered the whole tree, including the
un-memoized MessageList. That cost scales with history length, and on a
busy mesh it saturated the main thread so keystrokes queued behind it.
Measured in Chromium with the real components, cost per overheard packet:
history before after
50 7.3ms ~0ms
500 48.5ms ~0ms
1000 97.7ms ~0ms
2000 228.4ms ~0ms
The packet stream now lives in a small external store that views subscribe
to individually, so only the map, visualizer, raw feed, and cracker re-render
when a packet arrives, so the chat view is no longer along for the ride.
This also retires useRawPacketStatsSession, whose session state was App
state for the same reason.
51 lines
1.7 KiB
TypeScript
51 lines
1.7 KiB
TypeScript
import { fireEvent, render, screen } from '@testing-library/react';
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
import { VisualizerView } from '../components/VisualizerView';
|
|
import { resetRawPacketStore, seedRawPacketStore } from '../stores/rawPacketStore';
|
|
import type { RawPacket } from '../types';
|
|
|
|
// The 3D scene needs WebGL, which jsdom does not provide.
|
|
vi.mock('../components/PacketVisualizer3D', () => ({
|
|
PacketVisualizer3D: () => <div data-testid="packet-visualizer-3d" />,
|
|
}));
|
|
|
|
function createPacket(overrides: Partial<RawPacket> = {}): RawPacket {
|
|
return {
|
|
id: 1,
|
|
timestamp: 1700000000,
|
|
data: '000000000000',
|
|
payload_type: 'REQ',
|
|
snr: null,
|
|
rssi: null,
|
|
decrypted: false,
|
|
decrypted_info: null,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe('VisualizerView packet feed', () => {
|
|
beforeEach(() => {
|
|
window.localStorage.clear();
|
|
resetRawPacketStore();
|
|
});
|
|
|
|
it('opens the packet analyzer when a feed packet is clicked', () => {
|
|
seedRawPacketStore({ packets: [createPacket({ id: 7, observation_id: 21 })] });
|
|
render(<VisualizerView contacts={[]} channels={[]} config={null} />);
|
|
|
|
expect(screen.queryByText('Packet Details')).not.toBeInTheDocument();
|
|
|
|
// Desktop split-pane and mobile tab both render the feed, so take the first.
|
|
fireEvent.click(screen.getAllByRole('button', { name: /TF/ })[0]);
|
|
|
|
expect(screen.getByText('Packet Details')).toBeInTheDocument();
|
|
});
|
|
|
|
it('does not render the analyzer until a packet is selected', () => {
|
|
render(<VisualizerView contacts={[]} channels={[]} config={null} />);
|
|
|
|
expect(screen.queryByText('Packet Details')).not.toBeInTheDocument();
|
|
});
|
|
});
|