关于sendKeys 和e1 的简要说明
快速注意sendKeys 不返回 WebElement 或 ElementFinder。这意味着上例中的 e1 可能是未定义的。
陈旧元素和 DOM 变化
关于假设的快速说明:答案假设将文本发送到过滤器会改变屏幕上的行数或元素数。如果在您发送文本后屏幕上的元素数量相同,那么这将不起作用。我会看看下面 Florent 对过时参考错误的评论。
陈旧的元素通常在 DOM 发生变化时发生。如果你在 Angular 中使用一些结构性指令,如果你使用 *ngFor 或 *ngIf,DOM 将会改变。我的猜测是,在您过滤元素之后,您将在 DOM 根据您的过滤器实际更改期间或之前获取 DOM 中的元素。这将导致过时的引用 Web 元素。在下面的示例中,我使用 async / await 并关闭了控制流。
过滤期间的显式等待
您可以显式设置睡眠,以便在您调用单击第一个元素之前更新 DOM。这可能会导致潜在的不稳定测试,因为根据您将运行的环境,超时是未知的。
it('should do something', async () => {
const filterItem = element(by.id('FiltItemTransDocNo'));
await filterItem.sendKeys(grno);
await browser.sleep(1000); // or some other waits
await element.all(by.name('chkGrd')).first().click();
});
比较 element.all 的行
或者,您可以对点击前后的element.all 项目的数量进行比较检查,并仅在内容更新时继续。
it('should do something', async () => {
const filterItem = element(by.id('FiltItemTransDocNo'));
const table = element.all(by.name('chkGrd'));
const length = await table.count();
await filterItem.sendKeys(grno);
// After the filter keys are sent, check to see if the current table
// count is not equal to the `table.count()`.
let updated = false;
await browser.wait(async () => {
updated = length !== await table.count();
return updated;
}, 5000);
// So if we use the entire 5 seconds and the count has not changed,
// we should probably fail before clicking on stuff.
expect(updated).toBeTruthy();
// now we can click on the next element.
await element.all(by.name('chkGrd')).first().click();
});
为什么调用length !== await table.count() 有效?这是因为表格代表了获取 Web 元素的承诺。当您调用count 方法时,它首先通过解析Web 元素来执行操作。如果 DOM 发生变化,这可能会有所不同。然后,我们将当前计数与前一个计数进行比较。
确保您使用的是 async / await
在您的配置文件中,您需要指定您已脱离控制流:
exports.config = {
// In this case, I plan to use a selenium standalone server
// at http://127.0.0.1:4444/wd/hub. You could also use other
// methods like direct connect or starting it up with 'local'.
seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
// Required flag to tell Protractor you do not want to use the
// control flow. This means that you will have to either chain
// your promises or async / await your actions. Historically
// jasminewd node module would resolve promises for you. This
// package will no longer be used in future releases since the
// control flow is deprecated.
SELENIUM_PROMISE_MANAGER: false,
// The rest of your config...
}
希望对您有所帮助。