Expected Conditions in Protractor

Expected conditions in protractor

Once feat(expectedConditions) is in (probably protractor 1.7), you can do:

var EC = protractor.ExpectedConditions;
var e = element(by.id('xyz'));
browser.wait(EC.presenceOf(e), 10000);
expect(e.isPresent()).toBeTruthy();

Please note though, if you're working with an Angular app and your test requires these conditional waits, it's a big red flag for what you're doing, as protractor should handle waits natively.

Protractor: ExpectedConditions.elementToBeClickable of Undefined

The main problem with imports.

You should import the ExpectedConditions from protractor module like this:

import { ExpectedConditions as EC } from 'protractor';

usage:

await browser.wait(EC.elementToBeClickable(element(by.css('kw'))), 5000);

How exactly do Protractor's ExpectedConditions work (related to behaviour on a non-angular site)?

My guess would be that this bit doesn't work well within protractor's capabilities?:
EC.and(isPresent, isVisible, isClickable);

I'd try something like this instead:

let isPresent = await EC.presenceOf(btnToggleDeactivateQuestionnaire);
let isClickable = await EC.elementToBeClickable(btnToggleDeactivateQuestionnaire);
await btnToggleDeactivateQuestionnaire.click();

Since I don't think you need visibilityOf followed by elementToBeClickable, waiting for its clickability should work fine.

I learned that a web application is not always perfectly made so when you are automating tests, finding the correct element to wait on, is the most challenging part.

How to manually use a protractor ExpectedCondition?

visibilityOf and all other ExpectedConditions return functions. You can call this function, and you will get Promise<boolean> . Basically all ExpectedConditions are predicates - functions, that when called return promise resolved to boolean (should be no exceptions thrown). So basically you can try to use something like this:

let shouldBeVisible = protractor.ExpectedConditions.visibilityOf
expect(
shouldBeVisible($('div.button'))() // Notice () - this where we are manually calling predicate function to get boolean result
).toBeTruthy('Element div.button should be visible');

But lucky you - if you are using JasmineJS - you can try my lib to assert visibility of elements:
https://github.com/Xotabu4/jasmine-protractor-matchers

So you will get not just checking element visibility, but matcher will automatically wait for a while to element to become visible. Check this:

expect($('div.button')).toAppear()

More examples in README.MD

ExpectedConditions is throwing error in Protractor

Have you tried changing the locator definition from function to a variable?

Also you don't have to use await twice in the expected conditions line.

Try the following:

Page Object

// You should specify the index if using .all (with .get(index); at the end)
this.optyList = element.all(by.xpath("//a/ancestor::th[@scope='row']"));

Spec (Here you could try with visibilityOf or presenceOf)

this.Then(/^Select Any Opty and click on New button$/,async ()=>{
await cmBrowser.wait(EC.presenceOf(loginPO.optyList),20000);
// or:
await cmBrowser.wait(EC.visibilityOf(loginPO.optyList),20000);
});

In what circumstances would I need to use Protractor ExpectedConditions to wait for an element

From my experience working with Protractor, the use of ExpectedConditions depends on the behavior of the page you are automating. It's mostly used due to failing if the condition doesn't comply in the specified time.

These conditions will also return a promise that you can handle to your liking.

I'll give you a few scenarios so you can understand where to use them.

  1. alertIsPresent(): This condition will wait till an alert appears.

e.g.: After clicking a button, there will be an alert appearance; however, there's an API call which makes the pop-up take longer and also a small animation, so we want to wait a few seconds and no more than that.

// will click on a button  
element(by.id('button')).click();
// will wait for the condition
let EC = ExpectedConditions;
browser.wait(EC.alertIsPresent(), 5000);

The following code will wait for 5 seconds after clicking the button, to see if the alert is present, else it will throw an error.


  1. invisibilityOf(): This condition will wait till the specified element is not being displayed.

e.g.: There's a loader that appears for every single action that is triggered in the page. For this we want to wait till this loader disappears so we can continue with the automation process. By business requirements, this loader shouldn't take longer than 10 seconds.

This loader locks the whole page, so other elements are not interactable while it is up.

// trigger random action on page so loader appears  
element(by.id('button2')).click();
// will wait for the condition
let EC = ExpectedConditions;
browser.wait(EC.invisibilityOf(element(by.id('loader'))), 10000);

After clicking a button, we will give a 10 seconds grace for the loader to disappear, else the condition will throw an error.


  1. elementToBeClickable(): This condition will wait till the specified element can be clicked.

e.g.: The button to the login form is disabled by default, so it can't be clicked unless we complete the username and password textfields. The button being enabled after filling the textfields has a fast animation, either way we want to give it 1 second to complete and check if we are able to click it.

// complete both textfields required for the button to be enabled  
element(by.id('username')).sendKeys('User1234');
element(by.id('password')).sendKeys('Protractor');
// will wait for the condition and then will click the button
let EC = ExpectedConditions;
browser.wait(EC.elementToBeClickable(element(by.id('loginButton'))), 1000);
element(by.id('loginButton')).click();

After completing both textfields, the condition will wait for 1 second for the element to be clickable, if it is, it will procede with the next line and click it. On the other hand, if it doesn't, an error will be thrown.


  1. presenceOf(): In this case, the condition will check if the element is present in the DOM (Document Object Model) but it won't check if the element is visible or not.

e.g.: On a page with a radio button group containing 3 flavors: chocolate, vanilla and strawberry. Depending on which you choose, you will be shown different questions. Developers mentioned that the questions are in the page at all moments, but are hidden due to which radio button is selected at the moment. In this situation, we just want to check that all questions exist in the DOM, whether or not they will be shown by a radio button being selected.

// check all questions directly, without selecting any radio buttons  
let EC = ExpectedConditions;
browser.wait(EC.presenceOf(element(by.id('question-1'))), 1000);
browser.wait(EC.presenceOf(element(by.id('question-2'))), 1000);
browser.wait(EC.presenceOf(element(by.id('question-3'))), 1000);

The time is pretty irrelevant here; nonetheless, using this conditions we will be able to check that the questions, even though hidden, exist in the DOM. If one is missing, an error will cut the test immediately.


These were a few examples I've had to deal with in the past. The use of the conditions is situational and mostly they are useful when you want to use the existing conditions since they save you the time of building them yourself.

PD: More information can be found in the Protractor API.

protractor: custom ExpectedConditions - on attribute change

Please try again with below changes:

this.attributeToHave = async (elementFinder, attrName, attrVal) => {
const EC = protractor.ExpectedConditions;
const hasAttr = async () => {
const actualText = await elementFinder.getAttribute(attrName); // should add await
return actualText.indexOf(attrVal) !== -1;
};

return await EC.and(EC.presenceOf(elementFinder), await hasAttr()); // should call `hasAttr()` this function.
};


Related Topics



Leave a reply



Submit