This commit is contained in:
143
tests/errors/createErrorResolver.test.ts
Normal file
143
tests/errors/createErrorResolver.test.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { createErrorResolver } from '../../src/errors/createErrorResolver';
|
||||
|
||||
const CATALOG = {
|
||||
AUTH_UNAUTHORIZED: 'Unauthorized access. Please sign in again.',
|
||||
FORBIDDEN: 'You do not have permission to perform this action.',
|
||||
USER_NOT_FOUND: 'User not found.',
|
||||
INTERNAL_ERROR: 'Unexpected request error.',
|
||||
REQUEST_FAILED: 'Request failed. Please try again.',
|
||||
};
|
||||
|
||||
const resolver = createErrorResolver({
|
||||
catalog: CATALOG,
|
||||
fallbackCode: 'REQUEST_FAILED',
|
||||
defaultContext: 'default',
|
||||
contextOverrides: {
|
||||
session: {
|
||||
AUTH_UNAUTHORIZED: 'Session expired. Please sign in again.',
|
||||
},
|
||||
},
|
||||
inferCodeFromStatus: (status?: number | null) => {
|
||||
switch (status) {
|
||||
case 401:
|
||||
return 'AUTH_UNAUTHORIZED';
|
||||
case 403:
|
||||
return 'FORBIDDEN';
|
||||
case 404:
|
||||
return 'USER_NOT_FOUND';
|
||||
default:
|
||||
if (status != null && status >= 500) {
|
||||
return 'INTERNAL_ERROR';
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
inferCodeFromLegacyMessage: (message?: string | null) => {
|
||||
if (message?.toLowerCase() === 'unauthorized') {
|
||||
return 'AUTH_UNAUTHORIZED';
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
|
||||
describe('createErrorResolver', () => {
|
||||
it('recognizes known error codes', () => {
|
||||
expect(resolver.isKnownErrorCode('AUTH_UNAUTHORIZED')).toBe(true);
|
||||
expect(resolver.isKnownErrorCode('NOPE')).toBe(false);
|
||||
});
|
||||
|
||||
it('returns context override for known code', () => {
|
||||
expect(
|
||||
resolver.resolveErrorMessage({
|
||||
code: 'AUTH_UNAUTHORIZED',
|
||||
context: 'session',
|
||||
}),
|
||||
).toBe('Session expired. Please sign in again.');
|
||||
});
|
||||
|
||||
it('falls back from unknown code to legacy message inference', () => {
|
||||
expect(
|
||||
resolver.resolveErrorMessage({
|
||||
code: 'UNKNOWN_CODE',
|
||||
fallbackMessage: 'unauthorized',
|
||||
}),
|
||||
).toBe('Unauthorized access. Please sign in again.');
|
||||
});
|
||||
|
||||
it('falls back to status mapping when code is missing', () => {
|
||||
expect(resolver.resolveErrorMessage({ status: 404 })).toBe('User not found.');
|
||||
});
|
||||
|
||||
it('falls back to status mapping when legacy inference returns an unmapped code', () => {
|
||||
const resolverWithUnmappedLegacyCode = createErrorResolver({
|
||||
catalog: CATALOG,
|
||||
inferCodeFromStatus: resolver.inferErrorCodeFromStatus,
|
||||
inferCodeFromLegacyMessage: () => 'LEGACY_ONLY_CODE',
|
||||
});
|
||||
|
||||
expect(
|
||||
resolverWithUnmappedLegacyCode.resolveErrorMessage({
|
||||
status: 403,
|
||||
fallbackMessage: 'legacy message',
|
||||
}),
|
||||
).toBe('You do not have permission to perform this action.');
|
||||
});
|
||||
|
||||
it('uses fallbackCode when no code/status resolve and fallback message is missing', () => {
|
||||
expect(resolver.resolveErrorMessage({ status: 418 })).toBe('Request failed. Please try again.');
|
||||
});
|
||||
|
||||
it('uses fallback message when no mapping exists and fallback code is unavailable', () => {
|
||||
const noFallbackCodeResolver = createErrorResolver({
|
||||
catalog: CATALOG,
|
||||
inferCodeFromStatus: () => undefined,
|
||||
});
|
||||
|
||||
expect(
|
||||
noFallbackCodeResolver.resolveErrorMessage({
|
||||
code: 'UNKNOWN',
|
||||
fallbackMessage: 'raw backend message',
|
||||
}),
|
||||
).toBe('raw backend message');
|
||||
});
|
||||
|
||||
it('returns default request failure message when no signal is available', () => {
|
||||
const emptyResolver = createErrorResolver({
|
||||
catalog: {},
|
||||
});
|
||||
|
||||
expect(emptyResolver.resolveErrorMessage({})).toBe('Request failed. Please try again.');
|
||||
});
|
||||
|
||||
it('resolveOptionalErrorMessage returns undefined for empty inputs', () => {
|
||||
expect(resolver.resolveOptionalErrorMessage(undefined)).toBeUndefined();
|
||||
expect(resolver.resolveOptionalErrorMessage(null)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('resolveOptionalErrorMessage resolves known codes', () => {
|
||||
expect(resolver.resolveOptionalErrorMessage('FORBIDDEN')).toBe(
|
||||
'You do not have permission to perform this action.',
|
||||
);
|
||||
});
|
||||
|
||||
it('toErrorMessage prefers rawMessage over message and handles unknown values', () => {
|
||||
expect(
|
||||
resolver.toErrorMessage({
|
||||
status: 403,
|
||||
rawMessage: 'unauthorized',
|
||||
message: 'ignored message',
|
||||
}),
|
||||
).toBe('Unauthorized access. Please sign in again.');
|
||||
|
||||
expect(resolver.toErrorMessage('boom')).toBe('Request failed. Please try again.');
|
||||
expect(resolver.toErrorMessage(null)).toBe('Request failed. Please try again.');
|
||||
});
|
||||
|
||||
it('exposes inferErrorCodeFromStatus', () => {
|
||||
expect(resolver.inferErrorCodeFromStatus(401)).toBe('AUTH_UNAUTHORIZED');
|
||||
expect(resolver.inferErrorCodeFromStatus(500)).toBe('INTERNAL_ERROR');
|
||||
expect(resolver.inferErrorCodeFromStatus(418)).toBeUndefined();
|
||||
expect(resolver.inferErrorCodeFromStatus(null)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user