Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/features/packets/PacketRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ export function PacketRow({ packet, expanded, isFresh, onToggle }: PacketRowProp
</Tooltip>
</div>

{packet.summary && <div className="mt-1 truncate text-[11px] text-text-bright" title={packet.summary}>{packet.summary}</div>}

<div className="flex flex-wrap items-center gap-x-2 gap-y-1 mt-1 text-[11px] text-text-dim">
<span className="font-mono text-[11px] text-text-muted uppercase tracking-wider bg-text-muted/8 px-1.5 py-px rounded-sm">
{packet.routeTypeName || "Unknown"}
Expand Down
2 changes: 1 addition & 1 deletion src/features/packets/PacketTableHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function PacketTableHeader() {
<span>Obs</span>
<span>Hops</span>
<span>Hash Size</span>
<span>Src → Dst</span>
<span className="truncate" title="Summary and source / destination">Summary / Src → Dst</span>
<span>IATA</span>
<span className="text-right">Age</span>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/features/packets/PacketTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export function PacketTableRow({ packet, expanded, isFresh, onToggle }: PacketTa
<span className="font-mono text-text-muted">{pathLength?.hopCount ?? na}</span>
<span className="font-mono text-text-muted">{pathLength?.hashSize ?? na}</span>
<span className="min-w-0 overflow-hidden">
{packet.summary && <span className="block truncate text-text-bright" title={packet.summary}>{packet.summary}</span>}
<PacketEndpoints packet={packet} />
</span>
<span className="font-mono font-bold text-primary tracking-wider">
Expand Down
1 change: 1 addition & 0 deletions src/features/packets/usePackets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ export function usePackets(frozen: boolean = false, serverFilter: PacketServerFi
lastHeardAt: data.observation.heardAt,
observationCount: data.packet.observationCount,
scope: data.packet.scope,
summary: data.packet.summary,
latestObserver: {
id: data.observation.observerId,
displayName: data.observation.observerName,
Expand Down
1 change: 1 addition & 0 deletions src/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export interface PacketSummary {
observationCount: number;
latestObserver?: LatestObserver;
scope?: string; // matched transport scope name, e.g. "#bc"
summary?: string; // packet-derived display text, currently the advertised name
}

export interface ResolvedNode {
Expand Down
1 change: 1 addition & 0 deletions src/types/ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export interface WsPacketObservation {
isFirstObservation: boolean;
observationCount: number;
scope?: string; // matched transport scope name; omitted when none matched
summary?: string;
};
observation: {
observerId: string;
Expand Down
2 changes: 1 addition & 1 deletion tests/features/packets/PacketTableHeader.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { GRID_TEMPLATE } from "../../../src/features/packets/packet-grid";
describe("PacketTableHeader", () => {
it("declares every column heading", () => {
render(<PacketTableHeader />);
for (const h of ["Hash", "Type", "Route", "Obs", "Hops", "Hash Size", "Src → Dst", "IATA", "Age"]) {
for (const h of ["Hash", "Type", "Route", "Obs", "Hops", "Hash Size", "Summary / Src → Dst", "IATA", "Age"]) {
expect(screen.getByText(h)).toBeInTheDocument();
}
});
Expand Down
7 changes: 7 additions & 0 deletions tests/features/packets/PacketTableRow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ const observer = (
};

describe("PacketTableRow", () => {
it("keeps endpoints visible alongside a payload summary", () => {
render(<PacketTableRow packet={pkt({ summary: "Packet summary", latestObserver: observer({ resolvedSource: node("Source node"), resolvedDestination: node("Destination node") }) })} expanded={false} onToggle={() => {}} />);
expect(screen.getByText("Packet summary")).toBeInTheDocument();
expect(screen.getByText("Source node")).toBeInTheDocument();
expect(screen.getByText("Destination node")).toBeInTheDocument();
});

it("exposes one button carrying the expansion state", () => {
render(<PacketTableRow packet={pkt()} expanded={false} onToggle={() => {}} />);
const btn = screen.getByRole("button");
Expand Down
26 changes: 26 additions & 0 deletions tests/features/packets/packet-summary.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { describe, it, expect, vi } from "vitest";
import { render, screen, fireEvent } from "@testing-library/react";
import { PacketRow } from "../../../src/features/packets/PacketRow";
import { PacketTableRow } from "../../../src/features/packets/PacketTableRow";

const packet = {
packetHash: "AA11BB22", payloadType: 4, payloadTypeName: "ADVERT",
routeType: 1, routeTypeName: "FLOOD", firstHeardAt: 1, lastHeardAt: 2, observationCount: 1,
};

describe.each([["mobile", PacketRow], ["desktop", PacketTableRow]] as const)("%s packet summary", (_name, Row) => {
it("shows the packet's advertised name and keeps row selection working", () => {
const toggle = vi.fn();
render(<Row packet={{ ...packet, summary: "MD00-Repeater 📡" }} expanded={false} onToggle={toggle} />);
const summary = screen.getByText("MD00-Repeater 📡");
expect(summary).toHaveAttribute("title", "MD00-Repeater 📡");
fireEvent.click(summary);
expect(toggle).toHaveBeenCalledTimes(1);
});

it("supports rows from an older server without summaries", () => {
render(<Row packet={packet} expanded={false} onToggle={() => {}} />);
expect(screen.getByText(/AA11/)).toBeInTheDocument();
expect(screen.queryByText("MD00-Repeater 📡")).not.toBeInTheDocument();
});
});
14 changes: 14 additions & 0 deletions tests/features/packets/usePackets.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,20 @@ describe("usePackets live heard window", () => {

const flushRaf = () => rafCallbacks.splice(0).forEach((cb) => cb(0));

it("keeps summaries from history and passes summaries through live observations", async () => {
getPackets.mockResolvedValue({ items: [{ ...packet("history"), summary: "Historical advert" }], nextCursor: null });
const { result } = renderHook(() => usePackets(), { wrapper });
await waitFor(() => expect(result.current.allPackets.find((p) => p.packetHash === "history")?.summary).toBe("Historical advert"));
const event = observation("live");
event.packet.summary = "Live advert 📡";
act(() => {
result.current.handlePacketObservation(event);
flushRaf();
});
expect(result.current.allPackets.find((p) => p.packetHash === "live")?.summary).toBe("Live advert 📡");
expect(result.current.allPackets.find((p) => p.packetHash === "history")?.summary).toBe("Historical advert");
});

// Each WS message carries only its own heardAt, so a second observation of the same packet used to
// collapse the window to a single instant — the expanded row then read "spread 0.000s".
it("widens the heard window across observations instead of collapsing it", async () => {
Expand Down
Loading