From d5a7d50f8f99398d833a6c9f6d9d8494962fe17a Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 9 May 2026 10:05:20 -0400 Subject: [PATCH 1/2] Restore legacy colors.blue/colors.success and add consumer-types harness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adversarial review of the merged 0.8.x line surfaced three real follow-ups: 1. The `/legacy` shim's `colors` was missing `blue` (Tailwind sky 50–900) and `success` (#22C55E) that @policyengine/design-system 0.2.0/0.3.0 shipped. The snapshot copied into src/legacy/ for 0.8.0 came from a later workspace build that had already dropped both. Two consumer migrations (PolicyEngine/cbo-baseline-tracker#3, PolicyEngine/uk-spring-statement-2026#22) had to backfill the missing values locally — the canary that the shim wasn't a true 1:1 mirror. Restored under "Semantic colors" / "Blue accent palette" with a comment noting the migration story. 2. The migration JSDoc in src/legacy/index.ts told consumers to map `colors.gray[N]` → `palette.gray[N]` and `colors.text.warning` → `rootColorsLight['--text-warning']` without flagging that both silently change visible hex values (legacy gray is Tailwind-3 #6B7280 etc.; canonical is Slate #64748B etc. — and `--text-warning` was darkened from Mantine orange.9 to Tailwind orange-700 in 0.6.0 for WCAG AA). Annotated each pair as same-hex or value-shifting so bulk sed-replace doesn't silently regress consumers. 3. The bundler-resolution drop fixed in #29 / #30 (dist/.js shadowing dist//index.d.ts under moduleResolution: "bundler") was masked because nothing in this repo type-checked the package as an external consumer. Added tests/consumer-types/ with a fixture exercising the main entry, the legacy/ subpath, and per-feature subpaths, plus a tsconfig with paths to dist/ and a vitest spawn of tsc --noEmit. CI now runs `bun run build` before `bun run test` so the harness sees fresh dist/ output. Legacy color tests pin colors.blue[50/500/600/900] and colors.success exactly so a future shim regression fails locally instead of in 18+ consumers. 295 tests pass (was 293, +2 for blue/success). Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/pr.yaml | 11 +- changelog.d/consumer-types-harness.added.md | 1 + .../legacy-blue-success-restored.fixed.md | 1 + .../legacy-migration-map-clarity.changed.md | 1 + src/legacy/index.ts | 37 +++- src/legacy/tokens/colors.ts | 19 ++ tests/consumer-types/fixture.ts | 177 ++++++++++++++++++ tests/consumer-types/tsconfig.json | 29 +++ tests/consumer-types/typecheck.test.ts | 66 +++++++ tests/legacy/colors.test.ts | 31 ++- 10 files changed, 360 insertions(+), 13 deletions(-) create mode 100644 changelog.d/consumer-types-harness.added.md create mode 100644 changelog.d/legacy-blue-success-restored.fixed.md create mode 100644 changelog.d/legacy-migration-map-clarity.changed.md create mode 100644 tests/consumer-types/fixture.ts create mode 100644 tests/consumer-types/tsconfig.json create mode 100644 tests/consumer-types/typecheck.test.ts diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 70f1bce..5d19f9e 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -30,8 +30,13 @@ jobs: - name: Install dependencies run: bun install --frozen-lockfile - - name: Run tests - run: bun run test - + # Build first so the consumer-types harness in tests/consumer-types/ + # can type-check the dist/ surface a real consumer sees. With this + # order the harness will fail loudly on regressions like the + # bundler-resolution drop fixed in 0.8.1/0.8.2; flipped (test before + # build), the harness silently skips. - name: Build package run: bun run build + + - name: Run tests + run: bun run test diff --git a/changelog.d/consumer-types-harness.added.md b/changelog.d/consumer-types-harness.added.md new file mode 100644 index 0000000..ac3f570 --- /dev/null +++ b/changelog.d/consumer-types-harness.added.md @@ -0,0 +1 @@ +Consumer-style typecheck harness (`tests/consumer-types/`). Type-checks a representative consumer fixture against the *built* `dist/` surface using `moduleResolution: "bundler"`, so any regression on the export shape of the main entry, the `legacy/` subpath, or the per-feature subpaths fails CI loudly. Catches the silent `dist/.js`-shadows-`dist//index.d.ts` resolution failure that 0.8.0/0.8.1 shipped before being fixed in 0.8.1/0.8.2. The PR check workflow now runs `bun run build` before `bun run test` so the harness exercises freshly-built artifacts. diff --git a/changelog.d/legacy-blue-success-restored.fixed.md b/changelog.d/legacy-blue-success-restored.fixed.md new file mode 100644 index 0000000..35e7a65 --- /dev/null +++ b/changelog.d/legacy-blue-success-restored.fixed.md @@ -0,0 +1 @@ +`@policyengine/ui-kit/legacy` now exposes `colors.blue` (Tailwind sky 50–900) and `colors.success` (`#22C55E`), restoring parity with `@policyengine/design-system` 0.2.0/0.3.0. The snapshot copied into `src/legacy/` for 0.8.0 came from a later workspace build that had dropped both, forcing cbo-baseline-tracker and uk-spring-statement-2026 to backfill them locally. The legacy color tests now pin both values so future regressions fail CI. diff --git a/changelog.d/legacy-migration-map-clarity.changed.md b/changelog.d/legacy-migration-map-clarity.changed.md new file mode 100644 index 0000000..4bac019 --- /dev/null +++ b/changelog.d/legacy-migration-map-clarity.changed.md @@ -0,0 +1 @@ +JSDoc migration map in `src/legacy/index.ts` now flags which design-system → ui-kit mappings preserve hex values (most) and which shift them (`colors.gray[N]` → `palette.gray[N]` is Tailwind-3 → Slate; `colors.text.warning` → `--text-warning` is Mantine orange.9 → Tailwind orange-700, the latter for WCAG AA). Bulk `sed`-replace from design-system to canonical ui-kit names is unsafe for those two pairs without a visual review. diff --git a/src/legacy/index.ts b/src/legacy/index.ts index f1df1dc..c7916c8 100644 --- a/src/legacy/index.ts +++ b/src/legacy/index.ts @@ -14,16 +14,35 @@ * - import … from '@policyengine/design-system/charts' → '@policyengine/ui-kit/legacy/charts' * - import … from '@policyengine/design-system/tokens/colors' → '@policyengine/ui-kit/legacy/tokens/colors' * - * Mapping to canonical ui-kit exports for net-new code: + * Mapping to canonical ui-kit exports for net-new code. ⚠ Several mappings + * shift visible color values (usually for WCAG accessibility). Don't bulk + * `sed`-replace — pick per usage: * - * colors.primary[N] → palette.teal[N] - * colors.gray[N] → palette.gray[N] - * colors.warning → semanticFills.warning - * colors.error → semanticFills.error - * colors.text.warning → rootColorsLight['--text-warning'] (or `var(--text-warning)`) - * typography.fontFamily.primary → typography.fontFamily.sans - * spacing.{layout,…} → namedSpacing (only `header`, `sidebar`, `content` exposed today) - * chartColors / chartLayout → see charts/chartDefaults.ts (Recharts) or chartPalette (resolved hex) + * colors.primary[N] → palette.teal[N] (same hex) + * colors.gray[N] → palette.gray[N] (DIFFERENT hex — + * legacy is Tailwind-3 + * gray, canonical is + * Slate-flavored. e.g. + * legacy gray.500 + * #6B7280 vs canonical + * gray.500 #64748B) + * colors.blue[N] → palette.blue[N] (same hex) + * colors.warning → semanticFills.warning (same: #FEC601) + * colors.error → semanticFills.error (same: #EF4444) + * colors.success → semanticFills.success (same: #22C55E) + * colors.text.warning → rootColorsLight['--text-warning'] (DIFFERENT hex — + * legacy #d9480f + * fails WCAG AA at + * small text; + * canonical #c2410c + * clears 5.18:1) + * typography.fontFamily.primary → typography.fontFamily.sans (same stack) + * spacing.{layout,…} → namedSpacing (only `header`, + * `sidebar`, `content` + * exposed today — + * scale values aren't) + * chartColors / chartLayout → see charts/chartDefaults.ts (Recharts) or chartPalette + * (resolved hex) * * This module will be removed in a future major release once consumers migrate. */ diff --git a/src/legacy/tokens/colors.ts b/src/legacy/tokens/colors.ts index eae21e2..c91517c 100644 --- a/src/legacy/tokens/colors.ts +++ b/src/legacy/tokens/colors.ts @@ -39,10 +39,29 @@ export const colors = { }, // Semantic colors + success: "#22C55E", warning: "#FEC601", error: "#EF4444", info: "#2C7A7B", + // Blue accent palette — restored from @policyengine/design-system 0.2.0/0.3.0. + // The snapshot copied into legacy/ in ui-kit 0.8.0 came from a later workspace + // build that had dropped this; consumer migrations from the published 0.3.x + // were silently losing colors.blue, forcing local backfills in + // cbo-baseline-tracker and uk-spring-statement-2026. + blue: { + 50: "#F0F9FF", + 100: "#E0F2FE", + 200: "#BAE6FD", + 300: "#7DD3FC", + 400: "#38BDF8", + 500: "#0EA5E9", + 600: "#0284C7", + 700: "#026AA2", + 800: "#075985", + 900: "#0C4A6E", + }, + // Neutral colors white: "#FFFFFF", black: "#000000", diff --git a/tests/consumer-types/fixture.ts b/tests/consumer-types/fixture.ts new file mode 100644 index 0000000..7521c3c --- /dev/null +++ b/tests/consumer-types/fixture.ts @@ -0,0 +1,177 @@ +/** + * Consumer-style import surface used by the typecheck harness in + * `tests/consumer-types/typecheck.test.ts`. Mirrors what real consumers + * write — the harness type-checks this file against the *built* package + * (via path mappings to dist/), so any regression that drops symbols from + * the main entry, the legacy/ subpath, or the per-feature subpaths fails + * the test loudly instead of silently shipping to consumers. + * + * If you add a new top-level export to ui-kit, add a use of it here too — + * otherwise the test won't catch a regression on it. + */ + +// Main entry — primitives, layout, charts, visualization, theme, utils +import { + // Primitives — main offenders for the dist/.js vs dist//index.d.ts + // resolution bug, kept in alphabetical order to make additions easy + Accordion, + Alert, + Badge, + Button, + Card, + Checkbox, + Collapsible, + Container, + Dialog, + DropdownMenu, + Input, + Label, + Popover, + Progress, + RadioGroup, + ScrollArea, + Select, + Separator, + Sheet, + Skeleton, + Spinner, + Switch, + Tabs, + Text, + Textarea, + Title, + Tooltip, + // Layout + DashboardShell, + Header, + Footer, + Stack, + Group, + // Inputs + CurrencyInput, + NumberInput, + // Display + DataTable, + MetricCard, + // Charts + ChartContainer, + PEBarChart, + PELineChart, + PEAreaChart, + PEWaterfallChart, + // Tokens (runtime) + palette, + semanticFills, + typography, + namedSpacing, + chartPalette, + rootColorsLight, + rootColorsDark, + // Utilities + cn, + formatCurrency, + formatPercent, + getNiceTicks, + // Assets + logos, +} from "@policyengine/ui-kit"; + +// Legacy compat — design-system migration target +import { + colors as legacyColors, + typography as legacyTypography, + spacing as legacySpacing, + chartColors as legacyChartColors, +} from "@policyengine/ui-kit/legacy"; + +// Legacy subpath — explicit per-module resolution +import { colors as legacyColors2 } from "@policyengine/ui-kit/legacy/tokens"; +import { colors as legacyColors3 } from "@policyengine/ui-kit/legacy/tokens/colors"; +import { typography as legacyTypography2 } from "@policyengine/ui-kit/legacy/tokens/typography"; +import { spacing as legacySpacing2 } from "@policyengine/ui-kit/legacy/tokens/spacing"; +import { chartColors as legacyChartColors2 } from "@policyengine/ui-kit/legacy/charts"; + +// Per-feature subpaths — used by consumers that want narrow imports +import { Badge as Badge2 } from "@policyengine/ui-kit/primitives"; +import { Container as Container2 } from "@policyengine/ui-kit/layout"; +import { ChartContainer as ChartContainer2 } from "@policyengine/ui-kit/charts"; + +// Specific properties consumers depend on — separate use site so a missing +// value (e.g. `colors.blue`/`colors.success` going missing in the legacy +// shim, which forced two consumer migrations to add local backfills) gets +// caught even though the top-level `colors` import already type-checks. +export const _LegacyColorPaths = { + bluePalette: legacyColors.blue, // restored in 0.9.0; was missing in 0.8.x + successScalar: legacyColors.success, // ditto + textWarning: legacyColors.text.warning, + primaryBrand: legacyColors.primary[500], + grayMid: legacyColors.gray[500], +}; + +// Touch each binding so unused-import settings don't strip them. +export type _SmokeTest = + | typeof Accordion + | typeof Alert + | typeof Badge + | typeof Button + | typeof Card + | typeof Checkbox + | typeof Collapsible + | typeof Container + | typeof Dialog + | typeof DropdownMenu + | typeof Input + | typeof Label + | typeof Popover + | typeof Progress + | typeof RadioGroup + | typeof ScrollArea + | typeof Select + | typeof Separator + | typeof Sheet + | typeof Skeleton + | typeof Spinner + | typeof Switch + | typeof Tabs + | typeof Text + | typeof Textarea + | typeof Title + | typeof Tooltip + | typeof DashboardShell + | typeof Header + | typeof Footer + | typeof Stack + | typeof Group + | typeof CurrencyInput + | typeof NumberInput + | typeof DataTable + | typeof MetricCard + | typeof ChartContainer + | typeof PEBarChart + | typeof PELineChart + | typeof PEAreaChart + | typeof PEWaterfallChart + | typeof palette + | typeof semanticFills + | typeof typography + | typeof namedSpacing + | typeof chartPalette + | typeof rootColorsLight + | typeof rootColorsDark + | typeof cn + | typeof formatCurrency + | typeof formatPercent + | typeof getNiceTicks + | typeof logos + | typeof legacyColors + | typeof legacyTypography + | typeof legacySpacing + | typeof legacyChartColors + | typeof legacyColors2 + | typeof legacyColors3 + | typeof legacyTypography2 + | typeof legacySpacing2 + | typeof legacyChartColors2 + | typeof Badge2 + | typeof Container2 + | typeof ChartContainer2; diff --git a/tests/consumer-types/tsconfig.json b/tests/consumer-types/tsconfig.json new file mode 100644 index 0000000..dcdd678 --- /dev/null +++ b/tests/consumer-types/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true, + "isolatedModules": true, + "types": [], + "baseUrl": "../..", + "paths": { + "@policyengine/ui-kit": ["./dist/index.d.ts"], + "@policyengine/ui-kit/legacy": ["./dist/legacy/index.d.ts"], + "@policyengine/ui-kit/legacy/tokens": ["./dist/legacy/tokens/index.d.ts"], + "@policyengine/ui-kit/legacy/tokens/colors": ["./dist/legacy/tokens/colors.d.ts"], + "@policyengine/ui-kit/legacy/tokens/typography": ["./dist/legacy/tokens/typography.d.ts"], + "@policyengine/ui-kit/legacy/tokens/spacing": ["./dist/legacy/tokens/spacing.d.ts"], + "@policyengine/ui-kit/legacy/charts": ["./dist/legacy/charts/index.d.ts"], + "@policyengine/ui-kit/primitives": ["./dist/primitives/index.d.ts"], + "@policyengine/ui-kit/layout": ["./dist/layout/index.d.ts"], + "@policyengine/ui-kit/charts": ["./dist/charts/index.d.ts"] + } + }, + "include": ["fixture.ts"] +} diff --git a/tests/consumer-types/typecheck.test.ts b/tests/consumer-types/typecheck.test.ts new file mode 100644 index 0000000..f70753f --- /dev/null +++ b/tests/consumer-types/typecheck.test.ts @@ -0,0 +1,66 @@ +import * as fs from "node:fs"; +import * as path from "node:path"; +import { execFileSync } from "node:child_process"; +import { describe, expect, it } from "vitest"; + +/** + * Consumer-style typecheck harness. + * + * Real consumers see ui-kit through `package.json` `exports`, with + * `moduleResolution: "bundler"` (Next.js, Vite, anything modern). When + * `dist/.js` and `dist//index.d.ts` coexist, TypeScript's + * bundler resolver historically prefers the file (no types) and silently + * drops every `export *` symbol — see PR #29 and PR #30. This harness + * type-checks `tests/consumer-types/fixture.ts` against the *built* + * package via `paths` mappings to `dist/`, so any regression on that + * resolution path fails CI loudly instead of in 36 downstream consumer + * repos a release later. + * + * Run after `bun run build`. The harness skips with an actionable message + * when `dist/` is missing. + */ + +const ROOT = path.resolve(__dirname, "..", ".."); +const TS_BIN = path.join(ROOT, "node_modules", ".bin", "tsc"); +const FIXTURE_TSCONFIG = path.join(__dirname, "tsconfig.json"); +const DIST_INDEX = path.join(ROOT, "dist", "index.d.ts"); + +// Skip the harness when dist/ is missing so a fresh `bun run test` doesn't +// fail before `bun run build` ever runs. CI runs build before tests; local +// runs typically already have dist/ from a prior build cycle. +const distAvailable = fs.existsSync(DIST_INDEX); + +describe.skipIf(!distAvailable)("consumer-style type resolution", () => { + it("main + legacy + per-feature subpaths all type-check from a bundler-resolution consumer", () => { + let stdout = ""; + let stderr = ""; + let exitCode = 0; + try { + stdout = execFileSync(TS_BIN, ["--noEmit", "-p", FIXTURE_TSCONFIG], { + cwd: ROOT, + encoding: "utf8", + stdio: ["ignore", "pipe", "pipe"], + }); + } catch (err) { + // execFileSync throws on non-zero exit; capture output for the assertion. + const e = err as NodeJS.ErrnoException & { + stdout?: Buffer | string; + stderr?: Buffer | string; + status?: number; + }; + stdout = e.stdout?.toString() ?? ""; + stderr = e.stderr?.toString() ?? ""; + exitCode = e.status ?? 1; + } + + if (exitCode !== 0) { + throw new Error( + `tsc reported errors against tests/consumer-types/fixture.ts ` + + `(exit ${exitCode}). This means a real consumer with ` + + `moduleResolution: "bundler" would fail to import these symbols.\n\n` + + `=== tsc stdout ===\n${stdout}\n=== tsc stderr ===\n${stderr}`, + ); + } + expect(exitCode).toBe(0); + }); +}); diff --git a/tests/legacy/colors.test.ts b/tests/legacy/colors.test.ts index 29f4a84..ab42e8c 100644 --- a/tests/legacy/colors.test.ts +++ b/tests/legacy/colors.test.ts @@ -50,10 +50,14 @@ describe("colors", () => { }); describe("semantic colors", () => { - it("should have warning, error, info colors", () => { + it("should have warning, error, info, success colors", () => { expect(colors.warning).toBe("#FEC601"); expect(colors.error).toBe("#EF4444"); expect(colors.info).toBe("#2C7A7B"); + // `success` was missing from the 0.8.0 shim and got re-added in this PR. + // Two consumer migrations had to backfill it locally; pin it now so a + // future shim regression fails CI here. + expect(colors.success).toBe("#22C55E"); }); it("should export semantic colors as constants", () => { @@ -63,6 +67,31 @@ describe("colors", () => { }); }); + describe("blue accent palette", () => { + // Same restoration story as `colors.success` — the snapshot copied into + // ui-kit/src/legacy in 0.8.0 had dropped the `blue` palette that + // @policyengine/design-system 0.2.0/0.3.0 shipped, forcing + // cbo-baseline-tracker and uk-spring-statement-2026 to backfill it. + it("should have a complete blue scale from 50-900", () => { + const expectedShades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]; + expectedShades.forEach((shade) => { + expect(colors.blue[shade as keyof typeof colors.blue]).toBeDefined(); + expect(colors.blue[shade as keyof typeof colors.blue]).toMatch( + /^#[0-9A-Fa-f]{6}$/, + ); + }); + }); + + it("should match the design-system 0.3.0 sky palette", () => { + // Pin the exact hex values so accidental re-imports from a different + // palette source (Tailwind blue vs sky) get caught. + expect(colors.blue[500]).toBe("#0EA5E9"); + expect(colors.blue[600]).toBe("#0284C7"); + expect(colors.blue[50]).toBe("#F0F9FF"); + expect(colors.blue[900]).toBe("#0C4A6E"); + }); + }); + describe("background colors", () => { it("should have background variants", () => { expect(colors.background.primary).toBe("#FFFFFF"); From 97967b6974d6c9889d12b7bacca509b1b1489803 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 9 May 2026 10:11:59 -0400 Subject: [PATCH 2/2] Address round 2 nits: colors.info value drift, skip-hint, soften JSDoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - src/legacy/index.ts: flag colors.info → semanticFills.info as a value-shifting pair (design-system 0.3.0 had Ant blue #1890FF; 0.4.0+ and this shim use PE teal-700 #2C7A7B for brand consistency). Consumers bumping from 0.3.x will see a one-time blue→teal shift on info usages. Also softened the module-level JSDoc framing from 'shim mirroring design-system' to acknowledge that some values shifted between 0.3.0 and 0.4.0 and that --text-{warning,error,success} are shim-only accessibility variants. - tests/consumer-types/typecheck.test.ts: switch from describe.skipIf to an explicit it.skip with an actionable hint ("run `bun run build`") so a dev running `bun run test` cold sees why the harness didn't fire instead of silently missing. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/legacy/index.ts | 23 +++++++++++++++++++---- tests/consumer-types/typecheck.test.ts | 13 +++++++++++-- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/legacy/index.ts b/src/legacy/index.ts index c7916c8..12d103a 100644 --- a/src/legacy/index.ts +++ b/src/legacy/index.ts @@ -1,10 +1,15 @@ /** * @policyengine/ui-kit/legacy * - * @deprecated Backwards-compatibility shim that re-exports the API surface of - * the legacy `@policyengine/design-system` package. Use the canonical exports - * from `@policyengine/ui-kit` (root) and the `tokens` / `theme.css` / - * `quarto.scss` subpath exports for new code. + * @deprecated Backwards-compatibility shim that re-exports the API *shape* of + * the legacy `@policyengine/design-system` package. The keys are 1:1 with the + * latest design-system source (`policyengine-app-v2/packages/design-system`), + * and most values are bit-identical to design-system 0.3.0 — but a few values + * have shifted between 0.3.0 and 0.4.0 (notably `colors.info` blue → teal), + * and the shim added `colors.text.{warning,error,success}` accessibility-tuned + * variants that weren't in 0.3.0. Use the canonical exports from + * `@policyengine/ui-kit` (root) and the `tokens` / `theme.css` / `quarto.scss` + * subpath exports for new code. * * This module exists to make the migration from `@policyengine/design-system` * a pure import-path rename: @@ -30,6 +35,16 @@ * colors.warning → semanticFills.warning (same: #FEC601) * colors.error → semanticFills.error (same: #EF4444) * colors.success → semanticFills.success (same: #22C55E) + * colors.info → semanticFills.info (DIFFERENT hex — + * 0.3.0 was Ant blue + * #1890FF; design-system + * 0.4.0+ and this shim + * use PE teal-700 + * #2C7A7B for brand + * consistency. Consumers + * coming from 0.3.x will + * see info change blue→ + * teal.) * colors.text.warning → rootColorsLight['--text-warning'] (DIFFERENT hex — * legacy #d9480f * fails WCAG AA at diff --git a/tests/consumer-types/typecheck.test.ts b/tests/consumer-types/typecheck.test.ts index f70753f..38cee05 100644 --- a/tests/consumer-types/typecheck.test.ts +++ b/tests/consumer-types/typecheck.test.ts @@ -27,10 +27,19 @@ const DIST_INDEX = path.join(ROOT, "dist", "index.d.ts"); // Skip the harness when dist/ is missing so a fresh `bun run test` doesn't // fail before `bun run build` ever runs. CI runs build before tests; local -// runs typically already have dist/ from a prior build cycle. +// runs typically already have dist/ from a prior build cycle. We use a +// visible `it.skip` (not `describe.skipIf`) so the test report shows a +// "skipped" line with an actionable hint instead of silently dropping the +// test — that way a dev who runs `bun run test` cold can see *why* the +// harness didn't fire. const distAvailable = fs.existsSync(DIST_INDEX); -describe.skipIf(!distAvailable)("consumer-style type resolution", () => { +describe("consumer-style type resolution", () => { + if (!distAvailable) { + it.skip("(skipped — run `bun run build` first to exercise the typecheck harness against dist/)", () => {}); + return; + } + it("main + legacy + per-feature subpaths all type-check from a bundler-resolution consumer", () => { let stdout = ""; let stderr = "";