4. An API test of your own
The example's tests were written for you. This chapter writes one: a file of its own, a value
captured from one response and used in the next request, and the three commands that keep a growing
suite tidy: fmt, check and refactor apply.
A file, and a value carried between requests
Section titled “A file, and a value carried between requests”A .tflw file anywhere under the project is part of the suite. This one places orders: two check
what an order costs, and the third reads one back. capture takes a value out of a response and
gives it a name; {name} puts it into a later step. The spacing is deliberately untidy, for fmt to
fix below:
cat > tests/my-order.tflw <<'EOF'@functionaltest "an order costs the price times the quantity" api POST /orders body {itemId: 1, qty: 2} expect status equals 201 expect body.total equals 2800
@functionaltest "a bigger order costs more" api POST /orders body {itemId: 1, qty: 5} expect status equals 201 expect body.total equals 7000
@functionaltest "an order reads back the way it was placed" api POST /orders body {itemId: 1, qty: 2} capture body.id as order api GET /orders/{order} expect status equals 200 expect body.qty equals 2EOFRun it:
npx tflw run tests/my-order.tflw09:32:10.402 ✓ an order costs the price times the quantity (11 ms)09:32:10.406 ✓ a bigger order costs more (3 ms)09:32:10.412 ✓ an order reads back the way it was placed (6 ms)
09:32:10.412 PASS 3/3 passed · env local · seed 6120 · now 2026-10-01T09:32:10.000Z · 26 ms…expect lines are the test. Each one names a part of the response (status, body.total,
body.qty) and what it must be. Assertions lists every matcher: equals,
contains, has count, matches, and the rest.
fmt: one layout for every file
Section titled “fmt: one layout for every file”tflw fmt rewrites files to one layout, the way a code formatter does. It changes whitespace only,
never what a file means, and names each file it changed:
npx tflw fmt tests/my-order.tflwformatted tests/my-order.tflw1 file, 1 formatted.npx tflw fmt --check changes nothing and exits 1 if any file would change, which is the form for
CI.
check: everything except running
Section titled “check: everything except running”tflw check parses and checks every file and sends no request. It is fast enough to run on every
save, and it needs none of the suite's secrets:
npx tflw check13 files checked, no problems found.
1 reuse hint found — apply with `tflw refactor apply <id>`:
reuse[RF001]: 2 occurrences of a similar 3-step sequence --> tests/my-order.tflw:3 (test "an order costs the price times the quantity") --> tests/my-order.tflw:9 (test "a bigger order costs more") = proposed: action post orders(qty, value) in shared/post-orders.tflw = call site: post orders(2, 2800) = call site: post orders(5, 7000) = apply: tflw refactor apply RF001Besides problems, check looks for the same steps repeated across tests and offers to make them
one action. The first two tests both place an order and check its status and total, so check
offers to extract those three steps. That is a hint, with an id, and it never changes the exit
code. The third test is not offered, though it places an order too: its next step captures from
that order's response, which an extracted action would keep to itself.
refactor apply: take the hint
Section titled “refactor apply: take the hint”npx tflw refactor apply RF001applied RF001: extracted `action post orders(qty, value)` into shared/post-orders.tflw updated: tests/my-order.tflwIt wrote the repeated steps into shared/post-orders.tflw as an action, with the two values that
differed as its parameters, replaced each copy with one line calling it, and imported the new file.
The file it rewrote still passes:
cat tests/my-order.tflwnpx tflw run tests/my-order.tflwimport "../shared/post-orders.tflw"@functionaltest "an order costs the price times the quantity" post orders(2, 2800)
@functionaltest "a bigger order costs more" post orders(5, 7000)
@functionaltest "an order reads back the way it was placed" api POST /orders body { itemId: 1, qty: 2 } capture body.id as order api GET /orders/{order} expect status equals 200 expect body.qty equals 2
…09:34:51.630 PASS 3/3 passed · env local · seed 4113 · now 2026-10-01T09:34:51.000Z · 22 ms…An action is the unit of reuse: steps with a name, called like a function, and able to give a
value back. Actions covers writing them by hand.
The docs, from the terminal
Section titled “The docs, from the terminal”tflw docs prints these pages in the terminal, one at a time, with no network. With no topic it lists
them, grouped as this site groups them:
npx tflw docstflw docs <topic> [section] — print a page of tflw's documentation. Topics:…Reference matchers Matchers generators Generators cli CLI flags diagnostics Diagnostic codes
run `tflw docs <topic>` to read one, e.g. `tflw docs matchers`, or `tflw docs <topic> <section>` for one part, e.g. `tflw docs cli run`.the same pages, with pictures, are at https://deepak-tuteja.github.io/tflw.A topic and a word print one section of a page, and a word that is not a topic is looked for among
every page's section titles. The Coffee Shelf's checkout tests make their keys with unique, and this
is what it promises:
npx tflw docs uniqueVariables, generators & expressions › `unique` vs. `random`…(part of `tflw docs variables`)And tflw spec lists every construct this build knows: each keyword, matcher, generator and
diagnostic code. It is the answer to does my version have this?:
npx tflw spec…declaration: test crawl action…What the language leaves out is as deliberate as what it has: a test has no if, no loop and no
boolean operator. That line is the fence. A step that needs logic calls a
helper module through use, and the escape hatch shows how.
You now have
Section titled “You now have”A test file of your own, tests/my-order.tflw, formatted, checked and passing, calling an action
in shared/ that refactor apply extracted from it.
Next, or instead
Section titled “Next, or instead”- Next: 5. A browser test.
- Writing API tests in depth: Functional tests and Variables.
- Sign-ins and acting as more than one user: Sessions.
- Every command in this chapter, with all its flags:
tflw fmt,tflw check,tflw refactor.