Input Steps

Input steps are the pointer and touch toolkit: hover variants, double / right / middle clicks, modifier-key clicks, drag-and-drop, touch taps, and viewport resizing. They pick up where the core click and press steps stop - the gestures behind mega-menus, tooltips, context menus, kanban boards, spreadsheet-style editing, and multi-row selection.

Every step in this group addresses its target with a CSS selector (#id, .class, [data-testid=...], or any compound selector) and operates on the first match. Under the hood each gesture is a Playwright locator action, so the usual auto-waiting applies: the element must be attached, visible, and stable before the pointer moves. Like all state-changing steps, each gesture is followed by a silent BBR smart-settle pass so menus, drop targets, and context menus opened by the gesture are ready for the next step.

When a gesture cannot be performed, the step throws a friendly error naming the action and selector plus a hint - usually that the element must exist, be visible, and not be covered by an overlay. That last case (an interception overlay) is the most common real-world cause of pointer failures.

Quick reference

StepWhat it does
When I hover over "#nav-products"Hover the mouse pointer over an element.
When I move the pointer to "#cta"Alias for hover, phrased as pointer movement.
When I double-click on "#row-1"Double-click an element (also double click).
When I right-click on "#row-1"Right-click (context menu) an element (also right click).
When I middle-click on "a.external"Middle-click an element (also middle click).
When I click on "#row-1" while holding "Shift"Click while holding Shift, Control, Alt, or Meta.
When I drag "#card-1" to "#column-done"Drag a source element onto a target element.
When I set the viewport size to 1280x720Resize the browser viewport to WxH pixels.
When I tap on "#cta"Touch-tap an element, falling back to click without touch support.

Steps in detail

When I hover over "..." / When I move the pointer to "..."

Two phrasings for the same Playwright hover() action. Use them to open hover-triggered menus, reveal tooltips, or fire mouseenter handlers before asserting the revealed content. The pointer stays where you left it, so a hover followed by a click on the revealed item works naturally.

When I hover over "#nav-products"
Then I should see "All products"
When I move the pointer to ".tooltip-trigger"
Then ".tooltip" should be visible

When I double-click on "..."

Playwright dblclick(). Both double-click and double click spellings match. Typical uses: entering edit mode on a grid cell or opening an item from a file-tile view.

When I double-click on "td.editable-cell"
When I double click on ".file-tile"

When I right-click on "..." / When I middle-click on "..."

Non-primary button clicks (button: 'right' / button: 'middle'), with hyphenated and spaced spellings. Right-click is the way to open custom context menus; note it triggers the page's contextmenu handler, not the browser's native menu. Middle-click fires the click with the auxiliary button - it will not open a new tab in the automated browser.

When I right-click on ".tree-node"
Then I should see "Rename"
When I middle click on "a.external"

When I click on "..." while holding "..."

Clicks with a modifier key held. The modifier must be one of Playwright's names - Shift, Control, Alt, Meta (the error hint lists them if you pass anything else). This is the step for range-select and multi-select interactions in lists and tables.

When I click on "#row-1" while holding "Shift"
And I click on ".checkbox" while holding "Control"

When I drag "..." to "..."

Wraps Playwright's dragTo(): both elements are resolved first, then a full HTML5 drag sequence runs from source to target. Both must exist and the target must accept drops - libraries that only react to raw mouse events may need a page-specific step instead.

When I drag "#card-1" to "#column-done"
Then I should see "Done (1)"
When I drag ".file-tile" to "#trash"

When I set the viewport size to WxH

Resizes the viewport to exact pixel dimensions, e.g. 1280x720 or 375x667, for responsive checks mid-scenario. If the browser was launched in fluid-viewport mode the step fails with a hint to set a fixed contextOptions.viewport in the Playwright config. For named breakpoints (mobile, tablet, desktop) prefer the responsive steps group.

When I set the viewport size to 375x667
Then I should see an "button.menu" element
When I set the viewport size to 1920x1080

When I tap on "..."

Touch-taps the element. If the browser context was not created with hasTouch: true, the step transparently falls back to a regular click, so the same scenario runs in desktop and mobile-emulation profiles without edits.

When I set the viewport size to 375x667
And I tap on ".bottom-nav-item"
Then I should see "Menu"

Complete example

Feature: Kanban board pointer interactions

  Scenario: Move a card with drag-and-drop and manage it via the context menu
    Given I am on "/board"
     When I hover over "#card-1"
     Then I should see "Drag to move"
     When I drag "#card-1" to "#column-done"
     Then I should see "Done (1)"
     When I right-click on "#card-1"
     Then I should see "Archive"
     When I click on "#row-1" while holding "Shift"
      And I double-click on "td.editable-cell"

  Scenario: The board works on a phone-sized viewport
    Given I am on "/board"
     When I set the viewport size to 375x667
      And I tap on ".bottom-nav-item"
     Then I should see "Menu"

Tips

  • If a gesture fails with an interception error, something is covering the target - dismiss overlays and cookie banners first, or wait for animations to finish.
  • Modifier-click on macOS conventions: use Meta for Cmd-click behavior and Control for Ctrl-click; scenarios stay portable if the app treats both as multi-select.
  • These steps take CSS selectors only. To keep feature files readable, register long selectors once with the selector registry and reference short names.

Back to all step groups