fix: a signed-out tab no longer asks for saved views
The providers mount for the public landing too, and the saved-views query had no enabled gate, so every signed-out load logged a 401 for /api/saved-views. The query now waits for a signed-in account in BootGate's me cache, like WizardProvider.
This commit is contained in:
@@ -67,12 +67,19 @@ function Probe() {
|
||||
);
|
||||
}
|
||||
|
||||
// The views query waits for a signed-in account in the cache (BootGate's `me`).
|
||||
function signedInClient() {
|
||||
const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
qc.setQueryData(qk.me(), { id: ID, preferences: {} });
|
||||
return qc;
|
||||
}
|
||||
|
||||
async function mountResolved(views: SavedView[]) {
|
||||
// Fresh array + object copies per call, like a real fetch — so a refetch changes viewsQuery.data's
|
||||
// identity and re-runs the seed effect (which is what makes the per-source guard actually load-bearing
|
||||
// in the re-seed test; a shared reference would skip the effect and hide a missing guard).
|
||||
vi.spyOn(api, "savedViews").mockImplementation(async () => views.map((v) => ({ ...v })));
|
||||
const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
const qc = signedInClient();
|
||||
render(
|
||||
<QueryClientProvider client={qc}>
|
||||
<SavedViewsProvider>
|
||||
@@ -141,7 +148,7 @@ describe("SavedViewsProvider — default-view seeding on first resolve", () => {
|
||||
calls += 1;
|
||||
return calls === 1 ? [def] : [def, view({ id: 9, name: "added-later" })];
|
||||
});
|
||||
const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
const qc = signedInClient();
|
||||
render(
|
||||
<QueryClientProvider client={qc}>
|
||||
<SavedViewsProvider>
|
||||
@@ -174,3 +181,26 @@ describe("SavedViewsProvider — default-view seeding on first resolve", () => {
|
||||
expect(h.setPlexFilters).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("SavedViewsProvider — signed-out tab", () => {
|
||||
it("does NOT ask for saved views while no account is signed in (the landing logged a 401)", async () => {
|
||||
const spy = vi.spyOn(api, "savedViews").mockResolvedValue([]);
|
||||
const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
qc.setQueryData(qk.me(), null); // BootGate's "nobody"
|
||||
render(
|
||||
<QueryClientProvider client={qc}>
|
||||
<SavedViewsProvider>
|
||||
<Probe />
|
||||
</SavedViewsProvider>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
// Let any fetch the mount would start get going before asserting it never happened.
|
||||
await act(async () => {
|
||||
await new Promise((r) => setTimeout(r, 20));
|
||||
});
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
// …and it asks as soon as an account signs in.
|
||||
act(() => qc.setQueryData(qk.me(), { id: ID, preferences: {} }));
|
||||
await waitFor(() => expect(spy).toHaveBeenCalledWith("feed"));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -155,9 +155,14 @@ export function SavedViewsProvider({ children }: { children: ReactNode }) {
|
||||
}, [page, feedFilters, plexFilters, setFeedFilters, setPlexFilters]);
|
||||
|
||||
const source = cfg.source;
|
||||
// Passive observer of the account BootGate fetches: the providers mount for a signed-out tab too
|
||||
// (the public landing), and saved views are per-account, so asking for "nobody's" views only logs
|
||||
// a 401 on the landing page. Enabled once a signed-in account is cached.
|
||||
const { data: me } = useQuery({ queryKey: qk.me(), queryFn: api.me, enabled: false });
|
||||
const viewsQuery = useQuery({
|
||||
queryKey: qk.savedViews(source),
|
||||
queryFn: () => api.savedViews(source),
|
||||
enabled: !!me,
|
||||
});
|
||||
const views = useMemo(() => viewsQuery.data ?? [], [viewsQuery.data]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user