Skip to content

Commit 7d9b72d

Browse files
committed
feat(playwright): handle some review suggestions
Signed-off-by: Patrick Knight <pknight@redhat.com>
1 parent 11d66e0 commit 7d9b72d

5 files changed

Lines changed: 87 additions & 48 deletions

File tree

docs/changelog.md

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,131 +2,164 @@
22

33
All notable changes to this project will be documented in this file.
44

5-
## [1.1.14] - Current
5+
## [1.1.15] - Current
66

77
### Added
8+
9+
- **`RbacApiHelper`**: New HTTP client for the RHDH RBAC permission API (`/api/permission/`). Uses a static `build(token)` factory to asynchronously initialise a Playwright `APIRequestContext`. Provides `getPoliciesByRole()`, `getConditions()`, `getConditionsByRole()`, `deleteRole()`, `deletePolicy()`, and `deleteCondition()` for managing roles, policies, and conditional permission policies — primarily intended for `afterAll` cleanup. Exported from `@red-hat-developer-hub/e2e-test-utils/helpers`.
10+
- **`AuthApiHelper`**: New helper for retrieving Backstage identity tokens from a running RHDH instance via the auth refresh endpoint (`/api/auth/{provider}/refresh`). Accepts an existing Playwright `Page` and exposes a single `getToken(provider?, environment?)` method. Defaults to the `oidc` provider and `production` environment. Typically used in `beforeAll` to obtain a token for `RbacApiHelper.build()`. Exported from `@red-hat-developer-hub/e2e-test-utils/helpers`.
11+
- **`Response`** utility class (exported alongside `RbacApiHelper`): provides `Response.removeMetadataFromResponse(apiResponse)` to strip server-added `metadata` fields from policy arrays before passing them to delete endpoints.
12+
13+
## [1.1.14]
14+
15+
### Added
16+
817
- **`deploy()` built-in protection**: `rhdh.deploy()` now automatically skips if the deployment already succeeded in the current test run. No code changes needed — existing `beforeAll` patterns work as before, but deployments are no longer repeated when Playwright restarts workers after test failures.
918
- **`test.runOnce(key, fn)`**: Execute any function exactly once per test run, even across worker restarts. Use for expensive pre-deploy operations (external services, setup scripts, data seeding) that `deploy()` alone doesn't cover. Safe to nest with `deploy()`'s built-in protection.
1019
- **Teardown reporter**: Built-in Playwright reporter that automatically deletes Kubernetes namespaces after all tests complete. Active only in CI (`process.env.CI`).
1120
- **`registerTeardownNamespace(projectName, namespace)`**: Register custom namespaces for automatic cleanup. Import from `@red-hat-developer-hub/e2e-test-utils/teardown`.
1221

1322
### Changed
23+
1424
- Namespace cleanup moved from worker fixture to teardown reporter to prevent premature deletion on test failures.
1525

1626
## [1.1.13]
1727

1828
### Added
29+
1930
- Support for GitHub authentication provider
2031

2132
### Changed
22-
- `LoginHelper.loginAsGithubUser` now pulls default user credentials from the following vault keys: `VAULT_GH_USER_ID`, `VAULT_GH_USER_PASS`, `VAULT_GH_2FA_SECRET`
33+
34+
- `LoginHelper.loginAsGithubUser` now pulls default user credentials from the following vault keys: `VAULT_GH_USER_ID`, `VAULT_GH_USER_PASS`, `VAULT_GH_2FA_SECRET`
2335
- `APIHelper.githubRequest` pulls default user token from vault key `VAULT_GITHUB_USER_TOKEN`
2436

2537
### Environment Variables
26-
- `VAULT_GITHUB_OAUTH_OVERLAYS_APP_ID` - ID for GitHub OAuth application used as auth provider
27-
- `VAULT_GITHUB_OAUTH_OVERLAYS_APP_SECRET`- Client secret for GitHub OAuth application
28-
- `VAULT_GH_USER_ID` - GitHub user name
29-
- `VAULT_GH_USER_PASS` - GitHub user password
30-
- `VAULT_GH_2FA_SECRET` - GitHub user secret for 2 factor authentication
31-
- `VAULT_GITHUB_USER_TOKEN` - Github user token
38+
39+
- `VAULT_GITHUB_OAUTH_OVERLAYS_APP_ID` - ID for GitHub OAuth application used as auth provider
40+
- `VAULT_GITHUB_OAUTH_OVERLAYS_APP_SECRET`- Client secret for GitHub OAuth application
41+
- `VAULT_GH_USER_ID` - GitHub user name
42+
- `VAULT_GH_USER_PASS` - GitHub user password
43+
- `VAULT_GH_2FA_SECRET` - GitHub user secret for 2 factor authentication
44+
- `VAULT_GITHUB_USER_TOKEN` - Github user token
3245

