import { describe, it, expect, beforeAll } from 'vitest'; import type { Guide, Step, Screenshot } from '../src/shared/types'; class MockFileReader { result: string | ArrayBuffer | null = null; onload: ((ev: ProgressEvent) => void) | null = null; onerror: ((ev: ProgressEvent) => void) | null = null; readAsDataURL(_blob: Blob) { setTimeout(() => { this.result = `data:image/jpeg;base64,dGVzdA==`; if (this.onload) this.onload({} as ProgressEvent); }, 0); } } beforeAll(() => { // @ts-expect-error replace FileReader for test environment globalThis.FileReader = MockFileReader; }); let exportGuideAsMarkdown: typeof import('../src/export/markdown-export').exportGuideAsMarkdown; beforeAll(async () => { const mod = await import('../src/export/markdown-export'); exportGuideAsMarkdown = mod.exportGuideAsMarkdown; }); const guide: Guide = { id: 'g1', title: 'My Workflow Guide', createdAt: 1700000000000, updatedAt: 1700000000000, stepIds: ['s1', 's2'], }; const steps: Step[] = [ { id: 's1', guideId: 'g1', index: 0, description: 'Open the dashboard', action: 'click', url: 'https://example.com', timestamp: 1700000001000, screenshotId: 'sc1' }, { id: 's2', guideId: 'g1', index: 1, description: 'Click settings', action: 'click', url: 'https://example.com', timestamp: 1700000002000 }, ]; const screenshots: Map = new Map([ ['s1', { id: 'sc1', stepId: 's1', blob: new Blob(['img'], { type: 'image/jpeg' }), mimeType: 'image/jpeg', width: 800, height: 600 }], ]); describe('exportGuideAsMarkdown', () => { it('returns a string starting with # {guide.title}', async () => { const md = await exportGuideAsMarkdown(guide, steps, screenshots); expect(md.trimStart()).toMatch(/^# My Workflow Guide/); }); it('contains ## Step N: {description} format for each step', async () => { const md = await exportGuideAsMarkdown(guide, steps, screenshots); expect(md).toContain('## Step 1: Open the dashboard'); expect(md).toContain('## Step 2: Click settings'); }); it('embeds screenshot as ![Step N](data:image/jpeg;base64,...) for steps with screenshots', async () => { const md = await exportGuideAsMarkdown(guide, steps, screenshots); expect(md).toContain('![Step 1](data:image/jpeg;base64,'); }); it('steps without screenshots omit image line', async () => { const md = await exportGuideAsMarkdown(guide, steps, screenshots); expect(md).not.toContain('![Step 2]'); }); it('ends with *Generated by Mimik*', async () => { const md = await exportGuideAsMarkdown(guide, steps, screenshots); expect(md.trimEnd()).toMatch(/\*Generated by Mimik\*$/); }); });