@eleva-io/erp-sdk
Version:
SDK oficial para el ERP de Eleva
205 lines • 11.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const _1 = require(".");
const errors_remote_1 = require("./errors_remote");
const request = {
operation: 'GET',
metadata: { authorization: 'Bearer token' },
resource: '/api/users/1',
payload: undefined,
};
const response = {
statusCode: 404,
metadata: { 'content-type': 'application/json' },
payload: { code: 'NOT_FOUND', message: 'Not found', kind: 'domain', status: 404 },
};
const validBody = {
code: _1.ERROR_CODES.NOT_FOUND,
kind: _1.ErrorKind.DOMAIN,
status: 404,
message: 'User not found',
details: { entity: 'User' },
};
describe('RemoteElevaError', () => {
describe('constructor', () => {
it('is an instance of Error, ElevaError and RemoteElevaError', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: _1.ERROR_CODES.INTERNAL_SERVER_ERROR }, request, response);
expect(error).toBeInstanceOf(Error);
expect(error).toBeInstanceOf(_1.ElevaError);
expect(error).toBeInstanceOf(errors_remote_1.RemoteElevaError);
});
it('sets name to "RemoteElevaError"', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: _1.ERROR_CODES.INTERNAL_SERVER_ERROR }, request, response);
expect(error.name).toBe('RemoteElevaError');
});
it('exposes request and response as readonly properties', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: _1.ERROR_CODES.INTERNAL_SERVER_ERROR }, request, response);
expect(error.request).toBe(request);
expect(error.response).toBe(response);
});
it('inherits code, kind, status and message from the catalog', () => {
const error = errors_remote_1.RemoteElevaError.from({
code: _1.ERROR_CODES.NOT_FOUND,
}, request, response);
expect(error.code).toBe(_1.ERROR_CODES.NOT_FOUND);
expect(error.kind).toBe(_1.ErrorKind.DOMAIN);
expect(error.status).toBe(404);
});
it('forwards cause to the underlying Error', () => {
const cause = new Error('network timeout');
const error = errors_remote_1.RemoteElevaError.from({ code: _1.ERROR_CODES.INTERNAL_SERVER_ERROR }, request, response, cause);
expect(error.cause).toBe(cause);
});
});
describe('is()', () => {
it('returns true when the code matches', () => {
const error = errors_remote_1.RemoteElevaError.from({
code: _1.ERROR_CODES.NOT_FOUND,
}, request, response);
expect(error.is(_1.ERROR_CODES.NOT_FOUND)).toBe(true);
});
it('returns false when the code does not match', () => {
const error = errors_remote_1.RemoteElevaError.from({
code: _1.ERROR_CODES.NOT_FOUND,
}, request, response);
expect(error.is(_1.ERROR_CODES.CONFLICT)).toBe(false);
});
it('narrows details to the matching code', () => {
const err = errors_remote_1.RemoteElevaError.from({
code: _1.ERROR_CODES.NOT_FOUND,
details: { entity: 'User' },
}, request, response);
const entity = err.is(_1.ERROR_CODES.NOT_FOUND) ? err.details.entity : null;
expect(entity).toBe('User');
});
it('preserves request and response on the narrowed type', () => {
const err = errors_remote_1.RemoteElevaError.from({
code: _1.ERROR_CODES.NOT_FOUND,
details: { entity: 'User' },
}, request, response);
expect(err.is(_1.ERROR_CODES.NOT_FOUND)).toBe(true);
expect(err.request).toBe(request);
expect(err.response).toBe(response);
expect(err.details).toEqual({ entity: 'User' });
});
it('narrows correctly on a union-typed error', () => {
const err = errors_remote_1.RemoteElevaError.from(validBody, request, response);
const entity = err.is(_1.ERROR_CODES.NOT_FOUND) ? err.details.entity : null;
expect(entity).toBe('User');
});
it('returns true when a plain string matches the code', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: _1.ERROR_CODES.NOT_FOUND }, request, response);
expect(error.is('NOT_FOUND')).toBe(true);
});
it('returns false when a plain string does not match the code', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: _1.ERROR_CODES.NOT_FOUND }, request, response);
expect(error.is('CONFLICT')).toBe(false);
});
});
describe('toJSON()', () => {
it('includes all ElevaError fields plus request and response', () => {
const error = errors_remote_1.RemoteElevaError.from({
code: _1.ERROR_CODES.NOT_FOUND,
details: { entity: 'User' },
}, request, response);
const json = error.toJSON();
expect(json.code).toBe(_1.ERROR_CODES.NOT_FOUND);
expect(json.kind).toBe(_1.ErrorKind.DOMAIN);
expect(json.status).toBe(404);
expect(json.details).toEqual({ entity: 'User' });
expect(json.request).toBe(request);
expect(json.response).toBe(response);
});
it('toString serializes request and response', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: _1.ERROR_CODES.INTERNAL_SERVER_ERROR }, request, response);
const parsed = JSON.parse(error.toString());
expect(parsed.request.resource).toBe('/api/users/1');
expect(parsed.response.statusCode).toBe(404);
});
});
describe('from()', () => {
it('constructs a RemoteElevaError instance (not just ElevaError)', () => {
const error = errors_remote_1.RemoteElevaError.from(validBody, request, response);
expect(error).toBeInstanceOf(errors_remote_1.RemoteElevaError);
expect(error).toBeInstanceOf(_1.ElevaError);
expect(error.name).toBe('RemoteElevaError');
});
it('parses the body and sets code, message and details correctly', () => {
const error = errors_remote_1.RemoteElevaError.from(validBody, request, response);
expect(error.code).toBe(_1.ERROR_CODES.NOT_FOUND);
expect(error.message).toBe('User not found');
});
it('attaches request and response context', () => {
const error = errors_remote_1.RemoteElevaError.from(validBody, request, response);
expect(error.request).toBe(request);
expect(error.response).toBe(response);
});
it('uses the provided cause', () => {
const cause = new Error('axios error');
const error = errors_remote_1.RemoteElevaError.from(validBody, request, response, cause);
expect(error.cause).toBe(cause);
});
it('falls back to INTERNAL_SERVER_ERROR when body is malformed', () => {
const error = errors_remote_1.RemoteElevaError.from({ unexpected: true }, request, response);
expect(error.code).toBe(_1.ERROR_CODES.INTERNAL_SERVER_ERROR);
expect(error.message).toMatch(/^Failed to parse error payload:/);
});
it('uses the raw body as cause when body is malformed and no cause is provided', () => {
const body = 'not a valid error';
const error = errors_remote_1.RemoteElevaError.from(body, request, response);
expect(error.cause).toBe(body);
});
it('prefers the provided cause over the parsed cause on malformed body', () => {
const axiosCause = new Error('axios');
const error = errors_remote_1.RemoteElevaError.from('bad body', request, response, axiosCause);
expect(error.cause).toBe(axiosCause);
});
it('toJSON() includes request and response after from()', () => {
const error = errors_remote_1.RemoteElevaError.from(validBody, request, response);
const json = error.toJSON();
expect(json.request).toBe(request);
expect(json.response).toBe(response);
});
});
describe('custom / vendor-specific error codes', () => {
it('preserves an unknown code string verbatim', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: 'RATE_LIMIT', status: 429, message: 'Too many requests', kind: 'domain' }, request, response);
expect(error.code).toBe('RATE_LIMIT');
});
it('is() returns true for the custom code string', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: 'RATE_LIMIT', status: 429, message: 'Too many requests', kind: 'domain' }, request, response);
expect(error.is('RATE_LIMIT')).toBe(true);
});
it('is() returns false for a different custom code string', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: 'RATE_LIMIT', status: 429, message: 'Too many requests', kind: 'domain' }, request, response);
expect(error.is('QUOTA_EXCEEDED')).toBe(false);
});
it('uses status and kind from the body when both are valid', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: 'RATE_LIMIT', status: 429, message: 'Too many requests', kind: 'domain' }, request, response);
expect(error.status).toBe(429);
expect(error.kind).toBe(_1.ErrorKind.DOMAIN);
});
it('falls back to INTERNAL_SERVER_ERROR status and kind when they are absent', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: 'UNKNOWN_VENDOR_CODE', message: 'Something broke' }, request, response);
expect(error.code).toBe('UNKNOWN_VENDOR_CODE');
expect(error.status).toBe(500);
expect(error.kind).toBe(_1.ErrorKind.SYSTEM);
});
it('preserves the message from the body', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: 'RATE_LIMIT', status: 429, message: 'Retry after 60 s', kind: 'domain' }, request, response);
expect(error.message).toBe('Retry after 60 s');
});
it('preserves details from the body', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: 'RATE_LIMIT', status: 429, kind: 'domain', details: { retryAfter: 60 } }, request, response);
expect(error.details.retryAfter).toBe(60);
});
it('toJSON() includes the custom code, request and response', () => {
const error = errors_remote_1.RemoteElevaError.from({ code: 'RATE_LIMIT', status: 429, message: 'Too many requests', kind: 'domain' }, request, response);
const json = error.toJSON();
expect(json.code).toBe('RATE_LIMIT');
expect(json.request).toBe(request);
expect(json.response).toBe(response);
});
});
});
//# sourceMappingURL=errors_remote.spec.js.map