Skip to content

Check tables and doc strings

This guide shows you how to check tabular and multi-line expectations. In Varar a step may return a value; Varar compares it against what the Markdown claims and anchors any mismatch to the exact cell or character span. There are three shapes.

Use this when each row of a table is an independent example. Write the table under a sentence that names its columns:

Each row gives an example of a decimal and a roman number:
| decimal | roman |
| ------: | :---- |
| 3 | III |
| 9 | IX |
| 40 | XL |

Bind a sensor to that sentence. It receives one row at a time as an object keyed by the header, and returns the computed columns:

import { toRoman } from './roman-numerals'
sensor('a decimal and a roman number', (_state, row: { decimal: string; roman: string }) => {
return { decimal: row.decimal, roman: toRoman(Number(row.decimal)) }
})

Each row runs as its own check. If toRoman(9) returned "VIIII", only the IX cell fails — with expected and actual, anchored to that cell.

Use this when the table is one expectation, not a list of independent rows. The sensor receives the full table as a list of rows (header row first) and returns the reproduced table:

Uppercase each one:
| before | after |
| ------ | ----- |
| vár | VÁR |
| bdd | BDD |
sensor('Uppercase each one:', (_state, rows: ReadonlyArray<ReadonlyArray<string>>) => {
return rows.slice(1).map(([before]) => ({ before, after: (before ?? '').toUpperCase() }))
})

The table fills this sensor’s only slot, so it is returned bare. Varar compares every cell of the returned table against the source, as exact strings.

Use this for multi-line text: rendered output, error messages, generated files. Write the expected text as a fenced code block:

Greet Bob:
```text
Hello, Bob!
```

The step receives the block’s text as a trailing string argument, and returns the text the software actually produces:

sensor('Greet {word}:', (_state, name, _body: string) => {
return [name, `Hello, ${name}!\n`]
})

The comparison is exact equality, including the trailing newline. This step has two slots — the captured {word} and the doc string — so it returns an array with one element per value, in order: [name, text]. A step whose doc string fills its only slot returns the text bare:

sensor('Greet Bob:', (_state, _body: string) => {
return 'Hello, Bob!\n'
})

See the sensors reference for the full return-value rules.

  • A differing table cell fails with a CellMismatchError: each wrong cell gets its own expected / actual, anchored to the cell’s source span — editors redden exactly the failing characters.
  • A differing doc string fails with a CellMismatchError too: a doc string is one cell, compared whole.
  • Returning a value of the wrong shape is a ReturnShapeError.
  • A table or doc string is itself a slot, so returning undefined (None / null / nil) from one of these steps is a ReturnShapeError, not a pass. Throw if you want to assert by hand instead.