I saw other protractor related post mentioning about how to wait for an element to become visible. However, recently, I ran into an opposite use case. I wanted to wait for an element until it becomes invisible. Since I could not find anything specific about it. I went ahead and came up with a solution.
var ptor = protractor.getInstance();
ptor.wait(function() {
return element(by.css('#my-css-here')).isDisplayed().then(function(isVisible){
console.log('is visible :' + isVisible);
return !isVisible;
});
}, 12000).then(function(){
//do whatever you want
});
hopefully it helps. any suggestion is welcome.
Thanks,
Using the elementexplorer (https://github.com/angular/protractor/blob/master/docs/debugging.md) I looked at the protractor object and found an answer that is working wonderfully for me:
var el = element(by.id('visibleElementId'));
browser.driver.wait(protractor.until.elementIsNotVisible(el));
From #Machtyn
This should be the correct answer:
var EC=protractor.ExpectedConditions; browser.wait(EC.not(EC.presenceOf(el)), someTimeoutInMilli);
Protractor now has invisibilityOf function built in.
var EC = protractor.ExpectedConditions;
// Waits for the element with id 'abc' to be no longer visible on the dom.
browser.wait(EC.invisibilityOf($('#abc')), 5000);
Read more for details
None of the solution working for me. Please take a look at below code:
var protractor = require('protractor');
describe('Testing', function () {
it('Should show the settings button', function () {
var EC = protractor.ExpectedConditions;
var settings = $('.settings');
var isSettingVisible = EC.visibilityOf(settings);
browser.get('http://localhost:8080/#/edomonitor');
console.log("--------------------welcome 1-------------------");
protractor.browser.wait(isSettingVisible, 10000, "Searching for settings").then(() => {
console.log("waiting complete");
}, (error) => {
console.log(error);
})
expect(2).toEqual(2);
});
});
Related
I'm a newbie in protractor.
I've written a test with Selenium in Java and everything is OK.
But now, i need to do the same test in protractor and it driving me crazy!
I've to check the numbre of element by tagName in my page.
My code is something like this :
// Click on a button
element(by.id('e2e-idAutomate')).click();
// Wait for the next page to be present
var isPresent0 = EC.visibilityOf(element(by.tagName('ngx-carousel')));
var isPresent1 = EC.visibilityOf(element(by.tagName('cmyardneo-action-button')));
var condition = EC.and(isPresent0, isPresent1);
browser.wait(condition, 5000);
// Ok, here i want to chek the number of div by tagName
// First try!
expect<any>(element.all(by.tagName("div"))).toContain(40);
// Doesn't work... Fall in timeout!
// Second try
element.all(by.tagName("div")).then((liste) => { //Same Problem, fall in timeout
expect<any>(liste.length).toBe(40);
});
How can i read the liste return by the element.all?
Thanks!
For time our issue, please refer to http://www.protractortest.org/#/timeouts
One issue in your code:
// First try!
expect(element.all(by.tagName("div")).count()).toBe(40);
// element.all().count() is to get count of found elements
Ok,
After another tests, my problem is not about element.all
but about page change....
What i want to do is :
Open a first page
Click on a button that make à routing to a
second page
check this second page
I ve done something like that :
describe('test of application', function () {
beforeAll( () => {
TR.closeTabs();
browser.driver.manage().window().maximize();
browser.get('/ardoise');
browser.waitForAngularEnabled();
browser.wait(EC.visibilityOf(element(by.id("e2e-idAutomate"))),5000);
});
it('Click on the button', () => { // I will go on the second page
element(by.id('e2e-idAutomate')).click();
});
it('Check the second page', () => {
// brower.sleep(5000);
var isPresent0 = EC.visibilityOf(element(by.tagName('ngx-carousel')));
var isPresent1 = EC.visibilityOf(element(by.tagName('cmyardneo-action-button')));
var condition = EC.and(isPresent0, isPresent1);
// Here i want to be sure the second page is loaded
browser.wait(condition, 5000);
// Next check....
});
});
And the last condition is never OK (I've checked, the two tagName are OK!!!)
It sounds like protractor hasnot seen that a routing occurs...
I have code like this:
element(by.model("roleSelection.role")).element(by.cssContainingText('option', newRole)).click();//.then(function() {console.log('role click')})//;
where the options is loaded via a call to the server.
I can wait for the first element by doing this
browser.wait(function() {
return browser.isElementPresent(by.model("roleSelection.role")).then(function(present){
return present;
});}, 8000);
and it seems to work. But how can I wait until the "sub-element" is clickable.
I have tried this
browser.wait(function() {
return browser.isElementPresent(by.model("roleSelection.role")).then(function(present){
if (present) {
var elm = element(by.model("roleSelection.role"));
return elm.isElementPresent(by.cssContainingText('option', newRole)).then(function(subpresent) {
return subpresent;
});
}
}); }, 8000);
Have you tried clickable? Something along these lines
var EC = protractor.ExpectedConditions;
var select = element(by.model("roleSelection.role"))
var isClickable = EC.elementToBeClickable(select);
browser.wait(isClickable,5000); //now options should have been loaded by now
Well, try to this: https://angular.github.io/protractor/#/api?view=ExpectedConditions.prototype.elementToBeClickable
But, Please keep in mind, Protractor is suitable for angular webpages and interactions, and animations. For example ng-animate. So, it is not sure to working for example jquery, or other animates.
In this way:
onPrepare: function () {
// disable animations when testing to speed things up
var disableNgAnimate = function () {
angular.module('disableNgAnimate', []).run(function ($animate) {
$animate.enabled(false);
});
};
browser.addMockModule('disableNgAnimate', disableNgAnimate);
}
Or you can switch in script way in browser.executeScript().
Please see this link. It works only jquery animations.
If you not have animate problems. Use setTimeout() JS function.
In Steps definition, i declare 'chai' and use to debug:
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
chai.usexpece(chaiAsPromised);
var expect = chai.expect;
module.exports = function() {
this.Given(/^I go on "([^"]*)"$/, function (arg1, callback) {
browser.driver.get(arg1);
browser.manage().timeouts().pageLoadTimeout(10000);
var answer = 43;
expect(answer).to.equal(42);
console.log("this text will be displayed");
callback();
});
}
When i run the script, text this text will be displayed does not appear ,in console but when i comment this line //expect(answer).to.equal(42);, the text appear as normal.
I know there is a wrong in expect of chai object but cannot find out the solution. Anyone can help me to resolve the issue. Thank so much
cucumber-js supports steps that return promises.
When using chai-as-promised, i need to return the expectation (which is a promise)
this.When(/^I test async code$/,function() {
return expect(true).to.be.true;
});
I am new to Protractor (and Javascript by the way), and I am writing some tests to practice. My goal so far is to check that when I click on the home button of a website, the redirection leads me correctly to the expected address.
I have written this:
var HomeTopBanner = function() {
this.homeUrl = browser.params.homePageObject.homeUrl;
this.topBanner = element(by.css('.navbar-inner'));
this.homeButton = this.topBanner.element(by.css('.icon-home'));
}
describe('Home button', function(){
var homeTopBanner = new HomeTopBanner();
var newUrl = '';
it('clicks on the Home button', function(){
homeTopBanner.homeButton.click();
browser.getCurrentUrl().then(function storeNewUrl(url) {
newUrl = url;
});
})
it('checks that the home button leads to the homepage', function(){
expect(newUrl).toEqual(homeTopBanner.homeUrl);
})
});
This works, but my question is:
Why do I need to separate the "GetCurrentUrl" and the "expect(newUrl)" parts? I would prefer to have both of them in the same spec, but if I do that, during the comparison of the expect, newUrl=''
I assume this is related to browser.getCurrentUrl() being a promise, but is there a better way to do it?
Yes, getCurrentUrl returns a promise with the url in the form of a string as explained in the protractor api docs. You have to wait until the url is returned in order to use it. Now in order to combine both the specs you can write your expect statement inside the function that getCurrentUrl returns as shown below and there is no need of using a newUrl variable too if you want -
it('clicks on the Home button', function(){
homeTopBanner.homeButton.click();
browser.getCurrentUrl().then(function(url) {
expect(url).toEqual(homeTopBanner.homeUrl);
});
})
There could also be another issue when after the click action the previous url is being captured due to the fact that protractor is async and fast. In that case you can write your getCurrentUrl() function inside the promise that click() function returns. Here's an example of it -
it('clicks on the Home button', function(){
homeTopBanner.homeButton.click().then(function(){
browser.getCurrentUrl().then(function(url) {
expect(url).toEqual(homeTopBanner.homeUrl);
});
});
})
Hope this helps.
I've been checking others threads about this common error and trying to apply what they recommend but still getting same error. I warn you I'm totally newbie at PROTRACTOR.
This it's the first test I'm writting:
describe('Just some shitty test', function(){
'use strict';
it('Testing some shitty test', function(){
beforeEach(function () {
browser.get(browser.baseUrl);
});
/*
Purpose:
1. Getting in "HEALTH CARE PARTNER / ORGANISATION (KND. NR.: 438)" panel
2. Edit content
3. Save it
*/
// First, I find elements I want to test
//ANCHOR Bearbeiten
var $a = $('a','div.m-pane__control');
//INPUT Name
var $name = $('input[placeholder="Name"]');
//SELECT
var $select = $('select','m-form__select ng-scope');
//INPUT Yearly births
var $yearly = $('input[placeholder="Yearly births"]');
//INPUT Homepage
var $homepage = $('input[placeholder="Homepage"]');
//INPUT Email
var $email = $('input[placeholder="Email"]');
//TEXTAREA. two ways to find it
var $textarea1 = $('textarea[ng-model="model[field.name]"]');
var $textarea2 = element(by.model('model[field.name]'));
//BUTTON Speichern
var $speichern = $('button[ng-click="savebtn()"]');
// Sequence of actions
//Is bearbeiten button displayed?
//expect($a.isDisplayed()).toBe(true);
//Click on it!
//$a.click();
//Settings
//$name.sendKeys('John Smith').submit();
//$yearly.sendKeys('42');
//$homepage.sendKeys('something');
//$email.sendKeys('tschues#baba.at');
//$textarea1.sendKeys('fahren lassen');
//Save
//$speichern.click(); });});
I don't know if elements I've searched are ok but every time I call getText() function or either as click(), sendKeys or whatever, I always get Error while waiting for Protractor to sync with the page: {}.
What I'm forgetting or doing wrong?
Thank you
Try something like this
describe('Just some test', function(){
var ptor;
beforeEach(function () {
browser.get(browser.baseUrl);
ptor = protractor.getInstance();
ptor.waitForAngular();
});
it('should do something', function(){
var aLink = element(by.css('div.m-pane__control'));
aLink.click();
});
});
Biggest differences are I ask protractor to wait for angular, since it takes some time to get ready and I used the protractor style of finding elements on the page.