import { describe, it, expect, vi } from 'vitest'; import { z } from 'zod'; describe('Contact Page', () => { describe('form schema validation', () => { const mockT = (key: string) => key; const schema = z.object({ email: z.email(mockT('pages.contact.form.validation.invalidEmail')), name: z .string() .min(1, mockT('pages.contact.form.validation.shortName')) .max(100, mockT('pages.contact.form.validation.longName')), message: z .string() .min(10, mockT('pages.contact.form.validation.shortMessage')) .max(5000, mockT('pages.contact.form.validation.longMessage')), website: z.string().optional(), }); it('should validate valid form data', () => { const validData = { email: 'test@example.com', name: 'John Doe', message: 'This is a test message that is longer than 10 characters', website: '', }; const result = schema.safeParse(validData); expect(result.success).toBe(true); }); it('should reject invalid email', () => { const invalidData = { email: 'invalid-email', name: 'John Doe', message: 'This is a valid message', }; const result = schema.safeParse(invalidData); expect(result.success).toBe(false); }); it('should reject empty name', () => { const invalidData = { email: 'test@example.com', name: '', message: 'This is a valid message', }; const result = schema.safeParse(invalidData); expect(result.success).toBe(false); }); it('should reject too long name (>100 chars)', () => { const invalidData = { email: 'test@example.com', name: 'a'.repeat(101), message: 'This is a valid message', }; const result = schema.safeParse(invalidData); expect(result.success).toBe(false); }); it('should reject too short message (<10 chars)', () => { const invalidData = { email: 'test@example.com', name: 'John Doe', message: 'Short', }; const result = schema.safeParse(invalidData); expect(result.success).toBe(false); }); it('should reject too long message (>5000 chars)', () => { const invalidData = { email: 'test@example.com', name: 'John Doe', message: 'a'.repeat(5001), }; const result = schema.safeParse(invalidData); expect(result.success).toBe(false); }); it('should allow optional website field', () => { const validData = { email: 'test@example.com', name: 'John Doe', message: 'This is a valid test message', }; const result = schema.safeParse(validData); expect(result.success).toBe(true); }); it('should accept website when provided', () => { const validData = { email: 'test@example.com', name: 'John Doe', message: 'This is a valid test message', website: 'https://example.com', }; const result = schema.safeParse(validData); expect(result.success).toBe(true); }); }); describe('form state', () => { it('should initialize with undefined values', () => { const state = reactive({ name: undefined as string | undefined, email: undefined as string | undefined, message: undefined as string | undefined, website: undefined as string | undefined, }); expect(state.name).toBeUndefined(); expect(state.email).toBeUndefined(); expect(state.message).toBeUndefined(); expect(state.website).toBeUndefined(); }); it('should update values when set', () => { const state = reactive({ name: undefined as string | undefined, email: undefined as string | undefined, message: undefined as string | undefined, website: undefined as string | undefined, }); state.name = 'John Doe'; state.email = 'test@example.com'; state.message = 'Hello, this is a test message'; expect(state.name).toBe('John Doe'); expect(state.email).toBe('test@example.com'); expect(state.message).toBe('Hello, this is a test message'); }); }); describe('toast notification logic', () => { it('should show success toast on successful response', () => { const mockToastAdd = vi.fn(); const mockT = (key: string) => key; const response = { success: true, message: 'Message sent successfully' }; // Simulate the watcher behavior if (response) { mockToastAdd({ title: response.success ? mockT('pages.contact.toast.success') : mockT('pages.contact.toast.error'), description: mockT(response.message), color: response.success ? 'info' : 'error', }); } expect(mockToastAdd).toHaveBeenCalledWith({ title: 'pages.contact.toast.success', description: 'Message sent successfully', color: 'info', }); }); it('should show error toast on failed response', () => { const mockToastAdd = vi.fn(); const mockT = (key: string) => key; const response = { success: false, message: 'Failed to send' }; if (response) { mockToastAdd({ title: response.success ? mockT('pages.contact.toast.success') : mockT('pages.contact.toast.error'), description: mockT(response.message), color: response.success ? 'info' : 'error', }); } expect(mockToastAdd).toHaveBeenCalledWith({ title: 'pages.contact.toast.error', description: 'Failed to send', color: 'error', }); }); it('should show error toast on contact error', () => { const mockToastAdd = vi.fn(); const mockT = (key: string) => key; const error = { message: 'backend.errors.unknown' }; if (error) { mockToastAdd({ title: mockT('pages.contact.toast.error'), description: mockT(error.message), color: 'error', }); } expect(mockToastAdd).toHaveBeenCalledWith({ title: 'pages.contact.toast.error', description: 'backend.errors.unknown', color: 'error', }); }); }); });