You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 18:10:31