mirror of
https://github.com/MeshCore-Beacon/beacon-web.git
synced 2026-09-03 20:23:56 +00:00
- fresh-row highlights leaked under a steady stream (each new batch cancelled the previous batch's clear timer); per-batch timers in a small useFreshHashes hook now - closing the analyzer drops ?hash and the row selection, so the same row reopens on the next click and a closed analyzer stays closed after reload/share - sf=path / sf=payload from the URL fall back to hash search (only field matchesFilters implements; the UI options were already disabled) - remove the summary preview line no backend path ever populates - channel message rows key on packetHash (live WS messages carry no id)
88 lines
2.8 KiB
TypeScript
88 lines
2.8 KiB
TypeScript
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
import { renderHook, act } from "@testing-library/react";
|
|
import { useFreshHashes } from "../../../src/features/packets/useFreshHashes";
|
|
import type { PacketSummary } from "../../../src/types/api";
|
|
|
|
function pkt(hash: string): PacketSummary {
|
|
return {
|
|
packetHash: hash,
|
|
payloadType: 2,
|
|
payloadTypeName: "TEXT_MESSAGE",
|
|
routeType: 0,
|
|
routeTypeName: "FLOOD",
|
|
firstHeardAt: 0,
|
|
lastHeardAt: 0,
|
|
observationCount: 1,
|
|
};
|
|
}
|
|
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
describe("useFreshHashes", () => {
|
|
it("does not mark the initial batch fresh", () => {
|
|
const { result } = renderHook(({ packets }) => useFreshHashes(packets), {
|
|
initialProps: { packets: [pkt("a"), pkt("b")] },
|
|
});
|
|
expect(result.current.size).toBe(0);
|
|
});
|
|
|
|
it("marks prepended hashes fresh and clears them after the delay", () => {
|
|
const { result, rerender } = renderHook(({ packets }) => useFreshHashes(packets), {
|
|
initialProps: { packets: [pkt("a")] },
|
|
});
|
|
|
|
rerender({ packets: [pkt("b"), pkt("a")] });
|
|
expect(result.current.has("b")).toBe(true);
|
|
|
|
act(() => vi.advanceTimersByTime(1100));
|
|
expect(result.current.has("b")).toBe(false);
|
|
});
|
|
|
|
it("clears each batch on its own delay during a steady stream", () => {
|
|
const { result, rerender } = renderHook(({ packets }) => useFreshHashes(packets), {
|
|
initialProps: { packets: [pkt("a")] },
|
|
});
|
|
|
|
// t=0: b arrives
|
|
rerender({ packets: [pkt("b"), pkt("a")] });
|
|
expect(result.current.has("b")).toBe(true);
|
|
|
|
// t=500: c arrives while b's highlight is still pending
|
|
act(() => vi.advanceTimersByTime(500));
|
|
rerender({ packets: [pkt("c"), pkt("b"), pkt("a")] });
|
|
expect(result.current.has("c")).toBe(true);
|
|
expect(result.current.has("b")).toBe(true);
|
|
|
|
// t=1100: b is past its 1s window and must clear even though c arrived after it
|
|
act(() => vi.advanceTimersByTime(600));
|
|
expect(result.current.has("b")).toBe(false);
|
|
expect(result.current.has("c")).toBe(true);
|
|
|
|
// t=1600: c clears too
|
|
act(() => vi.advanceTimersByTime(500));
|
|
expect(result.current.has("c")).toBe(false);
|
|
});
|
|
|
|
it("a packets change with no new hashes does not cancel a pending clear", () => {
|
|
const { result, rerender } = renderHook(({ packets }) => useFreshHashes(packets), {
|
|
initialProps: { packets: [pkt("a")] },
|
|
});
|
|
|
|
rerender({ packets: [pkt("b"), pkt("a")] });
|
|
expect(result.current.has("b")).toBe(true);
|
|
|
|
// same content, new array identity — e.g. a filter re-evaluation
|
|
act(() => vi.advanceTimersByTime(100));
|
|
rerender({ packets: [pkt("b"), pkt("a")] });
|
|
|
|
act(() => vi.advanceTimersByTime(1000));
|
|
expect(result.current.has("b")).toBe(false);
|
|
});
|
|
});
|