How to verify number of tagName with protractor - protractor

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...

Related

How to wait the page to test is loaded in non angular site?

I've tried this:
browser.wait(function () {
return browser.executeScript('return document.readyState==="complete" &&' +
' jQuery !== undefined && jQuery.active==0;').then(function (text) {
return text === true;
});
}, 30000);
If jQuery.active==0 then page is completely loaded. This should work for sites with JQuery and non angular pages.
However, I have many problems of instability to test for non angular sites.
How to fix this?
By default protractor waits until the page is loaded completely. If you are facing any error then it is because protractor is waiting for the default time to be completed, that you have specified in your conf.js file to wait until page loads. Change the value to wait a for longer time if you think your app is slow -
// How long to wait for a page to load.
getPageTimeout: 10000, //Increase this time to whatever you think is better
You can also increase the defaultTimeoutInterval to make protractor wait a little longer before the test fails -
jasmineNodeOpts: {
// Default time to wait in ms before a test fails.
defaultTimeoutInterval: 30000
},
If you want to wait for any particular element, then you can do so by using wait() function. Probably waiting for last element to load is the best way to test it. Here's how -
var EC = protractor.ExpectedConditions;
var lastElement = element(LOCATOR_OF_LAST_ELEMENT);
browser.wait(EC.visibilityOf(lastElement), 10000).then(function(){ //Alternatively change the visibilityOf to presenceOf to check for the element's presence only
//Perform operation on the last element
});
Hope it helps.
I use ExpectedConditions to wait for, and verify page loads. I walk through it a bit on my site, and example code on GitHub. Here's the gist...
Base Page: (gets extended by all page objects)
// wait for & verify correct page is loaded
this.at = function() {
var that = this;
return browser.wait(function() {
// call the page's pageLoaded method
return that.pageLoaded();
}, 5000);
};
// navigate to a page
this.to = function() {
browser.get(this.url, 5000);
// wait and verify we're on the expected page
return this.at();
};
...
Page Object:
var QsHomePage = function() {
this.url = 'http://qualityshepherd.com';
// pageLoaded uses Expected Conditions `and()`, that allows us to use
// any number of functions to wait for, and test we're on a given page
this.pageLoaded = this.and(
this.hasText($('h1.site-title'), 'Quality Shepherd')
...
};
QsHomePage.prototype = basePage; // extend basePage
module.exports = new QsHomePage();
The page object may contain a url (if direct access is possible), and a pageLoaded property that returns the ExepectedCondition function that we use to prove the page is loaded (and the right page).
Usage:
describe('Quality Shepherd blog', function() {
beforeEach(function() {
// go to page
qsHomePage.to();
});
it('home link should navigate home', function() {
qsHomePage.homeLink.click();
// wait and verify we're on expected page
expect(qsHomePage.at()).toBe(true);
});
});
Calling at() calls the ExpectedCondidion (which can be be an and() or an or(), etc...).
Hope this helps...

How to send Keyboard keys in protractor like TAB

I need to select an element, send values to it, press tab and then send new values.
I can select the element and send values to it but am not being able to send TAB from my keyboard and then send new value.
I used ptor first but then it is being obsoleted, I now am trying to do same by using browser.key but its not working for me.
Please Help !
i wrote a snippet and tested it against google.de (not .com! maybe you have to adjust this) and when sending TAB the next element gets the focus (in this case it's the search button).
the snippet:
describe('Test', function () {
it('should browse to google', function () {
browser.ignoreSynchronization = true;
browser.driver.get('https://www.google.de');
expect(browser.getCurrentUrl()).toEqual('https://www.google.de/');
});
it('should unfocus the search field', function () {
var search = element(by.name('q'));
search.sendKeys(protractor.Key.TAB);
browser.sleep(3000); // 3s to take a look ;)
});
});

Protractor : wait for element to become invisible/hidden

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);
});
});

TERROR MOVIE: Error while waiting for Protractor to sync with the page: {} VOL VIII

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.

How to fire place_changed event for Google places auto-complete on Enter key

The click seems to fire the event and set the cookies but pressing enter to submit doesn't set the cookies and instead the page redirects without the cookies.
function locationAuto() {
$('.search-location').focus(function () {
autocomplete = new google.maps.places.Autocomplete(this);
searchbox = this;
google.maps.event.addListener(autocomplete, 'place_changed', function () {
var thisplace = autocomplete.getPlace();
if (thisplace.geometry.location != null) {
$.cookie.raw = true;
$.cookie('location', searchbox.value, { expires: 1 });
$.cookie('geo', thisplace.geometry.location, { expires: 1 });
}
});
});
The .search-location is a class on multiple textboxes.
There is a submit button that takes the values from the cookies and redirects (server side)
Adapted from Jonathan Caulfield's answer:
$('.search-location').keypress(function(e) {
if (e.which == 13) {
google.maps.event.trigger(autocomplete, 'place_changed');
return false;
}
});
I've encountered this problem as well, and came up with a good solution. In my website I wanted to save the autocomplete.getPlace().formatted_address in a hidden input prior to submission. This worked as expected when clicking the form's submit button, but not when pressing the Enter key on the selection in the autocomplete's dropdown menu. My solution was as follows:
$(document).ready(function() {
// Empty the value on page load
$("#formattedAddress").val("");
// variable to indicate whether or not enter has been pressed on the input
var enterPressedInForm = false;
var input = document.getElementById("inputName");
var options = {
componentRestrictions: {country: 'uk'}
};
autocomplete = new google.maps.places.Autocomplete(input, options);
$("#formName").submit(function(e) {
// Only submit the form if information has been stored in our hidden input
return $("#formattedAddress").val().length > 0;
});
$("#inputName").bind("keypress", function(e) {
if(e.keyCode == 13) {
// Note that simply triggering the 'place_changed' event in here would not suffice, as this would just create an object with the name as typed in the input field, and no other information, as that has still not been retrieved at this point.
// We change this variable to indicate that enter has been pressed in our input field
enterPressedInForm = true;
}
});
// This event seems to fire twice when pressing enter on a search result. The first time getPlace() is undefined, and the next time it has the data. This is why the following logic has been added.
google.maps.event.addListener(autocomplete, 'place_changed', function () {
// If getPlace() is not undefined (so if it exists), store the formatted_address (or whatever data is relevant to you) in the hidden input.
if(autocomplete.getPlace() !== undefined) {
$("#formattedAddress").val(autocomplete.getPlace().formatted_address);
}
// If enter has been pressed, submit the form.
if(enterPressedInForm) {
$("#formName").submit();
}
});
});
This solution seems to work well.
Both of the above responses are good answers for the general question of firing a question when the user presses "enter." However - I ran into a more specific problem when using Google Places Autocomplete, which might have been part of the OP's problem. For the place_changed event to do anything useful, the user needs to have selected one of the autocomplete options. If you just trigger 'place_changed', the if () block is skipped and the cookie isn't set.
There's a very good answer to the second part of the question here:
https://stackoverflow.com/a/11703018/1314762
NOTE: amirnissim's answer, not the chosen answer, is the one to use for reasons you'll run into if you have more than one autocomplete input on the same page.
Maybe not the most user friendly solution but you could use JQuery to disable the enter key press.
Something like this...
$('.search-location').keypress(function(e) {
if (e.which == 13) {
return false;
}
});