75 lines
2.1 KiB
TypeScript
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()
|
|
})
|
|
})
|