Files
carmanagement/apps/marketplace/src/lib/api.test.ts
T

74 lines
3.0 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from 'vitest'
import { MarketplaceApiError, marketplaceFetch, marketplaceFetchOrDefault, marketplacePost } from './api'
afterEach(() => {
delete process.env.NEXT_PUBLIC_API_URL
delete process.env.API_INTERNAL_URL
vi.restoreAllMocks()
Reflect.deleteProperty(globalThis, 'fetch')
})
describe('marketplace API helpers', () => {
it('unwraps successful GET responses from the data envelope', async () => {
const fetchMock = vi.fn(async () => ({ ok: true, json: async () => ({ data: [{ id: 'vehicle_1' }] }) }))
Object.defineProperty(globalThis, 'fetch', { configurable: true, value: fetchMock })
await expect(marketplaceFetch('/marketplace/vehicles')).resolves.toEqual([{ id: 'vehicle_1' }])
expect(fetchMock).toHaveBeenCalledWith(expect.stringMatching(/\/api\/v1\/marketplace\/vehicles$/), { cache: 'no-store' })
})
it('throws rich marketplace API errors', async () => {
Object.defineProperty(globalThis, 'fetch', {
configurable: true,
value: vi.fn(async () => ({
ok: false,
status: 409,
json: async () => ({ message: 'Vehicle unavailable', error: 'VEHICLE_UNAVAILABLE', nextAvailableAt: '2026-07-01T10:00:00.000Z' }),
})),
})
await expect(marketplaceFetch('/marketplace/book')).rejects.toMatchObject({
name: 'MarketplaceApiError',
message: 'Vehicle unavailable',
status: 409,
code: 'VEHICLE_UNAVAILABLE',
nextAvailableAt: '2026-07-01T10:00:00.000Z',
})
})
it('returns fallbacks when GET requests fail', async () => {
Object.defineProperty(globalThis, 'fetch', {
configurable: true,
value: vi.fn(async () => ({ ok: false, status: 500, json: async () => ({ message: 'Down' }) })),
})
await expect(marketplaceFetchOrDefault('/marketplace/homepage', { hero: null })).resolves.toEqual({ hero: null })
})
it('posts JSON payloads and unwraps successful responses', async () => {
process.env.NEXT_PUBLIC_API_URL = 'https://api.example.com/api/v1'
const fetchMock = vi.fn(async () => ({ ok: true, json: async () => ({ data: { id: 'reservation_1' } }) }))
Object.defineProperty(globalThis, 'fetch', { configurable: true, value: fetchMock })
await expect(marketplacePost('/site/reservations', { vehicleId: 'vehicle_1' })).resolves.toEqual({ id: 'reservation_1' })
expect(fetchMock).toHaveBeenCalledWith('https://api.example.com/api/v1/site/reservations', expect.objectContaining({
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ vehicleId: 'vehicle_1' }),
}))
})
it('uses a generic error message when the response body is not JSON', async () => {
Object.defineProperty(globalThis, 'fetch', {
configurable: true,
value: vi.fn(async () => ({ ok: false, status: 502, json: async () => { throw new Error('bad json') } })),
})
await expect(marketplaceFetch('/site/homepage')).rejects.toMatchObject({
name: 'MarketplaceApiError',
message: 'Request failed',
status: 502,
})
})
})