Forum Discussion

vibin's avatar
vibin
New Contributor
4 years ago
Solved

Wait for Xpath

Hi,

I am using test complete for web testing and preferred XPATH to find elements. But I couldnt find a proper wait statement for xpath other than hard coded wait statements. My scripts are failing due to this and sometimes the inbuilt methods like click(), exists etc are also getting failed. Please find a sample script below. The language used is Python

 

def waitelement_click():  
page = Sys.Browser("chrome").Page("xyz.com")
viewcombtn = page.FindChildByXPath("//span[text()='View Comments']")
select_lst = page.FindChildByXPath("//span[@class='selected']")
selrange = page.FindChildByXPath("//span[text()='Year to Date']")
firstissue = page.FindChildByXPath("//div[@class='mdc-layout-grid action-bar list-bar ng-star-inserted'][1]//span[@class='blue']")
creator = page.FindChildByXPath("//div[@class='mdc-layout-grid action-bar list-bar ng-star-inserted'][1]//span[5]")
addcmtbtn = page.FindChildByXPath("//span[@class='val add-comment ng-star-inserted']")# popup = pop_parent.WaitChild('''Panel("cdk_overlay_55")''',5000)
viewcombbtn.Click()
select_lst.Click()
selrange.Click()
Log.Message(creator.contentText)
firstissue.Click()
addcmtbtn.Click()

 The failures are mainly in between clicking different buttons.. Please give me a solution. 

  • vibin :

    Hi,

     

    I expect a true or false in the variable val

    Your expectation is partially correct.

    Please carefully read for details the documentation for the FindChildByXPath method.

     

    The case is that been a wrapper around native (I guess) XPath search, this method differs from all other FindXXX and WaitXXX methods provided by TestComplete.

    All other methods return found object if succeeded and empty stub one in case of failure. Returned stub object contains the only property Exists and verification like in your code is correct for these cases.

    But FindChildByXPath behaves like this:

    -- If the search fails then null is returned. Note, null, but not a stub object. Thus you must check for null, but not for .Exists;

    - If the search succeeds, then TestComplete tries to match found web element to the object in its Objects Tree.

      -- If the match succeeds, then TestComplete returns its object that is a wrapper over the native web element and contains all additional methods and properties provided by TestComplete. .Exist is one of such properties so it is correct to use it in test code.

      -- If TestComplete fails to match the found web element to any object in its Objects Tree, then the found native DOM object is returned. This object does not contain any method and property provided by TestComplete and test code can refer only to the native methods and properties of the given DOM object provided by the given browser. (Note that functionally equivalent methods/properties can be named differently in different browsers. .contentText is an example of such a property named differently in different browsers. Another example: val.Click() will work only for the wrapping object provided by TestComplete and will fail for the native DOM object. For the native DOM object val.click() (lower-case 'c') must be used instead.)

     

    This complexity is one of the reasons why search by XPath is not a recommended technique in TestComplete's world and is worth to be used if one needs to search for the object that is absent in regular Objects Tree provided by the Object Browser.

     

    I think that this is the reason of the problem/inconsistency that you are observing.

     

