mirror of
https://github.com/MeshCore-Beacon/beacon-web.git
synced 2026-10-22 18:51:21 +00:00
Extract usePacketDetail and share it across the analyzer and overlay
This commit is contained in:
1 parent
161f481576
commit
1dbbce1ad8
3 files changed
+49
-17
No files matched your search
+4
-17
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect, useCallback, useRef, lazy, Suspense } from "react";
|
||||
import { BrowserRouter, useSearchParams } from "react-router-dom";
|
||||
import { QueryClient, QueryClientProvider, useQuery } from "@tanstack/react-query";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { RegionProvider, useRegion, useRegionSelection } from "./hooks/useRegion";
|
||||
import {
|
||||
ALL_REGIONS,
|
||||
@@ -27,7 +27,7 @@ import { RouteTable } from "./features/routes/RouteTable";
|
||||
import { TraceList } from "./features/traces/TraceList";
|
||||
import { ChannelList } from "./features/channels/ChannelList";
|
||||
import { EmptyState } from "./components/EmptyState";
|
||||
import { getPacketDetail } from "./api/client";
|
||||
import { usePacketDetail } from "./features/packets/usePacketDetail";
|
||||
import { WsManager } from "./api/ws-manager";
|
||||
import { WS_URL, ENABLED_TABS } from "./lib/constants";
|
||||
import type { PacketDetail } from "./types/api";
|
||||
@@ -145,21 +145,8 @@ function AppInner() {
|
||||
const [pathMapInitialKey, setPathMapInitialKey] = useState<string | null>(null);
|
||||
const pathLinkHandledRef = useRef(false);
|
||||
|
||||
// short staleTime: observations keep accruing, so reopening the analyzer should show them
|
||||
// instead of a snapshot frozen at first open
|
||||
const { data: analyzerDetail, isLoading: analyzerLoading } = useQuery({
|
||||
queryKey: ["packet-detail", analyzerHash],
|
||||
queryFn: () => getPacketDetail(analyzerHash!),
|
||||
enabled: !!analyzerHash,
|
||||
staleTime: 30_000,
|
||||
});
|
||||
|
||||
const { data: overlayPacketDetail, isLoading: overlayPacketLoading } = useQuery({
|
||||
queryKey: ["packet-detail", overlayPacketHash],
|
||||
queryFn: () => getPacketDetail(overlayPacketHash!),
|
||||
enabled: !!overlayPacketHash,
|
||||
staleTime: 30_000,
|
||||
});
|
||||
const { data: analyzerDetail, isLoading: analyzerLoading } = usePacketDetail(analyzerHash);
|
||||
const { data: overlayPacketDetail, isLoading: overlayPacketLoading } = usePacketDetail(overlayPacketHash);
|
||||
|
||||
// deep link: ?hash opens the analyzer drawer; ?path then opens the path popup once, pre-selected
|
||||
useEffect(() => {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getPacketDetail } from "../../api/client";
|
||||
import type { PacketDetail } from "../../types/api";
|
||||
|
||||
// One query per hash shared by the expanded row, the analyzer drawer and the overlay — TanStack
|
||||
// dedupes, so a row expanded under an open drawer costs a single request.
|
||||
export function usePacketDetail(hash: string | null) {
|
||||
return useQuery<PacketDetail>({
|
||||
queryKey: ["packet-detail", hash],
|
||||
queryFn: () => getPacketDetail(hash!),
|
||||
enabled: !!hash,
|
||||
staleTime: 30_000,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { renderHook, waitFor } from "@testing-library/react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { usePacketDetail } from "../../../src/features/packets/usePacketDetail";
|
||||
|
||||
const getPacketDetail = vi.fn();
|
||||
vi.mock("../../../src/api/client", () => ({
|
||||
getPacketDetail: (hash: string) => getPacketDetail(hash),
|
||||
}));
|
||||
|
||||
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<QueryClientProvider client={new QueryClient({ defaultOptions: { queries: { retry: false } } })}>
|
||||
{children}
|
||||
</QueryClientProvider>
|
||||
);
|
||||
|
||||
beforeEach(() => getPacketDetail.mockReset());
|
||||
|
||||
describe("usePacketDetail", () => {
|
||||
it("does not fetch when hash is null", () => {
|
||||
renderHook(() => usePacketDetail(null), { wrapper });
|
||||
expect(getPacketDetail).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("fetches the detail for a hash", async () => {
|
||||
getPacketDetail.mockResolvedValue({ packetHash: "AA11", observations: [] });
|
||||
const { result } = renderHook(() => usePacketDetail("AA11"), { wrapper });
|
||||
await waitFor(() => expect(result.current.data?.packetHash).toBe("AA11"));
|
||||
expect(getPacketDetail).toHaveBeenCalledWith("AA11");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user