@rpcbase/test
v0.338.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.
Downloads
6,188
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.config.ts (or .js / .json) in your package:
export default {
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.
Coverage artifacts are written to build/playwright/coverage/ and build/vitest/coverage/, with the report in build/coverage/report/.
Default file collection
If you omit collectCoverageFrom, rb-test uses a reasonable default:
src/**/*.{ts,tsx,js,jsx,mjs,cjs}whensrc/exists- if
src/is missing,rb-testthrows unless you setcollectCoverageFrom
Unit test files are excluded by default: !**/*.test.{ts,tsx,js,jsx,mjs,cjs}.
collectCoverageFrom supports negated globs (prefix with !) to exclude files.
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 {
thresholds: {
global: {
statements: 90,
lines: 85,
functions: 85,
branches: 70,
},
"src/core/**": {
statements: 98,
lines: 95,
},
"src/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 the package root (parent folder of
spec/). Absolute paths are not supported. - 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.
Because CDP is Chromium-only, V8 coverage is collected only when running on Chromium (Chrome); other browsers skip coverage collection.
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.
Spec file conventions (desktop vs mobile)
The wrapper also applies a default testMatch per project:
*.spec.tsruns on all projects*.spec.desktop.tsruns on non-mobile projects only*.spec.mobile.tsruns on mobile projects only (project.use.isMobile === true)
To run mobile specs on iOS Safari, add a mobile WebKit project, for example:
projects: [
{ name: "chromium", use: { ...devices["Desktop Chrome"] } },
{ name: "mobile-ios-safari", use: { ...devices["iPhone 15 Pro"] } },
],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.config.*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.
