Automation Engines

Driving a Browser Directly with PuppeteerClient

Complete Program

Here's the whole workflow, start to finish. Each piece is broken down and explained below.

using GenerallyPositive;

using GenerallyPositive.Browser;

using static GenerallyPositive.Enums;


GPAL.WithPublishToConsole(GPALEventType.INFO | GPALEventType.ERROR | GPALEventType.WARNING | GPALEventType.DEBUG)

.WithPublishStackTrace();


IBrowser browser = GPAL.Browser

.WithBrowserType(BrowserType.Chrome)

.WithAutomationEngine(AutomationEngine.PuppeteerPort)

.WithCDPDebugPort(0xdead)

.WithNetworkIdleMaxConnections(0)

.WithWaitOnIdleConnection()

.ToGPALObject();


browser.GoTo(""); // launches with the default page


IPuppeteerClient client = browser.PuppeteerClient;


var result = client

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

.AndThen().CheckNetworkIdle()

.AndThen().GoTo("https://example.org")

.Execute();


result = client.NewTab("https://example.com").AndThen().CheckNetworkIdle().Execute();

result = client.NextTab().Execute();


bool clickable = client.IsClickable("#search-input").Execute<bool>();

bool displayed = client.IsDisplayed("#search-input").Execute<bool>();


result = client.FillInOverwrite("#search-input").WithText("hello world").Execute();

result = client.SendKey(0x0D).Execute(); // Enter submits the form the input is in

result = client.ScrollWindow(0, 200).Execute();

result = client.PageDown(2).Execute();


browser.Close(true);

Get the PuppeteerClient From an Existing Browser

You don't construct an IPuppeteerClient directly - you get one off a live IBrowser. browser.PuppeteerClient hands you a client wired to the same automation engine and session as the browser, so anything it does happens in that browser.

IBrowser browser = GPAL.Browser

.WithBrowserType(BrowserType.Chrome)

.WithAutomationEngine(AutomationEngine.PuppeteerPort)

.WithCDPDebugPort(0xdead)

.WithNetworkIdleMaxConnections(0)

.WithWaitOnIdleConnection()

.ToGPALObject();


browser.GoTo("");


IPuppeteerClient client = browser.PuppeteerClient;

NOTE

WithCDPDebugPort sets the Chrome DevTools port GPAL connects to. This pairs with AutomationEngine.PuppeteerPort, which talks to Chrome over that port. AutomationEngine.PuppeteerPipe talks to it over a pipe instead, and browser.PuppeteerClient works the same on either.

AndThen Chains Steps on One Line

AndThen() runs the request built so far right away and hands the client back, so the next step can follow on the same line: navigate, then check whether the network is idle, then navigate again. Nothing is queued, and the final Execute() runs the last step and returns only its result. CheckNetworkIdle asks once and answers at once; it does not wait for the network to go idle. This is the lower-level equivalent of the multi-step chains you see on IBrowser.

var result = client

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

.AndThen().CheckNetworkIdle()

.AndThen().GoTo("https://example.org")

.Execute();


result = client.NewTab("https://example.com").AndThen().CheckNetworkIdle().Execute();

result = client.NextTab().Execute();

NOTE

AndThen() runs the current step and returns the client for the next one; Execute() (or Execute()) runs the current step and returns its result. A chain should always end in Execute or Execute.

Read State, Then Act on the Page

Execute() returns a typed result for queries like IsClickable and IsDisplayed - handy for checking an element's state before interacting with it. FillInOverwrite, SendKey, ScrollWindow, and PageDown are the same interaction primitives IBrowser builds its higher-level actions on top of.

bool clickable = client.IsClickable("#search-input").Execute<bool>();

bool displayed = client.IsDisplayed("#search-input").Execute<bool>();


result = client.FillInOverwrite("#search-input").WithText("hello world").Execute();

result = client.SendKey(0x0D).Execute(); // Enter submits the form the input is in

result = client.ScrollWindow(0, 200).Execute();

result = client.PageDown(2).Execute();

Closing Down

Close(true) on the IBrowser shuts down the underlying driver process once the workflow is finished, regardless of whether you drove it through IBrowser or IPuppeteerClient.

browser.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.

💬 Ask GPAL