Files
nexu-io__open-design/packages/contracts/tests/errors.test.ts
Ethan Guo ca9c2d10b5 test(contracts,agui-adapter): cover error helpers, schema parse, ctx.now fallback (#2393)
* test(contracts): cover error helpers and schema parse round-trips

* test(agui-adapter): cover ctx.now fallback and optional field passthrough
2026-06-29 12:41:26 +00: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' }],
});
});
});