Tutorials

Tutorials

Drag and Drop with Image-Based Selectors

DragAndDrop performs a hardware-level drag from one element to another, using offsets and deltas to land precisely. This tutorial walks through closing a popup with LeftClick and then dragging a map element using a selector built from CSS, XPath, text, an image, and pixel offsets.

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;

static Selector closeButtonSelector = (Selector)GPAL.Selector

.WithCSS(@"#dialog > div > button")

.WithXPath(@"//*[@id="dialog"]/div/button")

.WithText(@"x")

.MatchText(@"x")

.WithOffsetX(26)

.WithOffsetY(18)

.WithImage(imageData);

static Selector mapSelector = (Selector)GPAL.Selector

.WithCSS(@"#map")

.WithXPath(@"//*[@id="map"]")

.WithText(@"A pretty popup. Easily customizable.")

.MatchText(@"A pretty popup. Easily customizable.")

.WithOffsetX(694)

.WithOffsetY(109)

.WithDeltaX(-524)

.WithDeltaY(3);

IBrowser browser = GPAL.Browser

.WithBrowserType(BrowserType.Chrome)

.WithLoadImages(true)

.WithBlockPopUps(true)

.WithDriverLocation(@"C:drivers")

.WithUseAutomationEngine(AutomationEngine.PuppeteerPort)

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

.ToGPALObject();

browser

.LeftClick(closeButtonSelector);

browser

.DragAndDrop(mapSelector);

browser.Close(true);

A Selector Can Carry Many Clues at Once

closeButtonSelector stacks CSS, XPath, expected text (both WithText and MatchText), and a reference image (WithImage) all on the same selector. GPAL doesn't require you to pick just one strategy - it can use whichever combination of clues is available to find and confirm the element. WithOffsetX and WithOffsetY then say exactly where, relative to that element, the click should land.

static Selector closeButtonSelector = (Selector)GPAL.Selector

.WithCSS(@"#dialog > div > button")

.WithXPath(@"//*[@id="dialog"]/div/button")

.WithText(@"x")

.MatchText(@"x")

.WithOffsetX(26)

.WithOffsetY(18)

.WithImage(imageData);

TIP

WithImage takes image data (here, captured ahead of time as a base64 string in a field called imageData) that GPAL can use to visually confirm or locate the element on screen. This is most useful when CSS and XPath alone aren't reliable, such as canvas-based UI or elements that shift position. See The Selector System.

Close the Popup First

Before dragging anything, the workflow left-clicks the popup's close button. This is a normal LeftClick - no different from clicking any other element - it just happens to be the cleanup step that needs to run before the map underneath is usable.

browser

.LeftClick(closeButtonSelector);

DragAndDrop Uses Offsets and Deltas

mapSelector defines a starting point on the map (via WithOffsetX/WithOffsetY, relative to the matched element) and a movement distance (WithDeltaX/WithDeltaY - here, moving left 524 pixels and down 3 pixels). DragAndDrop performs a press-move-release sequence from the starting point across that delta, simulating a real mouse drag.

static Selector mapSelector = (Selector)GPAL.Selector

.WithCSS(@"#map")

.WithXPath(@"//*[@id="map"]")

.WithOffsetX(694)

.WithOffsetY(109)

.WithDeltaX(-524)

.WithDeltaY(3);

browser

.DragAndDrop(mapSelector);

WARNING

Drag-and-drop performed at the hardware level moves the real mouse cursor and requires the browser window to have focus and be in front. If another window steals focus mid-drag, the drag can land in the wrong place or fail entirely. See Hardware-Level Interaction.

Behind the Scenes: Every Engine, Every Mode

The actual test program in the repo loops over every BrowserType, AutomationEngine, and headless/headful combination, running this same close-then-drag sequence each time. That's purely for regression coverage across engines - your own workflow only needs the single pass shown above. See Automation Engines for what each engine offers.