Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 12:00:47 +08:00

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' }],
});
});
});