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');
});
});
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="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'.
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 done what was suggested by @KatePaulk in their answer, and my test now looks like this:
var usernameInputField = element(by.name('inputName'));
var passwordInputField = element(by.name('inputPass'));
...
function loginAsUser(username, password) {
username = "abc";
password = "xyz";
usernameInputField.sendKeys(username);
passwordInputField.sendKeys(password);
loginBtn.click();
}
it('should log the user in to app', function() {
loginAsUser(username, password);
});
and while the script is running, although the username & password fields are correctly populated on the log in form, I get an error message when the script is trying to press the 'Log In' button, to submit the form:
W/element - more than one element found for locator By(css selector, .form-control) = the first result will be used
If I continue the script after this, the browser window is closed, and the script exits.
What am I doing wrong with how I am retrieving & clicking the 'log in' button?
Edit
As requested, the HTML for the form is:
<div class="page-signin">
<div class="signin-header">
<section class="logo text-center">
<h1>Login to {{main.brand}}</h1>
</section>
</div>
<div class="signin-body">
<div class="container">
<div class="form-container" data-ng-controller="LoginCtrl">
<div ng-show="errors.general || errors.username || errors.password"
class="alert alert-danger">
{{errors.general || errors.username || errors.password}}
</div>
<form class="form-horizontal"
data-ng-submit="login()"
name="loginForm">
<fieldset>
<div class="form-group">
<div class="input-group input-group-first">
<span class="input-group-addon"
ng-class="{'login-error-icon': errors.username}">
<span class="ti-user"></span>
</span>
<input type="text" um-autofocus
class="form-control input-lg"
data-ng-model="user.username"
placeholder="Username"
autocapitalize="off"
name="inputName">
</div>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon"
ng-class="{'login-error-icon': errors.password}">
<span class="ti-lock"></span>
</span>
<input type="password"
class="form-control input-lg"
data-ng-model="user.password"
placeholder="Password"
name="inputPass">
</div>
</div>
<div class="form-group">
<div class="input-group login-checkbox">
<span class="input-group-addon">
<label class="ui-checkbox">
<input data-ng-model="persistent" type="checkbox"/>
<span></span>
</label>
</span>
<label class="form-control input-lg">
<input data-ng-model="persistent" type="checkbox"/>
<span>Remember me</span>
</label>
</div>
</div>
<div class="divider divider-sm"></div>
<div class="form-control">
<input type="submit"
class="btn btn-brand text-center pull-right"
value="Log in"/>
</div>
</fieldset>
</form>
</div>
</div>
</div>
</div>