import { describe, it, expect } from 'vitest';
import { FdxExporter } from './fdx';
import type { ScreenplayElement } from '../screenplay/types';
const sampleElements: ScreenplayElement[] = [
{ id: 'e1', type: 'sceneHeading', content: 'INT. COFFEE SHOP - DAY' },
{ id: 'e2', type: 'action', content: 'A bustling coffee shop.' },
{ id: 'e3', type: 'character', content: 'Jessica' },
{ id: 'e4', type: 'dialogue', content: 'Hello there.' },
{ id: 'e5', type: 'parenthetical', content: 'smiling' },
{ id: 'e6', type: 'transition', content: 'SMASH CUT TO:' },
{ id: 'e7', type: 'note', content: 'Writer note' },
{ id: 'e8', type: 'retained', content: 'Retained from v1' },
{ id: 'e9', type: 'centered', content: 'FADE OUT.' },
];
describe('FdxExporter', () => {
const exporter = new FdxExporter();
it('supports fdx format', () => {
expect(exporter.supportedFormats).toContain('fdx');
});
it('produces valid XML structure', () => {
const result = exporter.export(sampleElements, { format: 'fdx' });
expect(result.data).toContain('');
expect(result.data).toContain('');
expect(result.data).toContain('');
});
it('includes title page', () => {
const result = exporter.export(sampleElements, {
format: 'fdx',
title: 'Test Script',
author: 'Jane Doe',
});
expect(result.data).toContain('');
expect(result.data).toContain('Test Script');
expect(result.data).toContain('Jane Doe');
});
it('includes font face and page setup', () => {
const result = exporter.export(sampleElements, { format: 'fdx' });
expect(result.data).toContain('FontFace');
expect(result.data).toContain('PageSetup');
});
it('exports scene headings as SceneHeading tags', () => {
const result = exporter.export(sampleElements, { format: 'fdx' });
expect(result.data).toContain('INT. COFFEE SHOP - DAY');
});
it('exports action as Action tags', () => {
const result = exporter.export(sampleElements, { format: 'fdx' });
expect(result.data).toContain('A bustling coffee shop.');
});
it('exports characters in uppercase', () => {
const result = exporter.export(sampleElements, { format: 'fdx' });
expect(result.data).toContain('JESSICA');
});
it('exports dialogue', () => {
const result = exporter.export(sampleElements, { format: 'fdx' });
expect(result.data).toContain('Hello there.');
});
it('exports parentheticals', () => {
const result = exporter.export(sampleElements, { format: 'fdx' });
expect(result.data).toContain('smiling');
});
it('exports transitions in uppercase', () => {
const result = exporter.export(sampleElements, { format: 'fdx' });
expect(result.data).toContain('SMASH CUT TO:');
});
it('exports notes', () => {
const result = exporter.export(sampleElements, { format: 'fdx' });
expect(result.data).toContain('Writer note');
});
it('exports retained text', () => {
const result = exporter.export(sampleElements, { format: 'fdx' });
expect(result.data).toContain('Retained from v1');
});
it('exports centered text', () => {
const result = exporter.export(sampleElements, { format: 'fdx' });
expect(result.data).toContain('FADE OUT.');
});
it('escapes XML special characters', () => {
const elements: ScreenplayElement[] = [
{ id: 'e1', type: 'action', content: 'A sign reads: "Hello & Goodbye"' },
];
const result = exporter.export(elements, { format: 'fdx' });
expect(result.data).toContain('&');
expect(result.data).toContain('"');
});
it('uses correct content type and extension', () => {
const result = exporter.export(sampleElements, { format: 'fdx' });
expect(result.contentType).toBe('application/xml');
expect(result.extension).toBe('.fdx');
});
it('generates filename from title', () => {
const result = exporter.export(sampleElements, { format: 'fdx', title: 'My Script' });
expect(result.filename).toBe('My_Script.fdx');
});
it('handles empty elements array', () => {
const result = exporter.export([], { format: 'fdx' });
expect(result.data).toContain('');
expect(result.data).toContain('');
});
it('includes contact when provided', () => {
const result = exporter.export(sampleElements, {
format: 'fdx',
contact: 'jane@example.com',
});
expect(result.data).toContain('jane@example.com');
});
});