Question

I am writing a coded ui test for my project, and i'd like to test if a label is visible or not.

However, the auto-generated code uses WinText, which does not contain any visibility option.

Is there a way to check visibility of the ui element behind WinText's or get the actual label instead ?

Was it helpful?

Solution

The easiest and most straightforward way is to call WinText's TryGetClickablePoint. If it returns false that means the control is either invisible, offscreen or blocked by an other control.

Point p = new Point();
bool isVisible = UIMap.UIForm1Window.UILabel1Window.UILabel1Text.TryGetClickablePoint(out p);

If you want to fiddle with the "ui element behind WinText's" then you have to get its native element and cast it to the appropriate class (IAccessible if winform) and get the visibility state from there. Be careful tho: you'll probably have to get the label's window's native element and not the label's.

IAccessible acc = (UIMap.UIForm1Window.UILabel1Window.NativeElement as object[])[id] as IAccessible; //id is most probably 0, check with AccExplorer
bool isVisible = (((AccessibleStates)acc.accState & AccessibleStates.Invisible) == 0) && (((AccessibleStates)acc.accState & AccessibleStates.Offscreen) == 0);

OTHER TIPS

I'm using the following extension method for the UITestControl class, and so far it has been pretty bullet proof:

using Microsoft.VisualStudio.TestTools.UITesting;

namespace CodedUIExtensions
{
    public static class UITestControlExtensions
    {
        public static bool IsElementVisible(this UITestControl control)
        {
            // Assume the control is invisible
            bool visible = false;
            System.Drawing.Point p;

            try
            {
                // If the control is offscreen, bring it into the viewport
                control.EnsureClickable();

                // Now check the coordinates of the clickable point
                visible = control.TryGetClickablePoint(out p)
                    && (p.X > 0 || p.Y > 0);
            }
            catch (Exception ex)
            {
                // Boom goes the dynamite! Control is not visible.
                // Log to stdout for debugging.
                Console.WriteLine(ex);
            }

            return visible;
        }
    }
}

My requirements were:

  1. Ensure the control is inside the viewport so a control that is visible, but offscreen doesn't trigger a false negative
  2. Then assert the control is visible
  3. Do not throw exceptions
  4. If an exception occurs, do something with it for debugging purposes

And to use it:

using CodedUIExtensions;

[CodedUITest]
class MyTest
{
    [TestMethod]
    public void SomeVisibilityTest()
    {
        UITestControl control = // ...
        HtmlDiv div = // ...

        Assert.IsTrue(control.IsElementVisible(), "Not visible");
        Asset.IsFalse(div.IsElementVisible(), "Visible");
    }
}

As long as the Coded UI control class inherits from UITestControl and you have using CodedUIExtensions in your C# file, every control will have an IsElementVisible() method. This should work for web pages as well as GUI applications, such as WinForms.

You can try this:

Control.WaitForControlPropertyNotEqual(UITestControl.PropertyNames.State, ControlStates.Invisible);

This one worked for me (and also the method with .TryGetClickablePoint() ):

while (myControl.State != ControlStates.Offscreen) { }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top