Principle:Microsoft Playwright Add Assertions
| Knowledge Sources | |
|---|---|
| Domains | Testing, Code_Generation, Test_Verification |
| Last Updated | 2026-02-11 00:00 GMT |
Overview
Adding verification steps during test recording captures expected element states (visibility, text content, values, checked state, ARIA snapshots) so that generated tests not only replay actions but also validate application behavior.
Description
A test without assertions is merely a script that exercises the application without verifying correctness. The assertion recording principle addresses this by allowing the user to switch into assertion modes during a recording session, then click on elements to generate verification statements automatically.
Assertion recording operates through a modal interface:
- Recording mode: The default mode where user clicks, fills, and other interactions are captured as actions.
- Assertion modes: Specialized modes where clicks on elements generate assertions rather than actions. Each assertion mode targets a specific property of the element:
- Assert visibility: Generates a check that the element is visible on the page (e.g.,
toBeVisible()). - Assert text: Generates a check that the element contains or exactly matches specific text content (e.g.,
toContainText()ortoHaveText()). - Assert value: Generates a check that an input element has a specific value (e.g.,
toHaveValue()). - Assert checked: Generates a check that a checkbox or radio button is in a specific checked state (e.g.,
toBeChecked()). - Assert snapshot: Generates an ARIA snapshot assertion that captures the accessibility tree structure of an element (e.g.,
toMatchAriaSnapshot()).
- Assert visibility: Generates a check that the element is visible on the page (e.g.,
The assertion recording process works as follows:
- The user clicks an assertion mode button in the inspector UI.
- The recorder switches from action capture to assertion capture.
- The user hovers over elements, seeing a highlight indicating which element will be asserted.
- The user clicks an element, and the recorder reads the relevant property (text, value, visibility, checked state, or ARIA tree).
- An assertion action record is emitted and translated to language-specific assertion code.
- The user can return to recording mode to continue capturing actions.
This interleaving of actions and assertions produces tests that both exercise the application and verify its correctness in a single pass.
Usage
Apply this principle when:
- Verifying UI state after actions: After filling a form and submitting, assert that a success message is visible.
- Validating computed content: Assert that a calculated total, formatted date, or dynamic label contains the expected text.
- Checking form state: Assert that checkboxes are checked, inputs have values, or select elements show the correct option after interaction.
- Capturing accessibility contracts: Use ARIA snapshot assertions to verify that the accessibility tree matches expectations, catching regressions in screen reader compatibility.
- Establishing preconditions: Add assertions at the beginning of a recording to verify that the page is in the expected initial state before proceeding with actions.
Best practices for assertion recording:
- Assert after key actions: Add assertions after each significant state change, not just at the end.
- Prefer specific assertions: Use
toHaveText()overtoBeVisible()when text content matters, as it catches more regressions. - Use ARIA snapshots for complex components: For dropdown menus, tables, and tree views, ARIA snapshots capture the full structure.
- Keep assertions focused: Each assertion should verify one thing. Multiple assertions on different elements are preferable to no assertions at all.
Theoretical Basis
Assertion recording extends the basic action recording model with a mode system:
MODE_SYSTEM:
recording -> captures actions (click, fill, select, navigate, ...)
assertingText -> captures text content of clicked element
assertingValue -> captures input value of clicked element
assertingVisibility -> captures visibility state of clicked element
assertingSnapshot -> captures ARIA tree of clicked element
TRANSITION(current_mode, user_input):
button_click("Assert Text") -> assertingText
button_click("Assert Visibility") -> assertingVisibility
button_click("Assert Value") -> assertingValue
button_click("Assert Snapshot") -> assertingSnapshot
button_click("Record") -> recording
element_click(in assertion mode) -> emit assertion, stay in mode
ASSERTION_GENERATION(mode, element):
assertingText:
text = element.textContent
if text is simple -> toHaveText(text)
if text is partial match -> toContainText(text)
assertingValue:
value = element.value
-> toHaveValue(value)
assertingVisibility:
-> toBeVisible()
assertingSnapshot:
ariaTree = computeAriaTree(element)
-> toMatchAriaSnapshot(ariaTree)
The key design insight is that assertion modes are sub-modes of recording, not a separate state. The recorder remains active, selectors are still generated the same way, and the output still flows through the same code generation pipeline. Only the interpretation of the click changes: instead of emitting an action, the recorder emits an assertion.
This unified model means that assertions and actions can be freely interleaved in the action stream without special handling in the code generator.