我正在使用 jasmine/protractor 针对我公司管理的多个站点运行测试套件。 (这些网站是订单/结帐网站)目前,我为每个网站设置了一个单独的测试套件,该套件使用我创建并存储在帮助程序内部的函数来填写每个表单,以便我可以在我的规范,并运行订单流程来下测试订单,这目前有效,并且对助手的调用可以顺利完成。
Protractor :v5.1.2
Jasmine :v2.6
节点:v8.0.0
这里的问题是,每个站点倾向于对给定表单中的每个字段使用任意数量的字段标识符,并且我最终为特定站点上的特定表单编写了特定函数。每个站点使用 2 到 4 种表单,最终结果是重复数百个相同的功能,仅在选择器中有所不同。因此,我尝试重构我的代码,以便我可以为每个站点上使用的每种表单提供一个函数。
输入我的问题:我无法弄清楚如何让我的测试根据可能的元素列表检查页面上加载的元素的值。基本上我需要它做的是:
- 打开页面
- 根据我拥有的列表检查 element(by.name('someName')
- 找到匹配项后,将匹配项用作 someName 的值
- sendKeys('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 函数:
此函数存储在名为 arrayLoop.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));
}
}
可能的元素列表:
可能的元素存储在名为 formData.js 的帮助程序内(注意:只有具有多个可能值的元素才会存储在数组中;其他元素我没有遇到问题)
cartData = {
fName: ['cShipFname', 'zang_fname', 'fname'],
lName: ['cShipLname', 'zang_lname', 'lname'],
cZip: ['cShipZip', 'zang_zip', 'zip'],
cGender: 'zang_gender',
cAge: 'zang_age',
cProblem: 'zang_problem'
//lots of additional values here
};
结果:
当我按原样运行时,测试循环遍历 cartData.fName 中包含的所有值,认为它们全部显示,然后在尝试使用以下方式发送Keys 时失败:
Failed: Cannot read property 'sendKeys' of undefined
所以这就是我陷入困境的地方。我不仅需要循环来检查数组中的值是否在页面上,还需要它在找到匹配项后停止循环并返回,以便我可以按照 cQualify() 中的布局方式使用它功能。我尝试了一些不同的方法,例如在 if 内部使用 isDisplayed() ,但似乎这只能与 Expect 一起使用。我还尝试将我的规范放入函数中,然后直接在测试中循环该函数 - 但这具有类似的结果,并且也会破坏 formFill.js 的目的
更新:
我在 SO 上发现了另一个处理类似问题的问题:here
已接受答案的代码是:
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_fname' 或 @name='fname']
关于javascript - 检查数组中的任何值是否与 dom 中的元素匹配,然后将键发送到 Protractor 中的该元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46592444/