FRE-600: Fix code review blockers

- 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>
This commit is contained in:
2026-04-25 00:08:01 -04:00
parent 65b552bb08
commit 7c684a42cc
48450 changed files with 5679671 additions and 383 deletions

126
src/lib/export/fdx.test.ts Normal file
View File

@@ -0,0 +1,126 @@
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('&amp;');
expect(result.data).toContain('&quot;');
});
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>');
});
});