From 8fedc0a786a78bb5edb2051edcf0ad9ea08fec7f Mon Sep 17 00:00:00 2001 From: Claw Explorer Date: Sat, 28 Mar 2026 15:07:36 -0400 Subject: [PATCH 1/2] fix: parse imperial/metric sizes for led and diode string footprints The string parser only recognized 'res' and 'cap' as passive footprints that use imperial/metric sizing (e.g., res0402, cap0603). The 'led' and 'diode' footprints also use the passive() function but were incorrectly parsed as having num_pins instead of an imperial size code. For example, 'led0402' was parsed as { fn: 'led', num_pins: 402 } instead of { fn: 'led', imperial: '0402' }, causing a runtime error: 'Could not determine required pad dimensions (p, pw, ph)'. Fix: extend the passive footprint check in the string parser proxy to include 'led' and 'diode' alongside 'res' and 'cap'. Tests: added 11 new tests covering led and diode string parsing with imperial sizes, metric sizes, THT variant, and builder API parity. --- src/footprinter.ts | 9 ++- tests/__snapshots__/diode0402_string.snap.svg | 1 + tests/__snapshots__/diode0805_string.snap.svg | 1 + tests/__snapshots__/diode1206_string.snap.svg | 1 + tests/__snapshots__/led0402_string.snap.svg | 1 + tests/__snapshots__/led0805_string.snap.svg | 1 + tests/__snapshots__/led1206_string.snap.svg | 1 + tests/diode-string-parsing.test.ts | 70 +++++++++++++++++++ tests/led-string-parsing.test.ts | 67 ++++++++++++++++++ 9 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 tests/__snapshots__/diode0402_string.snap.svg create mode 100644 tests/__snapshots__/diode0805_string.snap.svg create mode 100644 tests/__snapshots__/diode1206_string.snap.svg create mode 100644 tests/__snapshots__/led0402_string.snap.svg create mode 100644 tests/__snapshots__/led0805_string.snap.svg create mode 100644 tests/__snapshots__/led1206_string.snap.svg create mode 100644 tests/diode-string-parsing.test.ts create mode 100644 tests/led-string-parsing.test.ts diff --git a/src/footprinter.ts b/src/footprinter.ts index 09c1cd8a..e6096d11 100644 --- a/src/footprinter.ts +++ b/src/footprinter.ts @@ -405,12 +405,17 @@ export const footprinter = (): Footprinter & { } else { target[prop] = true target.fn = prop - if (prop === "res" || prop === "cap") { + if ( + prop === "res" || + prop === "cap" || + prop === "led" || + prop === "diode" + ) { if (v) { if (typeof v === "string" && v.includes("_metric")) { target.metric = v.split("_metric")[0] } else { - target.imperial = v // e.g., res0402, cap0603 etc. + target.imperial = v // e.g., res0402, cap0603, led0805 etc. } } } else { diff --git a/tests/__snapshots__/diode0402_string.snap.svg b/tests/__snapshots__/diode0402_string.snap.svg new file mode 100644 index 00000000..8d67bac1 --- /dev/null +++ b/tests/__snapshots__/diode0402_string.snap.svg @@ -0,0 +1 @@ +{REF} \ No newline at end of file diff --git a/tests/__snapshots__/diode0805_string.snap.svg b/tests/__snapshots__/diode0805_string.snap.svg new file mode 100644 index 00000000..ff53e38d --- /dev/null +++ b/tests/__snapshots__/diode0805_string.snap.svg @@ -0,0 +1 @@ +{REF} \ No newline at end of file diff --git a/tests/__snapshots__/diode1206_string.snap.svg b/tests/__snapshots__/diode1206_string.snap.svg new file mode 100644 index 00000000..a4a85de7 --- /dev/null +++ b/tests/__snapshots__/diode1206_string.snap.svg @@ -0,0 +1 @@ +{REF} \ No newline at end of file diff --git a/tests/__snapshots__/led0402_string.snap.svg b/tests/__snapshots__/led0402_string.snap.svg new file mode 100644 index 00000000..8d67bac1 --- /dev/null +++ b/tests/__snapshots__/led0402_string.snap.svg @@ -0,0 +1 @@ +{REF} \ No newline at end of file diff --git a/tests/__snapshots__/led0805_string.snap.svg b/tests/__snapshots__/led0805_string.snap.svg new file mode 100644 index 00000000..ff53e38d --- /dev/null +++ b/tests/__snapshots__/led0805_string.snap.svg @@ -0,0 +1 @@ +{REF} \ No newline at end of file diff --git a/tests/__snapshots__/led1206_string.snap.svg b/tests/__snapshots__/led1206_string.snap.svg new file mode 100644 index 00000000..a4a85de7 --- /dev/null +++ b/tests/__snapshots__/led1206_string.snap.svg @@ -0,0 +1 @@ +{REF} \ No newline at end of file diff --git a/tests/diode-string-parsing.test.ts b/tests/diode-string-parsing.test.ts new file mode 100644 index 00000000..5b4b299f --- /dev/null +++ b/tests/diode-string-parsing.test.ts @@ -0,0 +1,70 @@ +import { expect, test } from "bun:test" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" +import { fp } from "../src/footprinter" + +test("diode0402 string produces 2 SMT pads with correct imperial size", () => { + const soup = fp.string("diode0402").circuitJson() + const pads = soup.filter((e: any) => e.type === "pcb_smtpad") + expect(pads).toHaveLength(2) + + // 0402: pw=0.54mm, ph=0.64mm, p=1.02mm + const pad1 = pads.find((p: any) => p.port_hints?.includes("1")) + expect(pad1).toBeDefined() + expect(pad1!.width).toBeCloseTo(0.54, 1) + expect(pad1!.height).toBeCloseTo(0.64, 1) + + const svgContent = convertCircuitJsonToPcbSvg(soup) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "diode0402_string") +}) + +test("diode0805 string produces 2 SMT pads with correct imperial size", () => { + const soup = fp.string("diode0805").circuitJson() + const pads = soup.filter((e: any) => e.type === "pcb_smtpad") + expect(pads).toHaveLength(2) + + // 0805: pw=1.025mm, ph=1.4mm + const pad1 = pads.find((p: any) => p.port_hints?.includes("1")) + expect(pad1!.width).toBeCloseTo(1.025, 2) + expect(pad1!.height).toBeCloseTo(1.4, 1) + + const svgContent = convertCircuitJsonToPcbSvg(soup) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "diode0805_string") +}) + +test("diode1206 string produces 2 SMT pads", () => { + const soup = fp.string("diode1206").circuitJson() + const pads = soup.filter((e: any) => e.type === "pcb_smtpad") + expect(pads).toHaveLength(2) + + const svgContent = convertCircuitJsonToPcbSvg(soup) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "diode1206_string") +}) + +test("diode string matches diode builder API output", () => { + const fromString = fp.string("diode0603").circuitJson() + const fromBuilder = fp().diode().imperial("0603").circuitJson() + + const stringPads = fromString.filter((e: any) => e.type === "pcb_smtpad") + const builderPads = fromBuilder.filter((e: any) => e.type === "pcb_smtpad") + + expect(stringPads).toHaveLength(builderPads.length) + + for (let i = 0; i < stringPads.length; i++) { + expect(stringPads[i].x).toBeCloseTo(builderPads[i].x, 5) + expect(stringPads[i].y).toBeCloseTo(builderPads[i].y, 5) + expect(stringPads[i].width).toBeCloseTo(builderPads[i].width, 5) + expect(stringPads[i].height).toBeCloseTo(builderPads[i].height, 5) + } +}) + +test("diode0402_metric string uses metric lookup", () => { + const params = fp.string("diode1005_metric").params() + expect(params.metric).toBe("1005") + expect(params.fn).toBe("diode") +}) + +test("diode0603_tht string produces through-hole pads", () => { + const soup = fp.string("diode0603_tht").circuitJson() + const holes = soup.filter((e: any) => e.type === "pcb_plated_hole") + expect(holes).toHaveLength(2) +}) diff --git a/tests/led-string-parsing.test.ts b/tests/led-string-parsing.test.ts new file mode 100644 index 00000000..55bc3d8c --- /dev/null +++ b/tests/led-string-parsing.test.ts @@ -0,0 +1,67 @@ +import { expect, test } from "bun:test" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" +import { fp } from "../src/footprinter" + +test("led0402 string produces 2 SMT pads with correct imperial size", () => { + const soup = fp.string("led0402").circuitJson() + const pads = soup.filter((e: any) => e.type === "pcb_smtpad") + expect(pads).toHaveLength(2) + + // Verify pads match the 0402 imperial size from the footprintSizes table + // 0402: pw=0.54mm, ph=0.64mm, p=1.02mm + const pad1 = pads.find((p: any) => p.port_hints?.includes("1")) + const pad2 = pads.find((p: any) => p.port_hints?.includes("2")) + expect(pad1).toBeDefined() + expect(pad2).toBeDefined() + expect(pad1!.width).toBeCloseTo(0.54, 1) + expect(pad1!.height).toBeCloseTo(0.64, 1) + + const svgContent = convertCircuitJsonToPcbSvg(soup) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "led0402_string") +}) + +test("led0805 string produces 2 SMT pads with correct imperial size", () => { + const soup = fp.string("led0805").circuitJson() + const pads = soup.filter((e: any) => e.type === "pcb_smtpad") + expect(pads).toHaveLength(2) + + // 0805: pw=1.025mm, ph=1.4mm + const pad1 = pads.find((p: any) => p.port_hints?.includes("1")) + expect(pad1!.width).toBeCloseTo(1.025, 2) + expect(pad1!.height).toBeCloseTo(1.4, 1) + + const svgContent = convertCircuitJsonToPcbSvg(soup) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "led0805_string") +}) + +test("led1206 string produces 2 SMT pads", () => { + const soup = fp.string("led1206").circuitJson() + const pads = soup.filter((e: any) => e.type === "pcb_smtpad") + expect(pads).toHaveLength(2) + + const svgContent = convertCircuitJsonToPcbSvg(soup) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "led1206_string") +}) + +test("led string matches led builder API output", () => { + const fromString = fp.string("led0603").circuitJson() + const fromBuilder = fp().led().imperial("0603").circuitJson() + + const stringPads = fromString.filter((e: any) => e.type === "pcb_smtpad") + const builderPads = fromBuilder.filter((e: any) => e.type === "pcb_smtpad") + + expect(stringPads).toHaveLength(builderPads.length) + + for (let i = 0; i < stringPads.length; i++) { + expect(stringPads[i].x).toBeCloseTo(builderPads[i].x, 5) + expect(stringPads[i].y).toBeCloseTo(builderPads[i].y, 5) + expect(stringPads[i].width).toBeCloseTo(builderPads[i].width, 5) + expect(stringPads[i].height).toBeCloseTo(builderPads[i].height, 5) + } +}) + +test("led0402_metric string uses metric lookup", () => { + const params = fp.string("led1005_metric").params() + expect(params.metric).toBe("1005") + expect(params.fn).toBe("led") +}) From 4946db3b0cab60aadfdb7b301fe9aee12b470eb4 Mon Sep 17 00:00:00 2001 From: Claw Explorer Date: Wed, 1 Apr 2026 15:13:00 -0400 Subject: [PATCH 2/2] refactor: split tests to one test per file (per review feedback) --- tests/diode-string-parsing.test.ts | 53 ----------------------------- tests/diode-string-parsing2.test.ts | 16 +++++++++ tests/diode-string-parsing3.test.ts | 12 +++++++ tests/diode-string-parsing4.test.ts | 19 +++++++++++ tests/diode-string-parsing5.test.ts | 8 +++++ tests/diode-string-parsing6.test.ts | 8 +++++ tests/led-string-parsing.test.ts | 48 -------------------------- tests/led-string-parsing2.test.ts | 16 +++++++++ tests/led-string-parsing3.test.ts | 12 +++++++ tests/led-string-parsing4.test.ts | 19 +++++++++++ tests/led-string-parsing5.test.ts | 8 +++++ 11 files changed, 118 insertions(+), 101 deletions(-) create mode 100644 tests/diode-string-parsing2.test.ts create mode 100644 tests/diode-string-parsing3.test.ts create mode 100644 tests/diode-string-parsing4.test.ts create mode 100644 tests/diode-string-parsing5.test.ts create mode 100644 tests/diode-string-parsing6.test.ts create mode 100644 tests/led-string-parsing2.test.ts create mode 100644 tests/led-string-parsing3.test.ts create mode 100644 tests/led-string-parsing4.test.ts create mode 100644 tests/led-string-parsing5.test.ts diff --git a/tests/diode-string-parsing.test.ts b/tests/diode-string-parsing.test.ts index 5b4b299f..ef2260ff 100644 --- a/tests/diode-string-parsing.test.ts +++ b/tests/diode-string-parsing.test.ts @@ -7,7 +7,6 @@ test("diode0402 string produces 2 SMT pads with correct imperial size", () => { const pads = soup.filter((e: any) => e.type === "pcb_smtpad") expect(pads).toHaveLength(2) - // 0402: pw=0.54mm, ph=0.64mm, p=1.02mm const pad1 = pads.find((p: any) => p.port_hints?.includes("1")) expect(pad1).toBeDefined() expect(pad1!.width).toBeCloseTo(0.54, 1) @@ -16,55 +15,3 @@ test("diode0402 string produces 2 SMT pads with correct imperial size", () => { const svgContent = convertCircuitJsonToPcbSvg(soup) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "diode0402_string") }) - -test("diode0805 string produces 2 SMT pads with correct imperial size", () => { - const soup = fp.string("diode0805").circuitJson() - const pads = soup.filter((e: any) => e.type === "pcb_smtpad") - expect(pads).toHaveLength(2) - - // 0805: pw=1.025mm, ph=1.4mm - const pad1 = pads.find((p: any) => p.port_hints?.includes("1")) - expect(pad1!.width).toBeCloseTo(1.025, 2) - expect(pad1!.height).toBeCloseTo(1.4, 1) - - const svgContent = convertCircuitJsonToPcbSvg(soup) - expect(svgContent).toMatchSvgSnapshot(import.meta.path, "diode0805_string") -}) - -test("diode1206 string produces 2 SMT pads", () => { - const soup = fp.string("diode1206").circuitJson() - const pads = soup.filter((e: any) => e.type === "pcb_smtpad") - expect(pads).toHaveLength(2) - - const svgContent = convertCircuitJsonToPcbSvg(soup) - expect(svgContent).toMatchSvgSnapshot(import.meta.path, "diode1206_string") -}) - -test("diode string matches diode builder API output", () => { - const fromString = fp.string("diode0603").circuitJson() - const fromBuilder = fp().diode().imperial("0603").circuitJson() - - const stringPads = fromString.filter((e: any) => e.type === "pcb_smtpad") - const builderPads = fromBuilder.filter((e: any) => e.type === "pcb_smtpad") - - expect(stringPads).toHaveLength(builderPads.length) - - for (let i = 0; i < stringPads.length; i++) { - expect(stringPads[i].x).toBeCloseTo(builderPads[i].x, 5) - expect(stringPads[i].y).toBeCloseTo(builderPads[i].y, 5) - expect(stringPads[i].width).toBeCloseTo(builderPads[i].width, 5) - expect(stringPads[i].height).toBeCloseTo(builderPads[i].height, 5) - } -}) - -test("diode0402_metric string uses metric lookup", () => { - const params = fp.string("diode1005_metric").params() - expect(params.metric).toBe("1005") - expect(params.fn).toBe("diode") -}) - -test("diode0603_tht string produces through-hole pads", () => { - const soup = fp.string("diode0603_tht").circuitJson() - const holes = soup.filter((e: any) => e.type === "pcb_plated_hole") - expect(holes).toHaveLength(2) -}) diff --git a/tests/diode-string-parsing2.test.ts b/tests/diode-string-parsing2.test.ts new file mode 100644 index 00000000..33756776 --- /dev/null +++ b/tests/diode-string-parsing2.test.ts @@ -0,0 +1,16 @@ +import { expect, test } from "bun:test" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" +import { fp } from "../src/footprinter" + +test("diode0805 string produces 2 SMT pads with correct imperial size", () => { + const soup = fp.string("diode0805").circuitJson() + const pads = soup.filter((e: any) => e.type === "pcb_smtpad") + expect(pads).toHaveLength(2) + + const pad1 = pads.find((p: any) => p.port_hints?.includes("1")) + expect(pad1!.width).toBeCloseTo(1.025, 2) + expect(pad1!.height).toBeCloseTo(1.4, 1) + + const svgContent = convertCircuitJsonToPcbSvg(soup) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "diode0805_string") +}) diff --git a/tests/diode-string-parsing3.test.ts b/tests/diode-string-parsing3.test.ts new file mode 100644 index 00000000..55d19ae0 --- /dev/null +++ b/tests/diode-string-parsing3.test.ts @@ -0,0 +1,12 @@ +import { expect, test } from "bun:test" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" +import { fp } from "../src/footprinter" + +test("diode1206 string produces 2 SMT pads", () => { + const soup = fp.string("diode1206").circuitJson() + const pads = soup.filter((e: any) => e.type === "pcb_smtpad") + expect(pads).toHaveLength(2) + + const svgContent = convertCircuitJsonToPcbSvg(soup) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "diode1206_string") +}) diff --git a/tests/diode-string-parsing4.test.ts b/tests/diode-string-parsing4.test.ts new file mode 100644 index 00000000..64cec5aa --- /dev/null +++ b/tests/diode-string-parsing4.test.ts @@ -0,0 +1,19 @@ +import { expect, test } from "bun:test" +import { fp } from "../src/footprinter" + +test("diode string matches diode builder API output", () => { + const fromString = fp.string("diode0603").circuitJson() + const fromBuilder = fp().diode().imperial("0603").circuitJson() + + const stringPads = fromString.filter((e: any) => e.type === "pcb_smtpad") + const builderPads = fromBuilder.filter((e: any) => e.type === "pcb_smtpad") + + expect(stringPads).toHaveLength(builderPads.length) + + for (let i = 0; i < stringPads.length; i++) { + expect(stringPads[i].x).toBeCloseTo(builderPads[i].x, 5) + expect(stringPads[i].y).toBeCloseTo(builderPads[i].y, 5) + expect(stringPads[i].width).toBeCloseTo(builderPads[i].width, 5) + expect(stringPads[i].height).toBeCloseTo(builderPads[i].height, 5) + } +}) diff --git a/tests/diode-string-parsing5.test.ts b/tests/diode-string-parsing5.test.ts new file mode 100644 index 00000000..ce96f7e0 --- /dev/null +++ b/tests/diode-string-parsing5.test.ts @@ -0,0 +1,8 @@ +import { expect, test } from "bun:test" +import { fp } from "../src/footprinter" + +test("diode0402_metric string uses metric lookup", () => { + const params = fp.string("diode1005_metric").params() + expect(params.metric).toBe("1005") + expect(params.fn).toBe("diode") +}) diff --git a/tests/diode-string-parsing6.test.ts b/tests/diode-string-parsing6.test.ts new file mode 100644 index 00000000..0c1f8f99 --- /dev/null +++ b/tests/diode-string-parsing6.test.ts @@ -0,0 +1,8 @@ +import { expect, test } from "bun:test" +import { fp } from "../src/footprinter" + +test("diode0603_tht string produces through-hole pads", () => { + const soup = fp.string("diode0603_tht").circuitJson() + const holes = soup.filter((e: any) => e.type === "pcb_plated_hole") + expect(holes).toHaveLength(2) +}) diff --git a/tests/led-string-parsing.test.ts b/tests/led-string-parsing.test.ts index 55bc3d8c..fe87159f 100644 --- a/tests/led-string-parsing.test.ts +++ b/tests/led-string-parsing.test.ts @@ -7,8 +7,6 @@ test("led0402 string produces 2 SMT pads with correct imperial size", () => { const pads = soup.filter((e: any) => e.type === "pcb_smtpad") expect(pads).toHaveLength(2) - // Verify pads match the 0402 imperial size from the footprintSizes table - // 0402: pw=0.54mm, ph=0.64mm, p=1.02mm const pad1 = pads.find((p: any) => p.port_hints?.includes("1")) const pad2 = pads.find((p: any) => p.port_hints?.includes("2")) expect(pad1).toBeDefined() @@ -19,49 +17,3 @@ test("led0402 string produces 2 SMT pads with correct imperial size", () => { const svgContent = convertCircuitJsonToPcbSvg(soup) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "led0402_string") }) - -test("led0805 string produces 2 SMT pads with correct imperial size", () => { - const soup = fp.string("led0805").circuitJson() - const pads = soup.filter((e: any) => e.type === "pcb_smtpad") - expect(pads).toHaveLength(2) - - // 0805: pw=1.025mm, ph=1.4mm - const pad1 = pads.find((p: any) => p.port_hints?.includes("1")) - expect(pad1!.width).toBeCloseTo(1.025, 2) - expect(pad1!.height).toBeCloseTo(1.4, 1) - - const svgContent = convertCircuitJsonToPcbSvg(soup) - expect(svgContent).toMatchSvgSnapshot(import.meta.path, "led0805_string") -}) - -test("led1206 string produces 2 SMT pads", () => { - const soup = fp.string("led1206").circuitJson() - const pads = soup.filter((e: any) => e.type === "pcb_smtpad") - expect(pads).toHaveLength(2) - - const svgContent = convertCircuitJsonToPcbSvg(soup) - expect(svgContent).toMatchSvgSnapshot(import.meta.path, "led1206_string") -}) - -test("led string matches led builder API output", () => { - const fromString = fp.string("led0603").circuitJson() - const fromBuilder = fp().led().imperial("0603").circuitJson() - - const stringPads = fromString.filter((e: any) => e.type === "pcb_smtpad") - const builderPads = fromBuilder.filter((e: any) => e.type === "pcb_smtpad") - - expect(stringPads).toHaveLength(builderPads.length) - - for (let i = 0; i < stringPads.length; i++) { - expect(stringPads[i].x).toBeCloseTo(builderPads[i].x, 5) - expect(stringPads[i].y).toBeCloseTo(builderPads[i].y, 5) - expect(stringPads[i].width).toBeCloseTo(builderPads[i].width, 5) - expect(stringPads[i].height).toBeCloseTo(builderPads[i].height, 5) - } -}) - -test("led0402_metric string uses metric lookup", () => { - const params = fp.string("led1005_metric").params() - expect(params.metric).toBe("1005") - expect(params.fn).toBe("led") -}) diff --git a/tests/led-string-parsing2.test.ts b/tests/led-string-parsing2.test.ts new file mode 100644 index 00000000..09977549 --- /dev/null +++ b/tests/led-string-parsing2.test.ts @@ -0,0 +1,16 @@ +import { expect, test } from "bun:test" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" +import { fp } from "../src/footprinter" + +test("led0805 string produces 2 SMT pads with correct imperial size", () => { + const soup = fp.string("led0805").circuitJson() + const pads = soup.filter((e: any) => e.type === "pcb_smtpad") + expect(pads).toHaveLength(2) + + const pad1 = pads.find((p: any) => p.port_hints?.includes("1")) + expect(pad1!.width).toBeCloseTo(1.025, 2) + expect(pad1!.height).toBeCloseTo(1.4, 1) + + const svgContent = convertCircuitJsonToPcbSvg(soup) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "led0805_string") +}) diff --git a/tests/led-string-parsing3.test.ts b/tests/led-string-parsing3.test.ts new file mode 100644 index 00000000..7c3d4d48 --- /dev/null +++ b/tests/led-string-parsing3.test.ts @@ -0,0 +1,12 @@ +import { expect, test } from "bun:test" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" +import { fp } from "../src/footprinter" + +test("led1206 string produces 2 SMT pads", () => { + const soup = fp.string("led1206").circuitJson() + const pads = soup.filter((e: any) => e.type === "pcb_smtpad") + expect(pads).toHaveLength(2) + + const svgContent = convertCircuitJsonToPcbSvg(soup) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "led1206_string") +}) diff --git a/tests/led-string-parsing4.test.ts b/tests/led-string-parsing4.test.ts new file mode 100644 index 00000000..17d465ef --- /dev/null +++ b/tests/led-string-parsing4.test.ts @@ -0,0 +1,19 @@ +import { expect, test } from "bun:test" +import { fp } from "../src/footprinter" + +test("led string matches led builder API output", () => { + const fromString = fp.string("led0603").circuitJson() + const fromBuilder = fp().led().imperial("0603").circuitJson() + + const stringPads = fromString.filter((e: any) => e.type === "pcb_smtpad") + const builderPads = fromBuilder.filter((e: any) => e.type === "pcb_smtpad") + + expect(stringPads).toHaveLength(builderPads.length) + + for (let i = 0; i < stringPads.length; i++) { + expect(stringPads[i].x).toBeCloseTo(builderPads[i].x, 5) + expect(stringPads[i].y).toBeCloseTo(builderPads[i].y, 5) + expect(stringPads[i].width).toBeCloseTo(builderPads[i].width, 5) + expect(stringPads[i].height).toBeCloseTo(builderPads[i].height, 5) + } +}) diff --git a/tests/led-string-parsing5.test.ts b/tests/led-string-parsing5.test.ts new file mode 100644 index 00000000..04c04b6e --- /dev/null +++ b/tests/led-string-parsing5.test.ts @@ -0,0 +1,8 @@ +import { expect, test } from "bun:test" +import { fp } from "../src/footprinter" + +test("led0402_metric string uses metric lookup", () => { + const params = fp.string("led1005_metric").params() + expect(params.metric).toBe("1005") + expect(params.fn).toBe("led") +})