Skip to main content

CORE SYNTAX

Expressions

Execute JavaScript functions, query data with XPath and JsonPath, and embed dynamic expressions directly in JSON and XML.

Benefits of Expressions

  • JavaScript integration: Use full JavaScript including ES6 features for complex logic
  • Query languages: Extract data with XPath for XML and JsonPath for JSON
  • Embedded expressions: Inject dynamic values using #(expression) syntax
  • Reusable functions: Define JavaScript functions for data transformation and validation
  • Built-in utilities: Access Karate's utility functions for filtering, mapping, and data manipulation

Simple Expressions

Execute JavaScript directly for calculations, string operations, and basic conditional logic.

Gherkin
Feature: Basic JavaScript expressions

Scenario: String operations
* def firstName = 'John'
* def lastName = 'Doe'
* def fullName = `${firstName} ${lastName}`
* match fullName == 'John Doe'

* def email = firstName.toLowerCase() + '@example.com'
* match email == 'john@example.com'

Scenario: Number calculations
* def price = 50
* def quantity = 3
* def subtotal = price * quantity
* match subtotal == 150

* def discount = 10
* def total = subtotal - discount
* match total == 140

Scenario: Conditional logic
* def age = 30
* def isAdult = age >= 18
* match isAdult == true

* def discount = age >= 65 ? 0.20 : age >= 18 ? 0.10 : 0
* match discount == 0.10

* def accountType = age >= 65 ? 'senior' : age >= 18 ? 'adult' : 'minor'
* match accountType == 'adult'

Embedded Expressions

Inject dynamic values into JSON and XML using #(expression) syntax. Types are preserved (numbers stay numbers, booleans stay booleans), and you can execute any JavaScript expression inline.

When to Use Embedded Expressions

Use #(expression) when you need to:

  • Build API request payloads with dynamic values
  • Template JSON from files with test-specific data
  • Preserve data types (numbers as numbers, not strings)
  • Mix static structure with dynamic values

Basic Variable Embedding

Embed simple variables into JSON while preserving their types.

Gherkin
Feature: Basic embedded expressions

Scenario: Embed variables into API request
* def userId = 12345
* def userName = 'john.doe'
* def isActive = true

* def userRequest =
"""
{
id: '#(userId)',
username: '#(userName)',
active: '#(isActive)'
}
"""

* match userRequest.id == 12345
* match userRequest.username == 'john.doe'
* match userRequest.active == true

Embedded Calculations

Execute calculations directly within JSON using embedded expressions.

Gherkin
Feature: Embedded calculations

Scenario: Calculate values in API request
* def basePrice = 100
* def quantity = 5

* def orderRequest =
"""
{
basePrice: '#(basePrice)',
quantity: '#(quantity)',
subtotal: '#(basePrice * quantity)',
tax: '#(basePrice * quantity * 0.08)',
total: '#((basePrice * quantity) * 1.08)'
}
"""

* match orderRequest.subtotal == 500
* match orderRequest.tax == 40
* match orderRequest.total == 540

Conditional Logic in Embedded Expressions

Use ternary operators for conditional values.

Gherkin
Feature: Conditional embedded expressions

Scenario: Apply conditional discount
* def customerType = 'premium'
* def orderAmount = 100

* def invoice =
"""
{
amount: '#(orderAmount)',
customerType: '#(customerType)',
discount: '#(customerType == "premium" ? 15 : 5)',
finalAmount: '#(orderAmount - (customerType == "premium" ? 15 : 5))'
}
"""

* match invoice.discount == 15
* match invoice.finalAmount == 85

Embedded vs Enclosed

Choose between #(expression) for mixing static and dynamic values, or ({ ... }) for fully dynamic structures.

Gherkin
Feature: Embedded vs enclosed JavaScript

Scenario: Compare both approaches
* def userName = 'John'
* def userAge = 30

# Embedded: mix static JSON with dynamic values
* def embedded = { name: '#(userName)', age: '#(userAge)', email: '#(userName.toLowerCase() + "@example.com")' }

# Enclosed: entire object is JavaScript
* def enclosed = ({ name: userName, age: userAge, email: userName.toLowerCase() + '@example.com' })

# Both produce identical results
* match embedded == enclosed
When to Use Each

Use embedded #(expression) when you have mostly static JSON with a few dynamic values. Use enclosed ({ ... }) when your entire structure is dynamic or requires complex JavaScript logic.

JavaScript Functions

