This lesson is for PRO members.

Unlock this lesson NOW!
Already subscribed? sign in

Testing With Protractor Page Objects

3:28 Angular 1.x lesson by

Protractor Page Objects are a recommended for testing your AngularJS applications. Page Objects abstract the interaction between the browser and your functional tests, resulting in much cleaner tests.

Get the Code Now
click to level up comment guidelines


Protractor Page Objects are a recommended for testing your AngularJS applications. Page Objects abstract the interaction between the browser and your functional tests, resulting in much cleaner tests.


How does element('button1')) work as it gets called before the browser gets to the page with the button on it. Will protractor just lazily find the element when click() is called?


In my tests I'm finding that the locator is resolved on page object instantiation causing a few test failures. I've used Object.defineProperty to provide some lazy evaluated locators

In reply to Rob
Victor Alfonso Hazbun Anuff

is the IndexPage.js file under e2e/index folder, correct?

Joel Hooks: Page objects are an awesome pattern for keeping your Protractor tests very clean. Since interacting with pages is what you are generally doing with Protractor, we want to avoid fiddling with complex repetitive setup for every page that we're going to be testing.

We're going to create an object that provides an API for interacting with the page under test. The page object is just a constructor. In this case, we're going to call it Index Page. The page has two elements, a button and some message binding. We need to add properties to our page object to access these two guys.

This button will be assigned to the button element. And this message will be assigned to the message test binding. Because we need to load our page, we're going to also create a get method to load the correct URL for this particular page.

The last thing we'll add to this page object right now is a click button method. What the click button method does is actually uses the button element and calls its click method. So this is a way we can access that button without actually accessing that button.

Now down here in our tests we're going to create a variable called page and we're going to assign that a new instance of our page object.

We also want to make sure that our page is freshly loaded for each spec that we're going to run. We'll make it before each method for the index spec, and in the before each we're going to call the get method on the page object.

We can delete this call to browser get in the first spec. it wasn't a great place to call it anyway, because each spec would have relied on this particular spec having called that beforehand to load the page under test.

We don't want to interact with this browser object at all in our test. So instead of calling browser get title, we're going to go ahead and add a method to your page object. It's simply going to be called get title and it's going to call browser get title.

Now in our expectation, we can remove this call to browser get title and replace it with page get title.

We've made quite a few changes and we need to make sure our tests still pass, so we'll run those now. And they still pass. So now we can update the next test.

In this next test we have two variables that we just don't even need anymore. We can delete those and we're going to access them through the page object. Instead of calling the button elements click method directly, we're going to call the click button method that's on the page object.

We're accessing the message element directly as well, so instead of doing that we're going to go back to our page object and we're going to create a method called get message text.

As you may have guessed, this is simply going to call message get text. And now in our test we can access this method through our page instead and we're no longer accessing any elements within our test.

We'll run the tests again and they're still passing. The tests are a lot cleaner, but I really don't like that we have this page object that's sitting at the top of our test. What I'm going to do is create a file called indexpage.js and we're going to move this functionality over there. We're going to chop out this constructor and paste it to the new file.

Since Protractor is running on Node, we can use the module syntax. We're going to add module.exports=indexpage. Back in our test file I'm going to create a variable called index page and I'm going to set that equal to require index page.

Now the full syntax of our page object is no longer cluttering up our tests. We're going to run our tests. They are still passing.

Page objects are a great way to organize your Protractor tests. You are able to create clean API's for interacting with your application, and the result is tests that are very easy to read and understand.

Joel's Head
Why are we asking?