@rpcbase/test
v0.252.0
Published
`@rpcbase/test` ships the shared Playwright wiring we use across RPCBase packages: a preconfigured `test`/`expect`, automatic V8 coverage collection, and the `rb-test` CLI.
Readme
@rpcbase/test helpers
@rpcbase/test ships the shared Playwright wiring we use across RPCBase packages: a preconfigured test/expect, automatic V8 coverage collection, and the rb-test CLI.
1. Declare your coverage config
Create spec/coverage.ts (or .js / .json) in your package:
import path from "node:path"
import { fileURLToPath } from "node:url"
const workspaceRoot = path.resolve(fileURLToPath(new URL("../", import.meta.url)))
export default {
workspaceRoot,
libDirs: ["lib"],
testResultsDir: "test-results",
thresholds: {
statements: 75,
lines: 75,
functions: 75,
branches: 60,
},
}Only RB_DISABLE_COVERAGE=1 skips the hooks; every other option lives inside this config file.
Per-folder thresholds
Need stricter coverage in a sub-tree? Extend the same thresholds object with glob keys (mirroring Jest's coverageThreshold syntax):
export default {
workspaceRoot,
thresholds: {
global: {
statements: 90,
lines: 85,
functions: 85,
branches: 70,
},
"lib/core/**": {
statements: 98,
lines: 95,
},
"lib/components/**": {
functions: 92,
},
},
}- When
thresholdsonly has metric keys, it behaves exactly like before. - Adding
thresholds.globallets you keep a default floor while overriding specific directories. - Globs run against POSIX-style paths relative to
workspaceRoot, but absolute paths work too if you prefer. - Metrics you omit inside an override inherit from the global thresholds (or the 75/75/75/60 defaults).
- If a glob matches no files you'll get a warning and the override is skipped, so typos are easy to spot.
2. Import test / expect directly
// spec/my-component.spec.ts
import { test, expect } from "@rpcbase/test"
test("renders", async ({ page }) => {
await page.goto("/playground")
await expect(page.locator("button"))..toBeVisible()
})The exported test already records coverage via CDP and writes per-test payloads automatically.
3. Build your Playwright config via the shared wrapper
// playwright.config.ts
import { defineConfig, devices } from "@rpcbase/test"
export default defineConfig({
testDir: "./spec",
reporter: [["list"]],
use: {
baseURL: "http://localhost:9198",
launchOptions: { headless: true },
},
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
],
})Whenever coverage is enabled, the wrapper appends the shared reporter so Istanbul aggregation + threshold enforcement run after the suite.
4. Run tests with rb-test
Each package uses its npm test script as tsc --noEmit && rb-test. The CLI runs two stages:
- Playwright, with any CLI flags you pass through untouched; repo defaults are applied unless you provide your own
--config.
Coverage is enforced separately:
- Playwright uses
spec/coverage.*via the shared reporter and will fail the run if thresholds aren’t met. - Vitest only reads
src/coverage.json(JSON object). If that file is missing, Vitest coverage is skipped.
Need to debug without coverage? Set RB_DISABLE_COVERAGE=1 npm test and the Playwright hooks short-circuit.
