feat: typed api client and auth context with setup gate
This commit is contained in:
68
web/test/auth.test.tsx
Normal file
68
web/test/auth.test.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import { AuthProvider, useAuth } from '../src/auth'
|
||||
|
||||
function Probe() {
|
||||
const { status, user, setupNeeded } = useAuth()
|
||||
return (
|
||||
<div>
|
||||
<div>status:{status}</div>
|
||||
{setupNeeded && <div>setup-needed</div>}
|
||||
{user && <div>user:{user.username}</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const fetchMock = vi.fn()
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMock.mockReset()
|
||||
vi.stubGlobal('fetch', fetchMock)
|
||||
})
|
||||
|
||||
function jsonOnce(status: number, body: unknown) {
|
||||
return new Response(JSON.stringify(body), {
|
||||
status,
|
||||
headers: { 'content-type': 'application/json' },
|
||||
})
|
||||
}
|
||||
|
||||
describe('AuthProvider', () => {
|
||||
it('reports setupNeeded when the server has no users', async () => {
|
||||
fetchMock.mockResolvedValueOnce(jsonOnce(200, { needed: true }))
|
||||
render(
|
||||
<AuthProvider>
|
||||
<Probe />
|
||||
</AuthProvider>
|
||||
)
|
||||
expect(screen.getByText('status:loading')).toBeTruthy()
|
||||
await waitFor(() => expect(screen.getByText('status:setup')).toBeTruthy())
|
||||
expect(screen.getByText('setup-needed')).toBeTruthy()
|
||||
expect(fetchMock).toHaveBeenCalledWith('/api/setup', expect.anything())
|
||||
})
|
||||
|
||||
it('exposes the user when /api/me succeeds', async () => {
|
||||
fetchMock
|
||||
.mockResolvedValueOnce(jsonOnce(200, { needed: false }))
|
||||
.mockResolvedValueOnce(jsonOnce(200, { user: { id: 1, username: 'sam', isAdmin: true } }))
|
||||
render(
|
||||
<AuthProvider>
|
||||
<Probe />
|
||||
</AuthProvider>
|
||||
)
|
||||
await waitFor(() => expect(screen.getByText('status:authenticated')).toBeTruthy())
|
||||
expect(screen.getByText('user:sam')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('reports unauthenticated when /api/me is 401', async () => {
|
||||
fetchMock
|
||||
.mockResolvedValueOnce(jsonOnce(200, { needed: false }))
|
||||
.mockResolvedValueOnce(jsonOnce(401, { error: 'unauthorized' }))
|
||||
render(
|
||||
<AuthProvider>
|
||||
<Probe />
|
||||
</AuthProvider>
|
||||
)
|
||||
await waitFor(() => expect(screen.getByText('status:unauthenticated')).toBeTruthy())
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user