Skip to content

Commit 0d3e851

Browse files
authored
feat(keycloak): add getGroupsOfUser function (#53)
This change adds an additional function to get the effective groups of a user by username so that tests that need to query the state of users and groups can retrieve the groups that a user is part of. This is done by matching the username currently instead of exposign the keycloak user ID given that the current default test user set consists of unique user names. Assisted-By: Cursor Desktop rh-pre-commit.version: 2.3.2 rh-pre-commit.check-secrets: ENABLED
1 parent d40c0b2 commit 0d3e851

6 files changed

Lines changed: 66 additions & 2 deletions

File tree

docs/api/deployment/keycloak-helper.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,23 @@ async getGroups(realm: string): Promise<GroupRepresentation[]>
150150

151151
Get all groups in a realm.
152152

153+
### `getGroupsOfUser()`
154+
155+
```typescript
156+
async getGroupsOfUser(realm: string, username: string): Promise<KeycloakGroupConfig[]>
157+
```
158+
159+
Get the list of groups for a user in a realm. The user is resolved by `username`; no user id is exposed. Useful for assertions in e2e tests (e.g. verifying Backstage user page shows the same groups as Keycloak).
160+
161+
| Parameter | Type | Description |
162+
| --------- | -------- | ------------------------------ |
163+
| `realm` | `string` | Realm name |
164+
| `username`| `string` | Username of the user |
165+
166+
**Returns:** `KeycloakGroupConfig[]` (at least `name`).
167+
168+
Requires `connect()` or `deploy()` to have been called first.
169+
153170
### `deleteUser()`
154171

155172
```typescript

docs/changelog.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22

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

5-
## [1.1.16] - Current
5+
## [1.1.17] - Current
6+
7+
### Added
8+
9+
- **KeycloakHelper.getGroupsOfUser(realm, username)**: Returns groups for a user in a realm; the user is resolved by `username` (id is resolved internally). Intended for e2e assertions that compare Backstage UI to Keycloak data (e.g. catalog users page).
10+
11+
## [1.1.16]
612

713
### Fixed
814

docs/guide/deployment/keycloak-deployment.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,25 @@ const groups = await keycloak.getGroups("rhdh");
171171
await keycloak.deleteGroup("rhdh", "testers");
172172
```
173173

174+
### Using getUsers and getGroupsOfUser in tests
175+
176+
When testing against an existing Keycloak (e.g. RHDH with Keycloak auth), use `connect(config)` with base URL, realm, and client id/secret (or username/password). Then use `getUsers(realm)` to get the list of users and `getGroupsOfUser(realm, user.username)` to get each user's groups for UI assertions (e.g. catalog users page):
177+
178+
```typescript
179+
await keycloak.connect({
180+
baseUrl: process.env.KEYCLOAK_BASE_URL!,
181+
realm: process.env.KEYCLOAK_REALM!,
182+
clientId: process.env.KEYCLOAK_CLIENT_ID!,
183+
clientSecret: process.env.KEYCLOAK_CLIENT_SECRET!,
184+
});
185+
186+
const users = await keycloak.getUsers(realm);
187+
for (const user of users) {
188+
const groups = await keycloak.getGroupsOfUser(realm, user.username);
189+
// Assert Backstage UI shows same groups for this user
190+
}
191+
```
192+
174193
### Realm Management
175194

176195
```typescript

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.16",
3+
"version": "1.1.17",
44
"description": "Test utilities for RHDH E2E tests",
55
"license": "Apache-2.0",
66
"repository": {

src/deployment/keycloak/deployment.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,27 @@ export class KeycloakHelper {
299299
return groups.map((g) => ({ name: g.name! }));
300300
}
301301

302+
/**
303+
* Get groups for a user in a realm (user resolved by username).
304+
*/
305+
async getGroupsOfUser(
306+
realm: string,
307+
username: string,
308+
): Promise<KeycloakGroupConfig[]> {
309+
await this._ensureAdminClient();
310+
this._adminClient!.setConfig({ realmName: realm });
311+
312+
const users = await this._adminClient!.users.find({ username });
313+
if (users.length === 0) {
314+
return [];
315+
}
316+
const user = users[0];
317+
const groups = await this._adminClient!.users.listGroups({
318+
id: user.id!,
319+
});
320+
return groups.map((g) => ({ name: g.name! }));
321+
}
322+
302323
/**
303324
* Delete a user from a realm
304325
*/

src/deployment/keycloak/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export { KeycloakHelper } from "./deployment.js";
2+
export type { KeycloakUserConfig, KeycloakGroupConfig } from "./types.js";

0 commit comments

Comments
 (0)