ktg-plugin-marketplace/plugins/config-audit/tests/lib/yaml-parser.test.mjs

147 lines
5 KiB
JavaScript

import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { parseFrontmatter, parseSimpleYaml, parseJson, findImports, extractSections } from '../../scanners/lib/yaml-parser.mjs';
describe('parseFrontmatter', () => {
it('parses standard frontmatter', () => {
const content = '---\nname: test\nmodel: opus\n---\n\nBody here';
const { frontmatter, body } = parseFrontmatter(content);
assert.deepStrictEqual(frontmatter, { name: 'test', model: 'opus' });
assert.ok(body.includes('Body here'));
});
it('returns null frontmatter when none exists', () => {
const { frontmatter, body } = parseFrontmatter('Just body text');
assert.strictEqual(frontmatter, null);
assert.strictEqual(body, 'Just body text');
});
it('handles empty frontmatter', () => {
const { frontmatter } = parseFrontmatter('---\n---\nBody');
assert.deepStrictEqual(frontmatter, {});
});
it('calculates bodyStartLine correctly', () => {
const content = '---\na: 1\nb: 2\n---\nBody';
const { bodyStartLine } = parseFrontmatter(content);
assert.strictEqual(bodyStartLine, 5);
});
});
describe('parseSimpleYaml', () => {
it('parses key-value pairs', () => {
const result = parseSimpleYaml('name: test\nmodel: opus');
assert.strictEqual(result.name, 'test');
assert.strictEqual(result.model, 'opus');
});
it('parses boolean values', () => {
const result = parseSimpleYaml('enabled: true\ndisabled: false');
assert.strictEqual(result.enabled, true);
assert.strictEqual(result.disabled, false);
});
it('parses numeric values', () => {
const result = parseSimpleYaml('count: 42\nrate: 3.14');
assert.strictEqual(result.count, 42);
assert.strictEqual(result.rate, 3.14);
});
it('parses inline arrays', () => {
const result = parseSimpleYaml('tools: [Read, Write, Bash]');
assert.deepStrictEqual(result.tools, ['Read', 'Write', 'Bash']);
});
it('strips quotes from values', () => {
const result = parseSimpleYaml('name: "quoted value"');
assert.strictEqual(result.name, 'quoted value');
});
it('normalizes hyphens to underscores in keys', () => {
const result = parseSimpleYaml('allowed-tools: Read');
assert.ok('allowed_tools' in result);
});
it('normalizes comma-separated strings in list fields', () => {
const result = parseSimpleYaml('allowed-tools: Read, Write, Bash');
assert.deepStrictEqual(result.allowed_tools, ['Read', 'Write', 'Bash']);
});
it('handles null values', () => {
const result = parseSimpleYaml('value: null\ntilde: ~\nempty:');
assert.strictEqual(result.value, null);
assert.strictEqual(result.tilde, null);
assert.strictEqual(result.empty, null);
});
it('skips comments', () => {
const result = parseSimpleYaml('# comment\nname: test\n# another');
assert.strictEqual(result.name, 'test');
assert.strictEqual(Object.keys(result).length, 1);
});
it('handles multi-line pipe values', () => {
const result = parseSimpleYaml('description: |\n Line 1\n Line 2\nname: test');
assert.ok(result.description.includes('Line 1'));
assert.ok(result.description.includes('Line 2'));
assert.strictEqual(result.name, 'test');
});
});
describe('parseJson', () => {
it('parses valid JSON', () => {
const result = parseJson('{"key": "value"}');
assert.deepStrictEqual(result, { key: 'value' });
});
it('returns null for invalid JSON', () => {
assert.strictEqual(parseJson('{invalid}'), null);
});
it('returns null for empty string', () => {
assert.strictEqual(parseJson(''), null);
});
});
describe('findImports', () => {
it('finds @import lines', () => {
const content = '# Title\n@path/to/file.md\nSome text\n@another/file.md';
const imports = findImports(content);
assert.strictEqual(imports.length, 2);
assert.strictEqual(imports[0].path, 'path/to/file.md');
assert.strictEqual(imports[0].line, 2);
assert.strictEqual(imports[1].path, 'another/file.md');
assert.strictEqual(imports[1].line, 4);
});
it('returns empty array when no imports', () => {
assert.deepStrictEqual(findImports('Just text'), []);
});
it('ignores @ in the middle of lines', () => {
const imports = findImports('Email me at user@example.com');
assert.strictEqual(imports.length, 0);
});
});
describe('extractSections', () => {
it('extracts markdown headings', () => {
const content = '# Title\n## Section 1\nText\n### Sub-section\n## Section 2';
const sections = extractSections(content);
assert.strictEqual(sections.length, 4);
assert.strictEqual(sections[0].heading, 'Title');
assert.strictEqual(sections[0].level, 1);
assert.strictEqual(sections[1].heading, 'Section 1');
assert.strictEqual(sections[1].level, 2);
});
it('returns empty for no headings', () => {
assert.deepStrictEqual(extractSections('Just plain text'), []);
});
it('includes line numbers', () => {
const content = 'line1\n## Heading\nline3';
const sections = extractSections(content);
assert.strictEqual(sections[0].line, 2);
});
});