API client, auth bootstrap and job polling (#42)
CI / ci (push) Successful in 1m32s
CI / ci (pull_request) Successful in 1m33s

Co-authored-by: dev_agent <dev_agent@cubecraftlabs.com>
Co-committed-by: dev_agent <dev_agent@cubecraftlabs.com>
This commit was merged in pull request #42.
This commit is contained in:
2026-10-04 08:46:40 -04:00
committed by approver_agent
parent c899f07b1f
commit 048d5dd71a
18 changed files with 840 additions and 24 deletions
+48
View File
@@ -0,0 +1,48 @@
import { vi, type Mock } from 'vitest'
import type { ApiLocation, Me } from '../api/index.ts'
export const ME: Me = {
name: 'Sam',
email: 'sam@example.com',
household: { label: 'Our kitchen' },
csrfToken: 'token-1',
}
export function jsonResponse(status: number, body: unknown): Response {
return new Response(JSON.stringify(body), { status, headers: { 'Content-Type': 'application/json' } })
}
export function errorResponse(status: number, code: string, retryable = false): Response {
return jsonResponse(status, { error: { code, message: `${code} message`, retryable } })
}
// stubFetch replaces the global fetch with a mock answered from responses in
// order; a request beyond them fails the test. Undo with vi.unstubAllGlobals.
export function stubFetch(...responses: Response[]): Mock<typeof fetch> {
const fetchMock = vi.fn<typeof fetch>()
for (const response of responses) fetchMock.mockResolvedValueOnce(response)
fetchMock.mockImplementation((input, init) => {
throw new Error(`unexpected fetch: ${init?.method ?? 'GET'} ${String(input)}`)
})
vi.stubGlobal('fetch', fetchMock)
return fetchMock
}
// request returns the method, path and headers of the fetch mock's nth call.
export function request(fetchMock: Mock<typeof fetch>, n: number) {
const call = fetchMock.mock.calls[n]
if (call === undefined) throw new Error(`fetch was called ${fetchMock.mock.calls.length} times, not ${n + 1}`)
const [input, init] = call
return {
path: String(input),
method: init?.method,
credentials: init?.credentials,
headers: new Headers(init?.headers),
body: init?.body,
}
}
// fakeLocation stands in for window.location, recording navigations.
export function fakeLocation(pathname = '/', search = ''): ApiLocation & { assign: Mock<(url: string | URL) => void> } {
return { pathname, search, assign: vi.fn<(url: string | URL) => void>() }
}