import { ComponentDefinition } from '../component-definition'; import { IFeedbackFormStructure } from '../types'; import { validate } from '../validator'; import { MarkdownSchema } from '../components/markdown'; describe('validate()', () => { it('requires an id', () => { // @ts-expect-error pass invalid config const result = validate({ title: 'title', components: [{ type: 'TextInput', label: 'Label', questionId: 'q' }], }); expect(result.success).toBe(false); expect(result.error?.format().id).toBeDefined(); expect(result.error?.format().id!._errors[0]).toMatch(/Required/); }); it('requires a title', () => { // @ts-expect-error pass invalid config const result = validate({ id: 'id', components: [{ type: 'TextInput', label: 'Label', questionId: 'q' }], }); expect(result.success).toBe(false); expect(result.error?.format().title).toBeDefined(); expect(result.error?.format().title!._errors[0]).toMatch(/Required/); }); it('requires at least one component', () => { const result = validate({ id: 'id', title: 'title', components: [], }); expect(result.success).toBe(false); expect(result.error?.format().components).toBeDefined(); expect(result.error?.format().components!._errors[0]).toMatch( /at least 1 element/, ); }); it('requires unique question ids', () => { const result = validate({ id: 'id', title: 'title', components: [ { type: 'TextInput', label: 'Label', questionId: 'q' }, { type: 'TextInput', label: 'Label', questionId: 'q' }, ], }); expect(result.success).toBe(false); expect(result.error?.format().components).toBeDefined(); expect(result.error?.format().components!._errors[0]).toMatch( /must be unique/, ); }); it('passes with a single component', () => { const result = validate({ id: 'id', title: 'title', components: [{ type: 'TextInput', label: 'Label', questionId: 'q' }], }); expect(result.success).toBe(true); }); it('passes with all components in minimal configuration', () => { const result = validate({ id: 'id', title: 'title', components: [ { type: 'Dropdown', label: 'Label', questionId: 'q1', options: [ { id: '1', displayName: '1' }, { id: '2', displayName: '2' }, ], }, { type: 'FacesRatingBar', label: 'Label', questionId: 'q2', }, { type: 'SegmentedToggle', label: 'Label', questionId: 'q3', }, { type: 'TextInput', label: 'Label', questionId: 'q4' }, { type: 'Markdown', content: 'Simple markdown' }, ], }); expect(result.success).toBe(true); }); it('passes with all components in full configuration', () => { const result = validate({ id: 'id', title: 'title', components: [ { type: 'Dropdown', label: 'Label', questionId: 'q1', options: [ { id: '1', displayName: '1' }, { id: '2', displayName: '2' }, { id: '3', displayName: '3' }, ], placeholder: 'test', }, { type: 'FacesRatingBar', label: 'Label', questionId: 'q2', tooltips: ['1', '2', '3', '4', '5'], }, { type: 'SegmentedToggle', label: 'Label', questionId: 'q3', buttons: [ { id: 'positive', displayName: '+' }, { id: 'negative', displayName: '-' }, ], }, { type: 'Thumbnails', label: 'Label', questionId: 'thumbnailsQuestion', options: [ { id: 'opt1', label: 'Label 1', imageUrl: 'https://placehold.co/400x300', }, { id: 'opt2', label: 'Label 2', imageUrl: 'https://placehold.co/400x300', }, ], }, { type: 'TextInput', label: 'Label', questionId: 'q4', placeholder: 'test', }, { type: 'Markdown', content: 'This is **full** markdown with [link](https://example.com).', }, ], }); expect(result.success).toBe(true); }); it('MarkdownSchema accepts valid markdown', () => { const result = MarkdownSchema.safeParse({ type: 'Markdown', content: 'Hello **world**', }); expect(result.success).toBe(true); }); it('MarkdownSchema rejects empty content', () => { const result = MarkdownSchema.safeParse({ type: 'Markdown', content: '', }); expect(result.success).toBe(false); }); it('MarkdownSchema rejects invalid type', () => { const result = MarkdownSchema.safeParse({ type: 'MarkdownX', content: 'Some text', }); expect(result.success).toBe(false); }); });