How to check for visibility on a HTML control using Microsoft Coded UI tests

As you may have gathered from the title, I had written a test where I had to check if a control was visible on the page after I pressed a button. I wrote the test, clicked the button, everything was fine. Then I decided to double-check the test by reversing the condition (e.g. swapping an Assert.IsTrue for an Assert.IsFalse, or something similar). If this succeeded, then my test was probably working, and not just throwing a false positive. As always with these things, the test still passed, and that led to this post.

To give you a grossly simplified example, imagine a web page with a button. After we press the button, the words “Ta-dah!” appear on the page. Or for those of you with terrible imaginations, this JSFiddle should work.

We want to check that when the page first loads up, the words “Ta-dah!” aren’t visible. Here’s our first stab at it:

[code language=”csharp”][TestMethod]
public void FirstAttempt()
{
//Open up our web app
using (var window = BrowserWindow.Launch(AppUri))
{
//Set up some search properties for our control
HtmlControl control = new HtmlControl(window);
control.SearchProperties.Add(HtmlControl.PropertyNames.Id, "invisible");

//This should mean that we only find visible controls, right?
control.SearchConfigurations.Add(SearchConfiguration.VisibleOnly);

UITestControlCollection matches = control.FindMatchingControls();

//If we haven’t found anything, then I guess we’re good
Assert.AreEqual(0, matches.Count);
}
}[/code]

A bit of a hack, but it’s simple enough. We set up our search terms and tell the framework to find all the controls which match those, as usual. If the control’s not visible, it shouldn’t be found by our search and so there won’t be any matches.

Unfortunately, when we run the test, it fails. This is because SearchConfiguration.VisibleOnly doesn’t work on HTML controls, so even controls which aren’t shown on the page will be found by the search. In order to find our control, we’re going to have to use another method. In the example, the hidden paragraph is hidden by setting its style to ‘display:none’, and conveniently enough there’s a very simple method we can use in that situation: when a control’s been hidden this way, its bounding rectangle will have a negative height and width. So, with that in mind, we can use a simple extension method to ensure we only grab visible controls:

[code language=”csharp”]public static class HtmlControlExtensions
{
public static UITestControlCollection FindVisibleMatches(this UITestControl control)
{
UITestControlCollection matches = control.FindMatchingControls();
matches.RemoveAll(x => !IsVisible(x));
return matches;
}

private static bool IsVisible(UITestControl control)
{
return
control.BoundingRectangle.Width > 0 &&
control.BoundingRectangle.Height > 0;
}
}[/code]

Then, instead of using FindMatchingControls, just use the extension method:

[code language=”csharp”][TestMethod]
public void SecondAttempt()
{
//Open up the web app
using (var window = BrowserWindow.Launch(AppUri))
{
//Set up some search properties for our control
HtmlControl control = new HtmlControl(window);
control.SearchProperties.Add(HtmlControl.PropertyNames.Id, "invisible");

//Use the extension method to only grab visible controls
UITestControlCollection matches = control.FindVisibleMatches();

//And now this assert succeeds
Assert.AreEqual(0, matches.Count);
}
}[/code]

This second test succeeds. Finally, we can write a test to check whether the control is visible after the button is pressed:

[code language=”csharp”][TestMethod]
public void WordsAreVisibleAfterButtonIsPressed()
{
//Open up the web app
using (var window = BrowserWindow.Launch(AppUri))
{
//Press the button
HtmlControl button = new HtmlControl(window);
button.SearchProperties.Add(HtmlControl.PropertyNames.Id, "button");
HtmlControl foundButton = button.FindMatchingControls()[0] as HtmlControl;
if (foundButton == null)
{
Assert.Fail("Button was not of an appropriate type");
}
else
{
Mouse.Click(foundButton);
}

//Set up some search properties for our control
HtmlControl control = new HtmlControl(window);
control.SearchProperties.Add(HtmlControl.PropertyNames.Id, "invisible");

//Use the extension method to only grab visible controls
UITestControlCollection matches = control.FindVisibleMatches();

//We should be finding the paragraph now
Assert.AreEqual(1, matches.Count);
}
}[/code]

and know that it’s only going to find the paragraph if it’s visible.

Before I go, I should point out that this won’t work if the control is hidden in a way which means it still takes up room on the page (for example, adding visibility:hidden to its style). If you have a way of doing that, or any other questions, ideas, criticisms, then leave a comment below. If you have none of those things, but you want to leave a comment anyway – perhaps you’re on fire, and the only way you can call for help is by leaving a comment – then by all means, feel free.

Leave a Reply

Your email address will not be published. Required fields are marked *