diff --git a/.github/workflows/changeset-status.yml b/.github/workflows/changeset-status.yml index 324263c..7af3d4d 100644 --- a/.github/workflows/changeset-status.yml +++ b/.github/workflows/changeset-status.yml @@ -102,3 +102,6 @@ jobs: - name: Validate registry metadata run: pnpm registry:check + + - name: Run registry consumer smoke test + run: pnpm test:registry:consumer diff --git a/.github/workflows/release-version-pr.yml b/.github/workflows/release-version-pr.yml index b6a055d..5df0ae8 100644 --- a/.github/workflows/release-version-pr.yml +++ b/.github/workflows/release-version-pr.yml @@ -37,6 +37,9 @@ jobs: - name: Install dependencies run: pnpm install --frozen-lockfile + - name: Run registry consumer smoke test + run: pnpm test:registry:consumer + - name: Open or update version PR uses: changesets/action@v1 with: diff --git a/README.md b/README.md index c33b5e8..46b6a8f 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ Run tests: ```bash pnpm test +pnpm test:registry:consumer pnpm test:e2e:smoke ``` @@ -111,6 +112,8 @@ copy selected items into their own codebase. - Registry metadata lives in `registry/index.json` and is generated by `pnpm registry:build`. - The installer copies components into `src/cadence-ui`, adds missing package dependencies, and writes `src/cadence-ui/.install-manifest.json` so upgrades can reuse the same item set. +- `pnpm test:registry:consumer` creates a temporary consumer app, runs the installer, and + verifies the copied source typechecks and builds. - Install and upgrade instructions live in [docs/registry.md](/Users/xd/project/cadence-ui/docs/registry.md). ## Docs and QA diff --git a/docs/registry.md b/docs/registry.md index aac7972..e253efc 100644 --- a/docs/registry.md +++ b/docs/registry.md @@ -37,6 +37,15 @@ pnpm registry:check The pull request workflow now runs `pnpm registry:check`, and the release version PR workflow refreshes the registry automatically via `pnpm release:version`. +To validate the end-to-end consumer flow locally: + +```bash +pnpm test:registry:consumer +``` + +That smoke test creates a temporary app, runs the registry installer, installs the +required dependencies, and verifies that the copied source both typechecks and builds. + ## Consumer install flow ### 1. Pin the Cadence UI source diff --git a/docs/releasing.md b/docs/releasing.md index fe717b5..d85f325 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -78,6 +78,7 @@ Use the docs and smoke checks when the change touches behavior-heavy UI: ```bash pnpm build:docs +pnpm test:registry:consumer pnpm test:e2e:smoke ``` @@ -166,6 +167,15 @@ pnpm registry:check This prevents registry metadata drift from merging unnoticed. +The repo also runs: + +```bash +pnpm test:registry:consumer +``` + +This verifies that the committed registry snapshot can still install into a fresh +consumer app, typecheck, and build. + ### Version PR workflow The `Release Version PR` workflow runs on pushes to `main` and on manual dispatch. It: diff --git a/package.json b/package.json index 41459e0..dea7e35 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "test": "pnpm --filter @ai-ui/ui test", "test:e2e": "playwright test", "test:e2e:smoke": "playwright test tests/e2e/storybook-smoke.spec.ts", + "test:registry:consumer": "node ./tests/registry/consumer-smoke.mjs", "test:watch": "pnpm --filter @ai-ui/ui test:watch", "typecheck": "pnpm -r typecheck" }, diff --git a/tests/registry/consumer-smoke.mjs b/tests/registry/consumer-smoke.mjs new file mode 100644 index 0000000..12eac8a --- /dev/null +++ b/tests/registry/consumer-smoke.mjs @@ -0,0 +1,242 @@ +import fs from "node:fs/promises"; +import os from "node:os"; +import path from "node:path"; +import { spawn } from "node:child_process"; +import { fileURLToPath } from "node:url"; + +const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); +const registryInstallerPath = path.join(repoRoot, "scripts", "registry-install.mjs"); +const tscBinPath = path.join(repoRoot, "node_modules", "typescript", "bin", "tsc"); +const viteBinPath = path.join(repoRoot, "node_modules", "vite", "bin", "vite.js"); +const tempPrefix = path.join(os.tmpdir(), "cadence-ui-registry-consumer-"); +const keepArtifacts = process.env.CADENCE_KEEP_REGISTRY_SMOKE === "1"; +const pnpmCommand = process.platform === "win32" ? "pnpm.cmd" : "pnpm"; + +const registryItems = ["button", "dialog", "input", "form"]; + +const packageJson = { + name: "cadence-ui-registry-consumer-smoke", + private: true, + type: "module", + dependencies: { + react: "^18.3.1", + "react-dom": "^18.3.1" + }, + devDependencies: { + "@types/react": "^18.3.28", + "@types/react-dom": "^18.3.7" + } +}; + +const tsconfig = { + compilerOptions: { + target: "ES2022", + module: "ESNext", + moduleResolution: "Bundler", + jsx: "react-jsx", + strict: true, + esModuleInterop: true, + skipLibCheck: true, + noEmit: true, + types: ["react", "react-dom"] + }, + include: ["src"] +}; + +const indexHtml = ` + +
+ + +