node-test-runner-e2e
E2E testing patterns using Node.js native test runner — createTestingApp, createDbHelper, factories, app.inject() for HTTP testing.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
E2E testing patterns using Node.js native test runner — createTestingApp, createDbHelper, factories, app.inject() for HTTP testing.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Awilix dependency injection patterns for this Fastify project — auto-loading conventions, Cradle usage, partial application, type declarations.
CQS (Command Query Separation) patterns — mutations for writes with events, queries for reads without side effects.
Safe Drizzle ORM migration patterns for PostgreSQL. Auto-loads on migration files. Mandatory reading before writing or editing a migration.
Drizzle ORM query patterns for this project — base repository, soft delete, NON_PASSWORD_COLUMNS, query builder conventions.
Fastify route handler patterns — TypeBox validation, DI access, schema definitions, JWT guards, error handling conventions.
| name | node-test-runner-e2e |
| description | E2E testing patterns using Node.js native test runner — createTestingApp, createDbHelper, factories, app.inject() for HTTP testing. |
| globs | ["tests/**/*.test.ts","tests/**/*.spec.ts","src/**/*.test.ts","src/**/*.spec.ts"] |
| allowed-tools | Read, Write, Edit, Grep, Glob, Bash(pnpm:*), Bash(ENV_NAME=test:*) |
import { describe, it, before, after, beforeEach } from "node:test";
import assert from "node:assert/strict";
import { createTestContext } from "#tests/helpers/index.ts";
describe("GET /v1/users", () => {
let app, db, teardown;
before(async () => {
const ctx = await createTestContext();
app = ctx.app;
db = ctx.db;
teardown = ctx.teardown;
});
beforeEach(async () => {
await db.cleanUp();
});
after(async () => {
await teardown();
});
it("[200] should return paginated users list", async () => {
await db.seed(userFactory.createManySeed(3));
const response = await app.inject({
method: "GET",
path: "/v1/users",
query: { page: "1", limit: "10" },
});
assert.strictEqual(response.statusCode, 200);
const body = response.json();
assert.ok(Array.isArray(body.data));
assert.strictEqual(body.data.length, 3);
});
});
const ctx = await createTestContext();
// Returns: { app, db, teardown }
const { app, database, teardown } = await createTestingApp();
const db = createDbHelper(database.drizzle);
db.cleanUp() — truncates all tables (validates test DB name)db.seed(seedConfig) — inserts data: { table, data }db.seedMany(configs) — multiple seedsdb.count(table) — count rowsdb.withTransaction(testFn) — savepoint-based rollbackimport { userFactory } from "#tests/helpers/index.ts";
userFactory.create() // single user object
userFactory.create({ role: "admin" }) // with overrides
userFactory.createMany(5) // array of 5 users
userFactory.createSeed() // { table, data } for db.seed()
userFactory.createManySeed(3) // { table, data[] } for db.seed()
import { authFactory } from "#tests/helpers/index.ts";
const auth = authFactory.for(user);
auth.accessToken // JWT string
auth.refreshToken // JWT string
auth.accessTokenHeader // { authorization: "Bearer <token>" }
auth.authTokenSeed // { table, data } for seeding auth tokens
import { createEndpoint } from "#tests/helpers/index.ts";
const endpoint = createEndpoint("/v1/users/:id");
endpoint({ id: "123" }) // "/v1/users/123"
pnpm test # all tests with coverage
pnpm test:unit # unit only
pnpm test:integration # integration only
pnpm test:e2e # e2e only
ENV_NAME=test node --test <file> # single file
db.cleanUp() in beforeEach — every test starts cleanteardown() in after — close connectionsapp.inject() for HTTP requests — not fetch or supertestassert from node:assert/strict — not chai, not jest[200] should return..., [404] should throw...setTimeout in tests (use proper async/await)