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.
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);
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);
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.
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);
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.
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);
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 ...
}
}
}
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.
Showing off some plain text in these paragraphs eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Here you can find different accents and emphasis sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
This is a link and how it could look like bestlinkinthebeautifulworld. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Here's just some classic bold text adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam notBoldSecondbestlinkinthebeautifulworld illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Obcaecati, iste distinctio veritatis eligendi laboriosam adipisicing elit illo nostrum corporis at adipisicing elit libero vel voluptas? Expedita, adipisicing facere dolores voluptatem ad ab rem assumenda soluta!
Other cuple of colors in case we want to emphasize several ways adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam adipisicing elit illo nostrum corporis at voluptatem libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quod veniam, quam ad expedita laborum sed at voluptates culpa ipsam ut vel. Ullam temporibus a mollitia quod aliquam ratione exercitationem nesciunt.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quod veniam, quam ad expedita laborum sed at voluptates culpa ipsam ut vel. Ullam temporibus a mollitia quod aliquam ratione exercitationem nesciunt.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Repudiandae quas consequuntur illo numquam assumenda autem exercitationem distinctio perspiciatis in natus. Eius dicta similique ipsam ipsa minima, nemo quae enim tempore.
GPAL
.CallIfNotFound(GenericCallIfNotFound)
.WithPublishToConsole();
//System.Drawing.Rectangle windowSize = new System.Drawing.Rectangle(10, 10, 1500, 1024);
// NOTE: we have to set browser = before we execute any steps
// this is due to the 'GenericCallIfNotFound' which might throw an exception, and BankScraper will not have the browser set when it calls scraper.Close()
// until the complete fluent line gets executed (meaning every step, meaning browser is not set until everything else succeeds)
browser = GPAL.Browser
.WithBrowserType(Enums.BrowserType.Chrome)
.WithProfileDataDirectory(ChromeProfileLocation)
.WithUseAutomationEngine(AutomationEngine.Selenium)
.WithWindowSize(new System.Drawing.Rectangle(0,0,1920,1080))
.ToGPALObject();