@tscircuit/schematic-trace-solver 0.0.149 → 0.0.150

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/.agents/skills/schematic-trace-visualization/SKILL.md +7 -2
  2. package/dist/index.d.ts +28 -1
  3. package/dist/index.js +26 -4
  4. package/lib/solvers/InlineNetLabelSolver/InlineNetLabelSolver.ts +14 -4
  5. package/lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver.ts +17 -1
  6. package/lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/SingleNetLabelPlacementSolver.ts +2 -0
  7. package/lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/solvePortOnlyPin.ts +2 -0
  8. package/lib/types/InputProblem.ts +27 -1
  9. package/package.json +8 -1
  10. package/tests/bug-reports/bug-report-20260706T213649Z/__snapshots__/bug-report-20260706T213649Z.snap.svg +751 -5
  11. package/tests/bug-reports/bug-report-20260706T220324Z/__snapshots__/bug-report-20260706T220324Z.snap.svg +660 -5
  12. package/tests/bug-reports/bug-report-20260707T020342Z/__snapshots__/bug-report-20260707T020342Z.snap.svg +44 -5
  13. package/tests/bug-reports/bug-report-20260707T092615Z/__snapshots__/bug-report-20260707T092615Z.snap.svg +394 -5
  14. package/tests/bug-reports/bug-report-20260707T134549Z/__snapshots__/bug-report-20260707T134549Z.snap.svg +170 -5
  15. package/tests/bug-reports/bug-report-20260707T134722Z/__snapshots__/bug-report-20260707T134722Z.snap.svg +79 -5
  16. package/tests/bug-reports/bug-report-20260707T140410Z/__snapshots__/bug-report-20260707T140410Z.snap.svg +219 -5
  17. package/tests/bug-reports/bug-report-20260707T141025Z/__snapshots__/bug-report-20260707T141025Z.snap.svg +65 -5
  18. package/tests/bug-reports/bug-report-20260707T141421Z/__snapshots__/bug-report-20260707T141421Z.snap.svg +142 -5
  19. package/tests/bug-reports/bug-report-20260707T230831Z/__snapshots__/bug-report-20260707T230831Z.snap.svg +100 -5
  20. package/tests/bug-reports/bug-report-20260708T053736Z/__snapshots__/bug-report-20260708T053736Z.snap.svg +23 -5
  21. package/tests/bug-reports/bug-report-20260708T055430Z/__snapshots__/bug-report-20260708T055430Z.snap.svg +58 -5
  22. package/tests/bug-reports/bug-report-20260708T095725Z/__snapshots__/bug-report-20260708T095725Z.snap.svg +86 -5
  23. package/tests/bug-reports/bug-report-20260716T144856Z/__snapshots__/bug-report-20260716T144856Z.snap.svg +226 -5
  24. package/tests/bug-reports/bug-report-20260717T022934Z/__snapshots__/bug-report-20260717T022934Z.snap.svg +191 -5
  25. package/tests/bug-reports/bug-report-20260717T031704Z/__snapshots__/bug-report-20260717T031704Z.snap.svg +30 -5
  26. package/tests/bug-reports/bug-report-20260717T042845Z/__snapshots__/bug-report-20260717T042845Z.snap.svg +37 -5
  27. package/tests/bug-reports/bug-report-20260721T221026Z/__snapshots__/bug-report-20260721T221026Z.snap.svg +580 -2
  28. package/tests/bug-reports/bug-report-20260724T175257Z/__snapshots__/bug-report-20260724T175257Z.snap.svg +44 -5
  29. package/tests/bug-reports/bug-report-20260728T144234Z/__snapshots__/bug-report-20260728T144234Z.snap.svg +107 -5
  30. package/tests/bug-reports/bug-report-20260728T225606Z/__snapshots__/bug-report-20260728T225606Z.snap.svg +114 -5
  31. package/tests/bug-reports/bug-report-20260730T061837Z/__snapshots__/bug-report-20260730T061837Z.snap.svg +121 -5
  32. package/tests/bug-reports/bug-report-20260731T052229Z/__snapshots__/bug-report-20260731T052229Z.snap.svg +51 -5
  33. package/tests/bug-reports/bug-report-20260804T095800Z/__snapshots__/bug-report-20260804T095800Z.snap.svg +212 -5
  34. package/tests/bug-reports/bug-report-20260804T171919Z/__snapshots__/bug-report-20260804T171919Z.snap.svg +569 -5
  35. package/tests/bug-reports/bug-report-20260804T225912Z/__snapshots__/bug-report-20260804T225912Z.snap.svg +37 -5
  36. package/tests/bug-reports/bug-report-20260805T061316Z/__snapshots__/bug-report-20260805T061316Z.snap.svg +289 -5
  37. package/tests/bug-reports/bug-report-20260806T061548Z/__snapshots__/bug-report-20260806T061548Z.snap.svg +289 -5
  38. package/tests/bug-reports/bug-report-20260806T093501Z/__snapshots__/bug-report-20260806T093501Z.snap.svg +149 -5
  39. package/tests/bug-reports/bug-report-20260811T075142Z/__snapshots__/bug-report-20260811T075142Z.snap.svg +93 -5
  40. package/tests/bug-reports/bug-report-20260815T073240Z/__snapshots__/bug-report-20260815T073240Z.snap.svg +79 -5
  41. package/tests/bug-reports/bug-report-20260819T091818Z/__snapshots__/bug-report-20260819T091818Z.snap.svg +244 -2
  42. package/tests/examples/__snapshots__/example01.snap.svg +44 -5
  43. package/tests/examples/__snapshots__/example02.snap.svg +51 -5
  44. package/tests/examples/__snapshots__/example03.snap.svg +86 -5
  45. package/tests/examples/__snapshots__/example04.snap.svg +30 -5
  46. package/tests/examples/__snapshots__/example05.snap.svg +30 -5
  47. package/tests/examples/__snapshots__/example06.snap.svg +30 -5
  48. package/tests/examples/__snapshots__/example07.snap.svg +58 -5
  49. package/tests/examples/__snapshots__/example08.snap.svg +37 -5
  50. package/tests/examples/__snapshots__/example09.snap.svg +149 -5
  51. package/tests/examples/__snapshots__/example10.snap.svg +65 -5
  52. package/tests/examples/__snapshots__/example11.snap.svg +51 -5
  53. package/tests/examples/__snapshots__/example12.snap.svg +51 -5
  54. package/tests/examples/__snapshots__/example13.snap.svg +72 -5
  55. package/tests/examples/__snapshots__/example14.snap.svg +79 -5
  56. package/tests/examples/__snapshots__/example15.snap.svg +86 -5
  57. package/tests/examples/__snapshots__/example16.snap.svg +51 -5
  58. package/tests/examples/__snapshots__/example17.snap.svg +51 -5
  59. package/tests/examples/__snapshots__/example18.snap.svg +58 -5
  60. package/tests/examples/__snapshots__/example19.snap.svg +44 -5
  61. package/tests/examples/__snapshots__/example20.snap.svg +44 -5
  62. package/tests/examples/__snapshots__/example21.snap.svg +72 -5
  63. package/tests/examples/__snapshots__/example22.snap.svg +51 -5
  64. package/tests/examples/__snapshots__/example23.snap.svg +51 -5
  65. package/tests/examples/__snapshots__/example24.snap.svg +51 -5
  66. package/tests/examples/__snapshots__/example25.snap.svg +86 -5
  67. package/tests/examples/__snapshots__/example26.snap.svg +51 -5
  68. package/tests/examples/__snapshots__/example27.snap.svg +72 -5
  69. package/tests/examples/__snapshots__/example28.snap.svg +44 -5
  70. package/tests/examples/__snapshots__/example29.snap.svg +324 -5
  71. package/tests/examples/__snapshots__/example30.snap.svg +107 -5
  72. package/tests/examples/__snapshots__/example31.snap.svg +37 -5
  73. package/tests/examples/__snapshots__/example32.snap.svg +149 -5
  74. package/tests/examples/__snapshots__/example33.snap.svg +93 -5
  75. package/tests/examples/__snapshots__/example34.snap.svg +51 -5
  76. package/tests/examples/__snapshots__/example35.snap.svg +58 -5
  77. package/tests/examples/__snapshots__/example36.snap.svg +44 -5
  78. package/tests/examples/__snapshots__/example37.snap.svg +72 -5
  79. package/tests/examples/__snapshots__/example38.snap.svg +30 -5
  80. package/tests/examples/__snapshots__/example39.snap.svg +37 -5
  81. package/tests/examples/__snapshots__/example40.snap.svg +100 -5
  82. package/tests/examples/__snapshots__/example41.snap.svg +44 -5
  83. package/tests/examples/__snapshots__/example42.snap.svg +65 -5
  84. package/tests/examples/__snapshots__/example43.snap.svg +58 -5
  85. package/tests/examples/__snapshots__/example44.snap.svg +107 -5
  86. package/tests/examples/__snapshots__/example45.snap.svg +51 -5
  87. package/tests/examples/__snapshots__/example46.snap.svg +93 -5
  88. package/tests/examples/__snapshots__/example47.snap.svg +93 -5
  89. package/tests/examples/__snapshots__/example48.snap.svg +65 -5
  90. package/tests/examples/__snapshots__/example49.snap.svg +177 -5
  91. package/tests/examples/__snapshots__/example50.snap.svg +93 -5
  92. package/tests/examples/__snapshots__/example51.snap.svg +590 -5
  93. package/tests/fixtures/convertSolverOutputToCircuitJson.test.ts +219 -0
  94. package/tests/fixtures/convertSolverOutputToCircuitJson.ts +1058 -0
  95. package/tests/fixtures/matcher.ts +45 -8
  96. package/tests/repros/__snapshots__/board-1273-trace-overlap-cycle.snap.svg +762 -2
  97. package/tests/repros/__snapshots__/board-15984-same-net-junction.snap.svg +111 -2
  98. package/tests/repros/__snapshots__/board1096-usb-label-overlap-iteration.snap.svg +167 -2
  99. package/tests/repros/__snapshots__/bugreport-001-gnd-overlap.snap.svg +65 -5
  100. package/tests/repros/__snapshots__/manufacturePartNumber-text-box.snap.svg +30 -5
  101. package/tests/repros/__snapshots__/netlabel-connector-through-rail-label.snap.svg +79 -5
  102. package/tests/repros/__snapshots__/repro-atmega328p-fault-pullup.snap.svg +65 -5
  103. package/tests/repros/__snapshots__/repro-atmega328p-missing-gnd-netlabel.snap.svg +149 -5
  104. package/tests/repros/__snapshots__/repro-board-589-regulator-section.snap.svg +55 -2
  105. package/tests/repros/__snapshots__/repro-board-648-esp12f-section.snap.svg +160 -2
  106. package/tests/repros/__snapshots__/repro-bq24074-battery-charger.snap.svg +135 -5
  107. package/tests/repros/__snapshots__/repro-bq25895-cross-net-trace-overlap.snap.svg +69 -2
  108. package/tests/repros/__snapshots__/repro-cc2340r5.snap.svg +86 -5
  109. package/tests/repros/__snapshots__/repro-core-555-power-cross-net-overlap.snap.svg +44 -5
  110. package/tests/repros/__snapshots__/repro-core-subcircuit-missing-ground.snap.svg +44 -5
  111. package/tests/repros/__snapshots__/repro-core-tb67s579ftg-inline-label-routing.snap.svg +30 -5
  112. package/tests/repros/__snapshots__/repro-example35-minimize-trace-crossing.snap.svg +335 -2
  113. package/tests/repros/__snapshots__/repro-ground-label-on-lower-rail-end.snap.svg +48 -2
  114. package/tests/repros/__snapshots__/repro-ina237-current-monitor.snap.svg +149 -5
  115. package/tests/repros/__snapshots__/repro-missing-trace-netlabel.snap.svg +72 -5
  116. package/tests/repros/__snapshots__/repro-netlabel-collision-687.snap.svg +100 -5
  117. package/tests/repros/__snapshots__/repro-netlabel-overlap-trace.snap.svg +51 -5
  118. package/tests/repros/__snapshots__/repro-nrf52810-clock-routing.snap.svg +90 -2
  119. package/tests/repros/__snapshots__/repro-power-group-rail-labels.snap.svg +37 -5
  120. package/tests/repros/__snapshots__/repro-rectifier-trace-overlap.snap.svg +44 -5
  121. package/tests/repros/__snapshots__/repro-rp2040-gamepad-trace-alignment.snap.svg +237 -2
  122. package/tests/repros/__snapshots__/repro-rp2040-usb-cc2-ground-overlap.snap.svg +72 -5
  123. package/tests/repros/__snapshots__/repro-rp2040-v3v3-label-placement.snap.svg +51 -5
  124. package/tests/repros/__snapshots__/repro-rp2040-zero-crystal-fallback-netlabels.snap.svg +30 -5
  125. package/tests/repros/__snapshots__/repro-ti-power-output-section.snap.svg +79 -5
  126. package/tests/repros/__snapshots__/repro-tida010076-j4-ground-bus.snap.svg +27 -2
  127. package/tests/repros/__snapshots__/repro-tida010076-page02.snap.svg +1150 -5
  128. package/tests/repros/__snapshots__/repro-tps61222-trace-intersection.snap.svg +51 -5
  129. package/tests/repros/__snapshots__/repro-type-c-16pin-self-connection.snap.svg +30 -5
  130. package/tests/repros/__snapshots__/repro-type-c-16pin-to-resistor.snap.svg +30 -5
  131. package/tests/repros/__snapshots__/repro-type-c-vbus-led-ground-label.snap.svg +44 -5
  132. package/tests/repros/__snapshots__/repro-usb-power-vbus-label-detour.snap.svg +685 -2
  133. package/tests/repros/__snapshots__/repro-vcc-pin1-detour.snap.svg +27 -2
  134. package/tests/repros/__snapshots__/repro129-host-custom-symbol-passives.snap.svg +51 -5
  135. package/tests/repros/__snapshots__/repro130-bq27441-fuel-gauge-trace-through-c1.snap.svg +100 -5
  136. package/tests/repros/__snapshots__/repro161-power-section-autolayout.snap.svg +107 -5
  137. package/tests/repros/__snapshots__/repro47-endpoint-obstacle-detour.snap.svg +51 -5
  138. package/tests/repros/__snapshots__/repro48-555-timer-vcc-rail-label.snap.svg +104 -2
  139. package/tests/repros/__snapshots__/repro5-escape-padded-text-obstacles.snap.svg +30 -5
  140. package/tests/repros/__snapshots__/repro51-overlap-junction-crossing.snap.svg +65 -5
  141. package/tests/repros/__snapshots__/repro84-stacked-gnd-label-orientation.snap.svg +27 -2
  142. package/tests/repros/__snapshots__/small-variant-resistor-facing-direction.snap.svg +58 -5
  143. package/tests/repros/__snapshots__/trace-overlap-box-resistor.snap.svg +37 -5
  144. package/tests/solvers/InlineNetLabelSolver/__snapshots__/fallback-net-label-width.snap.svg +25 -7
  145. package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label-anchored-label-clearance.snap.svg +34 -2
  146. package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label-port-stub.snap.svg +23 -5
  147. package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label-two-pin-net.snap.svg +23 -5
  148. package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label01.snap.svg +23 -5
  149. package/tests/solvers/InlineNetLabelSolver/__snapshots__/inline-net-label02.snap.svg +23 -5
  150. package/tests/solvers/InlineNetLabelSolver/__snapshots__/terminal-stub-trace-clearance.snap.svg +23 -5
  151. package/tests/solvers/InlineNetLabelSolver/fallback-net-label-width.test.ts +10 -1
  152. package/tests/solvers/SchematicTraceSingleLineSolver2/__snapshots__/SchematicTraceSingleLineSolver2_01-example17-d1_1-u1_1.snap.svg +23 -5
  153. package/tests/solvers/SchematicTraceSingleLineSolver2/__snapshots__/SchematicTraceSingleLineSolver2_repro47-short-opposing-pins.snap.svg +20 -2
  154. package/tests/solvers/TraceCleanupSolver/__snapshots__/TraceCleanupSolver.snap.svg +44 -5
  155. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/__snapshots__/TraceLabelOverlapAvoidanceSolver.snap.svg +79 -5
  156. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/__snapshots__/MergedNetLabelObstacles.snap.svg +44 -5
  157. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/__snapshots__/OverlapAvoidanceStepSolver.snap.svg +23 -5
  158. package/tests/solvers/TraceLabelOverlapAvoidanceSolver/sub-solver/__snapshots__/SingleOverlapSolver.snap.svg +30 -5
@@ -0,0 +1,219 @@
1
+ import { expect, test } from "bun:test"
2
+ import {
3
+ any_circuit_element,
4
+ type SchematicPort,
5
+ type SchematicTrace,
6
+ } from "circuit-json"
7
+ import { convertCircuitJsonToSchematicSvg } from "circuit-to-svg"
8
+ import { BaseSolver } from "lib/solvers/BaseSolver/BaseSolver"
9
+ import type { InputProblem } from "lib/types/InputProblem"
10
+ import { convertSolverOutputToCircuitJson } from "./convertSolverOutputToCircuitJson"
11
+
12
+ const inputProblem: InputProblem = {
13
+ chips: [
14
+ {
15
+ chipId: "schematic_component_0",
16
+ center: { x: 0, y: 0 },
17
+ width: 1,
18
+ height: 1,
19
+ pins: [
20
+ { pinId: "U1.1", x: 0.5, y: 0.2, _facingDirection: "x+" },
21
+ { pinId: "U1.2", x: 0.5, y: -0.2, _facingDirection: "x+" },
22
+ ],
23
+ },
24
+ {
25
+ chipId: "schematic_component_1",
26
+ // tscircuit/core passes a text-inclusive obstacle here. These bounds are
27
+ // deliberately much larger and off-center from the capacitor symbol.
28
+ center: { x: 2.2, y: 0.35 },
29
+ width: 2,
30
+ height: 1.6,
31
+ pins: [
32
+ { pinId: "C1.1", x: 2, y: 0.3, _facingDirection: "y+" },
33
+ { pinId: "C1.2", x: 2, y: -0.3, _facingDirection: "y-" },
34
+ ],
35
+ },
36
+ {
37
+ chipId: "schematic_component_2",
38
+ symbolName: "led_right",
39
+ center: { x: 4.35, y: 0.4 },
40
+ width: 2.2,
41
+ height: 1.45,
42
+ pins: [
43
+ { pinId: "LED1.1", x: 3.46, y: 0, _facingDirection: "x-" },
44
+ { pinId: "LED1.2", x: 4.54, y: 0, _facingDirection: "x+" },
45
+ ],
46
+ },
47
+ ],
48
+ directConnections: [
49
+ {
50
+ pinIds: ["U1.1", "C1.1"],
51
+ netId: "ROUTED",
52
+ netLabelText: "CLK",
53
+ netLabelWidth: 0.514,
54
+ },
55
+ {
56
+ pinIds: ["U1.2", "C1.2"],
57
+ netId: "UNROUTED",
58
+ },
59
+ ],
60
+ netConnections: [],
61
+ textBoxes: [
62
+ {
63
+ chipId: "schematic_component_0",
64
+ center: { x: 0, y: -0.7 },
65
+ width: 1,
66
+ height: 0.2,
67
+ text: "part number",
68
+ },
69
+ ],
70
+ availableNetLabelOrientations: { ROUTED: ["x+"] },
71
+ }
72
+
73
+ class SnapshotTestSolver extends BaseSolver {
74
+ inputProblem = inputProblem
75
+
76
+ getOutput() {
77
+ return {
78
+ traces: [
79
+ {
80
+ mspPairId: "routed-trace",
81
+ globalConnNetId: "internal-global-net-id",
82
+ userNetId: "",
83
+ pinIds: ["U1.1", "C1.1"],
84
+ tracePath: [
85
+ { x: 0.5, y: 0.2 },
86
+ { x: 1.2, y: 0.2 },
87
+ { x: 1.2, y: 0.3 },
88
+ { x: 2, y: 0.3 },
89
+ ],
90
+ },
91
+ ],
92
+ netLabelPlacements: [
93
+ {
94
+ globalConnNetId: "internal-global-net-id",
95
+ netId: " ",
96
+ mspConnectionPairIds: ["routed-trace"],
97
+ pinIds: ["U1.1", "C1.1"],
98
+ orientation: "x+" as const,
99
+ anchorPoint: { x: 1.2, y: 0.2 },
100
+ width: 0.8,
101
+ height: 0.2,
102
+ center: { x: 1.6, y: 0.2 },
103
+ },
104
+ {
105
+ globalConnNetId: "internal-unrouted-net-id",
106
+ netId: " ",
107
+ mspConnectionPairIds: [],
108
+ pinIds: ["U1.2", "C1.2"],
109
+ orientation: "x+" as const,
110
+ anchorPoint: { x: 0.5, y: -0.2 },
111
+ width: 0.514,
112
+ height: 0.2,
113
+ center: { x: 0.757, y: -0.2 },
114
+ },
115
+ ],
116
+ inlineNetLabelPlacements: [],
117
+ }
118
+ }
119
+ }
120
+
121
+ test("solver snapshot Circuit JSON is semantic and omits the rats nest", () => {
122
+ const circuitJson = convertSolverOutputToCircuitJson(new SnapshotTestSolver())
123
+
124
+ for (const element of circuitJson) {
125
+ expect(any_circuit_element.safeParse(element).success).toBe(true)
126
+ }
127
+
128
+ expect(
129
+ circuitJson.filter((element) => element.type === "schematic_component"),
130
+ ).toHaveLength(3)
131
+ const genericBoxComponent = circuitJson.find(
132
+ (element) =>
133
+ element.type === "schematic_component" &&
134
+ element.source_component_id === "source_component_0",
135
+ )
136
+ if (genericBoxComponent?.type !== "schematic_component") {
137
+ throw new Error("Expected generic box schematic component")
138
+ }
139
+ expect(genericBoxComponent.size.width).toBeCloseTo(0.2)
140
+ expect(genericBoxComponent.size.height).toBe(1)
141
+ expect(
142
+ circuitJson.find(
143
+ (element) =>
144
+ element.type === "schematic_port" &&
145
+ element.schematic_component_id ===
146
+ genericBoxComponent.schematic_component_id,
147
+ ),
148
+ ).toMatchObject({ distance_from_component_edge: 0.4 })
149
+ expect(
150
+ circuitJson.find(
151
+ (element) =>
152
+ element.type === "schematic_component" &&
153
+ element.source_component_id === "source_component_1",
154
+ ),
155
+ ).toMatchObject({ symbol_name: "capacitor_down" })
156
+
157
+ const capacitorComponent = circuitJson.find(
158
+ (element) =>
159
+ element.type === "schematic_component" &&
160
+ element.source_component_id === "source_component_1",
161
+ )
162
+ expect(capacitorComponent).toMatchObject({
163
+ center: { x: 2, y: 0 },
164
+ size: { width: 0.9, height: 0.6 },
165
+ })
166
+ if (capacitorComponent?.type !== "schematic_component") {
167
+ throw new Error("Expected capacitor schematic component")
168
+ }
169
+ const ledComponent = circuitJson.find(
170
+ (element) =>
171
+ element.type === "schematic_component" &&
172
+ element.source_component_id === "source_component_2",
173
+ )
174
+ expect(ledComponent).toMatchObject({
175
+ center: { x: 4, y: 0 },
176
+ size: { width: 1.13, height: 0.65 },
177
+ symbol_name: "led_right",
178
+ })
179
+
180
+ const capacitorPorts = circuitJson
181
+ .filter(
182
+ (element): element is SchematicPort =>
183
+ element.type === "schematic_port" &&
184
+ element.schematic_component_id ===
185
+ capacitorComponent.schematic_component_id,
186
+ )
187
+ .sort((a, b) => a.center.y - b.center.y)
188
+ expect(capacitorPorts[0]!.center.y).toBeCloseTo(-0.3)
189
+ expect(capacitorPorts[1]!.center.y).toBeCloseTo(0.3)
190
+ expect(
191
+ circuitJson.filter((element) => element.type === "schematic_box"),
192
+ ).toHaveLength(1)
193
+ expect(
194
+ circuitJson.filter((element) => element.type === "schematic_net_label"),
195
+ ).toHaveLength(2)
196
+ expect(
197
+ circuitJson
198
+ .filter((element) => element.type === "schematic_net_label")
199
+ .map((element) => element.text),
200
+ ).toEqual(["CLK", "XXX"])
201
+
202
+ const schematicTraces = circuitJson.filter(
203
+ (element): element is SchematicTrace => element.type === "schematic_trace",
204
+ )
205
+ expect(schematicTraces).toHaveLength(1)
206
+ expect(schematicTraces[0]!.edges).toHaveLength(3)
207
+ expect(
208
+ circuitJson.find((element) => element.type === "source_trace"),
209
+ ).toMatchObject({ name: "ROUTED" })
210
+ expect(schematicTraces[0]!.edges).not.toContainEqual({
211
+ from: { x: 0.5, y: -0.2 },
212
+ to: { x: 2, y: -0.3 },
213
+ })
214
+
215
+ const svg = convertCircuitJsonToSchematicSvg(circuitJson)
216
+ expect(svg).toContain('data-circuit-json-type="schematic_component"')
217
+ expect(svg).toContain('data-circuit-json-type="schematic_trace"')
218
+ expect(svg).toContain('data-circuit-json-type="schematic_net_label"')
219
+ })