ktg-plugin-marketplace/plugins/voyage/tests/lib/frontmatter.test.mjs
Kjell Tore Guttormsen 7a90d348ad feat(voyage)!: marketplace handoff — rename plugins/ultraplan-local to plugins/voyage [skip-docs]
Session 5 of voyage-rebrand (V6). Operator-authorized cross-plugin scope.

- git mv plugins/ultraplan-local plugins/voyage (rename detected, history preserved)
- .claude-plugin/marketplace.json: voyage entry replaces ultraplan-local
- CLAUDE.md: voyage row in plugin list, voyage in design-system consumer list
- README.md: bulk rename ultra*-local commands -> trek* commands; ultraplan-local refs -> voyage; type discriminators (type: trekbrief/trekreview); session-title pattern (voyage:<command>:<slug>); v4.0.0 release-note paragraph
- plugins/voyage/.claude-plugin/plugin.json: homepage/repository URLs point to monorepo voyage path
- plugins/voyage/verify.sh: drop URL whitelist exception (no longer needed)

Closes voyage-rebrand. bash plugins/voyage/verify.sh PASS 7/7. npm test 361/361.
2026-05-05 15:37:52 +02:00

74 lines
2.7 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { test } from 'node:test';
import { strict as assert } from 'node:assert';
import { splitFrontmatter, parseFrontmatter, parseDocument } from '../../lib/util/frontmatter.mjs';
test('splitFrontmatter — basic LF', () => {
const r = splitFrontmatter('---\nfoo: bar\n---\nbody here\n');
assert.equal(r.hasFrontmatter, true);
assert.equal(r.frontmatter, 'foo: bar');
assert.equal(r.body, 'body here\n');
});
test('splitFrontmatter — CRLF tolerated', () => {
const r = splitFrontmatter('---\r\nfoo: bar\r\n---\r\nbody\r\n');
assert.equal(r.hasFrontmatter, true);
assert.equal(r.frontmatter, 'foo: bar');
});
test('splitFrontmatter — BOM stripped', () => {
const r = splitFrontmatter('---\nfoo: bar\n---\n');
assert.equal(r.hasFrontmatter, true);
});
test('splitFrontmatter — no frontmatter', () => {
const r = splitFrontmatter('# title\nbody only\n');
assert.equal(r.hasFrontmatter, false);
assert.match(r.body, /title/);
});
test('parseFrontmatter — string scalars', () => {
const r = parseFrontmatter('type: trekbrief\nslug: jwt-auth\n');
assert.equal(r.valid, true);
assert.equal(r.parsed.type, 'trekbrief');
assert.equal(r.parsed.slug, 'jwt-auth');
});
test('parseFrontmatter — number, bool, null', () => {
const r = parseFrontmatter('research_topics: 3\nautoResearch: true\nfoo: false\nbar: null\n');
assert.equal(r.parsed.research_topics, 3);
assert.equal(r.parsed.autoResearch, true);
assert.equal(r.parsed.foo, false);
assert.equal(r.parsed.bar, null);
});
test('parseFrontmatter — quoted strings', () => {
const r = parseFrontmatter('plan_version: "1.7"\nname: \'test thing\'\n');
assert.equal(r.parsed.plan_version, '1.7');
assert.equal(r.parsed.name, 'test thing');
});
test('parseFrontmatter — list of scalars', () => {
const r = parseFrontmatter('keywords:\n - planning\n - research\n - agents\n');
assert.equal(r.valid, true);
assert.deepEqual(r.parsed.keywords, ['planning', 'research', 'agents']);
});
test('parseFrontmatter — rejects nested dict', () => {
const r = parseFrontmatter('a: 1\n b: 2\n');
assert.equal(r.valid, false);
assert.ok(r.errors.find(e => e.code === 'FM_INDENT'));
});
test('parseDocument — full pipeline', () => {
const text = '---\ntype: trekbrief\nresearch_topics: 2\n---\n\n# Body\n\ncontent\n';
const r = parseDocument(text);
assert.equal(r.valid, true);
assert.equal(r.parsed.frontmatter.type, 'trekbrief');
assert.match(r.parsed.body, /content/);
});
test('parseDocument — missing frontmatter is an error', () => {
const r = parseDocument('# just markdown\nno frontmatter here\n');
assert.equal(r.valid, false);
assert.ok(r.errors.find(e => e.code === 'FM_MISSING'));
});