REST and APIs

Chaining Browser Actions Through GPAL.RESTClient with AndThen

Complete Program

It builds a RESTClient pointed at the OttoMagic REST API, reads a product name off the page, types it into a search box and submits it, reads the resulting URL, and navigates to it - each step feeding the next through named results.

using GenerallyPositive;

using GenerallyPositive.Browser;

using static GenerallyPositive.Enums;


GPAL.WithPublishToConsole();


IBrowser browser = GPAL.Browser

.WithBrowserType(BrowserType.Chrome)

.WithAutomationEngine(AutomationEngine.OttoMagic)

.WithDriverLocation("C:\drivers")

.ToGPALObject();


browser.GoTo("https://example-shop.com"); // launches the browser, which starts its REST API


IRESTClient client = GPAL.RESTClient

.WithAPIBase(browser.RestApiBaseUrl)

.WithName("ChainClient")

.WithResultName("productName")

.GetAttribute("//div[@class='product-name']")

.WithAttribute("innerText")

.AndThen<string>() // "productName": "Laptop"


.WithEndpoint(ApiEndpoint.FillInOverwrite)

.WithXPath("//input[@id='search']")

.WithTextFromResult("productName") // Use Result "productName": "Laptop"

.AndThen() // Types "Laptop" into the input field


.SendKey(0x0D)

.AndThen() // Enter submits the search


.WithResultName("currentUrl")

.GetCurrentUrl()

.AndThen<string>() // "currentUrl": "https://example-shop.com/search?q=Laptop"


.WithEndpoint(ApiEndpoint.GoTo)

.WithUrlFromResult("currentUrl") // Use Result "currentUrl"

.AndThen(); // Navigates to the URL


var results = client.GetExecutionResults();

GPAL.PublishSimpleEvent(GPALEventType.NOTICE, $"Product Name: [{results["productName"]}]");

GPAL.PublishSimpleEvent(GPALEventType.NOTICE, $"Current URL: [{results["currentUrl"]}]");

GPAL.RESTClient: The General-Purpose Client

WithAPIBase points the client at any REST API base URL - here, browser.RestApiBaseUrl, the local OttoMagic server. WithName labels the client for logging. From here you configure each call with WithEndpoint and whatever With* parameters that endpoint needs.

IRESTClient client = GPAL.RESTClient

.WithAPIBase(browser.RestApiBaseUrl)

.WithName("ChainClient")

.ToGPALObject();

NOTE

browser.OttoMagicClient skips the WithAPIBase call by pointing at browser.RestApiBaseUrl automatically, but it's the same RESTClient underneath. Anything you can do with one, you can do with the other.

AndThen<T>() Runs the Call and Names the Result

WithResultName labels the result of the call that follows it, so it comes first: here the outcome is named "productName". GetAttribute finds the element by its XPath, and WithAttribute("innerText") picks its text. AndThen() executes the call, stores the string under that name, and hands back the client for the next step.

client

.WithResultName("productName")

.GetAttribute("//div[@class='product-name']")

.WithAttribute("innerText")

.AndThen<string>(); // "productName": "Laptop"

Feed One Result Into the Next Call

WithTextFromResult("productName") pulls the value stored under that name from the previous step and uses it as the text for FillInOverwrite. AndThen() without a type parameter runs the call without expecting a typed return - useful for actions like filling in a field where you don't need the result value itself. SendKey(0x0D) then presses Enter to submit the search.

client

.WithEndpoint(ApiEndpoint.FillInOverwrite)

.WithXPath("//input[@id='search']")

.WithTextFromResult("productName") // Use Result "productName": "Laptop"

.AndThen() // Types "Laptop" into the input field


.SendKey(0x0D)

.AndThen(); // Enter submits the search

NOTE

GetExecutionResults() looks results up by the name given to WithResultName. The With*FromResult methods also take an index, but the index counts every entry the client has stored, not just the named ones, so a name is the safer choice.

Read the URL Back, Then Navigate to It

GetCurrentUrl reads the page's current URL into "currentUrl". The final step uses WithUrlFromResult to plug that value into a GoTo call - the chain ends by navigating using a value the workflow itself produced one step earlier.

client

.WithResultName("currentUrl")

.GetCurrentUrl()

.AndThen<string>()


.WithEndpoint(ApiEndpoint.GoTo)

.WithUrlFromResult("currentUrl")

.AndThen();


var results = client.GetExecutionResults();

GPAL.PublishSimpleEvent(GPALEventType.NOTICE, $"Current URL: [{results["currentUrl"]}]");

💬 Ask GPAL