3346
## [1.1.12] - Current
3447

3548
### Changed
49+
3650
- **`deploy()` timeout is now configurable**: `deploy()` accepts an optional `{ timeout }` parameter to control the Playwright test timeout during deployment. Defaults to `600_000` (600s). Pass a custom number to override, `0` for no timeout (infinite), or `null` to skip setting the timeout entirely and let the consumer control it.
3751

3852
## [1.1.11]
3953

4054
### Added
55+
4156
- **`runQuietUnlessFailure()`**: New utility that captures command output silently on success and displays full output on failure for better debugging. Used in Keycloak deployment for `helm repo update` and `helm upgrade --install`.
4257

4358
## [1.1.10]
4459

4560
### Fixed
61+
4662
- **`plugins-list.yaml` parsing**: Parse as proper YAML instead of text splitting, correctly handling entries with build flags (e.g., `--embed-package`, `--suppress-native-package`) and YAML comments.
4763

4864
### Changed
65+
4966
- **Video recording**: Changed mode from `"on"` to `"retain-on-failure"` and reduced size from `1920x1080` to `1280x720` to save disk space.
5067
- **Workers and retries**: Now configurable via `PLAYWRIGHT_WORKERS` (default: `"50%"`) and `PLAYWRIGHT_RETRIES` (default: `0`) environment variables.
5168

5269
## [1.1.9]
5370

5471
### Fixed
72+
5573
- **OCI URL replacement with user-provided `dynamic-plugins.yaml`**: When a workspace provides its own `dynamic-plugins.yaml`, plugin package paths were not replaced with OCI URLs for PR builds. Extracted shared `replaceWithOCIUrls()` function so both `generateDynamicPluginsConfigFromMetadata()` and `loadAndInjectPluginMetadata()` code paths now perform OCI replacement when `GIT_PR_NUMBER` is set.
5674

5775
## [1.1.8]
5876

5977
### Fixed
78+
6079
- Fixed namespace deletion race condition during test retries
6180
- Improved 404 error detection for different Kubernetes client versions
6281

6382
### Changed
83+
6484
- Increased default timeouts (300s → 500s) and test timeout (600s)
6585
- Reduced CI retries from 2 to 1
6686
- Added pod diagnostics logging on timeout and periodic status updates
6787

6888
## [1.1.7]
6989

7090
### Fixed
91+
7192
- **Secrets with control characters**: Fixed `SyntaxError: Bad control character in string literal` when secrets contain newlines or special characters (e.g., GitHub App private keys)
7293

7394
### Dependencies
95+
7496
- Added `lodash.clonedeepwith@^4.5.0` for safe environment variable substitution
7597

7698
## [1.1.6]
7799

78100
### Added
101+
79102
- **"next" tag support**: Both Helm and Operator deployments now support `RHDH_VERSION=next`
80103
- Helm: Resolves "next" to semantic version by querying `rhdh-hub-rhel9` image tags
81104
- Operator: Uses `main` branch and `--next` flag instead of release branch
82105

83106
### Changed
107+
84108
- **Default values**: `RHDH_VERSION` defaults to `next` and `INSTALLATION_METHOD` defaults to `helm` when not set
85109

86110
### Environment Variables
111+
87112
- `RHDH_VERSION`: RHDH version to deploy (default: `next`)
88113
- `INSTALLATION_METHOD`: Deployment method - `helm` or `operator` (default: `helm`)
89114

90115
## [1.1.5]
91116

92117
### Added
118+
93119
- **Plugin metadata auto-generation**: When `dynamic-plugins.yaml` doesn't exist, configuration is automatically generated from `metadata/*.yaml` files
94120
- **OCI URL generation for PR builds**: When `GIT_PR_NUMBER` is set, local plugin paths are replaced with OCI URLs (e.g., `oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/my-plugin:pr_1234__1.0.0`)
95121
- Plugin metadata injection into existing `dynamic-plugins.yaml` configurations
96122
- New utilities: `shouldInjectPluginMetadata()`, `generateDynamicPluginsConfigFromMetadata()`, `loadAndInjectPluginMetadata()`, `extractPluginName()`
97123
- **Early pod failure detection**: `waitForPodsWithFailureDetection()` in KubernetesClientHelper detects CrashLoopBackOff, ImagePullBackOff, init container failures, etc. within seconds instead of waiting for full timeout
98124

