- Implement tests for Pagination, StatusBadge, ConfirmDialog, and MobileInput components. - Add tests for useSubscription, usePaymentConfig, and usePwaInstall hooks. - Create tests for API requests in the api module, including success and error handling. - Add utility function tests for formatting and validating Iranian mobile numbers. - Implement tests for BlogFormPage and BlogsPage to validate form submissions and data fetching. - Add tests for LoginPage to ensure proper validation and state management. - Create tests for authStore and uiStore to validate state management and functionality. - Set up Vitest configuration and testing utilities for consistent testing environment.
171 lines
5.8 KiB
TypeScript
171 lines
5.8 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
||
import {
|
||
formatRial,
|
||
formatNumber,
|
||
toDate,
|
||
formatDate,
|
||
formatDateTime,
|
||
toGregorianDate,
|
||
maskMobile,
|
||
cn,
|
||
toEnglishDigits,
|
||
sanitizeMobileInput,
|
||
isValidIranMobile,
|
||
IRAN_MOBILE_RE,
|
||
iranMobileSchema,
|
||
iranMobileOptionalSchema,
|
||
} from '@/lib/utils';
|
||
|
||
const PERSIAN_DIGITS = /[۰-۹]/;
|
||
|
||
describe('formatRial', () => {
|
||
it('عدد را با جداکننده فارسی و پسوند تومان برمیگرداند', () => {
|
||
const out = formatRial(1000);
|
||
expect(out).toContain('تومان');
|
||
expect(out).toMatch(PERSIAN_DIGITS);
|
||
});
|
||
it('صفر را هم فرمت میکند', () => {
|
||
expect(formatRial(0)).toContain('تومان');
|
||
});
|
||
});
|
||
|
||
describe('formatNumber', () => {
|
||
it('رقم فارسی برمیگرداند', () => {
|
||
expect(formatNumber(1234)).toMatch(PERSIAN_DIGITS);
|
||
});
|
||
});
|
||
|
||
describe('toDate', () => {
|
||
it('null و رشته خالی → null', () => {
|
||
expect(toDate(null)).toBeNull();
|
||
expect(toDate(undefined)).toBeNull();
|
||
expect(toDate('')).toBeNull();
|
||
});
|
||
it('عدد را بهعنوان ثانیه (×۱۰۰۰) تفسیر میکند', () => {
|
||
const d = toDate(1_700_000_000);
|
||
expect(d).toBeInstanceOf(Date);
|
||
expect(d!.getTime()).toBe(1_700_000_000 * 1000);
|
||
});
|
||
it('Y-m-d را ظهر محلی میگیرد (نه نیمهشب UTC)', () => {
|
||
const d = toDate('2024-03-21');
|
||
expect(d!.getHours()).toBe(12);
|
||
expect(d!.getFullYear()).toBe(2024);
|
||
});
|
||
it('رشته ISO کامل را پارس میکند', () => {
|
||
const d = toDate('2024-03-21T08:30:00Z');
|
||
expect(d).toBeInstanceOf(Date);
|
||
expect(isNaN(d!.getTime())).toBe(false);
|
||
});
|
||
});
|
||
|
||
describe('formatDate', () => {
|
||
it('ورودی نامعتبر → "—"', () => {
|
||
expect(formatDate(null)).toBe('—');
|
||
expect(formatDate('not-a-date')).toBe('—');
|
||
});
|
||
it('timestamp ثانیهای معتبر → رشته شمسی با رقم فارسی', () => {
|
||
const out = formatDate(1_700_000_000);
|
||
expect(out).not.toBe('—');
|
||
expect(out).toMatch(PERSIAN_DIGITS);
|
||
});
|
||
});
|
||
|
||
describe('formatDateTime', () => {
|
||
it('ورودی نامعتبر → "—"', () => {
|
||
expect(formatDateTime(undefined)).toBe('—');
|
||
});
|
||
it('معتبر → شامل ساعت و رقم فارسی', () => {
|
||
const out = formatDateTime(1_700_000_000);
|
||
expect(out).not.toBe('—');
|
||
expect(out).toMatch(PERSIAN_DIGITS);
|
||
});
|
||
});
|
||
|
||
describe('toGregorianDate', () => {
|
||
it('YYYY-MM-DD با صفر پیشرو', () => {
|
||
expect(toGregorianDate(new Date(2024, 0, 5))).toBe('2024-01-05');
|
||
expect(toGregorianDate(new Date(2024, 11, 31))).toBe('2024-12-31');
|
||
});
|
||
});
|
||
|
||
describe('maskMobile', () => {
|
||
it('شماره ۱۱ رقمی را ماسک میکند', () => {
|
||
expect(maskMobile('09123456789')).toBe('0912***789');
|
||
});
|
||
it('شماره کوتاهتر از ۷ رقم بدون تغییر', () => {
|
||
expect(maskMobile('123')).toBe('123');
|
||
});
|
||
});
|
||
|
||
describe('cn', () => {
|
||
it('مقادیر falsy را حذف و بقیه را با فاصله میچسباند', () => {
|
||
expect(cn('a', false, null, undefined, 'b')).toBe('a b');
|
||
expect(cn()).toBe('');
|
||
});
|
||
});
|
||
|
||
describe('toEnglishDigits', () => {
|
||
it('رقم فارسی به انگلیسی', () => {
|
||
expect(toEnglishDigits('۰۹۱۲۳۴۵۶۷۸۹')).toBe('09123456789');
|
||
});
|
||
it('رقم عربی به انگلیسی', () => {
|
||
expect(toEnglishDigits('٠٩١٢')).toBe('0912');
|
||
});
|
||
it('ورودی خالی → رشته خالی', () => {
|
||
expect(toEnglishDigits('')).toBe('');
|
||
});
|
||
it('کاراکترهای غیررقمی را دستنخورده نگه میدارد', () => {
|
||
expect(toEnglishDigits('شماره ۰۹')).toBe('شماره 09');
|
||
});
|
||
});
|
||
|
||
describe('sanitizeMobileInput', () => {
|
||
it('غیررقم حذف، رقم فارسی نرمال، حداکثر ۱۱ رقم', () => {
|
||
expect(sanitizeMobileInput('۰۹۱۲-۳۴۵ ۶۷۸۹۰۱۲')).toBe('09123456789');
|
||
});
|
||
it('فقط حروف → خالی', () => {
|
||
expect(sanitizeMobileInput('abc')).toBe('');
|
||
});
|
||
});
|
||
|
||
describe('isValidIranMobile / IRAN_MOBILE_RE', () => {
|
||
it.each([
|
||
['09123456789', true],
|
||
['۰۹۱۲۳۴۵۶۷۸۹', true],
|
||
['9123456789', false],
|
||
['08123456789', false],
|
||
['0912345678', false],
|
||
['091234567890', false],
|
||
])('%s → %s', (input, expected) => {
|
||
expect(isValidIranMobile(input as string)).toBe(expected);
|
||
});
|
||
it('regex مستقیم روی ارقام انگلیسی', () => {
|
||
expect(IRAN_MOBILE_RE.test('09120000000')).toBe(true);
|
||
});
|
||
});
|
||
|
||
describe('iranMobileSchema', () => {
|
||
it('رقم فارسی را پذیرفته و نرمال میکند', () => {
|
||
expect(iranMobileSchema.parse('۰۹۱۲۳۴۵۶۷۸۹')).toBe('09123456789');
|
||
});
|
||
it('جداکنندهها را حذف میکند', () => {
|
||
expect(iranMobileSchema.parse('0912-345-6789')).toBe('09123456789');
|
||
});
|
||
it('شماره نامعتبر → ناموفق', () => {
|
||
const r = iranMobileSchema.safeParse('12345');
|
||
expect(r.success).toBe(false);
|
||
});
|
||
});
|
||
|
||
describe('iranMobileOptionalSchema', () => {
|
||
it('رشته خالی مجاز است', () => {
|
||
expect(iranMobileOptionalSchema.parse('')).toBe('');
|
||
});
|
||
it('شماره معتبر نرمال میشود', () => {
|
||
expect(iranMobileOptionalSchema.parse('۰۹۱۲۳۴۵۶۷۸۹')).toBe('09123456789');
|
||
});
|
||
it('شماره نیمهکاره → ناموفق', () => {
|
||
expect(iranMobileOptionalSchema.safeParse('0912').success).toBe(false);
|
||
});
|
||
});
|