Debugging ToolsTest Flows

Test Flows for Debugging

Use ReAPI’s visual test flow editor for debugging complex multi-step scenarios without writing assertions. Perfect for workflows that require flow control, data extraction, and conditional logic.

See also: Debugging Tools Overview for comparing Test Flows with Local Requests and Debug Collections.

What Are Test Flows for Debugging?

Test Flows are ReAPI’s visual flow-based test editor, but you don’t need assertions to use them for debugging. Build multi-step workflows to:

  • Debug complex scenarios: Login → extract token → use in next request
  • Use flow control: IF/ELSE, loops, parallel execution
  • Extract and pass data: Use JSONata to grab values from responses
  • Inspect at each step: See request/response data throughout the flow
  • Add assertions later: Convert to automated test when ready

Key Advantages

Why use Test Flows for debugging:

  • Multi-step workflows: Natural representation of complex scenarios
  • Data extraction: Automatic with JSONata (no manual copy-paste)
  • Conditional logic: IF nodes for different paths
  • Loops: Iterate over lists or retry logic
  • Context variables: Pass data between steps
  • Team sharing: Team members can run your debug flows
  • Evolution path: Add assertions → automated test

Unique capabilities:

  • Flow control (IF/ELSE, Loop, Parallel)
  • Automatic data extraction with JSONata
  • Context variable management
  • Visual representation of complex logic

Creating Debug Flows

Create a dedicated folder structure:

📁 Your Project
  📁 Test Suites (automated tests)
  │  ├─ User Management Tests
  │  ├─ Payment Flow Tests
  │  └─ API Contract Tests

  📁 Debug Flows (debugging only)
     ├─ Auth Debug Flow
     ├─ Payment Debug Flow
     └─ Complex Scenarios

Benefits:

  • Clear separation from production tests
  • Easy to find and run debug flows
  • Can convert to automated tests later
  • Team members can access your debug flows

Step 1: Create Test Case

  1. Navigate to your “Debug Flows” folder
  2. Click New Test Case
  3. Name it: “Debug - [Scenario]”
    • Example: “Debug - Order Payment Flow”
    • Example: “Debug - Multi-tenant Auth”
  4. Click Create

Step 2: Build Flow

Add nodes to represent your workflow:

Start with API nodes:

  1. Drag API Node onto canvas
  2. Connect from Start node
  3. Configure request
  4. Add more nodes as needed

Add flow control:

  • Sequence Node: Run steps in order
  • IF Node: Conditional branching
  • Loop Node: Iterate over items
  • Parallel Node: Run steps concurrently

Step 3: Extract Data

Use Context Operations to extract data:

  1. Add Context Operation node after API call
  2. Use JSONata to extract values
  3. Store in context variables
  4. Use in subsequent nodes

Step 4: Run and Inspect

  1. Click Run button
  2. Watch execution in real-time
  3. Inspect data at each step
  4. Identify issues
  5. Modify and re-run

No assertions needed - just inspect and verify manually.

Building Debug Flows

Example 1: Login and Fetch Data

Scenario: Debug user data retrieval with auth

Flow:

1. API: Login
   ├─ Method: POST
   ├─ URL: {{baseUrl}}/auth/login
   └─ Body: { "email": "...", "password": "..." }

2. Context Operation: Extract Token
   ├─ Expression: response.token
   └─ Store as: authToken

3. API: Get User Profile
   ├─ Method: GET
   ├─ URL: {{baseUrl}}/users/me
   └─ Headers: Authorization: Bearer {{authToken}}

4. Context Operation: Extract User ID
   ├─ Expression: response.id
   └─ Store as: userId

5. API: Get User Orders
   ├─ Method: GET
   ├─ URL: {{baseUrl}}/users/{{userId}}/orders
   └─ Headers: Authorization: Bearer {{authToken}}

Run this flow to inspect:

  • Login response
  • Extracted token
  • User profile data
  • User ID extraction
  • Orders list

Example 2: Conditional Order Processing

Scenario: Debug order flow with premium user discount

Flow:

1. API: Get User
   └─ Fetch user data

