Cover Axios error message extraction, generic error fallbacks, ArrayBuffer views used by Web Crypto, and share URL builders.
83 lines
2.9 KiB
TypeScript
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');
|
|
});
|
|
});
|