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.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
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');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user