我们的网络应用程序有各种html表单,每个表单都包含一个表单字段列表。使用Protractor,我正在寻找一种方法来检索表单字段列表:字段标签,输入类型(文本框,选择,无线电等...)和输入控件(稍后用于设置值)。然后,我想动态地为表单中的字段填充某些值。
以下是表单字段标签的定义以及我想要设置的值:
this.fields = {
'Listing Agent': 1,
'Property Class': 1,
'Property Type': 2,
'Transaction Type': 'Sale',
'Ownership Terms': 'Sole Ownership',
'Listing Agreement': 'Yes',
'Display Listing on Internet': 'Yes',
'Display Address on Internet': 'Yes',
'Allow Automated Valuation on Internet': 'Yes',
'Allow Public Comment/Reviews on Internet': 'Yes'
};
然后我通过标签文本检索与这些字段名称匹配的元素:
this.elements = form.find.allElements(this.fields);
调用该方法时,它会检索正确的元素,但是我在设置每个字段的输入类型时遇到问题。检查字段的输入类型会返回一个promise而不是实际值,所以我无法弄清楚如何检索每个元素的输入类型,然后返回所有元素的数组。
this.find = {
allElements: function (fields) {
var items = [];
for (var key in fields) {
var el = element(by.cssContainingText('.sheet-grid-row', key));
this.getElementType(el).then(function (type) {
var item = {
type: type,
label: key,
isRequired: false,// TODO: el.getAttribute('class').indexOf('is-required-field') > -1
input: this.getElementInput(el, type)
};
items.push(item);
});
}
return items;// TODO: Doesn't work, of course...
},
getElementType: function (el) {
var deferred = protractor.promise.defer();
el.element(by.css('select')).isPresent().then(function (exists) {
if (exists)
deferred.fulfill(self.inputTypes.select);
else {
el.element(by.css('input[type="text"]')).isPresent().then(function (exists) {
if (exists)
deferred.fulfill(self.inputTypes.textbox);
else {
el.element(by.css('input[type="radio"]')).isPresent().then(function (exists) {
if (exists)
deferred.fulfill(self.inputTypes.textbox);
else
deferred.fulfill(self.inputTypes.unknown);
});
}
});
}
});
return deferred.promise;
},
getElementInput: function (el, type) {
switch (type) {
case self.inputTypes.select:
return new SelectWrapper(el.element(by.css('select')));
break;
case self.inputTypes.textbox:
return el.element(by.css('input[type="text"]'));
break;
case self.inputTypes.radio:
return el.element(by.css('input[type="radio"]'));
break;
}
return null;
}
};
此时,我希望我能够获得本机DOM元素,而不是处理承诺。有没有办法完成我追求的目标?
答案 0 :(得分:0)
您正在尝试在同步循环element.isPresent()
内执行异步操作for
。您希望allElements
函数看起来更像这样:
this.find = {
allElements: function (fields) {
var self = this;
var items = [];
var getItems = function(inputArray, currentIndex, outputArray) {
outputArray = outputArray || [];
currentIndex = currentIndex || 0;
var key = inputArray[currentIndex];
if (key) {
var el = element(by.cssContainingText('.sheet-grid-row', key));
return self.getElementType(el).then(function(type) {
var item = {
type: type,
label: key,
isRequired: false,// TODO: el.getAttribute('class').indexOf('is-required-field') > -1
input: self.getElementInput(el, type)
};
outputArray.push(item);
}).then(function() {
return getItems(inputArray, currentIndex + 1, outputArray);
});
} else {
return Promise.resolve(outputArray);
}
};
return getItems(Object.keys(fields));
},
getElementType: function (el) {
var self = this;
return el.element(by.css('select')).isPresent().then(function(exists) {
if (exists) {
return self.inputTypes.select;
} else {
return el.element(by.css('input[type="text"]')).isPresent().then(function(exists) {
if (exists) {
return self.inputTypes.textbox;
} else {
return el.element(by.css('input[type="radio"]')).isPresent().then(function(exists) {
if (exists) {
return self.inputTypes.radio;
} else {
return self.inputTypes.unknown;
}
});
}
});
}
});
},
getElementInput: function (el, type) {
switch (type) {
case self.inputTypes.select:
return new SelectWrapper(el.element(by.css('select')));
break;
case self.inputTypes.textbox:
return el.element(by.css('input[type="text"]'));
break;
case self.inputTypes.radio:
return el.element(by.css('input[type="radio"]'));
break;
}
return null;
}
};
请记住,find.allElements
的输出现在应该是一个承诺,因此它的用法如下:
this.find.allElements(this.fields).then(function(items) {
console.log('this is an array of my ' + items.length + ' items');
});