Javascript 检查数组中是否有任何值与dom中的元素匹配,然后在量角器中向该元素发送键

Javascript 检查数组中是否有任何值与dom中的元素匹配,然后在量角器中向该元素发送键,javascript,arrays,protractor,jasmine-node,Javascript,Arrays,Protractor,Jasmine Node,我正在使用jasmine/量角器对公司管理的多个站点运行测试套件。(这些站点是订单/结帐站点)目前,我为每个站点设置了一个单独的测试套件,该套件使用我创建并存储在助手中的函数来填写每个表单,这样我就可以在我的规范中调用这些函数,并运行订购过程来下测试订单,这目前起作用,打给助手的电话没有问题 量角器:v5.1.2 茉莉花:v2.6 节点:v8.0.0 这里的问题是,每个站点倾向于为给定表单中的每个字段使用任意数量的字段标识符,而我最终为特定站点上的特定表单编写了特定函数。由于每个站点使用2到4个

我正在使用jasmine/量角器对公司管理的多个站点运行测试套件。(这些站点是订单/结帐站点)目前,我为每个站点设置了一个单独的测试套件,该套件使用我创建并存储在助手中的函数来填写每个表单,这样我就可以在我的规范中调用这些函数,并运行订购过程来下测试订单,这目前起作用,打给助手的电话没有问题

量角器:v5.1.2
茉莉花:v2.6
节点:v8.0.0

这里的问题是,每个站点倾向于为给定表单中的每个字段使用任意数量的字段标识符,而我最终为特定站点上的特定表单编写了特定函数。由于每个站点使用2到4个表单之间的任意位置,最终结果是数百个相同的函数被重复执行,只是选择器中存在差异。所以我正试图重构我的代码,这样我就可以为每个站点上使用的每个表单使用一个函数

输入我的问题:我不知道如何让我的测试根据可能的元素列表检查页面上加载的元素的值。基本上我需要它做的是:

  • 打开页面
  • 根据我的列表检查元素(by.name('someName')
  • 找到匹配项后,将该匹配项用作someName的值
  • 向该值发送键('someValue')
  • 对表单上的所有字段重复此操作
我所拥有的:

我的规格:

这是我测试文件中的实际规范

    it('Checks for fieldName and then fills in the form', function(done) {
        cQualify();
        done();
    });
cQualify函数:

该函数存储在名为formFill.js的助手中

cQualify = function() {
    findElementByFieldName(cartData.fName).sendKeys('Jimmy');
    findElementByFieldName(cartData.cGender).sendKeys('Male');
    findElementByFieldName(cartData.cAge).sendKeys('34');
    findElementByFieldName(cartData.cZip).sendKeys('33071');
//more fields here and a submit button
};
findElementByFieldName函数:

此函数存储在名为ArrayLop.js的帮助程序中,是我最新尝试实现此功能的一次尝试。最初,这更符合以下内容:

    browser.driver.findElement(by.name('someName')).sendKeys('nameToSend');
//repeated for each field on the form
以下是函数:

    findElementByFieldName = function(fieldName) {
        if (fieldName.constructor === Array) {
            console.log('Array found, looping values for array: ' + fieldName);

            for(var i=0; i < fieldName.length; i++) {
                expect(element(by.name(fieldName[i])).isDisplayed()).toBe(true);
                console.log('Checking if page element ' + fieldName[i] + ' exists');
            } 
//some code that checks if the current value of fieldName[i] is in the page DOM
//and if so; returns that and exits the loop

        } else {
            return browser.driver.findElement(by.name(fieldName));
        }
    }
结果:

当我按原样运行此测试时,测试将遍历cartData.fName中包含的所有值,认为它们都已显示,然后在尝试使用以下内容发送密钥时失败:

Failed: Cannot read property 'sendKeys' of undefined
这就是我被卡住的地方。我不仅需要循环来检查数组中的值是否在页面上,还需要它在找到匹配项后停止循环并返回该值,以便我可以按照cQualify()函数中的方式使用它。我尝试了一些不同的方法,例如使用isDisplayed()在if内部,但这似乎只能与expect一起使用。我还尝试将我的规范放在函数内部,然后在测试中直接循环该函数-但这有类似的结果,也会破坏formFill.js的用途

更新:

我在上找到了另一个处理类似问题的问题:
接受答案的代码为:

var link = element.all(by.css('a')).reduce(function (result, elem, index) {
    if(result) return result;

    return elem.getText().then(function(text){
        if(text === "mylink") return elem;
    });

}).then(function(result){
    if(!result) throw new Error("Element not found");
    return result;
});

尽管我(到目前为止)还不知道如何调整它以满足我的需要。

您可以简单地构造一个带有多个or条件的动态XPath表达式,而不是使其更复杂。请看下面的示例代码

function getElement(nameList) {
    if(nameList.constructor != Array){
        nameList=[nameList]
    }

    var xpathExpression = ".//*["
    nameList.forEach(function(name,index){
        xpathExpression += "@name='"+name+"'";
            if(index != nameList.length-1){
                xpathExpression+=" or ";
            } else {
                xpathExpression+= "]";
            }
      });
   return element(by.xpath(xpathExpression));
}
因此,如果您想查找
fName:['cShipFname','zang_fName','fName']
,只需调用
getElement
,它就会根据匹配的XPath表达式返回web元素。
fName
的XPath表达式为


/*[@name='cShipFname'或@name='zang\u fname'或@name='fname']

您可以简单地构造一个具有多个or条件的动态XPath表达式,而不是使其更复杂。请看下面的示例代码

function getElement(nameList) {
    if(nameList.constructor != Array){
        nameList=[nameList]
    }

    var xpathExpression = ".//*["
    nameList.forEach(function(name,index){
        xpathExpression += "@name='"+name+"'";
            if(index != nameList.length-1){
                xpathExpression+=" or ";
            } else {
                xpathExpression+= "]";
            }
      });
   return element(by.xpath(xpathExpression));
}
因此,如果您想查找
fName:['cShipFname','zang_fName','fName']
,只需调用
getElement
,它就会根据匹配的XPath表达式返回web元素。
fName
的XPath表达式为


/*[@name='cShipFname'或@name='zang\u fname'或@name='fname']

虽然有人回答,但我并不真正喜欢XPath。因此,我想提供一种替代方法,使用
过滤器()
索引()
包含()

首先使用
indexOf()

这一次使用
includes()
,也会略有不同

function getElement(nameList) {
    //keeping it an array for all calls (thumbs up for this thought of @SudharsanSevaraj)
    if(nameList.constructor != Array){
        nameList=[nameList]
    }
    //selecting all elements with a name-attribute, 
    //then filter the one(s), that is/are present in nameList and use first
    return $$('[name]').filter(function(elem, index){
        return elem.getAttribute('name').then(function(elName){
            return nameList.includes(elName);
        });
    }).first();
};

虽然答案是肯定的,但我并不真正喜欢XPath。因此,我想提供另一种方法,使用
filter()
indexOf()
includes()

首先使用
indexOf()

这一次使用
includes()
,也会略有不同

function getElement(nameList) {
    //keeping it an array for all calls (thumbs up for this thought of @SudharsanSevaraj)
    if(nameList.constructor != Array){
        nameList=[nameList]
    }
    //selecting all elements with a name-attribute, 
    //then filter the one(s), that is/are present in nameList and use first
    return $$('[name]').filter(function(elem, index){
        return elem.getAttribute('name').then(function(elName){
            return nameList.includes(elName);
        });
    }).first();
};

太好了!这个很好用,非常感谢!太好了!这个很好用,非常感谢!