Get started with zuplo test
This guide takes a Zuplo project from no tests to a green test run against a
local dev server, in three steps. It covers where test files live, what
TestHelper gives you, and the CLI flags worth knowing. The only install is one
assertion library.
Every test zuplo test runs is an integration test: it makes a real HTTP
request to a real running gateway and asserts on the real response. The endpoint
is a command-line flag, so the same files run against local dev, a preview
deployment, or production.
-
Install an assertion library
describe,it, the lifecycle hooks, andTestHelpercome from@zuplo/test, which arrives transitively with thezuplopackage. The CLI requires Node.js 24.0.0 or later, which every sample here assumes.Assertions in these docs use
expectfrom chai. Chai is not included in a new Zuplo project, so install it yourself:CodeThe CLI marks
chaias external when it compiles your tests, so it resolves fromnode_modulesat run time. Skip the install step and the compiler fails withCannot find package 'chai'before any test runs.Prefer no dependencies? Node's built-in
node:assert/strictworks instead and needs nothing installed. The strict form compares with===, soassert.equal(200, "200")fails instead of quietly passing. -
Write the first test
Test files go in a
testsfolder at the root of your project and must end in.test.ts. Nested folders are fine.CodeTestHelper.TEST_URLis whatever you passed to--endpoint. Build request URLs from it rather than hard-coding a host — that is the single change that lets one suite serve every environment:Code -
Run it
Start the dev server in one terminal:
CodeRun the suite in another:
CodeThe CLI discovers every
tests/**/*.test.tsfile, compiles them into.zuplo/__tests__, and runs them..zuplois generated output — leave it out of source control.Add the endpoint you use most to a script so the common case is one word:
Code
TestHelper reference
TestHelper has two static members.
| Member | Type | Description |
|---|---|---|
TestHelper.TEST_URL | string | The value passed to --endpoint. Throws if zuplo test was not given one. |
TestHelper.environment | Record<string, string> | The test process environment. This is process.env — the two are interchangeable, including anything from .env. |
TestHelper.environment reads the environment of the test process, not the
environment variables configured on your Zuplo project. Those belong to the
gateway; these belong to the test process. Fixture tokens, API keys, and seed
data come in this way:
Code
Code
The CLI also loads a .env file from the directory you run it in, so local
fixture values can live there instead of on the command line.
Never commit fixture credentials. Keep them in .env (gitignored) locally and
in your CI provider's secret store in the pipeline.
Select which tests run
Two flags select tests by name. Both match against the full test name, which is
the describe label and the it label joined together, so a test named
smoke: orders route answers is selected by --filter smoke even when its
enclosing describe does not match.
Code
--skip-filter is applied after --filter, so the two compose. This is the
mechanism behind production smoke checks: name the read-only subset
consistently, then run only that subset against production.
Skip a test in code
Prefix a suite or test with .skip (or its alias .ignore) to declare it
without running it:
Code
.only takes effect only when the run is started with --only. Without the
flag, zuplo test runs the marked test and every other test — silently the
opposite of what you wanted, and it looks like it worked.
Code
With the flag, only the marked tests and suites execute. If your CLI does not
recognize --only, upgrade the zuplo package — or use --filter to narrow
the run by test name, which works on every version.
Next steps
- Gateway test recipes — what to assert at a gateway, as copy-pasteable files
- Testing preview environments — run the same suite against the real deployment of your branch
- Testing GitHub deployments — make a failing gateway test block the merge
- Testing overview — when to run what, and why