070959e133
landing-page-staging / Deploy landing page to staging (push) Has been skipped
landing-page-ci / Validate landing page (push) Failing after 4s
visual-baseline / Capture visual baselines (push) Has been cancelled
bake-plugin-previews / Bake plugin previews (push) Has been cancelled
64 lines
2.0 KiB
TypeScript
64 lines
2.0 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
API_ERROR_CODES,
|
|
createApiError,
|
|
createApiErrorResponse,
|
|
type ApiError,
|
|
} from '../src/errors.js';
|
|
|
|
describe('createApiError', () => {
|
|
it('returns the minimal shape when only code and message are supplied', () => {
|
|
const err = createApiError('NOT_FOUND', 'project missing');
|
|
expect(err).toEqual({ code: 'NOT_FOUND', message: 'project missing' });
|
|
});
|
|
|
|
it('carries optional fields (details, retryable, requestId, taskId) through', () => {
|
|
const err = createApiError('RATE_LIMITED', 'slow down', {
|
|
details: { retryAfterMs: 1500 },
|
|
retryable: true,
|
|
requestId: 'req-1',
|
|
taskId: 'task-9',
|
|
});
|
|
expect(err).toEqual({
|
|
code: 'RATE_LIMITED',
|
|
message: 'slow down',
|
|
details: { retryAfterMs: 1500 },
|
|
retryable: true,
|
|
requestId: 'req-1',
|
|
taskId: 'task-9',
|
|
});
|
|
});
|
|
|
|
it('does not leak omitted optional fields onto the returned object', () => {
|
|
const err = createApiError('UNAUTHORIZED', 'no token');
|
|
expect(Object.keys(err).sort()).toEqual(['code', 'message']);
|
|
});
|
|
|
|
it('accepts every ApiErrorCode the contract exports', () => {
|
|
for (const code of API_ERROR_CODES) {
|
|
const err = createApiError(code, 'x');
|
|
expect(err.code).toBe(code);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('createApiErrorResponse', () => {
|
|
it('wraps an ApiError in the `{ error }` envelope', () => {
|
|
const err: ApiError = { code: 'BAD_REQUEST', message: 'bad' };
|
|
expect(createApiErrorResponse(err)).toEqual({ error: err });
|
|
});
|
|
|
|
it('round-trips through createApiError', () => {
|
|
const resp = createApiErrorResponse(
|
|
createApiError('VALIDATION_FAILED', 'invalid input', {
|
|
details: { kind: 'validation', issues: [{ path: 'name', message: 'required' }] },
|
|
}),
|
|
);
|
|
expect(resp.error.code).toBe('VALIDATION_FAILED');
|
|
expect(resp.error.details).toEqual({
|
|
kind: 'validation',
|
|
issues: [{ path: 'name', message: 'required' }],
|
|
});
|
|
});
|
|
});
|