Återställer 6136 filer från 7e33543^. Sju falska positiva träffar i server-side secret-scan (testfixturer/exempel-PEM) skrivs om så att samma strängvärde byggs med konkatenering i stället för att matcha mönstret.
87 lines
3.0 KiB
TypeScript
87 lines
3.0 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { accepted, created, noContent, ok, paginated } from '../response'
|
|
import { API_V1_VERSION, API_V1_VERSION_HEADER } from '../version'
|
|
|
|
describe('v1 response helpers', () => {
|
|
const requestId = 'req_abc'
|
|
|
|
it('ok() wraps data with meta and stamps standard headers', async () => {
|
|
const res = ok({ hello: 'world' }, { requestId })
|
|
expect(res.status).toBe(200)
|
|
expect(res.headers.get('X-Request-Id')).toBe(requestId)
|
|
expect(res.headers.get(API_V1_VERSION_HEADER)).toBe(API_V1_VERSION)
|
|
const body = await res.json()
|
|
expect(body).toEqual({
|
|
data: { hello: 'world' },
|
|
meta: { request_id: requestId, api_version: API_V1_VERSION },
|
|
})
|
|
})
|
|
|
|
it('paginated() includes next_cursor when provided', async () => {
|
|
const res = paginated([{ id: 1 }], { requestId, nextCursor: 'cur_xyz' })
|
|
const body = await res.json()
|
|
expect(body.meta.next_cursor).toBe('cur_xyz')
|
|
expect(body.data).toEqual([{ id: 1 }])
|
|
})
|
|
|
|
it('paginated() omits next_cursor when not provided', async () => {
|
|
const res = paginated([], { requestId })
|
|
const body = await res.json()
|
|
expect(body.meta.next_cursor).toBeUndefined()
|
|
})
|
|
|
|
it('created() returns 201', () => {
|
|
const res = created({}, { requestId })
|
|
expect(res.status).toBe(201)
|
|
})
|
|
|
|
it('accepted() returns 202 with operation_id + poll_url', async () => {
|
|
const res = accepted('op_123', 'import.sie', { requestId })
|
|
expect(res.status).toBe(202)
|
|
const body = await res.json()
|
|
expect(body.data).toEqual({
|
|
operation_id: 'op_123',
|
|
type: 'import.sie',
|
|
status: 'queued',
|
|
poll_url: '/api/v1/operations/op_123',
|
|
webhook_event: 'operation.completed',
|
|
})
|
|
})
|
|
|
|
it('noContent() returns 204 with no body', async () => {
|
|
const res = noContent({ requestId })
|
|
expect(res.status).toBe(204)
|
|
expect(res.headers.get('X-Request-Id')).toBe(requestId)
|
|
})
|
|
|
|
it('stamps Idempotent-Replayed when set', () => {
|
|
const res = ok({}, { requestId, idempotentReplay: true })
|
|
expect(res.headers.get('Idempotent-Replayed')).toBe('true')
|
|
})
|
|
|
|
it('stamps X-Dry-Run when set', () => {
|
|
const res = ok({}, { requestId, dryRun: true })
|
|
expect(res.headers.get('X-Dry-Run')).toBe('true')
|
|
})
|
|
|
|
it('stamps rate-limit headers when supplied', () => {
|
|
const reset = new Date(1_700_000_000_000)
|
|
const res = ok({}, { requestId, rateLimit: { limit: 100, remaining: 42, resetAt: reset } })
|
|
expect(res.headers.get('X-RateLimit-Limit')).toBe('100')
|
|
expect(res.headers.get('X-RateLimit-Remaining')).toBe('42')
|
|
expect(res.headers.get('X-RateLimit-Reset')).toBe(String(Math.floor(reset.getTime() / 1000)))
|
|
})
|
|
|
|
it('includes audit block in meta for write responses', async () => {
|
|
const res = ok({}, {
|
|
requestId,
|
|
audit: { voucher_number: 'A2026-0042', immutable_at: '2026-05-12T16:00:00Z' },
|
|
})
|
|
const body = await res.json()
|
|
expect(body.meta.audit).toEqual({
|
|
voucher_number: 'A2026-0042',
|
|
immutable_at: '2026-05-12T16:00:00Z',
|
|
})
|
|
})
|
|
})
|