I’m a fan of the PageObject pattern when writing Protractor tests, because PageObjects make the test code more expressive and readable. When I sit down to write some Protractor tests, I usually write the test code I want to see first, and then try to make it happen.
For example, when writing some tests for a “login and redirect” scenario, I started off with some test specs like the following.
describe("The security application", function () { var secret = new SecretPage(); var login = new LoginPage(); it("should redirect to login page if trying to view a secret as anonymous user", function () { secret.go(); expect(browser.getCurrentUrl()).toBe(LoginPage.url); }); it("should go back to the secret after a login", function () { login.login("sallen", "sallen"); expect(browser.getCurrentUrl()).toBe(SecretPage.url); }); });
These tests require two page objects, the SecretRecipePage and the LoginPage. SInce Protractor tests run in Node, each page can live in a distinct module. First, the SecretRecipePage.
var config = require("./config"); var SecretPage = function () { this.go = function() { browser.get(SecretPage.url); }; }; SecretPage.url = config.baseUrl + "security/shell.html#/secret"; module.exports = SecretPage;
And the LoginPage.
var config = require("./config"); var LoginPage = function () { this.go = function() { browser.get(LoginPage.url); }; this.login = function(username, password) { $(".container [name=username]").sendKeys(username); $(".container [name=password]").sendKeys(password); $(".container [name=loginForm]").submit(); }; }; LoginPage.url = config.baseUrl + "security/shell.html#/login"; module.exports = LoginPage;
Both of these modules depend on a config module to remove hard coded URLs and magic strings. A simple config might look like the following.
var config = { baseUrl: http://localhost:9000/Apps/ }; module.exports = config;
Now all the spec file needs to do is require the two page modules …...
var SecretPage = require("../pages/SecretPage"); var LoginPage = require("../pages/LoginPage.js"); describe("The security application", function () { // …... });
And presto! Readable Protractor tests are passing.