imrishabh18/rp2040-motor-controller
Bottom-side mirrored PCB silkscreen logos rendered as embedded SVG graphics, including via-clearance-aware placement and scaling.
- Version
- 1.0.47
- License
- unset
- Stars
- 5
tests/preview-renderer.test.ts
import { expect, test } from "bun:test";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { patchPreviewRenderer } from "../scripts/patch-preview-renderer";
const bundle = readFileSync(
new URL("../node_modules/@tscircuit/runframe/dist/standalone.min.js", import.meta.url),
"utf8",
);
// Exercise the actual pinned canvas renderer, without executing the browser app.
function declaration(name: string): string {
const start = bundle.indexOf(`function ${name}(`);
if (start < 0) throw new Error(`Missing pinned renderer function ${name}`);
const body = bundle.indexOf("{", start);
let depth = 0;
let quote = "";
for (let i = body; i < bundle.length; i++) {
const c = bundle[i];
if (quote) {
if (c === "\\") i++;
else if (c === quote) quote = "";
continue;
}
if (c === '"' || c === "'" || c === "`") quote = c;
else if (c === "{") depth++;
else if (c === "}" && --depth === 0) return bundle.slice(start, i + 1);
}
throw new Error(`Unterminated pinned renderer function ${name}`);
}
function layerFilter(source: string): (trace: any, layers: Set<string>) => any {
const start = source.indexOf("var OBo=");
const end = source.indexOf(",WBo=", start);
if (start < 0 || end < 0) throw new Error("Missing pinned preview route filter");
return new Function(`return (${source.slice(start + "var OBo=".length, end)})`)();
}
const originalFilter = layerFilter(bundle);
const patchedFilter = layerFilter(patchPreviewRenderer(bundle));
const isTaper = new Function(`return (${declaration("YdI")})`)();
const splitRuns = new Function("YdI", `return (${declaration("L$A")})`)(isTaper);
const getTaperedSegments = new Function("YdI", "bdI", `return (${declaration("K$A")})`)(
isTaper, new Function(`return (${declaration("bdI")})`)(),
);
const traceDrawerFactory = new Function(
"L$A", "VdI", "$gA", "rx", "HdI", "qdI", "K$A", "_dI",
`return (${declaration("H_t")})`,
);
const createTraceDrawer = (...dependencies: any[]) => traceDrawerFactory(
...dependencies, getTaperedSegments, () => { throw new Error("Unexpected tapered route in constant-width fixture"); },
);
type Stroke = { layer: string; a: [number, number]; b: [number, number]; width: number };
function draw(trace: any, layer: string): Stroke[] {
const strokes: Stroke[] = [];
const drawTrace = createTraceDrawer(
splitRuns,
(name: string) => name,
(line: any) => strokes.push({
layer: line.stroke,
a: [line.start.x, line.start.y],
b: [line.end.x, line.end.y],
width: line.strokeWidth,
}),
() => { throw new Error("Unexpected interpolated trace in line fixture"); },
(points: any[]) => points,
() => {},
);
if (trace) drawTrace({ ctx: {}, trace, realToCanvasMat: {}, colorMap: {}, layer });
return strokes;
}
const wire = (x: number, y: number, layer: string, width = 0.15) =>
({ route_type: "wire", x, y, layer, width });
const via = (x: number, y: number) =>
({ route_type: "via", x, y, from_layer: "top", to_layer: "bottom" });
test("preview preserves separated runs when an inner layer is revisited through vias", () => {
const trace = { type: "pcb_trace", pcb_trace_id: "fixture", route: [
wire(0, 0, "inner2"), wire(1, 0, "inner2"), via(1, 0),
wire(1, 0, "bottom"), wire(1, 2, "bottom"), via(1, 2),
wire(1, 2, "inner2"), wire(2, 2, "inner2"),
] };
const layers = new Set(["inner2"]);
const expected: Stroke[] = [
{ layer: "inner2", a: [0, 0], b: [1, 0], width: 0.15 },
{ layer: "inner2", a: [1, 2], b: [2, 2], width: 0.15 },
];
expect(draw(originalFilter(trace, layers), "inner2")).toHaveLength(3);
expect(draw(patchedFilter(trace, layers), "inner2")).toEqual(expected);
});
test("preview keeps layer changes and through-pad markers as run boundaries", () => {
const trace = { type: "pcb_trace", pcb_trace_id: "boundaries", route: [
wire(0, 0, "top"), wire(1, 0, "top"),
wire(1, 0, "inner2"), wire(2, 0, "inner2"),
wire(4, 0, "top"), wire(5, 0, "top"),
{ route_type: "through_pad", start: { x: 5, y: 0 }, end: { x: 5, y: 1 },
width: 0.15, start_layer: "top", end_layer: "top" },
wire(5, 1, "top"), wire(6, 1, "top"),
] };
const visible = patchedFilter(trace, new Set(["top", "inner2"]));
expect(draw(visible, "top")).toEqual([
{ layer: "top", a: [0, 0], b: [1, 0], width: 0.15 },
{ layer: "top", a: [4, 0], b: [5, 0], width: 0.15 },
{ layer: "top", a: [5, 1], b: [6, 1], width: 0.15 },
]);
expect(draw(visible, "inner2")).toEqual([
{ layer: "inner2", a: [1, 0], b: [2, 0], width: 0.15 },
]);
});
test("preview preserves widths, pour flags, interpolation and source geometry without mutation", () => {
const trace = { type: "pcb_trace", pcb_trace_id: "metadata", route_thickness_mode: "interpolated", route: [
{ ...wire(0, 0, "top", 0.3), is_inside_copper_pour: true },
wire(1, 0, "top", 0.7), via(1, 0),
wire(1, 0, "inner2", 0.2), wire(2, 0, "inner2", 0.4),
] };
const before = structuredClone(trace);
const filtered = patchedFilter(trace, new Set(["inner2"]));
expect(filtered).toBe(trace);
expect(filtered.route).toBe(trace.route);
expect(trace).toEqual(before);
const polygons: any[] = [];
const drawInterpolated = createTraceDrawer(
splitRuns,
(layer: string) => layer,
() => { throw new Error("Unexpected constant-width stroke"); },
(polygon: any) => polygons.push(polygon.points),
(points: any[]) => points,
() => {},
);
drawInterpolated({ ctx: {}, trace: filtered, realToCanvasMat: {}, colorMap: {}, layer: "inner2" });
expect(polygons).toEqual([[trace.route[3], trace.route[4]]]);
expect(patchedFilter(trace, new Set(["inner1"]))).toBeNull();
// Retain the via's owning trace on its endpoint layers even without two wires.
expect(patchedFilter({ ...trace, route: [via(1, 0)] }, new Set(["top"]))).not.toBeNull();
});
test("full board selected-layer strokes match complete routes on all four copper layers", () => {
const json = JSON.parse(readFileSync(resolve(
process.env.CIRCUIT_JSON_PATH ?? "dist/index/circuit.json",
), "utf8"));
const traces = json.filter((e: any) => e.type === "pcb_trace");
const before = JSON.stringify(traces);
for (const layer of ["top", "inner1", "inner2", "bottom"]) {
const complete = traces.flatMap((t: any) => draw(t, layer));
const filtered = traces.flatMap((t: any) => draw(patchedFilter(t, new Set([layer])), layer));
expect(complete.length).toBeGreaterThan(0);
expect(filtered).toEqual(complete);
}
expect(JSON.stringify(traces)).toBe(before);
});
test("the screenshot's phantom AVDD diagonal is absent from the patched actual-board drawing", () => {
const json = JSON.parse(readFileSync(resolve(
process.env.CIRCUIT_JSON_PATH ?? "dist/index/circuit.json",
), "utf8"));
const trace = json.find((e: any) => e.type === "pcb_trace" && e.pcb_trace_id === "top_assembly_000");
expect(trace).toBeDefined();
const isPhantom = (s: Stroke) =>
Math.abs(s.a[0] + 1.000103) < 1e-6 && Math.abs(s.a[1] - 5.1) < 1e-6 &&
Math.abs(s.b[0] - 3.799897) < 1e-6 && Math.abs(s.b[1] + 4.05) < 1e-6;
expect(draw(originalFilter(trace, new Set(["inner2"])), "inner2").some(isPhantom)).toBe(true);
expect(draw(patchedFilter(trace, new Set(["inner2"])), "inner2").some(isPhantom)).toBe(false);
});
test("via drill clearing stays restricted to actual runs on the selected layer", () => {
const cleared: [number, number][] = [];
const clearHoles = new Function(
"L$A", "TdI", "ZdI", "Y_t", "Fl", "NR", "ND", "K$A",
`return (${declaration("qdI")})`,
)(
splitRuns,
(x: number, y: number, xx: number, yy: number) => Math.abs(x - xx) <= 1e-6 && Math.abs(y - yy) <= 1e-6,
(shape: any) => JSON.stringify(shape),
() => undefined,
(circle: any) => cleared.push([circle.center.x, circle.center.y]),
() => { throw new Error("Unexpected oval"); },
() => { throw new Error("Unexpected pill"); },
getTaperedSegments,
);
const trace = { type: "pcb_trace", pcb_trace_id: "holes", route: [
wire(0, 0, "top"), wire(1, 0, "top"), via(1, 0),
wire(0, 1, "bottom"), wire(1, 1, "bottom"), via(1, 1),
wire(0, 2, "inner2"), wire(1, 2, "inner2"),
] };
clearHoles({
ctx: { save() {}, restore() {} },
trace: patchedFilter(trace, new Set(["inner2"])),
realToCanvasMat: {}, layer: "inner2", platedHoles: [],
vias: [0, 1, 2].map(y => ({ x: 1, y, hole_diameter: 0.3, layers: ["top", "inner2", "bottom"] })),
});
expect(cleared).toEqual([[1, 2]]);
});