- Consolidated duplicate UndoManagers to single instance - Fixed connection promise to only resolve on 'connected' status - Fixed WebSocketProvider import (WebsocketProvider) - Added proper doc.destroy() cleanup - Renamed isPresenceInitialized property to avoid conflict Co-Authored-By: Paperclip <noreply@paperclip.ing>
127 lines
4.8 KiB
TypeScript
127 lines
4.8 KiB
TypeScript
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('<?xml version="1.0" encoding="UTF-8"?>');
|
|
expect(result.data).toContain('<FDX version="8.0">');
|
|
expect(result.data).toContain('</FDX>');
|
|
});
|
|
|
|
it('includes title page', () => {
|
|
const result = exporter.export(sampleElements, {
|
|
format: 'fdx',
|
|
title: 'Test Script',
|
|
author: 'Jane Doe',
|
|
});
|
|
expect(result.data).toContain('<TitlePage>');
|
|
expect(result.data).toContain('<Title>Test Script</Title>');
|
|
expect(result.data).toContain('<Author>Jane Doe</Author>');
|
|
});
|
|
|
|
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('<SceneHeading fontFaceId="0">INT. COFFEE SHOP - DAY</SceneHeading>');
|
|
});
|
|
|
|
it('exports action as Action tags', () => {
|
|
const result = exporter.export(sampleElements, { format: 'fdx' });
|
|
expect(result.data).toContain('<Action fontFaceId="0">A bustling coffee shop.</Action>');
|
|
});
|
|
|
|
it('exports characters in uppercase', () => {
|
|
const result = exporter.export(sampleElements, { format: 'fdx' });
|
|
expect(result.data).toContain('<Character fontFaceId="0">JESSICA</Character>');
|
|
});
|
|
|
|
it('exports dialogue', () => {
|
|
const result = exporter.export(sampleElements, { format: 'fdx' });
|
|
expect(result.data).toContain('<Dialogue fontFaceId="0">Hello there.</Dialogue>');
|
|
});
|
|
|
|
it('exports parentheticals', () => {
|
|
const result = exporter.export(sampleElements, { format: 'fdx' });
|
|
expect(result.data).toContain('<Parenthetical fontFaceId="0">smiling</Parenthetical>');
|
|
});
|
|
|
|
it('exports transitions in uppercase', () => {
|
|
const result = exporter.export(sampleElements, { format: 'fdx' });
|
|
expect(result.data).toContain('<Transition fontFaceId="0">SMASH CUT TO:</Transition>');
|
|
});
|
|
|
|
it('exports notes', () => {
|
|
const result = exporter.export(sampleElements, { format: 'fdx' });
|
|
expect(result.data).toContain('<Note fontFaceId="0">Writer note</Note>');
|
|
});
|
|
|
|
it('exports retained text', () => {
|
|
const result = exporter.export(sampleElements, { format: 'fdx' });
|
|
expect(result.data).toContain('<Retained fontFaceId="0">Retained from v1</Retained>');
|
|
});
|
|
|
|
it('exports centered text', () => {
|
|
const result = exporter.export(sampleElements, { format: 'fdx' });
|
|
expect(result.data).toContain('<Centered fontFaceId="0">FADE OUT.</Centered>');
|
|
});
|
|
|
|
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('<Content>');
|
|
expect(result.data).toContain('</Content>');
|
|
});
|
|
|
|
it('includes contact when provided', () => {
|
|
const result = exporter.export(sampleElements, {
|
|
format: 'fdx',
|
|
contact: 'jane@example.com',
|
|
});
|
|
expect(result.data).toContain('<Contact>jane@example.com</Contact>');
|
|
});
|
|
});
|