Avoid duplicate flight detail SignalR subscribe
ci-deploy / build-deploy-test (push) Successful in 1m31s

This commit is contained in:
2026-05-19 00:53:14 +03:00
parent 5c3f49204c
commit 9345eb162a
3 changed files with 31 additions and 5 deletions
@@ -401,7 +401,7 @@ export const OnlineBoardDetailsPage: FC<OnlineBoardDetailsPageProps> = ({
// Live updates via SignalR
const { flight: liveFlight, connectionStatus } = useLiveFlightDetails(
flight?.flightId ?? flightId,
flight?.flightId ?? null,
flight,
refresh,
);
@@ -240,6 +240,23 @@ describe("useLiveFlightDetails", () => {
expect(result.current.flight).toBeNull();
});
it("does not subscribe before the API flight id is available", async () => {
const { hub, conn } = installMockHub(HUB_URL);
const subscribeSpy = vi.spyOn(conn, "subscribe");
const { result } = renderHook(() =>
useLiveFlightDetails(null, null),
);
await act(async () => {
await vi.runAllTimersAsync();
});
expect(result.current.connectionStatus).toBe("idle");
expect(subscribeSpy).not.toHaveBeenCalled();
expect(hub.invoke).not.toHaveBeenCalled();
});
it("subscribes to Angular TrackerHub refresh and invokes Subscribe", async () => {
const { hub } = installMockHub(HUB_URL);
const id: IParsedFlightId = {
@@ -34,6 +34,13 @@ export interface UseLiveFlightDetailsResult {
type LiveFlightId = IParsedFlightId | IFlightId;
const DISABLED_ID: LiveFlightId = {
carrier: "",
flightNumber: "",
suffix: "",
date: "",
};
export function buildFlightChannelKey(id: LiveFlightId): string {
return `flight:${id.carrier}${id.flightNumber}${id.suffix ?? ""}@${id.date}`;
}
@@ -48,13 +55,15 @@ export function buildTrackerFlightSubscriptionKey(id: LiveFlightId): string {
// ---------------------------------------------------------------------------
export function useLiveFlightDetails(
id: LiveFlightId,
id: LiveFlightId | null,
initialFlight: ISimpleFlight | null,
onRefresh?: () => void,
): UseLiveFlightDetailsResult {
const env = getEnv();
const effectiveId = id ?? DISABLED_ID;
const config = useMemo<UseLiveFlightsConfig<LiveFlightId>>(
() => ({
hubUrl: getEnv().SIGNALR_HUB_URL,
hubUrl: id ? env.SIGNALR_HUB_URL : "",
channelKey: buildFlightChannelKey,
subscription: {
eventName: "Refresh",
@@ -67,7 +76,7 @@ export function useLiveFlightDetails(
return undefined;
},
}),
[onRefresh],
[env.SIGNALR_HUB_URL, id, onRefresh],
);
// useLiveFlights expects an array — wrap/unwrap the single flight
@@ -79,7 +88,7 @@ export function useLiveFlightDetails(
const { data, connectionStatus } = useLiveFlights<
LiveFlightId,
ISimpleFlight
>(id, initialData, config);
>(effectiveId, initialData, config);
const flight = data[0] ?? null;