import { describe, it, expect, vi, beforeEach } from 'vitest' import { createMockEvent } from '../helpers/createMockEvent.js' import { emailSchema, memberCreateSchema, memberProfileUpdateSchema, eventRegistrationSchema, paymentVerifySchema, adminEventCreateSchema } from '../../../server/utils/schemas.js' import { validateBody } from '../../../server/utils/validateBody.js' // --- Schema unit tests --- describe('emailSchema', () => { it('accepts a valid email', () => { const result = emailSchema.safeParse({ email: 'test@example.com' }) expect(result.success).toBe(true) expect(result.data.email).toBe('test@example.com') }) it('rejects a malformed email', () => { const result = emailSchema.safeParse({ email: 'not-an-email' }) expect(result.success).toBe(false) }) it('rejects missing email', () => { const result = emailSchema.safeParse({}) expect(result.success).toBe(false) }) it('trims and lowercases email', () => { const result = emailSchema.safeParse({ email: ' Test@EXAMPLE.COM ' }) expect(result.success).toBe(true) expect(result.data.email).toBe('test@example.com') }) }) describe('memberCreateSchema', () => { const validMember = { email: 'new@example.com', name: 'Test User', circle: 'community', contributionTier: '0' } it('accepts valid member data', () => { const result = memberCreateSchema.safeParse(validMember) expect(result.success).toBe(true) }) it('rejects role field (mass assignment)', () => { const result = memberCreateSchema.safeParse({ ...validMember, role: 'admin' }) expect(result.success).toBe(true) // role should NOT be in the output expect(result.data).not.toHaveProperty('role') }) it('rejects status field (mass assignment)', () => { const result = memberCreateSchema.safeParse({ ...validMember, status: 'active' }) expect(result.success).toBe(true) expect(result.data).not.toHaveProperty('status') }) it('rejects helcimCustomerId field (mass assignment)', () => { const result = memberCreateSchema.safeParse({ ...validMember, helcimCustomerId: 'cust_123' }) expect(result.success).toBe(true) expect(result.data).not.toHaveProperty('helcimCustomerId') }) it('rejects _id field (mass assignment)', () => { const result = memberCreateSchema.safeParse({ ...validMember, _id: '507f1f77bcf86cd799439011' }) expect(result.success).toBe(true) expect(result.data).not.toHaveProperty('_id') }) it('rejects invalid circle enum', () => { const result = memberCreateSchema.safeParse({ ...validMember, circle: 'superadmin' }) expect(result.success).toBe(false) }) it('rejects invalid contributionTier enum', () => { const result = memberCreateSchema.safeParse({ ...validMember, contributionTier: '999' }) expect(result.success).toBe(false) }) it('rejects missing required fields', () => { const result = memberCreateSchema.safeParse({ email: 'test@example.com' }) expect(result.success).toBe(false) }) it('lowercases email', () => { const result = memberCreateSchema.safeParse({ ...validMember, email: 'NEW@Example.COM' }) expect(result.success).toBe(true) expect(result.data.email).toBe('new@example.com') }) }) describe('eventRegistrationSchema', () => { it('accepts valid registration', () => { const result = eventRegistrationSchema.safeParse({ name: 'Jane', email: 'jane@example.com' }) expect(result.success).toBe(true) }) it('rejects missing name', () => { const result = eventRegistrationSchema.safeParse({ email: 'jane@example.com' }) expect(result.success).toBe(false) }) it('rejects malformed email', () => { const result = eventRegistrationSchema.safeParse({ name: 'Jane', email: 'bad' }) expect(result.success).toBe(false) }) it('lowercases email', () => { const result = eventRegistrationSchema.safeParse({ name: 'Jane', email: 'JANE@Example.COM' }) expect(result.success).toBe(true) expect(result.data.email).toBe('jane@example.com') }) }) describe('paymentVerifySchema', () => { it('accepts valid card token and customer ID', () => { const result = paymentVerifySchema.safeParse({ cardToken: 'tok_123', customerId: 'cust_456' }) expect(result.success).toBe(true) }) it('rejects missing cardToken', () => { const result = paymentVerifySchema.safeParse({ customerId: 'cust_456' }) expect(result.success).toBe(false) }) it('rejects empty cardToken', () => { const result = paymentVerifySchema.safeParse({ cardToken: '', customerId: 'cust_456' }) expect(result.success).toBe(false) }) }) describe('adminEventCreateSchema', () => { const validEvent = { title: 'Test Event', description: 'A test event', startDate: '2026-04-01T10:00:00Z', endDate: '2026-04-01T12:00:00Z' } it('accepts valid event data', () => { const result = adminEventCreateSchema.safeParse(validEvent) expect(result.success).toBe(true) }) it('rejects missing title', () => { const { title, ...rest } = validEvent const result = adminEventCreateSchema.safeParse(rest) expect(result.success).toBe(false) }) it('rejects missing dates', () => { const { startDate, endDate, ...rest } = validEvent const result = adminEventCreateSchema.safeParse({ ...rest, title: 'Test' }) expect(result.success).toBe(false) }) }) describe('memberProfileUpdateSchema', () => { it('rejects role in profile update', () => { const result = memberProfileUpdateSchema.safeParse({ role: 'admin', bio: 'test' }) expect(result.success).toBe(true) expect(result.data).not.toHaveProperty('role') }) it('rejects status in profile update', () => { const result = memberProfileUpdateSchema.safeParse({ status: 'active', bio: 'test' }) expect(result.success).toBe(true) expect(result.data).not.toHaveProperty('status') }) it('strips unknown privacy fields from profile update', () => { const result = memberProfileUpdateSchema.safeParse({ bioPrivacy: 'members', bio: 'hello' }) expect(result.success).toBe(true) expect(result.data).not.toHaveProperty('bioPrivacy') expect(result.data.bio).toBe('hello') }) }) // --- validateBody integration tests --- describe('validateBody', () => { it('returns validated data on success', async () => { const event = createMockEvent({ method: 'POST', body: { email: 'test@example.com' } }) const data = await validateBody(event, emailSchema) expect(data.email).toBe('test@example.com') }) it('throws 400 on validation failure', async () => { const event = createMockEvent({ method: 'POST', body: { email: 'bad' } }) await expect(validateBody(event, emailSchema)).rejects.toMatchObject({ statusCode: 400, statusMessage: 'Validation failed' }) }) it('strips unknown fields from output', async () => { const event = createMockEvent({ method: 'POST', body: { email: 'test@example.com', name: 'Test', circle: 'community', contributionTier: '0', role: 'admin', _id: 'fake' } }) const data = await validateBody(event, memberCreateSchema) expect(data).not.toHaveProperty('role') expect(data).not.toHaveProperty('_id') expect(data.email).toBe('test@example.com') expect(data.name).toBe('Test') }) })