WindowTitleFilter

public WindowTitleFilter()
{
    Require(stack => !string.IsNullOrEmpty(stack.Peek().UIElement.TopLevelElement.Name));
}

protected override void Run(IUITestActionStack stack)
{
    UITestAction action = stack.Peek();
    var conditions = new List<IQueryCondition>(LetterFragments(action.UIElement.TopLevelElement.Name)
        .Select(s => new PropertyCondition(
            "Name",
            s,
            PropertyConditionOperator.Contains)));
        
    // We have to preserve other conditions the
    // the window has, so we go through and collect
    // them.
    foreach (var condition in
        (action.UIElement.TopLevelElement.QueryId.Condition as AndCondition).Conditions)
    {
        if (condition is PropertyCondition &&
            (condition as PropertyCondition).PropertyName != "Name")
        {
            conditions.Add(condition);
        }
    }

    action.UIElement.TopLevelElement.QueryId.Condition = new AndCondition(conditions.ToArray());
}

This is the first more complicated filter, largely because of the algorithm for removing the problematic parts of the window title. The filter itself is fairly self describing. The problem it solves is where the CUITs often create new elements and then interact with new windows with hard to predict IDs. To fix this, numbers are removed from the window titles. Unfortunately, the hand-made PropertyConditions can't interact with some elements of the window title. This seems to be caused by odd unicode issues, but the exact cause is unknown. To fix this as a workaround, parentheticals are also ignored.

private IEnumerable<string> LetterFragments(string str)
{
    if (str == null) return new string[0];

    // Gather all the indices in the string where
    // there are characters that are not letters or
    // spaces, or are inside parentheses.
    List<string> elements = new List<string>();
    List<int> nonAlphaIndices = new List<int>();
    // Also have the beginning...
    nonAlphaIndices.Add(-1);
    bool insideParens = false;
    for (int i = 0; i < str.Length; ++i)
    {
        if (str[i] == '(')
        {
            insideParens = true;
        }
        if (insideParens || (!char.IsLetter(str[i]) && !char.IsWhiteSpace(str[i])))
        {
            nonAlphaIndices.Add(i);
        }
        if (str[i] == ')')
        {
            insideParens = false;
        }
    }
    // ... and the end.
    nonAlphaIndices.Add(str.Length);

    // Go through again, only adding substantive
    // substrings of the string which follow the
    // criteria.
    for (int i = 1; i < nonAlphaIndices.Count; ++i)
    {
        int left = nonAlphaIndices[i - 1] + 1;
        int right = nonAlphaIndices[i];
        int length = right - left;
        if (length > 1)
        {
            elements.Add(str.Substring(left, right - left));
        }
    }
    return elements;
}

This is the function used to separate the title of a window in to fragments around the numbers and parentheticals. To do this, it identifies every index on which there are numbers, or which is in parentheses. It then goes through every pair of adjacent indices in series, only adding the substring between them if it's large enough.

Last edited Aug 1, 2014 at 7:25 PM by wgoodin, version 8