用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/webiny/stdlib --skill testing-patterns命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | testing-patterns |
| description | Testing conventions for @webiny/stdlib — container setup, tmpdir patterns, browser environment directives. |
| context | guides |
Tests live in __tests__/ at the repo root (outside src/), organised into __tests__/node/ and __tests__/browser/. A single vitest.config.ts at the repo root handles both test discovery and coverage — there is no workspace file.
makeContainer()Every test file that tests a tool creates a makeContainer() helper. Silence logs during tests by registering a config instance with logLevel: "error" before registering the logger feature, then register the features under test.
import { Container } from "@webiny/di";
import { FileTool, FileToolFeature } from "../features/FileTool/index.js";
import { DirectoryToolFeature } from "../features/DirectoryTool/index.js";
import { PinoLoggerConfig, PinoLoggerFeature } from "@webiny/stdlib/node";
function makeContainer(): Container {
const container = new Container();
container.registerInstance(PinoLoggerConfig, {
getConfig: () => ({ logLevel: "error" as const, transport: "json" as const })
});
PinoLoggerFeature.register(container);
DirectoryToolFeature.register(container);
FileToolFeature.register(container);
return container;
}
For stdlib common tests (testing with ConsoleLogger instead of PinoLogger), use ConsoleLoggerConfig and ConsoleLoggerFeature from @webiny/stdlib instead.
Resolve instances in beforeEach so each test gets a fresh container — this avoids singleton state bleeding across tests:
let tool: FileTool.Interface;
beforeEach(() => {
tool = makeContainer().resolve(FileTool);
});
Rule: never construct an implementation class directly in a test. Always resolve via the container, so the test exercises the same wiring as production.
Use Node's tmpdir() for temporary directories in filesystem tests. Always clean up in afterEach:
import { join } from "node:path";
import { tmpdir } from "node:os";
import { mkdirSync, rmSync } from "node:fs";
let tmpDir: string;
beforeEach(() => {
tmpDir = join(tmpdir(), `wby-test-${Date.now()}`);
mkdirSync(tmpDir, { recursive: true });
});
afterEach(() => {
rmSync(tmpDir, { recursive: true, force: true });
});
vitest.config.ts does NOT set a global environment. Browser tests opt into the happy-dom environment on a per-file basis using a directive at the very top of the test file:
// __tests__/browser/LocalStorageCache.test.ts
// @vitest-environment happy-dom
import { ... } from "@webiny/stdlib/browser";
Node tests need no environment directive — Vitest defaults to the Node environment.
happy-dom spy cleanup: vi.restoreAllMocks() does not reliably clean up vi.spyOn calls on happy-dom objects (e.g. localStorage.setItem). Always call spy.mockRestore() explicitly in a finally block when spying on happy-dom storage.
Test files must be type-correct. yarn typecheck covers __tests__/ via each slice's check config (tsconfig.check.common.json, tsconfig.check.node.json, tsconfig.check.browser.json). Type errors in tests are caught before any test runs.
yarn test:coverage runs the full suite with v8 coverage in one invocation, using the coverage block in vitest.config.ts:
coverage: {
provider: "v8",
include: ["src/**/*.ts"],
exclude: ["**/__tests__/**", "**/index.ts", "**/abstractions/**"]
}
Barrel files (index.ts) and abstraction files are excluded from coverage since they contain no executable logic worth measuring — only implementation and feature files are covered.
yarn test # all tests
yarn test:coverage # with v8 coverage
Both must pass as part of the pre-commit chain before committing:
yarn && yarn adio && yarn format:fix && yarn lint:fix && yarn typecheck && yarn build && yarn test:coverage
See the adding-a-feature skill for where writing tests fits into the overall workflow when introducing a new tool.