I am trying to creat to page object files with protractor.
My app has the following layout. and page object files..
navbar_po.js
var NavBar = function() {
// define navbar elements and operations
// .
// .
};
module.exports = NavBar;
subNavbar_po.js
var SubNavBar = function() {
// define subnavbar elements and operations
// .
// .
};
module.exports = SubNavBar;
page1_po.js
var Page1 = function() {
this.navbar = function(){
var navbar = require('./navbar_po.js');
return new navbar();
}
this.subnavbar = function(){
var subnavbar = require('./subNavbar_po.js');
return new subnavbar();
}
// define Page1 particular elements and operations
// .
// .
};
module.exports = Page1;
and I access the navbar elements as follows in test script..
var page1 = new require('./page1_po.js');
page1.navbar.something_method();
page1.subnavbar.something_method();
Is this the best way?
I don't want to define the same navbar elements for each page object file.
Is there any other good way?
Ok, great question, super detailed information too!
🛠Let's get to it. We'll be using ES6 syntax!
Small structural conventions will make the project easier to maintain and won't need defining the same navbar (or any other) elements for each page object file.
Also, the suggested filename kebab-case style will help keep things recognizable as your project grows :)
navbar_po.js
// suggest renaming to nav-bar.pageObject.js
export default class NavBar {
constructor() {
this.homePageButton = element(by.id('home-button'))
// more element locators
}
function clickHomePageButton() {
this.homePageButton.click()
}
// more operations
}
subNavbar_po.js
// suggest renaming to sub-nav-bar.pageObject.js
export default class SubNavBar {
constructor() {
this.aboutPageButton = element(by.id('about-button'))
// more element locators
}
function clickAboutPageButton() {
this.aboutPageButton.click()
}
// more operations
}
page1_po.js
// suggest renaming to page-one.pageObject.js
import SubNavBar from './sub-nav-bar.pageObject' // the .js at the end can be omitted, it will know it's JS!
import navBar from './nav-bar.pageObject'
export default class pageOne {
constructor() {
this.NavBar = NavBar
this.SubNavBar = SubNavBar
// more element locators
}
function visitHomePageThenAboutPage() {
const navBar = new NavBar()
const subNavBar = new SubNavBar
navBar.clickHomePageButton()
subNavBar.clickAboutPageButton()
}
// more operations
}
your test script
pageOne.spec.js
If any of your elements change, you only ever need to change them in the relevant pageObject file. Nothing else needs changing, not even your test script!
import PageOne from './page-one.pageObject');
describe('navigating', () => {
it('should go to home and about', () => {
const pageOne = new PageOne()
pageOne.visitHomePageThenAboutPage()
// expect statement
}
}
💡 pageObject concept
Imagine that your test script mimics human interaction with your site. And pageObjects are how you abstract away and hide exactly what needs to be done for those user behaviours to interact with your page.
📚 Resources
The following is a great styleguide that helps keep things manageable ✨
https://github.com/CarmenPopoviciu/protractor-styleguide
Also, checkout this (disclaimer: my) curated list on all things awesome for Protractor! Make a pull request if you ever want to add anything!
Good luck testing!
https://github.com/chowdhurian/awesome-protractor
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With