import { EditorSelection } from '@codemirror/state'; import createTestEditor from '../../testing/createTestEditor'; import renderBlockMedia from './renderBlockMedia'; import { EditorView } from '@codemirror/view'; const allowMediaInfoToResolve = async () => { // Yield to the event loop. Since resource info is fetched asynchronously, this is // needed to allow the asynchronous promise code to run await Promise.resolve(); }; const resolveResourceInfo = jest.fn((src: string) => { const match = src.match(/:\/([a-zA-Z0-9]{32})/); const id = match ? match[1] : ''; const mimeById: Record = { 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa': 'audio/mpeg', 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb': 'video/mp4', 'cccccccccccccccccccccccccccccccc': 'application/pdf', }; const mime = mimeById[id]; if (!mime) return Promise.resolve(null); return Promise.resolve({ url: `https://example.com/${id}`, mime }); }); const createEditor = async (initialMarkdown: string) => { const editor = await createTestEditor( initialMarkdown, EditorSelection.cursor(0), ['Link'], [renderBlockMedia({ resolveImageSrc: async () => '', openLink: () => {}, resolveResourceInfo })], ); await allowMediaInfoToResolve(); return editor; }; const findMedia = (editor: EditorView) => { return editor.dom.querySelectorAll('div.cm-md-media > audio, div.cm-md-media > video'); }; describe('renderBlockMedia', () => { test.each([ { markup: '[recording.m4a](:/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)', tag: 'AUDIO' }, { markup: '[video.mp4](:/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)', tag: 'VIDEO' }, { markup: '[3月24日(1).mp4](:/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)', tag: 'BODY' }, ])('should render a player below a standalone media link (case %#)', async ({ markup, tag }) => { const editor = await createEditor(markup); const media = findMedia(editor); expect(media).toHaveLength(1); expect(media[0].getAttribute('aria-label')).toContain(tag === 'BODY' ? '3月24日(1).mp4' : tag === 'AUDIO' ? 'recording.m4a' : 'video.mp4'); // The raw Markdown must stay editable above the player expect(editor.state.doc.toString()).toContain(markup); }); test('should not render a player for non-media attachments', async () => { const editor = await createEditor('[doc.pdf](:/cccccccccccccccccccccccccccccccc)'); expect(findMedia(editor)).toHaveLength(0); // The leftover placeholder wrapper must be removed expect(editor.dom.querySelectorAll('div.cm-md-media')).toHaveLength(0); }); test('should not render a player for web links', async () => { const editor = await createEditor('[video](https://example.com/video.mp4)'); expect(findMedia(editor)).toHaveLength(0); expect(editor.dom.querySelectorAll('div.cm-md-media')).toHaveLength(0); }); });