AnasSarkiz/magnetic-shutter-remote-r8
A USB‑C rechargeable battery-powered ESP32‑C3 wireless controller with Li‑ion charging, protected 3.3‑V buck‑boost regulation, thermal/safety monitoring, status LEDs, buttons, programming UART, crystal clock, and 2.4‑GHz antenna matching network.
- Version
- 0.4.0-prototype
- License
- unset
- Stars
- 0
tests/r8-style-vias.test.ts
import { expect, test } from "bun:test";
import { any_circuit_element } from "circuit-json";
import { z } from "zod";
const records = await Bun.file("dist/index/circuit.json").json();
const circuit = any_circuit_element.array().parse(records);
const rawRoutes = z
.array(
z.object({
type: z.string(),
route: z
.array(
z.object({
route_type: z.string(),
via_diameter: z.number().optional(),
via_hole_diameter: z.number().optional(),
}),
)
.optional(),
}),
)
.parse(
z
.array(z.object({ type: z.string() }).passthrough())
.parse(records)
.filter((record) => record.type === "pcb_trace"),
);
test("R8 has only outer copper and 0.30/0.45 mm through vias", () => {
const board = circuit.find((element) => element.type === "pcb_board");
if (!board || board.type !== "pcb_board") throw new Error("Missing board");
expect(board.num_layers).toBe(2);
const vias = circuit.filter((element) => element.type === "pcb_via");
expect(vias.length).toBeGreaterThan(0);
for (const via of vias) {
expect(via.hole_diameter).toBeCloseTo(0.3, 8);
expect(via.outer_diameter).toBeCloseTo(0.45, 8);
expect([...via.layers].sort()).toEqual(["bottom", "top"]);
}
const traces = circuit.filter((element) => element.type === "pcb_trace");
expect(traces.length).toBeGreaterThan(0);
for (const trace of traces) {
for (const point of trace.route) {
if (point.route_type === "wire")
expect(["top", "bottom"]).toContain(point.layer);
if (point.route_type === "via") {
expect(
vias.some(
(via) =>
Math.abs(via.x - point.x) < 1e-8 &&
Math.abs(via.y - point.y) < 1e-8,
),
).toBe(true);
expect([point.from_layer, point.to_layer].sort()).toEqual([
"bottom",
"top",
]);
}
}
}
for (const trace of rawRoutes.filter(
(element) => element.type === "pcb_trace",
)) {
for (const point of trace.route ?? []) {
if (point.route_type === "via") {
if (point.via_hole_diameter !== undefined)
expect(point.via_hole_diameter).toBeCloseTo(0.3, 8);
if (point.via_diameter !== undefined)
expect(point.via_diameter).toBeCloseTo(0.45, 8);
}
}
}
});
test("native USB-C symbol preserves the qualified connector's physical ports", () => {
const usb = circuit.find(
(element) => element.type === "source_component" && element.name === "J1",
);
if (
!usb ||
usb.type !== "source_component" ||
usb.ftype !== "simple_connector"
)
throw new Error("Missing J1");
expect(usb.standard).toBe("usb_c");
const ports = circuit
.filter((element) => element.type === "source_port")
.filter(
(element) => element.source_component_id === usb.source_component_id,
);
expect(
ports.map((port) => port.pin_number).sort((a, b) => (a ?? 0) - (b ?? 0)),
).toEqual(Array.from({ length: 16 }, (_, index) => index + 13));
for (const port of ports) {
expect(
circuit.some(
(element) =>
element.type === "pcb_port" &&
element.source_port_id === port.source_port_id,
),
).toBe(true);
}
const symbol = circuit.find(
(element) =>
element.type === "schematic_component" &&
element.source_component_id === usb.source_component_id,
);
if (!symbol || symbol.type !== "schematic_component")
throw new Error("Missing USB schematic");
expect(
circuit.filter(
(element) =>
element.type === "schematic_path" &&
element.schematic_component_id === symbol.schematic_component_id,
).length,
).toBeGreaterThan(0);
});