How to wait for DOM to load in protractor tests - angularjs

I am hitting the url in browser by "browser.get(url)" and then I am expecting something to be present on the screen. But My test cases are failing because it is taking some time to load the page and test cases are executed before the page loads. So is there a way where I can wait for DOM to load and then the rest of the test cases are executed. I do not want to put sleep as the time to load the page is not consistent and it is unnecessary delay in executing the tests.
I am looking for some solution where we can wait for DOM to load and then we go to next tests to execute.

I solved this by waiting for some specific element to be present on the screen and then perform next activity: here is the code, how I am waiting for the element:
browser.wait(function(){
return browser.driver.isElementPresent(by.id(elementId));
},30000);
So, if you have doubt that execution can happen before the element is present on the screen, then just wait for some element to be present on the screen and then perform next activity.
Hope this will help other, who will face same kind of issues.

You can put a timeout for the script in your config
jasmineNodeOpts: {defaultTimeoutInterval: 70000}
This will wait AT MAX for specified time.

Related

Cypress, retrying against element thats no longer attached to the DOM

I'm currently using cypress to test that a 'pill' element is added on the frontend when the data gets to a particular state.
I identify the row being targeted using cy.contains()
I then chain it with parents('tr').contains('<string>') to identify that the pill I want is being added
The only problem is because the cleanup logic that happens prior to the test triggers a third party webhook that my app responds to, sometimes the row I'm targeting gets removed (after its been found using the first cy.contains() command) and then re-added to the DOM before it reaches its final state.
I believe this is then what causes the second part to fail - cypress appears not to have realised its been detached from the DOM and times out expecting to find my <string> on the detached node.
The full chain looks something like this
cy.get('table')
.find('tr') // Get all the rows
.contains('stringToIdentifyMyTableRow') // Get the text in the specific row I care about
.parents('tr') // broaden scope to whole row
.contains('pillString') // Find text I'm looking for
It seems like its found everything after the .parents('tr') command so its not bothering to retry, even when they are actually detached from the DOM - rather its continuing to look for the pillString in the detached node. What I'd like it to happen is for cypress to continually retry the whole chain until the application reaches its intended state.
Try updating to the latest version 12. It has a new feature that retries when elements are detached from the DOM docs.cypress.io/guides/references/changelog#12-0-0
Maybe try eliminating the .parents('tr') step
cy.get('table')
.contains('tr', 'stringToIdentifyMyTableRow')
.contains('pillString') // should be pill cell
It's easy to get detached errors with React because of the frequent re-render of components.
Your test has no action to cause a re-render, if the webhook is doing it then you need a way to start the test after the webhook has run.

Why explicit wait is waiting for entire wait time even though element is visible/clickable before the wait time is over

I have given a wait time for 60 sec, and i am using wait until element to be clickable/visible but script is waiting for whole 30 secs even though the element is visible on UI and also clickable?
I tried using latest selenium version, tried using different waits also using different locators. but it did not work
The reasons could be in:
The element belongs to iframe so you need to switch to the iframe prior to attempting locating anything inside it
The element belongs to Shadow DOM so you need to locate ShadowRoot object, cast it to the WebElement and find the sub-element you want to click
Your locator is not correct, try getting the page source and saving it to a file. Once done use your favourite browser developer tools to locate the elemen
The syntax of your Explicit Wait is not correct. Check out Explicit Waits and How to use Selenium to test web applications using AJAX technology for code examples
Going forward consider adding page source and your code to your question as the chance you will get the comprehensive answer will be much higher, otherwise we have to go for "blind shots"

Is there a way to refresh the page as many times as possible and wait for an element to load in that page in selenium?

