Files
landing-builder/lib/schema/page.test.ts
T
2025-11-14 16:40:45 +09:00

75 lines
2.1 KiB
TypeScript

import { describe, it, expect } from 'vitest'
// TDD: 아직 구현되지 않은 스키마를 가정
import { pageSchema } from '@/lib/schema/page'
describe('pageSchema', () => {
it('유효한 랜딩 페이지 스키마를 통과시킨다', () => {
const valid = {
title: 'My Landing',
locale: 'en',
theme: {
primaryColor: '#0ea5e9',
fontFamily: 'Inter',
},
sections: [
{
type: 'hero',
props: {
heading: 'Hello',
subheading: 'World',
imageUrl: 'https://cdn.example.com/hero.png',
},
},
],
form: {
actionUrl: '', // 빈 문자열이면 Sheets로 제출(향후 로직)
fields: [
{ type: 'text', name: 'name', label: 'Name', required: true },
{ type: 'email', name: 'email', label: 'Email', required: true },
{ type: 'checkbox', name: 'agree', label: 'Agree', required: true },
],
spamProtection: {
honeypotFieldName: '_hp',
minSubmitSeconds: 2,
},
},
analytics: {
ga4MeasurementId: '',
metaPixelId: '',
customHeadHtml: '',
},
seo: {
title: 'My Landing',
description: 'Best product',
ogImage: 'https://cdn.example.com/og.png',
},
}
const parsed = pageSchema.parse(valid)
expect(parsed.title).toBe('My Landing')
expect(parsed.sections.length).toBe(1)
})
it('파일 업로드 필드는 허용하지 않는다', () => {
const invalid = {
title: 'No File Please',
locale: 'en',
theme: { primaryColor: '#000000', fontFamily: 'Inter' },
sections: [],
form: {
actionUrl: '',
fields: [
// 파일 타입은 금지
{ type: 'file', name: 'attachment', label: 'Upload' },
],
spamProtection: { honeypotFieldName: '_hp', minSubmitSeconds: 2 },
},
analytics: {},
seo: { title: 'x', description: '', ogImage: '' },
}
expect(() => pageSchema.parse(invalid)).toThrow()
})
})