Skip to main content

Driver and elements

The in-process AvaloniaDriver uses familiar Appium and Selenium names. It drives Avalonia controls directly; it is not an Appium server, a WebDriver protocol implementation, or a drop-in OpenQA.Selenium driver.

Namespaces​

using Avalonia.HeadlessTestingFramework.Appium;

AvaloniaDriver​

The main entry point for Appium-style testing.

// Create driver from a window
using var driver = new AvaloniaDriver(window);

// Or from a control
using var driver = new AvaloniaDriver(rootControl);

Finding Elements​

Use By locators to find elements, similar to Selenium/Appium:

// By ID (Name property)
var button = driver.FindElement(By.Id("submitButton"));

// By AutomationId
var input = driver.FindElement(By.AutomationId("username_field"));

// By class name (type name)
var buttons = driver.FindElements(By.ClassName("Button"));

// By text content
var element = driver.FindElement(By.Text("Click Me"));

// By partial text
var element = driver.FindElement(By.ContainsText("Click"));

// By CSS selector (standard Selenium method)
var primary = driver.FindElement(By.CssSelector(".primary"));

// By CSS class (Avalonia-specific)
var styled = driver.FindElement(By.CssClass("primary"));

// By link text (standard Selenium)
var link = driver.FindElement(By.LinkText("Click here"));

// By partial link text (standard Selenium)
var partialLink = driver.FindElement(By.PartialLinkText("Click"));

// By XPath-like expression
var nested = driver.FindElement(By.XPath("//StackPanel/Button[@Name='submit']"));

// By tag name (standard Selenium)
var buttons = driver.FindElements(By.TagName("Button"));

// By property value
var enabled = driver.FindElement(By.Property("IsEnabled", true));

// Generic type
var button = driver.FindElement(By.Type<Button>());

// Regex pattern
var elements = driver.FindElements(By.NameRegex("btn_.*"));

Composite Locators​

Combine multiple locators:

// All conditions must match (AND)
var element = driver.FindElement(By.All(
By.ClassName("Button"),
By.Text("Submit")));

// Any condition can match (OR)
var element = driver.FindElement(By.Any(
By.Id("submitBtn"),
By.Id("okBtn")));

// Chained search (nested)
var element = driver.FindElement(By.Chained(
By.Id("container"),
By.ClassName("Button")));

AvaloniaElement​

Wrapper around Avalonia controls with Appium-like methods:

var element = driver.FindElement(By.Id("myButton"));

// Properties
string id = element.Id;
string tagName = element.TagName;
string text = element.Text;
bool displayed = element.Displayed;
bool enabled = element.Enabled;
bool selected = element.Selected;
bool focused = element.Focused;
Point location = element.Location;
Size size = element.Size;

// Actions (chainable) - Standard Selenium methods
element
.Click()
.SendKeys("Hello")
.Clear()
.Submit() // Standard Selenium form submission
.Focus()
.Hover()
.ScrollIntoView();

// Touch actions (Appium-compatible)
element.Tap();
element.DoubleTap();
element.LongPress(1000);
element.Swipe(SwipeDirection.Up, 200);
element.Pinch(1.5); // Zoom in
element.Scroll(0, -100);

// Keyboard
element.PressKey(Key.Enter);

// Attributes (standard Selenium getAttribute)
string value = element.GetAttribute("enabled");
var isEnabled = element.GetProperty<bool>("IsEnabled");
element.SetProperty("IsEnabled", false);

// CSS classes
var classes = element.GetClasses();
bool hasClass = element.HasClass("primary");

// Find child elements
var child = element.FindElement(By.ClassName("TextBlock"));
var children = element.FindElements(By.ClassName("Button"));

// Navigation
var parent = element.Parent;
var kids = element.Children;

// Screenshots
element.SaveScreenshot("element.png");
using var bitmap = element.Screenshot();

TouchAction​

Build complex gesture sequences:

// Press and drag
driver.CreateTouchAction()
.Press(element)
.Wait(100)
.MoveTo(200, 300)
.Release()
.Perform();

// Long press
driver.CreateTouchAction()
.LongPress(element, 1000)
.Release()
.Perform();

// Swipe
driver.CreateTouchAction()
.Press(100, 100)
.Swipe(SwipeDirection.Left, 200)
.Release()
.Perform();

// Complex gesture
driver.CreateTouchAction()
.Tap(element)
.Wait(500)
.Tap(100, 200, count: 2) // Double tap at position
.Perform();

// Multi-touch (pinch)
MultiTouchAction.Pinch(driver, element, 0.5, durationMs: 300);
MultiTouchAction.Scroll(driver, element, 0, -100);

Waiting​

WebDriverWait-style explicit waits:

