locked
Navigating menus common between web app pages is too slow. RRS feed

  • Question

  • I'm having an issue with menu navigation.  Using TFS 2010 on a Windows 7 machine, our web app has a menu system common between all of the individual pages.  To access these menus, we mapped each menu to the Home page.  All other individual page maps then are linked back to the Home page as follows:

        using HomePageMapClasses;
        
        public partial class DisplayPartHistoryPageMap : HomePageMap

    The problem is that it takes about 4 to 5 seconds to initially find the menu bar, then another 3 to 4 second to mouse over each menu selection before finally clicking on the desired option.  In the example below, it takes a little over 15 seconds to select (in this case) the Display Stock Balance menu option.  With as many menu selections as our test scripts require, execution time is seriously impacted. 

    The reason we had to go this route is because the menu IDs are dynamic.  In the .uitest file, the overall hierarchy is mapped as follows:

    HomeWindow
        HomeDocument
            DisplayStockBalanceInfo
                DisplayStockBalanceInfoBVX

    HomeWindow                         Control Type:  Window
    HomeDocument                      Control Type:  Document
    DisplayStockBalanceInfo         Class Name:   HtmlTableRow
                                                 Control Type:   Row
    DisplayStockBalanceInfoBVX   Class Name:   HtmlHyperlink
                                                 Control Type:   Hyperlink
                                                 FriendlyName: ctl00_ctl10_1 SubMenuItem ctl00_ctl10_5

    In the end, we had to strip down the search parameters by getting rid of the PropertyCondition Name="Id" parameter since some pages were unable to find the proper menu.  This gets particularly bad when menu items are added or deleted based on project demands.  For example, the Display Stock Balance menu now looks like this...

      <UIObject ControlType="Hyperlink"
           Id="DisplayStockBalanceInfoBVX"
           FriendlyName="Display Stock Balance Info (BVX)"
           SpecialControlType="None">
        <TechnologyName>Web</TechnologyName>
        <WindowTitles>
          <WindowTitle>WebSceptre : Home</WindowTitle>
        </WindowTitles>
        <AndCondition Id="SearchCondition">
          <AndCondition Id="Primary">
            <PropertyCondition Name="ControlType">Hyperlink</PropertyCondition>
            <PropertyCondition Name="Id" />
            <PropertyCondition Name="Name" />
            <PropertyCondition Name="TagName">A</PropertyCondition>
            <PropertyCondition Name="Target" />
            <PropertyCondition Name="InnerText">Display Stock Balance Info (BVX)</PropertyCondition>
          </AndCondition>
          <FilterCondition Id="Secondary">
            <PropertyCondition Name="AbsolutePath">/Parts/Info/DisplayStockBalanceInfo.aspx</PropertyCondition>
            <PropertyCondition Name="Title" />
            <PropertyCondition Name="Href">http://to-int-websceptre/Parts/Info/DisplayStockBalanceInfo.aspx</PropertyCondition>
            <PropertyCondition Name="ControlDefinition">style="BORDER-BOTTOM-STYLE: none; BORDER</PropertyCondition>
            <PropertyCondition Name="TagInstance">1</PropertyCondition>
          </FilterCondition>
        </AndCondition>
        <SupportLevel>0</SupportLevel>
        <Descendants />
      </UIObject>

    In the following example, we have a menu chain (partial) that looks like this...

    Parts
        Info
            Display Part History
            Display Tooling
            Display Interchangeable
            Display Stock Balance
       Order
            Order Part
            Display On-Order

    Given: Action Type: Menu Option
              Action Text:  Parts|Info|Display Part History|Display Stock Balance
     
     (This Action Text format is needed to keep from accidentally selecting an incorrect menu option when the cascading menu list is long, since the Mouse.Move opens whichever cascading menu happens to be in the way of the desired selection.  For example, if the Display Stock Balance menu is supposed to be selected, Mouse.Move would have to pass over the Order menu to get to the position where Display Stock Balance would normally be, but doing so would cause the Order cascading menu to open, so what would be selected instead is Order Part.  Including the Display Part History sub-menu in the Action Text forces the Info cascading menu to remain open, allowing any subsequent sub-menu to be available for clicking.)

    The actual code used to select the menu option is as follows:

     public void PerformAction(Dictionary<FieldObject, string> action, object map, Dictionary<string, string> global, int stepNumber)
     {
      foreach (FieldObject key in action.Keys)
      {
       string[] keys = action[key].Split('|');
      
       // SetFocus forces the screen to scroll to the top to uncover the menus
       if (key.FieldName == "MenuOption")
        HomeWindow.HomeDocument.HomeCell.Home.SetFocus();
      
       foreach (string k in keys)
       {
        clickObject = map.GetType().GetProperty(k).GetValue(map, null);
      
        if (keys.Length > 1)
        {
         Mouse.MouseMoveSpeed = 10000;
      
         // Find the Action object...
         Mouse.Move((UITestControl)clickObject, ((UITestControl)clickObject).GetClickablePoint());
        }
       }
      
       // Perform the action...
       Mouse.Click((UITestControl)clickObject, ((UITestControl)clickObject).GetClickablePoint());
      }
     }


    Can someone suggest a better method for selecting dynamic menus (or at least speeding up this process)?

     


    Kevin
    Monday, September 19, 2011 4:00 PM

Answers

  • Kevin,

    I have new Point (10, 10) just to specify point to Click/Hover on control. Also, point specified is not a point on screen its relative to control it is treated as coordinate on control
    You can use GetClickablePoint() method in place of it.

    2000
    specified is duration of hover.

    thus we can write:
    Mouse.Hover(menuto, menuto.GetClickablePoint(), 2000);


    ----Vinay
    Wednesday, September 21, 2011 4:53 PM

