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