diff --git a/lib/schemas/package-detail-shape-schema.ts b/lib/schemas/package-detail-shape-schema.ts index 852f89b6..8e0e7134 100644 --- a/lib/schemas/package-detail-shape-schema.ts +++ b/lib/schemas/package-detail-shape-schema.ts @@ -13,11 +13,14 @@ const safeNumber = (defaultValue = 0) => const tenthmil = z .union([z.number(), z.string()]) .optional() - .transform((n) => - typeof n === "string" && n.endsWith("mil") - ? n - : `${Number.parseFloat(n as string) * 10}mil`, - ) + .transform((n) => { + if (typeof n === "string" && n.endsWith("mil")) return n + // parseFloat(undefined)/non-numeric input is NaN, which previously produced + // the nonsensical unit string "NaNmil" (and later "NaNmm" in output). Fall + // back to 0, matching the safeNumber(0) convention above. + const parsed = Number.parseFloat(n as string) + return `${(Number.isNaN(parsed) ? 0 : parsed) * 10}mil` + }) .pipe(z.string()) export const PointSchema = z diff --git a/tests/parse-tests/pad-tenthmil-nan.test.ts b/tests/parse-tests/pad-tenthmil-nan.test.ts new file mode 100644 index 00000000..6dfc3540 --- /dev/null +++ b/tests/parse-tests/pad-tenthmil-nan.test.ts @@ -0,0 +1,42 @@ +import { it, expect } from "bun:test" +import { PadSchema } from "lib/schemas/package-detail-shape-schema" + +const basePad = { + type: "PAD" as const, + shape: "ELLIPSE" as const, + center: { x: 100, y: 200 }, + width: 60, + height: 60, + layermask: 1, + number: 1, + plated: false, +} + +it("does not emit NaNmil when an optional tenthmil field is missing", () => { + // A short/variant EasyEDA pad string can leave holeRadius (or a later field) + // undefined. tenthmil must not turn that into the nonsensical unit "NaNmil", + // which otherwise surfaces as "NaNmm" in the generated component. + const pad = PadSchema.parse({ ...basePad }) // holeRadius omitted -> undefined + expect(pad.holeRadius).toBe("0mil") + for (const v of [ + pad.center.x, + pad.center.y, + pad.width, + pad.height, + pad.holeRadius, + ]) { + expect(String(v)).not.toContain("NaN") + } +}) + +it("still converts present tenthmil values (bare number => mil*10, unit string passes through)", () => { + const pad = PadSchema.parse({ + ...basePad, + width: 60, + height: "40", + holeRadius: "5mil", + }) + expect(pad.width).toBe("600mil") // 60 * 10 + expect(pad.height).toBe("400mil") // "40" -> 40 * 10 + expect(pad.holeRadius).toBe("5mil") // already has a unit, passed through +})