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,52 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* 每个 Jest worker 在任何被测模块被 import 之前执行(setupFiles 阶段)。
|
||||
*
|
||||
* 职责:把数据源**无条件**钉死到 /tmp 的一次性库,并在钉死之前先做守卫断言。
|
||||
* 这一步是必须的:src/lib/db.ts 里 `new PrismaClient()` 无参构造,运行时读 env("DATABASE_URL"),
|
||||
* 只要该变量残留成 prisma/dev.db,测试就会写真库 —— 所以宁可在这里直接抛错。
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const { TextEncoder, TextDecoder } = require('util');
|
||||
|
||||
const guard = require('./env.js');
|
||||
|
||||
// 1) 取 globalSetup 落盘的 URL;拿不到就退回固定路径,但两种来源都必须通过守卫
|
||||
let url = process.env.DATABASE_URL;
|
||||
try {
|
||||
const manifest = JSON.parse(fs.readFileSync(guard.MANIFEST_PATH, 'utf8'));
|
||||
url = manifest.datasourceUrl;
|
||||
} catch {
|
||||
url = guard.DATASOURCE_URL;
|
||||
}
|
||||
|
||||
// 2) 守卫:绝对 file: URL、位于 realpath(os.tmpdir()) 之下、不是仓库内路径、不是 dev.db/data.db
|
||||
const resolved = guard.assertSafeDatasourceUrl(url, 'setupFiles');
|
||||
|
||||
// 3) 项目库指纹必须仍与 setup 阶段一致(worker 起来就已经是最早的写入者之前)
|
||||
try {
|
||||
const manifest = JSON.parse(fs.readFileSync(guard.MANIFEST_PATH, 'utf8'));
|
||||
const now = guard.devDbBaselines();
|
||||
const drift = Object.keys(manifest.baseline || {}).filter(
|
||||
(k) => !guard.sameFingerprint(manifest.baseline[k], now[k]),
|
||||
);
|
||||
if (drift.length > 0) {
|
||||
throw new Error(`[itest:setupFiles] 项目数据源指纹漂移:${drift.join(', ')}`);
|
||||
}
|
||||
} catch (e) {
|
||||
if (String(e.message).includes('指纹漂移')) throw e;
|
||||
/* manifest 缺失时由 globalSetup 的断言负责 */
|
||||
}
|
||||
|
||||
process.env.DATABASE_URL = url;
|
||||
process.env.NOVALON_ITEST_DB = resolved;
|
||||
// 测试专用 JWT 密钥:刻意不读 .env*,保证集成层与本机开发密钥完全隔离
|
||||
process.env.JWT_SECRET = 'novalon-integration-only-access-secret';
|
||||
process.env.JWT_REFRESH_SECRET = 'novalon-integration-only-refresh-secret';
|
||||
process.env.NEXT_PUBLIC_APP_URL = 'http://localhost:3000';
|
||||
|
||||
// 4) jsdom 环境的最小 Node 能力补齐(与 jest.setup.js:4-6 同源,但本文件不加载全局 mock)
|
||||
if (typeof globalThis.TextEncoder === 'undefined') globalThis.TextEncoder = TextEncoder;
|
||||
if (typeof globalThis.TextDecoder === 'undefined') globalThis.TextDecoder = TextDecoder;
|
||||
|
||||
console.log(`[itest:worker] DATABASE_URL pinned to ${url} (resolved ${resolved})`);
|
||||
Reference in New Issue
Block a user