Page Object Model structure for a complex application

允我心安 提交于 2019-12-25 01:48:25

问题


I've in the past couple of months used Puppeteer to drive an automation for a couple of small level projects. Now I want to scale the framework for a medium/large complex application.

I want to use the famed Page Object Model, where in I have separated the locators, page methods in separate files and I'm calling them in the corresponding page execution code.

My directory structure is like this

e2e_tests
    - locators
        - common-locators.js
        - page1locators.js
        - page2locators.js

    - constants
        - config.js

    - utils
        - base_functions.js
        - page1methods.js
        - page2methods.js

    - urls
        - urls.json

    - screenshots

    - test
        - bootstrap.js
        - page1.js
        - page2.js

The problem I'm facing right now is that I am not able to get the page to initialise in the method body for that particular page.

For e.g. if I have an input box in page1, I want to define a method inside utils/page1methods.js which can take care of this - something like

module.exports = {
    fillFirstInputBox(){
        await page.type(locator, "ABCDEFG");
     }
}

And then I want to call this inside the page1.js it block - something like this

const firstPage = require('../utils/page1methods.js').
.
.
.
it('fills first input box', async function (){
   firstPage.fillFirstInputBox();
});

I've tried this approach and ran into all kinds of .js errors regarding page being not defined in the page1methods.js file. I can copy paste the errors if that's necessary.

What can I do so that I

  • I am able to achieve this kind of modularisation.
  • If I can improve on this structure, what should be my approach.

回答1:


You can return an arrow function that will return the modules/set of functions with page variable. Be sure to wrap the whole thing in first braces, or manually return it.

module.exports = (page) => ({ // <-- to have page in scope
    async fillFirstInputBox(){ // <-- make this function async
        await page.type(locator, "ABCDEFG");
     }
})

And then pass the variable up there,

// make page variable
const firstPage = require('../utils/page1methods.js')(page)

That's it. Now all functions have access to page variable. There are other ways like extending classes, binding page etc. But this will be the easiest way as you can see. You can split it if you need.

We are halfway there. That itself won't solve this problem. The module still won't work due to async-await and class issue.

Here is a full working example,

const puppeteer = require("puppeteer");
const extras = require("./dummy"); // call it

puppeteer.launch().then(async browser => {
    const page = await browser.newPage();
    await page.goto("https://www.example.com");

    const title = await extras(page).getTitle(); // use it here
    console.log({ title }); // prints { title: 'Example Domain' }

    await browser.close();
});


来源:https://stackoverflow.com/questions/52298882/page-object-model-structure-for-a-complex-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!