Scripting GuideOverview

Scripting Overview

ReAPI’s scripting capabilities let you write JavaScript code to handle complex testing scenarios that visual nodes can’t address. Scripts run in a secure sandbox environment compatible with both web and Node.js, giving you flexibility when you need it while keeping the primary interface accessible to QA teams.

This is the 0.1 in ReAPI’s N+0.1 model: visual nodes handle 95% of your testing needs, and scripting handles the remaining edge cases requiring custom logic, complex transformations, or specialized integrations.

Quick Navigation

Jump to the script type you need:


Request/Response Hooks

Hooks let you inject custom logic into the API request lifecycle, extending what API nodes can do.

Before Request Scripts

Run code immediately before sending an API request to dynamically modify the request.

Common Scenarios:

  • Add authentication headers based on runtime conditions
  • Inject timestamps or request IDs for tracking
  • Modify request body based on environment or context

Example: Dynamic Authentication

async function beforeRequest() {
  // Add JWT token to headers
  $request.headers["Authorization"] = `Bearer ${$context.accessToken}`;
 
  // Add request tracking
  $request.headers["X-Request-ID"] = `req_${Date.now()}`;
 
  // Inject timestamp for SLA validation
  $context.requestStartTime = Date.now();
}

Learn more about Before Request scripts →

After Response Scripts

Run code after receiving an API response to process data, perform assertions, or update context.

Common Scenarios:

  • Extract tokens or IDs from responses for subsequent requests
  • Calculate response time metrics
  • Perform custom validations using business logic
  • Transform response data before storing in context

Example: Token Extraction & Metrics

async function afterResponse() {
  // Extract auth token for next requests
  if ($response.data.token) {
    $context.accessToken = $response.data.token;
  }
 
  // Calculate response time
  $context.responseTime = Date.now() - $context.requestStartTime;
 
  // Custom validation
  $expect($response.status).to.equal(200);
  $assert.isObject($response.data.user, "User object must be present");
}

Learn more about After Response scripts →


Reusable Functions

Create libraries of reusable functions that can be called throughout your test suites.

Value Generator Scripts

Create functions that generate or transform data dynamically. These are perfect for creating test data with realistic values.

Unique Capability: Value generators can be called from JS expressions anywhere in your tests using js:$gen.generatorName(params).

Common Scenarios:

  • Generate test users with realistic data
  • Create dynamic API payloads
  • Build mock data for testing edge cases

Example: User Generator

async function createTestUser(options) {
  const { role = "user", includeAddress = false } = options || {};
 
  return {
    id: faker.string.uuid(),
    email: faker.internet.email(),
    name: faker.person.fullName(),
    role: role,
    createdAt: new Date().toISOString(),
    ...(includeAddress && {
      address: {
        street: faker.location.streetAddress(),
        city: faker.location.city(),
        country: faker.location.country(),
      },
    }),
  };
}

Usage: Call this generator in any expression field:

js:$gen.createTestUser({ role: 'admin', includeAddress: true })

Learn more about Value Generators →

Custom Assertion Scripts

Create complex, reusable validation logic that integrates seamlessly with ReAPI’s assertion nodes.

Unique Capability: Once defined, custom assertions appear in the assertion node UI — QA teams can use them without writing any code.

Common Scenarios:

  • Validate complex business rules (e.g., “is valid order”, “meets SLA”)
  • Check data structure patterns
  • Perform multi-field validations

Example: Valid User Assertion

async function isValidUser(value) {
  try {
    const isValid =
      value &&
      typeof value === "object" &&
      typeof value.id === "string" &&
      typeof value.email === "string" &&
      value.email.includes("@") &&
      typeof value.name === "string" &&
      value.name.length > 0;
 
    $addAssertionResult({
      passed: isValid,
      message: isValid
        ? "Value is a valid user object"
        : "Value does not match user structure",
      operator: "isValidUser",
      leftValue: value,
      rightValue: "user object",
    });
  } catch (error) {
    $addAssertionResult({
      passed: false,
      message: `Validation error: ${error.message}`,
      operator: "isValidUser",
      leftValue: value,
      rightValue: "user object",
    });
  }
}

Usage: After defining this, QA teams select “isValidUser” from the assertion dropdown in the UI.

Learn more about Custom Assertions →


Script Node

The Script Node lets you run any JavaScript code as a step in your test flow. Use it for complex operations that don’t fit into other node types.

Common Scenarios:

  • Multi-step data transformations
  • Complex business logic calculations
  • Batch processing of arrays
  • Building complex nested data structures

Example: Processing Response Data

async function runScript() {
  // Get response data from context
  const orders = $context.apiResponse.orders;
 
  // Process and categorize
  const processed = {
    total: orders.length,
    byStatus: {},
    highValue: [],
    metrics: {
      avgValue: 0,
      totalValue: 0,
    },
  };
 
  orders.forEach((order) => {
    // Categorize by status
    if (!processed.byStatus[order.status]) {
      processed.byStatus[order.status] = [];
    }
    processed.byStatus[order.status].push(order.id);
 
    // Track high-value orders
    if (order.total > 1000) {
      processed.highValue.push(order);
    }
 
    // Calculate metrics
    processed.metrics.totalValue += order.total;
  });
 
  processed.metrics.avgValue = processed.metrics.totalValue / orders.length;
 
  // Store results in context for next steps
  $context.orderAnalysis = processed;
}

Learn more about Script Node →


Global Functions

Global functions are utilities defined once and available across all script types in your project. They’re managed directly in the ReAPI web application.

