import { describe, expect, test } from 'bun:test'; import { HumanFormatter, XmlFormatter, getFormatter, type StatusInfo, type TreeNode } from '../lib/formatters.js'; import type { SyncDiff } from '../lib/sync/sync-engine.js'; describe('HumanFormatter', () => { const formatter = new HumanFormatter(); describe('formatSpaces', () => { test('formats list of spaces', () => { const spaces = [ { id: '1', key: 'TEST', name: 'Test Space' }, { id: '2', key: 'DOCS', name: 'Documentation' }, ]; const output = formatter.formatSpaces(spaces); expect(output).toContain('TEST'); expect(output).toContain('Test Space'); expect(output).toContain('DOCS'); expect(output).toContain('Documentation'); }); test('handles empty spaces list', () => { const output = formatter.formatSpaces([]); expect(output).toContain('No spaces found'); }); }); describe('formatSyncDiff', () => { test('formats diff with changes', () => { const diff: SyncDiff = { added: [{ type: 'added', pageId: '1', title: 'New Page' }], modified: [{ type: 'modified', pageId: '2', title: 'Updated Page' }], deleted: [{ type: 'deleted', pageId: '3', title: 'Removed Page' }], }; const output = formatter.formatSyncDiff(diff); expect(output).toContain('Added'); expect(output).toContain('New Page'); expect(output).toContain('Modified'); expect(output).toContain('Updated Page'); expect(output).toContain('Deleted'); expect(output).toContain('Removed Page'); }); test('handles no changes', () => { const diff: SyncDiff = { added: [], modified: [], deleted: [], }; const output = formatter.formatSyncDiff(diff); expect(output).toContain('No changes'); }); }); describe('formatStatus', () => { test('formats unconfigured status', () => { const status: StatusInfo = { configured: false, connected: false, initialized: false, }; const output = formatter.formatStatus(status); expect(output).toContain('Not configured'); }); test('formats configured status', () => { const status: StatusInfo = { configured: true, connected: true, initialized: true, confluenceUrl: 'https://test.atlassian.net', email: 'test@example.com', spaceKey: 'TEST', spaceName: 'Test Space', lastSync: '2024-01-01T00:00:00Z', pageCount: 10, }; const output = formatter.formatStatus(status); expect(output).toContain('https://test.atlassian.net'); expect(output).toContain('test@example.com'); expect(output).toContain('TEST'); expect(output).toContain('Test Space'); }); }); describe('formatTree', () => { test('formats page tree', () => { const nodes: TreeNode[] = [ { id: '1', title: 'Home', children: [ { id: '2', title: 'Getting Started', children: [] }, { id: '3', title: 'API Reference', children: [] }, ], }, ]; const output = formatter.formatTree(nodes); expect(output).toContain('Home'); expect(output).toContain('Getting Started'); expect(output).toContain('API Reference'); }); test('formats empty tree', () => { const output = formatter.formatTree([]); expect(output).toBe(''); }); }); }); describe('XmlFormatter', () => { const formatter = new XmlFormatter(); describe('formatSpaces', () => { test('formats spaces as XML', () => { const spaces = [{ id: '1', key: 'TEST', name: 'Test Space' }]; const output = formatter.formatSpaces(spaces); expect(output).toContain(''); expect(output).toContain(''); expect(output).toContain('key="TEST"'); expect(output).toContain('Test Space'); }); test('escapes special characters', () => { const spaces = [{ id: '1', key: 'TEST', name: 'Test & ' }]; const output = formatter.formatSpaces(spaces); expect(output).toContain('&'); expect(output).toContain('<'); expect(output).toContain('>'); }); }); describe('formatSyncDiff', () => { test('formats diff as XML', () => { const diff: SyncDiff = { added: [{ type: 'added', pageId: '1', title: 'New Page' }], modified: [], deleted: [], }; const output = formatter.formatSyncDiff(diff); expect(output).toContain(''); expect(output).toContain('id="1"'); expect(output).toContain('title="New Page"'); }); }); describe('formatStatus', () => { test('formats status as XML', () => { const status: StatusInfo = { configured: true, connected: true, initialized: true, confluenceUrl: 'https://test.atlassian.net', spaceKey: 'TEST', }; const output = formatter.formatStatus(status); expect(output).toContain('https://test.atlassian.net'); }); }); describe('formatTree', () => { test('formats tree as XML', () => { const nodes: TreeNode[] = [ { id: '1', title: 'Home', children: [{ id: '2', title: 'Child', children: [] }], }, ]; const output = formatter.formatTree(nodes); expect(output).toContain(''); expect(output).toContain(''); expect(output).toContain('id="1"'); expect(output).toContain('title="Home"'); }); }); }); describe('getFormatter', () => { test('returns HumanFormatter for non-XML mode', () => { const formatter = getFormatter(false); expect(formatter).toBeInstanceOf(HumanFormatter); }); test('returns XmlFormatter for XML mode', () => { const formatter = getFormatter(true); expect(formatter).toBeInstanceOf(XmlFormatter); }); });