agentFrontmatter.test.ts3.2 KBView on GitHub
import { Schema } from '@tiptap/pm/model';

import { __testing } from '@/modules/documents/agent/HideFrontmatterExtension';

const { frontmatterDecorations, FRONTMATTER_LANG } = __testing;

/**
 * A minimal schema with the three node types the rule keys on. Building a real TipTap
 * editor here would drag in the whole Yjs/collab stack for a function that only reads
 * `doc.child(i).type.name` and one attribute.
 */
const schema = new Schema({
  nodes: {
    doc: { content: 'block+' },
    paragraph: { group: 'block', content: 'text*', toDOM: () => ['p', 0] },
    codeBlock: {
      group: 'block',
      content: 'text*',
      attrs: { language: { default: null } },
      toDOM: () => ['pre', ['code', 0]],
    },
    horizontalRule: { group: 'block', toDOM: () => ['hr'] },
    text: {},
  },
});

const para = (text: string) => schema.nodes.paragraph!.create(null, text ? schema.text(text) : null);
const hr = () => schema.nodes.horizontalRule!.create();
const code = (language: string | null, text = 'name: coaching') =>
  schema.nodes.codeBlock!.create({ language }, schema.text(text));
const doc = (...children: ReturnType<typeof para>[]) => schema.nodes.doc!.create(null, children);

describe('agent frontmatter hiding', () => {
  it('hides the sentinel code block — the shape the server actually emits', () => {
    // `extractFrontmatter` peels the YAML before markdown-it sees it and re-emits it as
    // ONE codeBlock with this language. Missing that is what rendered an agent's whole
    // configuration as a grey box of text beneath its own settings form.
    const decos = frontmatterDecorations(doc(code(FRONTMATTER_LANG), para('Body.')));
    expect(decos.find()).toHaveLength(1);
  });

  it('leaves a real code block alone, even at the top of the document', () => {
    expect(frontmatterDecorations(doc(code('ts'), para('Body.'))).find()).toHaveLength(0);
    expect(frontmatterDecorations(doc(code(null), para('Body.'))).find()).toHaveLength(0);
  });

  it('does not hide a sentinel block that is not leading', () => {
    // Only the LEADING block is frontmatter. One further down belongs to the prose.
    const decos = frontmatterDecorations(doc(para('Body.'), code(FRONTMATTER_LANG)));
    expect(decos.find()).toHaveLength(0);
  });

  it('still hides the legacy hr-run, for a Y.Doc persisted before the peeling', () => {
    // hr → paragraph → paragraph → hr, then the body: four nodes hidden, body untouched.
    const decos = frontmatterDecorations(
      doc(hr(), para('name: coaching'), para('model: sonnet'), hr(), para('Body.')),
    );
    expect(decos.find()).toHaveLength(4);
  });

  it('hides NOTHING when the legacy run has no closing rule', () => {
    // Hiding to the end of the document would eat the instructions. A visible block is a
    // far cheaper failure than a document that looks empty.
    const decos = frontmatterDecorations(doc(hr(), para('name: coaching'), para('Body.')));
    expect(decos.find()).toHaveLength(0);
  });

  it('hides nothing in a document with no frontmatter at all', () => {
    expect(frontmatterDecorations(doc(para('Just prose.'))).find()).toHaveLength(0);
    expect(frontmatterDecorations(schema.nodes.doc!.create()).find()).toHaveLength(0);
  });
});