- .archify content is YAML (JSON still accepted); converted to JSON for the renderer - Archify Diagram custom editor is the default for *.archify; Show Source opens the YAML beside it - YAML syntax errors and validation problems mapped to YAML lines - yamlValidation for schema completion with redhat.vscode-yaml - scripts/to-yaml.mjs converts existing .archify files
88 lines
4.7 KiB
TypeScript
88 lines
4.7 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import { test } from 'node:test';
|
|
import { hasSourceEvidence, isArchifyHtml, readDiagramSource, stripSourceEvidence, typeFromFilename } from '../src/detect';
|
|
import { pointerSegments, rangeForPointer, rangeForPointerYaml, yamlSyntaxProblems } from '../src/jsonPointer';
|
|
|
|
test('reads diagram_type from content', () => {
|
|
const source = readDiagramSource('{"schema_version":1,"diagram_type":"sequence","meta":{}}', 'plain.json');
|
|
assert.equal(source?.type, 'sequence');
|
|
});
|
|
|
|
test('falls back to the file name for unparseable sources', () => {
|
|
assert.equal(readDiagramSource('{"diagram_type": ', 'x.workflow.json')?.type, 'workflow');
|
|
assert.equal(readDiagramSource('{"name":"pkg"}', 'package.json'), undefined);
|
|
assert.equal(typeFromFilename('/a/b/Web.Architecture.json'), 'architecture');
|
|
});
|
|
|
|
test('recognizes Archify HTML by its generator meta', () => {
|
|
assert.ok(isArchifyHtml('<html><head><meta name="generator" content="archify 3.0.1"></head></html>'));
|
|
assert.ok(!isArchifyHtml('<html><head><meta name="generator" content="hugo"></head></html>'));
|
|
});
|
|
|
|
test('strips source evidence without touching the original', () => {
|
|
const diagram = {
|
|
meta: { title: 't', repository: { url: 'https://github.com/a/b', revision: 'x' } },
|
|
components: [{ id: 'a', sources: [{ path: 'src/a.ts' }] }, { id: 'b' }],
|
|
};
|
|
assert.ok(hasSourceEvidence('architecture', diagram));
|
|
const stripped = stripSourceEvidence('architecture', diagram);
|
|
assert.ok(!hasSourceEvidence('architecture', stripped));
|
|
assert.ok(diagram.meta.repository, 'original keeps its repository');
|
|
assert.deepEqual((stripped.components as unknown[])[1], { id: 'b' });
|
|
});
|
|
|
|
test('json pointer segments decode escapes and indexes', () => {
|
|
assert.deepEqual(pointerSegments('/components/0/a~1b~0c'), ['components', 0, 'a/b~c']);
|
|
assert.deepEqual(pointerSegments(''), []);
|
|
});
|
|
|
|
test('json pointer ranges point at keys for containers and values for leaves', () => {
|
|
const text = '{\n "meta": { "title": "x" },\n "components": [ { "id": "a" } ]\n}';
|
|
const meta = rangeForPointer(text, '/meta');
|
|
assert.equal(text.slice(meta.start, meta.end), '"meta"');
|
|
const title = rangeForPointer(text, '/meta/title');
|
|
assert.equal(text.slice(title.start, title.end), '"x"');
|
|
const item = rangeForPointer(text, '/components/0');
|
|
assert.equal(text.slice(item.start, item.end), '{');
|
|
const missing = rangeForPointer(text, '/components/0/label');
|
|
assert.equal(text.slice(missing.start, missing.end), '{', 'falls back to the nearest existing ancestor');
|
|
});
|
|
|
|
test('.archify files are diagram sources typed by their content', async () => {
|
|
const { diagramBaseName, isArchifyFile, isDiagramFileName } = await import('../src/detect');
|
|
assert.ok(isArchifyFile('/w/My Platform.archify'));
|
|
assert.ok(isDiagramFileName('/w/x.ARCHIFY'));
|
|
assert.ok(isDiagramFileName('/w/x.workflow.json'));
|
|
assert.ok(!isDiagramFileName('/w/archify.json'));
|
|
assert.equal(diagramBaseName('/w/web.archify'), 'web');
|
|
assert.equal(diagramBaseName('/w/web.architecture.json'), 'web.architecture');
|
|
assert.equal(readDiagramSource('{"diagram_type":"lifecycle"}', 'run.archify')?.type, 'lifecycle');
|
|
assert.equal(readDiagramSource('{"title":"no type yet"}', 'run.archify'), undefined);
|
|
const yaml = readDiagramSource('schema_version: 1\ndiagram_type: sequence\nmeta:\n title: T\n', 'flow.archify');
|
|
assert.equal(yaml?.type, 'sequence');
|
|
assert.equal(yaml?.format, 'yaml');
|
|
assert.deepEqual(JSON.parse(yaml!.json), { schema_version: 1, diagram_type: 'sequence', meta: { title: 'T' } });
|
|
assert.equal(readDiagramSource('diagram_type: [unclosed', 'bad.archify'), undefined);
|
|
});
|
|
|
|
test('yaml pointer ranges match the json behaviour', () => {
|
|
const text = 'meta:\n title: x\ncomponents:\n - id: a\n label: A\n';
|
|
const meta = rangeForPointerYaml(text, '/meta');
|
|
assert.equal(text.slice(meta.start, meta.end), 'meta');
|
|
const title = rangeForPointerYaml(text, '/meta/title');
|
|
assert.equal(text.slice(title.start, title.end), 'x');
|
|
const item = rangeForPointerYaml(text, '/components/0');
|
|
assert.equal(text.slice(item.start, item.end), 'i', 'first character of the item');
|
|
const label = rangeForPointerYaml(text, '/components/0/label');
|
|
assert.equal(text.slice(label.start, label.end), 'A');
|
|
const missing = rangeForPointerYaml(text, '/components/0/type');
|
|
assert.equal(text.slice(missing.start, missing.end), 'i', 'falls back to the nearest existing ancestor');
|
|
});
|
|
|
|
test('yaml syntax problems carry offsets', () => {
|
|
assert.deepEqual(yamlSyntaxProblems('a: 1\nb: 2\n'), []);
|
|
const problems = yamlSyntaxProblems('a: [1, 2\nb: 3\n');
|
|
assert.ok(problems.length > 0);
|
|
assert.ok(problems[0].start >= 0 && problems[0].end > problems[0].start);
|
|
});
|