2. Context Operation: Extract Premium Status
   └─ Store: response.isPremium

3. IF Node: Check Premium Status
   ├─ Condition: $context.isPremium = true

   ├─ THEN: Apply Premium Discount
   │   └─ API: Apply Discount Code
   │       └─ Body: { "code": "PREMIUM10" }

   └─ ELSE: Regular Price
       └─ API: Skip Discount
           └─ No discount applied

4. API: Place Order
   └─ Submit order with final price

Run to see which path executes based on user status.

Example 3: Loop Through Items

Scenario: Debug bulk operations

Flow:

1. API: Get Items List
   └─ Fetch all items

2. Loop Node: Process Each Item
   ├─ Iterate over: response.items
   ├─ Current item: $loopItem

   └─ Loop body:
       ├─ API: Update Item
       │   └─ URL: {{baseUrl}}/items/{{$loopItem.id}}

       └─ Context Operation: Log Progress
           └─ Expression: "Processed " & $loopItem.id

Inspect each iteration to debug item processing.

Flow Control Nodes

Sequence Node

Run steps in order:

Sequence
  ├─ Step 1: API Call
  ├─ Step 2: Extract Data
  └─ Step 3: Another API Call

Use for: Ordered operations

IF Node

Conditional branching:

IF Node
  ├─ Condition: $context.userRole = "admin"
  ├─ THEN: Admin-specific logic
  └─ ELSE: Regular user logic

Conditions use JSONata:

// Check equality
$context.status = "active"
 
// Check existence
$exists($context.token)
 
// Numeric comparison
$context.amount > 100
 
// Complex logic
$context.isPremium and $context.credits > 0

Loop Node

Iterate over arrays:

Loop Node
  ├─ Array: $context.users
  ├─ Item variable: $loopUser
  └─ Body: Process each user

Access current item:

// In API URL
{{baseUrl}}/users/{{$loopUser.id}}
 
// In body
{
  "userId": "{{$loopUser.id}}",
  "email": "{{$loopUser.email}}"
}

Parallel Node

Run steps concurrently:

Parallel Node
  ├─ Branch 1: Fetch User Data
  ├─ Branch 2: Fetch Orders
  └─ Branch 3: Fetch Settings

Use for: Independent operations that can run simultaneously

Data Extraction with JSONata

Basic Extraction

Extract simple values:

// Extract token
response.token;
 
// Extract nested value
response.data.user.id;
 
// Extract from array
response.items[0].name;

Array Operations

Work with lists:

// Get all IDs
response.items.id
 
// Filter array
response.items[status="active"]
 
// Count items
$count(response.items)
 
// Map values
response.users.{ "id": id, "name": name }

Conditional Extraction

Extract based on conditions:

// Get first active user
response.users[(status = "active")][0];
 
// Check if exists
$exists(response.token) ? response.token : "no-token";
 
// Default value
response.data.value ? response.data.value : 0;

Context Variables

Storing Data

Use Context Operation nodes:

Simple value:

// Store token
response.token;
// → Stores as $context.authToken

Multiple values:

// Store object
{
  "userId": response.id,
  "userName": response.name,
  "userEmail": response.email
}
// → Stores in $context

Using Variables

Reference in subsequent nodes:

In URLs:

{{baseUrl}}/users/{{$context.userId}}/orders

In JSONata:

// In condition
$context.userId > 0;
 
// In expression
$context.userName & " - " & $context.userEmail;

In request bodies:

{
  "userId": "{{$context.userId}}",
  "token": "{{$context.authToken}}"
}

Inspecting Execution

Real-Time Monitoring

During execution:

  • Each node lights up as it runs
  • Green checkmark = success
  • Red X = failure
  • See timing for each step

Step-by-Step Inspection

Click on any completed node to see:

  • Request: Full request details
  • Response: Complete response
  • Context: Current context variables
  • Timing: Execution duration

Response Data

Inspect response at each step:

  • Status code
  • Headers
  • Body (formatted JSON)
  • Timing info

Context State

