recording-fence-render.test.ts3.0 KBView on GitHub /**
* Does a ```recording fence actually become its node when real document markdown is parsed?
*
* Same hazard as the coaching fences: StarterKit's generic fenced-code rule will happily claim
* ```recording and render a grey code block, which to a reader is indistinguishable from "the
* video didn't load". This drives the fence through the real extension list, together with a
* moment fence carrying the new `externalId:` key, and checks both survive a round trip back to
* markdown — the node stores its body verbatim, so a lossy trip would silently rewrite a
* document every time someone opened it.
*/
import { Editor } from '@tiptap/core';
import { Markdown } from '@tiptap/markdown';
import StarterKit from '@tiptap/starter-kit';
import { MomentFenceNode } from '@/modules/documents/coaching/MomentFenceNode';
import { RecordingFenceNode } from '@/modules/documents/recording/RecordingFenceNode';
const extensions = [
StarterKit.configure({ heading: { levels: [1, 2, 3] } }),
Markdown,
MomentFenceNode,
RecordingFenceNode,
];
const DOC = [
'# Pirros — 2026-07-28',
'',
'```recording',
'provider: fathom',
'externalId: 168089693',
'title: Pirros // Marmon Mok discovery',
'at: 05:12',
'recording: https://fathom.video/share/5mga_KS6Xbvz',
'```',
'',
'## Moments',
'',
'```moment',
'deal: Marmon Mok',
'meeting: Pirros | Marmon Mok',
'at: 02:16',
'externalId: 168089693',
'provider: fathom',
'verdict: bad',
'coaching: Ask what changed since the pilot stalled.',
'',
'## moment',
'**Ben Zavala** (02:16) We are just revisiting whether we can afford it.',
'```',
].join('\n');
function types(json: unknown, acc: Set<string> = new Set()): Set<string> {
if (!json || typeof json !== 'object') return acc;
const n = json as { type?: string; content?: unknown[] };
if (n.type) acc.add(n.type);
for (const c of n.content ?? []) types(c, acc);
return acc;
}
describe('recording fence renders from real document markdown', () => {
let editor: Editor;
beforeAll(() => {
editor = new Editor({ extensions, content: DOC, contentType: 'markdown' as never });
});
afterAll(() => editor?.destroy());
it('produces a recordingBlock, not a generic code block', () => {
const t = types(editor.getJSON());
expect(t.has('recordingBlock')).toBe(true);
expect(t.has('codeBlock')).toBe(false);
});
it('still produces a momentBlock alongside it', () => {
expect(types(editor.getJSON()).has('momentBlock')).toBe(true);
});
it('round-trips both fences back to markdown with the id intact', () => {
const md = (editor as unknown as { getMarkdown: () => string }).getMarkdown();
expect(md).toContain('```recording');
expect(md).toContain('externalId: 168089693');
expect(md).toContain('title: Pirros // Marmon Mok discovery');
expect(md).toContain('```moment');
// The id is what makes the card playable; losing it on a round trip would silently
// downgrade every moment in the document to a link.
expect(md.match(/externalId: 168089693/g)).toHaveLength(2);
});
});