Define reusable functions for authentication, data generation, and response validation.

Inline Functions

Simple one-line functions for quick transformations.

Gherkin
Feature: Inline JavaScript functions

Scenario: Generate dynamic test data
* def randomId = function(){ return Math.floor(Math.random() * 10000) }
* def uuid = function(){ return java.util.UUID.randomUUID() + '' }

* def userId = randomId()
* def requestId = uuid()

* match userId == '#number'
* match requestId == '#string'

Multi-Line Functions

Use triple quotes for complex logic like data transformation or calculation.

Gherkin
Feature: Multi-line functions

Scenario: Calculate price with tax and discount
* def calculateTotal =
"""
function(price, quantity, discountPercent) {
var subtotal = price * quantity;
var discount = subtotal * (discountPercent / 100);
var taxableAmount = subtotal - discount;
var tax = taxableAmount * 0.08;
return taxableAmount + tax;
}
"""

* def total = calculateTotal(100, 3, 10)
* match total == 291.6

Functions for Dynamic Headers

Generate authentication headers dynamically for each request.

Gherkin
Feature: Dynamic header generation

Scenario: Generate headers with authentication
* def getAuthHeaders =
"""
function() {
var timestamp = new Date().getTime();
var requestId = java.util.UUID.randomUUID() + '';
return {
'X-Request-ID': requestId,
'X-Timestamp': timestamp,
'X-Client-Version': '1.0.0'
};
}
"""

* def headers = getAuthHeaders()
* match headers['X-Request-ID'] == '#string'
* match headers['X-Timestamp'] == '#number'
* match headers['X-Client-Version'] == '1.0.0'

Functions with Array Operations

Use ES6 arrow functions and array methods for data transformation.

Gherkin
Feature: Array transformations

Scenario: Filter and map data
* def users =
"""
[
{ name: 'John', age: 30, active: true },
{ name: 'Jane', age: 25, active: false },
{ name: 'Bob', age: 35, active: true }
]
"""

# Filter active users
* def activeUsers = users.filter(u => u.active)
* match activeUsers == '#[2]'

# Extract names
* def names = users.map(u => u.name)
* match names == ['John', 'Jane', 'Bob']

# Chain operations
* def activeNames = users.filter(u => u.active).map(u => u.name)
* match activeNames == ['John', 'Bob']

Karate Utilities

Access built-in functions through the karate object for common data operations.

Gherkin
Feature: Karate utility functions

Scenario: Common utilities
* def users = [{ name: 'John', age: 30 }, { name: 'Jane', age: 25 }]

# Filter with Karate function
* def filtered = karate.filter(users, function(u) { return u.age > 25 })
* match filtered == '#[1]'

# Map with Karate function
* def names = karate.map(users, function(u) { return u.name })
* match names == ['John', 'Jane']

# Array utilities
* def numbers = [1, 2, 2, 3, 3, 3]
* def unique = karate.distinct(numbers)
* match unique == [1, 2, 3]

# Object utilities
* def keys = karate.keysOf(users[0])
* match keys contains 'name'
* match keys contains 'age'
JavaScript Capabilities

Karate's Graal JS engine supports full ES6. Use native array methods (map, filter, reduce, find, some, every) directly on arrays. The karate object provides additional utilities like log(), jsonPath(), xmlPath(), distinct(), and sort().

JsonPath Queries

Extract and filter JSON data using JsonPath syntax with wildcards and conditional filters.

Gherkin
Feature: JsonPath operations

Scenario: Extract data from API response
# Simulating a real API response
* def apiResponse =
"""
{
success: true,
data: {
users: [
{ id: 1, name: 'Alice Johnson', role: 'admin', active: true },
{ id: 2, name: 'Bob Smith', role: 'user', active: true },
{ id: 3, name: 'Carol White', role: 'user', active: false }
]
}
}
"""

# Extract all user names using JsonPath
* def allNames = $apiResponse.data.users[*].name
* match allNames == ['Alice Johnson', 'Bob Smith', 'Carol White']

# Get first user
* def firstUser = $apiResponse.data.users[0]
* match firstUser.name == 'Alice Johnson'

# Check response status
* def status = $apiResponse.success
* match status == true

JsonPath Filters

Apply conditional filters to extract specific data from arrays.

Gherkin
Feature: JsonPath filters

