I'm trying make sure that the protractor test cannot continue while a class is present in my angular app. The class is responsible for locking the ui with a high z-index so the user wouldn't be able to click anything. I want to simulate this in my test. However, I'm not having any luck with this code:
// Wait http commands to finish
browser.wait(function() {
console.log(element(by.className('is-fetchingData')).isPresent());
return element(by.className('is-fetchingData')).isPresent()
}, 10000);
browser.wait(function() {
return element(by.className('is-fetchingData')).isPresent().
then(function(isPresent){
console.log("Is Element Present? - "+isPresent);
if(isPresent){
return true;
}
});
},'element is not present till timeout reached', 10000);
You can also do it using expected condtions, Look at below example
var ele = element(by.className('is-fetchingData'));
var EC = protractor.ExpectedConditions;
// Waits for the element to be no longer visible on the dom.
browser.wait(EC.invisibilityOf(ele), 5000); //this will wait untill the element is disappeared from the page.
Related
I am trying to create a Tampermonkey script to automatically fill a login form with my username and password and then I would like to click the login button. However, with the code below, it appears to wait the three seconds, and THEN it fills the text into the boxes. How can I "flush" the changes so that they appear before the wait time occurs?
Thanks!
(function() {
'use strict';
function wait(ms){
var start = new Date().getTime();
var end = start;
while(end < start + ms) {
end = new Date().getTime();
}
}
window.onbeforeunload = function (){
return "Leaving page...";
}
$(document).ready(function() {
document.getElementById("username").value = "userValue";
document.getElementById("password").value = "passwordValue";
wait(3000);
document.getElementsByClassName("btn-large").click();
});
})();
That wait function is locking up the browser tab (and probably the browser, and potentially the whole computer). Don't code like that!
Also:
(function() {... is completely superfluous in a Tampermonkey script.
$(document).ready(function()... is not helpful except in rare cases that do not apply here.
Lots, lots more, etc...
Here's that code refactored:
window.onbeforeunload = function () {
return "Leaving page...";
}
//-- Hacker easter egg! See linked questions.
document.getElementById ("username").value = "userValue";
document.getElementById ("password").value = "passwordValue";
setTimeout (clickBtnAfterDelay, 3000);
function () {
//-- Brittle! See linked questions.
document.getElementsByClassName ("btn-large")[0].click ();
}
From controller i detect resize event for $window and restart my carousel directive after it .
But the problem is , that carusel restart nearly 5-6 times . I cant find any helpful solution about this .
angular.element($window).bind('resize', function () {
$scope.$apply(function(){
$scope.showCarousel = false;
$timeout(function(){
$scope.calculateGamesCount();
$scope.showCarousel = true;
}, 250);
});
});
How can i detect , if resize event is finished then run functions ?
Unfortunately, there's no such event as "resize done" that we can hook into. Each pixel change is its own independent event. If a third party solution is 100% out of the question, you could implement your own home-grown debounce:
function debounce(f, n){
let allow_run = true;
return function(...args){
if(allow_run){
allow_run = false;
setTimeout(_=> allow_run = true, n);
return f.apply(f, args);
}
}
}
window.onresize = debounce(_=> console.log('resizing!'), 250);
Essentially, we have a gatekeeper, allow_run. If the debounced function is called while the gate is "open", execution is allowed, and the gate is closed until the timeout (n milliseconds) expires. If the debounced function is called with the gate "closed", nothing happens.
demo
I have a sample AngularJS site # https://gamersweb-js.firebaseapp.com/ with a protractor test case which is supposed to find an element by id on one of it's pages. The element with this id 'displayNameInHome' certainly does exist (in the user's 'Home' page), but the test case fails to find it there.
To get to the web page, log in using the credentials of user 'tester#qa.com' + password '123456', which will take you to the user's home page. The following test case fails to find element 'displayNameInHome' on this page, which will be the id of string 'tester' after the Welcome ....:
beforeEach(function() {
//browser.get('http://localhost:5000/');
browser.get('https://gamersweb-js.firebaseapp.com');
});
it('Testing display name in profile for logged in user:', function() {
element(by.model('loginUI.email')).clear().sendKeys('tester#qa.com');
element(by.model('loginUI.password')).clear().sendKeys('123456');
element(by.id('loginBtn')).click();
return browser.wait(function() {
var displayNameInHome = element(by.id('displayNameInHome'));
return displayNameInHome.getText().then(function(text) {
return text =="tester";
});
}, 10000);
});
I cannot figure out why the element 'displayNameInHome' is not found by the test case. Any help would be greatly appreciated.
Thank you.
The first parameter of browser.wait() is actually a condition to wait on. So your test is exiting pretty fast because the first parameter is not a condition.
Also, your test is lacking expects.
I changed your code so that the test waits 10 seconds for the #displayNameInHome element to be present and then perform the assertion.
it('Testing display name in profile for logged in user:', function() {
element(by.model('loginUI.email')).clear().sendKeys('tester#qa.com');
element(by.model('loginUI.password')).clear().sendKeys('123456');
element(by.id('loginBtn')).click();
var displayNameInHome = element(by.id('displayNameInHome'));
browser.wait(function() {
return browser.isElementPresent(displayNameInHome)
}, 10000);
expect(displayNameInHome.getText()).toEqual('tester');
});
I've a tricky question for you guys out there. I've made a simple exercise webapp using AngularJS and ngRoute.
Inside my index.html I got an ng-view element which provide two pages search_page.html and detail_of_result_page.html. The code works pretty fine, I put something in the first page input field, hit search button and all results magically appears in my page. The troubles comes with protractor that seems to not see my result in results repeater with his:
element.all(by.repeater("result in results"))
I've tried to put in browser.pause() and watch for errors, but everything seems right.
I've forgot the error code from Protractor:
Failed: Index out of bound.
Trying to access element at index: 0, but there are only 0 elements that match locator by.repeater("result in results")
OK, under your searchTest.js line: 27
beforeEach(function () {
var EC = protractor.ExpectedConditions;
browser.wait(EC.presenceOf($('li')),5000);
var resultItem = element.all(by.repeater('result in results')).first(); //BUG
var resultLink = resultItem.element(by.css('a'));
resultLink.click();
resultId = resultLink.getAttribute('href').then(function (attr) {
//var res = attr.match('/\/TDDBook\/Search\/#\/detail\/(\d+)/')[1]; // TODO: fix this shit
return 1;
});
});
Things seem alright until you do resultLink.click(); Assuming that it work fine for the first it ("should set the url to the selected detail view"). But when it come to second it("should see the details in the main page component") at this moment you are no longer on /#/splash route. Therefore your pereater no longer available to be located when your beforeEach() run again.
Solution
Your beforeEach doesn't seem useful and logically not run-able for your second it("should see the details in the main page component"). So just move all the thing like this:
it ("should set the url to the selected detail view",function () {
var EC = protractor.ExpectedConditions;
browser.wait(EC.presenceOf($('li')),5000);
var resultItem = element.all(by.repeater('result in results')).first(); //BUG
var resultLink = resultItem.element(by.css('a'));
resultLink.click();
resultId = resultLink.getAttribute('href').then(function (attr) {
//var res = attr.match('/\/TDDBook\/Search\/#\/detail\/(\d+)/')[1]; // TODO: fix this shit
return 1;
});
resultId.then(function (id) {
var expectedUrl = '/detail/'+id;
browser.getLocationAbsUrl().then(function (url) {
expect(url).toBe(expectedUrl);
})
})
})
P.S. just for your information, there is Page Object in protractor, which will be fit with the thing you attempt to do with your beforeEach() . Plus with a tiny bit of knowledge of commonJS (module.exports & require()) it will perfectly suit your needs ;) Cheer!
When I click the export button, it makes a REST call to our endpoint then few seconds after, I receive the response then I also render the table. Unfortunately, I read that every call is asynchronous which means my expect will be executed even if table hasn't been rendered yet. The expect I wrote checks if the string is on the table but it's failing since it's not there yet. What is the proper approach to this?
it('should generate global user report', function() {
element(by.css('button#exportButton')).click();
expect(element(by.css("th[name*=Date]")).getText()).
toEqual('Date');
})
The error on the console is
NoSuchElementError: No element found using locator: By.cssSelector("th[name*=Date]")
I noticed that the table hasn't been rendered yet that's why it's failing.
Protractor 1.7 introduced a feature called "Expected Conditions", that can be applied here.
Wait for element to become visible:
var EC = protractor.ExpectedConditions;
var elm = element(by.css("th[name*=Date]"));
browser.wait(EC.visibilityOf(elm), 5000);
expect(elm.getText()).toEqual('Date');
I had problem waiting for a dynamic element to appear. Have the driver wait for it to either be present or displayed. The number at the end is the timeout.
element(by.css('button#exportButton')).click();
var header = element(by.css("th[name*=Date]"));
browser.driver.wait(function() {
return header.isPresent();
}, 1000);
expect(header.getText()).toEqual('Date');
I had to wait until it was present AND displayed before the test was fully stable. You can do that like this:
var header = element(by.css("th[name*=Date]"));
browser.driver.wait(function() {
return header.isPresent().then(function(present) {
if (present) {
return header.isDisplayed().then(function(visible) {
return visible;
});
} else {
return false;
}
});
}, 1000);