Selenium / WebdriverJs / Protractor承诺链接页面对象

时间:2016-05-09 08:05:36

标签: javascript selenium promise chaining

我目前正在量角器/ selenium中实现页面对象模式。

因为量角器中的每个方法都会返回一个promise,为了保证我的页面对象中的方法也应该返回promises。

更多我的页面对象可能具有返回另一个页面对象或页面对象的自定义的函数(如LeftNavigation,MainContent)。应该在promise中返回页面对象,而不是返回页面对象本身。目前我并不真正理解如何做到这一点。

此外,我想在不使用.then(..)方法的情况下链接我的方法调用。对于WebElements,可以在不调用.then(..)方法的情况下调用其他函数,例如

browser.driver.findElement(By.css('#someid')).findElement(By.css('#somebutton')).click();

我还想用页面对象模式来实现这个目的:

let pagePromise = AdminBaseBage.get(); // returns a Promise<AdminBasePage>
let mContent = page.mainContent;// should return a Promise<MainContent>
let titlePromise = mContent.getModuleTitle(); // returns a Promise<string>

甚至更好

AdminBaseBage.get().mainContent.getModuleTitle();

在我的PageObjects的摘录下面有一些问题:

AdminBasePage.js

var LeftNavigation = require('../../pageobject/LeftNavigation.js');
var MainContent = require('../../pageobject/MainContent.js');

class AdminBasePage {

    constructor() {
        this._leftNavigation = new LeftNavigation();
        this._mainContent = new MainContent();
    }

    /**
     * @returns {Promise<AdminBasePage>}
     */
    static getPage() {
        return browser.driver.get("index.php").then(function() {
            return new AdminBasePage();
        });
    }

    /**
     * @returns <LoginPage>
     */
    logout() {
        this.leftNavigation.logout();
        return new LoginPage(); //also here I would like to return a promise.
    }

    /**
     * @returns {LeftNavigation}
     */
    get leftNavigation() {
        //Instead of return the object directly, I would like to return a promise here. 
        //But how?
        return this._leftNavigation;
    };

    /**
     * @returns {MainContent}
     */
    get mainContent() {
        //Instead of return the object directly, I would like to return a promise here. 
        //But how?
        return this._mainContent;
    };
}

module.exports = AdminBasePage;

MainContent.js

class MainContent {

    constructor() {

        /** @type {WebElementPromise} */
        this._element_mainContent = this.webDriver.findElement(By.css('#maincontent'));

    }


    /**
     * Gets the title of the main content
     *
     * @returns {webdriver.promise.Promise<string>}
     */
    getMainContentTitle() {
        return this._element_mainContent
                   .findElement(By.id('moduleTitle'))
                   .getText();
    }

}

/** @type {MainContent} */
module.exports = MainContent;

你能提出任何建议吗? 我希望以某种方式清楚我要解释的是: - )

此致

2 个答案:

答案 0 :(得分:1)

你不应该试图让PageObject成为一个承诺。 PageObject应该是一个方法/属性工厂,因此不应该是执行流程中的约束。 我会通过返回一个带属性的元素而不是试图找到构造函数中的所有元素来保持简单:

describe('Suite', function() {

    it('should module title be ...', function() {
        let pageAdmin = AdminBaseBage.get();
        let mContent = pageAdmin.mainContent;
        let titlePromise = mContent.getModuleTitle();
        expect(titlePromise).toEqual('module title');
    });

});


class MainContent {

    constructor() {

    }

    get element_module_title() { return element(By.css('#maincontent #moduleTitle')); }

    /**
     * Gets the title of the main content
     *
     * @returns {webdriver.promise.Promise<string>}
     */
    getModuleTitle() {
        return this.element_module_title.getText();
    }

}

答案 1 :(得分:0)

感谢您的意见。

你是对的,页面对象不应该限制执行流程。我会忘记试图在这里做出承诺:-)。 我还将constrcturos中的元素初始化提取到getter方法。

我的主页面对象现在由我创建的几个页面元素(LeftNavigation,TopMenu等)组成。 现在,每个页面元素都可以访问所需的WebElements(仅通过getter方法)。

class AdminBasePage extends BasePage {

    constructor{
        super();

        /** @type {LeftNavigation} */
        this._leftNavigation = new LeftNavigation();

        /** @type {TopMenu} */
        this._topMenu = new TopMenu();

        /** @type {PathNavi} */
        this._pathNavi = new PathNavi();

        /** @type {ContentTopBar} */
        this._contentTopBar = new ContentTopBar();

    /** @type MainContent*/
        this._mainContent = new MainContent()
    }

   /**
    * @returns {Promise<AdminBasePage>}
    */
    static getPage() {
        return browser.driver.get("index.php").then(function() {
            return new AdminBasePage();
        });
    }

    ....getters + other methods follow

}

我的测试现在看起来如下:

describe('module_checklist', function () {
     it('Check number of elements in list', function () {
        let page = AdminBasePage.getPage();//returns Promise<AdminBage>

        // check number of list rows
        page.then(function (templateListPage) {
                return templateListPage.mainContent.getArrListRows();//returns Promise<ListRow[]>
            })
            .then(function (arrRows) {
                expect(arrRows.length).toEqual(2);
            });


        //check total number in pagination
        page.then(function (templateListPage) {
            expect(templateListPage.mainContent.getPagination().getIntPaginationTotalNumber()).toEqual(2);
        });
    });
}