在Protractor中正确使用页面对象模式

Using Page Object Pattern Correctly in Protractor

本文关键字:面对 对象 模式 Protractor      更新时间:2023-09-26

我有一个Angular应用程序,我正在使用Protractor来测试它。

HTML

 <div id="all" class="row text-center">
        <div class="col-lg-4 col-md-4 col-sm-6 col-xs-6">
          <div class="dashboard-stat block panel padder-v bg-primary">
            <div class="icon hidden-xs">
              <img src="../assets/images/icon-ppt-inv.png">
            </div>
            <div>
              <div id="value" class="font-thin h1 block">
                {{summary.num | number:0}}
              </div>
              <div id="name" class="text-muted text-xs">
                Albert
              </div>
            </div>
          </div>
        </div>
        </div>

这是页面对象的代码:

    'use strict';
        var history_page = function (){
            this.getStat = function(){
                return element.all(by.css('#all'));
            };
            this.getName = function(){
                return element(by.css('#name')).getText();
            };
            this.getValue = function(){
                return element(by.css('#value')).getText();
            };

        };
        module.exports = new history_page();

测试代码

 var historyPage = require('./history_page.js');
    it('Test', function(){

     var history = historyPage.getStat().map(function (stat) {
        return {
            name: stat.historyPage.getName()
            value: stat.historyPage.getValue(),
        }
    });
     history.then(function (value) {
        console.log(value);
    });

     });

由于某种原因,我一直收到一个错误,说没有定义getName。如果我更改以下两行

name: stat.historyPage.getName() 
value: stat.historyPage.getValue(),

作为

name: stat.element(by.css('#name')).getText(),
value: stat.element(by.css('#value')).getText()

它运行良好。我不确定原因是什么。我真的想避免在我的测试页面上写css定位器,因为这看起来不好,而且是一种糟糕的做法。我将感谢能帮助我的建议。

我会将完整的map()块移动到页面对象:

var history_page = function () {
    this.all = element.all(by.css('#all'));
    this.getStat = function() {
        return this.all.map(function (stat) {
            return {
                name: stat.element(by.css('#name')).getText(),
                value: stat.element(by.css('#value')).getText()
            }
        });
    };
};
module.exports = new history_page();
'use strict';
    var history_page = function (){
        this.getStat = function(){
            return element.all(by.css('#all'));
        };
        this.getName = function(index){
            return this.getStat().then(function(stats){
                  return stats[index].get(index).element(by.css('#name'));
        };

    };
    module.exports = new history_page();

Yup、定位器、函数(如@alecxe提到的)和条件属于页面对象。否则就违背了他们的目的。

我会做一些类似的事情:

var historyPage = function() {
    this.stats = $$('.row');
    this.name = $('#name');
    this.getValue = $('#value');
};
module.exports = new history_page();

测试类似于:

var historyPage = require('./history_page.js');
it('Test', function() {
    expect(historyPage.name.getText()).toBe('Albert');
});

使用地图重复数据很酷。。。但以你的例子来说,我不确定我是否遵循了。#all是唯一的,所以如果你要映射重复的数据,你可能想映射出.row?不确定。但它可能看起来像这样:

    this.getStat = function() {
        var that = this;
        return this.stats.map(function(stat) {
            return {
                // not tested... 
                name: stat.that.name.getText(),
                value: stat.that.value.getText()
            }
        });
    };

FWIW,我的dractor_example-reo 中有一些页面对象示例