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

Playwright无法打开下拉菜单并点击内部链接问题求助

问题描述

使用Playwright做自动化测试时,打不开导航栏下拉菜单并点击其中的"Dropdown Link 1"链接。正常点击或悬停带"Header Link"的a标签就能展开下拉菜单,但测试时系统一直提示目标链接不可见。哪怕用--headed模式运行,下拉菜单也只是一闪而过,加固定延时也没用。

页面HTML结构:

<nav class="main-navigation">
    <ul class="main-navigation__list">
        <li class="main-navigation__item main-navigation__item--has-child">
            <a class="main-navigation__link " href="/somewhere" aria-haspopup="true" aria-expanded="false">
                Header Link
            </a>
            <div class="sub-navigation">
                <ul class="sub-navigation__list sub-navigation__list--parent">
                    <li class="sub-navigation__item">
                        <p>Some text here...</p>
                        <ul class="sub-navigation__list sub-navigation__list--child">
                            <li class="sub-navigation__item">
                                <a class="sub-navigation__link" href="/somewhere/link_1">Dropdown Link 1</a>
                            </li>
                            <li class="sub-navigation__item"></li>
                            <li class="sub-navigation__item"></li>
                            <li class="sub-navigation__item"></li>
                        </ul>
                    </li>
                    <li class="sub-navigation__item"></li>
                </ul>
            </div>
        </li>
    </ul>
</nav>

尝试过的代码片段:

test("Example", async () => {
    // When trying one of these solution, playwright can't find the element.
    // await this.page.getByRole("link", { name: "Header Link"}).click();
    // await this.page.getByRole("link", { name: "Header Link"}).hover();

    // This locator works...
    const top_link = this.page.locator('.main-navigation >> .main-navigation__list >> li >> a:has-text("Header Link")');
    await expect(top_link).toBeVisible();
    await top_link.click()
    // Try to click on the now visible - if it would work - link inside the dropdown
    // ...
});

报错日志:

Call log:
    - waiting for locator('.main-navigation').locator('.main-navigation__list').locator('li').locator('a:has-text("Header Link")')
    - locator resolved to <a aria-haspopup="true" aria-expanded="false" href=…>…</a>
    - attempting click action
    - waiting for element to be visible, enabled and stable
    - element is visible, enabled and stable
    - scrolling into view if needed
解决思路及方案

1. 阻止Header Link的默认跳转

Header Link自带href="/somewhere",点击后会触发页面跳转,导致下拉菜单刚展开就被刷新覆盖。点击时要阻止默认事件:

test("Example", async () => {
    const topLink = this.page.getByRole("link", { name: "Header Link" });
    await topLink.click({ preventDefault: true }); // 阻止页面跳转
    // 等待下拉菜单里的目标链接可见
    const dropdownLink = this.page.getByRole("link", { name: "Dropdown Link 1" });
    await dropdownLink.waitFor({ state: "visible" });
    await dropdownLink.click();
});

2. 用hover触发下拉菜单

不少导航栏的下拉菜单是靠hover事件触发的,不是点击。试试用hover操作:

test("Example", async () => {
    const topLink = this.page.getByRole("link", { name: "Header Link" });
    await topLink.hover();
    // 等待子菜单容器可见
    await this.page.locator(".sub-navigation").waitFor({ state: "visible" });
    const dropdownLink = this.page.getByRole("link", { name: "Dropdown Link 1" });
    await dropdownLink.click();
});

3. 显式等待目标链接可见

下拉菜单的动画可能导致元素延迟出现,别用固定延时,显式等目标链接处于可见状态:

test("Example", async () => {
    const topLink = this.page.locator('.main-navigation__link:has-text("Header Link")');
    await topLink.click({ preventDefault: true });
    // 延长超时时间等待目标链接出现
    const dropdownLink = this.page.locator('.sub-navigation__link:has-text("Dropdown Link 1")');
    await expect(dropdownLink).toBeVisible({ timeout: 5000 });
    await dropdownLink.click();
});

4. 模拟真实用户的鼠标操作

通过完整的鼠标移动、悬停流程,贴近真实用户行为:

test("Example", async () => {
    const topLink = this.page.getByRole("link", { name: "Header Link" });
    // 把鼠标移到元素中心位置
    const box = await topLink.boundingBox();
    await this.page.mouse.move(box.x + box.width/2, box.y + box.height/2);
    await this.page.waitForTimeout(300); // 等动画跑完
    const dropdownLink = this.page.getByRole("link", { name: "Dropdown Link 1" });
    await dropdownLink.click();
});

5. 排查页面干扰因素

  • 确认测试过程中没有弹窗、遮罩层弹出遮挡下拉菜单
  • 检查导航栏的JS事件绑定,确认下拉菜单是click还是mouseenter/hover触发的

内容的提问来源于stack exchange,提问作者finethen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 03:10:56