【问题标题】:Protractor: functions overloading量角器:函数重载
【发布时间】:2015-08-10 09:53:22
【问题描述】:

我尝试扩展 ElementFinder 库。我想知道如何要求具有相同名称的不同方法? 我想做类似的东西:

 // spec.js
 var ef1 = require('./ef_extend1.js');
 var ef2 = require('./ef_extend2.js');

 expect(column_resizer.ef1.getWidth()).toEqual(18);
 expect(column_resizer.ef2.getWidth()).toEqual(18);

现在我有一个错误:

TypeError: Cannot read property 'getWidth' of undefined

我需要的库:

// ef_extend1.js
var ElementFinder = $('').constructor;
ElementFinder.prototype.getWidth = function() {
    return this.getSize().then(function(size) {
                                  return size.width + 1;
                               });
};

第二个:

// ef_extend2.js
var ElementFinder = $('').constructor;
ElementFinder.prototype.getWidth = function() {
    return this.getSize().then(function(size) {
                                  return size.width;
                               });
};

【问题讨论】:

    标签: angularjs overloading protractor angularjs-e2e e2e-testing


    【解决方案1】:

    我猜你已经使用了来自Protractor issue #1102 的解决方案,但是现在在PR#1633 之后可以更轻松地完成它,因为ElementFinder 现在暴露在protractor 全局变量中:

    protractor.ElementFinder.prototype.getWidth = function () {
        return this.getSize().then(function (size) {
            return size.width;
        });
    };
    
    expect($('body').getWidth()).toBe(100);
    

    更新:

    正如我在评论中所说,ElementFinder 只能一次又一次地扩展。如果你已经有一个方法getWidth,并且你用一个getWidth 实现扩展ElementFinder,那么第一个将被覆盖,不应该有任何冲突。但是您必须根据您何时要使用适当的方法集来严格按顺序排列它们:

    require('./ef_extend1.js');
    
    expect(column_resizer.getWidth()).toEqual(18);
    
    require('./ef_extend2.js');
    
    expect(column_resizer.getWidth()).toEqual(18);
    

    实际上,我已经提出了一些替代方法,但我认为它不会很好用,但无论如何。这是一个带有扩展方法的示例模块:

    // ef_extend1.js
    
    // shortcut
    var EF = protractor.ElementFinder;
    
    // holds methods you want to add to ElementFinder prototype
    var extend = {
        getWidth: function () {
            return this.getSize().then(function (size) {
                return size.width;
            });
        }
    };
    
    // will hold original ElementFinder methods, if they'll get overriden
    // to be able to restore them back
    var original = {};
    
    // inject desired methods to prototype and also save original methods
    function register() {
        Object.keys(extend).forEach(function (name) {
            original[name] = EF.prototype[name]; // save original method
            EF.prototype[name] = extend[name]; // override
        });
    }
    
    // remove injected methods and return back original ones
    // to keep ElementFinder prototype clean after each execution
    function unregister() {
        Object.keys(original).forEach(function (name) {
            if (typeof original[name] === 'undefined') {
                // if there was not such a method in original object
                // then get rid of meaningless property
                delete EF.prototype[name];
            } else {
                // restore back original method
                EF.prototype[name] = original[name];
            }
        });
        original = {};
    }
    
    // pass a function, which will be executed with extended ElementFinder
    function execute(callback) {
        register();
    
        callback();
    
        unregister();
    }
    
    module.exports = execute;
    

    您将像这样使用它们,能够在“隔离”环境中运行量角器命令,其中每个都有自己的ElementFinder 方法集:

    var ef1 = require('./ef_extend1.js');
    var ef2 = require('./ef_extend2.js');
    
    ef1(function () {
        expect(column_resizer.getWidth()).toEqual(18);
    });
    
    ef2(function () {
        expect(column_resizer.getWidth()).toEqual(18);
    });
    

    我不确定,也许我在这里过度设计,有比这更容易的解决方案。

    【讨论】:

    • 是的!它看起来更容易。谢谢!但是超载怎么办?我的目标是为页面中的每个组件创建独立的方法列表。也许有些方法名称相同,但功能不同。
    • 对不起,我把你的问题弄错了。关于重载问题我不确定它是否可以以正确的方式完成,因为你不能用你自己的实现替换原来的ElementFinder,你只能一遍又一遍地扩展它。我已经更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    相关资源
    最近更新 更多