Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
81 lines
3.2 KiB
TypeScript
81 lines
3.2 KiB
TypeScript
import { AxiosError, AxiosHeaders } from 'axios'
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
import {
|
|
extractServerErrorDetail,
|
|
NETWORK_ERROR_MESSAGE_KEY,
|
|
normalizeServiceError,
|
|
resolveServiceErrorDisplayMessage,
|
|
} from '@/services/errorHandler'
|
|
|
|
describe('service error normalization', () => {
|
|
it('extracts nested validation messages', () => {
|
|
expect(extractServerErrorDetail({ body: { message: ['شماره نامعتبر است', 'کد منقضی شده است'] } })).toBe(
|
|
'شماره نامعتبر است\nکد منقضی شده است'
|
|
)
|
|
})
|
|
|
|
it('preserves API code, status and useful server detail', () => {
|
|
const error = new AxiosError('Request failed with status code 409', 'ERR_BAD_REQUEST', undefined, undefined, {
|
|
data: { message: 'رزرو فعال وجود دارد', code: 'ACTIVE_BOOKING_EXISTS' },
|
|
status: 409,
|
|
statusText: 'Conflict',
|
|
headers: {},
|
|
config: { headers: new AxiosHeaders() },
|
|
})
|
|
const normalized = normalizeServiceError(error)
|
|
|
|
expect(normalized.apiCode).toBe('ACTIVE_BOOKING_EXISTS')
|
|
expect(normalized.statusCode).toBe(409)
|
|
expect(normalized.detailMessage).toBe('رزرو فعال وجود دارد')
|
|
})
|
|
|
|
it('maps transport failures to localized network errors', () => {
|
|
const normalized = normalizeServiceError(new AxiosError('Network Error', 'ERR_NETWORK'))
|
|
|
|
expect(normalized.messageKey).toBe(NETWORK_ERROR_MESSAGE_KEY)
|
|
expect(
|
|
resolveServiceErrorDisplayMessage(normalized, {
|
|
apiError: 'خطای API',
|
|
networkError: 'خطای شبکه',
|
|
})
|
|
).toBe('خطای شبکه')
|
|
})
|
|
|
|
it('replaces an English API message with Persian copy and preserves its code', () => {
|
|
const error = new AxiosError('Request failed with status code 409', 'ERR_BAD_REQUEST', undefined, undefined, {
|
|
data: { message: 'An active booking already exists', code: 'ACTIVE_BOOKING_EXISTS' },
|
|
status: 409,
|
|
statusText: 'Conflict',
|
|
headers: {},
|
|
config: { headers: new AxiosHeaders() },
|
|
})
|
|
const normalized = normalizeServiceError(error)
|
|
|
|
expect(normalized.message).toBe('برای این رویداد رزرو فعال دارید.')
|
|
expect(normalized.detailMessage).toBe('برای این رویداد رزرو فعال دارید.')
|
|
expect(normalized.apiCode).toBe('ACTIVE_BOOKING_EXISTS')
|
|
})
|
|
|
|
it('uses a Persian status fallback for unknown English server errors', () => {
|
|
const error = new AxiosError('Request failed with status code 503', 'ERR_BAD_RESPONSE', undefined, undefined, {
|
|
data: { message: 'Service unavailable' },
|
|
status: 503,
|
|
statusText: 'Service Unavailable',
|
|
headers: {},
|
|
config: { headers: new AxiosHeaders() },
|
|
})
|
|
|
|
expect(normalizeServiceError(error).message).toBe('سرویس موقتاً در دسترس نیست. لطفاً کمی بعد دوباره تلاش کنید.')
|
|
})
|
|
|
|
it('never returns an English-only display message', () => {
|
|
expect(
|
|
resolveServiceErrorDisplayMessage(
|
|
{ message: 'Internal Server Error', detailMessage: 'Database connection failed' },
|
|
{ apiError: 'خطای API', networkError: 'خطای شبکه' }
|
|
)
|
|
).toBe('خطایی در انجام درخواست پیش آمد.')
|
|
})
|
|
})
|