Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If a w2ui overlay appears during a headed Cypress run but disappears in cypress run, classify the failure before changing the test. The overlay may not have been created, may exist but fail Cypress visibility rules, may be clipped by a different viewport, may have been dismissed by an outside click, or may behave differently in the browser used by CI.

The reliable fix is to trigger the control with a real Cypress action, wait for the overlay’s DOM node and meaningful content, assert visibility, control application and screen dimensions separately, then reproduce the run with the same browser as CI. Save a screenshot or video at each failure point so you can distinguish a selector problem from CSS, geometry, dismissal, or browser-parity problems.

What a w2ui overlay is—and why the DOM alone is not enough

w2ui describes an overlay as a popup within the page. It is provided by w2utils, not by the w2popup object. The w2overlay plugin places the popup below or above its target and supports alignment, offsets, tip controls, dimensions, classes, custom styles, callbacks, and an openAbove option. An outside click hides it, and a unique name permits multiple overlays; normally only one is displayed at a time.

That lifecycle explains many intermittent tests: the node is created only after the trigger runs, it can be removed or replaced when the target is re-rendered, and a subsequent command can dismiss it before the assertion executes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Do not confuse overlays with tags

w2ui tags follow their target and are destroyed when that target is destroyed. If your test causes a component to render a new input, the old transient UI is no longer associated with the new target. Re-query the newly rendered target and open a fresh overlay instead of retaining a subject from before the render.

“In the DOM” does not mean “visible”

Cypress runs in a real browser and evaluates styles, layout, hit testing, and document membership. An overlay can therefore exist while having display:none, visibility:hidden, zero dimensions, zero opacity, an off-screen rectangle, a low z-index, or another element covering it. A selector assertion can pass while .should('be.visible') or a click fails.

A repeatable diagnosis sequence

  1. Prove the trigger is real

    Use the same user action that opens the overlay: usually click or focus. Assert that the target exists and is interactable before opening it. If the target is replaced during a render, obtain a new Cypress subject after the render completes.

  2. Wait for a meaningful condition

    Query the overlay’s stable class, id, role, or distinctive text after the trigger. Cypress retries queries and assertions, so this is preferable to a fixed sleep. Use the selector emitted by the w2ui version in your application; prefer a stable id, role, or text over a positional selector.

    Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  3. Separate existence from visibility

    First determine whether the node exists. If it does, inspect computed styles and geometry. A missing node points to trigger timing, a changed selector, or an application error. A present-but-hidden node points to CSS, positioning, clipping, dismissal, or browser timing.

  4. Check for accidental dismissal

    w2ui hides an overlay on an outside click. A later Cypress click, a blur caused by focusing another field, or a re-render can close it before the assertion. Keep the open-and-assert sequence together and avoid commands that move focus until the overlay checks are complete.

  5. Control the two kinds of size

    Set the application viewport with cy.viewport(width, height) or project configuration. Separately, set the headless browser’s screen dimensions when screenshot or video dimensions matter. Cypress documents a 1280×720 headless rendering default with device pixel ratio 1. Screen dimensions used for screenshots and videos are not the same setting as the application viewport.

  6. Match the CI browser

    Run headed with the browser and version used by CI, then compare screenshots and video. Cypress launches browsers headlessly by default for cypress run, including Electron, Chrome/Chromium/Edge, and Firefox; experimental WebKit is also available. Electron is a particular parity risk because Cypress’s bundled Electron is deprecated and its embedded Chromium can trail current Chrome.

    Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  7. Inspect clipping and stacking

    Look for overflow:hidden, transformed ancestors, restrictive containers, viewport-edge clipping, and conflicting z-index values. Check the overlay’s bounding rectangle and the element that occupies the same point on the page.

A stable Cypress test pattern

This test keeps the trigger, overlay query, and visibility assertion in one flow. Replace the selector with the stable markup emitted by your application.

describe('w2ui overlay', () => {
  it('opens and is visible in headless mode', () => {
    cy.viewport(1280, 720)

    cy.get('#input-overlay')
      .should('exist')
      .and('be.visible')
      .click()

    cy.get('.w2ui-overlay')
      .should('exist')
      .and('be.visible')
      .contains('Expected overlay text')
      .should('be.visible')
  })
})

If the overlay is intentionally outside the normal flow, assert its document location and visibility before trying to click an item inside it. If your markup provides a unique id or role, use that instead of a broad .w2ui-overlay selector.

Instrument a failing run instead of guessing

Add temporary diagnostics after the trigger. They tell you whether the failure is creation, CSS, geometry, or coverage.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
cy.get('#input-overlay').click()

cy.get('.w2ui-overlay').then(($overlay) => {
  const node = $overlay[0]
  const style = window.getComputedStyle(node)
  const rect = node.getBoundingClientRect()

  cy.log(`display: ${style.display}`)
  cy.log(`visibility: ${style.visibility}`)
  cy.log(`opacity: ${style.opacity}`)
  cy.log(`position: ${style.position}`)
  cy.log(`z-index: ${style.zIndex}`)
  cy.log(`rect: ${rect.x},${rect.y} ${rect.width}x${rect.height}`)

  expect(node.ownerDocument).to.equal(document)
})

A zero-width or zero-height rectangle indicates layout or timing, not a selector typo. A rectangle outside the viewport suggests alignment, openAbove, offsets, or clipping. A normal rectangle with a failing click suggests a covering element or stacking conflict. Capture a Cypress screenshot immediately after this block to preserve the state before another command dismisses the popup.

Make viewport and screen settings explicit

