Files
mdg-filius/packages/doc/test/view.test.ts
T
julian.kiedaischandClaude Opus 5.5 63273916b5 feat(editor): F4.3 the editor's frame and surface; a switch's cloud read and written
packages/editor (React 18, Vite) draws a document as Java FILIUS does: Java's
default hardware icons, the device button of JSidebarButton, cables as
JCablePanel's quadratic curve between the buttons' middles, wireless cables
dashed, documentation items below. The surface moves with mouse and finger
(the pointer captured only once it moved) and zooms with Ctrl and the
wheel, a trackpad pinch, two fingers and the zoom bar; the first view shows
all. German and English catalogs with Java's device names, the dashboard's
colour tokens, the bridge with its origin check. packages/doc gets the
drawing's light view of a document.

Java's Switch.cloud (the Internet in the examples) was lost on reading; it
is now read, kept in the model and written, with FlsOracle and the corpus,
written and exported checks renewed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 09:05:25 +00:00

73 lines
4.0 KiB
TypeScript

// The drawing of a document against the project it holds, for every file of
// the corpus: the same devices in the same order at the same places, Java's
// labels, the cables as the export draws them (wireless or not), the
// documentation items in the model's render order.
import { readdirSync, readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { describe, expect, it } from 'vitest';
import * as Y from 'yjs';
import { stableGeneratedMacAddress } from '@mdg-filius/core';
import { exportProject, openProjectArchive, type ImportedProject } from '@mdg-filius/fls';
import { readProject, topologyView, writeProject } from '../src/index.js';
const corpus = join(dirname(fileURLToPath(import.meta.url)), '../../../corpus');
const files = ['java-examples', 'java-tests', 'ipad-fixtures'].flatMap((folder) =>
readdirSync(join(corpus, folder))
.filter((name) => name.endsWith('.fls'))
.map((name) => join(folder, name)),
);
function docOf(file: string, change: (project: ImportedProject) => void = () => {}): Y.Doc {
let counter = 0;
const project = openProjectArchive(new Uint8Array(readFileSync(join(corpus, file))), () => `00000000-0000-0000-0000-${(0xffff_ffff - ++counter).toString(16).padStart(12, '0')}`);
change(project);
const doc = new Y.Doc();
writeProject(doc, project);
return doc;
}
describe('the drawing of a document', () => {
for (const file of files) {
it(file, () => {
const doc = docOf(file);
const project = readProject(doc);
const view = topologyView(doc);
expect(view.nodes.map((node) => [node.id, node.kind, node.name, node.x, node.y])).toEqual(
project.graph.nodes.map((node) => [node.id, node.kind, node.displayName, node.position.x, node.position.y]),
);
expect(view.nodes.map((node) => node.ports)).toEqual(project.graph.nodes.map((node) => node.ports.map((port) => ({ id: port.id, label: port.label }))));
expect(view.links.map((link) => [link.id, link.sourceNode, link.sourcePort, link.targetNode, link.targetPort])).toEqual(
project.graph.links.map((link) => [link.id, link.sourceNodeId, link.sourcePortId, link.targetNodeId, link.targetPortId]),
);
expect(view.links.map((link) => link.wireless)).toEqual(exportProject(project).topology.links.map((link) => link.wireless));
expect(view.docs.map(({ id, kind, x, y, width, height, text, color, font, size, bold, order }) => ({ id, kind, frame: { x, y, width, height }, text, color, fontName: font, fontSize: size, isBold: bold, order }))).toEqual(project.documentationItems);
});
}
it('draws the Internet of the NAT example as a cloud', () => {
const view = topologyView(docOf('java-examples/nat.fls'));
expect(view.nodes.filter((node) => node.cloud).map((node) => node.name)).toEqual(['Internet']);
});
it("writes a host's label as Java does: its name, address, MAC address or both", () => {
const labels = (policy: 'manual' | 'ipAddress' | 'macAddress' | 'ipAndMAC') => {
const doc = docOf('java-examples/zwei_rechnernetze_komplett.fls', (project) => {
for (const node of project.graph.nodes) node.hostLabelPolicy = policy;
});
const project = readProject(doc);
const notebook = project.graph.nodes.find((node) => node.displayName === 'Notebook 1.10')!;
const view = topologyView(doc);
return { label: view.nodes.find((node) => node.id === notebook.id)!.label, mac: notebook.ports[0]!.importedMacAddress ?? stableGeneratedMacAddress(notebook.ports[0]!.id), switchLabel: view.nodes.find((node) => node.kind === 'networkSwitch')!.label };
};
expect(labels('manual').label).toBe('Notebook 1.10');
expect(labels('ipAddress').label).toBe('141.99.1.10');
const { label, mac, switchLabel } = labels('ipAndMAC');
expect(label).toBe(`141.99.1.10 (${mac})`);
expect(labels('macAddress').label).toBe(mac);
// Only hosts show an address (Host.holeAnzeigeName).
expect(switchLabel).toBe('Switch 1');
});
});