import { describe, it, expect } from 'vitest'; import { extractPlaceholders, substitutePlaceholders, hasUnresolvedPlaceholders, validateTemplateName, getAutoFilledPlaceholders, getPlaceholdersFromTemplate, isBuiltInPlaceholder, filterTemplates, exportTemplates, importTemplates, } from '../template-utils'; import type { EmailTemplate } from '../template-types'; function makeTemplate(overrides: Partial = {}): EmailTemplate { return { id: 'test-id', name: 'Test Template', subject: '', body: '', category: '', isFavorite: false, createdAt: '2026-01-01T00:00:00Z', updatedAt: '2026-01-01T00:00:00Z', ...overrides, }; } describe('extractPlaceholders', () => { it('extracts single placeholder', () => { expect(extractPlaceholders('Hello {{name}}')).toEqual(['name']); }); it('extracts multiple placeholders', () => { const result = extractPlaceholders('{{greeting}} {{name}}, welcome to {{company}}'); expect(result).toEqual(['greeting', 'name', 'company']); }); it('deduplicates repeated placeholders', () => { expect(extractPlaceholders('{{name}} and {{name}}')).toEqual(['name']); }); it('returns empty array for no placeholders', () => { expect(extractPlaceholders('No placeholders here')).toEqual([]); }); it('handles empty string', () => { expect(extractPlaceholders('')).toEqual([]); }); it('ignores malformed placeholders', () => { expect(extractPlaceholders('{{}} {name} {{ name }}')).toEqual([]); }); it('handles underscored names', () => { expect(extractPlaceholders('{{first_name}} {{last_name}}')).toEqual(['first_name', 'last_name']); }); }); describe('substitutePlaceholders', () => { it('replaces a single placeholder', () => { expect(substitutePlaceholders('Hello {{name}}', { name: 'Alice' })).toBe('Hello Alice'); }); it('replaces multiple placeholders', () => { const result = substitutePlaceholders('{{greeting}} {{name}}', { greeting: 'Hi', name: 'Bob', }); expect(result).toBe('Hi Bob'); }); it('leaves unresolved placeholders', () => { expect(substitutePlaceholders('{{known}} {{unknown}}', { known: 'yes' })).toBe('yes {{unknown}}'); }); it('sanitizes XSS in values', () => { const result = substitutePlaceholders('{{name}}', { name: '' }); expect(result).not.toContain('' }], }); const result = importTemplates(json); expect(result.templates[0].name).not.toContain('onerror'); expect(result.templates[0].subject).not.toContain('