From 953fb73bba46a2dc781cc1874a1ed7945c1bb53e Mon Sep 17 00:00:00 2001 From: techmannih Date: Wed, 11 Mar 2026 01:11:22 +0530 Subject: [PATCH 1/2] feat: add test for KiCad JST XH connector footprint --- .../kicad-jst-xh-connector-footprint.snap.svg | 1 + .../kicad-jst-xh-connector-footprint.test.tsx | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 tests/features/__snapshots__/kicad-jst-xh-connector-footprint.snap.svg create mode 100644 tests/features/kicad-jst-xh-connector-footprint.test.tsx diff --git a/tests/features/__snapshots__/kicad-jst-xh-connector-footprint.snap.svg b/tests/features/__snapshots__/kicad-jst-xh-connector-footprint.snap.svg new file mode 100644 index 000000000..079234e6a --- /dev/null +++ b/tests/features/__snapshots__/kicad-jst-xh-connector-footprint.snap.svg @@ -0,0 +1 @@ +U1${REFERENCE}JST_XH_B3B-XH-AM_1x03_P2.50mm_Vertical \ No newline at end of file diff --git a/tests/features/kicad-jst-xh-connector-footprint.test.tsx b/tests/features/kicad-jst-xh-connector-footprint.test.tsx new file mode 100644 index 000000000..4becdef93 --- /dev/null +++ b/tests/features/kicad-jst-xh-connector-footprint.test.tsx @@ -0,0 +1,59 @@ +import { expect, test } from "bun:test" +import { getTestFixture } from "tests/fixtures/get-test-fixture" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" + +const KICAD_FOOTPRINT_CACHE_URL = "https://kicad-mod-cache.tscircuit.com" + +test( + "kicad JST XH connector footprint loads correctly", + async () => { + const { circuit } = getTestFixture({ + platform: { + footprintLibraryMap: { + kicad: async (footprintName: string) => { + const baseUrl = `${KICAD_FOOTPRINT_CACHE_URL}/${footprintName}` + const circuitJsonUrl = `${baseUrl}.circuit.json` + const res = await fetch(circuitJsonUrl) + if (!res.ok) { + throw new Error( + `Failed to load KiCad footprint "${footprintName}" (HTTP ${res.status})`, + ) + } + const raw: any[] = await res.json() + const filtered = raw.filter((el) => + el?.type === "pcb_silkscreen_text" ? el?.text === "REF**" : true, + ) + return { footprintCircuitJson: filtered } + }, + }, + }, + }) + + circuit.add( + + + , + ) + + await circuit.renderUntilSettled() + + const circuitJson = circuit.getCircuitJson() + + const errors = circuitJson.filter( + (el) => el.type.includes("error") || el.type.includes("warning"), + ) + + expect(errors).toHaveLength(0) + + const holes = circuitJson.filter((el) => el.type === "pcb_plated_hole") + expect(holes).toHaveLength(3) + + expect(convertCircuitJsonToPcbSvg(circuitJson as any)).toMatchSvgSnapshot( + import.meta.path, + ) + }, + 30 * 1000, +) From c396bf49c08dad4e7f9b92c2a32fa2e3f38f2c71 Mon Sep 17 00:00:00 2001 From: techmannih Date: Wed, 11 Mar 2026 01:36:50 +0530 Subject: [PATCH 2/2] up --- .../kicad-jst-xh-connector-footprint.test.tsx | 23 +- .../assets/external-jst-xh-b3b-footprint.json | 393 ++++++++++++++++++ 2 files changed, 405 insertions(+), 11 deletions(-) create mode 100644 tests/fixtures/assets/external-jst-xh-b3b-footprint.json diff --git a/tests/features/kicad-jst-xh-connector-footprint.test.tsx b/tests/features/kicad-jst-xh-connector-footprint.test.tsx index 4becdef93..a5bc791b2 100644 --- a/tests/features/kicad-jst-xh-connector-footprint.test.tsx +++ b/tests/features/kicad-jst-xh-connector-footprint.test.tsx @@ -2,7 +2,7 @@ import { expect, test } from "bun:test" import { getTestFixture } from "tests/fixtures/get-test-fixture" import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" -const KICAD_FOOTPRINT_CACHE_URL = "https://kicad-mod-cache.tscircuit.com" +import jstXhB3BFootprint from "tests/fixtures/assets/external-jst-xh-b3b-footprint.json" test( "kicad JST XH connector footprint loads correctly", @@ -11,19 +11,20 @@ test( platform: { footprintLibraryMap: { kicad: async (footprintName: string) => { - const baseUrl = `${KICAD_FOOTPRINT_CACHE_URL}/${footprintName}` - const circuitJsonUrl = `${baseUrl}.circuit.json` - const res = await fetch(circuitJsonUrl) - if (!res.ok) { - throw new Error( - `Failed to load KiCad footprint "${footprintName}" (HTTP ${res.status})`, + if ( + footprintName === + "Connector_JST/JST_XH_B3B-XH-AM_1x03_P2.50mm_Vertical" + ) { + const filtered = jstXhB3BFootprint.filter((el) => + el?.type === "pcb_silkscreen_text" + ? el?.text === "REF**" + : true, ) + return { footprintCircuitJson: filtered } } - const raw: any[] = await res.json() - const filtered = raw.filter((el) => - el?.type === "pcb_silkscreen_text" ? el?.text === "REF**" : true, + throw new Error( + `Footprint "${footprintName}" not found in local mock`, ) - return { footprintCircuitJson: filtered } }, }, }, diff --git a/tests/fixtures/assets/external-jst-xh-b3b-footprint.json b/tests/fixtures/assets/external-jst-xh-b3b-footprint.json new file mode 100644 index 000000000..2fcc59997 --- /dev/null +++ b/tests/fixtures/assets/external-jst-xh-b3b-footprint.json @@ -0,0 +1,393 @@ +[ + { + "type": "source_component", + "source_component_id": "source_component_0", + "supplier_part_numbers": {} + }, + { + "type": "schematic_component", + "schematic_component_id": "schematic_component_0", + "source_component_id": "source_component_0", + "center": { + "x": 0, + "y": 0 + }, + "rotation": 0, + "size": { + "width": 0, + "height": 0 + } + }, + { + "type": "source_port", + "source_port_id": "source_port_0", + "source_component_id": "source_component_0", + "name": "1", + "port_hints": ["1"], + "pin_number": 1, + "pin_label": "pin1" + }, + { + "type": "schematic_port", + "schematic_port_id": "schematic_port_1", + "source_port_id": "source_port_0", + "schematic_component_id": "schematic_component_0", + "center": { + "x": 0, + "y": 0 + } + }, + { + "type": "source_port", + "source_port_id": "source_port_2", + "source_component_id": "source_component_0", + "name": "2", + "port_hints": ["2"], + "pin_number": 2, + "pin_label": "pin2" + }, + { + "type": "schematic_port", + "schematic_port_id": "schematic_port_3", + "source_port_id": "source_port_2", + "schematic_component_id": "schematic_component_0", + "center": { + "x": 0, + "y": 0 + } + }, + { + "type": "source_port", + "source_port_id": "source_port_4", + "source_component_id": "source_component_0", + "name": "3", + "port_hints": ["3"], + "pin_number": 3, + "pin_label": "pin3" + }, + { + "type": "schematic_port", + "schematic_port_id": "schematic_port_5", + "source_port_id": "source_port_4", + "schematic_component_id": "schematic_component_0", + "center": { + "x": 0, + "y": 0 + } + }, + { + "type": "pcb_component", + "source_component_id": "source_component_0", + "pcb_component_id": "pcb_component_0", + "layer": "top", + "center": { + "x": 0, + "y": 0 + }, + "rotation": 0, + "width": 1.2000000000000002, + "height": 1.2000000000000002 + }, + { + "type": "pcb_port", + "pcb_port_id": "pcb_port_0", + "source_port_id": "source_port_0", + "pcb_component_id": "pcb_component_0", + "x": 0, + "y": 0, + "layers": [] + }, + { + "type": "pcb_port", + "pcb_port_id": "pcb_port_1", + "source_port_id": "source_port_2", + "pcb_component_id": "pcb_component_0", + "x": 2.5, + "y": 0, + "layers": [] + }, + { + "type": "pcb_port", + "pcb_port_id": "pcb_port_2", + "source_port_id": "source_port_4", + "pcb_component_id": "pcb_component_0", + "x": 5, + "y": 0, + "layers": [] + }, + { + "type": "pcb_hole", + "pcb_hole_id": "pcb_hole_0", + "x": -1.6, + "y": -2, + "hole_shape": "circle", + "hole_diameter": 1.2, + "pcb_component_id": "pcb_component_0" + }, + { + "type": "pcb_plated_hole", + "pcb_plated_hole_id": "pcb_plated_hole_0", + "shape": "circular_hole_with_rect_pad", + "hole_shape": "circle", + "pad_shape": "rect", + "x": 0, + "y": 0, + "hole_offset_x": 0, + "hole_offset_y": 0, + "hole_diameter": 0.95, + "rect_pad_width": 1.7, + "rect_pad_height": 1.95, + "rect_border_radius": 0.12500015, + "port_hints": ["pin1"], + "layers": ["top", "bottom"], + "pcb_component_id": "pcb_component_0", + "pcb_port_id": "pcb_port_0", + "pin_number": 1, + "pin_label": "pin1" + }, + { + "type": "pcb_plated_hole", + "pcb_plated_hole_id": "pcb_plated_hole_1", + "shape": "pill", + "x": 2.5, + "y": 0, + "outer_width": 1.7, + "outer_height": 1.95, + "hole_width": 0.95, + "hole_height": 0.95, + "port_hints": ["pin2"], + "layers": ["top", "bottom"], + "pcb_component_id": "pcb_component_0", + "pcb_port_id": "pcb_port_1", + "pin_number": 2, + "pin_label": "pin2" + }, + { + "type": "pcb_plated_hole", + "pcb_plated_hole_id": "pcb_plated_hole_2", + "shape": "pill", + "x": 5, + "y": 0, + "outer_width": 1.7, + "outer_height": 1.95, + "hole_width": 0.95, + "hole_height": 0.95, + "port_hints": ["pin3"], + "layers": ["top", "bottom"], + "pcb_component_id": "pcb_component_0", + "pcb_port_id": "pcb_port_2", + "pin_number": 3, + "pin_label": "pin3" + }, + { + "type": "pcb_silkscreen_path", + "pcb_silkscreen_path_id": "pcb_silkscreen_path_0", + "pcb_component_id": "pcb_component_0", + "layer": "top", + "route": [ + { + "x": -2.85, + "y": 2.75 + }, + { + "x": -2.85, + "y": 1.5 + } + ], + "stroke_width": 0.12 + }, + { + "type": "pcb_silkscreen_path", + "pcb_silkscreen_path_id": "pcb_silkscreen_path_1", + "pcb_component_id": "pcb_component_0", + "layer": "top", + "route": [ + { + "x": -2.55, + "y": 0.2 + }, + { + "x": -1.8, + "y": 0.2 + } + ], + "stroke_width": 0.12 + }, + { + "type": "pcb_silkscreen_path", + "pcb_silkscreen_path_id": "pcb_silkscreen_path_2", + "pcb_component_id": "pcb_component_0", + "layer": "top", + "route": [ + { + "x": -1.8, + "y": 0.2 + }, + { + "x": -1.8, + "y": -1.14 + } + ], + "stroke_width": 0.12 + }, + { + "type": "pcb_silkscreen_path", + "pcb_silkscreen_path_id": "pcb_silkscreen_path_3", + "pcb_component_id": "pcb_component_0", + "layer": "top", + "route": [ + { + "x": -1.6, + "y": 2.75 + }, + { + "x": -2.85, + "y": 2.75 + } + ], + "stroke_width": 0.12 + }, + { + "type": "pcb_silkscreen_path", + "pcb_silkscreen_path_id": "pcb_silkscreen_path_4", + "pcb_component_id": "pcb_component_0", + "layer": "top", + "route": [ + { + "x": 2.5, + "y": -2.75 + }, + { + "x": -0.74, + "y": -2.75 + } + ], + "stroke_width": 0.12 + }, + { + "type": "pcb_silkscreen_path", + "pcb_silkscreen_path_id": "pcb_silkscreen_path_5", + "pcb_component_id": "pcb_component_0", + "layer": "top", + "route": [ + { + "x": 6.8, + "y": 0.2 + }, + { + "x": 6.8, + "y": -2.75 + } + ], + "stroke_width": 0.12 + }, + { + "type": "pcb_silkscreen_path", + "pcb_silkscreen_path_id": "pcb_silkscreen_path_6", + "pcb_component_id": "pcb_component_0", + "layer": "top", + "route": [ + { + "x": 6.8, + "y": -2.75 + }, + { + "x": 2.5, + "y": -2.75 + } + ], + "stroke_width": 0.12 + }, + { + "type": "pcb_silkscreen_path", + "pcb_silkscreen_path_id": "pcb_silkscreen_path_7", + "pcb_component_id": "pcb_component_0", + "layer": "top", + "route": [ + { + "x": 7.55, + "y": 0.2 + }, + { + "x": 6.8, + "y": 0.2 + } + ], + "stroke_width": 0.12 + }, + { + "type": "pcb_fabrication_note_path", + "fabrication_note_path_id": "fabrication_note_path_0", + "pcb_component_id": "pcb_component_0", + "layer": "top", + "route": [ + { + "x": -0.625, + "y": 2.35 + }, + { + "x": 0, + "y": 1.35 + } + ], + "stroke_width": 0.1, + "port_hints": [] + }, + { + "type": "pcb_fabrication_note_path", + "fabrication_note_path_id": "fabrication_note_path_1", + "pcb_component_id": "pcb_component_0", + "layer": "top", + "route": [ + { + "x": 0, + "y": 1.35 + }, + { + "x": 0.625, + "y": 2.35 + } + ], + "stroke_width": 0.1, + "port_hints": [] + }, + { + "type": "pcb_fabrication_note_text", + "layer": "top", + "font": "tscircuit2024", + "font_size": 1, + "pcb_component_id": "pcb_component_0", + "anchor_position": { + "x": 2.5, + "y": -2.7 + }, + "anchor_alignment": "center", + "text": "${REFERENCE}" + }, + { + "type": "pcb_silkscreen_text", + "layer": "top", + "font": "tscircuit2024", + "font_size": 1, + "pcb_component_id": "pcb_component_0", + "anchor_position": { + "x": 2.5, + "y": 3.55 + }, + "anchor_alignment": "center", + "text": "REF**" + }, + { + "type": "pcb_fabrication_note_text", + "layer": "top", + "font": "tscircuit2024", + "font_size": 1, + "pcb_component_id": "pcb_component_0", + "anchor_position": { + "x": 2.5, + "y": -4.6 + }, + "anchor_alignment": "center", + "text": "JST_XH_B3B-XH-AM_1x03_P2.50mm_Vertical" + } +]