Skip to main content

testing-patterns

Testing conventions for @webiny/stdlib — container setup, tmpdir patterns, browser environment directives.

Source facts

Repository
webiny/stdlib
Last source activity
July 28, 2026 at 13:05
Detected SKILL.md language
English
Stars
0
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
testing-patterns
description
Testing conventions for @webiny/stdlib — container setup, tmpdir patterns, browser environment directives.
context
guides
# Testing Patterns in @webiny/stdlib 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. ## Container setup — `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. ```ts 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: ```ts 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. ## tmpdir cleanup Use Node's `tmpdir()` for temporary directories in filesystem tests. Always clean up in `afterEach`: ```ts 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 }); }); ``` ## Browser environment directive `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: ```ts // __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. ## Type-checking tests 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. ## Coverage `yarn test:coverage` runs the full suite with v8 coverage in one invocation, using the coverage block in `vitest.config.ts`: ```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. ## Running tests ```sh yarn test # all tests yarn test:coverage # with v8 coverage ``` Both must pass as part of the pre-commit chain before committing: ```sh 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.
View on GitHub