Skip to content

Modus-Logo-Long-BlackCreated with Sketch.

  • Services
  • Work
  • Blog
  • Resources

    OUR RESOURCES

    Innovation Podcast

    Explore transformative innovation with industry leaders.

    Guides & Playbooks

    Implement leading digital innovation with our strategic guides.

    Practical guide to building an effective AI strategy
  • Who we are

    Our story

    Learn about our values, vision, and commitment to client success.

    Open Source

    Discover how we contribute to and benefit from the global open source ecosystem.

    Careers

    Join our dynamic team and shape the future of digital transformation.

    How we built our unique culture
  • Let's talk
  • EN
  • FR

Protractor and Page Objects

Published on September 29, 2015
Last Updated on June 14, 2021
Quality Assurance

In a previous post, we looked at using the Protractor framework with AngularJS apps. While Protractor is a great testing tool out of the box, it can benefit from some best practices to make a testing suite and its code more manageable. One practice worth considering for organizing test code is the use of a Page Object design pattern.

A page object is a class that simply stores your page elements. Elements and methods are housed in the page object file. This pattern allows testers to write clean code, avoid duplication, and better maintain their suites.

Let’s take a look at our previous Protractor example:

   
describe('Protractor Test', function() {  
  var addField = element(by.css('[placeholder="add new todo here"]'));  
  var checkedBox = element(by.model('todo.done'));  
  var addButton = element(by.css('[value="add"]'));  
  
  it('should navigate to the AngularJS homepage', function() {  
    browser.get('https://angularjs.org/'); //overrides baseURL  
  });  
    
  it('should show a search field', function() {  
    browser.sleep(5000); //used just to give you enough time to scroll to todo section  
    addField.isDisplayed();  
  });  
    
  it('should let you add a new task ', function() {  
    addField.sendKeys('New Task');  
    addButton.click();  
    browser.sleep(5000); //used just to see the task list update  
  });  
});

As you can see, each element is defined within the spec. This pattern can be ok for a small suite, but it isn’t able to support larger, more complex automation. With this pattern, each spec has its’ own set of elements to maintain. If multiple specs use the same elements then code duplication will quickly become a problem. And, if the UI of your application changes (that rarely happens, right?), you will need to update your elements within each, individual test.

All of these complications can be fixed with the use of page objects. Here is what a page object file for the spec could look like:

 
'use strict';  
  
module.exports = {  
    toDo: {  
        addField: element(by.css('[placeholder="add new todo here"]')),  
        checkedBox: element(by.model('todo.done')),  
        addButton: element(by.css('[value="add"]'))  
    },  
      
    go: function() {  
        browser.get('https://angularjs.org/'); //overrides baseURL  
        browser.waitForAngular();  
    },  
      
    addItem: function(item) {  
        var todo = this.toDo;  
          
        todo.addField.isDisplayed();  
        todo.addField.sendKeys(item);  
        todo.addButton.click();  
    }  
};

The majority of our logic needed to run the tests is now housed in a file called toDoPage.js. As your application grows, you may have multiple page object files that correspond to individual views. For example, a login view and home view may have their own, dedicated page objects. Organization of your tests and files may differ based on preference, but it’s important to decide on that organization structure early on.

Now that the page object has been defined, here is the cleaned up test spec:

   
var toDoPage = require('../pages/toDoPage.js');  
  
describe('Protractor Test', function() {  
  
  it('should navigate to the AngularJS homepage', function() {  
    toDoPage.go();  
  });  
    
  it('should let you add a new task ', function() {  
   toDoPage.addItem('New Task Item')  
  });  
});

This cleans up the spec significantly and enhances maintainability. With the Page Object design pattern, test workflows are in the specs while logic and UI elements are in the page objects. That is a good way to look at the separation between these two components.

This is a simple example, but it should give you enough information to begin adopting this design pattern. There are a lot of great resources on creating Page Objects if you want to learn more.

  • https://github.com/angular/protractor/blob/master/docs/page-objects.md
  • http://spin.atomicobject.com/2015/01/05/protractor-page-objects/
  • https://github.com/stuplum/astrolabe
Posted in Quality Assurance
Share this

Mallory Mooney

Mallory Mooney was a QA Engineer at Modus Create until 2018. She has experience in developing test automation for a broad range of technologies as well as establishing QA processes for projects. She’s an advocate for open source automation tools and believes in building the “right” tests for the job - not just an arbitrary number of them. Aside from her work, Mallory enjoys photography, Texas BBQ, and a good hard cider.
Follow

Related Posts

  • Protractor and Elementor
    Protractor and Elementor

    Intro Locators and elements are the foundation of any automated test (youdontsay). You spend a…

  • Test your Angular apps with Protractor
    Testing AngularJS Apps with Protractor

    Do the words “automated” and “tests” make you cringe a little? Creating automated tests for…

Want more insights to fuel your innovation efforts?

Sign up to receive our monthly newsletter and exclusive content about digital transformation and product development.

What we do

Our services
AI and data
Product development
Design and UX
IT modernization
Platform and MLOps
Developer experience
Security

Our partners
Atlassian
AWS
GitHub
Other partners

Who we are

Our story
Careers
Open source

Our work

Our case studies

Our resources

Blog
Innovation podcast
Guides & playbooks

Connect with us

Get monthly insights on AI adoption

© 2025 Modus Create, LLC

Privacy PolicySitemap
Scroll To Top
  • Services
  • Work
  • Blog
  • Resources
    • Innovation Podcast
    • Guides & Playbooks
  • Who we are
    • Our story
    • Careers
  • Let’s talk
  • EN
  • FR