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.

.norn
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.

.norn
wait 1s
wait 500ms

URL-Encoded Form Data

For application/x-www-form-urlencoded requests, separate headers from the body with a blank line. Norn accepts one field per line using either key=value or key: value, and it also accepts a single ampersand-delimited line such as name=John+Doe&email=john%40example.com.

.norn
POST https://httpbin.org/post
Content-Type: application/x-www-form-urlencoded

username=testuser
password=secret123
grant_type=password

If a form body line is not valid, Norn reports it as a syntax error before the request is sent. 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.

.norn
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.

.norn
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.

.norn
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. Structured values stay as objects, so debugger views and type checks see real object types instead of JSON strings.

.norn
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.

.norn
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.

.norn
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 if closes an if block. endif also works, but the docs use end if consistently.
  • Retry options are written inline as retry N and optional backoff N ms or backoff N s.
  • run readJson loads data relative to the current file.
  • Imported .norn files expose named requests and sequences; .nornapi imports expose header groups and endpoints.