From d88fe8dec22cc7d7c11f7a99ee9289a72ff1bab3 Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Tue, 10 Nov 2026 10:56:31 +0800 Subject: [PATCH] test(connections): retain only allocation and formatting guards Reduce snapshot and table tests to reference reuse, notification suppression, and visible-row formatting cost. --- .../connection/connection-table.test.ts | 42 ++----- src/hooks/use-connection-data.test.ts | 118 +++++------------- 2 files changed, 41 insertions(+), 119 deletions(-) diff --git a/src/components/connection/connection-table.test.ts b/src/components/connection/connection-table.test.ts index 985838249..0cffbfd42 100644 --- a/src/components/connection/connection-table.test.ts +++ b/src/components/connection/connection-table.test.ts @@ -35,7 +35,7 @@ vi.mock('./connection-row-view', async (importOriginal) => { } }) -it('sorts numeric columns above the cache bound while formatting only virtual rows', () => { +it('formats only virtual rows when sorting numeric columns above the cache bound', () => { const connections: IConnectionsItem[] = Array.from( { length: 2_101 }, (_, i) => ({ @@ -59,33 +59,17 @@ it('sorts numeric columns above the cache bound while formatting only virtual ro }), ) - for (const [column, field] of [ - ['download', 'download'], - ['upload', 'upload'], - ['dlSpeed', 'curDownload'], - ['ulSpeed', 'curUpload'], - ] as const) { - for (const desc of [false, true]) { - sorting.id = column - sorting.desc = desc - vi.mocked(formatConnectionTraffic).mockClear() - const html = renderToStaticMarkup( - createElement(ConnectionTable, { - connections, - onShowDetail: vi.fn(), - columnManagerOpen: false, - onCloseColumnManager: vi.fn(), - }), - ) - const expected = connections - .slice() - .sort((a, b) => ((a[field] ?? 0) - (b[field] ?? 0)) * (desc ? -1 : 1)) - expect(html.match(/host-\d+:443/g)).toEqual( - expected.slice(0, 6).map((row) => `${row.metadata.host}:443`), - ) - expect(formatConnectionTraffic).toHaveBeenCalledTimes(24) - } + for (const column of ['download', 'upload', 'dlSpeed', 'ulSpeed']) { + sorting.id = column + vi.mocked(formatConnectionTraffic).mockClear() + renderToStaticMarkup( + createElement(ConnectionTable, { + connections, + onShowDetail: vi.fn(), + columnManagerOpen: false, + onCloseColumnManager: vi.fn(), + }), + ) + expect(formatConnectionTraffic).toHaveBeenCalledTimes(24) } - expect(connections[0].id).toBe('0') - expect(connections.at(-1)?.id).toBe('2100') }) diff --git a/src/hooks/use-connection-data.test.ts b/src/hooks/use-connection-data.test.ts index efc3f62dc..ad39b6c0f 100644 --- a/src/hooks/use-connection-data.test.ts +++ b/src/hooks/use-connection-data.test.ts @@ -1,5 +1,5 @@ import { useSyncExternalStore } from 'react' -import { afterEach, beforeEach, expect, it, vi } from 'vitest' +import { afterEach, expect, it, vi } from 'vitest' const socket = vi.hoisted(() => ({ addListener: @@ -18,38 +18,15 @@ vi.mock('tauri-plugin-mihomo-api', () => ({ MihomoWebSocket: { connect_connections: async () => socket }, })) -beforeEach(() => { - vi.resetModules() - vi.clearAllMocks() - vi.useFakeTimers() - vi.setSystemTime(10_000) - vi.stubGlobal('window', globalThis) -}) - afterEach(() => { vi.useRealTimers() vi.unstubAllGlobals() }) -const connection = (id: string, upload = 0): IConnectionsItem => ({ - id, - metadata: { - network: 'tcp', - type: 'HTTP', - host: `${id}.example`, - sourceIP: '127.0.0.1', - sourcePort: '1234', - destinationPort: '443', - }, - chains: ['DIRECT'], - rule: 'Match', - rulePayload: '', - start: '2026-01-01T00:00:00Z', - upload, - download: 0, -}) - -const monitor = async () => { +it('reuses unchanged snapshot and list references without notifying subscribers', async () => { + vi.useFakeTimers() + vi.setSystemTime(10_000) + vi.stubGlobal('window', globalThis) const { useConnectionData: readConnectionData } = await import( './use-connection-data' ) @@ -65,7 +42,26 @@ const monitor = async () => { const unsubscribe = subscribe(listener) await Promise.resolve() const onMessage = socket.addListener.mock.calls[0][0] - const send = (connections: IConnectionsItem[], uploadTotal = 0) => { + const connections: IConnectionsItem[] = [ + { + id: 'a', + metadata: { + network: 'tcp', + type: 'HTTP', + host: 'example.com', + sourceIP: '', + sourcePort: '', + destinationPort: '443', + }, + chains: [], + rule: '', + rulePayload: '', + start: '', + upload: 0, + download: 0, + }, + ] + const send = (uploadTotal = 0) => { vi.advanceTimersByTime(500) onMessage({ type: 'Text', @@ -73,69 +69,11 @@ const monitor = async () => { }) return read() } - return { send, listener, unsubscribe } -} - -it('reuses unchanged snapshots and lists without notifying, including totals-only updates', async () => { - const { send, listener, unsubscribe } = await monitor() - const first = send([connection('a'), connection('b')]) - Object.freeze(first.activeConnections) - first.activeConnections.forEach(Object.freeze) - expect(send([connection('a'), connection('b')])).toBe(first) + const first = send() + expect(send()).toBe(first) expect(listener).toHaveBeenCalledTimes(1) - - const totalsOnly = send([connection('a'), connection('b')], 100) - expect(totalsOnly).not.toBe(first) + const totalsOnly = send(100) expect(totalsOnly.activeConnections).toBe(first.activeConnections) expect(totalsOnly.closedConnections).toBe(first.closedConnections) - expect(totalsOnly.uploadTotal).toBe(100) - expect(listener).toHaveBeenCalledTimes(2) - unsubscribe() -}) - -it('updates traffic, decays speed to zero, and preserves immutable history through reorder and removal', async () => { - const { send, unsubscribe } = await monitor() - const first = send([connection('a'), connection('b')]) - const changed = send([connection('a', 50), connection('b')]) - expect(changed.activeConnections[0].curUpload).toBe(50) - expect(changed.activeConnections[0].metadata).toBe( - first.activeConnections[0].metadata, - ) - expect(changed.activeConnections[0].chains).toBe( - first.activeConnections[0].chains, - ) - expect(changed.activeConnections[1]).toBe(first.activeConnections[1]) - expect(first.activeConnections[0].upload).toBe(0) - - const idle = send([connection('a', 50), connection('b')]) - expect(idle.activeConnections[0].curUpload).toBe(0) - expect(send([connection('a', 50), connection('b')])).toBe(idle) - const reordered = send([connection('b'), connection('a', 50)]) - expect(reordered.activeConnections).toEqual([ - idle.activeConnections[1], - idle.activeConnections[0], - ]) - expect(reordered.closedConnections).toBe(idle.closedConnections) - const removed = send([connection('b'), connection('c')]) - expect(removed.closedConnections).toEqual([idle.activeConnections[0]]) - expect(removed.closedConnections[0]).toBe(idle.activeConnections[0]) - const next = send([connection('b', 10), connection('c')]) - expect(next.closedConnections).toBe(removed.closedConnections) - unsubscribe() -}) - -it('evicts the oldest closed entries at 500 without mutating retained history', async () => { - const { send, unsubscribe } = await monitor() - send(Array.from({ length: 502 }, (_, i) => connection(`${i}`))) - const closed = send([]) - expect(closed.closedConnections).toHaveLength(500) - expect(closed.closedConnections[0].id).toBe('2') - send([connection('new-a'), connection('new-b')]) - const evicted = send([]) - expect(evicted.closedConnections).toHaveLength(500) - expect(evicted.closedConnections[0].id).toBe('4') - expect(evicted.closedConnections.at(-1)?.id).toBe('new-b') - expect(closed.closedConnections[0].id).toBe('2') - unsubscribe() })