Quickstart
Suppose we have a couple of acceptance tests to test the login page of our site.
test('logs in sucessfully', function(assert) {
visit('/login');
fillIn('#username', 'admin');
fillIn('#password', 'secret');
click('button');
andThen(function() {
assert.equal(currentURL(), '/private-page');
});
});
test('shows an error when password is wrong', function(assert) {
visit('/login');
fillIn('#username', 'admin');
fillIn('#password', 'invalid');
click('button');
andThen(function() {
assert.equal(currentURL(), '/login');
assert.equal($.trim(find('.errors').text()), 'Invalid credentials');
});
});
We want to convert this test to use a page object, so, the first thing we need to do is to create a new page object. For this we’ll use one of the generators that comes with the addon.
$ ember generate page-object login
installing
create tests/pages/login.js
The generator created a file inside /tests/pages
folder. Let’s describe the login page structure on our new page object.
import PageObject from '../page-object';
const { clickable, fillable, text, visitable } = PageObject;
export default PageObject.create({
visit: visitable('/'),
username: fillable('#username'),
password: fillable('#password'),
submit: clickable('button'),
error: text('.errors')
});
Now the only step left is to include the page object on our test and use it
import page from '../pages/login';
...
test('logs in sucessfully', function(assert) {
page
.visit()
.username('admin')
.password('secret')
.submit();
andThen(function() {
assert.equal(currentURL(), '/private-page');
});
});
test('shows an error when password is wrong', function(assert) {
page
.visit()
.username('admin')
.password('invalid')
.submit();
andThen(function() {
assert.equal(page.error(), 'Invalid credentials');
});
});
We can go a step further and describe the steps of the test using higher level of abstraction. Let’s see an example of this
import PageObject from '../page-object';
const { clickable, fillable, text, visitable } = PageObject;
export default PageObject.create({
visit: visitable('/'),
username: fillable('#username'),
password: fillable('#password'),
submit: clickable('button'),
error: text('.errors'),
loginSuccessfully() {
return this.visit()
.username('admin')
.password('secret')
.submit();
},
loginFailed() {
return this.visit()
.username('admin')
.password('invalid')
.submit();
}
});
And update the test accordingly
test('logs in sucessfully', function(assert) {
page.loginSuccessfully();
andThen(function() {
assert.equal(currentURL(), '/private-page');
});
});
test('shows an error when password is wrong', function(assert) {
page.loginFailed();
andThen(function() {
assert.equal(page.error(), 'Invalid credentials');
});
});
And that’s it! Now we have cleaner, more maintainable and easier to read tests.