Key Features:

  • Centralized utility management
  • Available in hooks, generators, assertions, and script nodes
  • Loaded after external libraries (can use library functions)
  • Built-in libraries available: lodash (_), CryptoJS

Common Scenarios:

  • Date/time formatters used everywhere
  • Encryption/hashing utilities
  • Common calculations or conversions
  • Custom string manipulations

Example: Date Utilities Class

class $$DateUtils {
  static formatToISO(date) {
    return new Date(date).toISOString();
  }
 
  static isRecent(timestamp, hoursAgo = 24) {
    const cutoff = Date.now() - hoursAgo * 60 * 60 * 1000;
    return new Date(timestamp).getTime() > cutoff;
  }
 
  static daysBetween(date1, date2) {
    const diff = Math.abs(new Date(date2) - new Date(date1));
    return Math.floor(diff / (1000 * 60 * 60 * 24));
  }
}

Best Practice: Use class-based structure with unique prefixes (like $$) to avoid naming conflicts.

Usage in any script:

const formatted = $$DateUtils.formatToISO(new Date());
const isNew = $$DateUtils.isRecent($response.data.createdAt, 48);

JS Expressions

JS expressions provide an alternative to JSONata for cases where you need to generate values rather than query existing data.

JSONata vs JS Expressions

GoalToolExample
Query existing dataJSONata (default)body.user.id
Transform existing dataJSONata (default)body.items[price > 100]
Generate new valuesJS Expression (js:)js:faker.internet.email()
Call value generatorsJS Expression (js:)js:createTestUser({role: 'admin'})
Dynamic calculationsJS Expression (js:)js:Date.now() - 3600000

When to Use JS Expressions

Use the js: prefix in expression fields when you need to:

  • Generate mock data for testing
  • Perform calculations for expected values
  • Call your custom value generators
  • Use lodash or faker functions

Example: Dynamic Timestamp Assertion

Assert that a response timestamp is recent (within the last hour):

# Assertion Node
- field: body.user.lastLogin
  operator: greaterThan
  expected: "js:Date.now() - 3600000" # One hour ago

Example: Using Value Generators

# API Node Request Body
{
  "user": "js:createTestUser({ role: 'admin' })",
  "testId": "js:faker.string.uuid()",
}

Example: Lodash Utility

# Context Node
contextVar: "js:_.random(1000, 9999)"

Learn more about Template Engine & Expressions →


External Libraries

ReAPI provides comprehensive JavaScript library support for all your scripting needs.

Built-in Libraries (Always Available)

These libraries are pre-loaded and always available without any setup:

  • Lodash (_) - Data manipulation utilities (docs)
  • Faker - Mock data generation (docs)
  • Zod (z) - Schema validation, v4.x (docs)
  • Ky - Modern HTTP client (docs)
  • Luxon - Date/time manipulation (docs)

Additional Library Support

  • Predefined Libraries - Curated collection (CryptoJS, DayJS, Axios, Moment, Validator, Turf.js, Numeral)
  • Custom Libraries - Load any IIFE/UMD library from a public URL
  • ESM Bundler Service - Convert modern ESM modules to IIFE format

📚 View complete library documentation →

Learn about all available libraries, examples, the ESM Bundler Service, and how to add custom libraries.


Sandbox Environment

All scripts run in a secure, isolated sandbox environment with the following characteristics:

Security Features

  • Isolated execution - Scripts can’t access other scripts’ state
  • No file system access - Can’t read or write local files
  • Limited network access - Only via fetch API
  • No Node.js built-ins - Can’t access fs, path, process, etc.

Performance Limits

  • Memory limits - Prevents memory leaks from affecting system
  • Execution timeout - Automatic termination of long-running scripts
  • CPU throttling - Prevents resource exhaustion

Available Globals

  • $context - Test context (read/write)
  • $request - Request object (in hooks)
  • $response - Response object (in after-response hooks)
  • _ - Lodash library
  • fetch - HTTP client
  • console - Logging functions
  • setTimeout, setInterval - Timer functions
  • JSON - JSON utilities
  • structuredClone - Deep cloning

Best Practices

Choosing the Right Script Type

Use Request/Response Hooks when:

  • You need to modify API calls dynamically
  • You need to extract data from responses
  • You want to perform custom validations

Use Value Generators when:

  • You need reusable data generation functions
  • You want to call functions from JS expressions
  • You need to create mock data patterns

Use Custom Assertions when:

  • You have complex validation logic
  • QA teams need to use your validation in the UI
  • You want to encapsulate business rules

Use Script Node when:

  • You need general-purpose JavaScript execution
  • You’re doing complex multi-step transformations
  • None of the specific script types fit

Use Global Functions when:

  • You have utilities needed across multiple script types
  • You want centralized, maintainable helper functions
  • You need to share logic between hooks, generators, and assertions

Code Quality

  • Keep it simple - Visual nodes should handle most logic
  • Single responsibility - Each script does one thing well
  • Meaningful names - Use descriptive function and variable names
  • Error handling - Always wrap in try/catch for robustness
  • Comments - Explain business logic, not obvious code

Performance

  • Avoid loops - Use array methods like map, filter, reduce
  • Cache values - Don’t recalculate the same thing repeatedly
  • Clean up - Delete temporary context variables you don’t need
  • Monitor execution - Track script performance in production

Integration with Visual Nodes

  • Set clear context - Use descriptive variable names for subsequent nodes
  • Simplify conditions - Create boolean flags for IF nodes to use
  • Prepare iteration data - Format arrays properly for ITERATION nodes
  • Document outputs - Make it clear what context variables you’re setting

Next Steps

Dive deeper into specific script types:

Learn about context and expressions: