Ask a Question

setInterval is not defined: Suggestion for best wait method during page loads

SOLVED
nish_b
Contributor

setInterval is not defined: Suggestion for best wait method during page loads

Hi,

 

ISSUE:  ReferenceError: setInterval is not defined

 

DESCRIPTION: I am trying to write a pure JavaScript function for the webpage to fully load before proceeding with my test script. I am using setInterval() to poll until the DOM Load event is fired

 

BACKGROUND: I have already used page.Wait(); for waiting during page load. But still the webelements are not found after the wait. I also have tried a polling function to check whether the element exists.

 

CODE SNIPPETS:

1) Pure JavaScript function for DOM:

      let webpage = Sys.Browser().Page(this.openBrowserWindowURL()).contentDocument; //Get current webpage document

waitForDOMToLoadFullyLoad(webpage){
//The basic check 
if(webpage.readyState === 'complete') {
  // Polling further until load event fires - which means all icons are fully loaded
  let pageisloaded=0;
  let interval = setInterval(function() {
     window.addEventListener('load', (event) => {
     pageisloaded=1;
    })
   if(pageisloaded) {
      Log.Message("DOM Load event is completed!");
      clearInterval(interval);
    }
  }, 100);
}

    }

 

2) POLLING FUNCTION:

isElementPresent(webElement,timeout,pollingTime,frequency) {
let flag=false;
aqUtils.Delay(timeout);
for(let i=0;i<frequency;i++){
  if(webElement.Exists){
    Log.Message("Element exists");
    flag=true;
    break;
  }
 else {
    Log.Message("Waiting for element at iteration: "+i);
    webElement.WaitItem(index,pollingTime);
    }
  }
 return flag;

}


QUESTIONS: 

1. Please suggest which is better option? Code Snippet 1 or 2? Code Snippet 2 is not giving satisfying results. It works sometimes, sometimes it doesn't work.

2. Why am I getting error: setInterval is not defined. Is it not supported in TestComplete?

11 REPLIES 11
AlexKaras
Community Hero

Hi,

 

function for the webpage to fully load

Definition of the fully loaded page depends on how the given tested page is implemented.

The generic process is like this:

-- Browser sends request for the page to the server and waits for the response;

-- When the response is fully received, browser starts to render it. This is the moment that page.Wait waits for;

-- Page may contain script functions that modify DOM structure. These might be jQuery, Angular, regular script function or something else. jQuery and Angular provide internal ways to determine if they finished their current activities or not. This can be used to delay test execution until jQuery and/or Angular finish their current activities. Regular script functions are not predictable. They can provide some heavy processing that takes a lot of time without any indication whether or not the processing has completed;

-- Finally, page may contain some Ajax calls that are executed asynchronously. Depending on their nature, these calls may get data and change page DOM structure in a way that you are interested in. In this case your code must postpone until the required web element appears on the page. Otherwise, such calls may be ignored and test code may proceed.

 

So, your approach to wait for the page load may depend on the page design and implementation.

 

As for the setInterval() / clearInterval() functions - what these functions are provided by? They are not built-in TestComplete functions. If JavaScript provides these functions, then they should be accessible from JavaScript-based test project. If this is something provided by DOM/jQuery/etc. then these functions must be called from within page context. Check https://support.smartbear.com/articles/testcomplete/embedding-scripts-into-web-pages/ and "Run JavaScript on Web Pages" TestComplete's help topic for more details on how to call script function from the page context.

 

Your polling function provided in code snippet #2:

It will not work as you probably expect it to function. The reason is that this function checks if the object provided as a parameter exists. If the object does not exist, then the code waits in a loop until object's .Exists property becomes True. This will never happen. If the object did not exist when it was obtained, then this means that TestComplete's stub object was returned. And even if/when the sought for object appears, this will in no way be reflected on the stub object. The approach in this case must be not to wait for .Exists to become true, but search in a loop for the object (via .FindXXX() ) and check its .Exists property.

 

Regards,
  /Alex [Community Hero]
____
[Community Heroes] are not employed by SmartBear Software but
are just volunteers who have some experience with the tools by SmartBear Software
and a desire to help others. Posts made by [Community Heroes]
may differ from the official policies of SmartBear Software and should be treated
as the own private opinion of their authors and under no circumstances as an
official answer from SmartBear Software.
The [Community Hero] signature is used with permission by SmartBear Software.
https://community.smartbear.com/t5/custom/page/page-id/hall-of-fame
================================

Hi Alex,

 

Thank you for your response! I will work on the suggestions provided and let you know the update! 🙂 

Hi Alex,

 

I tried your suggestion for 2. i modified the function to loop and keep searching for webelement and then check Exists property. But at 2nd iteration (when i =1)  , when it tries to find the webelement again, it is throwing "Unspecified Error". Could you help here?

 

Below is the rewritten function:

 

isElementPresent(webpage,xpath,timeout,pollingTime,frequency) {
let flag=false;
let webObj;
Log.Message("Timeout starting");
aqUtils.Delay(timeout);
Log.Message("Timeout stopped");
for(let i=0;i<frequency;i++){
webObj=webpage.FindChildByXPath(xpath);
Log.Message("webobj is: "+webObj);
if(webObj!==null){
Log.Message("webObj is not null, checking its existence");
if(webObj.Exists===true){
Log.Message("Element exists at iteration: "+i);
flag=true;
break;
}
else
{
Log.Message("Waiting for element at iteration: "+i);
aqUtils.Delay(pollingTime);
}
}
else {
Log.Message("WebObj is null/Undefined. Waiting for element at iteration: "+i);
aqUtils.Delay(pollingTime);
}
}
return flag;
}

Thanks for the suggestion, Alex. I could build on it and create the wait function which polls regularly.

 

I was able to resolve the issue I mentioned in previous post by myself - by changing this: Instead of getting webpage reference from the argument list of the calling function only 1 time , I am currently taking the current webpage dynamically at every iteration and it works fine!

Hi,

 

Good to hear that the problem has been solved.

 

One note as for the rewritten function:

As it is described in the documentation, when the search for the object is done via XPath:

-- null is returned if the object was not found;

-- If the object was found, then TestComplete tries to match the found native DOM object to the object from the Object Tree. If the match is found, then TestComplete returns wrapper object that contains all properties and methods added by TestComplete. If the match is not found then native DOM object is returned as a result of the search. (Obviously, this object contains only properties and methods provided by DOM and properties and methods provided by TestComplete cannot be used.)

Considering the above, if you search by XPath you must consider the fact that native DOM object may be obtained as a result of the search.

Thus, your code should be improved like this:

 

if(webObj!==null){
  Log.Message("webObj is not null, checking its existence");
  if (aqObject.IsSupported(webObj, "Exists") // TestComplete wrapping object was returned. Safe to use .Exists and everything else provided by TestComplete
    if(webObj.Exists===true){
      Log.Message("Element exists at iteration: "+i);
      flag=true;
      break;
    }
  else // native DOM object was returned. .Exists cannot be used but only native DOM methods/properties
...

 

 

Regards,
  /Alex [Community Hero]
____
[Community Heroes] are not employed by SmartBear Software but
are just volunteers who have some experience with the tools by SmartBear Software
and a desire to help others. Posts made by [Community Heroes]
may differ from the official policies of SmartBear Software and should be treated
as the own private opinion of their authors and under no circumstances as an
official answer from SmartBear Software.
The [Community Hero] signature is used with permission by SmartBear Software.
https://community.smartbear.com/t5/custom/page/page-id/hall-of-fame
================================

Thanks for your response, Alex. The problem "Unspecified Error" re-occurred when I ran the scripts on Jenkins. 😞  I will try out your new suggestion on the improvement. Hoping it would solve the issue permanently. 

Hi,

 

Can you provide actual code, what line throws the "Unspecified Error" (can be obtained from the message in the log or by double-clicking on the error message in the log) and the content of the Details log pane ?

 

Regards,
  /Alex [Community Hero]
____
[Community Heroes] are not employed by SmartBear Software but
are just volunteers who have some experience with the tools by SmartBear Software
and a desire to help others. Posts made by [Community Heroes]
may differ from the official policies of SmartBear Software and should be treated
as the own private opinion of their authors and under no circumstances as an
official answer from SmartBear Software.
The [Community Hero] signature is used with permission by SmartBear Software.
https://community.smartbear.com/t5/custom/page/page-id/hall-of-fame
================================

Hi Alex,

 

I added the improvement as suggested. Thanks!

 

Below is the answer to your question:

 

When executed in Jenkins, it is failing at the below line during 2nd iteration (Basically when it tries to find the element again). 

for(let i=0;i<frequency;i++)
{
  Log.Message("Searching for webelement");
  webObj=this.getOpenBrowserPage().FindChildByXPath(xpath); //Failing here at the iteration - 1

....

 

Hi,

 

.FindChildByXPath() should work. I expect the problem is within the getOpenBrowserPage() method. Can you provide it?

What happens between two subsequent calls to getOpenBrowserPage()? If the page or its content changes somehow then test code must wait at least until the page is reloaded (via <page>.Wait() method) and only then proceed.

 

Regards,
  /Alex [Community Hero]
____
[Community Heroes] are not employed by SmartBear Software but
are just volunteers who have some experience with the tools by SmartBear Software
and a desire to help others. Posts made by [Community Heroes]
may differ from the official policies of SmartBear Software and should be treated
as the own private opinion of their authors and under no circumstances as an
official answer from SmartBear Software.
The [Community Hero] signature is used with permission by SmartBear Software.
https://community.smartbear.com/t5/custom/page/page-id/hall-of-fame
================================
cancel
Showing results for 
Search instead for 
Did you mean: