diff --git a/lib/components/base-components/Renderable.ts b/lib/components/base-components/Renderable.ts index 44152b2e4..668a3b242 100644 --- a/lib/components/base-components/Renderable.ts +++ b/lib/components/base-components/Renderable.ts @@ -48,6 +48,7 @@ export const orderedRenderPhases = [ "SchematicTraceRender", "SchematicSheetRender", "SchematicReplaceNetLabelsWithSymbols", + "SchematicLabelNetsWithConflictingNames", "PanelBoardLayout", "ValidatePcbCoordinates", "PcbComponentRender", @@ -107,6 +108,12 @@ const asyncPhaseDependencies: Partial> = { "PcbFootprintStringRender", "FetchPartFootprint", ], + SchematicLabelNetsWithConflictingNames: [ + "RenderIsolatedSubcircuits", + "PcbFootprintStringRender", + "FetchPartFootprint", + "SchematicTraceRender", + ], PcbFootprintLayout: ["PcbFootprintStringRender", "FetchPartFootprint"], PcbComponentSizeCalculation: [ "PcbFootprintStringRender", diff --git a/lib/components/primitive-components/Group/Group.ts b/lib/components/primitive-components/Group/Group.ts index a75da1a9d..7c50d5489 100644 --- a/lib/components/primitive-components/Group/Group.ts +++ b/lib/components/primitive-components/Group/Group.ts @@ -1,3 +1,4 @@ +import { assignSchematicNetLabelSuperscripts } from "lib/utils/schematic/assign-schematic-net-label-superscripts" import { type SimpleRouteJson as AutorouterSimpleRouteJson, type RerouteRectRegion, @@ -2726,6 +2727,18 @@ export class Group = typeof groupProps> Group_doInitialStandaloneSubcircuitPcbDesignRuleChecks(this) } + doInitialSchematicLabelNetsWithConflictingNames() { + if (this.root?.schematicDisabled) return + // Number networks once for the whole circuit, after every group's labels + // exist, rather than independently numbering sibling subcircuits. + if (this.getTopLevelRenderable() !== this) return + assignSchematicNetLabelSuperscripts(this.root!.db) + } + + updateSchematicLabelNetsWithConflictingNames() { + this.doInitialSchematicLabelNetsWithConflictingNames() + } + doInitialSchematicReplaceNetLabelsWithSymbols() { if (this.root?.schematicDisabled) return if (!this.isSubcircuit) return diff --git a/lib/utils/schematic/assign-schematic-net-label-superscripts.ts b/lib/utils/schematic/assign-schematic-net-label-superscripts.ts new file mode 100644 index 000000000..de8785d1c --- /dev/null +++ b/lib/utils/schematic/assign-schematic-net-label-superscripts.ts @@ -0,0 +1,85 @@ +import type { CircuitJsonUtilObjects } from "@tscircuit/circuit-json-util" +import type { SourceNet } from "circuit-json" +import { + type ConnectivityMap, + getFullConnectivityMapFromCircuitJson, +} from "circuit-json-to-connectivity-map" + +type NetName = SourceNet["name"] +type SourceNetworkId = keyof ConnectivityMap["netMap"] + +/** Assign display suffixes during SchematicLabelNetsWithConflictingNames. */ +export function assignSchematicNetLabelSuperscripts( + db: CircuitJsonUtilObjects, +) { + const labels = [ + ...db.schematic_net_label.list(), + ...db.schematic_text.list().filter((text) => text.source_trace_id), + ] + if (labels.length === 0) return + + // Source connectivity is authoritative; PCB routing must not join source nets. + const connMap = getFullConnectivityMapFromCircuitJson( + db.toArray().filter((element) => element.type.startsWith("source_")), + ) + // The full-map API omits standalone nets and standalone internal connections. + connMap.addConnections([ + ...db.source_net.list().map((net) => [net.source_net_id]), + ...db.source_component_internal_connection + .list() + .map((connection) => connection.source_port_ids), + ]) + + const labelsWithNetworks = labels.map((label) => { + const isNetLabel = label.type === "schematic_net_label" + const sourceTraceId = + label.source_trace_id ?? + (isNetLabel && label.schematic_trace_id + ? db.schematic_trace.get(label.schematic_trace_id)?.source_trace_id + : undefined) + const network = + (isNetLabel + ? connMap.getNetConnectedToId(label.source_net_id) + : undefined) ?? + (sourceTraceId ? connMap.getNetConnectedToId(sourceTraceId) : undefined) + return { label, network } + }) + + const networksByName = new Map() + const addName = (name: NetName, network: SourceNetworkId | undefined) => { + if (!name.trim() || network === undefined) return + const networks = networksByName.get(name) ?? [] + if (!networks.includes(network)) networks.push(network) + networksByName.set(name, networks) + } + // Only names displayed on multiple networks need disambiguation. + // Unused source-net declarations must not create a visible conflict. + for (const { label, network } of labelsWithNetworks) { + addName(label.text, network) + } + + // Member IDs keep numbering stable when Circuit JSON is reordered. + const firstSourceId = (network: SourceNetworkId) => + [...connMap.getIdsConnectedToNet(network)].sort()[0]! + for (const networks of networksByName.values()) { + networks.sort((a, b) => + firstSourceId(a).localeCompare(firstSourceId(b), "en", { numeric: true }), + ) + } + + for (const { label, network } of labelsWithNetworks) { + const networks = networksByName.get(label.text) ?? [] + const display_superscript = + network !== undefined && networks.length > 1 + ? String(networks.indexOf(network) + 1) + : undefined + if (label.display_superscript === display_superscript) continue + if (label.type === "schematic_net_label") { + db.schematic_net_label.update(label.schematic_net_label_id, { + display_superscript, + }) + } else { + db.schematic_text.update(label.schematic_text_id, { display_superscript }) + } + } +} diff --git a/package.json b/package.json index 2e13d4b95..23f4107cc 100644 --- a/package.json +++ b/package.json @@ -69,12 +69,12 @@ "bun-match-svg": "0.0.12", "calculate-elbow": "^0.0.12", "chokidar-cli": "^3.0.0", - "circuit-json": "^0.0.481", + "circuit-json": "^0.0.484", "circuit-json-to-bpc": "^0.0.13", "circuit-json-to-connectivity-map": "^0.0.30", "circuit-json-to-gltf": "^0.0.118", "circuit-json-to-spice": "^0.0.45", - "circuit-to-svg": "^0.0.412", + "circuit-to-svg": "^0.0.413", "concurrently": "^9.1.2", "connectivity-map": "^1.0.0", "debug": "^4.3.6", @@ -133,6 +133,6 @@ "overrides": { "@tscircuit/circuit-json-util": "^0.0.106", "@tscircuit/props": "^0.0.646", - "circuit-json": "^0.0.481" + "circuit-json": "^0.0.484" } } diff --git a/tests/components/__snapshots__/normal-components-two-chips-schematic.snap.svg b/tests/components/__snapshots__/normal-components-two-chips-schematic.snap.svg index 4849051ef..a21296a15 100644 --- a/tests/components/__snapshots__/normal-components-two-chips-schematic.snap.svg +++ b/tests/components/__snapshots__/normal-components-two-chips-schematic.snap.svg @@ -9,4 +9,4 @@ .port-label { fill: rgb(0, 100, 100); } .component-name { fill: rgb(0, 100, 100); } - 2,-22,-12,02,12,23,-23,-13,03,13,24,-24,-14,04,14,25,-25,-15,05,15,26,-26,-16,06,16,27,-27,-17,07,17,28,-28,-18,08,18,29,-29,-19,09,19,210,-210,-110,010,110,211,-211,-111,011,111,212,-212,-112,012,112,213,-213,-113,013,113,214,-214,-114,014,114,215,-215,-115,015,115,216,-216,-116,016,116,2U_A1IN_A2OUT_A3INTERNAL8GND4567U_B1IN_B2OUT_B3INTERNAL8GND4567GNDGNDEXTERNALINTERNALEXTERNALINTERNAL \ No newline at end of file + 2,-22,-12,02,12,23,-23,-13,03,13,24,-24,-14,04,14,25,-25,-15,05,15,26,-26,-16,06,16,27,-27,-17,07,17,28,-28,-18,08,18,29,-29,-19,09,19,210,-210,-110,010,110,211,-211,-111,011,111,212,-212,-112,012,112,213,-213,-113,013,113,214,-214,-114,014,114,215,-215,-115,015,115,216,-216,-116,016,116,2U_A1IN_A2OUT_A3INTERNAL8GND4567U_B1IN_B2OUT_B3INTERNAL8GND4567GNDGNDEXTERNALINTERNAL1EXTERNALINTERNAL2 \ No newline at end of file diff --git a/tests/components/base-components/schematic-label-nets-with-conflicting-names-phase.test.ts b/tests/components/base-components/schematic-label-nets-with-conflicting-names-phase.test.ts new file mode 100644 index 000000000..41628e165 --- /dev/null +++ b/tests/components/base-components/schematic-label-nets-with-conflicting-names-phase.test.ts @@ -0,0 +1,55 @@ +import { expect, test } from "bun:test" +import { + Renderable, + orderedRenderPhases, +} from "lib/components/base-components/Renderable" + +test("superscript phase waits for descendant label work and supports dirty updates", async () => { + let finishTraceRender!: () => void + const traceRenderFinished = new Promise((resolve) => { + finishTraceRender = resolve + }) + class AsyncLabels extends Renderable { + doInitialSchematicTraceRender() { + this._queueAsyncEffect("labels", () => traceRenderFinished) + } + } + class SuperscriptRoot extends Renderable { + initialCalls = 0 + updateCalls = 0 + doInitialSchematicLabelNetsWithConflictingNames() { + this.initialCalls++ + } + updateSchematicLabelNetsWithConflictingNames() { + this.updateCalls++ + } + } + const root = new SuperscriptRoot({}) + const child = new AsyncLabels({}) + root.children.push(child) + child.parent = root + root.runRenderCycle() + expect(root.initialCalls).toBe(0) + expect( + root.renderPhaseStates.SchematicLabelNetsWithConflictingNames.initialized, + ).toBe(false) + finishTraceRender() + await traceRenderFinished + await Promise.resolve() + root.runRenderCycle() + expect(root.initialCalls).toBe(1) + root.runRenderCycle() + expect(root.updateCalls).toBe(0) + child._markDirty("SourceTraceRender") + expect( + root.renderPhaseStates.SchematicLabelNetsWithConflictingNames.dirty, + ).toBe(true) + root.runRenderCycle() + expect(root.initialCalls).toBe(1) + expect(root.updateCalls).toBe(1) + expect( + orderedRenderPhases.indexOf("SchematicLabelNetsWithConflictingNames"), + ).toBeGreaterThan( + orderedRenderPhases.indexOf("SchematicReplaceNetLabelsWithSymbols"), + ) +}) diff --git a/tests/components/normal-components/chip-with-subcircuit-net-label.test.tsx b/tests/components/normal-components/chip-with-subcircuit-net-label.test.tsx index c055c7452..78e750f23 100644 --- a/tests/components/normal-components/chip-with-subcircuit-net-label.test.tsx +++ b/tests/components/normal-components/chip-with-subcircuit-net-label.test.tsx @@ -75,7 +75,23 @@ it("should keep local nets isolated between adjacent subcircuits", async () => { , ) - circuit.render() + await circuit.renderUntilSettled() + + const labels = [ + ...circuit.db.schematic_net_label.list(), + ...circuit.db.schematic_text.list(), + ] + expect( + labels + .filter((label) => label.text === "INTERNAL") + .map((label) => label.display_superscript) + .sort(), + ).toEqual(["1", "2"]) + expect( + labels + .filter((label) => label.text === "EXTERNAL" || label.text === "GND") + .every((label) => label.display_superscript === undefined), + ).toBe(true) expect(circuit.getCircuitJson()).toMatchSchematicSnapshot( import.meta.dir + "-two-chips", diff --git a/tests/features/schematic-net-superscripts/__snapshots__/connected-subcircuits-schematic.snap.svg b/tests/features/schematic-net-superscripts/__snapshots__/connected-subcircuits-schematic.snap.svg new file mode 100644 index 000000000..40d271cb4 --- /dev/null +++ b/tests/features/schematic-net-superscripts/__snapshots__/connected-subcircuits-schematic.snap.svg @@ -0,0 +1,12 @@ +-2,-4-2,-3-2,-2-2,-1-2,0-2,1-1,-4-1,-3-1,-2-1,-1-1,0-1,10,-40,-30,-20,-10,00,11,-41,-31,-21,-11,01,12,-42,-32,-22,-12,02,13,-43,-33,-23,-13,03,14,-44,-34,-24,-14,04,15,-45,-35,-25,-15,05,16,-46,-36,-26,-16,06,17,-47,-37,-27,-17,07,18,-48,-38,-28,-18,08,19,-49,-39,-29,-19,09,1R11kΩR21kΩR31kΩGND1GND1GND2 \ No newline at end of file diff --git a/tests/features/schematic-net-superscripts/__snapshots__/disconnected-subcircuits-schematic.snap.svg b/tests/features/schematic-net-superscripts/__snapshots__/disconnected-subcircuits-schematic.snap.svg new file mode 100644 index 000000000..726d7ea9d --- /dev/null +++ b/tests/features/schematic-net-superscripts/__snapshots__/disconnected-subcircuits-schematic.snap.svg @@ -0,0 +1,26 @@ +-6,-6-6,-5-6,-4-6,-3-6,-2-6,-1-6,0-6,1-5,-6-5,-5-5,-4-5,-3-5,-2-5,-1-5,0-5,1-4,-6-4,-5-4,-4-4,-3-4,-2-4,-1-4,0-4,1-3,-6-3,-5-3,-4-3,-3-3,-2-3,-1-3,0-3,1-2,-6-2,-5-2,-4-2,-3-2,-2-2,-1-2,0-2,1-1,-6-1,-5-1,-4-1,-3-1,-2-1,-1-1,0-1,10,-60,-50,-40,-30,-20,-10,00,11,-61,-51,-41,-31,-21,-11,01,12,-62,-52,-42,-32,-22,-12,02,13,-63,-53,-43,-33,-23,-13,03,14,-64,-54,-44,-34,-24,-14,04,15,-65,-55,-45,-35,-25,-15,05,16,-66,-56,-46,-36,-26,-16,06,17,-67,-57,-47,-37,-27,-17,07,1R11kΩR22kΩR31kΩR42kΩGND1UNIQUE_AGND2UNIQUE_BSIGNAL1SIGNAL1SIGNAL2SIGNAL2 \ No newline at end of file diff --git a/tests/features/schematic-net-superscripts/__snapshots__/named-traces-schematic.snap.svg b/tests/features/schematic-net-superscripts/__snapshots__/named-traces-schematic.snap.svg new file mode 100644 index 000000000..d20a73d38 --- /dev/null +++ b/tests/features/schematic-net-superscripts/__snapshots__/named-traces-schematic.snap.svg @@ -0,0 +1,12 @@ +-4,-5-4,-4-4,-3-4,-2-4,-1-4,0-4,1-3,-5-3,-4-3,-3-3,-2-3,-1-3,0-3,1-2,-5-2,-4-2,-3-2,-2-2,-1-2,0-2,1-1,-5-1,-4-1,-3-1,-2-1,-1-1,0-1,10,-50,-40,-30,-20,-10,00,11,-51,-41,-31,-21,-11,01,12,-52,-42,-32,-22,-12,02,13,-53,-43,-33,-23,-13,03,14,-54,-44,-34,-24,-14,04,1R11kΩR22kΩR31kΩR42kΩBUS1BUS2 \ No newline at end of file diff --git a/tests/features/schematic-net-superscripts/__snapshots__/source-connectivity.snap.svg b/tests/features/schematic-net-superscripts/__snapshots__/source-connectivity.snap.svg new file mode 100644 index 000000000..30a89fc9a --- /dev/null +++ b/tests/features/schematic-net-superscripts/__snapshots__/source-connectivity.snap.svg @@ -0,0 +1,33 @@ +GND1GND1GND2GND1GND1GND2GNDnote \ No newline at end of file diff --git a/tests/features/schematic-net-superscripts/connected-subcircuits.test.tsx b/tests/features/schematic-net-superscripts/connected-subcircuits.test.tsx new file mode 100644 index 000000000..df7caa99b --- /dev/null +++ b/tests/features/schematic-net-superscripts/connected-subcircuits.test.tsx @@ -0,0 +1,48 @@ +import type { SourceNet } from "circuit-json" +import { expect, test } from "bun:test" +import { getTestFixture } from "tests/fixtures/get-test-fixture" + +test("connected same-name nets share one superscript and lose it when all networks join", async () => { + const { circuit } = getTestFixture({ platform: { pcbDisabled: true } }) + circuit.add( + + {["A", "B", "C"].map((name, index) => ( + + + + + ))} + + , + ) + await circuit.renderUntilSettled() + const nets = circuit.db.source_net.list().filter((net) => net.name === "GND") + expect(nets).toHaveLength(3) + const suffixForNet = (netId: SourceNet["source_net_id"]) => + circuit.db.schematic_net_label + .list() + .find((label) => label.source_net_id === netId)?.display_superscript + expect(suffixForNet(nets[0]!.source_net_id)).toBe("1") + expect(suffixForNet(nets[1]!.source_net_id)).toBe("1") + expect(suffixForNet(nets[2]!.source_net_id)).toBe("2") + expect(circuit).toMatchSchematicSnapshot(import.meta.path) + + // A direct database edit must dirty the phase that consumes the new data. + circuit.db.source_trace.insert({ + connected_source_net_ids: nets.map((net) => net.source_net_id), + connected_source_port_ids: [], + }) + circuit.firstChild!._markDirty("SchematicLabelNetsWithConflictingNames") + circuit.render() + expect( + circuit.db.schematic_net_label + .list() + .filter((label) => label.text === "GND") + .every((label) => label.display_superscript === undefined), + ).toBe(true) +}) diff --git a/tests/features/schematic-net-superscripts/disconnected-subcircuits.test.tsx b/tests/features/schematic-net-superscripts/disconnected-subcircuits.test.tsx new file mode 100644 index 000000000..f0d5b3962 --- /dev/null +++ b/tests/features/schematic-net-superscripts/disconnected-subcircuits.test.tsx @@ -0,0 +1,73 @@ +import { expect, test } from "bun:test" +import { getTestFixture } from "tests/fixtures/get-test-fixture" + +test("disconnected same-name nets get stable superscripts on regular and inline labels", async () => { + const { circuit } = getTestFixture({ platform: { pcbDisabled: true } }) + circuit.add( + + {["A", "B"].map((name, index) => ( + + + + + + + + + ))} + , + ) + let suffixesAtPhaseEnd: Array = [] + circuit.on("renderable:renderLifecycle:anyEvent", (event) => { + if ( + event.type === + "renderable:renderLifecycle:SchematicLabelNetsWithConflictingNames:end" && + event.renderId === circuit.firstChild!._renderId + ) { + suffixesAtPhaseEnd = circuit.db.schematic_net_label + .list() + .filter((label) => label.text === "GND") + .map((label) => label.display_superscript) + } + }) + await circuit.renderUntilSettled() + expect(new Set(suffixesAtPhaseEnd)).toEqual(new Set(["1", "2"])) + + const groundLabels = circuit.db.schematic_net_label + .list() + .filter((label) => label.text === "GND") + const signalLabels = circuit.db.schematic_text + .list() + .filter((label) => label.text === "SIGNAL") + expect( + new Set(groundLabels.map((label) => label.display_superscript)), + ).toEqual(new Set(["1", "2"])) + expect( + new Set(signalLabels.map((label) => label.display_superscript)), + ).toEqual(new Set(["1", "2"])) + expect( + circuit.db.schematic_net_label + .list() + .filter((label) => label.text.startsWith("UNIQUE_")) + .every((label) => label.display_superscript === undefined), + ).toBe(true) + const before = [...groundLabels, ...signalLabels].map( + (label) => label.display_superscript, + ) + circuit.render() + expect( + [ + ...circuit.db.schematic_net_label + .list() + .filter((label) => label.text === "GND"), + ...circuit.db.schematic_text + .list() + .filter((label) => label.text === "SIGNAL"), + ].map((label) => label.display_superscript), + ).toEqual(before) + expect(circuit).toMatchSchematicSnapshot(import.meta.path) +}) diff --git a/tests/features/schematic-net-superscripts/named-traces.test.tsx b/tests/features/schematic-net-superscripts/named-traces.test.tsx new file mode 100644 index 000000000..f47d78276 --- /dev/null +++ b/tests/features/schematic-net-superscripts/named-traces.test.tsx @@ -0,0 +1,38 @@ +import { expect, test } from "bun:test" +import { getTestFixture } from "tests/fixtures/get-test-fixture" + +test("inline names on disconnected traces are disambiguated without source nets", async () => { + const { circuit } = getTestFixture({ platform: { pcbDisabled: true } }) + circuit.add( + + {["A", "B"].map((name, index) => ( + + + + + + ))} + , + ) + await circuit.renderUntilSettled() + expect(circuit.db.source_net.list()).toHaveLength(0) + const labels = circuit.db.schematic_text + .list() + .filter((text) => text.text === "BUS") + expect(labels).toHaveLength(2) + expect(labels.map((label) => label.display_superscript).sort()).toEqual([ + "1", + "2", + ]) + expect( + circuit.db.schematic_text + .list() + .filter((text) => !text.source_trace_id) + .every((text) => text.display_superscript === undefined), + ).toBe(true) + expect(circuit).toMatchSchematicSnapshot(import.meta.path) +}) diff --git a/tests/features/schematic-net-superscripts/source-connectivity.test.ts b/tests/features/schematic-net-superscripts/source-connectivity.test.ts new file mode 100644 index 000000000..35423d377 --- /dev/null +++ b/tests/features/schematic-net-superscripts/source-connectivity.test.ts @@ -0,0 +1,109 @@ +import type { AnyCircuitElement } from "circuit-json" +import { expect, test } from "bun:test" +import { cju } from "@tscircuit/circuit-json-util" +import { convertCircuitJsonToSchematicSvg } from "circuit-to-svg" +import { assignSchematicNetLabelSuperscripts } from "lib/utils/schematic/assign-schematic-net-label-superscripts" + +test("internal connections, mixed label kinds, and reordered source JSON use the same network numbering", () => { + const circuitJson: AnyCircuitElement[] = [] + for (const [index, id] of ["a", "b", "c"].entries()) { + circuitJson.push({ + type: "source_net", + source_net_id: `net_${id}`, + name: "GND", + member_source_group_ids: [], + subcircuit_id: id, + subcircuit_connectivity_map_key: "same_scoped_key", + }) + circuitJson.push({ + type: "source_trace", + source_trace_id: `trace_${id}`, + connected_source_net_ids: [`net_${id}`], + connected_source_port_ids: [`port_${id}`], + }) + circuitJson.push({ + type: "schematic_net_label", + schematic_net_label_id: `label_${id}`, + source_net_id: `net_${id}`, + text: "GND", + center: { x: index * 2, y: 0 }, + anchor_position: { x: index * 2, y: 0 }, + anchor_side: "left", + }) + circuitJson.push({ + type: "schematic_text", + schematic_text_id: `inline_${id}`, + font_size: 0.18, + rotation: 0, + color: "black", + source_trace_id: `trace_${id}`, + text: "GND", + position: { x: index * 2, y: -1 }, + anchor: "left", + }) + } + circuitJson.push({ + type: "source_component_internal_connection", + source_component_internal_connection_id: "internal_connection", + source_component_id: "chip", + source_port_ids: ["port_a", "port_bridge"], + }) + circuitJson.push({ + type: "source_component", + source_component_id: "chip", + name: "U1", + ftype: "simple_chip", + internally_connected_source_port_ids: [["port_bridge", "port_b"]], + }) + circuitJson.push({ + type: "schematic_text", + schematic_text_id: "ordinary_text", + font_size: 0.18, + rotation: 0, + color: "black", + anchor: "left", + text: "GND", + display_superscript: "note", + position: { x: 0, y: -2 }, + }) + const db = cju(circuitJson) + assignSchematicNetLabelSuperscripts(db) + expect( + db.schematic_net_label.list().map((label) => label.display_superscript), + ).toEqual(["1", "1", "2"]) + expect( + db.schematic_text.list().map((label) => label.display_superscript), + ).toEqual(["1", "1", "2", "note"]) + const reversed = cju(db.toArray().toReversed()) + assignSchematicNetLabelSuperscripts(reversed) + expect( + reversed.schematic_net_label + .list() + .map((label) => label.display_superscript), + ).toEqual(["2", "1", "1"]) + expect( + reversed.schematic_text.get("ordinary_text")!.display_superscript, + ).toBe("note") + expect(convertCircuitJsonToSchematicSvg(db.toArray())).toMatchSvgSnapshot( + import.meta.path, + ) + db.source_trace.insert({ + connected_source_net_ids: ["net_b", "net_c"], + connected_source_port_ids: [], + }) + assignSchematicNetLabelSuperscripts(db) + expect( + db.schematic_net_label + .list() + .every((label) => label.display_superscript === undefined), + ).toBe(true) + expect( + db.schematic_text + .list() + .filter((label) => label.source_trace_id) + .every((label) => label.display_superscript === undefined), + ).toBe(true) + expect(db.schematic_text.get("ordinary_text")!.display_superscript).toBe( + "note", + ) +}) diff --git a/tests/features/subcircuit-circuit-json/__snapshots__/subcircuit-circuit-json14-schematic.snap.svg b/tests/features/subcircuit-circuit-json/__snapshots__/subcircuit-circuit-json14-schematic.snap.svg index e4711a335..c08363613 100644 --- a/tests/features/subcircuit-circuit-json/__snapshots__/subcircuit-circuit-json14-schematic.snap.svg +++ b/tests/features/subcircuit-circuit-json/__snapshots__/subcircuit-circuit-json14-schematic.snap.svg @@ -1,4 +1,4 @@ - \ No newline at end of file diff --git a/tests/features/subcircuit-circuit-json/subcircuit-circuit-json14.test.tsx b/tests/features/subcircuit-circuit-json/subcircuit-circuit-json14.test.tsx index 3a05bb3a6..a3a2f4ff5 100644 --- a/tests/features/subcircuit-circuit-json/subcircuit-circuit-json14.test.tsx +++ b/tests/features/subcircuit-circuit-json/subcircuit-circuit-json14.test.tsx @@ -70,6 +70,25 @@ test("subcircuit-circuit-json14 - subcircuit name prop being passed to the chip const pcbTrace = circuit.db.pcb_trace.list() expect(pcbTrace).toHaveLength(2) + // Only the exposed I2C nets are joined; local supply nets stay separate. + const labels = circuit.db.schematic_net_label.list() + for (const name of ["GND", "VCC"]) { + expect( + new Set( + labels + .filter((label) => label.text === name) + .map((label) => label.display_superscript), + ), + ).toEqual(new Set(["1", "2"])) + } + expect( + labels + .filter( + (label) => label.text.includes("SDA") || label.text.includes("SCL"), + ) + .every((label) => label.display_superscript === undefined), + ).toBe(true) + expect(circuit).toMatchPcbSnapshot(import.meta.path) expect(circuit).toMatchSchematicSnapshot(import.meta.path) }) diff --git a/tests/projects/rp2040/__snapshots__/index-schematic.snap.svg b/tests/projects/rp2040/__snapshots__/index-schematic.snap.svg index 0b198a853..836a9dfe5 100644 --- a/tests/projects/rp2040/__snapshots__/index-schematic.snap.svg +++ b/tests/projects/rp2040/__snapshots__/index-schematic.snap.svg @@ -1,4 +1,4 @@ -