page-object
page-object copied to clipboard
A pattern to test UI Components
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
- React
- Backbone
- Vue