0
votes

I have been testing a desktop application (WPF). in Use: C#, Appium, WinAppDriver. There are several numeric textboxes in one menu. The problem I have here is that I can't access the UpButton of a specific textbox on this page as all of the Up/Down Buttons have the same ID, "PART_IncreaseButton".

It's a numeric textbox with build in up down control. There are several of them in one menu. textbox

I use the inspect.exe to identify the object. Tree in inspector: inspect screenshot

So under custom are the 3 controls of the textbox "edit", "button", "button" With "Root_0_Blue_AutomationId" I can access the textbox and for instance write something into the box.

But if I inspect the up button of the specific textbox it has the automationID "Part_IncreaseButton". and the upcontrols of the other textboxes have the same ID. Only the AutomationID of the rootID is different, and the ID of the upcontrols stays the same, for instance:

Root ID (of the textbox): "Root_0_Blue_AutomationId" UpControl ID: "Part_Increasebutton"

Root ID (2nd textbox, green channel is different): "Root_0_Green_AutomationId" UpControl ID: "Part_Increasebutton"

How can I manage it to access the UpControl of the second textbox?

3
Hi @VanGoghh, welcome to StackOverflow! Please provide a complete, minimal, reproducible example of what have you tried in-code, the exact error message (if applicable) and what is the result you expect! - Ivan García Topete
Agreeing with @IvanGarcíaTopete, you are very welcome here, but if you expect a quality answer, your question will need to meet the criteria already mentioned in the comment above. But maybe, I can help you solve your problem yourself :-). Can I derive from your question that the up/down button is always contained in a textbox? In that case, if the textbox has a unique automation ID, you have the relative coordinates for your up/down buttons. - PixelPlex
Thanks a lot for your welcome and sorry for not providing more information. I will try to get better in future :). I have edited my question, I hope it's more understandable now. Thanks - VanGoghh
I've posted my answer. I see you've beat me to it ;-). Since I had it written out already, I decided to share it with you. Feel free to add feedback to it, if you decide to use my code. - PixelPlex

3 Answers

1
votes

It's entirely possible for multiple elements on the page to have the same automation id.

When this happens there are 3 things that can be done to identify and locate individual elements.

  1. Refactor the app so that each element has a different automation id.
  2. Use an alternative location strategy to uniquely identify the element.
  3. Locate a parent element that only contains 1 element with the target ID, then search it's children for the unique element you want to locate.

Provided you are working with a well designed app option 3 is the recommended approach. It allows you to use common logic for interacting with any up/down button while identifying them uniquely by the text box that contains them.

1
votes

Thanks a lot for the support.

I did it in the following way (2 steps):

First find the parent element:

WindowsElement TB1 = Editor.FindElementByAccessibilityId("Root_0_Blue_AutomationId");

then find the other controls:

AppiumWebElement TB1UpControl = TB1.FindElementByAccessibilityId("PART_IncreaseButton");

Click on UpControl:

Actions builder = new Actions(Editor);

builder.Click(TB1UpControl).Perform();

Best regards!

0
votes

Here's my implementation. I did not add error handling for simplicity's sake. The code compiles but I have not tested this. The up/down buttons and the textbox are contained in a object, so it's nicely separated from your other code.

using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Windows;
using System.Collections.ObjectModel;
using System.Linq;

namespace Example
{
    class SpinControl
    {
        public int Value {
            get
            {
                //call _textBox here to get the value from your control.
                return 0;
            }
        }

    private readonly AppiumWebElement _increaseButton;
    private readonly AppiumWebElement _decreaseButton;
    private readonly AppiumWebElement _textBox;

    public SpinControl(string automationID, WindowsDriver<WindowsElement> Driver)
    {
        WindowsElement customControl = Driver.FindElementByAccessibilityId(automationID);
        ReadOnlyCollection<AppiumWebElement> customControlChildren = customControl.FindElementsByXPath(".//*");

        _increaseButton = customControlChildren.First(e => e.FindElementByAccessibilityId("Part_IncreaseButton").Id == "Part_IncreaseButton");
        _decreaseButton = customControlChildren.First(e => e.FindElementByAccessibilityId("Part_DecreaseButton").Id == "Part_DecreaseButton");
        _textBox = customControlChildren.First(e => e != _increaseButton && e != _decreaseButton);
    }

    public void Increase()
    {
        //call _increaseButton here
    }

    public void Decrease()
    {
        //call _decreaseButton here
    }

    public void Input(int number)
    {
        //call _textBox here
    }
}

}

Can be used like this:

        SpinControl sp = new SpinControl("customControlAutomationID", Driver);

        sp.Increase();
        sp.Decrease();
        sp.Input(5);
        int value = sp.Value;