如何用Playwright测试可关闭按钮的点击事件取消逻辑
问题
我正在开发一个可关闭按钮组件,核心逻辑是:点击组件内的关闭图标时,会先触发click事件,随后触发自定义myClose事件;若click事件被取消,则myClose事件不会触发,组件也不会从DOM中移除。
我想用Playwright E2E测试验证「除非click事件被取消,否则组件会被移除」的逻辑,但目前测试失败——因为我还没实现测试中取消click事件的逻辑。以下是我的测试代码:
test(`myTest`, async ({ page }) => { const content = <my-button text="Button" type="closable" ></my-button> await setupPage(page, { content, addBrandFont: true }) await page.evaluate(() => { const closableButton = document.querySelector('.my-button[type="closable"]') closableButton?.dispatchEvent( new CustomEvent('myClose', { cancelable: true }), ) }) await page.locator('css=my-button[type="closable"] .my-icon').click() await page.waitForSelector('.my-button[type="closable"]', { state: 'detached', timeout: 2000, }) const closableButton = page.locator('my-button[type="closable"]') const myCloseSpy = await closableButton.spyOnEvent('myClose') expect(myCloseSpy).toHaveReceivedEventTimes(0) const isClosableButtonVisible = await page.isVisible( 'my-button[type="closable"]', ) expect(isClosableButtonVisible).toBeTruthy() })
解决方案
要在测试中取消click事件,你需要在页面上下文里给关闭图标绑定一个click事件监听器,通过调用event.preventDefault()(或根据组件逻辑使用event.stopPropagation()/event.stopImmediatePropagation())来取消事件,阻止后续的myClose触发和组件移除逻辑。
同时需要调整测试流程的顺序,确保事件监听在点击前设置,断言逻辑符合预期:
test(`cancel click prevents component removal`, async ({ page }) => { const content = <my-button text="Button" type="closable" ></my-button> await setupPage(page, { content, addBrandFont: true }) // 1. 给关闭图标添加click事件监听器,取消事件 await page.evaluate(() => { const closeIcon = document.querySelector('my-button[type="closable"] .my-icon'); if (closeIcon) { // 绑定一次性监听器,避免影响其他测试 closeIcon.addEventListener('click', (e) => { e.preventDefault(); // 取消click事件,根据组件逻辑调整为对应取消方式 }, { once: true }); } }); // 2. 监听myClose事件 const closableButton = page.locator('my-button[type="closable"]'); const myCloseSpy = await closableButton.spyOnEvent('myClose'); // 3. 点击关闭图标 await page.locator('my-button[type="closable"] .my-icon').click(); // 4. 断言组件仍然可见 const isVisible = await closableButton.isVisible(); expect(isVisible).toBeTruthy(); // 5. 断言myClose事件未触发 expect(myCloseSpy).toHaveReceivedEventTimes(0); })
关键说明
- 使用
page.evaluate()进入浏览器上下文,直接操作DOM元素绑定事件监听器 - 监听器添加
{ once: true }选项,确保只生效一次,避免干扰其他测试用例 - 调整测试步骤顺序:先设置事件取消逻辑,再监听自定义事件,最后执行点击并断言
- 如果你的组件是通过判断
event.defaultPrevented来决定是否触发myClose,则使用e.preventDefault();如果是通过阻止事件冒泡来控制,则改用e.stopPropagation()
内容的提问来源于stack exchange,提问作者Takoua
相关产品推荐
相关产品推荐

