I have a search field, when the user hits enter it has a table with a bunch of checkboxes. I need to wait for the results to load and then click the checkbox on the first row of the table.
This is separated into 2 test cases, the first executes the search, the 2nd clicks the checkbox in the first row of the results that does something else.
// Test #2
it('should perform the Search', () => {
po.searchAutocomplete.sendKeys('\n');
});
// Test #3
it('3 : should Activate and Inactivate a Program', () => {
const r = browser.driver.findElements(by.tagName('p-checkbox'));
browser.driver.wait(EC.presenceOf(r[0]));
r[0].click();
browser.sleep(2000).then(() => {
});
r[0].click();
});
// Test #4
it('4 : should navigate to Create New', () => {
po.createNewButton.click();
});
So, there are sync problems here - my Test #2 runs successfully but then Test #3 starts running here immediately. If the search results are too slow then I get an error that the checkbox does not exist, if it returns in time it's fine. Also, sometimes the 2nd click() results in object not attached to current page because the "Create New" in Test #4 navigates to another page.
It looks like the r[0].clicks's promise is returning after the page navigates to another view with the po.createNewButton.click() causing the object not attached to current page error.
I need all these operations synchronously. I put in a browser.wait but that does not work, it's just ignored.
How can I fix this?
Edit - thanks for the suggestions below. Here is what I changed and got it working :)
In my app had a clock timer using Observable.interval in my header, in addition I had a timer that was pinging the server to get some data at a fixed interval. Since these are always running and will never complete it was causing all sorts of timeouts in Protractor with the element.all syntax which is why I switched to browser.driver.findElement syntax but due to the async nature of it (as identified by the poster below - thank you!) makes it difficult to code.
I wrapped the timers in the following code:
this.ngZone.runOutsideAngular(() => { // Required to prevent interference with Protractor
this.updateTimer = Observable.interval(UPDATE_INTERVAL).publish();
this.updateTimer.subscribe(v => {
this.doSomething();
});
});
Now, I am able to use the element.all without it timing out!