pixalynx/edge-connector
Configures USB-A, Micro-USB, and USB-C PCB-edge connectors with exposed copper contacts and automatically shaped, positioned board tongues.
- Version
- 1.0.0
- License
- GPL-3.0-only
- Stars
- 0
UsbAEdgeConnector.test.mjs
import { expect, test } from "bun:test"
import { jsx } from "react/jsx-runtime"
import { Circuit } from "tscircuit"
import { UsbAEdgeConnector } from "./index.tsx"
import Example from "./index.circuit.tsx"
async function render(element) {
const circuit = new Circuit()
circuit.add(element)
await circuit.renderUntilSettled()
return circuit.getCircuitJson()
}
function padsBySignal(json) {
return Object.fromEntries(json.filter(e => e.type === "pcb_smtpad").map(pad => {
const pcbPort = json.find(e => e.type === "pcb_port" && e.pcb_port_id === pad.pcb_port_id)
const sourcePort = json.find(e => e.type === "source_port" && e.source_port_id === pcbPort.source_port_id)
return [sourcePort.name, pad]
}))
}
test("USB pin mapping, staggered contacts, exposed mask, and no paste", async () => {
const json = await render(jsx("board", {
width: 30, height: 30,
children: jsx(UsbAEdgeConnector, { name: "J1", pcbX: 0, pcbY: 0 }),
}))
const pads = padsBySignal(json)
expect(Object.keys(pads)).toEqual(["VBUS", "DM", "DP", "GND"])
expect(Object.values(pads).map(p => p.x)).toEqual([-3.5, -1, 1, 3.5])
expect(Object.values(pads).map(p => p.y - p.height / 2)).toEqual([-3.75, -3.75, -3.75, -3.75])
expect(pads.VBUS.y + pads.VBUS.height / 2 - pads.DM.y - pads.DM.height / 2).toBe(1)
expect(pads.GND.height).toBe(pads.VBUS.height)
for (const pad of Object.values(pads)) {
expect(pad.layer).toBe("top")
expect(pad.is_covered_with_solder_mask).toBe(false)
expect(pad.soldermask_margin).toBe(0.05)
}
expect(json.filter(e => e.type === "pcb_solder_paste")).toHaveLength(0)
const ports = json.filter(e => e.type === "source_port")
expect(ports.map(p => [p.pin_number, p.name])).toEqual([[1, "VBUS"], [2, "DM"], [3, "DP"], [4, "GND"]])
})
test("placement and 90-degree rotation preserve signal-to-pad mapping", async () => {
const json = await render(jsx("board", {
width: 40, height: 40,
children: jsx(UsbAEdgeConnector, { name: "J2", pcbX: 5, pcbY: 3, pcbRotation: 90 }),
}))
const pads = padsBySignal(json)
for (const [signal, x, y] of [["VBUS", 5, -0.5], ["DM", 5.5, 2], ["DP", 5.5, 4], ["GND", 5, 6.5]]) {
expect(pads[signal].x).toBeCloseTo(x)
expect(pads[signal].y).toBeCloseTo(y)
}
expect(json.filter(e => e.type === "pcb_solder_paste")).toHaveLength(0)
})
test("example puts all four contacts inside the 2 mm PCB tongue", async () => {
const json = await render(jsx(Example, {}))
const board = json.find(e => e.type === "pcb_board")
expect(board.thickness).toBe(2)
const tip = Math.max(...board.outline.map(p => p.y))
for (const pad of Object.values(padsBySignal(json))) {
expect(Math.abs(pad.x) + pad.width / 2).toBeLessThan(6)
expect(tip - pad.y - pad.height / 2).toBeGreaterThanOrEqual(1)
expect(pad.y - pad.height / 2).toBeGreaterThan(tip - 8.7)
}
expect(json.filter(e => /error$/.test(e.type))).toEqual([])
})