fix: align Channels queryFn return shape with Dashboard

Both Dashboard.tsx and Channels.tsx used the same React Query key
qk.channels.list({}) but returned different data shapes: Dashboard
returned the raw {items, total} object while Channels returned just
the items array. When Dashboard loaded first, React Query cached the
raw object, and Channels' for...of on the cached object threw
'g is not iterable'.

Fix: Channels queryFn now returns the raw API response (matching
Dashboard), and channels extraction uses data?.items ?? []. Added
regression test that pre-seeds the cache with the Dashboard shape.
This commit is contained in:
Louis King
2026-07-22 23:40:56 +01:00
parent 7b399a520f
commit 91bfe0d043
2 changed files with 15 additions and 10 deletions
@@ -2,7 +2,7 @@ import { screen, waitFor } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { Channels } from "@/pages/Channels";
import { renderWithProviders } from "@/test/renderWithProviders";
import { renderWithProviders, createTestQueryClient } from "@/test/renderWithProviders";
import { makeConfig } from "@/test/makeConfig";
import * as api from "@/utils/api";
@@ -69,4 +69,15 @@ describe("Channels", () => {
expect(screen.queryByText("Public")).not.toBeInTheDocument();
});
});
it("renders correctly when cache was pre-populated by Dashboard (raw object shape)", async () => {
mockChannelsApi();
const client = createTestQueryClient();
client.setQueryData(["channels", "list", {}], CHANNELS);
renderWithProviders(<Channels />, { client });
await waitFor(() => {
expect(screen.getByText("Public")).toBeInTheDocument();
expect(screen.getByText("Ops")).toBeInTheDocument();
});
});
});
@@ -293,16 +293,10 @@ export function Channels() {
error: queryError,
} = useQuery({
queryKey: qk.channels.list({}),
queryFn: async ({ signal }) => {
const resp = await apiGet<ChannelListResponse>(
"/api/v1/channels",
{},
{ signal },
);
return resp.items || [];
},
queryFn: ({ signal }) =>
apiGet<ChannelListResponse>("/api/v1/channels", {}, { signal }),
});
const channels = data ?? [];
const channels = data?.items ?? [];
const error = queryError ? queryError.message : null;
const [modal, setModal] = useState<ModalState | null>(null);