Skip to content

Commit 3eb2d6d

Browse files
feat(e2e): complete hardening — POMs, fixtures, naming, a11y gate
Migrate all specs off direct UIhelper usage into page objects, add global RHDH health setup and managed browser sessions, replace waitForSelector, remove deprecated showcase selectors, rename catalog constants, enforce critical axe violations, add stability script, and native fetch in Keycloak. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent c4cf27f commit 3eb2d6d

52 files changed

Lines changed: 1200 additions & 580 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

e2e-tests/README.md

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ letting CI or a local run target a subset.
201201
| `@smoke` | Fast, high-signal check suitable to run on every PR. |
202202
| `@ga-plugin` | Exercises a generally-available (GA) plugin. |
203203
| `@non-ga-plugin` | Exercises a tech-preview / dev-preview (non-GA) plugin. |
204+
| `@blocked` | Blocked by a known issue; tests are skipped with a Jira reference. |
204205

205206
```bash
206207
# Run only smoke-tagged tests
@@ -404,18 +405,24 @@ This opens an interactive UI where you can select individual tests, watch them r
404405

405406
After running `local-test-setup.sh`, these variables are set:
406407

407-
| Variable | Description |
408-
| --------------------------- | --------------------------------------------- |
409-
| `BASE_URL` | URL of the deployed RHDH instance |
410-
| `SHOWCASE_URL` | Showcase deployment URL |
411-
| `SHOWCASE_RBAC_URL` | Showcase RBAC deployment URL |
412-
| `K8S_CLUSTER_URL` | OpenShift API server URL |
413-
| `K8S_CLUSTER_TOKEN` | Service account token (48-hour duration) |
414-
| `JOB_NAME` | Selected job name |
415-
| `IMAGE_REGISTRY` | Image registry (default: `quay.io`) |
416-
| `IMAGE_REPO` | Image repository (fallback: `QUAY_REPO`) |
417-
| `TAG_NAME` | Image tag |
418-
| Plus all secrets from Vault | (exported with `-`, `.`, `/` replaced by `_`) |
408+
| Variable | Description |
409+
| --------------------------- | ---------------------------------------------------------------------------------------------- |
410+
| `BASE_URL` | URL of the deployed RHDH instance (Playwright uses this as the test base URL) |
411+
| `SHOWCASE_URL` | Legacy name for the standard RHDH deployment URL (same value as `BASE_URL` for showcase tests) |
412+
| `SHOWCASE_RBAC_URL` | Legacy name for the RBAC deployment URL |
413+
| `K8S_CLUSTER_URL` | OpenShift API server URL |
414+
| `K8S_CLUSTER_TOKEN` | Service account token (48-hour duration) |
415+
| `JOB_NAME` | Selected job name |
416+
| `IMAGE_REGISTRY` | Image registry (default: `quay.io`) |
417+
| `IMAGE_REPO` | Image repository (fallback: `QUAY_REPO`) |
418+
| `TAG_NAME` | Image tag |
419+
| Plus all secrets from Vault | (exported with `-`, `.`, `/` replaced by `_`) |
420+
421+
> **Note:** `BASE_URL` is the canonical Playwright base URL for the RHDH instance under test.
422+
> `SHOWCASE_URL` and `SHOWCASE_RBAC_URL` are legacy names retained by `local-test-setup.sh` and
423+
> deployment scripts; `local-test-setup.sh` sets `BASE_URL` from the appropriate legacy URL.
424+
> Yarn scripts such as `yarn showcase`, `yarn showcase-rbac`, and `yarn test:stability` still use
425+
> the `showcase` Playwright project name for historical reasons.
419426
420427
### Artifacts and Logs
421428

e2e-tests/oxlint.config.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,19 +142,37 @@ export default defineConfig({
142142
"expect",
143143
"toPass",
144144
"verifyHeading",
145+
"verifyWelcomeHeading",
146+
"verifyGuestProfile",
147+
"verifySignInPageTitle",
148+
"verifyProfileHeading",
149+
"verifySignInError",
145150
"verifyQuickAccess",
146151
"verifyLink",
147152
"verifyRowsInTable",
148153
"verifyDivHasText",
149154
"verifyComponentInCatalog",
155+
"verifyComponentsInCatalog",
150156
"verifyParagraph",
151157
"verifyText",
152158
"verifyTextinCard",
159+
"verifyTextInCard",
153160
"verifyVisitedCardContent",
154161
"verifyAboutCardIsDisplayed",
155162
"verifyPRStatisticsRendered",
156163
"verifyPRRows",
157164
"verifyPRRowsPerPage",
165+
"verifyTestPageContent",
166+
"verifyContextOneCard",
167+
"verifyContextTwoCard",
168+
"verifyTemplatesHeading",
169+
"verifyDocumentationHeading",
170+
"verifyDocHeading",
171+
"verifyCreateReactAppReviewTableWithGroupOwner",
172+
"verifyDependencyGraphLabels",
173+
"launchTemplateAndVerifyIntro",
174+
"runHttpRequestTemplateFlow",
175+
"inspectEntityAndVerifyYaml",
158176
"registerExistingComponent",
159177
"validateLog",
160178
"validateLogEvent",

e2e-tests/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"node": "24"
88
},
99
"scripts": {
10+
"test:stability": "playwright test --project=showcase --retries=0",
1011
"showcase": "playwright test --project=showcase",
1112
"showcase-rbac": "playwright test --project=showcase-rbac",
1213
"showcase-k8s": "playwright test --project=showcase-k8s",
@@ -36,7 +37,6 @@
3637
"@playwright/test": "1.59.1",
3738
"@types/js-yaml": "^4.0.9",
3839
"@types/node": "24.12.2",
39-
"@types/node-fetch": "^2.6.13",
4040
"@types/pg": "8.20.0",
4141
"eslint-plugin-check-file": "3.3.1",
4242
"eslint-plugin-playwright": "2.10.4",
@@ -57,7 +57,6 @@
5757
"@microsoft/microsoft-graph-client": "3.0.7",
5858
"isomorphic-fetch": "3.0.0",
5959
"js-yaml": "4.1.1",
60-
"node-fetch": "2.7.0",
6160
"octokit": "4.1.4",
6261
"pg": "8.22.0",
6362
"uuid": "14.0.0",

e2e-tests/playwright.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const k8sSpecificConfig = {
4141
};
4242

4343
export default defineConfig({
44+
globalSetup: "./playwright/global-setup.ts",
4445
timeout: 90 * 1000,
4546
testDir: "./playwright",
4647
/* Fail the build on CI if you accidentally left test.only in the source code. */

e2e-tests/playwright/e2e/audit-log/auditor-catalog.spec.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { test } from "@support/coverage/test";
22
import { Common } from "../../utils/common";
3-
import { UIhelper } from "../../utils/ui-helper";
43
import { LogUtils } from "./log-utils";
54
import { CatalogImport } from "../../support/pages/catalog-import";
65
import { APIHelper } from "../../utils/api-helper";
6+
import { SelfServicePage } from "../../support/pages/self-service-page";
7+
78
const template =
89
"https://github.com/janus-qe/sample-service/blob/main/demo_template.yaml";
910
const entityName = "hello-world-2";
@@ -26,7 +27,7 @@ async function ensureEntityDoesNotExist() {
2627
}
2728

2829
test.describe.serial("Audit Log check for Catalog Plugin", () => {
29-
let uiHelper: UIhelper;
30+
let selfServicePage: SelfServicePage;
3031
let common: Common;
3132
let catalogImport: CatalogImport;
3233

@@ -38,16 +39,16 @@ test.describe.serial("Audit Log check for Catalog Plugin", () => {
3839
});
3940

4041
test.beforeEach(async ({ page }) => {
41-
uiHelper = new UIhelper(page);
42+
selfServicePage = new SelfServicePage(page);
4243
common = new Common(page);
4344
catalogImport = new CatalogImport(page);
4445
await common.loginAsGuest();
45-
await uiHelper.goToSelfServicePage();
46+
await selfServicePage.open();
4647
});
4748

4849
test("Should fetch logs for entity-mutate event and validate log structure and values", async () => {
4950
await ensureEntityExists();
50-
await uiHelper.clickButton("Import an existing Git repository");
51+
await selfServicePage.clickImportGitRepository();
5152
await catalogImport.registerExistingComponent(template, false);
5253
await LogUtils.validateLogEvent(
5354
"entity-mutate",
@@ -64,7 +65,7 @@ test.describe.serial("Audit Log check for Catalog Plugin", () => {
6465

6566
test("Should fetch logs for location-mutate event and validate log structure and values", async () => {
6667
await ensureEntityDoesNotExist();
67-
await uiHelper.clickButton("Import an existing Git repository");
68+
await selfServicePage.clickImportGitRepository();
6869
await catalogImport.registerExistingComponent(template, false);
6970
await LogUtils.validateLogEvent(
7071
"location-mutate",

e2e-tests/playwright/e2e/audit-log/auditor-rbac.spec.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { test, expect, Page } from "@support/coverage/test";
2-
import { Common, setupBrowser, teardownBrowser } from "../../utils/common";
2+
import { Common } from "../../utils/common";
3+
import {
4+
createManagedBrowserSession,
5+
type ManagedBrowserSession,
6+
} from "../../support/fixtures/managed-browser";
37
import {
48
RBAC_API,
59
ROLE_NAME,
@@ -26,6 +30,7 @@ let rbacApi: RhdhRbacApi;
2630

2731
test.describe("Auditor check for RBAC Plugin", () => {
2832
let page: Page;
33+
let browserSession: ManagedBrowserSession;
2934

3035
test.beforeAll(async ({ browser }, testInfo) => {
3136
test.info().annotations.push({
@@ -34,7 +39,8 @@ test.describe("Auditor check for RBAC Plugin", () => {
3439
});
3540

3641
await (await import("./log-utils")).LogUtils.loginToOpenShift();
37-
page = (await setupBrowser(browser, testInfo)).page;
42+
browserSession = await createManagedBrowserSession(browser, testInfo);
43+
page = browserSession.page;
3844
common = new Common(page);
3945
await common.loginAsKeycloakUser();
4046
rbacApi = await RhdhRbacApi.buildRbacApi(page);
@@ -300,7 +306,7 @@ test.describe("Auditor check for RBAC Plugin", () => {
300306
).resolves.toBeUndefined();
301307
});
302308

303-
test.afterAll(async (_args, testInfo) => {
304-
await teardownBrowser(page, testInfo);
309+
test.afterAll(async () => {
310+
await browserSession.dispose();
305311
});
306312
});

e2e-tests/playwright/e2e/auth-providers/github.spec.ts

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
import { test, expect, Page, BrowserContext } from "@support/coverage/test";
22
import RHDHDeployment from "../../utils/authentication-providers/rhdh-deployment";
3-
import { Common, setupBrowser, teardownBrowser } from "../../utils/common";
4-
import { UIhelper } from "../../utils/ui-helper";
3+
import { Common } from "../../utils/common";
54
import { NO_USER_FOUND_IN_CATALOG_ERROR_MESSAGE } from "../../utils/constants";
5+
import { SettingsPage } from "../../support/pages/settings-page";
6+
import {
7+
createManagedBrowserSession,
8+
type ManagedBrowserSession,
9+
} from "../../support/fixtures/managed-browser";
610
let page: Page;
711
let context: BrowserContext;
12+
let browserSession: ManagedBrowserSession;
813

914
/* SUPORTED RESOLVERS
1015
GITHUB:
@@ -17,7 +22,7 @@ GITHUB:
1722
// oxlint-disable-next-line eslint/require-await -- top-level await configures test.use baseURL
1823
test.describe("Configure Github Provider", async () => {
1924
let common: Common;
20-
let uiHelper: UIhelper;
25+
let settingsPage: SettingsPage;
2126

2227
const namespace = "albarbaro-test-namespace-github";
2328
const appConfigMap = "app-config-rhdh";
@@ -53,9 +58,11 @@ test.describe("Configure Github Provider", async () => {
5358
await deployment.loadAllConfigs();
5459

5560
// setup playwright helpers
56-
({ context, page } = await setupBrowser(browser, testInfo));
61+
browserSession = await createManagedBrowserSession(browser, testInfo);
62+
context = browserSession.context;
63+
page = browserSession.page;
5764
common = new Common(page);
58-
uiHelper = new UIhelper(page);
65+
settingsPage = new SettingsPage(page);
5966

6067
// expect some expected variables
6168

@@ -146,8 +153,8 @@ test.describe("Configure Github Provider", async () => {
146153
);
147154
expect(login).toBe("Login successful");
148155

149-
await uiHelper.goToSettingsPage();
150-
await uiHelper.verifyHeading("RHDH QE Admin");
156+
await settingsPage.open();
157+
await settingsPage.verifyProfileHeading("RHDH QE Admin");
151158
await common.signOut();
152159
await context.clearCookies();
153160
});
@@ -170,8 +177,8 @@ test.describe("Configure Github Provider", async () => {
170177
);
171178
expect(login).toBe("Login successful");
172179

173-
await uiHelper.goToSettingsPage();
174-
await uiHelper.verifyHeading("RHDH QE Admin");
180+
await settingsPage.open();
181+
await settingsPage.verifyProfileHeading("RHDH QE Admin");
175182
await common.signOut();
176183
await context.clearCookies();
177184
});
@@ -197,7 +204,7 @@ test.describe("Configure Github Provider", async () => {
197204
);
198205
expect(login).toBe("Login successful");
199206

200-
await uiHelper.verifyAlertErrorMessage(
207+
await settingsPage.verifySignInError(
201208
NO_USER_FOUND_IN_CATALOG_ERROR_MESSAGE,
202209
);
203210
await context.clearCookies();
@@ -227,7 +234,7 @@ test.describe("Configure Github Provider", async () => {
227234

228235
expect(login).toBe("Login successful");
229236

230-
await uiHelper.verifyAlertErrorMessage(
237+
await settingsPage.verifySignInError(
231238
NO_USER_FOUND_IN_CATALOG_ERROR_MESSAGE,
232239
);
233240
await context.clearCookies();
@@ -271,8 +278,8 @@ test.describe("Configure Github Provider", async () => {
271278
expect(actualDuration).toBeGreaterThan(threeDays - tolerance);
272279
expect(actualDuration).toBeLessThan(threeDays + tolerance);
273280

274-
await uiHelper.goToSettingsPage();
275-
await uiHelper.verifyHeading("RHDH QE Admin");
281+
await settingsPage.open();
282+
await settingsPage.verifyProfileHeading("RHDH QE Admin");
276283
await common.signOut();
277284
await context.clearCookies();
278285
});
@@ -348,15 +355,15 @@ test.describe("Configure Github Provider", async () => {
348355

349356
expect(login).toBe("Login successful");
350357

351-
await uiHelper.verifyAlertErrorMessage(
358+
await settingsPage.verifySignInError(
352359
/Login failed; caused by Error: The GitHub provider is not configured to support sign-in/u,
353360
);
354361
await context.clearCookies();
355362
});
356363

357364
test.afterAll(async () => {
358-
if (page !== undefined) {
359-
await teardownBrowser(page, test.info());
365+
if (browserSession !== undefined) {
366+
await browserSession.dispose();
360367
}
361368
console.log("[TEST] Starting cleanup...");
362369
await deployment.killRunningProcess();

e2e-tests/playwright/e2e/auth-providers/gitlab.spec.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
import { test, expect, Page, BrowserContext } from "@support/coverage/test";
22
import RHDHDeployment from "../../utils/authentication-providers/rhdh-deployment";
3-
import { Common, setupBrowser, teardownBrowser } from "../../utils/common";
4-
import { UIhelper } from "../../utils/ui-helper";
3+
import { Common } from "../../utils/common";
54
import { GitLabHelper } from "../../utils/authentication-providers/gitlab-helper";
5+
import { SettingsPage } from "../../support/pages/settings-page";
6+
import {
7+
createManagedBrowserSession,
8+
type ManagedBrowserSession,
9+
} from "../../support/fixtures/managed-browser";
610
let page: Page;
711
let context: BrowserContext;
12+
let browserSession: ManagedBrowserSession;
813

914
/* SUPORTED RESOLVERS
1015
GITLAB:
@@ -17,7 +22,7 @@ GITLAB:
1722
// oxlint-disable-next-line eslint/require-await -- top-level await configures test.use baseURL
1823
test.describe("Configure GitLab Provider", async () => {
1924
let common: Common;
20-
let uiHelper: UIhelper;
25+
let settingsPage: SettingsPage;
2126
let gitlabHelper: GitLabHelper;
2227
let oauthAppId: number | null = null;
2328

@@ -55,9 +60,11 @@ test.describe("Configure GitLab Provider", async () => {
5560
await deployment.loadAllConfigs();
5661

5762
// setup playwright helpers
58-
({ context, page } = await setupBrowser(browser, testInfo));
63+
browserSession = await createManagedBrowserSession(browser, testInfo);
64+
context = browserSession.context;
65+
page = browserSession.page;
5966
common = new Common(page);
60-
uiHelper = new UIhelper(page);
67+
settingsPage = new SettingsPage(page);
6168

6269
// expect some expected variables
6370
expect(process.env.AUTH_PROVIDERS_GITLAB_HOST!).toBeDefined();
@@ -158,8 +165,8 @@ test.describe("Configure GitLab Provider", async () => {
158165
);
159166
expect(login).toBe("Login successful");
160167

161-
await uiHelper.goToSettingsPage();
162-
await uiHelper.verifyHeading("user1");
168+
await settingsPage.open();
169+
await settingsPage.verifyProfileHeading("user1");
163170
await common.signOut();
164171
await context.clearCookies();
165172
});
@@ -247,8 +254,8 @@ test.describe("Configure GitLab Provider", async () => {
247254
});
248255

249256
test.afterAll(async () => {
250-
if (page !== undefined) {
251-
await teardownBrowser(page, test.info());
257+
if (browserSession !== undefined) {
258+
await browserSession.dispose();
252259
}
253260
console.log("[TEST] Starting cleanup...");
254261

0 commit comments

Comments
 (0)