Assertions
Verify outcomes with inline assertions and Assertion nodes — warn, fail, or fatal.
Assertions are how a flow proves the app did the right thing. Cofactor checks them two ways: inline assertions that ride along with an action, and Assertion nodes that stand on their own in the path.
01Inline vs. node
Use an inline assertion when the check belongs to the action that triggered it — "after I click Save, a success toast appears." The check runs immediately after the action completes, in the same step, so the verification stays tied to its cause.
Use an Assertion node when the check is its own step — a standalone verification between other steps, or a check that doesn't follow directly from one action. Add it from the node menu like any other node.
Both evaluate a condition you write in plain language, such as "Ticket appears in the list."
02Write the behavior the spec promises
Assertions describe observable product behavior. For a pinning flow, use "The named column stays fixed while the level columns scroll" and "After unpinning, the named column scrolls with the grid." Specify exact values only when the requirement calls for them.
Keep implementation details out of the condition text: DOM attributes, SVG paths, CSS classes, and arbitrary pixel thresholds are ways a verifier might observe the page, not new acceptance requirements. A chosen scroll distance belongs in the action. Confirm the intended user during browser preflight; assert identity at runtime only when the journey tests identity or authentication.
Check meaningful transitions before moving on or restoring state. Relative checks need a baseline captured in the current run, so a changed count or position is compared with what this run actually observed.
03Severity
Severity decides what a failed check does to the run.
| Severity | Behavior | Available on |
|---|---|---|
| Warn | The check didn't pass, but the flow continues and records a warning | Inline + node |
| Fail | The check didn't pass and the run is marked failed | Inline + node |
| Fatal | The check didn't pass and the run stops immediately | Inline only |
- Use Fail for required outcomes when later steps still provide useful evidence.
- Use Warn for non-blocking checks that still matter — flag an unexpected UI state for review without failing the whole run.
- Use Fatal (inline) when continuing past the failure would be pointless or misleading.
04Dynamic content
Assertion conditions support variables and macros — type $ to insert them. Cached assertions replay their verification code against the current run; they do not reuse an earlier pass/fail result. Changing values can still be checked deterministically using current-run inputs and captured baselines. Enable Always use agent evaluation when judging the requirement needs an agent, such as a subjective visual assessment.
05Reading results
Assertion outcomes appear directly on the relevant steps in run details, with a per-run summary of what passed, warned, or failed. A warn marks the step as a warning and the run continues; a fail (or fatal) marks the run failed.
06Best practices
- Prefer inline assertions when a check directly follows one action — it keeps cause and verification together.
- Reserve Assertion nodes for standalone or multi-step verification logic.
- Don't over-assert: a few meaningful checks beat many brittle ones. See Designing a good test.
- Use Warn only for an optional signal. Clarify ambiguous requirements instead of making a core outcome non-blocking.