Skip to content

Commit c6a05b5

Browse files
UI E2E tests for Providers Page (#60705)
* E2E tests for Providers Page
1 parent 8f3ae04 commit c6a05b5

2 files changed

Lines changed: 238 additions & 0 deletions

File tree

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*!
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
import { expect, type Locator, type Page } from "@playwright/test";
20+
21+
import { BasePage } from "./BasePage";
22+
23+
export class ProvidersPage extends BasePage {
24+
public readonly heading: Locator;
25+
public readonly paginationNextButton: Locator;
26+
public readonly paginationPrevButton: Locator;
27+
public readonly rows: Locator;
28+
public readonly table: Locator;
29+
30+
public constructor(page: Page) {
31+
super(page);
32+
33+
this.heading = page.getByRole("heading", { name: /^providers$/i });
34+
this.table = page.getByTestId("table-list");
35+
this.rows = this.table.locator("tbody tr").filter({
36+
has: page.locator("td"),
37+
});
38+
this.paginationNextButton = page.locator('[data-testid="next"]');
39+
this.paginationPrevButton = page.locator('[data-testid="prev"]');
40+
}
41+
42+
/**
43+
* Click next page button
44+
*/
45+
public async clickNextPage(): Promise<void> {
46+
const initialProviderNames = await this.providerNames();
47+
48+
await this.paginationNextButton.click();
49+
50+
await expect.poll(() => this.providerNames(), { timeout: 10_000 }).not.toEqual(initialProviderNames);
51+
await this.waitForTableData();
52+
}
53+
54+
/**
55+
* Click previous page button
56+
*/
57+
public async clickPrevPage(): Promise<void> {
58+
const initialProviderNames = await this.providerNames();
59+
60+
await this.paginationPrevButton.click();
61+
62+
await expect.poll(() => this.providerNames(), { timeout: 10_000 }).not.toEqual(initialProviderNames);
63+
await this.waitForTableData();
64+
}
65+
66+
public async getRowCount(): Promise<number> {
67+
return this.rows.count();
68+
}
69+
70+
public async getRowDetails(index: number) {
71+
const row = this.rows.nth(index);
72+
const cells = row.locator("td");
73+
74+
const pkg = await cells.nth(0).locator("a").textContent();
75+
const ver = await cells.nth(1).textContent();
76+
const desc = await cells.nth(2).textContent();
77+
78+
return {
79+
description: (desc ?? "").trim(),
80+
packageName: (pkg ?? "").trim(),
81+
version: (ver ?? "").trim(),
82+
};
83+
}
84+
85+
public async navigate(): Promise<void> {
86+
await this.navigateTo("/providers");
87+
}
88+
89+
public async providerNames(): Promise<Array<string>> {
90+
return this.rows.locator("td a").allTextContents();
91+
}
92+
93+
public async waitForLoad(): Promise<void> {
94+
await this.table.waitFor({ state: "visible", timeout: 30_000 });
95+
await this.waitForTableData();
96+
}
97+
98+
private async waitForTableData(): Promise<void> {
99+
// Wait for actual data links to appear (not skeleton loaders)
100+
await this.page.waitForFunction(
101+
() => {
102+
const table = document.querySelector('[data-testid="table-list"]');
103+
104+
if (!table) {
105+
return false;
106+
}
107+
108+
// Check for actual links in tbody (real data, not skeleton)
109+
const links = table.querySelectorAll("tbody tr td a");
110+
111+
return links.length > 0;
112+
},
113+
undefined,
114+
{ timeout: 30_000 },
115+
);
116+
}
117+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*!
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
import { test, expect } from "@playwright/test";
20+
21+
import { ProvidersPage } from "../pages/ProvidersPage";
22+
23+
test.describe("Providers Page", () => {
24+
let providers: ProvidersPage;
25+
26+
test.beforeEach(async ({ page }) => {
27+
providers = new ProvidersPage(page);
28+
await providers.navigate();
29+
await providers.waitForLoad();
30+
});
31+
32+
test("verify providers page heading", async () => {
33+
await expect(providers.heading).toBeVisible();
34+
});
35+
36+
test("Verify Providers page is accessible via Admin menu", async ({ page }) => {
37+
await page.goto("/");
38+
39+
await page.getByRole("button", { name: /^admin$/i }).click();
40+
41+
// Click Providers
42+
const providersItem = page.getByRole("menuitem", { name: /^providers$/i });
43+
44+
await expect(providersItem).toBeVisible();
45+
await providersItem.click();
46+
47+
await providers.waitForLoad();
48+
// Assert Providers page loaded
49+
await expect(providers.heading).toBeVisible();
50+
expect(await providers.getRowCount()).toBeGreaterThan(0);
51+
});
52+
53+
test("Verify the providers list displays", async () => {
54+
await expect(providers.table).toBeVisible();
55+
});
56+
57+
test("Verify package name, version, and description are not blank", async () => {
58+
const count = await providers.getRowCount();
59+
60+
expect(count).toBeGreaterThan(0);
61+
62+
for (let i = 0; i < 2; i++) {
63+
const { description, packageName, version } = await providers.getRowDetails(i);
64+
65+
expect(packageName).not.toEqual("");
66+
expect(version).not.toEqual("");
67+
expect(description).not.toEqual("");
68+
}
69+
});
70+
71+
test("verify providers pagination", async () => {
72+
const limit = 5;
73+
74+
await providers.navigateTo(`/providers?offset=0&limit=${limit}`);
75+
await providers.waitForLoad();
76+
77+
const rows = await providers.getRowCount();
78+
79+
expect(rows).toBeGreaterThan(0);
80+
81+
const initialProviderNames = await providers.providerNames();
82+
83+
expect(initialProviderNames.length).toBeGreaterThan(0);
84+
85+
await expect(providers.paginationNextButton).toBeVisible();
86+
await expect(providers.paginationPrevButton).toBeVisible();
87+
88+
await providers.paginationNextButton.click();
89+
await providers.waitForLoad();
90+
91+
await providers.page.waitForURL((url) => {
92+
const u = new URL(url);
93+
const offset = u.searchParams.get("offset");
94+
95+
return offset !== null && offset !== "0";
96+
});
97+
98+
const rowsPage2 = await providers.getRowCount();
99+
100+
expect(rowsPage2).toBeGreaterThan(0);
101+
102+
const ProviderNamesAfterNext = await providers.providerNames();
103+
104+
expect(ProviderNamesAfterNext.length).toBeGreaterThan(0);
105+
expect(ProviderNamesAfterNext).not.toEqual(initialProviderNames);
106+
107+
await providers.paginationPrevButton.click();
108+
await providers.waitForLoad();
109+
110+
await providers.page.waitForURL((url) => {
111+
const u = new URL(url);
112+
const offset = u.searchParams.get("offset");
113+
114+
return offset === "0" || offset === null;
115+
});
116+
117+
const rowsBack = await providers.getRowCount();
118+
119+
expect(rowsBack).toBeGreaterThan(0);
120+
});
121+
});

0 commit comments

Comments
 (0)