Skip to content

Latest commit

 

History

History
94 lines (67 loc) · 2.87 KB

README.md

File metadata and controls

94 lines (67 loc) · 2.87 KB

Page object pattern for Javascript

This repo contains examples how to implement Page Object pattern for Javascript testing frameworks. Let's assume, that we have UI framework that gives us a component instance, where we can navigate through items:

const component = createComponent()

component.find('.name') // find and return element with class "name"
component.find('.action-button') // find button to trigger action

To avoid repeating this selectors every time, it is recommended to create Page Object as a wrapper:

function Page() {
  this.name = () => component.find('.name');
  this.action = () => component.find('.action-button');

  //getter functions can be parametrized
  this.formField = (name) => component.find(`.form-control[name=${name}]`);
}

Then use this object rather that raw instance to do test actions

it('fill form and submit', () => {
  const component = createComponent();
  const page = new Page(component);

  page.formField('username').val('tester');
  page.formField('email').val('[email protected]');

  page.action().click();
});

It also makes sense to put this setup code in a helper function or beforeEach hook:

function setup() {
  const component = createComponent();
  return new Page(component);
}

ProTip: use ES2015 features to return multiple values from the function if you need so

function setup(data) {
  const component = createComponent(data);
  const page = new Page(component);
  return {component, page}
}

// later in code
const {component, page} = setup(data);

FAQ

Can I use this pattern with my framework?

Yes, you probably can. It works with any framework that uses UI-Components. Then you need to have an ability to traverse through elements tree. See examples section for actual frameworks example

I want to put a method like "clickTheButton" into my page object. Is it correct?

It is not okay. If you have a button in your component, it should be available not only for click but also for checking its content or visibility at all. When you create a method that unconditionally clicks on button, it is not good for reusability. However, you can add two methods: one, that returns button, and second that makes a click:

function Page(component) {
  this.button = () => component.find('button');
  this.clickOnButton = () => this.button().click();
}

I have a complex component and I need to find an element within another element. How can I do that?

If your component framework supports .find() chaining, you can do it with page objects as well:

function Page(component) {
  this.topBar = () => component.find('.top-bar');
  this.topButton = () => this.topBar().find('.button');
}

Ask your question if you have one.

Examples