diff --git a/README.md b/README.md index 9dc171b0f..e4c6e5bb3 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ pnpm check:ci pnpm check:env pnpm check:secrets pnpm check:metadata +pnpm check:tests pnpm test:helpers pnpm check:artifacts pnpm check:quality diff --git a/docs/operations.md b/docs/operations.md index 1b188323f..7747c3b53 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -12,6 +12,7 @@ pnpm check:ci pnpm check:env pnpm check:secrets pnpm check:metadata +pnpm check:tests pnpm test:helpers pnpm exec tsc --noEmit --pretty false git diff --check @@ -31,7 +32,7 @@ pnpm check:quality ## CI -`.github/workflows/lint.yml` 是基础质量门禁,运行 `pnpm check:quality`,负责 lint、日志治理、公开交付面品牌治理、CI hygiene、环境变量示例卫生、secret hygiene、package metadata、轻量 helper 回归测试、类型检查、diff hygiene 和 tracked 污染物检查。 +`.github/workflows/lint.yml` 是基础质量门禁,运行 `pnpm check:quality`,负责 lint、日志治理、公开交付面品牌治理、CI hygiene、环境变量示例卫生、secret hygiene、package metadata、测试门禁卫生、轻量 helper 回归测试、类型检查、diff hygiene 和 tracked 污染物检查。 CI 和本地提交前检查复用同一个入口,避免规则漂移。 @@ -98,9 +99,12 @@ pnpm check:metadata ## 轻量 Helper 回归 ```bash +pnpm check:tests pnpm test:helpers ``` +`pnpm check:tests` 会确认轻量 helper 测试仍然使用 no-server 配置、只匹配纯 helper 测试,并且保留在 `pnpm check:quality` 里。 + `pnpm test:helpers` 使用 `playwright.helpers.config.ts` 运行不需要浏览器和 Next dev server 的纯 helper 测试,当前覆盖 Canvas chat/detail/upload helper 的关键行为。它已纳入 `pnpm check:quality`,和完整 Playwright e2e 分开,避免基础门禁被数据库、浏览器和登录态拖慢。 ## 首页性能烟测 diff --git a/docs/release-readiness.md b/docs/release-readiness.md index f47d2dd05..2c2866787 100644 --- a/docs/release-readiness.md +++ b/docs/release-readiness.md @@ -13,7 +13,7 @@ SMOKE_BASE_URL=http://127.0.0.1:3001 pnpm smoke:routes 预期: -- `pnpm check:quality` 通过 lint、日志脱敏门禁、公开交付面品牌治理、CI hygiene、环境变量示例卫生、secret hygiene、package metadata、轻量 helper 回归测试、类型检查、diff hygiene 和 tracked 污染物检查。 +- `pnpm check:quality` 通过 lint、日志脱敏门禁、公开交付面品牌治理、CI hygiene、环境变量示例卫生、secret hygiene、package metadata、测试门禁卫生、轻量 helper 回归测试、类型检查、diff hygiene 和 tracked 污染物检查。 - `pnpm smoke:routes` 验证 `/` 返回 200。 - `/classic` 和 `/chat/test-id` 重定向到 `/`。 - `/settings` 未登录重定向到 `/login?callbackUrl=%2Fsettings`。 diff --git a/package.json b/package.json index bc64e7918..0133eee3e 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,9 @@ "check:env": "node scripts/check-env-example.mjs", "check:secrets": "node scripts/check-secrets.mjs", "check:metadata": "node scripts/check-package-metadata.mjs", + "check:tests": "node scripts/check-test-hygiene.mjs", "test:helpers": "PLAYWRIGHT=True pnpm exec playwright test --config=playwright.helpers.config.ts", - "check:quality": "pnpm lint && pnpm check:logs && pnpm check:brand && pnpm check:ci && pnpm check:env && pnpm check:secrets && pnpm check:metadata && pnpm test:helpers && pnpm exec tsc --noEmit --pretty false && git diff --check && pnpm check:artifacts", + "check:quality": "pnpm lint && pnpm check:logs && pnpm check:brand && pnpm check:ci && pnpm check:env && pnpm check:secrets && pnpm check:metadata && pnpm check:tests && pnpm test:helpers && pnpm exec tsc --noEmit --pretty false && git diff --check && pnpm check:artifacts", "clean:artifacts": "node scripts/clean-local-artifacts.mjs", "smoke:routes": "node scripts/smoke-routes.mjs", "format": "pnpm exec ultracite fix", diff --git a/scripts/check-test-hygiene.mjs b/scripts/check-test-hygiene.mjs new file mode 100644 index 000000000..b2ac67809 --- /dev/null +++ b/scripts/check-test-hygiene.mjs @@ -0,0 +1,44 @@ +#!/usr/bin/env node + +import { readFileSync } from "node:fs"; + +const packageJson = JSON.parse(readFileSync("package.json", "utf8")); +const helpersConfig = readFileSync("playwright.helpers.config.ts", "utf8"); +const violations = []; + +const expectIncludes = (source, expected, reason) => { + if (!source.includes(expected)) { + violations.push(`missing ${reason}: ${expected}`); + } +}; + +const expectNotIncludes = (source, forbidden, reason) => { + if (source.includes(forbidden)) { + violations.push(`unexpected ${reason}: ${forbidden}`); + } +}; + +const testHelpersScript = packageJson.scripts?.["test:helpers"] ?? ""; +const qualityScript = packageJson.scripts?.["check:quality"] ?? ""; + +expectIncludes(testHelpersScript, "PLAYWRIGHT=True", "Playwright test env flag"); +expectIncludes(testHelpersScript, "playwright test --config=playwright.helpers.config.ts", "dedicated helper Playwright config"); +expectIncludes(qualityScript, "pnpm test:helpers", "helper tests in quality gate"); + +expectIncludes(helpersConfig, 'testDir: "./tests"', "tests directory"); +expectIncludes(helpersConfig, "testMatch: /routes\\/canvas-chat-helpers\\.test\\.ts/", "single pure helper test target"); +expectIncludes(helpersConfig, 'reporter: process.env.CI ? "github" : "list"', "fast non-html reporter"); +expectIncludes(helpersConfig, "timeout: 60 * 1000", "bounded helper test timeout"); + +expectNotIncludes(helpersConfig, "webServer", "Next dev server in helper tests"); +expectNotIncludes(helpersConfig, "devices[", "browser device dependency in helper tests"); +expectNotIncludes(helpersConfig, "projects:", "multi-project helper test expansion"); +expectNotIncludes(helpersConfig, "testMatch: /e2e", "e2e tests in helper gate"); + +if (violations.length > 0) { + console.error("Test hygiene check failed. Keep helper tests fast, no-server, and wired into check:quality."); + console.error(violations.join("\n")); + process.exit(1); +} + +console.log("Test hygiene check passed.");