feat(generators): ui byte-identical snapshot + dispatch entry + e2e test

- Adds ui.snapshot.json (28 entries) computed from packages/core-ui
- Wires CORE_PACKAGE_GENERATORS["ui"]: guard + emitTemplateTree +
  addToTranspilePackages + printUiNextSteps (web-tanstack/storybook
  wiring is printed, not generated — resists templating)
- Adds "ui" to the core-package generator choices list
- Adds core-package-ui.e2e.test.ts (byte-identical reconstruction)
  — passes in 14.6 s

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-09 14:19:22 +02:00
parent d974bb6267
commit d42d0e5c5c
3 changed files with 210 additions and 1 deletions

View File

@@ -0,0 +1,52 @@
import { describe, it, expect } from "vitest";
import { mkdtempSync, cpSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { execSync } from "node:child_process";
import { join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { computeSnapshot } from "../lib/snapshot";
import expectedSnapshot from "../__snapshots__/core-package/ui.snapshot.json";
// Repo root is 2 levels up from turbo/generators/__tests__
const REPO_ROOT = resolve(fileURLToPath(import.meta.url), "..", "..", "..", "..");
/**
* Strip "@repo/core-ui" from a package.json file in the tmp tree.
* Required when simulating a fresh scaffold: core-ui does not exist yet
* but the snapshot was captured before removal. Apps in the current tree
* still list it as a dependency.
*/
function stripCoreUiDep(pkgJsonPath: string): void {
const raw = readFileSync(pkgJsonPath, "utf8");
const parsed = JSON.parse(raw) as Record<string, Record<string, string>>;
for (const section of ["dependencies", "devDependencies", "peerDependencies"] as const) {
if (parsed[section]?.["@repo/core-ui"]) {
delete parsed[section]["@repo/core-ui"];
}
}
writeFileSync(pkgJsonPath, JSON.stringify(parsed, null, 2) + "\n");
}
describe("e2e: core-package ui", () => {
it("byte-identical reconstruction matches snapshot", { timeout: 120_000 }, () => {
const tmp = mkdtempSync(join(tmpdir(), "e2e-ui-"));
cpSync(REPO_ROOT, tmp, {
recursive: true,
filter: (src) =>
!src.includes("node_modules") &&
!src.includes(".turbo") &&
!src.includes("packages/core-ui"),
});
// Strip @repo/core-ui from app package.json files so pnpm install
// succeeds without the package being present (simulating the post-removal state).
stripCoreUiDep(join(tmp, "apps", "web-next", "package.json"));
stripCoreUiDep(join(tmp, "apps", "web-tanstack", "package.json"));
stripCoreUiDep(join(tmp, "apps", "storybook", "package.json"));
execSync(`cd ${tmp} && pnpm install --frozen-lockfile=false`, { stdio: "ignore" });
execSync(`cd ${tmp} && pnpm turbo gen core-package --args ui`, { stdio: "ignore" });
const result = computeSnapshot(join(tmp, "packages/core-ui"));
expect(result).toEqual(expectedSnapshot);
});
});