I'm fairly new to protractor and writing test cases.I tried to run this test case as shown below which is to open a page and click on "Home" which then takes back to another page added as expectation. The content of conf.js is:
exports.config = {
framework: 'jasmine',
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: [
'*navigating_spec.js'
],
useAllAngular2AppRoots: true
};
similarly the test case:
// spec.js
describe('Navigatiion', function() {
it('GNavigate to search page and back to dashboard', function() {
browser.get('http://appspot.com/#/pages/search');
element( by.ccs('/pages/dashboard')).click();
var EC = protractor.ExpectedConditions;
// Waits for the URL to contain 'foo'.
browser.wait(EC.urlContains('http://appspot.com/#/pages/dashboard'), 1000000);
});
});
The click part is not working, and I do not know which locator to use for this "Home" button
The text in application under text is shown below in image:
HTML text
When I run this test case, it does not do the click part and ends with error as process exited with error 1. Suggestions are appreciated is appreciated.
Just something to add, The conf.js file is working with another test, so configuration file should not be an issue. I just dont know which locator to use base don html code
Your locator element( by.ccs('/pages/dashboard')) is not valid CSS. You have a few options that I can see:
1) Select item by text:
element(by.cssContainingText('a', 'Home')).click()
2) Select item using attributes:
element(by.css('a[href="#/pages/dashboard"]')).click();
Also depending on the error you are getting, you can use an Expected Condition on that link too.
browser.wait(EC.elementToBeClickable(...)) (or present, or visible etc.)
Related
I am working on the development of an AngularJS app, and have recently been asked to look at integrating some automated testing into our development process. I have not used automated testing at all before, so am still getting to grips with it.
The framework that I have decided to use is Protractor, and I'm just looking at starting to write some basic tests, however, I'm having a bit of trouble getting hold of some of the HTML elements from within the spec.js file where my tests will be written. I have the following describe block in spec.js:
describe('My App', function() {
var loginForm = element(by.id('loginForm'));
var loginBtn = element(by.className('form-control'));
var usernameInputField = element(by.id('inputName'));
var passwordInputField = element(by.id('inputPass'));
it('should hit the VM hosted site', function() {
browser.get('http://192.168.x.xyz:8080');
expect(browser.getTitle()).toEqual('My app');
});
//Test to log in:
it('should enter the username into the username field on log in form', function() {
usernameInputField.sendKeys('username');
passwordInputField.sendKeys('password');
expect(loginForm.usernameInputField).toEqual("admin");
expect(loginForm.passwordInputField).toEqual("password");
});
});
My conf.js file currently looks like this:
exports.config = {
framework: 'jasmine',
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['spec.js'],
multiCapabilities: {
browserName: 'firefox'
}
}
When I run the command protractor conf.js from the command line, I get some output that says:
Failed: No element found using locator: By(css selector, "[id="loginForm.inputName"])
I have 'inspected' the input field for the username on the form in the browser, and it shows that the HTML element's 'name' attribute is 'inputName', and that that element is nested within the loginForm element.
I don't understand why the console is giving me the error that says it's trying to find the element using a 'CSS selector'- I'm expecting it to try and find the element by it's HTML tag's 'name' attribute... Clearly I'm doing something wrong in how I'm writing the 'test to log in', because if I comment that out, and run protractor conf.js again, I get 0 failures- so the other test is running successfully...
What am I doing wrong here? How can I get the form input fields and enter correct log in details into them to check that the 'log in' feature works correctly?
As an aside, although I will want to test the 'log in' capability too, is there a way to 'skip' this during testing, so that I can run the tests on all of the features of the app, without Protractor having to log in to the app every time to run the tests?
Edit
I've changed the variable definition of the form elements that I want to get, so that they're now:
var loginBtn = element(by.className('form-control.submit'));
var usernameInputField = element(by.id('loginForm.inputName'));
var passwordInputField = element(by.id('loginForm.inputPass'));
and have also changed the test to:
it('should enter the username into the username field on log in form', function() {
usernameInputField.sendKeys('username');
passwordInputField.sendKeys('password');
loginBtn.by.css('button.button.primary').click();
expect(loginForm.usernameInputField).toEqual("username");
expect(loginForm.passwordInputField).toEqual("password");
});
and this seems to have cleared up the No element found using locator... error message that I was getting. However, I'm now getting another error that says:
Failed: Cannot read property 'css' of undefined
on the line:
loginBtn.by.css('button.button.primary').click();
I don't understand why this is... Can anyone explain what I'm doing wrong here? How would I resolve this error?
This is where Your test fails:
loginBtn.by.css('button.button.primary').click();
You should change it into:
loginBtn.click()
Try replacing
var loginBtn = element(by.className('form-control.submit'));
by
var loginBtn = element.all(by.css('.form-control.submit')).get(0);
I am trying to do a simple Protractor test on different browsers and I am encountering that it is failing on IE, but not on Chrome.
I am testing the angularjs application on http://juliemr.github.io/protractor-demo/ which is a simple calculator app.
The test consists on the following code:
describe('Protractor Demo App', function() {
it('should add 2 numbers', function() {
var i,j;
var w=10000;
var t=100;
i=Math.floor((Math.random() * t) + 1);
j=Math.floor((Math.random() * t) + 1);
browser.sleep(w);
browser.get('http://juliemr.github.io/protractor-demo/');
browser.waitForAngular();
element(by.model('first')).sendKeys(i);
element(by.model('second')).sendKeys(j);
element(by.id('gobutton')).click();
console.log('Sent: ' + i.toString() + ' + ' + j.toString());
var x = element.all(by.repeater('result in memory').column('value')).get(0).getText();
expect(x).toEqual((i+j).toString());
And my config file is:
// conf.js
exports.config = {
capabilities: {
'browserName': 'internet explorer',
'platform': 'ANY',
'version': '11',
'nativeEvents': false,
'unexpectedAlertBehaviour': 'accept',
'ignoreProtectedModeSettings': true,
'enablePersistentHover': true,
'disable-popup-blocking': true
},
framework: 'jasmine',
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['spec.js']
}
When I set this last one for Chrome, (ie, commenting the capabilities part), the test runs as a charm and test is OK. I see the chrome window popping up, script puts numbers in, clicks button, result appears, and window closes.
When I set for IE (uncommenting the capabilities part) and launch the script, an IE window pops up with the text "This is the initial start page for the WebDriver server." and stays there for a while. Afterwards I see the script putting numbers in, and it closes straight away, giving a failed test on the log, with the message:
Message:
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 memory").column("value")
Stack:
NoSuchElementError: Index out of bound. Trying to access element at index: 0, but there are only 0 elements that match locator by.repeater("result in memory").column("value")
It seems like the "Go" button is not being clicked, but I do not understand why.
Can anyone help me understand what is going on?
Thank you!
The odd thing is that this is working in Chrome. Initially I thought this was an IE issue as well; however, the code above has an issue. In the StackOverflow link listed above in your comment, the column method is used correctly. The column usage is shown here on the Protractor site.
The line of code that looks suspect:
var x = element.all(by.repeater('result in memory').column('value')).get(0).getText();
This should probably be:
var x = element.all(by.repeater('result in memory').column('result .value')).get(0).getText();
This example is pretty much the same code as the protractor-cookbook. I would check that out as well.
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
When run in Protractor the following code
describe('todomvc angular2 tests', function() {
it('add to-dos and verify that they are displayed', function() {
browser.ignoreSynchronization = true; // The site/app under test uses AngularJS in what might be called a manually bootstrapped fashion, i.e. without use the ng-app directive.
browser.get('http://todomvc.com/examples/angular2/');
browser.driver.sleep(1000); // There's got to be a better way to wait for the custom tag (which is a custom AngularJS directive) to load.
var el = element(by.css('input.new-todo'));
el.clear();
el.sendKeys('task 1\r\n');
el.sendKeys('task 2\r\n');
browser.driver.sleep(2000); // aid in debugging
var resultlist = element.all(by.repeater('todo in todoStore.todos')); // This doesn't work...
expect(resultlist.count()).toEqual(2);
});
});
generates the following output:
Using the selenium server at http://localhost:4444/wd/hub
[launcher] Running 1 instances of WebDriver
F
Failures:
1) todomvc angular2 tests add to-dos and verify that they are displayed
Message:
Expected 0 to equal 2.
Stacktrace:
Error: Failed expectation
What is the best way (or any working way) to find and inspect the items within todoStore.todos (i.e. ul.todo-list)?
Protractor should be able to see those elements just fine. I wonder if the elements are not resolving for the expect? See if maybe this promise works:
$$('[ng-repeat="todo in todoStore.todos"]').count().then(function(countOfElements){
expect(countOfElements).toEqual(2, 'Error: Todo count did not match');
})
I am testing a scenario where there are 3 checkboxes that are populated based on a service call and the response of http get.
The i am having is when i run the tests with protractor conf.js the drop downs have not yet been populated with the response from the http get response, and so when i try testing anything the browser stops and the tests fails.
Is there way so that protractor can wait before running tests on those drop downs to be filled?
conf.js:
// An example configuration file.
exports.config = {
//directConnect: true,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
// Framework to use. Jasmine 2 is recommended.
framework: 'jasmine2',
// Spec patterns are relative to the current working directly when
// protractor is called.
specs: ['e2e/*.js'],
baseUrl: 'http://localhost:4000/',
// Options to be passed to Jasmine.
jasmineNodeOpts: {
defaultTimeoutInterval: 30000
}
};
test file:
var select = element(by.model('make'));
console.log(select);
select.$('[value="acura"]').click();
this fails on the click event because when this test runs the select has no option elements as the select gets populated from a json http get response.
Thanks in advance!!
you can try using the method below; before calling the click.
browser.waitForAngular();
Use protractor's inbuilt wait() method using ExpectedConditions that expects the drop down to be filled. Here's how -
var select = element(by.model('make'));
browser.wait(protractor.ExpectedConditions.presenceOf(select.$('[value="acura"]')), 10000)
.then(function(){
select.$('[value="acura"]').click();
});
Hope it helps.
use browser.wait()-
browser.wait(function(){
return elementPresent.isPresent();
}).then(function(){
element.click();
})