/** * csrfMiddleware 401-handling regression tests. * * Bug: clicking Logout (or landing on /login) flooded GET /api/session with 401s * and the page hung instead of returning to the login screen. * * Root cause: the middleware redirected on EVERY 401, including the session * probe's own 401. The redirect invalidated the ['session'] query, which * refetched GET /api/session, which 401'd, which redirected again → an infinite * refetch loop. These tests pin the fix: the session probe and the login * endpoint own their 401s (no redirect); any other endpoint's 401 still * redirects (session expired mid-use). * * We call onResponse() directly (rather than going through apiClient.GET) so the * test exercises the exact 401 branch without the singleton's relative baseUrl, * which has no absolute origin to resolve against under jsdom. */ import { describe, it, expect, vi, beforeEach } from 'vitest' import type { Middleware } from 'openapi-fetch' import { csrfMiddleware, registerLoginRedirect } from './client' type OnResponse = NonNullable type OnResponseParams = Parameters[0] /** Build the minimal onResponse params for the given schema path + response. */ function params(schemaPath: string, response: Response): OnResponseParams { return { schemaPath, response, request: new Request('http://test.local' + schemaPath) } as OnResponseParams } function response401(): Response { return new Response(JSON.stringify({ detail: 'unauthorized' }), { status: 401, headers: { 'Content-Type': 'application/json' }, }) } const onResponse = csrfMiddleware.onResponse as OnResponse describe('csrfMiddleware 401 redirect (session-flood regression)', () => { const redirect = vi.fn() beforeEach(() => { redirect.mockReset() registerLoginRedirect(redirect) }) it('does NOT redirect when GET /api/session returns 401 (probe owns its 401)', async () => { await onResponse(params('/api/session', response401())) expect(redirect).not.toHaveBeenCalled() }) it('does NOT redirect when POST /api/auth/login returns 401 (bad credentials)', async () => { await onResponse(params('/api/auth/login', response401())) expect(redirect).not.toHaveBeenCalled() }) it('redirects when a normal endpoint returns 401 (session expired mid-use)', async () => { await onResponse(params('/api/locations', response401())) expect(redirect).toHaveBeenCalledTimes(1) }) })