Repository: apache/airflow
File: airflow-core/src/airflow/ui/tests/e2e/specs/asset.spec.ts (TypeScript)

Code before:
      .poll(
        async () => {
          const row = page.locator("tbody tr").first();

          if (!(await row.isVisible().catch(() => false))) {
            return "loading";
          }

          const text = (await row.textContent())?.toLowerCase().trim() ?? "";

          if (text.includes("success")) return "success";
          if (text.includes("failed")) return "failed";
          if (text.includes("running")) return "running";

          return "loading";
        },
        {
          intervals: [3000],
          timeout: 30_000,
        },
      )
      .toBe("success");

    await page.close();
  });

  test.beforeEach(async ({ page }) => {
    assets = new AssetListPage(page);
    await assets.navigate();
    await assets.waitForLoad();
  });

  test("verify assets page heading", async () => {
    await expect(assets.heading).toBeVisible();
  });

  test("verify assets table", async () => {
    await expect(assets.table).toBeVisible();
  });

  test("verify asset rows when data exists", async () => {
    const count = await assets.assetCount();

    expect(count).toBeGreaterThanOrEqual(0);
  });

  test("verify asset has a visible name link", async () => {
    const names = await assets.assetNames();

    for (const name of names) {
      expect(name.trim().length).toBeGreaterThan(0);

Review comment (security):
```suggestion
test.beforeAll(async ({ browser }) => {
  test.setTimeout(3 * 60 * 1000);

  const context = await browser.newContext({ storageState: AUTH_FILE });
  const page = await context.newPage();
  const dagsPage = new DagsPage(page);

  await dagsPage.triggerDag("asset_produces_1");

  await expect
    .poll(
      async () => {
        const response = await page.request.get(
          `/api/v2/dags/asset_produces_1/dagRuns?order_by=-start_date&limit=1`
        );
        const data = await response.json();
        return data.dag_runs?.[0]?.state ?? "pending";
      },
      { intervals: [2000], timeout: 120_000 }
    )
    .toBe("success");

  await context.close();
});
```

Code after:
  });

  test("verify clicking an asset navigates to detail page", async ({ page }) => {
    const name = await assets.openFirstAsset();

    await expect(page).toHaveURL(/\/assets\/.+/);
    await expect(page.getByRole("heading", { name: new RegExp(name, "i") })).toBeVisible();
  });

  test("verify assets using search", async () => {
    const initialCount = await assets.assetCount();

    expect(initialCount).toBeGreaterThan(0);

    const searchTerm = "s3://dag1/output_1.txt";

    await assets.searchInput.fill(searchTerm);

    // Wait for filtered results - count should decrease OR stay same if search matches all
    await expect
      .poll(
        async () => {
          const links = await assets.rows.locator("td a").allTextContents();

          // Return true when we have results that match the search
          return (
            links.length > 0 && links.every((name) => name.toLowerCase().includes(searchTerm.toLowerCase()))
          );
        },
        { intervals: [500], timeout: 30_000 },
      )
      .toBe(true);

    const names = await assets.assetNames();

    expect(names.length).toBeGreaterThan(0);

    for (const name of names) {
      expect(name.toLowerCase()).toContain(searchTerm.toLowerCase());
    }
  });

  test("verify pagination controls navigate between pages", async () => {
    await assets.navigateTo("/assets?limit=5&offset=0");
    await assets.waitForLoad();

    const page1Initial = await assets.assetNames();

    expect(page1Initial.length).toBeGreaterThan(0);

    const pagination = assets.page.locator('[data-scope="pagination"]');