Advanced Features
These language features are part of everyday Norn usage once your tests move beyond single-request flows.
Conditionals
Use if blocks to run steps only when a condition passes. Conditions support the same operators as assertions.
GET {{baseUrl}}/todos/1
if $1.status == 200
var userId = $1.body.userId
print "Todo Found" | "Fetching related user"
GET {{baseUrl}}/users/{{userId}}
assert $2.status == 200
end if Wait Commands
Pause execution between steps with seconds or milliseconds.
wait 1s
wait 500ms URL-Encoded Form Data
For application/x-www-form-urlencoded requests, separate headers from the body with a blank line and write each form field on its own line.
POST https://httpbin.org/post
Content-Type: application/x-www-form-urlencoded
username=testuser
password=secret123
grant_type=password This also works with header groups and captured requests such as var result = POST PostFormData FormData.
Retry and Backoff
Retry works on direct requests, named endpoints, and named requests. The HTTP client retries network failures, 5xx responses, and 429 responses.
var direct = GET "https://api.example.com/health" retry 2 backoff 200 ms
var endpoint = GET GetTodo(1) retry 2 backoff 100 ms
var named = run GetStatus retry 3 backoff 150 ms Script Execution
Run shell, JavaScript, or PowerShell scripts from a sequence. Captured output becomes a variable. PowerShell accepts both powershell and pwsh.
run bash ./scripts/seed-db.sh
var signature = run js ./scripts/sign.js {{payload}}
var data = run powershell ./scripts/query.ps1 When a script prints JSON, Norn parses it automatically so you can access properties and array elements directly.
assert data[0].id == 1
print "First Row" | "value={{data[0].value}}" JSON File Loading
Load structured test data from disk with run readJson, then read or update properties in memory.
var config = run readJson ./test-data.json
print "Config" | "timeout={{config.settings.timeout}}"
config.settings.timeout = 10000
config.users[0].name = "Updated Alice" Print Statements
Use print for lightweight debugging and execution breadcrumbs. print "Title" | "Body" creates a structured message.
print "Starting Test"
print "Auth" | "token={{token}}" Imports
Import .norn files to reuse named requests and sequences. File-level variables inside the imported file are resolved into those imported definitions.
import "./shared-utils.norn"
import "./api.nornapi"
test sequence SmokeFlow
run AuthRequest
var token = run SharedSetup
GET GetTodo(1) Json
assert $2.status == 200
end sequence Rules to Remember
end ifcloses anifblock.endifalso works, but the docs useend ifconsistently.- Retry options are written inline as
retry Nand optionalbackoff N msorbackoff N s. run readJsonloads data relative to the current file.- Imported
.nornfiles expose named requests and sequences;.nornapiimports expose header groups and endpoints.