I need to check if an element is appearing after refreshing a page continuously, cause it takes a while for the changes to be reflected and the element to appear in that page.
Is there any built in method in selenium using Ruby as the programming language ?
Just to confirm, it sounds like the page does not dynamically update once the content is available, so you have to wait until that is true, and then manual refresh, right?
I don't know of anything built into selenium to handle this. It feels like it might even be a symptom of a UI that needs a little more design work (pardon my critique). If the user is experiencing the same thing as the test -- kicking off an action, waiting some unspecified period of time, and then manually refreshing to see the results -- that's a kind of lousy user experience. If that's a bad assumption, and there IS feedback (e.g. a spinner), then your best option will be to conditionally wait for the spinner to appear and then disappear, and then refresh a single time.
If there's really no visible feedback, then you still have a couple of options:
Easy: Hardcode a sleep that's longer than the operation will ever take to complete, and refresh once.
Medium: In a loop, sleep for a constant delay, refresh, repeat until some timeout.
Hard: If the delay required varies widely (sometimes seconds, sometimes minutes), you might consider an exponential back off solution, that sleeps for increasingly longer delays each iteration, before ultimately timing out. The upside is that you're not frantically refreshing dozens of times, the downside is that your delay might be unnecessarily long, if the content arrives just after the next big delay begins.
You can use wait method for the element to be available.
If you need to refresh the page continuously just make sure to wait after each refresh.

Can the time out issue be the consequence of browser.sleep() and browser.waitForAngular?

In protractor scripts i'm always having problem of time out, even if i put a big time out jasmine interval, allscripttimeout...
And in some places i'm obliged to wait until element are present like in home page until the url is totally loaded.
Can the time out issue be the consequence of
browser.sleep(time_ms);
browser.waitForAngular();
If so, how can i fix this problem ?
Here the problem in details
Thanks,
Yes they could be -- browser.sleep() would only timeout if you had it sleep longer than your Jasmine timeout interval (default is 30 seconds).
browser.waitForAngular() is automatically applied to every webDriver action by Protractor so you shouldn't need to call it. If this time's out then your app is still synchronizing something.
Both of these would result in A Jasmine spec timed out. Resetting the WebDriver Control Flow. following by Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL. if it takes too long.
I'm not positive how you would fix it - you've had a lot of questions about timeouts (for good reason), but at this point I think you need to use browser.ignoreSynchronization = true; and treat your app as non-Angular if you're having this many timeout issues. Something is preventing synchronization from finishing.
There are several helper methods that you can create and execute seamlessly on non-Angular apps by extending Protractor's functions to avoid explicit browser.sleep()'s . For example, the below code pauses test execution until isPresent returns true (or until a failure by exceeding the timeout I specified)
Util.prototype.waitForElementPresent = function (el, time) {
var timeout = time || 0,
return browser.wait(function() {
return el.isPresent();
}, timeout)
};

Extend Store class to always execute a function after load on ExtJS

I am working on a project where we were asked to "patch" (they don't want a lot of time spent on development as they soon will replace the system) a system implemented under ExtJS 4.1.0.
That system is used under a very slow and non-stable network connection. So sometimes the stores don't get the expected data.
First two things that come to my mind as patches are:
1. Every time a store is loaded for the first time, wait 5 seconds and try again. Most times, a page refresh fix the problem of stores not loading.
Somehow, check detect that no data was received after loading a store and, try to get it again.
This patches should be executed only once to avoid infinite loops or unnecessary recursivity, given that it's ok that some times, it's ok that stores don't get any data back.
I don't like this kind of solutions but it was requested by the client.
This link should help with your question.
One of the posters suggests adding the below in an overrides.js file which is loaded in between the ExtJs source code and your applications code.
Ext.util.Observable.observe(Ext.data.Connection);
Ext.data.Connection.on('requestexception', function(dataconn, response, options){
if (response.responseText != null) {
window.document.body.innerHTML = response.responseText;
}
});
Using this example, on any error instead of echoing the error in the example you could log the error details for debugging later and try to load again. I would suggest adding some additional logic into this so that it will only retry a certain number of times otherwise it could run indefinitely while the browser window is open and more than likely crash the browser and put additional load on your server.
Obviously the root cause of the issue is not the code itself, rather your slow connection. I'd try to address this issue rather than any other.

Resources