I am new to angular and protractor.We use protractor for functional testing and integrated with jenkins.
Problem
In some screens we use ng-toast to show toaster messages(mainly for server response messages like 'save filed' etc.).But protractor could not catch these, since it will wait for all angular timeouts(including toaster timeout) to complete.Showing error:
Timed out waiting for Protractor to synchronize with the page after 11 seconds.
I tried to set ignoreSynchronization too.
How to tackle this. I am really stuck on this..
After a long search on google I got answer.We can make use of promises with browser.waitin test cases those needs to wait for toaster messages.
.....
browser.wait(function() {
var deferred = protractor.promise.defer();
getToaster().then(function(){
deferred.fulfill(true);
expect(getToaster().isDisplayed()).toBe(true);//and other assertions
});
return deferred.promise;
});
.....
This is well described in this blog
Also more details about protractor.promise can be found here
Alternatively I did it in another way as:
...
browser.manage().timeouts().implicitlyWait(10000);//set timeout for element
expect(toaster.getToaster().isDisplayed()).toBe(true);
browser.manage().timeouts().implicitlyWait(1);//reset
....
But in a protractor way of doing is browser.wait with ExpectedCondition which is described in the protractor api including custom conditions.I am currently using this explicit wait approach.
Related
About 6 months or so ago I started developing an automated test suite for an AngularJS application developed by my company, using Protractor.
After I had been working on this for a couple of months, some other work came up which I had to prioritise over the test suite, and so I haven't looked at it since around the end of November/ December last year.
When I stopped working on it, I made sure that everything that I had done up to that date was in a fully working state (commented/ removed the tests I had started working on but hadn't finished, etc), and committed that git branch. At this point, I was able to run all of the tests I had written up until then using the command protractor conf.js, and I could see that they were all passing as expected.
I recently checked my testing branch out again, as I have a day or two in between other projects, and thought I could make use of the time by working on the testing again.
The first thing I did once I had checked out the testing branch, was to try running my test scripts again, to ensure everything I had implemented so far was still working.
However, while most of the tests do still pass, a few of them are now failing due to time outs, even though I had made sure that all of the timing elements were working correctly before I shelved the testing for a while.
I have tried increasing the times that my tests should sleep or wait for things at the points at which they are failing, but this doesn't seem to have made a difference.
The particular tests that are now failing due to time outs are:
1.
it('should navigate to the Config/Platform page & check the values are all correct', function() {
browser.waitForAngularEnabled(false);
browser.actions().mouseMove(configMenuBtn).perform();
browser.wait(EC.visibilityOf(pageConfigPlatformBtn), 8000).then(browser.sleep(5000).then( /*ERF(14/11/2017 # 1630) browser.sleep() required to give DialogMgr service time to complete */
pageConfigPlatformBtn.click().then(function(){
browser.sleep(10000); /*ERF(14/11/2017 # 1640) This line is needed- because of how the form HTML is created, it needs time to be replaced by configured HTML that is displaying the required fields */
var eth0Mode = element(by.model('modelinstances.platform.eth_0_mode'));
var eth0Address = element(by.model('modelinstances.platform.static_ip.eth_0_address'));
var eth0Netmask = element(by.model('modelinstances.platform.static_ip.eth_0_netmask'));
var eth0gateway = element(by.model('modelinstances.platform.static_ip.eth_0_gateway'));
var eth1mode = element(by.model('modelinstances.platform.eth_1_mode'));
var eth1Address = element(by.model('modelinstances.platform.static_ip.eth_1_address'));
var eth1netmask = element(by.model('modelinstances.platform.static_ip.eth_1_netmask'));
var eth1gateway = element(by.model('modelinstances.platform.static_ip.eth_1_gateway'));
expect(browser.getCurrentUrl()).toMatch(moxaConfigPlatformUrlRegExpPattern);
expect(eth0Mode.getAttribute('value')).toBe("Static IP");
expect(eth0Address.getAttribute('value')).toBe("192.168.1.127");
expect(eth0Netmask.getAttribute('value')).toBe("255.255.255.0");
expect(eth0gateway.getAttribute('value')).toBe("192.168.1.1");
expect(eth1mode.getAttribute('value')).toBe("Static IP");
expect(eth1Address.getAttribute('value')).toBe("192.168.2.127");
expect(eth1netmask.getAttribute('value')).toBe("255.255.255.0");
expect(eth1gateway.getAttribute('value')).toBe("");
})));
})
The failure message for this test is:
App should navigate to the Config/Platform page & check the values are all correct
Message:
Failed: Wait timed out after 8002ms
Stack:
TimeoutError: Wait timed out after 8002ms
2.
it('should navigate to the Config/Date/Time page', function() {
browser.waitForAngularEnabled(false);
browser.actions().mouseMove(configMenuBtn).perform();
browser.wait(EC.visibilityOf(pageConfigDateTimeBtn), 2000).then(browser.sleep(1000).then( /*ERF(14/11/2017 # 1630) browser.sleep() required to give DialogMgr service time to complete */
pageConfigDateTimeBtn.click().then(function() {
expect(browser.getCurrentUrl()).toBe(VM + '/#/config/systemtime');
})));
})
The failure message for this test is:
App should navigate to the Config/Date/Time page
Message:
Failed: Wait timed out after 2023ms
Stack:
TimeoutError: Wait timed out after 2023ms
3.
it('should navigate to the Tag Browser page (final test)', function() {
console.log("Start final Tag Browser page test");
browser.waitForAngularEnabled(false);
browser.wait(EC.visibilityOf(pagesMenuBtn), 10000).then(
browser.actions().mouseMove(pagesMenuBtn).perform().then(
browser.wait(EC.visibilityOf(pageConfigDateTimeBtn), 2000).then(browser.sleep(1000)).then( /*ERF(14/11/2017 # 1650) browser.sleep() required to give DialogMgr service time to complete */
browser.wait(EC.visibilityOf(pageTagBrowserBtn), 12000).then(
pageTagBrowserBtn.click().then(
function() {
console.log("Tag Browser menu button clicked");
}).then(
browser.wait(EC.visibilityOf(tagBrowserPageTagsLink), 20000).then(
function(){
console.log("End Tag Browser page test (then call)");
expect(browser.getCurrentUrl()).toBe(VM + '/#/pages/tagbrowser');
}
)
)
)
)
)
);
});
The failure message for this test is:
App should navigate to the Tag Browser page (final test)
Message:
Failed: Wait timed out after 2009ms
Stack:
TimeoutError: Wait timed out after 2009ms
I have tried increasing the times that the wait() calls are being passed, but this hasn't resolved the issue.
I have read in the past that automated testing can be quite flakey, and that changes to the environment in which they're run can cause them to fail- so I'm guessing it's possible that because my computer will have changed since the tests were last run successfully (i.e. new software installed), this may be causing the tests to fail...?
Is there a method of 'best practice' for resolving this sort of issue with automated testing, or is just a case of having to go back and tweak my test scripts until they start passing again?
It's probably worth mentioning that all of my test are written in a spec.js file, and that these tests which failed are the last 3 of 18 test scripts in that file (i.e. the first 15 all still pass).
Anyone have any ideas how I can resolve this/ get my tests passing again?
I'm using Webdriver.io to download a file continuously
I tried the following code:
var webdriverio = require('webdriverio');
var options = {
desiredCapabilities: {
browserName: 'chrome'
// waitforTimeout: 1000000
}
};
webdriverio
.remote(options)
.init()
.url('https://xxx')
.setValue('#username', ‘xxx#gmail.com’)
.click('#login-submit')
.pause(1000)
.setValue('#password’,’12345’)
.click('#login-submit')
.getTitle().then(function(title){
console.log('Title was: ' + title);
})
.pause(20000)
.getUrl().then(function(url){
console.log('URL: ' + url);
})
.getTitle().then(function(title){
console.log('Title was: ' + title);
})
.click("a[href='/wiki/admin'] button.iwdh")
.getUrl().then(function (url) {
console.log('URL after settings ' + url);
})
.pause(3000)
.scroll('div.jsAtfH',0,1000)
.click("a[href='/wiki/plugins/servlet/ondemandbackup/admin']")
.pause(10000)
.click('//*[#id="backup"]/a')
//.pause(400000)
.end();
Note: The file size is 7GB and how long it will take to download is depend upon the network so instead of using pause() and timeout() is there any way to do it using webdriver.io or node.js ?
To begin with, your current task (waiting for a HUUUUGE file to download) is not a common use-case when it comes to Webdriver-based automation frameworks, WebdriverIO included. Such frameworks aren't meant to download massive files.
First off, you're confusing the waitforTimeout value with WebdriverIO test timeout. Your test is timing out before the .pause() ends.
Currently you're running your tests via the WebdriverIO test-runner. If you want to increase the test timeout, you have to use a different test framework (Mocha, Jasmine, or Cucumber) and set its timeout value to w/e you find appropriate. Going on, I recommend you use Mocha (coming from an ex-Cucumber guy).
You will have to install Mocha: npm install --save-dev wdio-mocha-framework and run your tests with it. Your test should look like this afterwards:
describe("Your Testsuite", function() {
it("\nYour Testcase\n", function() {
return browser
.url('https://xxx')
.setValue('#username', ‘xxx#gmail.com’)
.click('#login-submit')
// rest of the steps
.scroll('div.jsAtfH',0,1000)
.click("a[href='/wiki/plugins/servlet/ondemandbackup/admin']")
.pause(10000)
.click('//*[#id="backup"]/a')
)}
)}
Your config (wdio.conf.js) should contain the following:
framework: 'mocha',
mochaOpts: {
ui: 'bdd',
timeout: 99999999
}
As a side-note, I tried waiting a very long time (> 30 mins) using the above config and had no issues what-so-ever.
Let me know if this helps. Cheers!
If you click on a download button in your browser and you close your browser then your download will be also closed. If you are owning the website where you click on the download button then try to rewrite your code that you have a download able url. Then you can search for a module or way to download files from http url. If you are not the owner and you cant find a url in the href then you can maybe get the generated download url from the network section at your inspector.
Also I never heard that a browser gets closed after timeout? Maybe it comes from webdriver.io I never let my chrome so long open with webdriver.io
You can try to make a workaround use Intervall each 1 Minute as example and then use a webdriver.io command to don´t timeout.
I know it's very old question but I wanted to answer question from comment (and have no such possibility yet). But I will answer main question too.
When i am giving timeout in "wdio.conf.js" file it's not able to
downlaod file it's closing the session but by giving .pause(2000000)
in webdriver.io code it's able to download file of 7GB. What is the
use of timeout in "wdio.conf.js" file if it's kicking out the session
without downlaod?
So this timeout is related to elements state during the test run. So it "determines how long the instance should wait for that element to reach the state".
https://webdriver.io/docs/timeouts.html - this can help. But to answer the question too:
There are more many timeouts such test deals with. Like iamdanchiv wrote for this you should try using one of automatically supported frameworks like Mocha or Jasmine.
IMO right now the easiest way would to do the quick fresh setup using CLI provided by WDIO:
https://webdriver.io/docs/gettingstarted.html
Where you can just simply pick the additional framework you want to use. I would suggest using Jasmine and Chromedriver for this. Than in your wdio.conf.js you can change this part:
waitforTimeout: 10000,
jasmineNodeOpts: {
// Jasmine default timeout
defaultTimeoutInterval: 60000,
//
},
To something that works for you. Or you can use boilerplate projects from wdio page like this one:
https://webdriver.io/docs/boilerplate.html
But that's not all! Still you will have to create some method or function that checks for the file. So check where do you download the file or make it download where you want to and then create a method that uses some kind of wait:
https://webdriver.io/docs/api/browser/waitUntil.html
browser.waitUntil(condition, { timeout, timeoutMsg, interval })
So you can set the timeout either here or in wdio.conf in 'waitforTimeout'. Inside this method condition you can use node filesystem (https://nodejs.org/api/fs.html) to check the state of the file.
This can be helpful to get through waiting for file condition:
https://blog.kevinlamping.com/downloading-files-using-webdriverio/
What are the methods we can use to wait for an Angular site to be loaded in order to test it with protractor in order to avoid this error caused by jasmine : A Jasmine spec timed out. Resetting the WebDriver Control Flow ?
I'm able to make the login and go to home page that test is passed, but from the second test i have problems of jasmine.
I have configured this problem by adding this function into my config file :
onPrepare: function() {
return browser.getProcessedConfig().then(function(config) {
var browserName = config.capabilities.browserName;
browser.manage().timeouts().setScriptTimeout(60000);
});
});
You can use the browser object of Protractor to wait for angular.
As soon as you load your page add the following :
browser.waitForAngular();
This error means that your test took too much time and exceeded the default Jasmine spec timeout interval which is 30 seconds by default (It looks like you've configured the timeout to be 60 seconds). It can be configured in the jasmineNodeOpts object in your Protractor config:
jasmineNodeOpts: {defaultTimeoutInterval: timeout_in_millis},
The solution is usually use-case specific and it usually indicates there is an error in the test code. In order to fully understand what is going, we would need to see the code itself.
In your particular case, for starters, you should try moving the "ignore synchronization" and the browser.get() part into the beforeEach. Also, since you are turning the sync off, you need to wait for the element to be present on the page before interacting with it:
describe("my app", function () {
beforeEach(function () {
browser.ignoreSynchronization = true;
browser.get("...");
});
it("should make the login test", function () {
// ...
var EC = protractor.ExpectedConditions;
var username = element(by.model("credentials.username"));
browser.wait(EC.presenceOf(username), 10000);
username.sendKeys("RET02");
// ...
});
});
And, I am not sure if you really need to turn the synchronization off since this is an AngularJS page you are working with.
Can you wait for a url?
Let's assume that when you click on the login button your page is redirected to another url. So you can wait for the expected url. Example:
browser.driver.wait(function() {
return browser.driver.getCurrentUrl().then(function(url) {
// Dashboard is the loaded url after login (in this example)
return /Dashboard/.test(url);
});
}, 60000);
This code waits for the page browser.baseUrl/Dashboard to be loaded, for 60 seconds
I am trying to open two views in succession, both as modals in an Appgyver project. when i do supersonic.ui.modal.hide() and supersonic.ui.modal.show(some_view), the second view does not show. If I throw in an alert('here') in between the modal.hide() and modal.show(), it seems to work. What is the problem here? It's the same with supsersonic.ui.layers.pop() and supersonic.ui.layers.push(another_view) in succession.
Usage sample:
}else if (option === 'chooseLocation'){
$scope.currentOption = "location you chose.";
$scope.f = true;
supersonic.ui.modal.hide().then(function(){
supersonic.ui.modal.show("chooseLocation");
$localStorage.locationOption = 'lastUsed';
});
}
another snippet that i tried this morning that's not related to modals, but also doesn't work:
supersonic.ui.layers.popAll().then(function(){
var view = new supersonic.ui.View("searchresults#index?"+paramText);
supersonic.ui.layers.push(view);
});
The error I get on the log screen:
landing#drawer 11:23:29.382 error
"supersonic.ui.layers.popAll rejected: {}"
This seems to be a bug in the Supersonic API.
The Javascript success callback is invoked when the native wrapper has received the API call. This is invalid behaviour. The Javascript success callback should be invoked when the native wrapper has completed the API call (expected behaviour).
As a workaround, use Use Steroids.js events such as didclose to determine when the native API call has completed.
See Steroids modals and Steroids layers for further documentation.
I have filed a new bug in AppGyver Github issues
I'm creating a SPA using AngularJs and the ui-router from Angular-UI. Now I'm trying to create the authentication logic.
$rootScope.$on("$stateChangeStart", function (event, toState) {
if(toState.authenticate && !MainService.isAuthenticated()) {
if($cookieStore.get('authToken')) {
MainService.loginWithToken($cookieStore.get('authToken'))
.then(function() {
$state.go(toState.name);
event.preventDefault();
});
}
$rootScope.requestPath = toState.name;
$state.go('public.login');
event.preventDefault();
}
if(toState.url == '/login' && MainService.isAuthenticated()) {
$state.go('private.main');
event.preventDefault();
}
});
On state change, this checks if state requires authentication and transfer to login state if necessary. Also if user is logged in it prevents from reaching the login state. Authentication is done by token stored in cookie.
This is my protractor test scenario:
describe('Routes', function() {
it('Should go to the selected path if user logged in', function() {
browser.get('/');
expect(browser.getLocationAbsUrl()).toMatch("/login");
browser.manage().addCookie("authToken", "aaa");
browser.manage().getCookie("authToken").then(function(cookie) {
expect(cookie.name).toBe('authToken');
expect(cookie.value).toBe('aaa');
});
browser.get('/');
expect(browser.getLocationAbsUrl()).toMatch("/main");
browser.get('/#/main');
expect(browser.getLocationAbsUrl()).toMatch("/main");
/* This part fails, because, when the user is logged in,
he should be transfered to main state, if he is trying to reach the
login page. In this failing case, the user is able to reach the
/login even if he is logged in. */
browser.get('/#/login');
expect(browser.getLocationAbsUrl()).toMatch("/main");
browser.manage().deleteCookie("authToken");
browser.get('/#/login');
expect(browser.getLocationAbsUrl()).toMatch("/login");
browser.get('/#/main');
expect(browser.getLocationAbsUrl()).toMatch("/login");
});
});
When I try to simulate the test behaviour myself, everything is ok, but when I run protractor:
Message:
Expected 'http://localhost/#/login' to match '/main'.
Stacktrace:
Error: Failed expectation
I bumped into another question which resolved this issue.
Basically, you wait for an element in the new page to appear instead of relying on protractor to wait for state/page finish loading. At the time of writing this answer, protractor is still unreliable on waiting page fully loaded for ui-router. Protractor waits for $timeout and $http to be done.
official doc
so if you are using websocket, it might not be covered (at least according my observation).
The api you need to use is browser.wait
browser.wait(function() {
return $('#test321').isPresent(); // keeps waiting until this statement resolves to true
},
timeToWaitInMilliseconds,
'message to log to console if element is not present after that time'
);
expect($('#test321').isPresent()).toBe(true);
You can find details in the following link
Protractor, AngularJS, Parse -- Protractor does not wait for Angular to resolve
You might need to wait for the page to get loaded:
browser.get('/#/main');
var ptor = protractor.getInstance();
ptor.waitForAngular();
expect(browser.getLocationAbsUrl()).toMatch("/main");
Note that in Angular version 1.3 browser.getLocationAbsUrl() returns only the relative path. See the issue in https://github.com/angular/protractor/issues/1436:
Using angular 1.3 in the app under test and protractor 1.3.1 browser.getLocationAbsUrl() returns a relative url instead of the absUrl due to using angular.getTestability().getLocation() instead of $location.absUrl(). It's probably as easy as adding a getLocationAbs() to $$testability, but that goes into architectural questions I don't have context for.