Files
framit/app/pages/contact.test.ts

208 lines
6.1 KiB
TypeScript
Raw Normal View History

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',
});
});
});
});