wd-test-format
.wd-test File Format
.wd-test files are Cap'n Proto configs that define test workers for workerd's test framework. They use the schema defined in src/workerd/server/workerd.capnp.
MANDATORY: Load Reference File When Relevant
This skill is split across multiple files for context efficiency. The core patterns below cover standard single-service tests. Advanced configuration patterns live in a reference file.
You MUST read the reference file before writing or reviewing test configs that involve its subject matter. Do not guess at advanced config syntax — the reference file contains the exact patterns and fields required. Skipping it WILL lead to incorrect configs that fail at runtime.
| File | MUST load when... |
|---|---|
reference/advanced-configs.md |
Test involves Durable Objects, multiple services |
| communicating via service bindings, outbound network access, | |
| external services/sockets, or TypeScript source files |
When in doubt about whether the reference file is relevant, load it — the cost of reading is far less than the cost of a broken test config.
Basic Structure
using Workerd = import "/workerd/workerd.capnp";
const unitTests :Workerd.Config = (
services = [(
name = "my-test",
worker = (
modules = [(name = "worker", esModule = embed "my-test.js")],
compatibilityFlags = ["nodejs_compat_v2"],
),
)],
);
Key rules:
- The const name (e.g.,
unitTests) must match what the test runner expects modulesusesembedto inline file contents at build time- The first module should be named
"worker"— this is the entry point compatibilityFlagscontrol which APIs are available. Use thecompat-date-attool to look up available flags and their enable dates.compatibilityDateshould not be used in wd-test; use specific flags instead
Module Types
modules = [
(name = "worker", esModule = embed "my-test.js"), # ES module (most common)
(name = "helper", esModule = embed "helper.js"), # Additional ES module
(name = "data.json", json = embed "test-data.json"), # JSON module
(name = "data.wasm", wasm = embed "module.wasm"), # WebAssembly module
(name = "legacy", commonJsModule = embed "legacy.js"), # CommonJS module
],
Bindings
Bindings make services, data, and namespaces available to the worker via env:
bindings = [
# Text binding — env.MY_TEXT is a string
(name = "MY_TEXT", text = "hello world"),
# Text from file
(name = "CERT", text = embed "fixtures/cert.pem"),
# Data binding — env.MY_DATA is an ArrayBuffer
(name = "MY_DATA", data = "base64encodeddata"),
# JSON binding — env.CONFIG is a parsed object
(name = "CONFIG", json = "{ \"key\": \"value\" }"),
# Service binding — env.OTHER_SERVICE is a fetch-able service
(name = "OTHER_SERVICE", service = "other-service-name"),
# Service binding with entrypoint
(name = "MY_RPC", service = (name = "my-service", entrypoint = "MyClass")),
# KV namespace — env.KV is a KV namespace
(name = "KV", kvNamespace = "kv-namespace-id"),
# Durable Object namespace — env.MY_DO is a DO namespace
(name = "MY_DO", durableObjectNamespace = "MyDurableObject"),
],
Test JavaScript Structure
Test files export named objects with a test() method:
// Each export becomes a separate test case
export const basicTest = {
test() {
// Synchronous test
assert.strictEqual(1 + 1, 2);
},
};
export const asyncTest = {
async test(ctrl, env) {
// ctrl is the test controller
// env contains bindings from the .wd-test config
const resp = await env.OTHER_SERVICE.fetch('http://example.com/');
assert.strictEqual(resp.status, 200);
},
};
BUILD.bazel Integration
wd_test(
src = "my-test.wd-test",
args = ["--experimental"], # Required for experimental features
data = ["my-test.js"], # Test JS/TS files
)
Additional data entries for fixture files:
wd_test(
src = "crypto-test.wd-test",
args = ["--experimental"],
data = [
"crypto-test.js",
"fixtures/cert.pem",
"fixtures/key.pem",
],
)
Test Variants
Every wd_test() automatically generates three variants:
| Target suffix | Compat date | Description |
|---|---|---|
@ |
2000-01-01 | Default, tests with oldest compat date |
@all-compat-flags |
2999-12-31 | Tests with all flags enabled |
@all-autogates |
2000-01-01 | Tests with all autogates enabled |
Run specific variants:
just stream-test //src/workerd/api/tests:my-test@
just stream-test //src/workerd/api/tests:my-test@all-compat-flags
Scaffolding
Use just new-test to scaffold a new test:
just new-test //src/workerd/api/tests:my-test
This creates the .wd-test file, .js test file, and appends the wd_test() rule to BUILD.bazel.