Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsiTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Handle a GDPR cookie popup according to the test’s purpose: use a new BrowserContext and interact with the banner when testing consent itself; use a reviewed storageState fixture or a supported API setup when testing a feature that should start with a known preference. Locate controls by accessible role and name, verify stored state and network behavior, and keep every test’s cookies isolated.
Choose the test purpose first
A cookie-banner test and a product-feature test need different setup. Mixing them is a common source of flaky tests and misleading privacy assertions.
Testing the consent experience
Create a fresh context for each test, open the page without saved state, wait for the banner, choose Accept, Reject, or a preferences option, and assert the resulting behavior. A fresh context prevents a previous test’s consent cookie or local storage from hiding the banner.
Testing a downstream feature
Do not make every feature test rediscover a third-party banner. Run a small, dedicated setup test that makes a reviewed choice, save its state, and load that state only in tests that intentionally require it. Playwright’s isolation model is designed so each test has independent cookies, storage, and session state.
Use resilient locators
Prefer what a user can perceive: an accessible dialog, button role, and accessible name. Generated CSS classes and long XPath chains often change when a consent-management platform updates its markup.
const banner = page.getByRole('dialog', { name: /cookie|privacy|consent/i });
await banner.getByRole('button', { name: /accept all/i }).click();
If the application does not expose a dialog role, scope to a stable container owned by your application and use getByRole, getByText, or a contract test id inside it. Keep button names aligned with the actual localized UI; “Allow all”, “Accept optional cookies”, and “Necessary only” are not interchangeable.
Wait for actionability instead of sleeping
Locator actions and assertions automatically wait for visibility and actionability. Use an assertion when presence is part of the test:
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →await expect(banner).toBeVisible();
await banner.getByRole('button', { name: /reject all|necessary only/i }).click();
await expect(banner).toBeHidden();
A fixed timeout can pass on a fast run and fail on a slow one. If a banner is intentionally delayed, wait for the locator or a documented application event rather than guessing a number of milliseconds.
Deal with iframes and shadow DOM
Banner inside an iframe
Identify the frame by a stable URL, title, or another contract controlled by your team, then apply the same role-and-name strategy to its frame locator:
#1 Best Overall
const consentFrame = page.frameLocator('iframe[title="Cookie preferences"]');
const frameBanner = consentFrame.getByRole('dialog', { name: /cookie|privacy|consent/i });
await frameBanner.getByRole('button', { name: /accept all/i }).click();
A vendor-generated frame selector can change. Prefer a stable title or URL contract and add a focused contract test if the integration is external.
Banner in a shadow root
Use normal Playwright locators where shadow-DOM support applies, then verify the component’s accessible name. If the component is closed or exposes no usable semantics, ask the application team for a supported test hook rather than reaching through implementation details.
Recommended Free Tools
Persist and reuse a deliberate consent choice
After a controlled interaction, save the context’s cookies and origin storage:
import { test, expect } from '@playwright/test';
test('create rejected-consent state', async ({ browser }) => {
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('/');
const banner = page.getByRole('dialog', { name: /cookie|privacy|consent/i });
if (await banner.isVisible()) {
await banner.getByRole('button', { name: /reject all|necessary only/i }).click();
}
await expect(banner).toBeHidden();
await context.storageState({ path: 'playwright/.auth/consent-rejected.json' });
await context.close();
});
test('feature starts with rejected consent', async ({ browser }) => {
const context = await browser.newContext({
storageState: 'playwright/.auth/consent-rejected.json'
});
const page = await context.newPage();
await page.goto('/account');
// Test the feature, not the banner setup.
await context.close();
});
Storage state can contain cookies and headers capable of impersonation. Keep these files outside version control, restrict access in CI, and generate separate accept and reject fixtures when both paths matter.
Seed a cookie only when its contract is known
context.addCookies() accepts a URL or a domain/path plus attributes such as httpOnly, secure, sameSite, expiry, and partition keys:
await context.addCookies([{
name: 'consent',
value: 'necessary-only',
url: 'https://app.example.test',
path: '/',
secure: true,
sameSite: 'Lax'
}]);
Do not guess a consent-management platform’s cookie name or value. Obtain the exact contract from your application documentation or a controlled acceptance test. An incorrect seed can hide the banner while leaving optional tracking enabled.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Use API setup when the application supports it
When your service exposes a supported preference or consent endpoint, prepare state through that API instead of clicking a vendor UI in every test. Playwright’s context-associated APIRequestContext shares the browser context’s cookie jar, so a request can establish state that the subsequent page uses.
Rank #3
import { test, expect } from '@playwright/test';
test('prepare consent through the supported endpoint', async ({ browser }) => {
const context = await browser.newContext();
const request = await context.request;
const response = await request.post('/api/privacy/consent', {
data: { analytics: false, marketing: false }
});
expect(response.ok()).toBeTruthy();
const page = await context.newPage();
await page.goto('/');
await expect(page.getByRole('dialog', { name: /cookie|privacy|consent/i })).toBeHidden();
await context.close();
});
Use this only for an endpoint your application supports and documents. Keep one UI test that proves the banner produces the same state.
Verify behavior, not just the click
Accept path
- Assert that the preference cookie or storage value is present and has the expected value.
- Assert that optional scripts or requests appear only after acceptance.
- Check that essential application functionality still works.
Reject path
- Assert that optional tracking remains disabled.
- Assert that required functionality remains available.
- Confirm the banner disappears and the rejection choice persists after reload.
For your own services, inspect requests and responses or use controlled routes to prove the gate. Avoid making tests depend on live third-party analytics or advertising endpoints; those systems can be unavailable, reordered, or changed without notice.
test('reject blocks optional collection', async ({ page }) => {
await page.goto('/');
const banner = page.getByRole('dialog', { name: /cookie|privacy|consent/i });
await banner.getByRole('button', { name: /reject all|necessary only/i }).click();
await expect(page).toHaveURL(///);
const cookies = await page.context().cookies();
const consent = cookies.find(cookie => cookie.name === 'consent');
expect(consent?.value).toBe('necessary-only');
});
Build a reusable fixture
A fixture keeps setup in one place while preserving a clear lifetime for the context and saved state:
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallimport { test as base } from '@playwright/test';
export const test = base.extend<{ consentContext: void }>({
consentContext: async ({ browser }, use) => {
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('/');
const banner = page.getByRole('dialog', { name: /cookie|privacy|consent/i });
if (await banner.isVisible()) {
await banner.getByRole('button', { name: /reject all|necessary only/i }).click();
}
await context.storageState({ path: 'playwright/.auth/consent-rejected.json' });
await context.close();
await use();
}
});
Adapt the names and structure to your accessible UI. This pattern tests browser behavior; it is not proof that a banner is legally compliant.
Compliance boundaries you must test separately
The UK Information Commissioner’s Office says organisations should tell people cookies are present, explain what they do and why, and obtain consent for cookies outside a strictly necessary exception. It also recommends a way for people to control non-essential cookies and keeping consent records. CNIL states that consent for non-exempt trackers must generally come before their deposit or reading and must be free, specific, informed, and unambiguous.
Rank #4
Jurisdiction, tracker type, and enforcement expectations differ. A passing Playwright click is not legal evidence. Involve the privacy counsel or regulator guidance applicable to your deployment, and retain the stored preference and network assertions that demonstrate the implemented behavior.
Troubleshooting flaky cookie tests
The banner is not found
Check whether a previous context or persisted profile already contains consent. Confirm the actual role, accessible name, locale, and whether the banner is in an iframe or shadow root. Capture the page accessibility snapshot during diagnosis instead of switching immediately to XPath.
The click is intercepted or times out
The banner may be covered by an animation, another overlay, or a delayed frame. Wait for the scoped locator to be visible and actionable; remove animation only through a test-controlled style if your application supports that contract. Do not force-click a different element, because that can produce a false pass.
The choice disappears after reload
Inspect cookies and origin storage after the click. Verify domain, path, secure and same-site attributes, expiration, and whether the application writes state asynchronously. Wait for the application’s stored-state signal before reloading.
Optional requests happen before consent
That is an application defect or an incorrectly isolated test, not a selector problem. Start from a new context, record early requests with a controlled route, and fix initialization so non-essential trackers are gated before deposit or reading.
Best Value
Tests pass locally but fail in CI
Use independent contexts, avoid live third-party dependencies, and make iframe or locale contracts explicit. Ensure saved state is generated for the same origin and deployment configuration used by CI, and never share a mutable profile between workers.
Performance, reliability, and maintenance
- Run the banner UI flow once per relevant locale and consent outcome; reuse reviewed state for broad feature coverage.
- Keep accept and reject fixtures separate, versioned by application contract, and regenerated when consent behavior changes.
- Prefer a small number of semantic locators over one giant selector that encodes vendor markup.
- Review Playwright APIs, consent-management markup, cookie names, and regulator guidance when upgrading dependencies or changing regions.
- Separate essential functionality assertions from optional-tracking assertions so a third-party outage does not fail unrelated tests.
Or skip the browser setup
If your goal is a clean visual capture rather than testing the banner interaction, ScreenshotNeo accepts the consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot. It bills only clean shots: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and each response identifies the page verdict and billing result in headers. Its MCP server gives Claude, Cursor, and other MCP clients take_screenshot, get_page_info, and capture_pdf tools.
One request is enough:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the complete parameter reference in the ScreenshotNeo documentation. Equivalent clients:
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo includes full-page and element capture, device and viewport controls, custom CSS and JavaScript, cookie and header settings, waits, blocking rules, PDFs, caching, signed links, asynchronous webhooks, bulk capture, and an OpenAPI spec. Every plan includes every feature: 1,000 shots per month are free with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
Frequently Asked Questions
Should I accept cookies automatically in every Playwright test?
No. Interact with the banner in tests that validate consent. For unrelated feature tests, load a reviewed state fixture or use a supported application API.
Can I use a vendor’s cookie name in a fixture?
Only when that name and value are part of your application’s documented contract. Otherwise create state through the real UI or a supported endpoint.
Does a successful Reject button click prove GDPR compliance?
No. You must also verify persistence, blocking of non-essential tracking before consent, required functionality, records, and the rules applicable to the deployment jurisdiction.
Quick Recap
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.

