Testing AngularJS with Protractor - angularjs

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

Related

Way to implement resetApp for React Native with wdio-cli/? - webdriverio

Hellow there! I am using the wdio/cli so I created the wdio.conf.js with this command, then I start doing the test. But the issues is when have more than one test in a single or multiple test files.
In the test file I have something like this:
beforeEach(async function() {
$('~home').waitForDisplayed(81000, false);
});
Where home tag is a tag in the first view when the app runs in first screen. And appear this error:
element ("~home") still not displayed after 10000ms
So need to do kind of driver.resetApp()/ But dont know how to do it, what import do I need to do etc.
Did you try resetApp? You can't user driver as "main object" - Everything is under browser variable. Try this
//async
await browser.resetApp();
//sync
browser.resetApp();
Check Appium doc + wdio documentation.

Protractor test working in Chrome but not in IE11

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.

Issue with protractor test case: Process exited with error 1

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

What are the methods we can use to wait for an angular site to be loaded in order to test it with protractor?

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

Can Protractor locate and inspect elements of list created by bootstrapped angularjs's ng-for?

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

Resources