Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default defineConfig({
{ text: "Examples", link: "/examples/" },
{ text: "Overlay Testing", link: "/overlay/" },
{
text: "v1.1.39",
text: "v2.2.0",
items: [{ text: "Changelog", link: "/changelog" }],
},
],
Expand Down Expand Up @@ -121,6 +121,14 @@ export default defineConfig({
{ text: "LoginHelper", link: "/guide/helpers/login-helper" },
{ text: "APIHelper", link: "/guide/helpers/api-helper" },
{ text: "AuthApiHelper", link: "/guide/helpers/auth-api-helper" },
{
text: "CatalogApiHelper",
link: "/guide/helpers/catalog-api-helper",
},
{
text: "RhdhNotificationsApi",
link: "/guide/helpers/notifications-api-helper",
},
{ text: "RbacApiHelper", link: "/guide/helpers/rbac-api-helper" },
],
},
Expand Down Expand Up @@ -227,6 +235,14 @@ export default defineConfig({
{ text: "LoginHelper", link: "/api/helpers/login-helper" },
{ text: "APIHelper", link: "/api/helpers/api-helper" },
{ text: "AuthApiHelper", link: "/api/helpers/auth-api-helper" },
{
text: "CatalogApiHelper",
link: "/api/helpers/catalog-api-helper",
},
{
text: "RhdhNotificationsApi",
link: "/api/helpers/notifications-api-helper",
},
{ text: "RbacApiHelper", link: "/api/helpers/rbac-api-helper" },
],
},
Expand Down
25 changes: 25 additions & 0 deletions docs/api/helpers/auth-api-helper.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,28 @@ const token = await authApiHelper.getToken();
// Custom provider
const token = await authApiHelper.getToken('github');
```

## `getSessionAuthToken()`

```typescript
async function getSessionAuthToken(
page: Page,
uiHelper: UIhelper,
baseUrl: string,
): Promise<string>
```

Polls `AuthApiHelper.getToken()` until a non-empty token is returned. Navigates to `baseUrl` and calls `uiHelper.waitForAppReady()` when the first attempt fails.

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `page` | `Page` | Authenticated Playwright page |
| `uiHelper` | `UIhelper` | Used for `waitForAppReady()` after navigation |
| `baseUrl` | `string` | RHDH base URL (e.g. `process.env.RHDH_BASE_URL`) |

**Returns** `Promise<string>`Backstage identity bearer token.

## Related Pages

- [AuthApiHelper Guide](/guide/helpers/auth-api-helper) — usage guide
- [CatalogApiHelper](/api/helpers/catalog-api-helper) — typical consumer of session tokens
85 changes: 85 additions & 0 deletions docs/api/helpers/catalog-api-helper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# CatalogApiHelper API

Static helper for RHDH catalog entity lookups via the REST API.

## Import

```typescript
import { CatalogApiHelper } from "@red-hat-developer-hub/e2e-test-utils/helpers";
```

## Methods

### `entityExists()`

```typescript
static async entityExists(
baseUrl: string,
token: string,
kind: string,
name: string,
namespace?: string,
): Promise<boolean>
```

Returns `true` if the entity exists. Returns `false` on HTTP 404. Rethrows other HTTP errors.

### `getEntity()`

```typescript
static async getEntity(
baseUrl: string,
token: string,
kind: string,
name: string,
namespace?: string,
): Promise<unknown>
```

Fetches `GET /api/catalog/entities/by-name/{kind}/{namespace}/{name}`.

### `getEntityDescription()`

```typescript
static async getEntityDescription(
baseUrl: string,
token: string,
kind: string,
name: string,
namespace?: string,
): Promise<string | undefined>
```

Returns `metadata.description` from the entity JSON.

### `getGroupEntity()`

```typescript
static async getGroupEntity(
baseUrl: string,
token: string,
groupName: string,
): Promise<unknown>
```

### `getGroupMembers()`

```typescript
static async getGroupMembers(
baseUrl: string,
token: string,
groupName: string,
): Promise<string[]>
```

### `dispose()`

```typescript
static async dispose(): Promise<void>
```

Disposes the internal Playwright `APIRequestContext`.

## Related Pages

- [CatalogApiHelper Guide](/guide/helpers/catalog-api-helper) — usage guide and polling patterns
82 changes: 82 additions & 0 deletions docs/api/helpers/notifications-api-helper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# RhdhNotificationsApi API

Typed REST helper for the RHDH notifications API.

## Import

```typescript
import {
RhdhNotificationsApi,
type NotificationRequest,
type NotificationPayload,
type NotificationRecipients,
type NotificationSeverity,
} from "@red-hat-developer-hub/e2e-test-utils/helpers";
```

## Factory

### `build()`

```typescript
static async build(token: string): Promise<RhdhNotificationsApi>
```

Creates an API client using `${RHDH_BASE_URL}/api/` as the base URL.

## Methods

### `createNotification()`

```typescript
async createNotification(
notification: NotificationRequest,
): Promise<APIResponse>
```

`POST /api/notifications`

### `markAllNotificationsAsRead()`

```typescript
async markAllNotificationsAsRead(): Promise<APIResponse>
```

`PATCH /api/notifications` with `{ ids: [], read: true }`.

## Types

### `NotificationSeverity`

```typescript
type NotificationSeverity = "critical" | "high" | "normal" | "low";
```

### `NotificationRequest`

```typescript
interface NotificationRequest {
recipients: NotificationRecipients;
payload: NotificationPayload;
}
```

### `BroadcastRecipients`

```typescript
type BroadcastRecipients = { type: "broadcast" };
```

### `EntityRecipients`

```typescript
type EntityRecipients = {
type: "entity";
entityRef: string | string[];
excludeEntityRef?: string | string[];
};
```

## Related Pages

- [RhdhNotificationsApi Guide](/guide/helpers/notifications-api-helper) — usage examples
10 changes: 8 additions & 2 deletions docs/api/helpers/ui-helper.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# UIhelper API

UI interaction helper for Material-UI components.
UI interaction helper for RHDH components (MUI and BUI).

## Import

Expand All @@ -22,7 +22,13 @@ new UIhelper(page: Page)
```typescript
async waitForLoad(timeout?: number): Promise<void>
```
Wait for page to fully load.
Wait for MUI and BUI loading indicators to clear. Default timeout: `120000` ms.

#### `waitForAppReady()`
```typescript
async waitForAppReady(timeout?: number): Promise<void>
```
Alias for `waitForLoad()`.

#### `dismissQuickstartIfVisible()`
```typescript
Expand Down
5 changes: 5 additions & 0 deletions docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ Complete API documentation for all exports from `@red-hat-developer-hub/e2e-test
- [UIhelper](/api/helpers/ui-helper) - UI interaction methods
- [LoginHelper](/api/helpers/login-helper) - Authentication methods
- [APIHelper](/api/helpers/api-helper) - API interaction methods
- [AuthApiHelper](/api/helpers/auth-api-helper) - Backstage identity tokens
- [`getSessionAuthToken`](/api/helpers/auth-api-helper#getsessionauthtoken) - Resilient token retrieval
- [CatalogApiHelper](/api/helpers/catalog-api-helper) - Catalog REST polling
- [RhdhNotificationsApi](/api/helpers/notifications-api-helper) - Notifications REST API
- [RbacApiHelper](/api/helpers/rbac-api-helper) - RBAC policy management

### Page Objects

Expand Down
32 changes: 19 additions & 13 deletions docs/api/pages/notification-page.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,29 @@ import { NotificationPage } from "@red-hat-developer-hub/e2e-test-utils/pages";
## Constructor

```typescript
new NotificationPage(page: Page)
new NotificationPage(page: Page, uiHelper?: UIhelper)
```

Creates a new NotificationPage instance with an internal `UIhelper`.
Creates a new NotificationPage instance. When `uiHelper` is omitted, an internal `UIhelper` is created.

| Parameter | Type | Description |
|-----------|------|-------------|
| `page` | `Page` | Playwright Page object |
| `uiHelper` | `UIhelper` | Optional fixture UIhelper for shared wait/navigation behavior |

Supports both MUI (legacy) and BUI (new frontend system) selectors.

## Methods

### Navigation

#### `clickNotificationsNavBarItem()`
#### `navigateToNotifications()`

```typescript
async clickNotificationsNavBarItem(): Promise<void>
async navigateToNotifications(): Promise<void>
```

Navigate to the notifications page via the sidebar and wait for it to load.
Navigate to the notifications page via the sidebar (with `/notifications` fallback), dismiss toasts, and wait until the page is ready.

### Notification Selection

Expand All @@ -42,17 +45,20 @@ async selectAllNotifications(): Promise<void>

Select all notifications using the header checkbox.

#### `selectNotification(nth?)`
#### `selectNotification(textOrNth?)`

```typescript
async selectNotification(nth?: number): Promise<void>
async selectNotification(
textOrNth?: string | RegExp | number,
): Promise<void>
```

Select a specific notification by index.
Select a notification by row title or by checkbox index.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `nth` | `number` | `1` | Zero-based index of the notification to select |
| Parameter | Type | Description |
|-----------|------|-------------|
| `textOrNth` | `string \| RegExp` | Row title to select (preferred) |
| `textOrNth` | `number` | Zero-based checkbox index (legacy) |

### Notification Content

Expand Down Expand Up @@ -208,7 +214,7 @@ test("manage notifications", async ({ page }) => {
const notificationPage = new NotificationPage(page);

// Navigate to notifications
await notificationPage.clickNotificationsNavBarItem();
await notificationPage.navigateToNotifications();

// Check for a specific notification
await notificationPage.notificationContains("Build completed successfully");
Expand All @@ -234,7 +240,7 @@ test("manage notifications", async ({ page }) => {
test("clear all notifications", async ({ page }) => {
const notificationPage = new NotificationPage(page);

await notificationPage.clickNotificationsNavBarItem();
await notificationPage.navigateToNotifications();
await notificationPage.markAllNotificationsAsRead();
});
```
Expand Down
17 changes: 16 additions & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,22 @@

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

## [2.1.1] - Current
## [2.2.0] - Current

### Added

- **`UIhelper.waitForAppReady()`**: Waits for MUI and BUI loading indicators to clear (extends `WAIT_OBJECTS` with BUI progress/spinner selectors).
- **`getSessionAuthToken()`**: Retrieves a bearer token from the logged-in browser session without unnecessary navigation.
- **`CatalogApiHelper`**: Static catalog API helper (`entityExists`, `getEntity`, `getEntityDescription`, `getGroupMembers`) for event-driven discovery polling.
- **`RhdhNotificationsApi`**: Typed notifications REST helper with valid broadcast/entity recipient shapes and lowercase severity values.

### Changed

- **`NotificationPage`**: Additive MUI + BUI support — tries legacy selectors (`loading-indicator`, `Severity`, `getByTitle`) and BUI selectors (`Min severity`, `aria-label` bulk actions, row checkboxes). Optional `uiHelper` constructor argument. `selectNotification` accepts a row title (`string`/`RegExp`) or legacy checkbox index (`number`). Renamed `clickNotificationsNavBarItem()` to `navigateToNotifications()`.
- **`CatalogApiHelper.getGroupEntity()`**: Delegates to `getEntity()` instead of duplicating fetch logic.
- **`UIhelper.openSidebar`**: Uses a real `.click()` instead of `dispatchEvent("click")` for more reliable navigation.

## [2.1.1]

### Changed

Expand Down
Loading
Loading