mirror of
https://github.com/MeshCore-Beacon/beacon-web.git
synced 2026-09-16 10:22:34 +00:00
Carry path and endpoint fields from WS observations into packet summaries
This commit is contained in:
@@ -159,6 +159,11 @@ export function usePackets(frozen: boolean = false, serverFilter: PacketServerFi
|
||||
id: data.observation.observerId,
|
||||
displayName: data.observation.observerName,
|
||||
iata: data.observation.iata,
|
||||
pathLength: data.observation.pathLength,
|
||||
pathBytes: data.observation.pathBytes,
|
||||
// WS nulls these when the payload type carries no endpoint; the REST shape uses undefined
|
||||
resolvedSource: data.observation.resolvedSource ?? undefined,
|
||||
resolvedDestination: data.observation.resolvedDestination ?? undefined,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,14 @@ export interface LatestObserver {
|
||||
id: string;
|
||||
displayName?: string;
|
||||
iata: string;
|
||||
// path fields land on the REST list from beacon-server ae0669c, and on live rows via the WS feed;
|
||||
// resolvedSource/Destination are WS-only for now — the list endpoints leave them nil on purpose.
|
||||
pathLength?: PathLength;
|
||||
pathBytes?: string;
|
||||
resolvedSource?: ResolvedHop;
|
||||
resolvedDestination?: ResolvedHop;
|
||||
// per-hop resolved path; WS-only, and only when the connection opts into configure{resolvePath}.
|
||||
resolvedPath?: ResolvedHop[];
|
||||
}
|
||||
|
||||
// packet list and detail shapes
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
import type { ChannelMessage } from "../features/channels/types";
|
||||
import type { NodeIATA } from "../features/nodes/types";
|
||||
import type { ResolvedHop } from "./api";
|
||||
import type { PathLength, ResolvedHop } from "./api";
|
||||
|
||||
// individual server-sent message shapes
|
||||
|
||||
@@ -60,6 +60,8 @@ export interface WsPacketObservation {
|
||||
rssi: number;
|
||||
snr: number;
|
||||
sourceBroker: string;
|
||||
pathLength?: PathLength;
|
||||
pathBytes?: string;
|
||||
// per-hop resolved path; populated only when the connection opts in via configure{resolvePath},
|
||||
// null otherwise. Same shape as the REST Observation.resolvedPath.
|
||||
resolvedPath?: ResolvedHop[] | null;
|
||||
|
||||
@@ -215,6 +215,70 @@ describe("usePackets server filter", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("usePackets path and endpoint fields", () => {
|
||||
let qc: QueryClient;
|
||||
let rafCallbacks: FrameRequestCallback[];
|
||||
|
||||
beforeEach(() => {
|
||||
getPackets.mockReset();
|
||||
getPackets.mockResolvedValue({ items: [], nextCursor: null });
|
||||
qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
|
||||
rafCallbacks = [];
|
||||
vi.stubGlobal("requestAnimationFrame", (cb: FrameRequestCallback) => {
|
||||
rafCallbacks.push(cb);
|
||||
return rafCallbacks.length;
|
||||
});
|
||||
vi.stubGlobal("cancelAnimationFrame", () => {});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<QueryClientProvider client={qc}>{children}</QueryClientProvider>
|
||||
);
|
||||
|
||||
it("carries path and endpoint fields from the WS observation into latestObserver", () => {
|
||||
const { result } = renderHook(() => usePackets(false, undefined), { wrapper });
|
||||
|
||||
act(() => {
|
||||
result.current.handlePacketObservation({
|
||||
packetHash: "AA11",
|
||||
packet: {
|
||||
payloadType: 1,
|
||||
payloadTypeName: "ADVERT",
|
||||
routeType: 1,
|
||||
routeTypeName: "FLOOD",
|
||||
isFirstObservation: true,
|
||||
observationCount: 1,
|
||||
},
|
||||
observation: {
|
||||
observerId: "obs-1",
|
||||
observerName: "Raven",
|
||||
iata: "YVR",
|
||||
heardAt: 1700000000,
|
||||
rssi: -94,
|
||||
snr: -7.5,
|
||||
sourceBroker: "b1",
|
||||
pathLength: { raw: "42", hashSize: 1, hopCount: 2 },
|
||||
pathBytes: "7fa4",
|
||||
resolvedSource: { confidence: "high", nodes: [{ id: "n1", publicKey: "ab", name: "Salish" }] },
|
||||
resolvedDestination: null,
|
||||
},
|
||||
});
|
||||
rafCallbacks.splice(0).forEach((cb) => cb(0));
|
||||
});
|
||||
|
||||
const obs = result.current.allPackets[0]!.latestObserver;
|
||||
expect(obs?.pathLength).toEqual({ raw: "42", hashSize: 1, hopCount: 2 });
|
||||
expect(obs?.pathBytes).toBe("7fa4");
|
||||
expect(obs?.resolvedSource?.nodes[0]!.name).toBe("Salish");
|
||||
expect(obs?.resolvedDestination).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
function observation(hash: string): WsPacketObservation["data"] {
|
||||
return {
|
||||
packetHash: hash,
|
||||
|
||||
Reference in New Issue
Block a user