diff --git a/workspaces/backstage/e2e-tests/package.json b/workspaces/backstage/e2e-tests/package.json index a4ea3a3f5..13a156ae0 100644 --- a/workspaces/backstage/e2e-tests/package.json +++ b/workspaces/backstage/e2e-tests/package.json @@ -1,36 +1,36 @@ { - "name": "backstage-e2e-tests", - "version": "1.0.0", - "private": true, - "type": "module", - "engines": { - "node": ">=22", - "yarn": ">=3" - }, - "packageManager": "yarn@3.8.7", - "description": "E2E tests for the plugins in the backstage workspace", - "scripts": { - "test": "playwright test", - "report": "playwright show-report", - "test:ui": "playwright test --ui", - "test:headed": "playwright test --headed", - "lint:check": "eslint .", - "lint:fix": "eslint . --fix", - "prettier:check": "prettier --check .", - "prettier:fix": "prettier --write .", - "check": "tsc --noEmit && yarn lint:check && yarn prettier:check" - }, - "devDependencies": { - "@eslint/js": "^9.39.2", - "@playwright/test": "1.57.0", - "@red-hat-developer-hub/e2e-test-utils": "1.1.10", - "@types/node": "^24.10.1", - "dotenv": "^16.4.7", - "eslint": "^9.39.2", - "eslint-plugin-check-file": "^3.3.1", - "eslint-plugin-playwright": "^2.4.0", - "prettier": "^3.7.4", - "typescript": "^5.9.3", - "typescript-eslint": "^8.50.0" - } + "name": "backstage-e2e-tests", + "version": "1.0.0", + "private": true, + "type": "module", + "engines": { + "node": ">=22", + "yarn": ">=3" + }, + "packageManager": "yarn@3.8.7", + "description": "E2E tests for the plugins in the backstage workspace", + "scripts": { + "test": "playwright test", + "report": "playwright show-report", + "test:ui": "playwright test --ui", + "test:headed": "playwright test --headed", + "lint:check": "eslint .", + "lint:fix": "eslint . --fix", + "prettier:check": "prettier --check .", + "prettier:fix": "prettier --write .", + "check": "tsc --noEmit && yarn lint:check && yarn prettier:check" + }, + "devDependencies": { + "@eslint/js": "^9.39.2", + "@playwright/test": "1.57.0", + "@red-hat-developer-hub/e2e-test-utils": "1.1.15", + "@types/node": "^24.10.1", + "dotenv": "^16.4.7", + "eslint": "^9.39.2", + "eslint-plugin-check-file": "^3.3.1", + "eslint-plugin-playwright": "^2.4.0", + "prettier": "^3.7.4", + "typescript": "^5.9.3", + "typescript-eslint": "^8.50.0" + } } diff --git a/workspaces/backstage/e2e-tests/support/api/rhdh-auth-api-hack.ts b/workspaces/backstage/e2e-tests/support/api/rhdh-auth-api-hack.ts deleted file mode 100644 index 9b90babe8..000000000 --- a/workspaces/backstage/e2e-tests/support/api/rhdh-auth-api-hack.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Page } from "@playwright/test"; - -// here, we spy on the request to get the Backstage token to use APIs -export class RhdhAuthApiHack { - static async getToken(page: Page, provider: "oidc" = "oidc", environment: string = "production") { - try { - const response = await page.request.get( - `/api/auth/${provider}/refresh?optional=&scope=&env=${environment}`, - { - headers: { - // eslint-disable-next-line @typescript-eslint/naming-convention - "x-requested-with": "XMLHttpRequest", - }, - }, - ); - - if (!response.ok()) { - throw new Error(`HTTP error! Status: ${response.status()}`); - } - - const body = await response.json(); - - if ( - typeof body?.backstageIdentity?.token === "string" - ) { - return body.backstageIdentity.token; - } else { - throw new TypeError("Token not found in response body"); - } - } catch (error) { - console.error("Failed to retrieve the token:", error); - - throw error; - } - } -} \ No newline at end of file diff --git a/workspaces/backstage/e2e-tests/tests/config/github-events/app-config-rhdh.yaml b/workspaces/backstage/e2e-tests/tests/config/github-events/app-config-rhdh.yaml index c86f1458e..fd95e7292 100644 --- a/workspaces/backstage/e2e-tests/tests/config/github-events/app-config-rhdh.yaml +++ b/workspaces/backstage/e2e-tests/tests/config/github-events/app-config-rhdh.yaml @@ -11,7 +11,18 @@ events: catalog: rules: - - allow: [Component, API, Resource, System, Domain, Location, Template, User, Group] + - allow: + [ + Component, + API, + Resource, + System, + Domain, + Location, + Template, + User, + Group, + ] providers: github: providerId: diff --git a/workspaces/backstage/e2e-tests/tests/specs/github-events-module.spec.ts b/workspaces/backstage/e2e-tests/tests/specs/github-events-module.spec.ts index a57d67357..c79f6d4a2 100644 --- a/workspaces/backstage/e2e-tests/tests/specs/github-events-module.spec.ts +++ b/workspaces/backstage/e2e-tests/tests/specs/github-events-module.spec.ts @@ -1,8 +1,12 @@ -import { test, expect, request } from "@red-hat-developer-hub/e2e-test-utils/test"; +import { + test, + expect, + request, +} from "@red-hat-developer-hub/e2e-test-utils/test"; import { CustomAPIHelper } from "../../support/api/api-helper"; import { GitHubEventsHelper } from "../../support/api/github-events"; import { createHmac } from "node:crypto"; -import { RhdhAuthApiHack } from "../../support/api/rhdh-auth-api-hack"; +import { AuthApiHelper } from "@red-hat-developer-hub/e2e-test-utils/helpers"; test.describe("GitHub Events Module", () => { let githubEventsHelper: GitHubEventsHelper; @@ -285,15 +289,18 @@ spec: test.beforeEach(async ({ page, uiHelper }) => { if (!staticToken) { + const authApiHelper = new AuthApiHelper(page); await page.goto(rhdhBaseUrl); // Wait for page to be ready and user to be logged in await uiHelper.waitForLoad(); await page.locator("nav").first().waitFor({ state: "visible" }); - + // Wait for user settings or profile button to appear await page - .locator('button[data-testid="user-settings-menu"], [aria-label*="user"]') + .locator( + 'button[data-testid="user-settings-menu"], [aria-label*="user"]', + ) .first() .waitFor({ state: "visible", timeout: 10000 }) .catch(() => {}); @@ -303,7 +310,7 @@ spec: .poll( async () => { try { - const token = await RhdhAuthApiHack.getToken(page); + const token = await authApiHelper.getToken(page); if (token && token.length > 0) { staticToken = token; return true; @@ -314,7 +321,8 @@ spec: } }, { - message: "Token should be retrieved after session is established", + message: + "Token should be retrieved after session is established", timeout: 30000, intervals: [2000], }, @@ -376,11 +384,19 @@ spec: await uiHelper.waitForLoad(10000); await expect - .poll(() => CustomAPIHelper.getGroupMembers(rhdhBaseUrl, staticToken, teamName), { - message: "User should be added to group", - timeout: 60000, - intervals: [3000], - }) + .poll( + () => + CustomAPIHelper.getGroupMembers( + rhdhBaseUrl, + staticToken, + teamName, + ), + { + message: "User should be added to group", + timeout: 60000, + intervals: [3000], + }, + ) .toContain("rhdh-qe"); }); @@ -401,11 +417,19 @@ spec: ); await expect - .poll(() => CustomAPIHelper.getGroupMembers(rhdhBaseUrl, staticToken, teamName), { - message: "User should be added to group before removal test", - timeout: 60000, - intervals: [3000], - }) + .poll( + () => + CustomAPIHelper.getGroupMembers( + rhdhBaseUrl, + staticToken, + teamName, + ), + { + message: "User should be added to group before removal test", + timeout: 60000, + intervals: [3000], + }, + ) .toContain("rhdh-qe"); await CustomAPIHelper.removeUserFromTeam( @@ -426,11 +450,19 @@ spec: await uiHelper.waitForLoad(10000); await expect - .poll(() => CustomAPIHelper.getGroupMembers(rhdhBaseUrl, staticToken, teamName), { - message: "User should be removed from group", - timeout: 60000, - intervals: [3000], - }) + .poll( + () => + CustomAPIHelper.getGroupMembers( + rhdhBaseUrl, + staticToken, + teamName, + ), + { + message: "User should be removed from group", + timeout: 60000, + intervals: [3000], + }, + ) .not.toContain("rhdh-qe"); }); }); diff --git a/workspaces/backstage/e2e-tests/yarn.lock b/workspaces/backstage/e2e-tests/yarn.lock index f1cffe158..313b38cb4 100644 --- a/workspaces/backstage/e2e-tests/yarn.lock +++ b/workspaces/backstage/e2e-tests/yarn.lock @@ -16,6 +16,16 @@ __metadata: languageName: node linkType: hard +"@backstage-community/plugin-rbac-common@npm:1.23.0": + version: 1.23.0 + resolution: "@backstage-community/plugin-rbac-common@npm:1.23.0" + peerDependencies: + "@backstage/errors": ^1.2.7 + "@backstage/plugin-permission-common": ^0.9.5 + checksum: 8cbb67a4854b9a72d329459cf37d05628da4ca4c665fb1e9c34e2dcbcd8d4399264b00bab8e4ee786717e2c0c5b0e3db7ee4eee6705424047a799fbf311eb5f4 + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.8.0, @eslint-community/eslint-utils@npm:^4.9.1": version: 4.9.1 resolution: "@eslint-community/eslint-utils@npm:4.9.1" @@ -293,11 +303,12 @@ __metadata: languageName: node linkType: hard -"@red-hat-developer-hub/e2e-test-utils@npm:1.1.10": - version: 1.1.10 - resolution: "@red-hat-developer-hub/e2e-test-utils@npm:1.1.10" +"@red-hat-developer-hub/e2e-test-utils@npm:1.1.15": + version: 1.1.15 + resolution: "@red-hat-developer-hub/e2e-test-utils@npm:1.1.15" dependencies: "@axe-core/playwright": ^4.11.0 + "@backstage-community/plugin-rbac-common": 1.23.0 "@eslint/js": ^9.39.1 "@keycloak/keycloak-admin-client": ^26.0.0 "@kubernetes/client-node": ^1.4.0 @@ -310,12 +321,13 @@ __metadata: lodash.mergewith: ^4.6.2 otplib: 12.0.1 prettier: ^3.7.4 + proper-lockfile: ^4.1.2 typescript: ^5.9.3 typescript-eslint: ^8.48.1 zx: ^8.8.5 peerDependencies: "@playwright/test": ^1.57.0 - checksum: b12ed69e5b1c9604336e451f50d9e506ef9ba152924927aab4292db39d52e3baecf9d243774b2a4dcd5a325a22c9afa4aa82b9b77463263b3161ab34e941c13d + checksum: 9b92ffbec69b77f263c875a9f3edb672fbe165f3cee8f84c5e2e7b9dd2428b693a2eb9b3375f42c0706960dd7ea2d434e7917f2eb5b6a3762d8f80c18a936c70 languageName: node linkType: hard @@ -618,7 +630,7 @@ __metadata: dependencies: "@eslint/js": ^9.39.2 "@playwright/test": 1.57.0 - "@red-hat-developer-hub/e2e-test-utils": 1.1.10 + "@red-hat-developer-hub/e2e-test-utils": 1.1.15 "@types/node": ^24.10.1 dotenv: ^16.4.7 eslint: ^9.39.2 @@ -1336,7 +1348,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": +"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 @@ -2032,6 +2044,17 @@ __metadata: languageName: node linkType: hard +"proper-lockfile@npm:^4.1.2": + version: 4.1.2 + resolution: "proper-lockfile@npm:4.1.2" + dependencies: + graceful-fs: ^4.2.4 + retry: ^0.12.0 + signal-exit: ^3.0.2 + checksum: 00078ee6a61c216a56a6140c7d2a98c6c733b3678503002dc073ab8beca5d50ca271de4c85fca13b9b8ee2ff546c36674d1850509b84a04a5d0363bcb8638939 + languageName: node + linkType: hard + "pump@npm:^3.0.0": version: 3.0.3 resolution: "pump@npm:3.0.3" @@ -2102,6 +2125,13 @@ __metadata: languageName: node linkType: hard +"signal-exit@npm:^3.0.2": + version: 3.0.7 + resolution: "signal-exit@npm:3.0.7" + checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 + languageName: node + linkType: hard + "smart-buffer@npm:^4.2.0": version: 4.2.0 resolution: "smart-buffer@npm:4.2.0"