import { beforeEach, describe, expect, it, vi } from 'vitest' import { showFormValidationToast } from '@/lib/formValidationToast' import { addToast } from '@/lib/toast' import { texts } from '@/texts' vi.mock('@/lib/toast', () => ({ addToast: vi.fn(), })) describe('showFormValidationToast', () => { beforeEach(() => { vi.mocked(addToast).mockClear() }) it('shows the first nested field message', () => { showFormValidationToast({ profile: { mobile: { type: 'pattern', message: 'شماره موبایل معتبر نیست' }, }, }) expect(addToast).toHaveBeenCalledWith({ title: texts.common.formIncomplete, description: 'شماره موبایل معتبر نیست', color: 'danger', }) }) it('does not recurse into FieldError.ref circular graphs', () => { const parent: { child?: object } = {} const input = { tagName: 'INPUT', parentNode: parent } parent.child = input expect(() => { showFormValidationToast({ mobile: { type: 'pattern', message: '', ref: input as never, }, code: { type: 'required', message: 'کد را وارد کنید' }, }) }).not.toThrow() expect(addToast).toHaveBeenCalledWith({ title: texts.common.formIncomplete, description: 'کد را وارد کنید', color: 'danger', }) }) it('tolerates self-referential error trees without throwing', () => { const errors: Record = {} errors.root = errors errors.mobile = { type: 'required', message: 'شماره موبایل را وارد کنید' } expect(() => { showFormValidationToast(errors as never) }).not.toThrow() expect(addToast).toHaveBeenCalledWith({ title: texts.common.formIncomplete, description: 'شماره موبایل را وارد کنید', color: 'danger', }) }) it('falls back when no message can be read safely', () => { const cyclic: Record = {} cyclic.self = cyclic showFormValidationToast(cyclic as never) expect(addToast).toHaveBeenCalledWith({ title: texts.common.formIncomplete, description: texts.common.formValidationDefault, color: 'danger', }) }) })