A browser test can pass perfectly while testing something that barely resembles the user’s experience.
This is not usually fraud or negligence. It is a side effect of how test environments evolve.
The test runner starts with a clean browser, a fixed viewport, a predictable location, a known account, and a URL pointing to a stable environment. Real users arrive with old cookies, narrow screens, unusual locale settings, browser extensions, consent choices, interrupted sessions, and devices your team may not own.
The more controlled the test environment becomes, the easier it is to forget what has been controlled away.
Headless mode is not merely Chrome without a window
Headless browsers have improved enormously.
For many applications, there is little practical difference between a headless and headed run. But “little difference” is not the same as “no difference.”
Problems can still emerge from:
- Font availability
- GPU acceleration
- Media permissions
- Window dimensions
- Focus behaviour
- Download handling
- Animation timing
- Browser visibility APIs
- Clipboard access
- Popups and new windows
This overview of why web applications break in headless mode provides a useful checklist.
The mistake is not using headless mode. Headless execution is practical and often necessary.
The mistake is assuming that one successful headless configuration represents every browser context that matters.
A sensible strategy is to run the large regression suite efficiently, then preserve a smaller group of high-risk flows for headed browsers, real devices, or both.
Responsive testing is not a screenshot exercise
Teams often treat responsive testing as a set of screenshots at three widths:
- Desktop
- Tablet
- Mobile
That is better than nothing, but responsive failures are not limited to visual differences.
A navigation element may remain visible but stop responding to touch. A modal may fit the viewport but place its close button beneath the browser chrome. A sticky footer may cover the final form field only when the mobile keyboard opens.
This guide to testing responsive breakpoints in real browsers explores the failures that appear between Chrome, Safari, and mobile viewports.
The useful assertion is rarely “the screenshot matches exactly.”
It is more likely:
- The user can reach the primary navigation.
- The checkout button remains visible and clickable.
- Text does not overlap interactive controls.
- The focus order remains usable.
- The page does not scroll horizontally.
- The virtual keyboard does not block the next action.
These assertions survive minor design changes while still protecting the user journey.
Preview environments are built to drift
Preview deployments are excellent for moving quickly. They also create a messy testing surface.
A preview may contain:
- A new frontend connected to an old API
- A partial database migration
- Different feature flags
- Missing background workers
- Temporary hostnames
- Expired credentials
- Stale test data
- A branch that has not received the latest configuration changes
When a browser test fails in that environment, the application code may not be the cause.
The article on building a browser QA checklist for feature flags, rollbacks, and environment drift is useful because it treats the environment as part of the test result.
Before debugging selectors, confirm what was actually deployed.
Record the commit, feature-flag state, service versions, test account, region, hostname, and relevant configuration. Without those details, a failure from yesterday may be impossible to reproduce today.
The first page is often determined before your test starts
Geo routing, cookie consent, language selection, and regional entry paths can change the application before the first automated click.
A user in France may see a consent banner that a user in the United States never sees. A request from the United Kingdom may be routed to a different domain. A returning user may bypass the region selector because a preference already exists in a cookie.
This comparison of Playwright and Selenium for testing cookie consent, geo routing, and region-specific entry paths highlights how much setup can be required before the visible workflow begins.
The most reliable regional tests usually control several variables together:
- IP location
- Browser locale
- Timezone
- Existing cookies
- Local storage
- Accepted consent state
- Application account region
Changing only the browser language may not be enough. Changing only the IP address may not be enough either.
The application may use several signals and resolve conflicts according to rules that are not documented anywhere.
Cross-domain authentication is a system, not a page
OAuth and SSO flows are where clean browser-test abstractions go to die.
The test leaves your application, reaches an identity provider, encounters a consent screen, opens a popup or redirect, and eventually returns with a new session.
Any part of that sequence can vary by account, browser policy, region, or previous consent.
This practical look at testing OAuth redirects, consent screens, and cross-domain login handoffs with Endtest outlines the real workflow more accurately than a simple “click Sign in” example.
The test should distinguish between several failures:
- The identity provider never opened.
- The user was already authenticated.
- The consent screen appeared unexpectedly.
- The callback URL was incorrect.
- The application received the callback but failed to create a session.
- The session was created but the frontend failed to update.
These are different bugs owned by different systems. A single timeout error hides that distinction.
Shadow DOM and accessibility can disagree with the screenshot
Modern component libraries frequently encapsulate controls inside Shadow DOM.
That creates a familiar situation: the button is clearly visible to a human, but the test cannot locate it using the selector strategy applied elsewhere in the application.
The reverse can happen too. A selector finds an element that appears correct visually, but its accessible name is missing or incorrect.
This guide to browser-testing platforms for Shadow DOM, accessible names, and component-library regressions is a reminder that the DOM tree, accessibility tree, and rendered interface are related but not identical.
A robust test may need to verify all three.
That is especially important when components are updated centrally. A small change to a shared button, modal, or input can create regressions across dozens of screens.
Editable grids expose browser differences quickly
Editable grids combine almost every difficult browser behaviour:
- Keyboard navigation
- Focus management
- Inline validation
- Virtualized rows
- Copy and paste
- Selection ranges
- Scrolling containers
- Delayed saves
- Optimistic updates
A grid can look correct while losing keystrokes or saving values into the wrong row.
This comparison of Endtest and Playwright for editable grids and keyboard-driven data entry provides a practical framework for deciding what to automate.
Do not test only the happy path of clicking a cell and entering text.
Test tabbing, escaping, invalid data, row changes, sorting after edits, interrupted saves, and the persistence of values after a reload.
Passkeys force the test outside the webpage
WebAuthn passkeys make authentication better for users and more complicated for browser automation.
The flow can depend on:
- The operating system
- The physical device
- A platform authenticator
- Browser policy
- Managed-enterprise settings
- Biometrics
- Cross-device QR flows
- Previously registered credentials
A simulated browser context can test some of this, but not everything.
This comparison of Playwright and Selenium for testing WebAuthn passkeys explains why real-device coverage still matters.
The goal is not to run every test on expensive physical infrastructure. It is to identify which parts of the authentication journey cannot be represented faithfully by a generic browser session.
Add reality deliberately
You cannot reproduce every user environment.
You should not try.
Instead, identify the variables most likely to alter important behaviour:
- Browser engine
- Device class
- Viewport
- Location
- Language
- Consent state
- Authentication state
- Feature flags
- Deployment configuration
- Accessibility mode
Then build a small, deliberate matrix around those risks.
A thousand identical headless Chrome runs do not provide the same confidence as a carefully chosen set of environments.
The purpose of browser automation is not to create the cleanest possible laboratory.
It is to discover whether the product still works when the outside world reaches it.
Top comments (0)