Tutorials

Tutorials

Handling Cookie Banners and Popups with Persistent Selectors

Cookie banners, newsletter popups, and other nags can appear at any point during a workflow, not just on the first page. WithPersistentSelector and PersistentCallIfFound register a selector and a callback that GPAL checks for on every navigation, so your main workflow can stay focused on the task at hand.

Complete Program

This is a trimmed version of the actual test program. It defines a cookie-banner selector, registers it as a persistent handler before navigating, then runs a normal workflow that downloads a file. The persistent handler fires automatically whenever the banner shows up, without any extra code in the main chain.

using System;

using System.Collections.Generic;

using GenerallyPositive;

using GenerallyPositive.Browser;

using static GenerallyPositive.Enums;

GPAL.WithTypingDelay(50)

.WithAutoUpdateWebDriver()

.WithPublishToConsole();

GPALFile htmlFile = @"c: emp est.html";

Selector allCookies = (Selector)GPAL.Selector

.WithSelectorName("Accept Cookies")

.WithXPath("//button")

.MatchText("Accept all cookies");

Selector downloadLink = (Selector)GPAL.Selector

.WithSelectorName("Download Link")

.WithXPath("//a[@id='download']");

IBrowser browser = GPAL.Browser

.WithBrowserType(BrowserType.Chrome)

.WithPersistentSelector(allCookies)

.PersistentCallIfFound(FoundAllCookies)

.WithDriverLocation(@"c:drivers")

.GoTo("https://example.com/downloads")

.ToGPALObject();

browser

.WithSelector(downloadLink)

.CallIfFound(CallIfFound)

.RightClickAndDownload(htmlFile)

.NewTab("https://example.com/another-page")

.WaitFor(2_000)

.Close(true);

public static CallIfStatus FoundAllCookies(IBrowser browser, List<GPALElement> foundElements, List<GPALElement> matchedElements, Selector selector, bool matchedAll)

{

CallIfStatus retVal = CallIfStatus.NotHandled;

foreach (GPALElement webElement in foundElements)

{

if (webElement.Text.Contains("cookies"))

{

webElement.Click();

retVal = CallIfStatus.Handled;

}

}

return retVal;

}

public static CallIfStatus CallIfFound(IBrowser browser, List<GPALElement> foundElements, List<GPALElement> matchedElements, Selector selector, bool matchedAll)

{

return CallIfStatus.Handled;

}

Define the Nag Selector

A persistent selector is just a regular Selector - give it a name and a way to find the element. Here it's an XPath for any button, narrowed down with MatchText so it only matches the cookie-acceptance button specifically, not every button on the page.

Selector allCookies = (Selector)GPAL.Selector

.WithSelectorName("Accept Cookies")

.WithXPath("//button")

.MatchText("Accept all cookies");

Register It Before You Navigate

WithPersistentSelector adds the selector to the browser's standing watch list. PersistentCallIfFound attaches the callback that runs whenever that selector matches something - on the first page load, after clicking a link, after opening a new tab, anywhere. Both calls happen on the same fluent chain used to configure and launch the browser.

IBrowser browser = GPAL.Browser

.WithBrowserType(BrowserType.Chrome)

.WithPersistentSelector(allCookies)

.PersistentCallIfFound(FoundAllCookies)

.WithDriverLocation(@"c:drivers")

.GoTo("https://example.com/downloads")

.ToGPALObject();

TIP

You don't need to re-check for the cookie banner after every click or tab change in your main workflow. GPAL evaluates every persistent selector on each navigation event and calls your handler automatically.

The Handler Decides Whether It Was Handled

FoundAllCookies looks at the matched elements, and if any of them contain the word "cookies" it clicks the element and returns CallIfStatus.Handled. Returning NotHandled tells GPAL the popup wasn't actually dealt with, which is useful if your handler sometimes needs to defer to other logic.

public static CallIfStatus FoundAllCookies(IBrowser browser, List<GPALElement> foundElements, List<GPALElement> matchedElements, Selector selector, bool matchedAll)

{

CallIfStatus retVal = CallIfStatus.NotHandled;

foreach (GPALElement webElement in foundElements)

{

if (webElement.Text.Contains("cookies"))

{

webElement.Click();

retVal = CallIfStatus.Handled;

}

}

return retVal;

}

The Main Workflow Stays Clean

With the persistent handler in place, the rest of the workflow just does its job - find the download link, react to it, download a file, open another tab. If the cookie banner reappears on the new tab, the persistent handler fires again without any changes here.

browser

.WithSelector(downloadLink)

.CallIfFound(CallIfFound)

.RightClickAndDownload(htmlFile)

.NewTab("https://example.com/another-page")

.WaitFor(2_000)

.Close(true);

WARNING

Passing true kills the running web driver process. Use true when the workflow is completely done; use false if another workflow in the same run still needs that driver.