Cross-project chains
Run a test in one project and then a test in another, threading captured values forward — sequential, fail-fast, and masked wherever a value is stored.
Most products are not one application. An order placed in the storefront becomes a row in the ops portal, a line in the finance export and an email. A test that stops at the storefront's confirmation page proves the first hop and nothing after it.
A chain is an ordered list of segments, each naming an existing test in some project. It runs them one after another, in one session of work, carrying values captured in one segment into the next. Chains are org-level rather than project-level, because spanning projects is the entire point.
Chains are a Team plan feature.
If what you need is "the Customer submits and the Manager approves", you want actor scenarios instead — a scenario is a chain that knows who is acting, and re-establishes a different session per stage. A chain is the simpler shape: a line of tests, one after another.
A segment is a reference, not a copy
Each segment carries a project, a test in that project, and two optional overrides:
| Field | What it does |
|---|---|
| Project | Which project the segment's test lives in. |
| Test | The test to run. Must belong to that project. |
| Environment | A named environment profile on that project. Unset means the project's defaults. |
| Role | An auth role to run as, overriding whatever the test itself is configured with. |
| Description | A note for whoever reads the chain later. |
Nothing is copied. Edit the test and every chain referencing it changes with it — that is why a chain is cheaper than a long test that duplicates four flows.
The role resolves in that order: the segment's override wins, then the test's own configured role, then the project's default. The environment supplies that segment's base URL, variables, auth config and setup fixtures, layered over the project's defaults. There is one level of layering — an environment does not inherit from another environment.
Sequential, and fail-fast
Segments run strictly one after another. The first segment that does not pass halts
the chain, and every remaining segment is recorded as skipped.
Skipped is recorded, not dropped. A chain that stopped at segment two must not look like a two-segment chain that passed.
A segment that cannot even be resolved fails the same way, with the reason attached rather than an exception: the project is gone, the test is gone, the test belongs to a different project than the segment claims, the named environment does not exist, or the test is not currently runnable (awaiting review, or quarantined). You find out which one, on the segment it happened to.
Cancellation is tracked separately from failure. A chain that was stopped reports
cancelled, and the segment that was mid-flight reports cancelled too — not
failed. Nothing went wrong; somebody stopped it.
Threading values between segments
This is what makes a chain more than "run these four tests in order". A segment can
capture a value — an order id, a reference number, a payout id — and later segments
use it as {{token}}.
Each segment's variable map is built from three sources, later winning:
- The project's (and environment's) variables.
- The chain's own variables, edited on the chain.
- Everything captured by earlier segments.
So a chain variable overrides a project default, and a value captured at runtime overrides both.
extract
Captures something from the page into a variable.
| Field | Meaning |
|---|---|
| Source | text, attribute, value (an input's current value) or url (the page's URL) |
| Selector | The element, for every source but url |
| Attribute | Which attribute, when the source is attribute |
| Pattern | An optional regex — the first capture group if there is one, otherwise the whole match |
| Save as | The variable name later steps and segments use |
| Sensitive | Marks the value for masking (see below) |
If the element is not there, or the pattern does not match, the step fails. It does
not save an empty string and carry on — a variable that silently became "" would
fail three segments later, somewhere unrelated.
api-request
Makes an HTTP request and pulls values out of the JSON response.
It goes through the run's browser context, which is the detail that matters: the
active role's captured session cookies and Basic Auth apply automatically, so you do
not re-authenticate to read your own API. The URL may be absolute or relative to the
run's base URL, and is SSRF-checked exactly like a goto.
Values come out by JSON dot-path (data.order.id); a path that is not in the
response fails the step. expectStatus pins the status you expect — leave it unset
and any 2xx passes.
Set retries (up to five) and backoffMs (default 1000 ms, doubled each attempt)
when the endpoint is eventually-consistent. The wait honours a Retry-After header
when the server asks for longer than the computed backoff, and no single wait exceeds
30 seconds. A retry happens only on 429, a 5xx, or a network failure — a 401 or a
404 fails immediately, because repeating a request the server already answered
definitively just gets the same answer more slowly.
Both actions work in ordinary tests too. They are not chain-only.
Sensitive values are masked at rest
Mark a capture sensitive and the value is written as *** everywhere it is
stored or displayed — the step result, the chain run's variable snapshot, the
variables strip on the run page. It stays real in memory for the rest of that
test, so later steps in the same segment substitute the true value.
It does not stay real across a segment boundary. The cross-segment accumulator is
built from each run's masked variables, so a sensitive capture arrives at the next
segment as the literal string ***. That is deliberate for now: chains are built to
carry non-sensitive identifiers between projects, and per-segment authentication is
meant to come from each project's role sessions rather than a token forwarded down
the line. If a downstream segment needs a real secret, give that project a role.
Running one
Run chain starts it. A chain is the longest-running thing in Vera — several browser runs in sequence — so expect minutes, not seconds.
While it runs, the page streams progress: each segment starting, per-step progress inside the segment currently executing, each segment's result as it completes, and the finished chain run at the end. Every past run is in the history list below, with its status, duration and the segment breakdown; open any segment that produced a run to read its full report.
The Variables captured strip shows the chain's final variable bag. Masked values
read *** there, which is the honest rendering rather than a missing row.
Stopping one
The Stop button appears once the live stream has named the run — a button that could only 404 is worse than no button. A chain running in a worker or in somebody else's tab gets its own Stop in the history list.
A stop is real, and it lands in two places. The chain checks between segments, so
nothing further starts. It also forwards the stop into the run that is currently
executing, so that segment ends at its next step rather than finishing the whole
test first. Everything after it is recorded skipped, and the chain lands
cancelled.
Stopping is never plan-gated. An entitlement decides whether you may start work, not whether you may stop it.
Limits worth knowing
- Team plan and above. On Free or Pro, the chain routes answer with a plan prompt.
- A chain needs at least one segment. There is no maximum, which means a forty-segment chain is possible and is almost certainly the wrong shape — fail-fast means the last segment only ever runs when the other thirty-nine passed.
- When a chain is queued to a worker, the resolved auth is stripped before the job is enqueued. Captured sessions do not sit in the job table.
- From an MCP client, an agent can list chains, start one (it returns the run id
immediately rather than waiting), poll the chain run, and stop it with
cancel_runandkind: "chain".
See also
- Actor scenarios — when the segments need to be different people
- Variables — where
{{token}}values come from, and in what order - Step actions reference —
extractandapi-requestin full - Reusable flows — factoring a repeated sequence out of several tests