test(scripts): wire scripts/**/*.test.mjs under a vitest runner
241 tests across 16 script test files were wired to NO runner (the generators vitest config never included them and several used node:test imports that vitest silently skips). New root vitest.scripts.config.mjs + pnpm test:scripts + a CI validate step run them all; node:test imports converted to vitest keeping node:assert. Split out of 8c88a9a where a concurrent agent's staged files were swept into the marketing-pages commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -81,6 +81,10 @@ jobs:
|
|||||||
- run: pnpm typecheck
|
- run: pnpm typecheck
|
||||||
- run: pnpm lint
|
- run: pnpm lint
|
||||||
- run: pnpm conformance
|
- run: pnpm conformance
|
||||||
|
# scripts/ is not a workspace package, so `pnpm test` (turbo) never
|
||||||
|
# reaches its test files — they get their own vitest run.
|
||||||
|
- name: Root scripts test suite
|
||||||
|
run: pnpm test:scripts
|
||||||
- name: Compliance manifest drift check
|
- name: Compliance manifest drift check
|
||||||
run: |
|
run: |
|
||||||
pnpm compliance:emit-all --check || {
|
pnpm compliance:emit-all --check || {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"lint": "turbo run lint",
|
"lint": "turbo run lint",
|
||||||
"test": "turbo run test",
|
"test": "turbo run test",
|
||||||
"test:e2e": "turbo run test:e2e",
|
"test:e2e": "turbo run test:e2e",
|
||||||
|
"test:scripts": "vitest run --config vitest.scripts.config.mjs",
|
||||||
"test:stories": "turbo run test:stories",
|
"test:stories": "turbo run test:stories",
|
||||||
"test:visual": "pnpm --filter @repo/storybook exec concurrently -k -s first -n 'SB,VRT' -c 'magenta,blue' 'pnpm --filter @repo/storybook exec http-server storybook-static --port 6006 --silent' 'pnpm --filter @repo/storybook exec wait-on tcp:6006 && pnpm exec playwright test --config ../../playwright.config.ts'",
|
"test:visual": "pnpm --filter @repo/storybook exec concurrently -k -s first -n 'SB,VRT' -c 'magenta,blue' 'pnpm --filter @repo/storybook exec http-server storybook-static --port 6006 --silent' 'pnpm --filter @repo/storybook exec wait-on tcp:6006 && pnpm exec playwright test --config ../../playwright.config.ts'",
|
||||||
"typecheck": "turbo run typecheck",
|
"typecheck": "turbo run typecheck",
|
||||||
@@ -45,6 +46,7 @@
|
|||||||
"prettier": "^3.5.0",
|
"prettier": "^3.5.0",
|
||||||
"turbo": "^2.4.0",
|
"turbo": "^2.4.0",
|
||||||
"typescript": "^5.8.0",
|
"typescript": "^5.8.0",
|
||||||
|
"vitest": "^3.2.7",
|
||||||
"zod": "^3.25.0"
|
"zod": "^3.25.0"
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
|
|||||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@@ -49,6 +49,9 @@ importers:
|
|||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.8.0
|
specifier: ^5.8.0
|
||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
|
vitest:
|
||||||
|
specifier: ^3.2.7
|
||||||
|
version: 3.2.7(@types/debug@4.1.13)(@types/node@22.19.17)(happy-dom@20.8.9)(jiti@2.7.0)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.49.0)(tsx@4.21.0)(yaml@2.9.0)
|
||||||
zod:
|
zod:
|
||||||
specifier: ^3.25.0
|
specifier: ^3.25.0
|
||||||
version: 3.25.76
|
version: 3.25.76
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { test, describe } from "node:test";
|
// Runs under vitest (pnpm test:scripts picks up scripts/**/*.test.mjs);
|
||||||
|
// node:assert keeps the original assertion style.
|
||||||
|
import { test, describe } from "vitest";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import os from "node:os";
|
import os from "node:os";
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { test, describe } from "node:test";
|
// Runs under vitest (pnpm test:scripts picks up scripts/**/*.test.mjs);
|
||||||
|
// node:assert keeps the original assertion style.
|
||||||
|
import { test, describe } from "vitest";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import os from "node:os";
|
import os from "node:os";
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { test, describe } from "node:test";
|
// Runs under vitest (pnpm test:scripts picks up scripts/**/*.test.mjs);
|
||||||
|
// node:assert keeps the original assertion style.
|
||||||
|
import { test, describe } from "vitest";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import os from "node:os";
|
import os from "node:os";
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { test, describe } from "node:test";
|
// Runs under vitest (pnpm test:scripts picks up scripts/**/*.test.mjs);
|
||||||
|
// node:assert keeps the original assertion style.
|
||||||
|
import { test, describe } from "vitest";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { test, describe } from "node:test";
|
// Runs under vitest (pnpm test:scripts picks up scripts/**/*.test.mjs);
|
||||||
|
// node:assert keeps the original assertion style.
|
||||||
|
import { test, describe } from "vitest";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { test, describe } from "node:test";
|
// Runs under vitest (pnpm test:scripts picks up scripts/**/*.test.mjs);
|
||||||
|
// node:assert keeps the original assertion style.
|
||||||
|
import { test, describe } from "vitest";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { test, describe } from "node:test";
|
// Runs under vitest (pnpm test:scripts picks up scripts/**/*.test.mjs);
|
||||||
|
// node:assert keeps the original assertion style.
|
||||||
|
import { test, describe } from "vitest";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import os from "node:os";
|
import os from "node:os";
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { test, describe } from "node:test";
|
// Runs under vitest (pnpm test:scripts picks up scripts/**/*.test.mjs);
|
||||||
|
// node:assert keeps the original assertion style.
|
||||||
|
import { test, describe } from "vitest";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import os from "node:os";
|
import os from "node:os";
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { test, describe } from "node:test";
|
// Runs under vitest (pnpm test:scripts picks up scripts/**/*.test.mjs);
|
||||||
|
// node:assert keeps the original assertion style.
|
||||||
|
import { test, describe } from "vitest";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import os from "node:os";
|
import os from "node:os";
|
||||||
|
|||||||
@@ -52,8 +52,10 @@ describe("pnpm work cli", () => {
|
|||||||
expect(out.length).toBeGreaterThan(0);
|
expect(out.length).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("dispatch prints a plan", () => {
|
it("dispatch prints a plan or reports nothing is ready", () => {
|
||||||
|
// Runs against the real docs/work tree, so the outcome depends on
|
||||||
|
// whether a ready task exists — both branches are valid CLI output.
|
||||||
const out = run("dispatch");
|
const out = run("dispatch");
|
||||||
expect(out).toContain("Dispatch plan");
|
expect(out).toMatch(/Dispatch plan|No ready task to dispatch/);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { test, describe } from "node:test";
|
// Runs under vitest (pnpm test:scripts picks up scripts/**/*.test.mjs);
|
||||||
|
// node:assert keeps the original assertion style.
|
||||||
|
import { test, describe } from "vitest";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import {
|
|||||||
function makeWorkTree({ epics }) {
|
function makeWorkTree({ epics }) {
|
||||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "dispatch-"));
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), "dispatch-"));
|
||||||
for (const [epicId, epicData] of Object.entries(epics)) {
|
for (const [epicId, epicData] of Object.entries(epics)) {
|
||||||
const epicDir = path.join(root, epicId);
|
// findNextTask/buildState walk <workRoot>/epics/ — mirror docs/work.
|
||||||
|
const epicDir = path.join(root, "epics", epicId);
|
||||||
fs.mkdirSync(epicDir, { recursive: true });
|
fs.mkdirSync(epicDir, { recursive: true });
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.join(epicDir, "_epic.md"),
|
path.join(epicDir, "_epic.md"),
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { test, describe } from "node:test";
|
// Runs under vitest (pnpm test:scripts picks up scripts/**/*.test.mjs);
|
||||||
|
// node:assert keeps the original assertion style.
|
||||||
|
import { test, describe } from "vitest";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import {
|
|||||||
function makeWorkTree({ epics }) {
|
function makeWorkTree({ epics }) {
|
||||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "work-state-"));
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), "work-state-"));
|
||||||
for (const [epicId, epicData] of Object.entries(epics)) {
|
for (const [epicId, epicData] of Object.entries(epics)) {
|
||||||
const epicDir = path.join(root, epicId);
|
// buildState walks <workRoot>/epics/ — mirror the real docs/work layout.
|
||||||
|
const epicDir = path.join(root, "epics", epicId);
|
||||||
fs.mkdirSync(epicDir, { recursive: true });
|
fs.mkdirSync(epicDir, { recursive: true });
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.join(epicDir, "_epic.md"),
|
path.join(epicDir, "_epic.md"),
|
||||||
@@ -85,6 +86,7 @@ describe("buildState", () => {
|
|||||||
epic1: {
|
epic1: {
|
||||||
status: "in-progress",
|
status: "in-progress",
|
||||||
title: "epic1",
|
title: "epic1",
|
||||||
|
prd: null,
|
||||||
stories: {
|
stories: {
|
||||||
story1: {
|
story1: {
|
||||||
status: "done",
|
status: "done",
|
||||||
@@ -127,7 +129,7 @@ describe("buildState", () => {
|
|||||||
|
|
||||||
it("parses depends-on and blocks frontmatter arrays", () => {
|
it("parses depends-on and blocks frontmatter arrays", () => {
|
||||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "work-dep-"));
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), "work-dep-"));
|
||||||
const epicDir = path.join(root, "epic1");
|
const epicDir = path.join(root, "epics", "epic1");
|
||||||
fs.mkdirSync(epicDir, { recursive: true });
|
fs.mkdirSync(epicDir, { recursive: true });
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.join(epicDir, "_epic.md"),
|
path.join(epicDir, "_epic.md"),
|
||||||
|
|||||||
24
vitest.scripts.config.mjs
Normal file
24
vitest.scripts.config.mjs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { defineConfig } from "vitest/config";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runner for the root scripts/ test suite (pnpm test:scripts).
|
||||||
|
*
|
||||||
|
* scripts/ is not a workspace package, so `turbo run test` never reaches
|
||||||
|
* these files — this dedicated config wires them to a runner. The suite
|
||||||
|
* runs in CI's validate job alongside the other root-level gates.
|
||||||
|
*
|
||||||
|
* Named vitest.scripts.config.mjs (not vitest.config.*) on purpose so a
|
||||||
|
* bare `vitest` invocation at the repo root does not auto-discover it.
|
||||||
|
*/
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
environment: "node",
|
||||||
|
include: ["scripts/**/*.test.mjs"],
|
||||||
|
clearMocks: true,
|
||||||
|
restoreMocks: true,
|
||||||
|
// Several suites exec child node processes (work CLI, conformance
|
||||||
|
// fixtures) — keep a generous per-test ceiling.
|
||||||
|
testTimeout: 60_000,
|
||||||
|
hookTimeout: 60_000,
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user