In a recent post of mine I had an issue with hideen elements (see Here). Since then I have moved from chrome driver to phantomjs for headless testing.
My issue is this.
Since the move selecting hidden elements causes the error below,
UnknownError: Error Message => ''undefined' is not a function (evaluating 'arguments[0].click()')'
Running in chrome (webdriver) is fine and all test pass but phantomjs doesn't seem to like this method. Is there another way round this issue that will run in under test using phantomjs and protractorjs.
EDIT
The test below is what I am having issues
it('should redirect to addresses', function () {
var hiddenWebElement = ptor.driver.findElement(by.css('ul#myaccount li:nth-child(2) a'));
ptor.driver.executeScript("arguments[0].click()",hiddenWebElement).then(function() {
expect(ptor.driver.getCurrentUrl()).toContain('#/addresses');
});
}, 15000);
my config file is
// An example configuration file.
exports.config = {
// The address of a running selenium server.
seleniumAddress: 'http://localhost:4444/wd/hub',
baseUrl: 'http://localhost:52254',
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'phantomjs'
},
// Spec patterns are relative to the current working directly when
// protractor is called.
specs: [
'Scenarios/account_spec.js',
'Scenarios/add_address_spec.js'
],
// Options to be passed to Jasmine-node.
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000
}
};
A point to notice is that all tests above this run expect the one below which again has an issue when trying to find the element
it('should redirect to login', function () {
ptor.driver.findElement(by.id('headerLoginBtn')).click().then(function () {
expect(ptor.driver.getCurrentUrl()).toContain('/Account/Login');
});
}, 15000);
which throws an exception of element is not visible. Also my tests in this scenario use ptor.driver because the pages contain c# ASP.NET code.
i found a workaround which looks like the only possible way to me. I removed the css that hide the element and then clicked on it and it worked. I am using selenium but it should be similar solution for you
executeJavaScript("$('.log-out').removeClass('hide');");
driver.findElement(By.className("log-out")).click();
Related
I am trying to write some end to end tests and waned to use async and await.
configuration file
exports.config = {
framework: 'jasmine',
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['spec.js'],
SELENIUM_PROMISE_MANAGER: false,
getPageTimeout: 10000,
multiCapabilities: [
{
browserName: 'firefox'
}, {
browserName: 'chrome'
}
]
}
spec file
describe('home-view', function(){
beforeEach(async function(){
await browser.get('http://localhost:49335/index.html#!/home');
});
it('sorted by firstname', async function(){
await element(by.css("[ng-click=\"sortData('firstname')\"]")).click();
var firstname = element.all(by.repeater('a in emps')).all(by.css('td'));
expect(await firstname.get(0).getText()).toEqual('abraham');
});
})
Error
Error while waiting for Protractor to sync with the page: "both angularJS testability and angular testability are undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping."
Why do I get this error? Thanks
You got this error because Protractor by default wait angular page is loaded. If you work with non angular you should add await browser.waitForAngularEnabled(false); to onPrepare block:
onPrepare: async () => {
...
await browser.waitForAngularEnabled(false);
...
How does this "waiting" mechanism works? I will copy description from code:
* If set to false, Protractor will not wait for Angular $http and $timeout
* tasks to complete before interacting with the browser. This can cause
* flaky tests, but should be used if, for instance, your app continuously
* polls an API with $timeout.
So, as you can see it is all about $http and $timeout tasks. A bit often developers use it in a not proper way.
In conclusion, if you see such error:
both angularJS testability and angular testability are undefined
you have to add await browser.waitForAngularEnabled(false);.
Give the getPageTimeOut more than 20 sec. Use explicit wait like browser.sleep(2000) after browser.get method. The error occured may be because of slow response from webpage and also use dirctConnect instead of seleniumAddress.
Earlier All I needed to add this in my script.js
browser.driver.ignoreSynchronization = true;
However adding this solved my problem.
browser.waitForAngularEnabled(false);
So altogether final script.js is
describe('My first non angular class', function() {
it('My function', function() {
browser.driver.ignoreSynchronization = true;
browser.waitForAngularEnabled(false);
browser.driver.manage().window().maximize();
//browser.get('http://juliemr.github.io/protractor-demo/');
browser.driver.get('https://stackoverflow.com/users/login');
element(by.id('email')).sendKeys('6');
})
})
We are trying to automate a publicly accessible website and click on one of the links, but the test fails with TimeOut Exception while locating the element as below:
From: Task: Protractor.waitForAngular() - Locator: By(link text, MY ACCOUNT)
Sample conf and spec file below.
Requesting help on how to solve this issue.
conf.js
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
capabilities: {
'browserName': 'chrome'
},
specs: ['test.js']
};
test.js
describe('test', function() {
it('should navigate', function(done) {
browser.get('https://ww2.tracfone.com');
element(by.linkText('MY ACCOUNT')).click();
done();
});
};
Found the root cause for the issue you were seeing for your webPage. Looks like your site continuously polls $timeout or $http, Protractor will wait indefinitely and time out.
I have monitored the http traffic below and see that your app polls at frequent intervals and Protractor just waits. Checkout the screen grab below.(The green marks in the timeline indicating $http calls to - https://ww2.tracfone.com/cgi-bin/tealeaf.pl )
More details on why you are seeing this error is documented here. ok. Coming to the different solutions for this, there are multiple work-arounds for this. I will just talk in brief about the alternatives and leave it to you to choose the best one.
IgnoreSynchronization: Turn this flag - browser.ignoreSynchronization to false before the browser.get() and continue with the test flow and set the flag to true again for other pages
Check here
Interval.js : I am no expert on this but you can explore more here
You should use the $interval for anything that polls continuously
(introduced in Angular 1.2rc3).
Try with different timeOut configurations and see if your app polling stops after some time
allScriptsTimeout: 120000,
getPageTimeout: 120000,
jasmineNodeOpts: {
defaultTimeoutInterval: 120000
}
I setup a sample project based on the items you've posted and this test appears to be working for me.I'm not sure why you are getting the timeout that is usually associated with pages that are not angular but setting browser.ignoreSynchronization = true helped get past this error.
var ec = protractor.ExpectedConditions;
var timeout = 60000;
describe('test', function() {
it('should navigate', function(done) {
browser.ignoreSynchronization = true;
browser.get('https://ww2.tracfone.com')
var myAccount = element(by.linkText('MY ACCOUNT'));
browser.wait(ec.visibilityOf(myAccount)).then(function() {
myAccount.click();
})
done();
});
});
I setup my protractor with this conf file below:
exports.config = {
framework: 'mocha',
rootElement: '#container1',
specs: ['*container1_spec.js'],
capabilities: {
browserName: 'chrome',
version: '',
platform: 'ANY'
},
onPrepare: function() {
// implicit and page load timeouts
browser.manage().timeouts().pageLoadTimeout(40000);
browser.manage().timeouts().implicitlyWait(25000);
}
}
The application is manually bootstrapped in angular and I need to change the root element after some steps when the application transfers the control to another application by doing a window.location.replace. The second application that starts is also an angular app which does manual bootstrapping.
From another thread in SO. I found the code that I could do browser.rootEl = 'div#container2';
WebDriverError: unknown error: [ng:test] no injector found for element argument to getTestability
http://errors.angularjs.org/1.5.8/ng/test
As I mentioned in the question, changing the rootEl did not work. I had to resort to working with the DOM to run the tests.
function getMessage() {
return document.getElementById('msg').textContent;
}
setTimeout(function() {
browser.executeScript(getMessage).then(function (txt) {
chai.expect(txt).to.equal("Error occured");
done();
});
}, 10000);
browser.executeScript is the key function that allowed me to query DOM and workaround. I had to add a timeout for the lag to allow the second application to download and bootstrap.
I have an angular application that I am writing e2e test for using protractor.
Following is my conf.js file setup
var project = require('./package.json');
var HtmlReporter = require('protractor-jasmine2-screenshot-reporter');
var multiCapabilities = [{
'browserName': 'chrome'
}];
multiCapabilities = [{
'browserName': 'chrome',
"platform": "Windows 7",
'build': 'Testing',
'name': project.name + ' tests'
}]
exports.config = {
framework: 'jasmine2',
sauceUser: 'blahblhablah',
sauceKey: 'xyzabcdxyzabac',
multiCapabilities: multiCapabilities,
specs: ['e2e/main.spec.js'],
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000
},
onPrepare: function() {
jasmine.getEnv().addReporter(new HtmlReporter({
dest: 'reports/e2e'
}));
}
};
Following is my test spec file
'use strict';
var mainPage = require('./page.js');
describe('Demo', function() {
//Check if title pages are consistent
it('Test 1', function() {
browser.get('http://localhost:3000/');
expect(browser.getTitle()).toEqual('NBA LIVE');
});
});
I am running my test on saucelabs when I run them locally I have no issues. So after I ran this test I got the following error message.
Message:
Failed: Angular could not be found on the page http://localhost:3000/ : retries looking for
angular exceeded
So i did a little more research and realized I can set browser.ignoreSynchronization = true; in my test spec file.
So after doing that I get the following error message:
Message:
Expected 'http://localhost:3000/' to equal 'NBA LIVE'.
So I think maybe the angular or the content is not loading because of me setting ignoring synchronization to true but if i do not then I get the other error. Again none of this is an issue when running my test locally on my laptop but only when doing on saucelab. It is clear I need to add something to make angular content load. Please advice me on what to do.
what might be happening is that it's checking the expect before the page loads so you could try to make it wait till the title says NBA LIVE before you expect it by using the protractor.until statments
browser.wait(protractor.until.titleIs("NBA LIVE"), 5000, "✗ Failed to wait for the NBA LIVE page to load");
expect(browser.getTitle()).toEqual("NBA LIVE");
EDIT:
Since you are using a local app and using saucelabs then you will need to setup sauce connect
My protractor tests are timing out waiting for page sync. I've checked the console, and no errors are shown, so I'm having trouble debugging. I've tried using allScriptsTimeout as well as defaultTimeoutInterval to no avail. No polling in my app, and the test does seem to log in correctly, it just hangs once logged in even though everything looks fully rendered. My code:
Config file:
var exports;
exports.config = {
// The address of a running selenium server.
seleniumAddress: 'http://localhost:4444/wd/hub',
// Spec patterns are relative to the location of this config.
specs: [
'scenarios/features/portfolio-manager-e2e-local.js'
],
multiCapabilities: [
{
'browserName': 'chrome'
}
],
jasmineNodeOpts: {
onComplete: null,
isVerbose: true,
showColors: true,
includeStackTrace: true,
defaultTimeoutInterval: 20000,
}
};
Test:
I'll just post one for now, the first test that runs and fails:
it('should login user with correct credentials', function () {
browser.get('/#/portfolio');
element(by.model('username')).sendKeys('test');
element(by.model('password')).sendKeys('test');
element(by.css('.btn.btn-md.btn-primary')).click();
expect(element(by.css('.port-header')).getText()).toEqual("Portfolios");
});
Thanks.
I found an ngToast successful login popup had a timeout of 15.5 seconds which was causing the hangup.
You need to wait for angular before making any assertions:
Instruct webdriver to wait until Angular has finished rendering and
has no outstanding $http calls before continuing.
browser.get('/#/portfolio');
browser.waitForAngular()