View context variables after each step:

  • What was extracted
  • Current variable values
  • How data flows between steps

Adding Assertions (Optional)

When ready to convert to automated test:

  1. Add Assertion nodes after API calls
  2. Define expected behavior
  3. Run to validate
  4. Flow becomes automated test

Before (debugging):

API Call → Inspect response manually

After (automated):

API Call → Assertion: response.status = 200
         → Assertion: $exists(response.data.user)

Best Practices

Naming Flows

Use descriptive names with “Debug” prefix:

Good:

  • “Debug - Order Payment Complete Flow”
  • “Debug - Multi-tenant User Switching”
  • “Debug - Webhook Processing”

Bad:

  • “Test Flow 1”
  • “Debug”
  • “My Flow”

Organizing Flows

Structure by feature:

📁 Debug Flows
  📁 Authentication
    ├─ Debug - Login Flow
    ├─ Debug - Token Refresh
    └─ Debug - Logout
  📁 Orders
    ├─ Debug - Create Order
    └─ Debug - Payment Flow

Adding Comments

Use Script nodes to add comments:

// Comment node
console.log("=== Starting order processing ===");
console.log("User ID:", $context.userId);
console.log("Order Total:", $context.orderTotal);

Helps document your debugging process.

Reusability

Build reusable debug flows:

  • Team members can run them
  • Document common scenarios
  • Serve as examples
  • Convert to automated tests later

Troubleshooting

Flow Fails at Step

Check:

  1. Previous step response
  2. Context variables extracted correctly
  3. Variable names match (case-sensitive)
  4. JSONata expressions are valid

Variable Not Found

Symptom: {{$context.variable}} not resolving

Solutions:

  • Check Context Operation node ran successfully
  • Verify variable name spelling
  • Ensure Context Operation stores to correct name
  • Check JSONata expression returns a value

IF Node Always Takes Same Path

Check:

  • Condition expression syntax
  • Context variable values
  • JSONata expression returns boolean
  • Use Script node to log condition value

Loop Not Iterating

Check:

  • Array expression is valid
  • Array is not empty
  • Loop body is connected correctly
  • Item variable name is used correctly

Converting to Automated Tests

When your debug flow is stable:

Step 1: Add Assertions

After each critical API call:

API Call
  └─ Add Assertion Node
      ├─ Status code = 200
      ├─ Response has required fields
      └─ Data meets expectations

Step 2: Move to Test Suites

  1. Copy flow from Debug Flows folder
  2. Paste into appropriate Test Suite folder
  3. Rename (remove “Debug -” prefix)
  4. Update documentation

Step 3: Enable in CI/CD

  1. Add to deployment/runner
  2. Run in pipeline
  3. Monitor results
  4. Fix any issues

Tips & Tricks

Rapid Iteration

  1. Keep flow open during debugging
  2. Modify single node
  3. Re-run entire flow
  4. Inspect changed behavior

Debugging Complex Conditionals

Add Script nodes to log values:

console.log("Condition check:")
console.log("isPremium:", $context.isPremium)
console.log("credits:", $context.credits)
console.log("Result:", $context.isPremium and $context.credits > 0)

Partial Flow Execution

Run from specific node:

  1. Right-click node
  2. Select “Run from here”
  3. Uses existing context
  4. Faster iteration

Saving Intermediate State

Use Context Operations to checkpoint:

{
  "checkpoint": "after-login",
  "timestamp": $now(),
  "data": $context
}

Comparison with Other Tools

Test Flows vs Local Requests

AspectLocal RequestsTest Flows
StepsSingleMultiple
Flow controlNoYes
Data passingManualAutomatic
ReusabilityLowHigh
Use caseQuick testComplex scenario

When to use Test Flows: Multi-step workflows, data dependencies, conditionals

Test Flows vs Debug Collections

AspectDebug CollectionsTest Flows
OrganizationFoldersFlow nodes
ExecutionOne at a timeAutomated sequence
Data extractionManualAutomatic
Use caseRequest libraryComplex workflows

When to use Test Flows: When requests depend on each other

Next Steps


Questions? Join our Discord community for help!