4

I am automating a simple Windows Form Application and I am attempting to locate a WindowsElement using its inner text. My WindowsElement looks like this:

ControlType = DataItem
    Name = 'Identifier'
    ValuePattern.Value = 'Text'
    LegacyIAccessiblePattern.Value = 'Text'
    AutomationId = blank

The element has no properties other than Name, ControlType (which I am using in an XPath), and ValuePattern.Value which contains the desired text I am searching on. I would like to locate the element based on 'Text', using ValuePattern.Value or LegacyIAccessiblePattern.Value, but I can't seem to write an XPath that successfully uses these attributes. I cannot use @Name to locate the element, because several other elements share the same @Name attribute value. Text is the only unique attribute.

In Selenium WebDriver, I can locate an element through text as such:

driver.FindElement(By.XPath("//*[text()='Text']"));

In Appium, I can use this:

driver.FindElement(By.XPath("//*[@text='Text']")

In WinAppDriver, I am attempting:

driver.FindElementByXPath("//DataItem[text()='Text']");

I have also tried:

driver.FindElementByXPath("//DataItem[@ValuePattern.Value='Text']");

Both of these throw a NoSuchElementException. However, I AM able to successfully invoke WebDriverWait on the TextToBePresentInElement and this is working:

// my locator
private WindowsElement IdentifierSearchResult => Driver.FindElementByXPath("//DataItem[@Name='Identifier']");

// webdriverwait using the above locator, wait for 'Text' to be present in this element.
new WebDriverWait(Driver, TimeSpan.FromSeconds(20)).Until(SeleniumExtras.WaitHelpers.ExpectedConditions.TextToBePresentInElement(IdentifierSearchResult, 'Text'));

This is also printing the correct text:

var elements = Driver.FindElementsByXPath("//DataItem[@Name='Identifier']");
var text = elements.First().Text;

However, this is just a debugging scenario where I am retrieving a list, and printing the text of the first one -- this is simply a test to verify that the element has a valid .Text attribute. I cannot use this locator for my final code, because there is no guarantee it is choosing the correct element.

I've looked around the WinAppDriver repository samples, but I can't find anything actually using text -- everyone uses @Name or @AutomationId -- my element name is not unique, and it has no automation ID, so this does not work for me.

I know that I can use LINQ to work around the issue as such:

var elements = driver.FindElementsByXPath("//DataItem[@Name='Identifier']");
var elementToClick = elements.FirstOrDefault(e => e.Text == 'Text');

But that feels like a hacky workaround, and I'd like to avoid it if possible.

How can I locate the element using its text? Something like //DataItem[@Text='Text'] (I've tried that too, btw) is preferable, where I can pass in my 'Text' as a parameter.

CEH
  • 5,701
  • 2
  • 16
  • 40

1 Answers1

2

I faced the same problem while working with menu items. At first, I used a ForEach loop to check for the text value. I later refactored it to a LINQ expression. But I believe there's no way around this problem, and you'll have to do it using a loop or LINQ. Update: using XPath in your Windows automation scripts will slow your tests. XPath processing in WAD is very slow.

Naeem A. Malik
  • 995
  • 4
  • 19