Scripts and tests
Postguy runs JavaScript before a request is sent and after the response arrives. It also checks a table of assertions against the response.
Scripts run in an embedded QuickJS sandbox with the pm API, the pg object and Bruno-style globals. This page covers where scripts live, when they run and which limits apply. The full API is in the Scripting API reference.
pm.cookies.jar() and pm.visualizer are not implemented.Where scripts live
| Place | Tab | Phases |
|---|---|---|
| Collection | Scripts | Pre-request, Post-response |
| Folder | Scripts | Pre-request, Post-response |
| Request | Scripts | Pre-request, Post-response |
| Request | Tests | assertion table and Test script |
A tab shows a dot when it has content. The script editors have a Snippets menu with ready-made code.
Execution order
For one send:
- Pre-request: the collection script, then each folder script from the outermost to the innermost folder, then the request script. Every script runs in its own function scope, so
constandletnames never collide between levels. - Postguy builds auth, URL and body from the (possibly edited) request and sends it. See HTTP requests.
- Post-response: the collection script, the folder scripts (outer to inner), then the request script.
- Tests tab: the enabled assertion rows in table order, then the
Test script.
All scripts of one phase share one sandbox run and one time budget. They see each other's variable changes. The Tests assertions and script are part of the post-response run.
A request with only a Tests tab and no scripts still runs the post-response phase.
Failure behaviour
| Where | What happens |
|---|---|
| Pre-request script throws, times out or runs out of memory | Nothing is sent. The send fails with pre-request script in <origin> failed at line <n>: <message>, and the error is written to the Console. Later pre-request scripts do not run. |
pm.execution.skipRequest() in a pre-request script | The request is skipped. This is not a failure. |
| Post-response script throws | The response is kept. The failure is listed as a script failure and a warning. The next scripts and the Tests tab still run. A timeout or memory limit stops the rest. |
| An assertion fails | One failed result with a message such as expected res.status equals 201, got 200. The remaining rows still run. |
<origin> names the level: collection <name>, folder <name> or request <name>. The Tests tab is request <name> tests.
Test results
The response viewer has a Test Results tab. It is labelled Test Results (passed/total) once something ran.
- Filters:
All,Passed,SkippedandFailed. - Rows are marked
PASS,FAILandSKIP. - Each failure shows its message. Script failures show in a banner.
- Results from assertion rows are tagged as assertions.
- Secret variable values are masked in failure messages.
In the runner, test results count towards the run's pass and fail totals.
Examples
A pm-style post-response script:
pm.test("status is 200", () => {
pm.response.to.have.status(200);
});
pm.test("has an id", () => {
const body = pm.response.json();
pm.expect(body.id).to.be.a("number");
pm.environment.set("lastId", String(body.id));
});
The same with pg. It has every pm member and adds a runtime variable scope. That scope lives for the app session and is never written to a file:
pg.test("status is 200", () => pg.response.to.have.status(200));
pg.setVar("token", pg.response.json().token);
pg.report.set("traceId", pg.response.headers.get("x-trace-id"));
A Bruno-style script uses the bru, req, res, test and expect globals. res exists in the post-response phase only:
test("created", () => {
expect(res.status).to.equal(201);
});
bru.setVar("orderId", res.body.id);
A pre-request script can change the request before it is sent, and can stop it:
pm.variables.set("requestTime", new Date().toISOString());
if (!pm.environment.get("baseUrl")) {
pm.execution.skipRequest();
}
Tests tab
The Tests tab has two parts: an assertion table and a Test script.
Each assertion row has an enable checkbox, an expression, an operator and a value:
- Expression: JavaScript evaluated after the post-response scripts, with
resavailable. Examples:res.status,res.body.id,res.headers['content-type']. An expression that throws fails the row withcould not evaluate <expr>: <message>. - Value: supports
{{variables}}and is trimmed. Postguy parses it as a JSON literal when possible:undefined,true,false,null, numbers, quoted strings and JSON arrays or objects. Anything else is plain text. - Unary operators ignore the value. The value field is hidden for them.
The result name is <expr> <operator token> <value>.
Operators
There are 28 operators. Each has a label in the table and a token in the collection file.
- Postguy also reads
equalsandnotEqualsaseqandneq. - An unknown token is kept in the file and evaluated as
eq.
| Token | Label | Passes when |
|---|---|---|
eq | equals | deep-equal to the parsed value, or a string equal to the raw text |
neq | not equals | not eq |
gt | greater than | number comparison; fails with expected a number otherwise |
gte | greater or equal | number comparison |
lt | less than | number comparison |
lte | less or equal | number comparison |
in | in | equals one item of a JSON array or a comma-separated list |
notIn | not in | equals none of those items |
contains | contains | a string contains the text, or an array has an equal item |
notContains | not contains | the opposite |
startsWith | starts with | a string starts with the text |
endsWith | ends with | a string ends with the text |
matches | matches | a JavaScript RegExp built from the value finds a match in the string form of the result |
notMatches | not matches | no match |
between | between | a number inside an inclusive range written 1, 10 or [1, 10] |
length | length | a string (characters), array or object (keys) has exactly the given length |
isEmpty | is empty | unary |
isNotEmpty | is not empty | unary; null and undefined fail |
isNull | is null | unary |
isUndefined | is undefined | unary |
isDefined | is defined | unary |
isTruthy | is truthy | unary |
isFalsy | is falsy | unary |
isNumber | is number | unary |
isString | is string | unary |
isBoolean | is boolean | unary |
isArray | is array | unary |
isJson | is JSON | unary; an array or an object |
Type errors:
startsWithandendsWithfail withexpected a stringon other types.containsandnotContainsfail withexpected a string or an array.
Tests and assertions travel with Postman exports as postguyTests. Bruno assertions map to these operators on import. See Import and export.
Sandbox limits
Scripts get no filesystem, process or network access. The only way out is pm.sendRequest and the cookie lookup. The app runs both through its own request pipeline. A script error or panic becomes a reported failure, never a crash.
| Limit | Value |
|---|---|
| Wall-clock time for all scripts of one phase | 5,000 ms |
| JavaScript heap | 64 MiB |
| Native stack | 1 MiB |
pm.sendRequest calls per run | 10 |
| Kept console lines per run | 1,000 |
| Kept test results per run | 1,000; more are ignored and reported as a script failure |
Modules loaded with require per run | 64 |
| Size of one module | 8 MiB, UTF-8 text |
A run that hits the time or memory limit stops with a failure message that names the limit. A pre-request run that does so sends nothing.
require and assets
require loads CommonJS modules from the collection's Assets folder. Paths are relative to the folder root, for example require('./lib/helpers.js').
- The virtual
fs,path,bufferandcryptoshims read the same folder.cryptooffersrandomUUID. Every write function throws an explanatory error. pg.assetsofferstext,base64,existsandlist.- npm packages cannot be loaded.
bru.sleep,bru.cwdandbru.runRequestare refused with an error.
See Collections for managing assets, and the Scripting API for the exact surface.
Turn scripts off
Settings › General › Disable scripts skips pre-request and post-response scripts, and the Tests tab, for every request and collection run.
The send then carries a warning: scripts are disabled in Settings; pre-request and post-response scripts were skipped. See Settings.
Headless
request_sendruns the whole pipeline, scripts and tests included, and returns the script report with the result.collection_runruns scripts and tests across a collection.runtime_variablesreads (and optionally clears) thepg.setVarandbru.setVarvalues of a collection.request_updateedits a request'sscriptsandteststhrough itsdefinition.