Modal Steps

The modal steps cover HTML modal overlays end to end: asserting a modal is (or is not) on screen, checking its title and body text, clicking buttons inside it by text or by CSS selector, and closing it again. Modal flows are notoriously flaky in browser tests - overlays animate in, close buttons vary wildly between frameworks, and a "visible" check based on offsetParent lies for fixed-position containers. These steps are built around those realities.

How a modal is found is driven by the selector registry: if a modal selector is registered - either directly or via an active CMS / framework preset (Bootstrap, MUI, Drupal admin, and so on all ship one) - that selector wins; otherwise the steps fall back to the standards-based [role="dialog"], dialog. Visibility is derived from computed style (display, visibility, opacity) rather than offsetParent, which makes the check reliable for fixed-position modal containers.

The phrasings are deliberately flexible: I/we, a/the, and a trailing dialog are all optional, so Then I should see a modal and Then we should not see the modal dialog hit the same step. The interaction steps wait up to 10 seconds for a visible modal before acting, and the companion steps When I wait for the modal to appear / to disappear live in the wait steps group - use them around animated open/close transitions.

Quick reference

StepWhat it does
Then I should see a modalAssert a modal dialog is visible (add not for the inverse).
Then I should see a modal with title "Confirm Action"Assert a modal with the given title (heading text or title/aria-label) is visible.
Then I should see a "confirmation-modal" modalAssert a specific modal by id, class, or data-modal value is visible.
Then I should see "Are you sure?" in the modalAssert the modal contains (or with not, lacks) the given text.
Then the modal should contain "Welcome modal text"Alternate phrasing - checks the modal's plain innerText.
Then the modal should not contain "Goodbye"Assert the modal lacks the text (passes if no modal exists).
When I click "Confirm" in the modalClick a button or link inside the modal by its visible text.
When I click on "#close-btn" in the modalClick a CSS-selector-addressed element inside the modal.
When I close the modalClose via a recognized close button, or Escape as fallback (also: dismiss).

Steps in detail

Then I should see a modal / Then I should not see a modal

Asserts whether any modal (per the registered or fallback selector) is currently visible, using the computed-style visibility check. This is a point-in-time assertion - if the modal animates open, precede it with When I wait for the modal to appear.

When I click "show-modal" by attr
 And I wait for the modal to appear
Then I should see a modal

Then I should see a modal with title "Confirm Action"

Asserts a modal with the given title is visible (or not, with not). The title is matched two ways: as text inside a heading element within the modal (.modal-title, .dialog-title, h1-h3), or as a substring of a title / aria-label attribute. Either match counts, so it works for both classic Bootstrap-style titles and ARIA-labelled dialogs.

Then I should see a modal with title "Welcome"
 And I should not see a modal with title "Error"

Then I should see a "confirmation-modal" modal

Targets one specific modal when several could exist. If the identifier starts with # or . it is used as a raw CSS selector; a bare name is tried as an id, a class, and a data-modal attribute value. Visibility is checked on the first match.

When I click "delete-btn" by attr
 And I wait for modal to appear
Then I should see a "delete-confirmation-modal" modal

Then I should see "Are you sure?" in the modal

Asserts that the visible modal contains (or, with not, does not contain) the given text anywhere inside it. Uses a locator text filter, so nested markup does not matter.

Then I should see "Are you sure you want to delete this item?" in the modal
 And I should not see "Error occurred" in the modal

Then the modal should contain "Welcome modal text" / should not contain

Alternate phrasing that reads the modal's plain innerText and does a substring check - use it when the text is part of the modal body rather than a specific element; on failure it prints the actual text found. The negative form is lenient by design: it passes when no modal exists at all or when a modal exists without the text, which makes it safe to use right after closing a modal.

When I close the modal
Then the modal should not contain "Welcome"

When I click "Confirm" in the modal

Waits up to 10 seconds for a visible modal, then clicks the first clickable element inside it - button, a, [role="button"], submit/button inputs, or .btn - whose text matches. Variants like click "OK" button in the modal dialog are accepted. On failure you get a friendly error suggesting you open the modal first and check the button text.

When I click "trigger-modal" by attr
 And I wait for the modal to appear
 When I click "Confirm" in the modal
 Then I should not see a modal

When I click on "#close-btn" in the modal

Clicks a CSS-selector-addressed element scoped to the active modal. Distinct from the text variant above - use it for icon buttons with no readable text, or when the same text appears on multiple buttons and you need the selector to disambiguate.

When I click on "button[aria-label=Close]" in the modal
 And I click on "[data-testid=accept]" in the modal

When I close the modal / When I dismiss the modal

Waits for a visible modal, then looks for a recognized close control - .close, .modal-close, [data-dismiss="modal"], [aria-label="Close"], .btn-close, or any button with "close" in its class - and clicks it. If no close button is visible it presses Escape on the modal instead. If neither works, the error suggests registering a custom close-button selector.

When I close the modal
 And I wait for the modal to disappear
Then I should not see the modal

Complete example

Adapted from tests/features/modal-basic-example.feature, running against the examples/test--modal-dialogs.html fixture:

Feature: Modal Dialog - Basic Interactions

  Background:
    Given I am on "/test--modal-dialogs.html"

  Scenario: Open, verify, and confirm a modal
    Then I should not see a modal
    When I click "show-modal" by attr
     And I wait for the modal to appear
    Then I should see a modal
     And I should see "This is a sample modal dialog" in the modal
    When I click "Confirm" in the modal
     And I wait 1 second
    Then I should not see a modal

  Scenario: Verify specific modal by identifier
    When I click "delete-btn" by attr
     And I wait for modal to appear
    Then I should see a "delete-confirmation-modal" modal
     And I should see "Are you sure you want to delete this item?" in the modal
    When I click "Cancel" button in the modal dialog
     And I wait 1 second
    Then I should not see the modal dialog

Tips

  • If your framework's modals are not detected, register a modal selector (and related modal close, modal title keys) in the selector registry, or activate the matching CMS/framework preset - every preset exposes the canonical modal keys.
  • These steps target in-page HTML overlays. Native browser dialogs (alert, confirm, prompt) are handled by the dialog steps instead.
  • Always bracket animated modals with When I wait for the modal to appear / to disappear from the wait steps group to avoid racing the transition.

Back to all step groups