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();