How to find a control if it is loaded in DOM after action

Sep 6, 2012 at 3:35 PM

I am trying to automate a page where when I click on a hyperlink, it loads this menu. It appears to be some kind of asynchronous call that loads the menu into the DOM after the fact (I can't find the menu in the HTML source prior to clicking on the link that loads it). When I try to search for elements in this menu so I can click on one of the menu items CUITe can't find them saying it could not find a match.

Is there something that I need to do to refresh the HTML for CUITe to look up? I've tried just re-getting the page but that didn't seem to do the trick.

Coordinator
Sep 7, 2012 at 11:04 AM

Seems like you found an answer to your questions here:

http://cuite.codeplex.com/discussions/394646

Sep 7, 2012 at 2:31 PM

No, this is a different issue, I've tired to call the Get in my test code and it still fails, it can't seem to fidn it.

accountsPage.Get<CUITe_HtmlHyperlink>("Title=Accounts: Requires Approval")

Sep 7, 2012 at 3:12 PM

By the way, I also tried using the method I used in the previous issue, but that also did not work. Both produce the same error:

Test method TejariAutomation.Tests.CRM_SmokeTest.GoToAccountsPage threw exception:
Microsoft.VisualStudio.TestTools.UITest.Extension.UITestControlNotFoundException: The playback failed to find the control with the given search properties. Additional Details:
TechnologyName:  'Web'
ControlType:  'Hyperlink'
TagName:  'A'
Title:  'Accounts: Requires Approval'
 Failed to find any control that matched the search condition ControlType='Hyperlink' && Title='Accounts: Requires Approval' ---> System.Runtime.InteropServices.COMException: Error HRESULT E_FAIL has been returned from a call to a COM component.

 

I'm 100% sure that this exists, but only after I click on the dropdown, so I think this is an issue with the DOM being updated dynamically?

Coordinator
Sep 8, 2012 at 2:08 AM

Hi ddoorn,

Can you provide some sample html/js and test code that can reproduce the problem please?

Thank you.

Sep 11, 2012 at 3:35 PM

ddoorn,

This might seem like a silly question, but have you tried putting a delay in the recording, to allow the menu javascript time to update the control? or can you not use the WaitForControlExist()

 

Kelso

Sep 12, 2012 at 1:35 PM

Unforunately I dont think I can provide sample code, this is coming from a complex web application (Microsoft Dynamics CRM). I've tried various ways to allow javascript time to update the control but none seem to work. I will try to see if I can search for anything else within the control instead to see if it is a search issue by title that is the problem.

Coordinator
Sep 14, 2012 at 11:34 PM

I am wondering if the actions recorded using built-in Coded UI recorder can play them back without issue?

If so, I would examine to code to see what could be different.

 

I also recommend turning on tracing for coded UI test components for additional diagnostic information.

How To: Enable Tracing for “UI Test” Components

http://blogs.msdn.com/b/gautamg/archive/2009/11/29/how-to-enable-tracing-for-ui-test-components.aspx

Sep 25, 2012 at 1:02 PM

I still need to enable tracing, but here is the CodedUI test code, the only thing that interests me is the fact they use "HtmlCustom" for both the list item and the hyperlink to click on the element. Does CUITe have something similar?

    [GeneratedCode("Coded UITest Builder", "10.0.40219.1")]
    public class UIAccountsRequiresApprCustom : HtmlCustom
    {
        
        public UIAccountsRequiresApprCustom(UITestControl searchLimitContainer) : 
                base(searchLimitContainer)
        {
            #region Search Criteria
            this.SearchProperties["Id"] = "{15C63745-0A6E-4322-8416-A62C84D90279}";
            this.SearchProperties[UITestControl.PropertyNames.Name] = null;
            this.SearchProperties["TagName"] = "LI";
            this.FilterProperties["Class"] = "ms-crm-VS-MenuItem-qrk ms-crm-VS-MenuItem-Rest-qrk";
            this.FilterProperties["ControlDefinition"] = "style=\"WIDTH: 282px; FLOAT: none\" id={15";
            this.FilterProperties["InnerText"] = "Accounts: Requires Approval";
            this.FilterProperties["TagInstance"] = "35";
            this.WindowTitles.Add("Accounts: All Accounts - Microsoft Dynamics CRM");
            #endregion
        }
        
        #region Properties
        public HtmlCustom UIAccountsRequiresApprCustom1
        {
            get
            {
                if ((this.mUIAccountsRequiresApprCustom1 == null))
                {
                    this.mUIAccountsRequiresApprCustom1 = new HtmlCustom(this);
                    #region Search Criteria
                    this.mUIAccountsRequiresApprCustom1.SearchProperties["Id"] = null;
                    this.mUIAccountsRequiresApprCustom1.SearchProperties[UITestControl.PropertyNames.Name] = null;
                    this.mUIAccountsRequiresApprCustom1.SearchProperties["TagName"] = "A";
                    this.mUIAccountsRequiresApprCustom1.FilterProperties["Class"] = "ms-crm-VS-MenuItem-Anchor-qrk ms-crm-VS-MenuItem-Anchor-Rest-qrk";
                    this.mUIAccountsRequiresApprCustom1.FilterProperties["ControlDefinition"] = "class=\"ms-crm-VS-MenuItem-Anchor-qrk ms-";
                    this.mUIAccountsRequiresApprCustom1.FilterProperties["TagInstance"] = "2";
                    this.mUIAccountsRequiresApprCustom1.WindowTitles.Add("Accounts: All Accounts - Microsoft Dynamics CRM");
                    #endregion
                }
                return this.mUIAccountsRequiresApprCustom1;
            }
        }
Coordinator
Sep 26, 2012 at 8:12 AM

Yes, CUITe has built-in wrappers around some html controls where HtmlCustom is used.

For example, CUITe_HtmlListItem is a wrapper around "li" tag elements (list items).

So in your case, you can try using .Get<CUITe_HtmlListItem>("Id={15C63745-0A6E-4322-8416-A62C84D90279}") to find the "Accounts: Requires Approval" list item for example and then call the Click() method on it.

Sep 26, 2012 at 11:24 AM

I tried that, but I got this error:

Error Message:

Test method TejariAutomation.Tests.CRM_SmokeTest.GoToAccountsPage threw exception:
CUITe.CUITe_InvalidSearchKey: Search Pattern Key not supported -> 'Id' in 'Id={15C63745-0A6E-4322-8416-A62C84D90279}'. Available Properties:

Stack Trace:

CUITe.Controls.CUITe_ControlBase`1.fillSearchProperties() in C:\CUITe Source Code\CUITe\Controls\CUITe_ControlBase.cs: line 275
CUITe.Controls.CUITe_ControlBase`1.Wrap(Object control) in C:\CUITe Source Code\CUITe\Controls\CUITe_ControlBase.cs: line 105
CUITe.Controls.HtmlControls.CUITe_BrowserWindow.Get[T](String searchParameters) in C:\CUITe Source Code\CUITe\Controls\HtmlControls\CUITe_BrowserWindow.cs: line 195
...

Coordinator
Sep 26, 2012 at 4:49 PM

Which version of CUITe are you using?

Please try using the latest code from the "Source Code" tab.

Thank you.

Sep 26, 2012 at 5:10 PM

I was using one a few weeks old, the latest seems to have resolved that problem.

So I was able to get the list item, but when I get the list item and try to click on it it says i'm blocked by another control. I'm assuming this means I need to get the hyperlink. So my code looks like this now:

            CUITe_HtmlListItem myListItem = accountsPage.Get<CUITe_HtmlListItem>("Id={15C63745-0A6E-4322-8416-A62C84D90279}");
            CUITe_HtmlHyperlink myLink = myListItem.Get<CUITe_HtmlHyperlink>("Title=Accounts: Requires Approval");
            myLink.Click();

However, I get this error:

Error message:

Test method TejariAutomation.Tests.CRM_SmokeTest.GoToAccountsPage threw exception:
Microsoft.VisualStudio.TestTools.UITest.Extension.UITestControlNotFoundException: The playback failed to find the control with the given search properties. Additional Details:
TechnologyName:  'Web'
ControlType:  'Hyperlink'
TagName:  'A'
Title:  'Accounts: Requires Approval'
 Failed to find any control that matched the search condition ControlType='Hyperlink' && Title='Accounts: Requires Approval' ---> System.Runtime.InteropServices.COMException: Error HRESULT E_FAIL has been returned from a call to a COM component.

Stack Trace:

Microsoft.VisualStudio.TestTools.UITest.Playback.Engine.IScreenElement.FindAllDescendants(String bstrQueryId, Object& pvarResKeys, Int32 cResKeys, Int32 nMaxDepth)
Microsoft.VisualStudio.TestTools.UITest.Playback.ScreenElement.FindAllScreenElement(String queryId, Int32 depth, Boolean singleQueryId, Boolean throwException)
Microsoft.VisualStudio.TestTools.UITest.Playback.ScreenElement.FindScreenElement(String queryId, Int32 depth)
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindFirstDescendant(String queryId, Int32 maxDepth, Int32& timeLeft)
Microsoft.VisualStudio.TestTools.UITesting.Playback.MapControlNotFoundException(COMException ex, IPlaybackContext context)
Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowComException(COMException innerException, IPlaybackContext context)
Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowException(SystemException exception, IPlaybackContext context)
Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowException(SystemException exception, String queryId)
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindFirstDescendant(String queryId, Int32 maxDepth, Int32& timeLeft)
Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.GetUITestControlRecursive(Boolean useCache, Boolean alwaysSearch, ISearchArgument searchArg, IList`1 windowTitles, Int32& timeLeft)
Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.GetElement(Boolean useCache, ISearchArgument searchArg)
Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.Search(ISearchArgument searchArg)
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindInternal()
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindControlIfNecessary()
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.WaitForControlReady(Int32 millisecondsTimeout)
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.WaitForControlReady()
CUITe.Controls.CUITe_ControlBase`1.Click() in C:\CUITe Source Code\CUITe\Controls\CUITe_ControlBase.cs: line 207
...

I first tried just getting the A tag rather than searching for the specific one, but I don't know how to get the second a tag. The HTML structure is somewhat strange, in that being there appears to be a hidden hyperlink first. Is there a way to just get the second hyperlink?

<li id=...>
  <a>
  <a title="Accounts: Requires Approval" ...>
    <span>

 

Coordinator
Sep 26, 2012 at 7:48 PM

You can try calling the GetChildren() method on myListItem and then get the second child.

You can also try calling the UnWrap().DrawHighlight() method on some of the controls in the hierarchy to see if the controls found are actually what you expected.

Sep 27, 2012 at 2:35 PM

I get a nullreferenceexception when trying to click after calling GetChildren and getting the second child

myListItem.GetChildren()[1].Click();

Drawhighlight on the LI element works, it is highlighting the right thing, it just seems like nothing exists underneath it.

Sep 27, 2012 at 2:53 PM

Actually, myListItem.GetChildren().Count returns a nullreferenceexception. It is as if nothing exists under the list item

Coordinator
Sep 27, 2012 at 4:34 PM

What is the error message and stack trace?

I'm thinking it might be related to a similar discussion here:

http://cuite.codeplex.com/discussions/397051

Thank you.

Sep 27, 2012 at 4:54 PM

The error message is:
System.NullReferenceException: Object reference not set to an instance of an object.

The stack trace is:

CUITe.Controls.HtmlControls.CUITe_HtmlControl`1.WrapUtil(HtmlControl control) in C:\CUITe Source Code\CUITe\Controls\HtmlControls\CUITe_HtmlControl.cs: line 323
CUITe.Controls.HtmlControls.CUITe_HtmlControl`1.GetChildren() in C:\CUITe Source Code\CUITe\Controls\HtmlControls\CUITe_HtmlControl.cs: line 184
...

Coordinator
Sep 28, 2012 at 7:14 AM

Hi.

It seems you have a bug in your code.

Please try:

CUITe_HtmlHyperlink myLink = myListItem.Get<CUITe_HtmlHyperlink>("InnerText=Accounts: Requires Approval");

Thank you.

Oct 1, 2012 at 5:22 PM

Could you elaborate what the bug in my code is?

I tried the above, but I got this error:

Test method TejariAutomation.Tests.CRM_SmokeTest.GoToAccountsPage threw exception:
Microsoft.VisualStudio.TestTools.UITest.Extension.UITestControlNotFoundException: The playback failed to find the control with the given search properties. Additional Details:
TechnologyName:  'Web'
ControlType:  'Hyperlink'
TagName:  'A'
InnerText:  'Accounts: Requires Approval'
 Failed to find any control that matched the search condition ControlType='Hyperlink' && InnerText='Accounts: Requires Approval' ---> System.Runtime.InteropServices.COMException: Error HRESULT E_FAIL has been returned from a call to a COM component.

Microsoft.VisualStudio.TestTools.UITest.Playback.Engine.IScreenElement.FindAllDescendants(String bstrQueryId, Object& pvarResKeys, Int32 cResKeys, Int32 nMaxDepth)
Microsoft.VisualStudio.TestTools.UITest.Playback.ScreenElement.FindAllScreenElement(String queryId, Int32 depth, Boolean singleQueryId, Boolean throwException)
Microsoft.VisualStudio.TestTools.UITest.Playback.ScreenElement.FindScreenElement(String queryId, Int32 depth)
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindFirstDescendant(String queryId, Int32 maxDepth, Int32& timeLeft)
Microsoft.VisualStudio.TestTools.UITesting.Playback.MapControlNotFoundException(COMException ex, IPlaybackContext context)
Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowComException(COMException innerException, IPlaybackContext context)
Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowException(SystemException exception, IPlaybackContext context)
Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowException(SystemException exception, String queryId)
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindFirstDescendant(String queryId, Int32 maxDepth, Int32& timeLeft)
Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.GetUITestControlRecursive(Boolean useCache, Boolean alwaysSearch, ISearchArgument searchArg, IList`1 windowTitles, Int32& timeLeft)
Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.GetElement(Boolean useCache, ISearchArgument searchArg)
Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.Search(ISearchArgument searchArg)
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindInternal()
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindControlIfNecessary()
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.WaitForControlReady(Int32 millisecondsTimeout)
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.WaitForControlReady()
CUITe.Controls.CUITe_ControlBase`1.Click() in C:\CUITe Source Code\CUITe\Controls\CUITe_ControlBase.cs: line 207
...

Coordinator
Oct 1, 2012 at 6:21 PM

Your previous code:

accountsPage.Get<CUITe_HtmlHyperlink>("Title=Accounts: Requires Approval")

The new code I recommended:

CUITe_HtmlHyperlink myLink = myListItem.Get<CUITe_HtmlHyperlink>("InnerText=Accounts: Requires Approval");

 

From the code generated from the Coded UI test recorder, it does not seem that you have a title attribute specified on the hyperlink, contrary to the html you posted.  I'm not sure which one is more accurate.

The new code I recommended uses the InnerText search key instead.

The user who reported a similar error was able to work-around this issue and he has posted his code here: http://cuite.codeplex.com/discussions/397051

Please try to use similar code "to move the mouse to [a] point relative to the parent control" before clicking, maybe something similar to this:

CUITe_HtmlListItem myListItem = accountsPage.Get<CUITe_HtmlListItem>("Id={15C63745-0A6E-4322-8416-A62C84D90279}");
CUITe_HtmlHyperlink myLink = myListItem.Get<CUITe_HtmlHyperlink>("InnerText=Accounts: Requires Approval");
Mouse.Move(myListItem.UnWrap(), new System.Drawing.Point(0,0));
Mouse.Click();

You can also try turning on tracing to help troubleshoot the issue.

Oct 1, 2012 at 6:40 PM

Oh, I must have sent the wrong set if code, I've been using myListItem.Get for a while now, i've tried many different combinations to get this to work.

The above code you sent me doesn't work because even though it calls .Click() in my case and in your case it calls the Mouse.Move() it is the Get of that hyperlink based off of InnerText (or for that matter anything) that returns the controlNotFoundException.

I will try to get that tracing on.

Test method TejariAutomation.Tests.CRM_SmokeTest.GoToAccountsPage threw exception:
Microsoft.VisualStudio.TestTools.UITest.Extension.UITestControlNotFoundException: The playback failed to find the control with the given search properties. Additional Details:
TechnologyName:  'Web'
ControlType:  'Hyperlink'
TagName:  'A'
InnerText:  'Accounts: Requires Approval'
 Failed to find any control that matched the search condition ControlType='Hyperlink' && InnerText='Accounts: Requires Approval' ---> System.Runtime.InteropServices.COMException: Error HRESULT E_FAIL has been returned from a call to a COM component.

Microsoft.VisualStudio.TestTools.UITest.Playback.Engine.IScreenElement.FindAllDescendants(String bstrQueryId, Object& pvarResKeys, Int32 cResKeys, Int32 nMaxDepth)
Microsoft.VisualStudio.TestTools.UITest.Playback.ScreenElement.FindAllScreenElement(String queryId, Int32 depth, Boolean singleQueryId, Boolean throwException)
Microsoft.VisualStudio.TestTools.UITest.Playback.ScreenElement.FindScreenElement(String queryId, Int32 depth)
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindFirstDescendant(String queryId, Int32 maxDepth, Int32& timeLeft)
Microsoft.VisualStudio.TestTools.UITesting.Playback.MapControlNotFoundException(COMException ex, IPlaybackContext context)
Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowComException(COMException innerException, IPlaybackContext context)
Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowException(SystemException exception, IPlaybackContext context)
Microsoft.VisualStudio.TestTools.UITesting.Playback.MapAndThrowException(SystemException exception, String queryId)
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindFirstDescendant(String queryId, Int32 maxDepth, Int32& timeLeft)
Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.GetUITestControlRecursive(Boolean useCache, Boolean alwaysSearch, ISearchArgument searchArg, IList`1 windowTitles, Int32& timeLeft)
Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.GetElement(Boolean useCache, ISearchArgument searchArg)
Microsoft.VisualStudio.TestTools.UITesting.SearchHelper.Search(ISearchArgument searchArg)
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindInternal()
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.FindControlIfNecessary()
Microsoft.VisualStudio.TestTools.UITesting.UITestControl.MouseHover(Point relativeCoordinates, Int32 millisecondsDuration, Int32 speed)
Microsoft.VisualStudio.TestTools.UITesting.Mouse.MoveImplementation(UITestControl control, Point relativeCoordinate)
Microsoft.VisualStudio.TestTools.UITesting.Mouse.MoveImplementationWrapper(UITestControl control, Point relativeCoordinate)
Microsoft.VisualStudio.TestTools.UITesting.Mouse.Move(UITestControl control, Point relativeCoordinate)
...

Dennis