All replies

  • Hi,

    Try adding SearchConfiguration to uiControl for the menu
                             uiControl.SearchConfigurations.Add(SearchConfiguration.ExpandWhileSearching);

    Can you give more details on how is menu navigated 

    e.g for saving doc in notepad we do
    Click 'File' Menu
    Click 'Save'

    to search 'Save' provide 'File' as search container and we add search configuration defined above
    Code would be like this
    WinWindow notepad = new WinWindow();
    ......//properties for main window

    WinMenuBar Menubar = new WinMenuBar(notepad);
    ......//properties for menubar

    WinMenuitem File = new WinMenuItem(MenuBar);  //propvided menubar object  as container
    ......//properties for File Menu

    WinMenuitem Save = new WinMenuItem(File);    //provided file object as container
    ......//properties for File Menu
    Save.SearchConfiguration.Add(SearchConfiguration.ExpandWhileSearching);  


    ----Vinay
    Tuesday, September 20, 2011 4:34 AM
  • Hi Vinay,

    Thanks for the response.  The way our menu is navigated is strictly via mouse-overs.  We don't actually have to click on the cascading menus to open them.  (That's why the extra menu option has to be in the list, to avoid accidentally opening the wrong cascade menu.)

    Our dataset input string identifies the menu routing to follow.  Thus, Parts|Info|Display Part History|Display Stock Balance depicts the "path" to click on the correct menu option.
     
    The line string[] keys = action[key].Split('|'); splits this input string up into the individual menu options and results in this...

        keys[0] = Parts
        keys[1] = Info
        keys[2] = Display Part History
        keys[3] = Display Stock Balance

    Then, the foreach (string k in keys) loop just moves the mouse over each consequative menu option, highlighting each one in turn.  The only menu that is actually clicked on is the last one in the sequence.

    Unfortunately, since I'm still rather new to C#, I'm not sure how using the ExpandWhileSearching option would replace what we're currently doing.  In our .uitest file, each menu item is mapped individually, under the Window and Document.  The sub-menus aren't dependents of the upper-level menus, so I'm not sure that providing the upper-level menus as containers would work for searching for the lower-level items.  Would it be better to restructure the .uitest file so that the lower-level menus are actually inside the upper-level menus?


    Kevin
    Tuesday, September 20, 2011 2:29 PM
  • Hi Kevin,

    If you don't want control to be click use Mouse.Hover in place of Mouse.Click, it will mouse hover the control for duration you provide.


    Below code i have tested for Microsoft Excel 2007  there in I navigated after clicking office button at the top (open new excel and run the below code)
                "Prepare|Restrict Permission|Unrestricted Access"

     

     

     

     

    public voidExcelHover()
    {
        WinWindow ExcelWindow = new WinWindow();
        ExcelWindow.SearchProperties[
    WinWindow.PropertyNames.Name] = "Microsoft Excel - Book1 [Compatibility Mode]";
        ExcelWindow.SearchProperties[
    WinWindow.PropertyNames.ClassName] = "XLMAIN"

    ;

        ExcelWindow.SetFocus();

     

     

     

        WinWindow MenuRibbon = new WinWindow(ExcelWindow);
        MenuRibbon.SearchProperties[
    WinWindow.PropertyNames.AccessibleName] = "Ribbon";
        MenuRibbon.SearchProperties[
    WinWindow.PropertyNames.ClassName] = "NetUIHWND"

    ;

     

        WinControl OfficeButton = new WinControl(ExcelWindow);
        OfficeButton.SearchProperties[
    UITestControl.PropertyNames.Name] = "Office Button";
        OfficeButton.SearchProperties[
    UITestControl.PropertyNames.ControlType] = "DropDownGridButton"

    ;

     

        // Click 'Office Button' DropDownGridButton
        Mouse.Click(OfficeButton, new Point

    (21, 25));

     

        string menu = "Prepare|Restrict Permission|Unrestricted Access";
        string[] menuarray = menu.Split('|'

    );

     

        WinMenuItem

    menuto;

     

        for (inti = 0; i < menuarray.Length; i++)
        {
            menuto =
    new WinMenuItem(MenuRibbon);
            menuto.SearchProperties[
    WinMenuItem.PropertyNames.Name] = menuarray[i];

            Mouse.Hover(menuto, new Point

    (10, 10), 2000);
        }

        menuto =

    new WinMenuItem(MenuRibbon);
        menuto.SearchProperties[
    WinMenuItem.PropertyNames

    .Name] = menuarray[menuarray.Length-1];

     

        Mouse

    .Click(menuto);
    }

     

     


    ----Vinay
    • Proposed as answer by Vinay P Wednesday, September 21, 2011 4:54 PM
    Wednesday, September 21, 2011 7:00 AM
  • Thanks, Vinay.  That will help a lot.  Did have one more question, though, with the line

        Mouse.Hover(menuto, new Point (10, 10), 2000);

    You're pointing to a discrete point on the screen with the new Point (10, 10), 2000.  Since our menus are changed all too frequently, can menuarray[i] be used as the hover point?

     


    Kevin
    Wednesday, September 21, 2011 3:49 PM
  • Kevin,

    I have new Point (10, 10) just to specify point to Click/Hover on control. Also, point specified is not a point on screen its relative to control it is treated as coordinate on control
    You can use GetClickablePoint() method in place of it.

    2000
    specified is duration of hover.

    thus we can write:
    Mouse.Hover(menuto, menuto.GetClickablePoint(), 2000);


    ----Vinay
    Wednesday, September 21, 2011 4:53 PM