如何在CucumberJS/Puppeteer中验证选择器不存在及使用cucumber-assert的throws断言?
验证元素不存在的CucumberJS + Puppeteer解决方案
嘿,针对你在Ember前端自动化测试里遇到的「验证元素不存在」的问题,我来帮你理清楚解决方案和逻辑哈。
为什么你用assert.throws的方式不顺畅?
你之前尝试用cucumber-assert的throws方法来捕获page.waitForSelector的错误,但这里有个核心问题:page.waitForSelector是异步返回Promise的,而assert.throws默认是用来捕获同步代码的异常。你直接传await page.waitForSelector(...)的话,其实已经把Promise的结果解析出来了,根本没法正确捕获它的reject状态。而且你写的回调里也没明确返回断言结果,这就导致整个断言逻辑是不完整的。
你找到的替代方案解析
你后来用page.$的方案是完全可行的,我帮你拆解下逻辑:
if (await page.$('[data-test-text-title-import-payment-file-widget-console="true"]') === null) { return Promise.resolve(); } return Promise.reject('Error: The widget is present');
page.$是Puppeteer中用于查找单个元素的API,找不到元素时会直接返回null,不会像waitForSelector那样抛出超时错误- 当元素不存在(返回
null)时,返回Promise.resolve()表示测试断言通过 - 如果元素存在,就返回
Promise.reject()并带上错误信息,这样Cucumber会自动把这个测试场景标记为失败,完全符合我们的预期
更贴合cucumber-assert的优化写法
如果你还是想结合cucumber-assert来编写断言,其实可以用它的assert.notOk方法,配合page.$的结果,代码会更简洁直观:
const assert = require('cucumber-assert'); const element = await page.$('[data-test-text-title-import-payment-file-widget-console="true"]'); return assert.notOk(element, 'Error: The widget should not be present');
assert.notOk会检查第一个参数是否为假值(比如null),如果是则断言通过,否则抛出第二个参数的错误信息,完美适配我们验证元素不存在的场景。
补充:用waitForSelector实现的另一种思路
如果你一定要用waitForSelector来实现验证元素不存在,可以利用它的timeout参数和catch方法捕获超时错误,不过这种写法不如page.$直接:
try { // 设置一个较短的超时时间,比如3秒 await page.waitForSelector('[data-test-text-title-import-payment-file-widget-console="true"]', { timeout: 3000 }); // 如果走到这里,说明元素存在,抛出错误 return Promise.reject('Error: The widget is present'); } catch (err) { // 捕获到超时错误,说明元素不存在,断言通过 return Promise.resolve(); }
不过要注意,这里要确保捕获到的超时错误确实是因为元素不存在导致的,而不是页面加载缓慢等其他问题。
内容的提问来源于stack exchange,提问作者Huckleberry Carignan
相关产品推荐
相关产品推荐

