Initial commit
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import { describe, it, expect, onTestFinished } from "vitest";
|
||||
import { mkdtempSync, rmSync, cpSync } 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.js";
|
||||
import expectedSnapshot from "../__snapshots__/core-package/analytics.snapshot.json" with { type: "json" };
|
||||
|
||||
// Repo root is 2 levels up from turbo/generators/__tests__
|
||||
const REPO_ROOT = resolve(
|
||||
fileURLToPath(import.meta.url),
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
);
|
||||
|
||||
describe("e2e: core-package analytics", () => {
|
||||
it(
|
||||
"byte-identical reconstruction matches snapshot",
|
||||
{ timeout: 120_000 },
|
||||
() => {
|
||||
const tmp = mkdtempSync(join(tmpdir(), "e2e-analytics-"));
|
||||
// Each e2e run clones the repo into the OS temp dir; remove it when
|
||||
// the test finishes so sequential runs don't accumulate and fill disk.
|
||||
onTestFinished(() => rmSync(tmp, { recursive: true, force: true }));
|
||||
cpSync(REPO_ROOT, tmp, {
|
||||
recursive: true,
|
||||
filter: (src) =>
|
||||
!src.includes("node_modules") &&
|
||||
!src.includes(".turbo") &&
|
||||
!src.includes(".pnpm-store") &&
|
||||
!src.includes("packages/core-analytics"),
|
||||
});
|
||||
|
||||
// No other package.json depends on @repo/core-analytics, so no strip
|
||||
// step is needed — excluding the source dir is sufficient.
|
||||
execSync(`cd ${tmp} && pnpm install --frozen-lockfile=false`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
execSync(`cd ${tmp} && pnpm turbo gen core-package --args analytics`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
const result = computeSnapshot(join(tmp, "packages/core-analytics"));
|
||||
expect(result).toEqual(expectedSnapshot);
|
||||
},
|
||||
);
|
||||
});
|
||||
78
turbo/generators/__tests__/core-package-audit.e2e.test.ts
Normal file
78
turbo/generators/__tests__/core-package-audit.e2e.test.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { describe, it, expect, onTestFinished } from "vitest";
|
||||
import {
|
||||
mkdtempSync,
|
||||
rmSync,
|
||||
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.js";
|
||||
import expectedSnapshot from "../__snapshots__/core-package/audit.snapshot.json" with { type: "json" };
|
||||
|
||||
// Repo root is 2 levels up from turbo/generators/__tests__
|
||||
const REPO_ROOT = resolve(
|
||||
fileURLToPath(import.meta.url),
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
);
|
||||
|
||||
/**
|
||||
* Strip "@repo/core-audit" from a package.json file in the tmp tree.
|
||||
* Required when simulating a fresh scaffold: core-audit does not exist yet
|
||||
* but the snapshot was captured before removal. Apps in the current tree
|
||||
* may still list it as a dependency.
|
||||
*/
|
||||
function stripCoreAuditDep(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-audit"]) {
|
||||
delete parsed[section]["@repo/core-audit"];
|
||||
}
|
||||
}
|
||||
writeFileSync(pkgJsonPath, JSON.stringify(parsed, null, 2) + "\n");
|
||||
}
|
||||
|
||||
describe("e2e: core-package audit", () => {
|
||||
it(
|
||||
"byte-identical reconstruction matches snapshot",
|
||||
{ timeout: 120_000 },
|
||||
() => {
|
||||
const tmp = mkdtempSync(join(tmpdir(), "e2e-audit-"));
|
||||
// Each e2e run clones the repo into the OS temp dir; remove it when
|
||||
// the test finishes so sequential runs don't accumulate and fill disk.
|
||||
onTestFinished(() => rmSync(tmp, { recursive: true, force: true }));
|
||||
cpSync(REPO_ROOT, tmp, {
|
||||
recursive: true,
|
||||
filter: (src) =>
|
||||
!src.includes("node_modules") &&
|
||||
!src.includes(".turbo") &&
|
||||
!src.includes(".pnpm-store") &&
|
||||
!src.includes("packages/core-audit"),
|
||||
});
|
||||
|
||||
// Strip @repo/core-audit from apps/web-next/package.json so pnpm install
|
||||
// succeeds without the package being present (simulating the post-removal state).
|
||||
stripCoreAuditDep(join(tmp, "apps", "web-next", "package.json"));
|
||||
|
||||
execSync(`cd ${tmp} && pnpm install --frozen-lockfile=false`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
execSync(`cd ${tmp} && pnpm turbo gen core-package --args audit`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
const result = computeSnapshot(join(tmp, "packages/core-audit"));
|
||||
expect(result).toEqual(expectedSnapshot);
|
||||
},
|
||||
);
|
||||
});
|
||||
79
turbo/generators/__tests__/core-package-consent.e2e.test.ts
Normal file
79
turbo/generators/__tests__/core-package-consent.e2e.test.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { describe, it, expect, onTestFinished } from "vitest";
|
||||
import {
|
||||
mkdtempSync,
|
||||
rmSync,
|
||||
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.js";
|
||||
import expectedSnapshot from "../__snapshots__/core-package/consent.snapshot.json" with { type: "json" };
|
||||
|
||||
// Repo root is 2 levels up from turbo/generators/__tests__
|
||||
const REPO_ROOT = resolve(
|
||||
fileURLToPath(import.meta.url),
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
);
|
||||
|
||||
/**
|
||||
* Strip "@repo/core-consent" from a package.json file in the tmp tree.
|
||||
* Required when simulating a fresh scaffold: core-consent does not exist yet
|
||||
* but the snapshot was captured before removal. Other packages in the current
|
||||
* tree may still list it as a dependency.
|
||||
*/
|
||||
function stripCoreConsentDep(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-consent"]) {
|
||||
delete parsed[section]["@repo/core-consent"];
|
||||
}
|
||||
}
|
||||
writeFileSync(pkgJsonPath, JSON.stringify(parsed, null, 2) + "\n");
|
||||
}
|
||||
|
||||
describe("e2e: core-package consent", () => {
|
||||
it(
|
||||
"byte-identical reconstruction matches snapshot",
|
||||
{ timeout: 120_000 },
|
||||
() => {
|
||||
const tmp = mkdtempSync(join(tmpdir(), "e2e-consent-"));
|
||||
// Each e2e run clones the repo into the OS temp dir; remove it when
|
||||
// the test finishes so sequential runs don't accumulate and fill disk.
|
||||
onTestFinished(() => rmSync(tmp, { recursive: true, force: true }));
|
||||
cpSync(REPO_ROOT, tmp, {
|
||||
recursive: true,
|
||||
filter: (src) =>
|
||||
!src.includes("node_modules") &&
|
||||
!src.includes(".turbo") &&
|
||||
!src.includes(".pnpm-store") &&
|
||||
!src.includes("packages/core-consent"),
|
||||
});
|
||||
|
||||
// Strip @repo/core-consent from package.json files so pnpm install
|
||||
// succeeds without the package being present (simulating the post-removal state).
|
||||
stripCoreConsentDep(join(tmp, "packages", "core-api", "package.json"));
|
||||
stripCoreConsentDep(join(tmp, "packages", "core-ui", "package.json"));
|
||||
|
||||
execSync(`cd ${tmp} && pnpm install --frozen-lockfile=false`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
execSync(`cd ${tmp} && pnpm turbo gen core-package --args consent`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
const result = computeSnapshot(join(tmp, "packages/core-consent"));
|
||||
expect(result).toEqual(expectedSnapshot);
|
||||
},
|
||||
);
|
||||
});
|
||||
78
turbo/generators/__tests__/core-package-dsr.e2e.test.ts
Normal file
78
turbo/generators/__tests__/core-package-dsr.e2e.test.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { describe, it, expect, onTestFinished } from "vitest";
|
||||
import {
|
||||
mkdtempSync,
|
||||
rmSync,
|
||||
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.js";
|
||||
import expectedSnapshot from "../__snapshots__/core-package/dsr.snapshot.json" with { type: "json" };
|
||||
|
||||
// Repo root is 2 levels up from turbo/generators/__tests__
|
||||
const REPO_ROOT = resolve(
|
||||
fileURLToPath(import.meta.url),
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
);
|
||||
|
||||
/**
|
||||
* Strip "@repo/core-dsr" from a package.json file in the tmp tree.
|
||||
* Required when simulating a fresh scaffold: core-dsr does not exist yet
|
||||
* but the snapshot was captured before removal. Other packages in the current
|
||||
* tree may still list it as a dependency.
|
||||
*/
|
||||
function stripCoreDsrDep(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-dsr"]) {
|
||||
delete parsed[section]["@repo/core-dsr"];
|
||||
}
|
||||
}
|
||||
writeFileSync(pkgJsonPath, JSON.stringify(parsed, null, 2) + "\n");
|
||||
}
|
||||
|
||||
describe("e2e: core-package dsr", () => {
|
||||
it(
|
||||
"byte-identical reconstruction matches snapshot",
|
||||
{ timeout: 120_000 },
|
||||
() => {
|
||||
const tmp = mkdtempSync(join(tmpdir(), "e2e-dsr-"));
|
||||
// Each e2e run clones the repo into the OS temp dir; remove it when
|
||||
// the test finishes so sequential runs don't accumulate and fill disk.
|
||||
onTestFinished(() => rmSync(tmp, { recursive: true, force: true }));
|
||||
cpSync(REPO_ROOT, tmp, {
|
||||
recursive: true,
|
||||
filter: (src) =>
|
||||
!src.includes("node_modules") &&
|
||||
!src.includes(".turbo") &&
|
||||
!src.includes(".pnpm-store") &&
|
||||
!src.includes("packages/core-dsr"),
|
||||
});
|
||||
|
||||
// Strip @repo/core-dsr from package.json files so pnpm install
|
||||
// succeeds without the package being present (simulating the post-removal state).
|
||||
stripCoreDsrDep(join(tmp, "packages", "core-api", "package.json"));
|
||||
|
||||
execSync(`cd ${tmp} && pnpm install --frozen-lockfile=false`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
execSync(`cd ${tmp} && pnpm turbo gen core-package --args dsr`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
const result = computeSnapshot(join(tmp, "packages/core-dsr"));
|
||||
expect(result).toEqual(expectedSnapshot);
|
||||
},
|
||||
);
|
||||
});
|
||||
90
turbo/generators/__tests__/core-package-events.e2e.test.ts
Normal file
90
turbo/generators/__tests__/core-package-events.e2e.test.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import { describe, it, expect, onTestFinished } from "vitest";
|
||||
import {
|
||||
mkdtempSync,
|
||||
rmSync,
|
||||
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.js";
|
||||
import expectedSnapshot from "../__snapshots__/core-package/events.snapshot.json" with { type: "json" };
|
||||
|
||||
// Repo root is 2 levels up from turbo/generators/__tests__
|
||||
const REPO_ROOT = resolve(
|
||||
fileURLToPath(import.meta.url),
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
);
|
||||
|
||||
/**
|
||||
* Strip "@repo/core-events" from a package.json file in the tmp tree.
|
||||
* Required when simulating a fresh scaffold: core-events does not exist yet
|
||||
* but the snapshot was captured before removal. Feature packages in the
|
||||
* current tree may still list it as a dependency.
|
||||
*/
|
||||
function stripCoreEventsDep(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-events"]) {
|
||||
delete parsed[section]["@repo/core-events"];
|
||||
}
|
||||
}
|
||||
writeFileSync(pkgJsonPath, JSON.stringify(parsed, null, 2) + "\n");
|
||||
}
|
||||
|
||||
describe("e2e: core-package events", () => {
|
||||
it(
|
||||
"byte-identical reconstruction matches snapshot",
|
||||
{ timeout: 120_000 },
|
||||
() => {
|
||||
const tmp = mkdtempSync(join(tmpdir(), "e2e-events-"));
|
||||
// Each e2e run clones the repo into the OS temp dir; remove it when
|
||||
// the test finishes so sequential runs don't accumulate and fill disk.
|
||||
onTestFinished(() => rmSync(tmp, { recursive: true, force: true }));
|
||||
cpSync(REPO_ROOT, tmp, {
|
||||
recursive: true,
|
||||
filter: (src) =>
|
||||
!src.includes("node_modules") &&
|
||||
!src.includes(".turbo") &&
|
||||
!src.includes(".pnpm-store") &&
|
||||
!src.includes("packages/core-events"),
|
||||
});
|
||||
|
||||
// Strip @repo/core-events from feature package.json files so pnpm install
|
||||
// succeeds without the package being present (simulating the post-removal state).
|
||||
const featurePackages = [
|
||||
"auth",
|
||||
"blog",
|
||||
"media",
|
||||
"marketing-pages",
|
||||
"navigation",
|
||||
];
|
||||
for (const pkg of featurePackages) {
|
||||
const pkgJson = join(tmp, "packages", pkg, "package.json");
|
||||
stripCoreEventsDep(pkgJson);
|
||||
}
|
||||
// Also strip from apps/web-next
|
||||
stripCoreEventsDep(join(tmp, "apps", "web-next", "package.json"));
|
||||
|
||||
execSync(`cd ${tmp} && pnpm install --frozen-lockfile=false`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
execSync(`cd ${tmp} && pnpm turbo gen core-package --args events`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
const result = computeSnapshot(join(tmp, "packages/core-events"));
|
||||
expect(result).toEqual(expectedSnapshot);
|
||||
},
|
||||
);
|
||||
});
|
||||
46
turbo/generators/__tests__/core-package-realtime.e2e.test.ts
Normal file
46
turbo/generators/__tests__/core-package-realtime.e2e.test.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { describe, it, expect, onTestFinished } from "vitest";
|
||||
import { mkdtempSync, rmSync, cpSync } 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.js";
|
||||
import expectedSnapshot from "../__snapshots__/core-package/realtime.snapshot.json" with { type: "json" };
|
||||
|
||||
// Repo root is 2 levels up from turbo/generators/__tests__
|
||||
const REPO_ROOT = resolve(
|
||||
fileURLToPath(import.meta.url),
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
);
|
||||
|
||||
describe("e2e: core-package realtime", () => {
|
||||
it(
|
||||
"byte-identical reconstruction matches snapshot",
|
||||
{ timeout: 120_000 },
|
||||
() => {
|
||||
const tmp = mkdtempSync(join(tmpdir(), "e2e-"));
|
||||
// Each e2e run clones the repo into the OS temp dir; remove it when
|
||||
// the test finishes so sequential runs don't accumulate and fill disk.
|
||||
onTestFinished(() => rmSync(tmp, { recursive: true, force: true }));
|
||||
cpSync(REPO_ROOT, tmp, {
|
||||
recursive: true,
|
||||
filter: (src) =>
|
||||
!src.includes("node_modules") &&
|
||||
!src.includes(".turbo") &&
|
||||
!src.includes(".pnpm-store") &&
|
||||
!src.includes("packages/core-realtime"),
|
||||
});
|
||||
execSync(`cd ${tmp} && pnpm install --frozen-lockfile=false`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
execSync(`cd ${tmp} && pnpm turbo gen core-package --args realtime`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
const result = computeSnapshot(join(tmp, "packages/core-realtime"));
|
||||
expect(result).toEqual(expectedSnapshot);
|
||||
},
|
||||
);
|
||||
});
|
||||
88
turbo/generators/__tests__/core-package-trpc.e2e.test.ts
Normal file
88
turbo/generators/__tests__/core-package-trpc.e2e.test.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { describe, it, expect, onTestFinished } from "vitest";
|
||||
import {
|
||||
mkdtempSync,
|
||||
rmSync,
|
||||
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.js";
|
||||
import expectedSnapshot from "../__snapshots__/core-package/trpc.snapshot.json" with { type: "json" };
|
||||
|
||||
// Repo root is 2 levels up from turbo/generators/__tests__
|
||||
const REPO_ROOT = resolve(
|
||||
fileURLToPath(import.meta.url),
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
);
|
||||
|
||||
/**
|
||||
* Strip "@repo/core-trpc" from a package.json file in the tmp tree.
|
||||
* Required when simulating a fresh scaffold: core-trpc does not exist yet
|
||||
* but the snapshot was captured before removal. Apps in the current tree
|
||||
* still list it as a dependency.
|
||||
*/
|
||||
function stripCoreTrpcDep(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-trpc"]) {
|
||||
delete parsed[section]["@repo/core-trpc"];
|
||||
}
|
||||
}
|
||||
writeFileSync(pkgJsonPath, JSON.stringify(parsed, null, 2) + "\n");
|
||||
}
|
||||
|
||||
describe("e2e: core-package trpc", () => {
|
||||
it(
|
||||
"byte-identical reconstruction matches snapshot",
|
||||
{ timeout: 120_000 },
|
||||
() => {
|
||||
const tmp = mkdtempSync(join(tmpdir(), "e2e-trpc-"));
|
||||
// Each e2e run clones the repo into the OS temp dir; remove it when
|
||||
// the test finishes so sequential runs don't accumulate and fill disk.
|
||||
onTestFinished(() => rmSync(tmp, { recursive: true, force: true }));
|
||||
cpSync(REPO_ROOT, tmp, {
|
||||
recursive: true,
|
||||
filter: (src) =>
|
||||
!src.includes("node_modules") &&
|
||||
!src.includes(".turbo") &&
|
||||
!src.includes(".pnpm-store") &&
|
||||
!src.includes("packages/core-trpc"),
|
||||
});
|
||||
|
||||
// Strip @repo/core-trpc from every package that references it so pnpm
|
||||
// install succeeds without the package being present (simulating the
|
||||
// post-removal state). Apps list it directly; the blog, marketing-pages,
|
||||
// and navigation features depend on it for their ./ui tRPC hooks.
|
||||
for (const pkgDir of [
|
||||
["apps", "web-next"],
|
||||
["apps", "web-tanstack"],
|
||||
["packages", "blog"],
|
||||
["packages", "marketing-pages"],
|
||||
["packages", "navigation"],
|
||||
]) {
|
||||
stripCoreTrpcDep(join(tmp, ...pkgDir, "package.json"));
|
||||
}
|
||||
|
||||
execSync(`cd ${tmp} && pnpm install --frozen-lockfile=false`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
execSync(`cd ${tmp} && pnpm turbo gen core-package --args trpc`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
const result = computeSnapshot(join(tmp, "packages/core-trpc"));
|
||||
expect(result).toEqual(expectedSnapshot);
|
||||
},
|
||||
);
|
||||
});
|
||||
80
turbo/generators/__tests__/core-package-ui.e2e.test.ts
Normal file
80
turbo/generators/__tests__/core-package-ui.e2e.test.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { describe, it, expect, onTestFinished } from "vitest";
|
||||
import {
|
||||
mkdtempSync,
|
||||
rmSync,
|
||||
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.js";
|
||||
import expectedSnapshot from "../__snapshots__/core-package/ui.snapshot.json" with { type: "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-"));
|
||||
// Each e2e run clones the repo into the OS temp dir; remove it when
|
||||
// the test finishes so sequential runs don't accumulate and fill disk.
|
||||
onTestFinished(() => rmSync(tmp, { recursive: true, force: true }));
|
||||
cpSync(REPO_ROOT, tmp, {
|
||||
recursive: true,
|
||||
filter: (src) =>
|
||||
!src.includes("node_modules") &&
|
||||
!src.includes(".turbo") &&
|
||||
!src.includes(".pnpm-store") &&
|
||||
!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);
|
||||
},
|
||||
);
|
||||
});
|
||||
76
turbo/generators/__tests__/feature.e2e.test.ts
Normal file
76
turbo/generators/__tests__/feature.e2e.test.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { describe, it, expect, onTestFinished } from "vitest";
|
||||
import { mkdtempSync, rmSync, cpSync, existsSync, readFileSync } 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";
|
||||
|
||||
// Repo root is 2 levels up from turbo/generators/__tests__
|
||||
const REPO_ROOT = resolve(
|
||||
fileURLToPath(import.meta.url),
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
);
|
||||
|
||||
/**
|
||||
* Generator-composition e2e: scaffold a feature, then run `gen job` against
|
||||
* the freshly-scaffolded feature.
|
||||
*
|
||||
* The `core-package` e2e tests verify each generator's output in isolation
|
||||
* (byte-identical snapshots). This one verifies generators run *in sequence*:
|
||||
* `gen job` asserts the consumer feature's `integrations/cms/index.ts` carries
|
||||
* a `<gen:job-tasks>` anchor, so this test fails loudly if the `feature`
|
||||
* template ever stops emitting that barrel — the regression that shipped once.
|
||||
*/
|
||||
describe("e2e: feature generator composition", () => {
|
||||
it(
|
||||
"scaffolds a feature that `gen job` can extend",
|
||||
{ timeout: 180_000 },
|
||||
() => {
|
||||
const tmp = mkdtempSync(join(tmpdir(), "e2e-feature-"));
|
||||
// Remove the temp clone when the test finishes so sequential runs
|
||||
// don't accumulate and fill disk.
|
||||
onTestFinished(() => rmSync(tmp, { recursive: true, force: true }));
|
||||
cpSync(REPO_ROOT, tmp, {
|
||||
recursive: true,
|
||||
filter: (src) =>
|
||||
!src.includes("node_modules") &&
|
||||
!src.includes(".turbo") &&
|
||||
!src.includes(".pnpm-store"),
|
||||
});
|
||||
|
||||
execSync(`cd ${tmp} && pnpm install --frozen-lockfile=false`, {
|
||||
stdio: "ignore",
|
||||
});
|
||||
execSync(
|
||||
`cd ${tmp} && pnpm turbo gen feature --args demo-feature Widget widgets`,
|
||||
{ stdio: "ignore" },
|
||||
);
|
||||
// Regression guard: `gen job` throws at its anchor assertion if the
|
||||
// feature template did not emit src/integrations/cms/index.ts.
|
||||
execSync(
|
||||
`cd ${tmp} && pnpm turbo gen job --args demo-feature send-demo-email void`,
|
||||
{ stdio: "ignore" },
|
||||
);
|
||||
|
||||
const featureRoot = join(tmp, "packages", "demo-feature");
|
||||
|
||||
const cmsIndex = join(featureRoot, "src/integrations/cms/index.ts");
|
||||
expect(existsSync(cmsIndex)).toBe(true);
|
||||
expect(readFileSync(cmsIndex, "utf8")).toContain(
|
||||
'export { sendDemoEmailTask } from "./jobs/send-demo-email.task"',
|
||||
);
|
||||
|
||||
expect(
|
||||
existsSync(join(featureRoot, "src/jobs/send-demo-email.job.ts")),
|
||||
).toBe(true);
|
||||
|
||||
const pkgJson = JSON.parse(
|
||||
readFileSync(join(featureRoot, "package.json"), "utf8"),
|
||||
) as { exports: Record<string, string> };
|
||||
expect(pkgJson.exports["./cms"]).toBe("./src/integrations/cms/index.ts");
|
||||
},
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user