Search code examples
appiumappium-ios

How to check if an element is only partially visible or fully visible in Appium iOS?


I have an iOS app that has a lot of input fields on a single page. I want to automate those inputs and i know how to scroll to those elements and everything, but I have a problem with partially displayed elements.

There are two cases in which partially displayed elements cause a problem:

The first case is caused when another element is overlapping with the element in the background. If I click on the element in the background, than Appium clicks on the overlapping element. This causes the wrong interaction and therefor the test crashes. The function isDisplayed() is not usable as the result is true for partially displayed elements, even if just one or two lines of pixels are visible.

The second case is happening when I type something into an element with sendKeys(). This opens the keyboard on iOS and when I want to click on the next element, it is possible that the keyboard is exactly over the element, except for some space that is still visible from the element, so that isDisplayed() returns true for the element. I know there is the option of hideKeyboard(), but this isn't always possible, as the keyboard displayed must have the hide key as a key visible.

One solution for me is that I don't click on the next element, but on the one below it, but this is ugly as hell, and there should be a nicer solution.

I already tried to calculate the height of the element, but in iOS this is impossible, as all elements, even if not on the screen, are still find-able in Appium and have always the height of the element.

So my question is how do I check if an element is fully visible with something more reliable than isDisplayed()? I would prefer a solution for Java, but I can manage other languages as well.


Solution

  • I managed this task by implementing a class BaseElement which holds an instance of a RemoteWebdriver (a base of AppiumWebdriver) as a "Session"- property.

    This BaseElement class also features the following property (The RootElement here is the original IWebElement of which I want to know whether it is fully visible):

    public virtual bool IsFullyVisible
    {
        get
        {
            IWindow wnd = this.Session.Manage().Window;
            Rectangle webViewScreenRect = new Rectangle(wnd.Position, wnd.Size);
    
            Rectangle elemRect = new Rectangle(this.RootElement.Location, this.RootElement.Size);
            return webViewScreenRect.Contains(elemRect);
        }
    }
    

    Unfortunately I got into troubles with this when using the code against an embedded device which featured a rather old version of chrome to show the UI. So maybe there is a problem when trying to get the Window object on older versions of chrome. If someone knows more about that, I would be delighted to hear of.

    I was asked to be a bit more clear about the actual solution to the problem described by the OP. So I try to elaborate on that part once more:

    The RemoteWebDriver (a base class of the AppiumDriver and the AndroidDriver as well) features the opportunity to get a IWindow object which enables us to get the screen dimensions. For simplicity's sake we create a Rectangle object with that information.

     IWindow wnd = SomeRemoteWebdriverInstance.Manage().Window;
     Rectangle webViewScreenRect = new Rectangle(wnd.Position, wnd.Size);
    

    Then we get the rectangle of the element we would like to check the visibility for:

    Rectangle elemRect = new Rectangle(TheIWebElementInstance.Location, TheIWebElementInstance.Size);
    

    After that we can use the rectangle's method to check, whether the element's rectangle is completly inside the screen's rectangle:

    webViewScreenRect.Contains(elemRect);
    

    Thus answering the initial question.

    The aforementioned encapsulation is just to have this and other methods always at hands when handling IWebElements. Well one could equally think of an extension method or other encapsulation of this mechanism. As mentioned above: Keep an eye out for older systems! Happy coding