Webrunner runs JavaScript scripts with Rhino. Use scripts to prepare outgoing requests, generate test data, validate responses, log diagnostic information, and pass values between requests.
This page is organized as a documentation tree. Start with the overview, then open the subsection for the feature you need.
Scripts run inside a request execution context. The most common flow is:
request.response and store values for later requests.Scripts can use plain JavaScript syntax plus Webrunner globals such as vars, globalContext,
request, response, log, assert, and data generation helpers like uuid().
Scripts are available in:
Normal request execution follows this order:
If Before Request throws, the transport call is not sent and the error is written to logs. If After Request throws, the response is still kept and the error is written to logs.
These names are available directly in scripts and through context.
| Global | Description |
|---|---|
vars |
Request-run variable store. Shared by chain child requests during one chain run. |
globalContext |
Project-level variable store loaded before request scripts. |
chainContext |
Chain-level variable store available during chain execution. |
request |
Mutable outgoing request snapshot. |
rawRequest |
Original saved request snapshot before script mutations. |
response |
Response object in After Request scripts. Empty object before a response exists. |
message |
Alias for response; mainly useful for Kafka listener scripts. |
context |
Object containing the same stores, request/response objects, and helper functions. |
log(...) |
Writes to execution logs. |
logAndReturn(...) |
Logs a value and returns it. |
assert(actual, expected, message) |
Records assertion failures in logs. |
stringify(value) |
Converts a value to JSON text. |
jsonify(value) |
Parses JSON text into an object when possible. |
getRequest(nameOrId) |
Reads a previous chain request snapshot. |
skip(...) |
Skips the current chain step. |
interrupt(...) |
Interrupts the chain. |
interruptChain(...) |
Alias for interrupt(...). |
proceed() |
Clears chain flow-control state back to normal execution. |
uuid() and random/date helpers |
Generate IDs, random values, and timestamps. |
context exposes these same members as context.vars, context.request, context.log(...),
context.getRequest(...), and so on.
vars, globalContext, and chainContext expose the same API:
| Method | Description |
|---|---|
get(name) |
Returns a stored value. Missing values return JavaScript undefined. |
set(name, value) |
Stores a value. |
add(name, value) |
Alias for set. |
all() |
Returns all entries as an object. |
Values can be strings, numbers, booleans, arrays, or objects.
vars.set("token", "abc");
vars.add("count", 3);
vars.set("profile", { id: 7, enabled: true });
vars.set("roles", ["admin", "editor"]);
log(vars.get("token"));
log(stringify(vars.all()));
For placeholder resolution, Webrunner merges stores in this priority:
globalContextchainContextvarsLater stores override earlier stores. If all three contain token, `` resolves from
vars.
Global Context is project-level state for values shared by requests: base URLs, tenant ids, credentials, environment flags, or defaults.
The Global Context window has:
Enabled table values are loaded first. Numeric-looking values are parsed as numbers. Then the
Global Context script runs and can mutate globalContext.
globalContext.set("baseUrl", "https://api.example.com");
globalContext.set("tenant", "demo");
globalContext.set("accessToken", "secret");
Use those values in request URLs, headers, params, and bodies:
/users?tenant=
Authorization: Bearer
Global Context changes are persisted after request execution.
chainContext is a variable store scoped to chain execution. It is useful for values that should be
shared across all steps in a chain but should not become project-level Global Context.
chainContext.set("runId", uuid());
chainContext.set("startedAt", currentIsoDate());
In chain placeholder resolution, chainContext sits between Global Context and vars:
Chain Context can be edited from the Chain Context window and can also be changed by scripts during the chain run.
request is the mutable outgoing request. Before Request scripts should mutate request; rawRequest
should be treated as read-only.
request fields| Field | Description |
|---|---|
request.body |
Body as an object/array when saved body is valid JSON, otherwise a string. Empty body becomes {}. |
request.headers |
Array of header entries. |
request.params |
Array of query parameter entries. |
request.formData |
Array of form-data entries. |
request.binaryFilePath |
Path used by binary body mode. |
Header and param entry shape:
{ name: "Header-Name", value: "value", enabled: true }
Form-data entry shape:
{ name: "file", value: "C:/tmp/report.pdf", enabled: true, file: true }
Examples:
request.body.traceId = uuid();
request.body.email = randomEmail();
request.headers.push({
name: "X-Trace-Id",
value: request.body.traceId,
enabled: true
});
request.params = [
{ name: "page", value: 1, enabled: true },
{ name: "size", value: 50, enabled: true }
];
When the script finishes, object and array bodies are serialized back to JSON.
rawRequestrawRequest is the original saved request before script changes and placeholder resolution. Use it
for comparison or diagnostics.
log("Saved body", rawRequest.body);
log("Runtime body", request.body);
Do not mutate rawRequest; changes are not intended to affect execution.
response is available in After Request scripts. Before a response exists it is an empty object.
message is an alias for response.
| Field | Description |
|---|---|
response.statusCode |
HTTP status code. |
response.headers |
Map of header name to array of values. |
response.body |
Parsed JSON object/array when possible, otherwise text. |
assert(response.statusCode, 200, "Expected HTTP 200");
vars.set("userId", response.body.id);
Headers are exposed as arrays:
var contentType = response.headers["content-type"]
? response.headers["content-type"][0]
: "";
| Field | Description |
|---|---|
response.statusCode |
gRPC status code. |
response.statusMessage |
gRPC status message. |
response.headers |
Response metadata map. |
response.body |
Parsed JSON object/array when possible, otherwise text. |
assert(response.statusCode, 0, "Expected OK");
vars.set("grpcResult", response.body);
Kafka listener scripts receive the consumed message as response and message.
| Field | Description |
|---|---|
message.topic |
Topic name. |
message.partition |
Partition number. |
message.offset |
Record offset. |
message.timestamp |
Record timestamp. |
message.key |
Record key. |
message.body |
Parsed JSON object/array when possible, otherwise text. |
message.headers |
Array of { name, value } header entries. |
log("Kafka message", message.topic, message.partition, message.offset);
vars.set("lastKafkaId", message.body.id);
log(...args) writes to the Logs tab. Multiple arguments are joined with spaces. Objects and arrays
are logged as JSON.
log("User", { id: 7, enabled: true });
logAndReturn(value) logs the value and returns it.
vars.set("id", logAndReturn(uuid()));
logAndReturn(message, value) logs message value and returns only value.
vars.set("token", logAndReturn("New token", response.body.token));
assert(actual, expected, message) records an assertion failure when values do not match. It does
not throw; script execution continues. Request tests and chain test runs treat assertion failures as
failed tests.
assert(response.statusCode, 200, "Expected successful response");
assert(response.body.ok, true, "Expected ok=true");
When expected is null, the assertion checks that actual is present and truthy, except false
is treated as a failure.
assert(response.body.token, null, "Expected token to exist");
Objects and arrays are compared structurally. Mismatch logs include JSON paths.
assert(response.body, { ok: true, user: { id: 7 } }, "Unexpected response body");
stringify(value) converts a value to JSON text. If the input is already a string, it returns that
string.
vars.set("payloadText", stringify({ id: 7, enabled: true }));
jsonify(value) parses JSON text into an object when possible. If the value is already an object or
array, it returns a script object/array. Empty or missing input becomes an empty object.
var body = jsonify(response.body);
vars.set("id", body.id);
General helpers:
| Function | Description |
|---|---|
uuid() |
Random UUID string. |
randomString(size) |
Alphanumeric random string. Returns empty string when size <= 0. |
randomEmail() |
Random email-like string. |
randomNumber(from, to) |
Random integer, inclusive. Throws when from > to. |
randomDouble(from, to) |
Decimal string with 10 digits after the decimal point. |
randomDouble(from, to, afterComma) |
Decimal string with exactly afterComma digits. |
Date/time helpers use UTC:
| Function | Format |
|---|---|
randomIsoDate() |
ISO 8601 offset date-time. |
randomRfcDate() |
RFC 1123 date-time. |
randomDateTime() |
yyyy-MM-dd HH:mm:ss.SSS. |
randomDate() |
yyyy-MM-dd. |
randomTime() |
HH:mm:ss.SSS. |
randomMillilsDate() |
Epoch milliseconds. |
randomEpochSecondsDate() |
Epoch seconds. |
currentIsoDate() |
Current ISO 8601 offset date-time. |
currentRfcDate() |
Current RFC 1123 date-time. |
currentDateTime() |
Current yyyy-MM-dd HH:mm:ss.SSS. |
currentDate() |
Current yyyy-MM-dd. |
currentTime() |
Current HH:mm:ss.SSS. |
currentMillilsDate() |
Current epoch milliseconds. |
currentEpochSecondsDate() |
Current epoch seconds. |
Example:
request.body = {
id: uuid(),
email: randomEmail(),
date: currentDate(),
timestamp: currentMillilsDate(),
amount: randomDouble(10, 100, 2)
};
Placeholders are resolved after Before Request and before sending the request.
Variable placeholder:
{
"token": ""
}
Function placeholder:
{
"id": "",
"name": "test-",
"createdAt": ""
}
Bare JSON placeholders preserve non-string values:
{
"enabled": ,
"count": 8,
"profile":
}
If the script sets:
vars.set("enabled", true);
vars.set("count", 3);
vars.set("profile", { id: 7, name: "Alice" });
the outgoing JSON becomes:
{
"enabled": true,
"count": 3,
"profile": { "id": 7, "name": "Alice" }
}
Missing bare JSON placeholders become null. Missing quoted placeholders stay unchanged.
Function placeholders are whitelisted. They can call predefined helpers such as or
, but they do not execute arbitrary JavaScript.
In Chain mode, all child requests share one vars store during the chain run. This is the main
mechanism for passing response data from one step to another.
First request After Request:
assert(response.statusCode, 200, "Expected login success");
vars.set("token", response.body.token);
vars.set("userId", response.body.user.id);
Second request URL/header/body:
GET /users/
Authorization: Bearer
Each chain step can define chain-level Before Request and After Request scripts. Step config checkboxes decide whether Webrunner also runs the selected request’s own Before Request, After Request, Stress, and Tests settings.
getRequest(nameOrId)After a chain step runs, Webrunner stores a snapshot that can be read by later steps:
var login = getRequest("Login");
vars.set("token", login.result.body.token);
Snapshot structure:
| Field | Description |
|---|---|
meta |
Request id, name, and type. |
configuredRequest |
Body, headers, params, formData, binary path, and protocol fields before execution. |
request |
Sent request snapshot. |
sentRequest |
Alias of sent request snapshot. |
rawRequest |
Original saved request snapshot. |
response |
Response snapshot. |
result |
Status, body, headers, cookies, logs, and duration. |
Snapshots are available by request name and request id.
Chain scripts can control execution:
| Function | Effect |
|---|---|
skip(...values) |
Marks current step as skipped and skips sending when called before transport. |
interrupt(...values) |
Interrupts the chain. |
interruptChain(...values) |
Alias for interrupt(...). |
proceed() |
Resets flow control to normal execution. |
if (!vars.get("token")) {
interruptChain("Missing token");
}
Request tests are request variants. Base is the original request. Each custom test has independent body, params, headers, form-data, binary path, Before Request, and After Response scripts.
When a test runs:
Passed for 2xx responses without assertion failures.Failed for non-2xx responses or assertion failures.When Chain Run basic tests is enabled for a step, Webrunner runs Base and then enabled custom
tests before moving to the next chain request. If any test fails, the chain marks that request as
Failed and stops on that failure.
Debug Call lets you inspect and edit each stage:
Use Debug Call when a placeholder resolves incorrectly, a script changes the wrong field, or a request works manually but fails in a chain.
request.headers = request.headers || [];
request.headers.push({
name: "Authorization",
value: "Bearer " + globalContext.get("accessToken"),
enabled: true
});
assert(response.statusCode, 200, "Expected login success");
vars.set("token", response.body.token);
if (!globalContext.get("baseUrl")) {
throw "Missing baseUrl in Global Context";
}
request.formData = [
{ name: "metadata", value: stringify({ id: uuid() }), enabled: true, file: false },
{ name: "file", value: "C:/tmp/report.pdf", enabled: true, file: true }
];
{
"id": "",
"email": "",
"createdAt": ""
}
| Navigation: Home | Previous: Response Viewer | Next: Debug Call |