pegasus/frontend/src/api.test.ts

58 lines
1.6 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from 'vitest'
import { api } from './api'
describe('api helper', () => {
afterEach(() => {
vi.restoreAllMocks()
})
it('returns parsed json when content-type is json', async () => {
const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue(
new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { 'content-type': 'application/json' },
}),
)
const res = await api<{ ok: boolean }>('/api/healthz')
expect(res.ok).toBe(true)
expect(fetchMock).toHaveBeenCalledWith('/api/healthz', { credentials: 'include' })
})
it('parses json from text payload when response header is not json', async () => {
vi.spyOn(globalThis, 'fetch').mockResolvedValue(
new Response('{"value":42}', {
status: 200,
headers: { 'content-type': 'text/plain' },
}),
)
const res = await api<{ value: number }>('/api/text-json')
expect(res.value).toBe(42)
})
it('returns raw text when text is not json', async () => {
vi.spyOn(globalThis, 'fetch').mockResolvedValue(
new Response('hello', {
status: 200,
headers: { 'content-type': 'text/plain' },
}),
)
const res = await api<string>('/api/text')
expect(res).toBe('hello')
})
it('throws server message when response is not ok', async () => {
vi.spyOn(globalThis, 'fetch').mockResolvedValue(
new Response('invalid credentials', {
status: 401,
headers: { 'content-type': 'text/plain' },
}),
)
await expect(api('/api/login')).rejects.toThrow('invalid credentials')
})
})