WebdriverIO元素数组迭代及逻辑封装问题求助
WebdriverIO元素数组迭代与封装问题解决
问题背景
无法迭代WebdriverIO返回的元素数组,希望将数组元素作为参数传递给后续函数,点击符合条件的元素。
报错代码(控制台提示:Can't call $ on element with selector "ng-drop-panel" because element wan't found)
let element = $$('ng-select'); for await (const item of element[0].$('ng-dropdown-panel').$('div').$$('div')[1].$$('div')) { if( await item.getText() == Field.CODE){ item.click(); break; } }
可正常运行但无法复用的代码
let element = $$('ng-select')[0]; for await (const item of element.$('ng-dropdown-panel').$('div').$$('div')[1].$$('div')) { if( await item.getText() == Field.CODE){ item.click(); break; } }
封装失败的尝试代码
public async formFilling(){ let element = $$('ng-select'); await this.selectValueInDropDown(element[0].$('ng-dropdown-panel').$('div').$$('div')[1].$$('div'), "ADD"); } public async selectValueInDropDown(dropDownSelector:any, dropDownValue: string){ for await (const item of dropDownSelector) { if( await item.getText() == dropDownValue){ item.click(); break; } } }
问题原因
WebdriverIO的元素定位操作是异步的,直接链式传递element[0].$('xxx').$$('xxx')这类表达式时,传递的是未完成的Promise/定位器对象,而非实际的元素数组。迭代时会因元素未完成定位触发报错,或无法正确遍历元素。
另外第一段代码报错的核心是:element[0]未等待定位完成就直接调用$('ng-dropdown-panel'),此时元素可能还未被找到,导致后续定位失败。
解决方案
方案1:先等待元素定位完成,再传递实际元素数组
先通过await拿到所有子元素的实际数组,再传入封装函数:
public async formFilling(){ // 等待ng-select元素定位完成 const selectElement = await $$('ng-select')[0]; // 等待所有下拉选项元素定位完成,拿到实际元素数组 const dropDownItems = await selectElement.$('ng-dropdown-panel').$('div').$$('div')[1].$$('div'); await this.selectValueInDropDown(dropDownItems, "ADD"); } public async selectValueInDropDown(dropDownItems: WebdriverIO.Element[], dropDownValue: string){ for (const item of dropDownItems) { const itemText = await item.getText(); if(itemText === dropDownValue){ await item.click(); break; } } }
方案2:传递父元素,在封装函数内完成子元素定位
更可靠的方式是把父元素(如ng-select)传入函数,在函数内部完成子元素的定位,确保所有异步操作都在函数内处理:
public async formFilling(){ const selectElement = await $$('ng-select')[0]; await this.selectValueInDropDown(selectElement, "ADD"); } public async selectValueInDropDown(parentElement: WebdriverIO.Element, dropDownValue: string){ // 在函数内完成下拉选项的定位,确保异步操作完成 const dropDownItems = await parentElement.$('ng-dropdown-panel').$('div').$$('div')[1].$$('div'); for (const item of dropDownItems) { const itemText = await item.getText(); if(itemText === dropDownValue){ await item.click(); break; } } }
补充说明
WebdriverIO的$$()返回的ElementArray支持异步迭代(for await...of),但直接传递未完成定位的ElementArray到其他函数时,可能因上下文问题导致迭代异常。通过await提前获取元素数组,或在函数内统一处理定位,能避免这类问题。
内容的提问来源于stack exchange,提问作者Alex Rodriguez
相关产品推荐
相关产品推荐