99125
### Changed
126+
100127
- Plugin versions for OCI URLs are fetched from source repo's `package.json` using `source.json` commit ref
101128
- Metadata handling disabled for periodic builds (when `JOB_NAME` contains `periodic-`)
102129
- Strict error handling for PR builds (fails if source files missing or fetch fails)
103130
- Improved boxen formatting for YAML output
104131
- RHDH and Keycloak deployments now use early failure detection for faster error reporting
105132

106133
### Environment Variables
134+
107135
- `GIT_PR_NUMBER`: Enables OCI URL generation for PR builds
108136
- `RHDH_SKIP_PLUGIN_METADATA_INJECTION`: Disables all metadata handling
109137

110138
## [1.1.4]
111139

112140
### Fixed
141+
113142
- Keycloak: Use plain HTTP route to avoid certificate issues (#19)
114143

115144
### Security
145+
116146
- Bump `lodash` from 4.17.21 to 4.17.23
117147
- Bump `tar` from 7.5.2 to 7.5.6
118148

119149
## [1.1.3]
120150

121151
### Added
152+
122153
- Comprehensive VitePress documentation site (#14)
123154

124155
### Fixed
156+
125157
- Corepack setup for Yarn 3 in CI workflow (#16)
126158

127159
## [1.1.2]
128160

129161
### Added
162+
130163
- Keycloak integration with modular auth configuration (#8)
131164
- KeycloakHelper class for Keycloak deployment and management
132165
- Support for guest and Keycloak authentication providers
@@ -135,19 +168,22 @@ All notable changes to this project will be documented in this file.
135168
- Keycloak integration documentation (#9)
136169

137170
### Changed
171+
138172
- Improved RHDHDeployment class with `configure()` method
139173
- Enhanced configuration merging for auth-specific configs
140174
- Better environment variable handling
141175

142176
## [1.1.1]
143177

144178
### Added
179+
145180
- Playwright helpers: UIHelper, LoginHelper, APIHelper (#7)
146181
- Page objects: CatalogPage, HomePage, CatalogImportPage, ExtensionsPage, NotificationPage
147182

148183
## [1.1.0]
149184

150185
### Added
186+
151187
- Initial release of `@red-hat-developer-hub/e2e-test-utils`
152188
- RHDHDeployment class for RHDH deployment
153189
- Playwright test fixtures (rhdh, uiHelper, loginHelper, baseURL)
@@ -160,11 +196,13 @@ All notable changes to this project will be documented in this file.
160196
- Support for Helm and Operator deployment methods
161197

162198
### Fixed
199+
163200
- Config file resolution for published package (#6)
164201

165202
## [1.0.0]
166203

167204
### Added
205+
168206
- Initial project setup
169207
- Basic deployment functionality
170208
- Playwright integration
@@ -178,21 +216,23 @@ All notable changes to this project will be documented in this file.
178216
1. **Update imports** - No changes required
179217
2. **Configure authentication** - Use the new `auth` option:
180218
```typescript
181-
await rhdh.configure({ auth: "keycloak" });
219+
await rhdh.configure({ auth: 'keycloak' });
182220
```
183221
3. **Keycloak auto-deployment** - Keycloak is now automatically deployed unless `SKIP_KEYCLOAK_DEPLOYMENT=true`
184222

185223
### New Authentication Configuration
186224

187225
Before (1.0.x):
226+
188227
```typescript
189228
// Manual Keycloak setup required
190229
await rhdh.deploy();
191230
```
192231

193232
After (1.1.x):
233+
194234
```typescript
195235
// Keycloak is auto-deployed and configured
196-
await rhdh.configure({ auth: "keycloak" });
236+
await rhdh.configure({ auth: 'keycloak' });
197237
await rhdh.deploy();
198238
```

docs/guide/helpers/auth-api-helper.md

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -56,42 +56,6 @@ const token = await authApiHelper.getToken('github');
5656
const token = await authApiHelper.getToken('oidc', 'development');
5757
```
5858

59-
## Complete Example
60-
61-
### Fetching a Token to Use with RbacApiHelper
62-
63-
A common pattern is to retrieve a token after login and pass it to `RbacApiHelper` (or another API helper) to make authenticated API calls:
64-
65-
```typescript
66-
import { test } from '@red-hat-developer-hub/e2e-test-utils/test';
67-
import {
68-
AuthApiHelper,
69-
RbacApiHelper,
70-
} from '@red-hat-developer-hub/e2e-test-utils/helpers';
71-
72-
test.describe('RBAC policy management', () => {
73-
let rbacApiHelper: RbacApiHelper;
74-
75-
test.beforeAll(async ({ page, loginHelper }) => {
76-
// Log in first so the page session is authenticated
77-
await page.goto('/');
78-
await loginHelper.loginAsKeycloakUser();
79-
80-
// Retrieve the Backstage identity token
81-
const authApiHelper = new AuthApiHelper(page);
82-
const token = await authApiHelper.getToken();
83-
84-
// Build the RBAC helper with the token
85-
rbacApiHelper = await RbacApiHelper.build(token);
86-
});
87-
88-
test('verify role policies exist', async () => {
89-
const response = await rbacApiHelper.getPoliciesByRole('my-role');
90-
// assert on response...
91-
});
92-
});
93-
```
94-
9559
## Error Handling
9660

9761
`getToken` throws on HTTP errors or if the token is missing from the response body. Wrap calls in a try/catch when you need to handle failures gracefully:
@@ -114,3 +78,4 @@ try {
11478
- [RbacApiHelper](/guide/helpers/rbac-api-helper) — uses tokens obtained from `AuthApiHelper`
11579
- [LoginHelper](/guide/helpers/login-helper) — authenticates the browser session before calling `getToken`
11680
- [APIHelper](/guide/helpers/api-helper) — catalog and GitHub API operations
81+
- [Common Patterns](/overlay/reference/patterns#fetching-a-token-to-use-with-rbacapihelper) — example of using `getToken` with `RbacApiHelper`

docs/overlay/reference/patterns.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,40 @@ test.describe("Plugin tests", () => {
2424
});
2525
```
2626

27+
### Fetching a Token to Use with RbacApiHelper
28+
29+
A common pattern is to retrieve a Backstage identity token after login and pass it to `RbacApiHelper` (or another API helper) to make authenticated API calls:
30+
31+
```typescript
32+
import { test } from '@red-hat-developer-hub/e2e-test-utils/test';
33+
import {
34+
AuthApiHelper,
35+
RbacApiHelper,
36+
} from '@red-hat-developer-hub/e2e-test-utils/helpers';
37+
38+
test.describe('RBAC policy management', () => {
39+
let rbacApiHelper: RbacApiHelper;
40+
41+
test.beforeAll(async ({ page, loginHelper }) => {
42+
// Log in first so the page session is authenticated
43+
await page.goto('/');
44+
await loginHelper.loginAsKeycloakUser();
45+
46+
// Retrieve the Backstage identity token
47+
const authApiHelper = new AuthApiHelper(page);
48+
const token = await authApiHelper.getToken();
49+
50+
// Build the RBAC helper with the token
51+
rbacApiHelper = await RbacApiHelper.build(token);
52+
});
53+
54+
test('verify role policies exist', async () => {
55+
const response = await rbacApiHelper.getPoliciesByRole('my-role');
56+
// assert on response...
57+
});
58+
});
59+
```
60+
2761
## Project and Spec Best Practices
2862

2963
Each Playwright project name creates a **separate namespace**. To keep deployments fast and predictable:

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@red-hat-developer-hub/e2e-test-utils",
3-
"version": "1.1.14",
3+
"version": "1.1.15",
44
"description": "Test utilities for RHDH E2E tests",
55
"license": "Apache-2.0",
66
"repository": {

src/playwright/helpers/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ export { GITHUB_API_ENDPOINTS } from "./api-endpoints.js";
22
export { APIHelper } from "./api-helper.js";
33
export { LoginHelper, setupBrowser } from "./common.js";
44
export { UIhelper } from "./ui-helper.js";
5-
export { RbacApiHelper } from "./rbac-api-helper.js";
5+
export { RbacApiHelper, Policy, Response } from "./rbac-api-helper.js";
66
export { AuthApiHelper } from "./auth-api-helper.js";

0 commit comments

Comments
 (0)