JavaScript Scripting (spec: script-js)

Napper runs JavaScript scripts (.js / .mjs files) via Node.js for pre/post request hooks and test orchestration. Scripts run on the real Node runtime with full access to npm — no sandbox, no limits.

Pre/post request hooks (spec: script-pre, script-post)

Reference scripts in your .nap file:

[script]
pre = ./scripts/setup-auth.js
post = ./scripts/validate-response.js

Import the injected ctx from the bundled napper module — no npm install required:

Pre-request scripts (spec: script-pre)

Run before the HTTP request is sent. Use them to set up authentication, generate dynamic data, or modify variables.

// setup-auth.js
import { ctx } from "napper";

const token = generateToken();
ctx.set("token", token);
ctx.log(`Token generated: ${token.slice(0, 8)}...`);

Post-request scripts (spec: script-post)

Run after the response is received. Use them for complex validation, data extraction, or chaining.

// validate-response.js
import { ctx } from "napper";

const body = ctx.response.json;

// Extract and pass to the next step
ctx.set("userId", String(body.id));

// Complex validation
if (body.id <= 0) ctx.fail("User ID must be positive");

ctx.log(`Created user ${body.id}`);

NapContext (spec: script-context)

Scripts receive a ctx object with these members:

Member Available Description
ctx.vars Pre + Post Object of all resolved variables
ctx.request Pre + Post The request about to be sent (method, url, headers, body)
ctx.response Post only Response with status, headers, body, json, durationMs
ctx.env Pre + Post Current environment name
ctx.set(key, value) Pre + Post Set a variable for downstream steps
ctx.fail(message) Pre + Post Fail the test with a message
ctx.log(message) Pre + Post Write to test output

Orchestration scripts (spec: script-orchestration)

For complex flows, a .js file can be the entry point and drive requests directly with the injected nap runner:

// orchestration.js
import { nap } from "napper";

// Run a request and get the result
const login = await nap.run("./auth/login.nap");

// Extract token from the response
nap.vars.token = login.response.json.token;

// Run a suite of tests with the token
const results = await nap.runList("./crud-tests.naplist");

// Data-driven testing
for (const userId of [1, 2, 3, 42, 99]) {
  nap.vars.userId = String(userId);
  const result = await nap.run("./users/get-user.nap");
  if (result.response.status !== 200) nap.fail(`User ${userId} failed`);
}

Reference orchestration scripts in a .naplist:

[steps]
./scripts/orchestration.js

NapRunner (spec: script-runner)

Orchestration scripts receive a nap object:

Member Description
nap.run(path) Run a .nap file, returns a result (status, json, body, headers, durationMs, passed)
nap.runList(path) Run a .naplist file, returns a list of results
nap.vars Shared, mutable variable object
nap.log(message) Write to test output
nap.fail(message) Fail the orchestration with a message

How it works (spec: script-protocol)

Napper hands the context to your script as JSON and reads back any set/fail/log calls — the bundled napper SDK wraps this protocol into the idiomatic ctx / nap objects above. Orchestration calls (nap.run) invoke the Napper binary itself with --output json, so script-driven and direct runs behave identically.

Editor autocomplete

The bundled SDK ships TypeScript .d.ts declarations, so editors give full completion on ctx and nap. For explicit vendoring or CI caching, install the published package:

npm install --save-dev @nimblesite/napper

Requirements (spec: script-runtime)

JavaScript scripts require Node.js 18+ on the machine. The Napper CLI binary itself is self-contained; .js scripts are executed via node, resolved from the nap.nodePath setting, the NAPPER_NODE environment variable, or your PATH. Plain .nap and .naplist files need no runtime at all.

Prefer Python? See Python Scripting. Already in .NET? F# and C# give the same surface.