Tutorials

Tutorials

Pacing a Workflow with WaitFor

Stepping through a native dropdown with SelectClick triggers real browser navigation between each choice. This tutorial uses that workflow to show where WaitFor belongs in a chain - right after the action that needs time to settle - and how it works whether or not WithSelector was just called.

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

.WithUseOttoMagic(@"C:OttoMagic")

.WithAutoUpdateWebDriver();

// the last <option> in eBay's category <select> - "Everything Else"

Selector categoryOption = GPAL.Selector

.WithCSS("#gh-cat > option:nth-child(36)")

.WithHardware

.ToGPALObject();

IBrowser browser = GPAL.Browser

.WithBrowserType(BrowserType.Chrome)

.WithDriverLocation(@"c:drivers")

.WithUseAutomationEngine(AutomationEngine.OttoMagic)

.ToGPALObject();

browser.GoTo("https://www.ebay.com/");

browser

.WithSelector(categoryOption)

.SelectClick(SelectClickType.LeftClick) // jump straight to "Everything Else" (the last option)

.WaitFor(5_000);

browser

.SelectClick(SelectClickType.SelectRandom) // pick a random category

.WaitFor(5_000);

browser

.SelectClick(SelectClickType.SelectNext) // move to the next option

.WaitFor(5_000);

browser

.SelectClick(SelectClickType.SelectPrevious) // back to the previous option

.WaitFor(5_000);

browser

.LeftClick(categoryOption) // re-select "Everything Else" so we know exactly where we are

.WaitFor(5_000)

.SelectClick(SelectClickType.SelectNextWithWrap) // already on the last option, so this wraps to the first ("All")

.WaitFor(5_000)

.SelectClick(SelectClickType.SelectPreviousWithWrap) // wrap back down to the last option ("Everything Else")

.WaitFor(5_000);

browser.Close(true);

WaitFor After WithSelector and an Action

WithSelector establishes the unit of work - the <option> we want to act on - and SelectClick(LeftClick) opens the dropdown and chooses it. That choice causes the page to react: the dropdown closes, and depending on the option, the page may reload or update. WaitFor(5_000) is the next step in the same chain, so it runs after SelectClick completes and before anything else does, giving the page time to settle.

browser

.WithSelector(categoryOption)

.SelectClick(SelectClickType.LeftClick) // jump straight to "Everything Else" (the last option)

.WaitFor(5_000);

TIP

GPAL doesn't treat WaitFor as special syntax - it's an action like LeftClick or SelectClick, executed in the position you place it in the chain. If an action needs time before the next one runs, put WaitFor right after it.

WaitFor Without Calling WithSelector Again

These three chains never call WithSelector - they call SelectClick directly. GPAL keeps the most recently used selector and unit of work active, so SelectClick(SelectRandom), SelectClick(SelectNext), and SelectClick(SelectPrevious) all continue operating on categoryOption from the first chain. Each one is followed by its own WaitFor(5_000), pacing the workflow the same way regardless of whether WithSelector was just called.

browser

.SelectClick(SelectClickType.SelectRandom) // pick a random category

.WaitFor(5_000);

browser

.SelectClick(SelectClickType.SelectNext) // move to the next option

.WaitFor(5_000);

browser

.SelectClick(SelectClickType.SelectPrevious) // back to the previous option

.WaitFor(5_000);

WARNING

Calls like SelectClick and LeftClick reuse the selector and unit of work from the most recent WithSelector. That's convenient here, but if a later step needs to act on a different element, call WithSelector again to make that explicit - otherwise GPAL keeps using whatever was set last.

Multiple WaitFor Calls in a Single Chain

WaitFor can appear more than once in the same fluent statement. Here, LeftClick resets the dropdown to a known position ("Everything Else", the last option), then WaitFor(5_000) lets that settle before SelectNextWithWrap runs - which, starting from the last option, wraps around to the first ("All"). Another WaitFor(5_000) lets that settle before SelectPreviousWithWrap wraps back down to "Everything Else", followed by a final WaitFor(5_000).

browser

.LeftClick(categoryOption) // re-select "Everything Else" so we know exactly where we are

.WaitFor(5_000)

.SelectClick(SelectClickType.SelectNextWithWrap) // already on the last option, so this wraps to the first ("All")

.WaitFor(5_000)

.SelectClick(SelectClickType.SelectPreviousWithWrap) // wrap back down to the last option ("Everything Else")

.WaitFor(5_000);

One Workflow Body, 42 Combinations

This entire workflow - selector, browser launch, and every SelectClick/WaitFor chain above - is the inner body of three nested loops: one over BrowserType, one over AutomationEngine, and an innermost one over headless vs. headful. Get(url) runs the workflow with no visible window; GoTo(url) opens a real browser window. Neither the selector definitions nor any WaitFor placement changes between the 42 combinations - only how the browser is launched and shown.

foreach (BrowserType bt in browserTypes)

{

foreach (AutomationEngine ae in automationEngines)

{

for (int headlessMode = 0; 2 > headlessMode; headlessMode++)

{

bool currentHeadless = (1 == headlessMode);

IBrowser browser = GPAL.Browser

.WithBrowserType(bt)

.WithDriverLocation(@"c:drivers")

.WithUseAutomationEngine(ae)

.ToGPALObject();

if (true == currentHeadless)

browser.Get("https://www.ebay.com/");

else

browser.GoTo("https://www.ebay.com/");

// ... the SelectClick + WaitFor chains from above, unchanged ...

}

}

}

TIP

Get(url) drives the page headlessly, with no visible window. GoTo(url) opens a real, visible browser window and navigates it. Both return the same kind of IBrowser, so every WithSelector/SelectClick/WaitFor chain you write works identically either way.