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

Playwright测试中page.waitForResponse偶发超时问题排查求助

Playwright测试中Media Size API偶发超时问题排查与解决

测试代码

import { expect, test } from "@playwright/test";
test.describe.configure({ mode: "serial" });

test.describe("Dashboard", () => {
  let sellerId: string;
  let userId: string;

  test.beforeEach(async ({ page }) => {
    await page.goto("https://ic.ewalls.io/");
    await page.getByPlaceholder("Enter your email").click();
    await page
      .getByPlaceholder("Enter your email")
      .fill("sridhar.fullstack.dev.india@gmail.com");
    await page.getByPlaceholder("Enter your password").click();
    await page.getByPlaceholder("Enter your password").fill("Qq1!Qq1!");
    await page.getByLabel("Show password").click();
    await page.getByRole("button", { name: "Sign in" }).click();

    const loginResponse = await page.waitForResponse(
      (response) =>
        response.url().includes("/dev/api/v1/user/getroutes") &&
        response.status() === 200
    );

    const loginJsonResponse = await loginResponse.json();
    sellerId = loginJsonResponse.user.sellerId;
    userId = loginJsonResponse.user.userId;

    expect(sellerId).toBeTruthy();
    expect(userId).toBeTruthy();

    console.log("\x1b[36m%s\x1b[0m", `SellerId: ${sellerId}`);
    console.log("\x1b[36m%s\x1b[0m", `UserId: ${userId}`);

    console.log("\x1b[34m%s\x1b[0m", "Login Passed ✓");
  });

  test("Media Size Test", async ({ page }) => {
    console.log("\x1b[36mRunning Media Size test [*]\x1b[0m");

    const mediaSizeResponsePromise = page.waitForResponse(
      (response) =>
        response.url().includes(`dev/api/v1/dashboard/mediasize/${sellerId}`) &&
        response.status() === 200,
      { timeout: 50000 }
    );

    const mediaSizeResponse = await mediaSizeResponsePromise;
    const mediaSizeResponseBody = await mediaSizeResponse.json();

    console.log(
      "Dashboard Media Size API Response:",
      JSON.stringify(mediaSizeResponseBody, null, 2)
    );

    const totalMediaSize = mediaSizeResponseBody.totalMediaSize.toFixed(3);
    const mediaSizeInMB = `${totalMediaSize}MB`;

    await page.getByRole("heading", { name: mediaSizeInMB }).click();
    console.log(`Clicked on media size: ${mediaSizeInMB}`);

    console.log("\x1b[34m%s\x1b[0m", "Media Size checked in UI ✓");
  });
});

报错信息

Running Media Size test [*]

1) [Google Chrome] › eWalls.test.ts:129:7 › Dashboard › Media Size Test ──────────────────────────

   TimeoutError: page.waitForResponse: Timeout 50000ms exceeded while waiting for event "response"

   130 |     console.log("\\x1b\[36mRunning Media Size test \[\*\]\\x1b\[0m");
   131 |

   > 132 |     const mediaSizeResponsePromise = page.waitForResponse(
   > |                                           ^
   > 133 |       (response) =>
   > 134 |         response.url().includes(`dev/api/v1/dashboard/mediasize/${sellerId}`) &&
   > 135 |         response.status() === 200,

        at /home/sridhar/Desktop/Sridhar/iris_frontend-Development/playwright/test/eWalls.test.ts:132:43

1 failed
[Google Chrome] › eWalls.test.ts:129:7 › Dashboard › Media Size Test ───────────────────────────
21 skipped
3 passed (1.7m)

原因分析

  • API请求未触发:测试代码中创建waitForResponse Promise后,没有执行导航或UI操作加载Dashboard页面,导致Media Size API根本未被调用,自然等待超时。
  • URL匹配不精准:用includes("dev/api/v1/...")匹配时缺少前缀/,可能无法匹配实际完整请求URL,或误匹配无关请求。
  • 测试环境响应不稳定:生产环境正常但测试环境偶发超时,说明测试环境API服务或网络存在波动,响应延迟超过设置的50s。
  • 未处理非200响应:如果API返回4xx/5xx状态码,当前匹配条件会忽略该响应,导致测试一直等待200响应而超时。

解决方案

1. 先触发API请求再等待响应

创建waitForResponse Promise后,执行触发Dashboard加载的操作,确保API被调用:

test("Media Size Test", async ({ page }) => {
  console.log("\x1b[36mRunning Media Size test [*]\x1b[0m");

  // 导航到Dashboard页面,触发Media Size API请求
  await page.goto("https://ic.ewalls.io/dashboard"); 

  const mediaSizeResponsePromise = page.waitForResponse(
    (response) =>
      response.url().includes(`/dev/api/v1/dashboard/mediasize/${sellerId}`) &&
      response.status() === 200,
    { timeout: 50000 }
  );

  const mediaSizeResponse = await mediaSizeResponsePromise;
  // 后续代码不变
});

若API在特定元素加载后触发,可先等待元素出现:

await page.waitForSelector('[data-testid="media-size-section"]'); // 替换为实际元素选择器

2. 优化URL匹配逻辑

用更精准的匹配方式避免误匹配:

  • 增加前缀/确保路径正确:
    response.url().includes(`/dev/api/v1/dashboard/mediasize/${sellerId}`)
    
  • 用正则匹配完整路径结尾:
    response.url().match(new RegExp(`/dev/api/v1/dashboard/mediasize/${sellerId}$`))
    
  • 直接匹配完整URL(域名固定时):
    response.url() === `https://ic.ewalls.io/dev/api/v1/dashboard/mediasize/${sellerId}`
    

3. 增加重试机制

针对测试环境波动,给测试添加重试配置:

// 单个测试重试2次
test("Media Size Test", async ({ page }) => { /* ... */ }).retry(2);

// 或在playwright.config.ts全局配置
export default defineConfig({
  testDir: './tests',
  retries: 2,
});

4. 排查非200响应

临时添加日志,查看所有匹配URL的响应状态:

const mediaSizeResponsePromise = page.waitForResponse(
  (response) => {
    const isTargetUrl = response.url().includes(`/dev/api/v1/dashboard/mediasize/${sellerId}`);
    if (isTargetUrl) {
      console.log(`Media Size API响应状态: ${response.status()},URL: ${response.url()}`);
    }
    return isTargetUrl && response.status() === 200;
  },
  { timeout: 50000 }
);

5. 延长超时时间(备选)

确认测试环境响应慢时,可临时加大超时:

{ timeout: 60000 } // 60秒

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 10:36:02