Scenario: Filter API response data
* def apiResponse =
"""
{
success: true,
data: {
users: [
{ id: 1, name: 'Alice Johnson', role: 'admin', active: true },
{ id: 2, name: 'Bob Smith', role: 'user', active: true },
{ id: 3, name: 'Carol White', role: 'user', active: false }
]
}
}
"""

# Filter active users only
* def activeUsers = karate.jsonPath(apiResponse, "$.data.users[?(@.active == true)]")
* match activeUsers == '#[2]'

# Extract names of admin users
* def adminNames = karate.jsonPath(apiResponse, "$.data.users[?(@.role == 'admin')].name")
* match adminNames == ['Alice Johnson']

# Filter active users with specific role
* def activeRegularUsers = karate.jsonPath(apiResponse, "$.data.users[?(@.active == true && @.role == 'user')]")
* match activeRegularUsers == '#[1]'
* match activeRegularUsers[0].name == 'Bob Smith'

XPath Queries

Navigate and query XML documents using XPath syntax with attribute filters and predicates.

Gherkin
Feature: XPath operations

Scenario: Basic XPath
* def order =
"""
<order>
<id>12345</id>
<customer>
<name>John Doe</name>
<email>john@example.com</email>
</customer>
<items>
<item>
<product>Laptop</product>
<price>999.99</price>
</item>
<item>
<product>Mouse</product>
<price>29.99</price>
</item>
</items>
</order>
"""

# Extract values using get keyword
* def orderId = get order /order/id
* def customerName = get order /order/customer/name
* match orderId == '12345'
* match customerName == 'John Doe'

# Array access (XPath uses 1-based indexing)
* def firstProduct = get order /order/items/item[1]/product
* match firstProduct == 'Laptop'

Advanced XPath

Use attribute filters, predicates, and node counting for complex queries.

Gherkin
Feature: Advanced XPath

Scenario: XPath with attributes and filters
* def inventory =
"""
<inventory>
<product category="electronics" available="true">
<name>Laptop</name>
<price>999</price>
</product>
<product category="electronics" available="false">
<name>Tablet</name>
<price>599</price>
</product>
<product category="books" available="true">
<name>Guide</name>
<price>49</price>
</product>
</inventory>
"""

# Attribute filters
* def available = karate.xmlPath(inventory, '//product[@available="true"]')
* match available == '#[2]'

# Value conditions
* def expensive = karate.xmlPath(inventory, '//product[price > 500]/name')
* match expensive == ['Laptop', 'Tablet']

# Count nodes
* def total = karate.xmlPath(inventory, 'count(//product)')
* match total == 3
XPath Indexing

XPath uses 1-based indexing ([1] for first element), unlike JavaScript's 0-based indexing. Use karate.xmlPath() for complex queries with predicates, attributes, and filters.

Dynamic Patterns

Generate test data and create environment-specific configurations using expressions.

Gherkin
Feature: Dynamic data generation

Scenario: Generate test users
* def generateUser =
"""
function(index) {
return {
id: index,
name: 'User' + index,
email: 'user' + index + '@test.com',
active: index % 2 === 0
};
}
"""

* def users = karate.repeat(3, generateUser)
* match users == '#[3]'
* match users[0].name == 'User0'
* match users[1].email == 'user1@test.com'

Scenario: Environment-based configuration
* def env = karate.env || 'dev'

* def config =
"""
{
baseUrl: '#(env == "prod" ? "https://api.example.com" : "https://api-" + env + ".example.com")',
timeout: '#(env == "prod" ? 60000 : 30000)',
debug: '#(env == "dev")'
}
"""

* assert config.timeout > 0
* match config.baseUrl contains env

Quick Reference

Common expression patterns for quick lookup.

TaskSyntaxExample
String concatenation`${var}` or +`Hello ${name}`
Embed variable#(variable){ id: '#(userId)' }
Conditional valuecondition ? true : false'#(age >= 18 ? "adult" : "minor")'
Calculate in JSON#(expression){ tax: '#(price * 0.08)' }
Call functionfunctionName(args)* def result = calculate(10, 20)
Filter array.filter(condition)users.filter(u => u.active)
Map array.map(transform)users.map(u => u.name)
Extract JsonPath$.path$.users[*].name
Extract XPath/pathresponse/order/id
Karate utilitykarate.method()karate.jsonPath(obj, '$.path')
Current timestampnew Date().getTime()* def now = new Date().getTime()
ISO date stringnew Date().toISOString()* def timestamp = new Date().toISOString()

Next Steps