Server setup
Holodeck runs as a real server next to your test server. This page installs it and starts it. Client setup wires the browser half.
Before you start
Install mkcert. Holodeck serves over TLS only, and mkcert is what issues the certificate it serves with.
brew install mkcert
brew install nss # only if you test in Firefoxsudo apt install libnss3-tools
# then install mkcert from https://github.com/FiloSottile/mkcert/releaseschoco install mkcertYou also need Node 24.21 or newer, and an app already built with WarpDrive's build configuration. Holodeck's browser build reads the same build-time flags as the rest of WarpDrive, so the pipeline that builds your tests has to supply them.
Install the package
Holodeck publishes to the canary channel only. Pin an exact version.
pnpm add -E @warp-drive/holodeck@canarynpm add -E @warp-drive/holodeck@canaryyarn add -E @warp-drive/holodeck@canarybun add -E @warp-drive/holodeck@canary@warp-drive/core is a required peer dependency. Add @warp-drive/legacy as well if your tests go through legacy adapters.
Trust a local certificate
Run the bundled ensure-cert command once per machine.
pnpm dlx @warp-drive/holodeck ensure-certIt installs a local certificate authority with mkcert -install, issues a certificate for localhost, writes the pair into your home directory, and appends two environment variables to your shell profile.
HOLODECK_SSL_CERT_PATH="$HOME/holodeck-localhost.pem"
HOLODECK_SSL_KEY_PATH="$HOME/holodeck-localhost-key.pem"Those two paths are also the defaults. Holodeck finds the certificate without the variables as long as the files are in your home directory, and announces the fallback when it starts. Set the variables only when you keep the certificate somewhere else.
ensure-cert checks for mkcert first and stops with install instructions when it is missing. It then issues the certificate whatever your shell is, and only after that writes the two variables to .zshrc, .bashrc, or fish's config.fish, going by the shell named in $SHELL. On any other shell it prints the lines to add yourself and exits normally, because the certificate at the default paths already works without them.
If you also use @warp-drive/diagnostic to serve your tests, it reads the same certificate. A machine without one fails there first, before holodeck starts at all.
Start the server with your test server
Holodeck has no command line of its own. Start it from whatever starts your test server, and give it a port one higher than the test server's.
With Diagnostic
Use the lifecycle hooks in the launch config in diagnostic.js.
import { launch } from '@warp-drive/diagnostic/server';
import holodeck from '@warp-drive/holodeck';
await launch({
async setup(options) {
await holodeck.launchProgram({
port: options.port + 1,
});
},
async cleanup() {
await holodeck.endProgram();
},
entry: './dist-test/index.html',
});With Testem
Use testem's async config.
module.exports = async function () {
const holodeck = (await import('@warp-drive/holodeck')).default;
await holodeck.launchProgram({
port: 7373,
});
process.on('beforeExit', async () => {
await holodeck.endProgram();
});
return {
// ... testem config
};
};To serve the mock from the test suite's own origin, see Common setups. Testem's proxies option cannot do it: holodeck accepts only HTTP/2, and proxies speaks HTTP/1.1 to its target.
WarpDrive's own test apps use Diagnostic, so that is the path with test coverage behind it.
The port convention
The + 1 above is a convention, not a default, and client setup repeats it on the browser side. Both halves have to agree, because holodeck binds the port it is given and never falls back to another one.
Run the launcher from the test app's own directory. launchProgram reads package.json from the current working directory, and writes .mock-cache there too.
A correct start looks like this.
@warp-drive/holodeck 🌅
=================================
Holodeck Access Granted
program: json-api
port: 7358
Serving Holodeck HTTP Mocks from https://localhost:7358
🚀 Serving Diagnostic Tests on https://localhost:7357Related
- Client setup adds the handler that scopes requests to a test.
- Test framework integration gives each test its id.