Search code examples
c#wpfwhite-framework

TestStack.White Why can I find a window with Application.GetWindows but not with .GetWindow?


Edit: In forming this question, I failed to note that the target window was a modal window so the approach I was trying was wrong. I should have been using GetModal, not GetWindow. Leaving this here as a potential reference for future travelers

I am trying to write some tests with TestStack.White for a massive WPF app I inherited; I have one case where a child window is created and I need to get a reference to it. If I iterate over the results of a call to Application.GetWindows I can find it, but I can't find it with any incarnation of Application.GetWindow that I can imagine.

This is illustrated in the following examples (where name is a string). The window is found in the foreach loop (as long as I sleep the thread for a second before iterating to give the window time to be created after clicking something else..) To be honest, the whole point of this exercise is just to get rid of this Thread.Sleep code-smell, so I'm wanting to use GetWindow and its built-in waiting.

        Thread.Sleep(1000);

        foreach (Window window in app.GetWindows())
        {
            if (window.AutomationElement.Current.Name == name)
            {
                Assert.AreEqual(window.Title, name); // passes.. they match
                Assert.AreEqual(window.AutomationElement.Current.Name, name);  // passes.. they match
                var aIdCheck = window.AutomationElement.Current.AutomationId; // empty string
            }
        }

        try  // this fails.. (after 30s)
        {
            var testGetWindow = app.GetWindow(name);
        }
        catch (Exception ex)   {   }

        try // this fails too... (after 5s)
        {
            var testGetWindow = app.GetWindow(SearchCriteria.ByNativeProperty(AutomationElement.NameProperty, name), InitializeOption.NoCache);
        }
        catch (Exception ex) {}

        try // you guessed it.. fail..
        {
            var testGetWindow = app.GetWindow(SearchCriteria.ByText(name), InitializeOption.NoCache);
        }
        catch (Exception ex) {}

Solution

  • Try this:

    var window = Retry.For(
                () => parent.GetWindows().First(x => x.Title.Contains(name)),
                TimeSpan.FromSeconds(5));
    

    If it works, what I believe the issue to be is that there are multiple processes/windows running with the name you are looking for. Your foreach loop works because it doesn't care and is simply finding the first, however the GetWindow() methods break when that is the case.