Handling Unexpected Popup

51 views
Skip to first unread message

JeffU

unread,
Aug 30, 2018, 1:55:10 PM8/30/18
to TestStack.White
We're automating the installation of our product and currently, once we being the installation, we simply wait for the finish button.

During that time, there's a possibility that the installation throws a pop-up window (for a feature installation, or other reasons). 

However, we haven't found a great way to catch these pop-ups without introducing a race-condition.

Does any know of a way to implement a watcher that can monitor for a popup/modal window and handle it?


Code Snippet:
WhiteUIItems.Button FinishButton = null;
            while (FinishButton == null)
            {
                try
                {
                    FinishButton = window.Get<WhiteUIItems.Button>(SearchCriteria.ByText("Finish"));
                    window.WaitTill(delegate () { return FinishButton.Visible; });
                }
                catch
                {
                    if(window.ModalWindows().Count() > 0)
                    {
                        PrintScreen("Install", "ModalWindow");
                        Assert.Fail("Got unexpected modal window, see screenshot");
                    }
                }
            }

Caveat: There is an expected modal window at the end, when the installation finishes, asking the customer if they want to restart. Here we simply wait for the Finish button to become visible and then search for the window:

List<Window> win = app.GetWindows();
            if (win.Count() > 1)  // Rando window popped up  
            {
                PrintScreen("InstallVIS", "WindowPOPUP");

                foreach (Window newWindow in win)
                {
                    Trace.WriteLine("Got Window");
                    try
                    {
                        WhiteUIItems.Button RestartNo = newWindow.Get<WhiteUIItems.Button>(SearchCriteria.ByText("No"));
                        if (RestartNo != null)
                        {
                            RestartNo.Click();
                            Trace.WriteLine("Clicked No on restart");
                        }
                    }
                    catch
                    {

                    }
                }
            }

Mike Hetzer

unread,
Aug 31, 2018, 11:34:57 AM8/31/18
to TestStack.White
I would say unless you can determine the condition for which the seemingly random pop-up will trigger, that you are stuck trying to account for it.
We automate a pretty hefty loan origination system and deal with this all the time.
We've been dealing with it by putting in a loop that will try to locate the "random" window in a certain period of time and if it doesn't find it, it returns false.
In your case it looks like you can just keep checking for a count of modal windows and then probably use another condition?

Either way, you can have a more stable test, albeit a longer one . .



On the other hand . . . . . . . you could go around White and use the core Windows Automation (White is built on top of this anyway).
When you find Automation Elements in this manner, you aren't as restricted because White expects certain things or else it throws exceptions.

PropertyConditions are White's 'SearchCriteria' - and AutomationElement is White's general 'UIItem'





Below is window checking method we use in our framework, simply because our app keeps getting too customized to use White.
This is "using UIAutomationClient;" - which is the unmanaged code version of System.Windows.Automation (S.W.A is what White is built over)
When trying to find an element using UIAutomationClient - if it doesn't exist, it will just come back as null, and that's all you have to worry about.
You can put in your own timeouts, conditions, or whatever to suit your needs.

                /// <summary>
/// Only to be used if the Window is not guaranteed to appear.
/// </summary>
/// <param name="Condition"></param>
/// <param name="TimeOutInSeconds"></param>
/// <returns></returns>
public static bool CheckForWindow(IUIAutomationCondition Condition, double TimeOutInSeconds = 30)
{
bool found = false;
IUIAWindow windowToFind = null;

IUIAutomationOrCondition windowTypes = (IUIAutomationOrCondition)_autoclass.CreateOrConditionFromArray(new IUIAutomationCondition[]
{
_autoclass.CreatePropertyCondition(UIA_PropertyIds.UIA_LocalizedControlTypePropertyId, "dialog"),
_autoclass.CreatePropertyCondition(UIA_PropertyIds.UIA_LocalizedControlTypePropertyId, "window")
});
IUIAutomationAndCondition windowLocator = (IUIAutomationAndCondition)_autoclass.CreateAndConditionFromArray(new IUIAutomationCondition[]
{
_autoclass.CreatePropertyCondition(UIA_PropertyIds.UIA_ProcessIdPropertyId, BaseTest.ProcessID),
Condition,
windowTypes
});

DateTime dtStart = DateTime.Now;
DateTime dtCurrent;
for (int i = 0; i < 10000; i++)
{
new UIA_BaseScreen();
try
{
windowToFind = (IUIAWindow)_root.FindFirst(TreeScope.TreeScope_Descendants, windowLocator);
}
catch(COMException e) { }
dtCurrent = DateTime.Now;
if (windowToFind == null)
{
Console.WriteLine($"CheckForWindow Method - Window Not Yet Found!");
Thread.Sleep(250);
}
else
{
found = true;
Console.WriteLine($"CheckForWindow Method - Window Found!");
}
Console.WriteLine($"CheckForWindow Method - Iteration: [{i}] - Seconds Spent: [{(dtCurrent - dtStart).TotalSeconds}]");
if (found)
break;
if ((dtCurrent - dtStart).TotalSeconds > TimeOutInSeconds)
{
Console.WriteLine($"CheckForWindow Method - Did not locate window in Process ID [{BaseTest.ProcessID}] in the alotted time - Kicking out!");
return false;
}
}

return found;
}
Reply all
Reply to author
Forward
0 new messages