API Monitoring & Testing: Advanced Assertions and Variables with JavaScript

Scripts are snippets of JavaScript connected with requests to handle more advanced variable extraction and assertion scenarios. Standard JavaScript modules like Math and Regexp are available along with a set of included helper libaries. Scripts have access to the current variable context and complete request and response data.

Execution Order

When a request within a test is executed, each of the associated scripts will be processed. Scripts are processed in addition to Variables and Assertions defined through the test editor. The execution order is as follows:

  1. Pre-request Scripts are executed.
  2. HTTP request is executed, and a response is returned.
  3. Variables extractions defined in the editor are processed on the response.
  4. Post-response Scripts are processed. Initial and request-specific variable values extracted from previous steps are available for use.
  5. Assertions defined in the test editor are processed on the response.

Pre-request Scripts

Pre-request Scripts give you a chance to modify the request after variables have been resolved, but before the request is made. You can use this script to do any last minute processing like adding additional headers or parameters to your request (e.g. generating signatures for authentication). You can directly assign to any of the request data (except for size_bytes).

Note: if you directly update request.url or request.body this will take precedence over request.params and request.form respectively.

Example Pre-request Script
var scheme = request.scheme;
var path = request.path;

// add a new custom header that is the concatenation of the request
// scheme and path
request.headers["Custom-Header"] = scheme + " - " + path;
// add a new querystring parameter ?foo=bar
request.params["foo"] = "bar";
Example S3 authentication
This example will automatically sign and authorize S3 requests for URLs that are private S3 resoruces. Just use the editor to make a request to a private S3 url (e.g. GET https://s3.amazonaws.com/bucket-name/filename.txt) and add this Pre-request Script to add authentication.
// See http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html
// for an explaination of the S3 authentication scheme

// This script requires you to define the following initial variables
//     SecretAccessKeyId
//     AWSAccessKeyId

var date = moment().format("ddd, DD MMM YYYY hh:mm:ss ZZ");
var data = request.method + "\n" +
    "" + "\n" +                     // content-md5 is "" for GET requests
    "" + "\n" +                     // content-type is "" for GET requests
    date + "\n" + 
var hash = CryptoJS.HmacSHA1(data, variables.get("SecretAccessKeyId"));
var signature = hash.toString(CryptoJS.enc.Base64);

// build the auth header    
var auth = "AWS " + variables.get("AWSAccessKeyId") + ":" + signature;
request.headers["Authorization"] = auth;
request.headers["Date"] = date;

Post-response Scripts

Post-response Scripts allow you to evaluate the response from an individual request, typically to make assertions to validate the data. You can also extract information from the response headers or body content and store in a variable for later use. Lastly, Post-response scripts can modify HTTP request and responses to remove sensitive information before it is stored.

Defining Assertions

Scripts allow for complex assertion definitions that are not possible to define in the test editor. Assertions are defined using the assert module of the Chai Assertion Library which is included for every script. Both the request and response data objects are available to use in your assertions.

Common Assertion Syntax Reference
assert(expression, message)
Write your own test expressions.
assert('foo' !== 'bar', 'foo is not bar');
assert(Array.isArray([]), 'empty arrays are arrays');
assert.ok(object, [message])
Asserts that object is truthy with an optional descriptive message.
assert.ok('everything', 'everything is ok');
assert.ok(false, 'this will fail');
assert.notOk(object, [message])
Asserts that object is falsy with an optional descriptive message.
assert.notOk('everything', 'this will fail');
assert.notOk(false, 'this will pass');
assert.equal(actual, expected, [message])
Asserts non-strict equality (==) of actual and expected.
assert.equal(3, '3', '== coerces values to strings');
assert.notEqual(actual, expected, [message])
Asserts non-strict inequality (!=) of actual and expected.
assert.notEqual(3, 4, 'these numbers are not equal');
Additional Assertion Syntax Options

Chai offers additional assertion options including checking for nulls, strict equality comparisons, type checking, regex matching, deep object comparisons and more. The library also includes should and expect assertion styles.

View Complete Assertion Syntax Documentation

// check for specific status code
assert.equal(response.status, 200, "status was 200 OK");

// parse JSON response body into object
var data = JSON.parse(response.body);

// check for specific JSON attribute value
assert.ok(data.is_admin, "customer is an admin")

// check an array for the presence of an item
var exists = false;
var customers = data.customers;
for (var customer in customers) {
    if (customers[customer].id === 123) {
        exists = true;
assert.ok(exists, "customer 123 exists");

// check that all items in a list contain a numeric id with regex and Underscore.js library
assert(_.every(data.customers, function(customer) { return customer.id.match(/^\d+$/); }), "IDs are all numeric");

// check for existence of key named id with Underscore.js library
assert(_.has(data, "id"), "contains 'id' key");

// check that a timestamp is less than now with Moment.js library
var created_at = moment.unix(data["created_at"]);
var now = moment();
assert(now.isAfter(created_at), "create date before now"); 

Getting and Setting Variables

Scripts have access to all Variables that have been defined in Initial Variables/Initial Script, the test editor (see: Execution Order) and previous scripts through the variables global object. Setting a variable value will make it available to subsequent scripts and requests.

Getting a Variable Value
var id = variables.get("id");
Setting a Variable Value
// grab a newly-created user ID and store for later
var data = JSON.parse(response.body);
variables.set("id", data.id);

Removing Sensitive Data from HTTP Requests and Responses

You can also use Post-response Scripts to remove data from the HTTP request and response before being stored for viewing. Edit the request and response objects directly to remove sensitive data like API keys:

// clear out Authorization header
request.headers.Authorization = "";

// redact customer phone numbers
var data = JSON.parse(response.body);
for (var customer in data.customers) {
    customer.phone_number = customer.phone_number.slice(0, -4) + "XXXX";

response.body = JSON.stringify(data);

Initial Script

For each test and shared environment, you can specify a script that runs prior to the first request of an API test. If you have a complicated signature or other value that needs to be generated and is common to all requests (e.g. random number generator), this is the place to define it. The initial script is processed after the Initial Variables are processed and has access to those values through the variables global. Any variable values set with variables.set(name, value) will available to the requests in the test. Any assertions defined in the initial script will be ignored.

An Initial Script specified in the shared environment will be executed before the Initial Script defined in an individual test environment, if the shared environment is inherited by that test environment.

Built-in Variables and Functions

Every script has access to the following values:

Response Data

The response object is only available in post-response scripts.

response.body The response body as a string.
response.headers A dictionary of response headers. The keys of the dictionary represent the header names. The dictionary values are arrays of values for the given key.
response.reason The reason portion of the HTTP status line returned. This value cannot be modified.
response.response_time_ms The time taken to execute the request and receive the response in milliseconds. This value cannot be modified.
response.size_bytes The size of the response body in bytes. This value cannot be modified.
response.status The response's status code. This value cannot be modified.
Request Data

The request object is available in both pre-request and post-response scripts.

request.body The request body as a string.
request.form A dictionary of form parameters sent with the request. The keys of the dictionary represent the parameter names. The dictionary values are arrays of values for the given key.
request.headers A dictionary of the request headers. The keys of the dictionary represent the header names. The dictionary values are arrays of values for the given key.
request.host The hostname of the URL executed.
request.method The request method (GET, POST, etc.) used to execute the request.
request.params A dictionary of URL parameters (querystring) sent with the request. The keys of the dictionary represent the parameter names. The dictionary values are arrays of values for the given key.
request.path The path segment of the URL without URL parameters.
request.scheme http or https
request.size_bytes The size of the request body in bytes. This value cannot be modified.
request.url The fully-assembled URL that was accessed for the request.
API Test Variables

The variables global is available in both pre-request and post-response scripts.

variables.get(name) Return a value from the current variable context. See: Getting and Setting Variables.
variables.set(name, value) Set a variable value. See: Getting and Setting Variables. Setting a variable in a pre-request script does not make the value available to the currently request step as scripts are evaluated after the template variables are inserted (see: Execution Order).
Helper Functions
log(Object|string) Write a string or pretty-printed version of an object to the output log viewable in test results.
encode_base64(value) Encode a string value as Base64.
decode_base64(value) Decode a Base64-encoded string.
runscope_bucket The key of the bucket the test belongs to and was executed in.
JavaScript Functions

The script interpreter also supports common JavaScript objects and functions:

  • Math
  • Date
  • RegExp
  • parseInt
  • parseFloat
  • decodeURI
  • decodeURIComponent
  • encodeURI
  • encodeURIComponent
  • escape
  • unescape
  • btoa (URL-friendly Base64 encode)
  • atob (URL-friendly Base64 decode)

Included Libraries

The following libraries are automatically included for every script:

Library Version Restrictions  
Underscore.js 1.7.0   View docs
Chai Assertion Library 1.9.0   View docs
Chai JSON-Schema 1.1.0   View docs
chai-fuzzy 269c01e   View docs
Moment.js 2.8.4 Includes locales. View docs
CryptoJS 3.1.2 AES, SHA-1, SHA-256, HMAC-SHA1, HMAC-SHA256, MD5 only View docs
json2.js 2014-02-04   View docs
marknote XML Parser 0.5.1 HTTP retrieval disabled View docs

Debugging Scripts

If you are receiving unexpected script errors, try the following to debug issues:

  • Use the log() function to write out values to be viewed with the test results. log() will "pretty print" the values of objects so they are easily readable. Using console.log is not recommended.
  • Verify your JavaScript is valid with a tool like JSLint.
  • Make sure the script is completing execution in under 3 seconds.
  • Verify you are using functions supported in the documented version of included libraries.
  • Do not overwrite the request and response objects entirely. Edit only specific attributes as needed.

Next: Test Editor →

Need help? We have you covered.

View the docs or contact our support team and we'll get back to you as soon as we're able to respond.

Search Docs

For Priority Support — including live chat (when available) — upgrade to a qualified Runscope plan.

Upgrade Now