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
Recommended: Separate Debug Folder
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 ScenariosBenefits:
- 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
- Navigate to your “Debug Flows” folder
- Click New Test Case
- Name it: “Debug - [Scenario]”
- Example: “Debug - Order Payment Flow”
- Example: “Debug - Multi-tenant Auth”
- Click Create
Step 2: Build Flow
Add nodes to represent your workflow:
Start with API nodes:
- Drag API Node onto canvas
- Connect from Start node
- Configure request
- 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:
- Add Context Operation node after API call
- Use JSONata to extract values
- Store in context variables
- Use in subsequent nodes
Step 4: Run and Inspect
- Click Run button
- Watch execution in real-time
- Inspect data at each step
- Identify issues
- 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 priceRun 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.idInspect 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 CallUse for: Ordered operations
IF Node
Conditional branching:
IF Node
├─ Condition: $context.userRole = "admin"
├─ THEN: Admin-specific logic
└─ ELSE: Regular user logicConditions use JSONata:
// Check equality
$context.status = "active"
// Check existence
$exists($context.token)
// Numeric comparison
$context.amount > 100
// Complex logic
$context.isPremium and $context.credits > 0Loop Node
Iterate over arrays:
Loop Node
├─ Array: $context.users
├─ Item variable: $loopUser
└─ Body: Process each userAccess 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 SettingsUse 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.authTokenMultiple values:
// Store object
{
"userId": response.id,
"userName": response.name,
"userEmail": response.email
}
// → Stores in $contextUsing Variables
Reference in subsequent nodes:
In URLs:
{{baseUrl}}/users/{{$context.userId}}/ordersIn 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:
- Add Assertion nodes after API calls
- Define expected behavior
- Run to validate
- Flow becomes automated test
Before (debugging):
API Call → Inspect response manuallyAfter (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 FlowAdding 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:
- Previous step response
- Context variables extracted correctly
- Variable names match (case-sensitive)
- 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 expectationsStep 2: Move to Test Suites
- Copy flow from Debug Flows folder
- Paste into appropriate Test Suite folder
- Rename (remove “Debug -” prefix)
- Update documentation
Step 3: Enable in CI/CD
- Add to deployment/runner
- Run in pipeline
- Monitor results
- Fix any issues
Tips & Tricks
Rapid Iteration
- Keep flow open during debugging
- Modify single node
- Re-run entire flow
- 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:
- Right-click node
- Select “Run from here”
- Uses existing context
- 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
| Aspect | Local Requests | Test Flows |
|---|---|---|
| Steps | Single | Multiple |
| Flow control | No | Yes |
| Data passing | Manual | Automatic |
| Reusability | Low | High |
| Use case | Quick test | Complex scenario |
When to use Test Flows: Multi-step workflows, data dependencies, conditionals
Test Flows vs Debug Collections
| Aspect | Debug Collections | Test Flows |
|---|---|---|
| Organization | Folders | Flow nodes |
| Execution | One at a time | Automated sequence |
| Data extraction | Manual | Automatic |
| Use case | Request library | Complex workflows |
When to use Test Flows: When requests depend on each other
Next Steps
- Local Requests - Quick, temporary testing
- Debug Collections - Organized request library
- Node Reference - Learn about all available nodes
- JSONata Guide - Master data extraction
- Testing Patterns - Convert to automated tests
Questions? Join our Discord community for help!