94 lines
3.2 KiB
JavaScript
94 lines
3.2 KiB
JavaScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { validateModel } from "../src/validate.js";
|
|
|
|
test("validate normalizes dense symbol pin spacing and body size deterministically", () => {
|
|
const model = {
|
|
meta: { title: "Dense symbol test" },
|
|
symbols: {
|
|
dense: {
|
|
symbol_id: "dense",
|
|
category: "generic",
|
|
body: { width: 80, height: 40 },
|
|
pins: [
|
|
{ name: "A", number: "1", side: "left", offset: 4, type: "input" },
|
|
{ name: "B", number: "2", side: "left", offset: 6, type: "input" },
|
|
{ name: "Y", number: "3", side: "right", offset: 5, type: "output" },
|
|
{ name: "Z", number: "4", side: "right", offset: 7, type: "output" }
|
|
]
|
|
}
|
|
},
|
|
instances: [{ ref: "U1", symbol: "dense", placement: { x: 100, y: 100, rotation: 0, locked: false } }],
|
|
nets: [
|
|
{
|
|
name: "N1",
|
|
class: "signal",
|
|
nodes: [
|
|
{ ref: "U1", pin: "A" },
|
|
{ ref: "U1", pin: "Y" }
|
|
]
|
|
},
|
|
{
|
|
name: "N2",
|
|
class: "signal",
|
|
nodes: [
|
|
{ ref: "U1", pin: "B" },
|
|
{ ref: "U1", pin: "Z" }
|
|
]
|
|
}
|
|
]
|
|
};
|
|
|
|
const first = validateModel(model);
|
|
assert.ok(first.model);
|
|
const dense = first.model.symbols.dense;
|
|
assert.ok(dense.body.width >= 96);
|
|
assert.ok(dense.body.height >= 64);
|
|
|
|
const leftPins = dense.pins.filter((pin) => pin.side === "left");
|
|
const rightPins = dense.pins.filter((pin) => pin.side === "right");
|
|
assert.ok(leftPins[1].offset - leftPins[0].offset >= 18);
|
|
assert.ok(rightPins[1].offset - rightPins[0].offset >= 18);
|
|
|
|
assert.ok(first.issues.some((issue) => issue.code === "symbol_geometry_adjusted"));
|
|
|
|
const second = validateModel(first.model);
|
|
assert.ok(second.model);
|
|
assert.deepEqual(second.model.symbols.dense, first.model.symbols.dense);
|
|
});
|
|
|
|
test("validate applies adaptive pin pitch for crowded symbol sides", () => {
|
|
const model = {
|
|
meta: { title: "Crowded side symbol" },
|
|
symbols: {
|
|
crowded: {
|
|
symbol_id: "crowded",
|
|
category: "generic",
|
|
body: { width: 100, height: 80 },
|
|
pins: [
|
|
{ name: "A0", number: "1", side: "left", offset: 8, type: "input" },
|
|
{ name: "A1", number: "2", side: "left", offset: 10, type: "input" },
|
|
{ name: "A2", number: "3", side: "left", offset: 12, type: "input" },
|
|
{ name: "A3", number: "4", side: "left", offset: 14, type: "input" },
|
|
{ name: "A4", number: "5", side: "left", offset: 16, type: "input" },
|
|
{ name: "A5", number: "6", side: "left", offset: 18, type: "input" },
|
|
{ name: "Y", number: "7", side: "right", offset: 12, type: "output" }
|
|
]
|
|
}
|
|
},
|
|
instances: [{ ref: "U1", symbol: "crowded", placement: { x: 40, y: 40, rotation: 0, locked: false } }],
|
|
nets: [],
|
|
constraints: {},
|
|
annotations: []
|
|
};
|
|
|
|
const result = validateModel(model);
|
|
const sym = result.model?.symbols?.crowded;
|
|
assert.ok(sym);
|
|
const left = sym.pins.filter((pin) => pin.side === "left");
|
|
assert.ok(left[1].offset - left[0].offset >= 22);
|
|
assert.ok(sym.body.width >= 96);
|
|
assert.ok(sym.body.height >= 180);
|
|
assert.ok(result.issues.some((issue) => issue.code === "symbol_geometry_adjusted"));
|
|
});
|