This is an automated email from the ASF dual-hosted git repository.

choo121600 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 30a9509a888 feat: Improve Playwright test patterns in 
dag-runs-tab.spec.ts (#63189)
30a9509a888 is described below

commit 30a9509a8881a2e9fc761ca15b59fd3c203e4f60
Author: Desel72 <[email protected]>
AuthorDate: Wed Mar 11 23:06:08 2026 -0500

    feat: Improve Playwright test patterns in dag-runs-tab.spec.ts (#63189)
    
    * feat: Improve Playwright test patterns in dag-runs-tab.spec.t
    
    * Check CI test
    
    * remove package-lock
    
    * Fix Prettier formatting in navigateToDag
---
 .../airflow/ui/tests/e2e/pages/DagRunsTabPage.ts   | 55 +++++++++++++---------
 .../ui/tests/e2e/specs/dag-runs-tab.spec.ts        |  2 +-
 2 files changed, 33 insertions(+), 24 deletions(-)

diff --git a/airflow-core/src/airflow/ui/tests/e2e/pages/DagRunsTabPage.ts 
b/airflow-core/src/airflow/ui/tests/e2e/pages/DagRunsTabPage.ts
index f89130f0a20..61360f923e5 100644
--- a/airflow-core/src/airflow/ui/tests/e2e/pages/DagRunsTabPage.ts
+++ b/airflow-core/src/airflow/ui/tests/e2e/pages/DagRunsTabPage.ts
@@ -27,27 +27,31 @@ export class DagRunsTabPage extends BasePage {
 
   public constructor(page: Page) {
     super(page);
-    this.markRunAsButton = 
page.locator('[data-testid="mark-run-as-button"]').first();
-    this.runsTable = page.locator('[data-testid="table-list"]');
-    this.tableRows = this.runsTable.locator("tbody tr");
-    this.triggerButton = page.locator('[data-testid="trigger-dag-button"]');
+    this.markRunAsButton = page.getByTestId("mark-run-as-button").first();
+    this.runsTable = page.getByTestId("table-list");
+    this.tableRows = this.runsTable.locator("tbody").getByRole("row");
+    this.triggerButton = page.getByTestId("trigger-dag-button");
+  }
+
+  private static escapeRegExp(value: string): string {
+    return value.replaceAll(/[$()*+.?[\\\]^{|}]/g, "\\$&");
   }
 
   public async clickRunAndVerifyDetails(): Promise<void> {
-    const firstRunLink = 
this.tableRows.first().locator("a[href*='/runs/']").first();
+    const firstRunLink = this.tableRows.first().getByRole("link").first();
 
     await expect(firstRunLink).toBeVisible({ timeout: 10_000 });
     await firstRunLink.click();
-    await this.page.waitForURL(/.*\/dags\/.*\/runs\/[^/]+$/, { timeout: 15_000 
});
+    await expect(this.page).toHaveURL(/.*\/dags\/.*\/runs\/[^/]+$/, { timeout: 
15_000 });
     await expect(this.markRunAsButton).toBeVisible({ timeout: 10_000 });
   }
 
   public async clickRunsTab(): Promise<void> {
-    const runsTab = this.page.locator('a[href$="/runs"]');
+    const runsTab = this.page.getByRole("link", { exact: true, name: "Runs" });
 
     await expect(runsTab).toBeVisible({ timeout: 10_000 });
     await runsTab.click();
-    await this.page.waitForURL(/.*\/dags\/[^/]+\/runs/, { timeout: 15_000 });
+    await expect(this.page).toHaveURL(/.*\/dags\/[^/]+\/runs/, { timeout: 
15_000 });
     await this.waitForRunsTableToLoad();
   }
 
@@ -56,12 +60,12 @@ export class DagRunsTabPage extends BasePage {
 
     currentUrl.searchParams.set("state", state.toLowerCase());
     await this.navigateTo(currentUrl.pathname + currentUrl.search);
-    await this.page.waitForURL(/.*state=.*/, { timeout: 15_000 });
+    await expect(this.page).toHaveURL(/.*state=.*/, { timeout: 15_000 });
     await this.waitForRunsTableToLoad();
   }
 
   public async markRunAs(state: "failed" | "success"): Promise<void> {
-    const stateBadge = 
this.page.locator('[data-testid="state-badge"]').first();
+    const stateBadge = this.page.getByTestId("state-badge").first();
 
     await expect(stateBadge).toBeVisible({ timeout: 10_000 });
     const currentState = await stateBadge.textContent();
@@ -73,7 +77,7 @@ export class DagRunsTabPage extends BasePage {
     await expect(this.markRunAsButton).toBeVisible({ timeout: 10_000 });
     await this.markRunAsButton.click();
 
-    const stateOption = 
this.page.locator(`[data-testid="mark-run-as-${state}"]`);
+    const stateOption = this.page.getByTestId(`mark-run-as-${state}`);
 
     await expect(stateOption).toBeVisible({ timeout: 5000 });
     await stateOption.click();
@@ -95,13 +99,18 @@ export class DagRunsTabPage extends BasePage {
 
   public async navigateToDag(dagId: string): Promise<void> {
     await this.navigateTo(`/dags/${dagId}`);
-    await this.page.waitForURL(`**/dags/${dagId}**`, { timeout: 15_000 });
+    await expect(this.page).toHaveURL(new 
RegExp(`/dags/${DagRunsTabPage.escapeRegExp(dagId)}`), {
+      timeout: 15_000,
+    });
     await expect(this.triggerButton).toBeVisible({ timeout: 10_000 });
   }
 
   public async navigateToRunDetails(dagId: string, runId: string): 
Promise<void> {
     await this.navigateTo(`/dags/${dagId}/runs/${runId}`);
-    await this.page.waitForURL(`**/dags/${dagId}/runs/${runId}**`, { timeout: 
15_000 });
+    await expect(this.page).toHaveURL(
+      new 
RegExp(`/dags/${DagRunsTabPage.escapeRegExp(dagId)}/runs/${DagRunsTabPage.escapeRegExp(runId)}`),
+      { timeout: 15_000 },
+    );
     await expect(this.markRunAsButton).toBeVisible({ timeout: 15_000 });
   }
 
@@ -110,7 +119,7 @@ export class DagRunsTabPage extends BasePage {
 
     currentUrl.searchParams.set("run_id_pattern", pattern);
     await this.navigateTo(currentUrl.pathname + currentUrl.search);
-    await this.page.waitForURL(/.*run_id_pattern=.*/, { timeout: 15_000 });
+    await expect(this.page).toHaveURL(/.*run_id_pattern=.*/, { timeout: 15_000 
});
     await this.waitForRunsTableToLoad();
   }
 
@@ -156,7 +165,7 @@ export class DagRunsTabPage extends BasePage {
     const rowCount = await rows.count();
 
     for (let i = 0; i < Math.min(rowCount, 5); i++) {
-      const stateBadge = rows.nth(i).locator('[data-testid="state-badge"]');
+      const stateBadge = rows.nth(i).getByTestId("state-badge");
 
       await expect(stateBadge).toBeVisible();
       await expect(stateBadge).toContainText(expectedState, { ignoreCase: true 
});
@@ -168,12 +177,12 @@ export class DagRunsTabPage extends BasePage {
 
     await expect(firstRow).toBeVisible({ timeout: 10_000 });
 
-    const runIdLink = firstRow.locator("a[href*='/runs/']").first();
+    const runIdLink = firstRow.getByRole("link").first();
 
     await expect(runIdLink).toBeVisible();
     await expect(runIdLink).not.toBeEmpty();
 
-    const stateBadge = firstRow.locator('[data-testid="state-badge"]');
+    const stateBadge = firstRow.getByTestId("state-badge");
 
     await expect(stateBadge).toBeVisible();
 
@@ -183,10 +192,10 @@ export class DagRunsTabPage extends BasePage {
   }
 
   public async verifyRunsExist(): Promise<void> {
-    const runLinks = this.runsTable.locator("a[href*='/runs/']");
+    const firstRow = this.tableRows.first();
 
-    await expect(runLinks.first()).toBeVisible({ timeout: 30_000 });
-    await expect(runLinks).not.toHaveCount(0);
+    await expect(firstRow).toBeVisible({ timeout: 30_000 });
+    await expect(this.tableRows).not.toHaveCount(0);
   }
 
   public async verifySearchResults(pattern: string): Promise<void> {
@@ -199,7 +208,7 @@ export class DagRunsTabPage extends BasePage {
     const count = await rows.count();
 
     for (let i = 0; i < Math.min(count, 5); i++) {
-      const runIdLink = rows.nth(i).locator("a[href*='/runs/']").first();
+      const runIdLink = rows.nth(i).getByRole("link").first();
 
       await expect(runIdLink).toContainText(pattern, { ignoreCase: true });
     }
@@ -208,9 +217,9 @@ export class DagRunsTabPage extends BasePage {
   public async waitForRunsTableToLoad(): Promise<void> {
     await expect(this.runsTable).toBeVisible({ timeout: 10_000 });
 
-    const dataLink = this.runsTable.locator("a[href*='/runs/']").first();
+    const firstRow = this.tableRows.first();
     const noDataMessage = this.page.getByText(/no.*dag.*runs.*found/i);
 
-    await expect(dataLink.or(noDataMessage)).toBeVisible({ timeout: 30_000 });
+    await expect(firstRow.or(noDataMessage)).toBeVisible({ timeout: 30_000 });
   }
 }
diff --git a/airflow-core/src/airflow/ui/tests/e2e/specs/dag-runs-tab.spec.ts 
b/airflow-core/src/airflow/ui/tests/e2e/specs/dag-runs-tab.spec.ts
index d9aef74f547..5c0edc5bd99 100644
--- a/airflow-core/src/airflow/ui/tests/e2e/specs/dag-runs-tab.spec.ts
+++ b/airflow-core/src/airflow/ui/tests/e2e/specs/dag-runs-tab.spec.ts
@@ -59,7 +59,7 @@ test.describe("DAG Runs Tab", () => {
     await dagRunsTabPage.navigateToDag(testDagId);
     await dagRunsTabPage.clickRunsTab();
 
-    await expect(dagRunsTabPage.page).toHaveURL(/\/dags\/.*\/runs/);
+    await expect(dagRunsTabPage.page).toHaveURL(/.*\/dags\/[^/]+\/runs/);
   });
 
   test("verify run details display correctly", async () => {

Reply via email to