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 181b39800f9 Improve Playwright test patterns in dag-grid-view.spec.ts 
#63411 (#63415)
181b39800f9 is described below

commit 181b39800f95ae84dd2111f7328534b290e1efef
Author: Haseeb Malik <[email protected]>
AuthorDate: Fri Mar 13 23:40:19 2026 -0400

    Improve Playwright test patterns in dag-grid-view.spec.ts #63411 (#63415)
---
 .../airflow/ui/src/layouts/Details/Grid/GridTI.tsx |  1 +
 .../ui/src/layouts/Details/Grid/TaskNames.tsx      |  1 +
 .../src/airflow/ui/tests/e2e/pages/GridPage.ts     | 46 +++++++---------------
 .../ui/tests/e2e/specs/dag-grid-view.spec.ts       | 24 ++---------
 4 files changed, 21 insertions(+), 51 deletions(-)

diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx 
b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx
index 1a4b1413f21..ede81eccbb0 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx
@@ -83,6 +83,7 @@ export const GridTI = ({ dagId, instance, isGroup, isMapped, 
onClick, runId, tas
       <TaskInstanceTooltip openDelay={500} positioning={{ placement: "bottom" 
}} taskInstance={instance}>
         <Box as="span" display="inline-block">
           <Link
+            data-testid={`grid-${runId}-${taskId}`}
             id={`grid-${runId}-${taskId}`}
             onClick={onClick}
             replace
diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/TaskNames.tsx 
b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/TaskNames.tsx
index c2e040ca17c..bd76a6663be 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/TaskNames.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/TaskNames.tsx
@@ -93,6 +93,7 @@ export const TaskNames = ({ nodes, onRowClick, virtualItems 
}: Props) => {
             borderTopWidth={virtualItem.index === 0 ? 1 : 0}
             cursor="pointer"
             data-node-id={node.id}
+            data-testid={`task-${node.id.replaceAll(".", "-")}`}
             height={`${ROW_HEIGHT}px`}
             id={`task-${node.id.replaceAll(".", "-")}`}
             key={node.id}
diff --git a/airflow-core/src/airflow/ui/tests/e2e/pages/GridPage.ts 
b/airflow-core/src/airflow/ui/tests/e2e/pages/GridPage.ts
index 3e5a1a643bf..6c5dd613882 100644
--- a/airflow-core/src/airflow/ui/tests/e2e/pages/GridPage.ts
+++ b/airflow-core/src/airflow/ui/tests/e2e/pages/GridPage.ts
@@ -22,13 +22,13 @@ import { BasePage } from "tests/e2e/pages/BasePage";
 export class GridPage extends BasePage {
   public readonly gridCells: Locator;
   public readonly gridViewButton: Locator;
-  public readonly taskNameLinks: Locator;
+  public readonly taskNameRows: Locator;
 
   public constructor(page: Page) {
     super(page);
     this.gridViewButton = page.getByTestId("grid-view-button");
-    this.gridCells = page.locator('a[id^="grid-"]');
-    this.taskNameLinks = page.locator('a[href*="/tasks/"]');
+    this.gridCells = page.getByTestId(/^grid-(?!view-button).+/);
+    this.taskNameRows = page.getByTestId(/^task-(?!state-badge).+/);
   }
 
   public async clickGridCellAndVerifyDetails(): Promise<void> {
@@ -38,28 +38,13 @@ export class GridPage extends BasePage {
 
     await expect(firstCell).toBeVisible();
     await firstCell.click();
-    await this.page.waitForURL(/.*\/tasks\/.*/, { timeout: 15_000 });
+    await expect(this.page).toHaveURL(/.*\/tasks\/.*/, { timeout: 15_000 });
     await expect(this.page.getByTestId("virtualized-list")).toBeVisible({ 
timeout: 10_000 });
   }
 
-  public async getGridCellCount(): Promise<number> {
-    await this.waitForGridToLoad();
-
-    return this.gridCells.count();
-  }
-
-  public async getTaskNames(): Promise<Array<string>> {
-    await this.waitForGridToLoad();
-
-    const names = await this.taskNameLinks.allTextContents();
-    const uniqueNames = [...new Set(names.map((name) => 
name.trim()).filter((name) => name !== ""))];
-
-    return uniqueNames;
-  }
-
   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/${dagId}`), { timeout: 
15_000 });
     await expect(this.gridViewButton).toBeVisible({ timeout: 10_000 });
   }
 
@@ -69,10 +54,16 @@ export class GridPage extends BasePage {
     await this.waitForGridToLoad();
   }
 
+  public async verifyGridHasTaskInstances(): Promise<void> {
+    await this.waitForGridToLoad();
+    await expect(this.taskNameRows).not.toHaveCount(0);
+    await expect(this.gridCells).not.toHaveCount(0);
+  }
+
   public async verifyGridViewIsActive(): Promise<void> {
     await expect(this.gridViewButton).toBeVisible({ timeout: 10_000 });
     await expect(this.gridCells.first()).toBeVisible({ timeout: 15_000 });
-    await expect(this.taskNameLinks.first()).toBeVisible({ timeout: 10_000 });
+    await expect(this.taskNameRows.first()).toBeVisible({ timeout: 20_000 });
   }
 
   public async verifyTaskStatesAreColorCoded(): Promise<void> {
@@ -85,12 +76,7 @@ export class GridPage extends BasePage {
     const badge = firstCell.getByTestId("task-state-badge");
 
     await expect(badge).toBeVisible();
-
-    const bgColor = await badge.evaluate((el) => 
window.getComputedStyle(el).backgroundColor);
-
-    const isTransparent = !bgColor || bgColor === "transparent" || bgColor === 
"rgba(0, 0, 0, 0)";
-
-    expect(isTransparent).toBe(false);
+    await expect(badge).not.toHaveCSS("background-color", "rgba(0, 0, 0, 0)");
   }
 
   public async verifyTaskTooltipOnHover(): Promise<void> {
@@ -101,13 +87,11 @@ export class GridPage extends BasePage {
     await expect(firstCell).toBeVisible();
     await firstCell.hover();
 
-    const tooltip = this.page.locator('[role="tooltip"], 
[data-scope="tooltip"]');
-
-    await expect(tooltip.first()).toBeVisible({ timeout: 10_000 });
+    await expect(this.page.getByRole("tooltip").first()).toBeVisible({ 
timeout: 10_000 });
   }
 
   public async waitForGridToLoad(): Promise<void> {
     await expect(this.gridCells.first()).toBeVisible({ timeout: 20_000 });
-    await expect(this.taskNameLinks.first()).toBeVisible({ timeout: 10_000 });
+    await expect(this.taskNameRows.first()).toBeVisible({ timeout: 10_000 });
   }
 }
diff --git a/airflow-core/src/airflow/ui/tests/e2e/specs/dag-grid-view.spec.ts 
b/airflow-core/src/airflow/ui/tests/e2e/specs/dag-grid-view.spec.ts
index 15d0191a7c5..f7a0f83def4 100644
--- a/airflow-core/src/airflow/ui/tests/e2e/specs/dag-grid-view.spec.ts
+++ b/airflow-core/src/airflow/ui/tests/e2e/specs/dag-grid-view.spec.ts
@@ -16,12 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { expect, test } from "@playwright/test";
+import { test } from "@playwright/test";
 import { AUTH_FILE, testConfig } from "playwright.config";
 import { DagsPage } from "tests/e2e/pages/DagsPage";
 import { GridPage } from "tests/e2e/pages/GridPage";
 
 test.describe("DAG Grid View", () => {
+  test.setTimeout(60_000);
+
   let gridPage: GridPage;
   const testDagId = testConfig.testDag.id;
 
@@ -45,48 +47,30 @@ test.describe("DAG Grid View", () => {
   });
 
   test("navigate to DAG detail page and display grid view", async () => {
-    test.setTimeout(60_000);
-
     await gridPage.navigateToDag(testDagId);
     await gridPage.switchToGridView();
     await gridPage.verifyGridViewIsActive();
   });
 
   test("render grid with task instances", async () => {
-    test.setTimeout(60_000);
-
     await gridPage.navigateToDag(testDagId);
     await gridPage.switchToGridView();
-    await gridPage.waitForGridToLoad();
-
-    const taskNames = await gridPage.getTaskNames();
-
-    expect(taskNames.length).toBeGreaterThan(0);
-
-    const cellCount = await gridPage.getGridCellCount();
-
-    expect(cellCount).toBeGreaterThan(0);
+    await gridPage.verifyGridHasTaskInstances();
   });
 
   test("display task states with color coding", async () => {
-    test.setTimeout(60_000);
-
     await gridPage.navigateToDag(testDagId);
     await gridPage.switchToGridView();
     await gridPage.verifyTaskStatesAreColorCoded();
   });
 
   test("show task details when clicking a grid cell", async () => {
-    test.setTimeout(60_000);
-
     await gridPage.navigateToDag(testDagId);
     await gridPage.switchToGridView();
     await gridPage.clickGridCellAndVerifyDetails();
   });
 
   test("show tooltip on grid cell hover", async () => {
-    test.setTimeout(60_000);
-
     await gridPage.navigateToDag(testDagId);
     await gridPage.switchToGridView();
     await gridPage.verifyTaskTooltipOnHover();

Reply via email to