1

I am running into a situation where the standard page object design is one-dimensional. These pages are very large and contain many (mostly unique) page sections.

The existing corpus of page objects look like this:

this.pageHeaderLogin = $$('div.header > a.login');
this.pageHeaderSignUp = $$('div.header > a.signup');
this.pageHeaderContact = $$('div.header > a.contact');
this.pageIntroSectionTitle = $$('div.intro > span.title');
this.pageIntroSectionText = $$('div.intro > span.description');

and so on, with as many as 50-100 elements, all immediate children of this.

It seems to me a much better structure would not be one-dimensional, but rather compartmentalized similar to how the page itself is structured. So I'd prefer to do a page object like:

this.pageHeader.login = $$('div.header > a.login');
this.pageHeader.signUp = $$('div.header > a.signup');
...
this.pageIntroSection.title = $$('div.intro > span.title');

and so on.

Unfortunately I've been told this is too complex. I'd like to make an argument that it isn't only not complex, but actually more organized, but all the examples out there for page objects are too small to illustrate anything beyond one-dimensional structure.

Can someone point me to good examples of a non-one-dimensional page object that I can use as a reference to show the benefits of this design?

bad_coder
  • 11,289
  • 20
  • 44
  • 72
Keith Tyler
  • 719
  • 4
  • 18

1 Answers1

1

Flat is always better than nested in theory and only until making things nested is actually a plus to readability, modularity and maintainability. I don't see anything wrong in having sub-page objects inside page objects. Makes perfect sense when a page object becomes overly complex and needed to be splited into parts.

We've done that for a couple of page objects in our test codebase. We've defined these kind of page objects as packages - directories with an index.js inside, sample page object directory structure:

- po
  -- somepage.po.js
  -- someotherpage.po.js
  -- page.po
    -- index.js
    -- subpage.po.js

Where inside the index.js is something like:

var SubPage = require("./subpage.po"),
var Page = function () {
    this.somefield = element(by.id("myid"));

    this.subPage = new SubPage(this);
}

module.exports = new Page();

Note that we are passing this to the SubPage constructor here - for it to access page object fields of the parent - might be handy in certain situations.

And here is how this nested page object can be used inside a test:

var page = requirePO("page");

describe("Some Test", function () {
    it("should do something good", function () {
        page.somefield.click();
        page.subPage.someotherfield.sendKeys("test");
    });
});

requirePO() is an utility function that we use to "import" page objects, see more at:

Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • I would think that a custom require() function woud be more complex to understand than this model. Some examples for page objects refer to "component objects" as an option. It occurs to me that I could just as easily do a homepageHeaderPageObject and a homepageIntroPageObject and a homepageFeaturesPageObject and so on. But then that's a lot more require()s and a lot more object juggling. Instead of home.intro.text and home.header.login, I'd have to have homeintro.text and homeheader.login. Can you elaborate why flat is preferable? – Keith Tyler Nov 18 '16 at 19:48
  • @KeithTyler I have a feeling that either you misunderstood my point or I have not explained it clearly enough, sorry if this is the case. I am actually supportive of the idea to nest complex page objects to a certain extent. With the presented approach, you can actually use fields from nested page objects without additional requires in your test, e.g. see `page.subPage.someotherfield` in the sample test. `requirePO` is just a helper tool to make requires in the tests more readable and have a single way to import page objects from a designated location in your project. Thanks! – alecxe Nov 18 '16 at 21:07