Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Checks: expect

The expect table: every check a step can make, and how each comparison reads.

  • expect retries until it holds or its timeout (5 s, --timeout-ms on the line or the run) runs out; exit, stdout, stderr, status, body, json and header read the last exec or http answer once. is compares numbers as numbers (1 is 1.0). A glob (request, download) has * for any run of characters and matches the whole URL or file name:
expectChecks
url/title is (or ==), contains, starts-with, ends-with, matches <value>the active tab
text "<t>", no text "<t>" [--within <target>]visible text, frames included, or inside an element
<target> visible, hidden, enabled, disabled, checked, unchecked, focused, editable, emptyan element’s state
<target> text, value, attr <name>, style <property> + a comparisonan element’s text, value, attribute or computed style
--selector <css> count is, >, >=, <, <= <n>how many match (exactly one --selector)
${var} + a comparisona saved value
js "<expression>" (or eval) [+ a comparison]a script in the page: truthy, or its value compared
js --file <script.js> [+ a comparison]the same, from a file next to the .bt (an expression, or a function body that returns its answer): for a check across rows or anything too long to quote
request <METHOD> <url glob> [status <n>], no request <METHOD> <url glob>a request the page made in this scenario (* in the URL matches anything)
request … json <$.path> + a comparisona value in the last matching response’s JSON: $, .key, [0], ["key"] ($.items[0].sku)
request … body + a comparisonthe last matching response’s body, as text (body contains "added to cart")
request … count + a comparisonhow many matching requests
cookie <name> [+ a comparison], no cookie <name>, cookie <name> absenta cookie of the scenario’s browser context
storage local|session <key> [+ a comparison | absent]Local or Session Storage
download <file glob>, no download …a finished download (then ${download.path}, ${download.name}: the latest match). Each scenario’s downloads go to a directory of its own beside its evidence (.bitti/runs/<time>/<scenario>/downloads, kept only when something came), so a name never carries over from another scenario; a second file of the same name in one scenario arrives as name (2).ext
download <file glob> compare <expected file> [--key <columns>] [compara flags…]the download is the same table as the expected file beside the .bt (compara on the PATH, or BITTI_COMPARA): CSV, NDJSON or Parquet, either side; compara’s flags (-i, --trim, --tolerance) pass through. A difference fails the step with compara’s counts and the reports it kept beside the scenario’s downloads: --report html,json,rows (the HTML report, the JSON summary of counts and column statistics, CSVs of the changed, added and removed rows) or none; the run’s --compare-report (compare_report in bitti.toml, default html) when the step doesn’t say, and compara’s own -o, --json or --export-dir win
console + a comparison, no console "<t>"a console message (any level)
no errorsno page exceptions or console errors
accessible [--selector <css>] [--tags wcag2a,wcag2aa,…] [--ignore <rule>,…]axe-core (built in, through navigera’s a11y, in a world of its own: the page never sees a window.axe) finds no violation in the page, or under the selector: WCAG 2.0 and 2.1 A and AA by default; --tags replaces that set (--tags wcag2a,wcag2aa,best-practice to add axe’s best practices); a failure names each rule, its impact, the first elements and what to fix
lcp, fcp, ttfb, load, inp <, <=, >, >= <time> (2.5s, 800ms; a bare number is ms); cls + a comparison and a score (0.1)a performance budget for the current page, as the browser measured it (navigera’s vitals): largest and first contentful paint, time to first byte, the load event (ms from the navigation’s start); the layout shift score (its largest session window, shifts after input left out); interaction to next paint, the slowest of the scenario’s clicks and key presses on this page so far (put it after them). A miss names the element behind it (3120 (#hero)). Not measured yet (the load event still to come, no interaction yet) is retried. Chrome keeps only interactions of 104 ms or more, so inp < 200ms passes when every one was quicker, and a budget under 104 ms is refused. Run under set cpu 4 and set network fast-3g to measure as a mid-tier phone
exit [is] <n>, stdout/stderr + a comparisonwhat the last exec gave
status [is] <n>, body + a comparison, json <$.path> [+ a comparison], header <name> [+ a comparison]the last http answer; a JSON object or array compared with is is compared as JSON (key order and 1 vs 1.0 don’t matter), with contains as a part of it (json $ contains '{"role": "shopper"}': the keys it names, at any depth; for an array, items that some item matches)
json <$.path> count + a comparisonhow many items the array (or keys the object) at the path has
json [<$.path>] schema <file.json>[#<pointer>]the answer (or the value at the path) is valid against a JSON Schema beside the .bt, or one inside a larger document (openapi.json#/components/schemas/Item: an OpenAPI 3 document in JSON, its $refs read in the whole document); a failure lists where it isn’t ($[1].price: expected number, got string "5"). See API tests for what it reads
json [<$.path>] snapshot <name> [--ignore <$.path>,…]the answer (or the value at the path) is what its baseline beside the .bt holds, <file>.bt.snapshots/<name>.json, compared as JSON; --ignore $.id,$.items[*].created leaves out what changes from run to run. With no baseline yet the run writes it and the step fails, so a person reads it first; --update-snapshots writes or replaces it. A difference names each path ($.total: 38, was 36)
time <, <=, >, >= <time> (300ms, 1.5s)how long the last http exchange took, redirects included
ax [<target>] matches + the tree indented under itthe page’s (or the target’s) accessibility tree, as navigera ax prints it, holds those lines: partially (button matches button "Place order") and in order, a line indented under another inside what that one matched, refs ignored, /regex/ (spaces allowed) for a name or a value
screenshot <name> [<target>] [--full-page] [--threshold 0.2] [--max-diff-pixels <n> | --max-diff-ratio <r>] [--mask <css>]…the viewport (or the element, or the whole page) as its baseline shows it, pixel by pixel; see below
not …any of them, negated

Made from docs/format.md.