Use a project viewport that reflects the layout you intend to test, then override it in a focused test when reproducing an edge condition.

import { defineConfig } from 'cypress'

export default defineConfig({
  e2e: {
    viewportWidth: 1280,
    viewportHeight: 720,
    setupNodeEvents(on, config) {
      on('before:browser:launch', (browser, launchOptions) => {
        if (browser.family === 'chromium') {
          launchOptions.args.push('--window-size=1280,720')
        }
        return launchOptions
      })
      return config
    }
  }
})

The viewport values control the application area. The launch hook changes the physical browser screen used for screenshots and videos. Keep both values deliberate; changing one does not implicitly change the other. If CI uses a different browser family, apply the corresponding launch configuration or compare artifacts without assuming identical window behavior.

Use artifacts to classify the failure

What you observe Likely layer Next check
No overlay node appears Trigger, selector, application error, or timing Assert the target before opening; inspect console output; wait for the stable overlay selector.
Node exists but is hidden CSS or dismissal Read display, visibility, opacity, dimensions, and focus state; check for an outside click or blur.
Node has a rectangle outside the viewport Geometry or viewport size Compare cy.viewport(), screen size, alignment, offsets, and openAbove.
Node is visible but cannot be clicked Covering element or stacking Inspect overflow, transforms, z-index, and the element at the click point.
Only Electron fails Browser parity Run with the installed Chrome or Chromium used by CI and compare screenshots or video.
Headed passes, headless fails at an edge Screen or DPR difference Reproduce with documented 1280×720 and DPR 1 defaults, then set dimensions explicitly.

Browser parity: Electron versus Chrome and other engines

First reproduce the CI command locally with the same browser family. If local debugging uses Chrome but CI uses Electron, a passing Chrome run does not establish parity. Cypress documents that its bundled Electron is deprecated and that embedded Chromium can behave differently from current Chrome. Once the failure is reproduced in the CI browser, compare headed and headless artifacts from that same engine. This prevents a browser mismatch from being mistaken for a w2ui defect.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Do not switch browsers merely to make a test green. Record which browser, version, viewport, screen dimensions, and device pixel ratio produced the result. A fix that depends on one engine’s layout can regress when the CI image changes.

Reliability and performance practices

  • Wait on state, not time: query the overlay and assert its meaningful content. Fixed sleeps make fast runs slower and still fail when rendering takes longer.
  • Keep the critical section short: open the overlay, verify it, perform the intended selection, and only then click elsewhere or trigger a render.
  • Use application-owned selectors: stable ids, roles, and distinctive text survive markup changes better than positional selectors.
  • Make geometry deterministic: use the same viewport for the test and the same screen dimensions when reviewing screenshots or video.
  • Capture evidence at the failure point: a screenshot after the trigger and a video of the run distinguish disappearance from never-created states.
  • Test dismissal deliberately: keep outside-click behavior in a separate assertion so the primary “opens” test does not accidentally exercise two lifecycle transitions at once.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common errors and fixes

“Expected to find element, but never found it”

The trigger may not have run, the selector may not match the current w2ui markup, or a render replaced the target. Assert the trigger first, inspect the post-render DOM, and use the current stable overlay selector.

“Element is not visible” although the node exists

Inspect computed display, visibility, opacity, dimensions, and rectangle. Then check whether an outside click, blur, or re-render hid it. Do not weaken the assertion until you know which state the application intends.

“Element is covered by another element”

Inspect stacking contexts, transformed ancestors, overflow clipping, and z-index values. A visible rectangle can still be unclickable when another element occupies the click point.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Overlay is clipped or appears on the wrong side

Compare the application viewport with the headless screen size. Check alignment, offsets, and openAbove behavior near viewport edges. Re-run with explicit dimensions rather than relying on defaults.

Only cypress run fails

Run the same browser headed, save screenshots and video, and compare with the headless artifact. Then repeat using the exact CI browser. If Electron is the outlier, test installed Chrome or Chromium before changing application CSS.

The test passes alone but fails in a suite

A previous command may leave focus elsewhere, click outside the overlay, or trigger a component re-render. Isolate the open-and-assert flow, re-query after renders, and keep each test’s cleanup from dismissing the next test’s popup.

Or skip the browser setup

When you need a rendered page image for debugging or evidence rather than an interactive Cypress assertion, ScreenshotNeo provides a single GET request. It accepts a URL and returns PNG, JPEG, WebP, or PDF; its cleanup steps accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets before capture, with each step independently switchable. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers. An MCP server supplies take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

See the ScreenshotNeo documentation for request options and authentication.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Every feature is available on every plan. The Free plan includes 1,000 shots per month with no card; paid plans are $5 for 3,000, $15 for 15,000, $39 for 60,000, $99 for 250,000, and $249 for 1,000,000. Yearly billing gives two months free. Create a free ScreenshotNeo account to start with 1,000 screenshots a month and no card.

Frequently Asked Questions

How should I protect a test from w2ui selector changes?

Expose an application-owned id, role, or distinctive text for the overlay and use that contract in Cypress. Re-check the emitted markup when upgrading w2ui instead of relying on a positional class.

How can I verify outside-click dismissal itself?

Make it a separate test: open the overlay, assert visibility, click a deliberate outside target, and assert the overlay is hidden or removed. Keeping this transition separate avoids masking an opening failure.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should I increase Cypress retries globally for this problem?

No. First wait on the overlay’s real DOM and content conditions. Increasing global retries can hide a geometry, dismissal, or browser-parity defect and slows unrelated tests.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.