Files
private_image/frontend/src/utils/http/resolveAxiosErrorMessage.spec.ts
T
nobswebdev 4376ed7ff1 Expand Vitest coverage for shared frontend utils.
Cover Axios error message extraction, generic error fallbacks, ArrayBuffer views used by Web Crypto, and share URL builders.
2026-10-19 23:05:46 +02:00

83 lines
2.9 KiB
TypeScript

import { AxiosError, type InternalAxiosRequestConfig } from 'axios';
import { describe, expect, it } from 'vitest';
import { resolveAxiosErrorMessage } from '@/utils/http/resolveAxiosErrorMessage';
const fallback = 'Upload failed';
const axiosErrorWithResponse = (data: unknown, message = 'Request failed'): AxiosError => {
return new AxiosError(
message,
AxiosError.ERR_BAD_REQUEST,
{} as InternalAxiosRequestConfig,
{},
{
status: 400,
statusText: 'Bad Request',
headers: {},
config: {} as InternalAxiosRequestConfig,
data
}
);
};
describe('resolveAxiosErrorMessage', () => {
it('falls back for non-Axios errors', () => {
expect(resolveAxiosErrorMessage(new Error('network'), fallback)).toBe('network');
expect(resolveAxiosErrorMessage('oops', fallback)).toBe(fallback);
});
it('falls back when Axios error has no response', () => {
const error = new AxiosError('timeout', AxiosError.ETIMEDOUT);
expect(resolveAxiosErrorMessage(error, fallback)).toBe('timeout');
});
it('uses string response data', () => {
const error = axiosErrorWithResponse('Rate limit exceeded');
expect(resolveAxiosErrorMessage(error, fallback)).toBe('Rate limit exceeded');
});
it('uses object message string (Nest-style)', () => {
const error = axiosErrorWithResponse({ message: 'Invalid ciphertext' });
expect(resolveAxiosErrorMessage(error, fallback)).toBe('Invalid ciphertext');
});
it('uses a single string from message array', () => {
const error = axiosErrorWithResponse({ message: ['iv must be valid base64'] });
expect(resolveAxiosErrorMessage(error, fallback)).toBe('iv must be valid base64');
});
it('joins multiple strings in message array', () => {
const error = axiosErrorWithResponse({
message: ['expiresAt must be a date', 'maxViews must be a number']
});
expect(resolveAxiosErrorMessage(error, fallback)).toBe(
'expiresAt must be a date, maxViews must be a number'
);
});
it('ignores non-string entries in message array', () => {
const error = axiosErrorWithResponse({
message: ['valid', 42, null, 'also valid']
});
expect(resolveAxiosErrorMessage(error, fallback)).toBe('valid, also valid');
});
it('falls back when response data has no usable message', () => {
const error = axiosErrorWithResponse({ message: [] }, 'HTTP 400');
expect(resolveAxiosErrorMessage(error, fallback)).toBe('HTTP 400');
});
it('falls back when response data is an object without message', () => {
const error = axiosErrorWithResponse({ statusCode: 400 }, 'HTTP 400');
expect(resolveAxiosErrorMessage(error, fallback)).toBe('HTTP 400');
});
});