// Configure default timeout
driver.Wait.Timeout = TimeSpan.FromSeconds(10);
driver.Wait.PollingInterval = TimeSpan.FromMilliseconds(100);

// Wait for element
var element = driver.Wait.ForElement(By.Id("loading"));

// Wait for visible
var visible = driver.Wait.ForElementVisible(By.Id("content"));

// Wait for clickable
var clickable = driver.Wait.ForElementClickable(By.Id("submit"));

// Wait for element to disappear
driver.Wait.ForElementNotPresent(By.Id("spinner"));

// Wait for text
driver.Wait.ForTextPresent(By.Id("result"), "Success");

// Custom condition
driver.Wait.Until(d => d.FindElement(By.Id("count")).Text == "5");

// Fixed delay
driver.Wait.ForMilliseconds(500);

ExpectedConditions​

Pre-built conditions for common scenarios:

using static Avalonia.HeadlessTestingFramework.Appium.ExpectedConditions;

// Element conditions
var el = driver.Wait.Until(ElementExists(By.Id("btn")));
var visible = driver.Wait.Until(ElementIsVisible(By.Id("btn")));
var clickable = driver.Wait.Until(ElementToBeClickable(By.Id("btn")));

// Invisibility
driver.Wait.Until(InvisibilityOfElement(By.Id("loading")));

// Text conditions
driver.Wait.Until(TextToBe(By.Id("status"), "Complete"));
driver.Wait.Until(TextToBePresentInElement(By.Id("log"), "Success"));
driver.Wait.Until(TextToMatch(By.Id("code"), @"\d{6}"));

// Attribute conditions
driver.Wait.Until(AttributeToBe(By.Id("input"), "value", "test"));
driver.Wait.Until(AttributeContains(By.Id("class"), "class", "active"));

// Count conditions
var elements = driver.Wait.Until(NumberOfElementsToBe(By.ClassName("Item"), 5));
var moreElements = driver.Wait.Until(NumberOfElementsToBeMoreThan(By.ClassName("Item"), 3));

// Logical combinations
driver.Wait.Until(And(
ElementToBeEnabled(By.Id("submit")),
d => d.ElementExists(By.Id("form"))));

driver.Wait.Until(Or(
ElementExists(By.Id("success")),
ElementExists(By.Id("error"))));

driver.Wait.Until(Not(ElementExists(By.Id("loading"))));

// Window conditions
driver.Wait.Until(TitleIs("Dashboard"));
driver.Wait.Until(TitleContains("Settings"));

Screenshots​

// Full window screenshot
driver.SaveScreenshot("window.png");
var bitmap = driver.Screenshot();
var base64 = driver.ScreenshotAsBase64();

// Element screenshot
element.SaveScreenshot("element.png");

Window Management​

// Size
driver.SetWindowSize(1280, 720);
var size = driver.GetWindowSize();

// Position
driver.SetWindowPosition(100, 100);
var pos = driver.GetWindowPosition();

// States
driver.Maximize();
driver.Minimize();
driver.Restore();
driver.Fullscreen();
driver.Close();

// Title
string title = driver.Title;

Page Source​

Get XML representation of the visual tree:

string source = driver.PageSource;
// Returns XML like:
// <Window name="MainWindow">
// <StackPanel name="Container">
// <Button name="submit" text="Click Me" />
// </StackPanel>
// </Window>

DataContext Interaction​

Execute actions on the ViewModel:

// Execute action
driver.ExecuteScript<MyViewModel>(vm => vm.LoadData());

// Get value
var count = driver.ExecuteScript<MyViewModel, int>(vm => vm.ItemCount);

Custom Predicates​

Register custom element finders:

driver.RegisterPredicate("largeButton", c =>
c is Button btn && btn.Bounds.Width > 100);

var largeButtons = driver.FindElements(By.Predicate("Large button", "largeButton"));

Complete Example​

[AvaloniaFact]
public void Login_WithValidCredentials_ShowsDashboard()
{
var window = new MainWindow();
window.Show();

using var driver = new AvaloniaDriver(window);
driver.Wait.Timeout = TimeSpan.FromSeconds(5);

// Enter credentials
driver.FindElement(By.AutomationId("username"))
.SendKeys("testuser");

driver.FindElement(By.AutomationId("password"))
.SendKeys("password123");

// Click login
driver.FindElement(By.Id("loginButton")).Click();

// Wait for dashboard
var dashboard = driver.Wait.Until(
ExpectedConditions.ElementIsVisible(By.Id("dashboard")));

Assert.NotNull(dashboard);
Assert.Contains("Welcome", dashboard.Text);

// Take screenshot
driver.SaveScreenshot("dashboard.png");
}