File size: 2,615 Bytes
391c43e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | import { describe, it, expect } from 'vitest';
import { templateToForm, formToTemplate, validateTemplateForm, emptyForm } from '../template-form';
import type { InterviewTemplate } from '../types';
describe('template-form', () => {
it('emptyForm has one blank required item and a default artifact path', () => {
const f = emptyForm();
expect(f.items).toHaveLength(1);
expect(f.items[0].required).toBe(true);
expect(f.artifactPath).toBe('/.interviews/untitled.md');
});
it('formToTemplate maps each item to a single judge assertion with a slug id', () => {
const f = emptyForm();
f.title = 'My Interview';
f.artifactPath = '/.interviews/my-interview.md';
f.items[0].question = 'What is the goal?';
f.items[0].criteria = 'The artifact states the goal.';
const t = formToTemplate(f, 'my-interview');
expect(t.id).toBe('my-interview');
expect(t.artifacts).toEqual([{ path: '/.interviews/my-interview.md' }]);
expect(t.items[0]).toMatchObject({
id: 'what-is-the-goal',
elicit: 'What is the goal?',
required: true,
completion: [{ type: 'judge', criteria: 'The artifact states the goal.', description: expect.any(String) }],
});
});
it('templateToForm round-trips a built-in', () => {
const t: InterviewTemplate = {
id: 'x', title: 'X', description: 'd',
artifacts: [{ path: '/.interviews/x.md' }],
items: [{ id: 'a', elicit: 'Q?', completion: [{ type: 'judge', criteria: 'C', description: 'c' }], required: false }],
};
const f = templateToForm(t);
expect(f.title).toBe('X');
expect(f.artifactPath).toBe('/.interviews/x.md');
expect(f.items[0]).toMatchObject({ question: 'Q?', criteria: 'C', required: false });
});
it('validation rejects empty title, no items, or missing question/criteria', () => {
const f = emptyForm();
expect(validateTemplateForm(f)).toContain('title');
f.title = 'T';
expect(validateTemplateForm(f)).toMatch(/question|done when|criteria/i);
f.items[0].question = 'Q'; f.items[0].criteria = 'C';
expect(validateTemplateForm(f)).toBeNull();
});
it('rejects an artifact path outside /.interviews/ or not ending in .md', () => {
const f = emptyForm();
f.title = 'T'; f.items[0].question = 'Q'; f.items[0].criteria = 'C';
f.artifactPath = '/public/x.md';
expect(validateTemplateForm(f)).toMatch(/\.interviews/i);
f.artifactPath = '/.interviews/x.txt';
expect(validateTemplateForm(f)).toMatch(/\.md/i);
f.artifactPath = '/.interviews/../x.md';
expect(validateTemplateForm(f)).toMatch(/\.\./);
});
});
|