I have written a few functions for browser.wait. My problem is when I run my tests, they inconsistently pass due to protractor running too fast. To combat this, I was using browser.sleep. This works, but is not efficient. If I am on a slow connection for example, these browser.sleep statements can become unreliable. So I have started to use browser.wait. Here is an example of a wait function that I use.
EC = Expected Conditions;
myForm = element(by.id('myForm');
button1 = element(by.id('btn1');
waitForBtn = this.EC.elementToBeClickable(button1)
formIsVisible = this.EC.visibilityOf(myForm)
//Test
it(should click the button and bring up the form), () => {
browser.wait(page.waitForBtn, 3000);
page.button1.click()
browser.wait(page.formIsVisible, 3000);
expect(page.getMyForm().isDisplayed).toBeTruthy();
This test would work in isoluation, but when combinded with other tests, sometimes a test will fail and return an error"element" is not clickable at point...
. Even with these wait functions, I will receive this error. It always seems to be for when an element is being clicked.
My question is this: When running multiple tests, what is the best way for protractor to wait so that protractor does not execute the test too fast and miss the element? Thank you. EDIT: Here is the solution.
Helper function for clicking elements.
async function sendClick(el: ElementFinder): Promise<void> {
try {
let result = await forCondition(function() { return el.isDisplayed() });
if(!result || !await el.isEnabled()) {
throw new Error('element disabled');
}
await browser.executeScript('arguments[0].click();', el.getWebElement());
} catch(error) {
console.warn('element:', el.locator().toString(), 'is not clickable', error.message);
}
}
export async function forCondition(condition: () => any | PromiseLike<boolean>, timeout = 20000): Promise<boolean> {
try {
return await browser.wait(condition, timeout);
} catch (err) {
console.log('Condition: false');
return false;
}
}