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 eb6a4d88815 feat: Improve Playwright test patterns in plugins.spec.ts 
and PluginsPage.ts (#63562)
eb6a4d88815 is described below

commit eb6a4d88815f3a0cd0c05849cfbcdb2026f20688
Author: BitToby <[email protected]>
AuthorDate: Tue Mar 17 14:35:31 2026 +0200

    feat: Improve Playwright test patterns in plugins.spec.ts and 
PluginsPage.ts (#63562)
    
    * feat: Improve Playwright test patterns in plugins.spec.ts and 
PluginsPage.ts
    
    * refactor: Refactor waitForLoad to use web-first assertions
    
    * fix: add data-testid
    
    * fix: update web-first assertion
---
 .../ui/src/components/DataTable/TableList.tsx      |  2 +-
 .../src/airflow/ui/tests/e2e/pages/PluginsPage.ts  | 59 ++++------------------
 .../src/airflow/ui/tests/e2e/specs/plugins.spec.ts | 30 +++++------
 3 files changed, 23 insertions(+), 68 deletions(-)

diff --git a/airflow-core/src/airflow/ui/src/components/DataTable/TableList.tsx 
b/airflow-core/src/airflow/ui/src/components/DataTable/TableList.tsx
index b8a9aa554a4..41e4f6907fd 100644
--- a/airflow-core/src/airflow/ui/src/components/DataTable/TableList.tsx
+++ b/airflow-core/src/airflow/ui/src/components/DataTable/TableList.tsx
@@ -90,7 +90,7 @@ export const TableList = <TData,>({ allowFiltering, 
renderSubComponent, table }:
             <Table.Row>
               {/* first row is a normal row */}
               {row.getVisibleCells().map((cell) => (
-                <Table.Cell key={cell.id}>
+                <Table.Cell data-testid={`table-cell-${cell.column.id}`} 
key={cell.id}>
                   {flexRender(cell.column.columnDef.cell, cell.getContext())}
                 </Table.Cell>
               ))}
diff --git a/airflow-core/src/airflow/ui/tests/e2e/pages/PluginsPage.ts 
b/airflow-core/src/airflow/ui/tests/e2e/pages/PluginsPage.ts
index c8f66309e57..08eaa97c593 100644
--- a/airflow-core/src/airflow/ui/tests/e2e/pages/PluginsPage.ts
+++ b/airflow-core/src/airflow/ui/tests/e2e/pages/PluginsPage.ts
@@ -16,49 +16,26 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+import { expect } from "@playwright/test";
 import type { Locator, Page } from "@playwright/test";
 
 import { BasePage } from "./BasePage";
 
 export class PluginsPage extends BasePage {
   public readonly heading: Locator;
+  public readonly nameColumn: Locator;
   public readonly rows: Locator;
+  public readonly sourceColumn: Locator;
   public readonly table: Locator;
 
   public constructor(page: Page) {
     super(page);
 
-    this.heading = page.getByRole("heading", {
-      name: /plugins/i,
-    });
+    this.heading = page.getByRole("heading", { name: /plugins/i });
     this.table = page.getByTestId("table-list");
-    this.rows = this.table.locator("tbody tr").filter({
-      has: page.locator("td"),
-    });
-  }
-
-  public async getPluginCount(): Promise<number> {
-    return this.rows.count();
-  }
-
-  public async getPluginNames(): Promise<Array<string>> {
-    const count = await this.rows.count();
-
-    if (count === 0) {
-      return [];
-    }
-
-    return this.rows.locator("td:first-child").allTextContents();
-  }
-
-  public async getPluginSources(): Promise<Array<string>> {
-    const count = await this.rows.count();
-
-    if (count === 0) {
-      return [];
-    }
-
-    return this.rows.locator("td:nth-child(2)").allTextContents();
+    this.rows = this.table.locator("tbody tr").filter({ has: 
page.locator("td") });
+    this.nameColumn = this.rows.getByTestId("table-cell-name");
+    this.sourceColumn = this.rows.getByTestId("table-cell-source");
   }
 
   public async navigate(): Promise<void> {
@@ -66,25 +43,7 @@ export class PluginsPage extends BasePage {
   }
 
   public async waitForLoad(): Promise<void> {
-    await this.table.waitFor({ state: "visible", timeout: 30_000 });
-    await this.waitForTableData();
-  }
-
-  public async waitForTableData(): Promise<void> {
-    await this.page.waitForFunction(
-      () => {
-        const table = document.querySelector('[data-testid="table-list"]');
-
-        if (!table) {
-          return false;
-        }
-
-        const cells = table.querySelectorAll("tbody tr td");
-
-        return cells.length > 0;
-      },
-      undefined,
-      { timeout: 30_000 },
-    );
+    await expect(this.table).toBeVisible({ timeout: 30_000 });
+    await expect(this.rows.first()).toBeVisible({ timeout: 30_000 });
   }
 }
diff --git a/airflow-core/src/airflow/ui/tests/e2e/specs/plugins.spec.ts 
b/airflow-core/src/airflow/ui/tests/e2e/specs/plugins.spec.ts
index 6d502cff603..8d85845db4b 100644
--- a/airflow-core/src/airflow/ui/tests/e2e/specs/plugins.spec.ts
+++ b/airflow-core/src/airflow/ui/tests/e2e/specs/plugins.spec.ts
@@ -37,36 +37,32 @@ test.describe("Plugins Page", () => {
     await expect(pluginsPage.table).toBeVisible();
   });
 
-  test("verify plugins list displays with data", async () => {
-    const count = await pluginsPage.getPluginCount();
-
-    expect(count).toBeGreaterThan(0);
+  test("verify plugins list has at least one entry", async () => {
+    await expect(pluginsPage.rows).not.toHaveCount(0);
   });
 
   test("verify each plugin has a name", async () => {
-    const pluginNames = await pluginsPage.getPluginNames();
-
-    expect(pluginNames.length).toBeGreaterThan(0);
+    await expect(pluginsPage.rows).not.toHaveCount(0);
+    const count = await pluginsPage.rows.count();
 
-    for (const name of pluginNames) {
-      expect(name.trim().length).toBeGreaterThan(0);
+    for (let i = 0; i < count; i++) {
+      await expect(pluginsPage.nameColumn.nth(i)).not.toBeEmpty();
     }
   });
 
   test("verify each plugin has a source", async () => {
-    const pluginSources = await pluginsPage.getPluginSources();
-
-    expect(pluginSources.length).toBeGreaterThan(0);
+    await expect(pluginsPage.rows).not.toHaveCount(0);
+    const count = await pluginsPage.rows.count();
 
-    for (const source of pluginSources) {
-      expect(source.trim().length).toBeGreaterThan(0);
+    for (let i = 0; i < count; i++) {
+      await expect(pluginsPage.sourceColumn.nth(i)).not.toBeEmpty();
     }
   });
 
   test("verify plugin names and sources have matching counts", async () => {
-    const pluginNames = await pluginsPage.getPluginNames();
-    const pluginSources = await pluginsPage.getPluginSources();
+    const rowCount = await pluginsPage.rows.count();
 
-    expect(pluginNames.length).toBe(pluginSources.length);
+    await expect(pluginsPage.nameColumn).toHaveCount(rowCount);
+    await expect(pluginsPage.sourceColumn).toHaveCount(rowCount);
   });
 });

Reply via email to