test(qa): e2e 装配修正 + 集成/门禁测试与工具链重构
- e2e:修死选择器与蜜罐误命中、补断言、GA4/security-headers 用例诚实标注 skip 边界;新增 assert-helpers/fixtures/hydrated/primary-nav/touch-targets 等复用桩。 - 集成层:config/test/jest.integration.config.js + tests-integration/ 真库 一次性 SQLite 用例,teardown 守卫开发库指纹。 - 门禁工具链:jest.setup 归位到根、scripts/accessibility 全站 axe 节点计数、 check-brand-text-token/check-motion-constraints 机械守卫、stryker/lighthouse 配置收敛。
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
// @ts-nocheck
|
||||
// 集成测试 Jest project —— 唯一跑真实数据层的测试配置。
|
||||
//
|
||||
// 与 config/test/jest.config.js(单元测试)的关系:完全独立,不复用 jest.setup.js,
|
||||
// 因为 jest.setup.js:12-50 全局 mock 了 `@/generated/prisma/client` 与
|
||||
// `@/lib/cms/data-server`(验收报告 ACCEPTANCE_REVIEW_2026-09-21.md A-8)。
|
||||
// 本配置不加载任何全局 mock,因此 src/lib/db.ts 导出的是真实的 PrismaClient。
|
||||
//
|
||||
// 文件发现:testMatch 只匹配 tests-integration 下的 .itest.ts。
|
||||
// 单测配置的 roots 是 <rootDir>/src,testMatch 是 *.test.ts(x);
|
||||
// `.itest.ts` 既不以 `.test.ts` 结尾、也不在 src/ 下,故 `npm run test:unit`、
|
||||
// `test:coverage`、stryker(同样读 config/test/jest.config.js)都不会发现这些用例 —— 行为零变化。
|
||||
//
|
||||
// 运行:npx jest --config config/test/jest.integration.config.js
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
rootDir: path.resolve(__dirname, '../..'),
|
||||
roots: ['<rootDir>/tests-integration'],
|
||||
testMatch: ['<rootDir>/tests-integration/**/*.itest.ts'],
|
||||
// testEnvironment 与单测配置(config/test/jest.config.js:6)的 jsdom **有意不同**,原因是硬约束:
|
||||
// jest-environment-jsdom 30 的沙箱里没有 Request/Response/Headers(Node 主 realm 才有),
|
||||
// 于是 `import { NextRequest } from 'next/server'` 直接 `ReferenceError: Request is not defined`
|
||||
// (node_modules/next/src/server/web/spec-extension/request.ts:14)。
|
||||
// 这正是既有「route.test.ts」宁愿手写 global.Request 假对象(jest.setup.js:185-232)并整体 mock
|
||||
// 掉 next/server(jest.setup.js:90-109)的原因 —— 而那类测试测不到真实的 HTTP 契约。
|
||||
// 被测对象是跑在 Node runtime 的 route handler + 真实 SQLite,所以集成层用 node 环境,
|
||||
// 从而拿到真实的 NextRequest/NextResponse(含 cookies / headers / clone 语义)。
|
||||
testEnvironment: 'node',
|
||||
globalSetup: '<rootDir>/config/test/itest/global-setup.js',
|
||||
globalTeardown: '<rootDir>/config/test/itest/global-teardown.js',
|
||||
// 每个 worker 在 import 被测模块之前把 DATABASE_URL 钉到 /tmp 并做守卫断言
|
||||
setupFiles: ['<rootDir>/config/test/itest/setup-files.js'],
|
||||
setupFilesAfterEnv: [],
|
||||
collectCoverage: false,
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
||||
moduleNameMapper: {
|
||||
'^@/(.*)$': '<rootDir>/src/$1',
|
||||
// 与 Next 运行时对齐的真实 React:src/lib/cms/data-server.ts:6 用 `import { cache } from 'react'`,
|
||||
// 而仓库依赖的 node_modules/react@18.3.1 **不导出 cache**(实测 typeof require('react').cache
|
||||
// === 'undefined';其 react-server 入口 react.shared-subset.js 直接抛
|
||||
// "This entry point is not yet supported outside of experimental channels")。
|
||||
// 应用能跑是因为 Next 把 react 解析到自己内置的 19.3.0-canary。这里做同样的解析,
|
||||
// 集成层才能 import 真实 data-server —— 而不是像 jest.setup.js:29-50 那样把它整体 mock 掉。
|
||||
'^react$': require.resolve('next/dist/compiled/react'),
|
||||
},
|
||||
transform: {
|
||||
// Prisma 生成产物是 ESM 且使用 import.meta.url(src/generated/prisma/client.ts:16),
|
||||
// 在 CJS 的 Jest 运行时里必须由专用 transformer 处理;该目录是机器生成的代码,
|
||||
// 只做转译不做类型检查(文件自身带 @ts-nocheck)。
|
||||
'src/generated/prisma/.+\\.ts$': '<rootDir>/config/test/itest/prisma-generated-transformer.js',
|
||||
'^.+\\.(ts|tsx)$': ['ts-jest', { tsconfig: { jsx: 'react-jsx' } }],
|
||||
},
|
||||
// SQLite 单写者 + 固定文件名:串行执行,避免多个 worker 同时写同一个临时库
|
||||
maxWorkers: 1,
|
||||
testTimeout: 30000,
|
||||
verbose: true,
|
||||
};
|
||||
Reference in New Issue
Block a user