8 Replies

  • AlexKaras's avatar
    AlexKaras
    Champion Level 3

    Hi,

     

    Yes, as Marsha has suggested. .WaitElement() is a new method introduced in TC 14.40 for Cross-platform testing.

    Note that test code created for cross-platform testing cannot use NameMapping/Aliasing, requires license for Device Cloud addon and applicable to page object only (which potentially means decreased performance).

     

    Otherwise, you must implement your own wait mechanism to wait in a loop until the sought-for object appears or timeout occurs.

     

    One more note as for your code.

    The code looks like a port from Selenium code that implements page object model. This code in TestCOmplete will work only in the case if all sought for objects (viewcombtn, select_lst, ...) exist at the moment of search. If the select_lst object appears only after the click on the viewcombtn, then your code will not work because the search for select_lst will fail anyway as the object will not exist until the button is clicked.

     

    • vibin's avatar
      vibin
      New Contributor

      Thanks Alex,

      A question on this part:-

       

      "One more note as for your code.

      The code looks like a port from Selenium code that implements page object model. This code in TestCOmplete will work only in the case if all sought for objects (viewcombtn, select_lst, ...) exist at the moment of search. If the select_lst object appears only after the click on the viewcombtn, then your code will not work because the search for select_lst will fail anyway as the object will not exist until the button is clicked."

       

      As you pointed out viewcombtn is clicked first and all the other elements comes to the page after this click.If am using waitElement() in test complete, will the code executes in that way we expect- with out considering the fact that "in TestCOmplete will work only in the case if all sought for objects (viewcombtn, select_lst, ...) exist at the moment of search"

       

      Thanks in advance

      Vibin

      • AlexKaras's avatar
        AlexKaras
        Champion Level 3

        Hi,

         

        > If am using waitElement() in test complete, will the code executes in that way we expect [...]

        Well... If I got your question right...

        1. TestComplete uses two types of object addressing.

        First type addresses objects directly. E.g.: Sys.browser.Page('aaa'). Translating to human language, this line of code says this: 'Look for the last started browser and for this browser return me the page that refers to the 'aaa' web address. I know that all these objects must exist (or must appear within the timeout specified in the project properties), so give me the page or fail if any of these objects do not exist'.

        Second type uses .WaitXXX methods to address objects. E.g.: Sys.browser.WaitPage('aaa', 1000). Translation to human says this: 'Look for the last started browser and for this browser check if the page that refers to the 'aaa' web address exists or appears within 1sec. If the page exists, return it to me. Return me an empty stub object if the page does not exist and do not fail. I know how to handle this'.

         

        2. TestComplete uses scripting languages for test code. Lines of code in these languages are executed sequentially and synchronously. (The only exception is when a reference to some Aliased object is stored in the global public variable. But this is really bad approach in TestComplete's world.)

         

        3. Your code commented:

        def waitelement_click():  
          page = Sys.Browser("chrome").Page("xyz.com") // Get page that refers to xyz.com address opened in any existing instance of Chrome. Fail if any of them do not exist
          viewcombtn = page.FindChildByXPath("//span[text()='View Comments']") // search for viewcombtn within the page. Return object if found and null otherwise
          select_lst = page.FindChildByXPath("//span[@class='selected']") // search for select_lst within the page. Return object if found and null otherwise
          selrange = page.FindChildByXPath("//span[text()='Year to Date']") // search for selrange within the page. Return object if found and null otherwise
          firstissue = page.FindChildByXPath("//div[@class='mdc-layout-grid action-bar list-bar ng-star-inserted'][1]//span[@class='blue']") // search for firstissue within the page. Return object if found and null otherwise
          creator = page.FindChildByXPath("//div[@class='mdc-layout-grid action-bar list-bar ng-star-inserted'][1]//span[5]") // search for creator within the page. Return object if found and null otherwise
          addcmtbtn = page.FindChildByXPath("//span[@class='val add-comment ng-star-inserted']") // search for addcmtbtn within the page. Return object if found and null otherwise
          viewcombbtn.Click() // if the viewcombbtn variable contains a valid reference to existing object, click this object. Fail otherwise.
          select_lst.Click() // if the select_lst variable contains a valid reference to existing object, click this object. Fail otherwise.
          selrange.Click() // if the selrange variable contains a valid reference to existing object, click this object. Fail otherwise.
          Log.Message(creator.contentText) // if the creator variable contains a valid reference to existing object, log the value of its contentText property (if the latter exists). Fail otherwise.
          firstissue.Click() // if the firstissue variable contains a valid reference to existing object, click this object. Fail otherwise.
          addcmtbtn.Click() // if the addcmtbtn variable contains a valid reference to existing object, click this object. Fail otherwise.

        Note: your code references two different variables: viewcombtn and viewcombbtn (note doubled 'b'). Is this a typo or an error?

         

        Hope the above will help.