Skip to content

fix(FR-2997): repair broken E2E tests for Access Control (RBAC & Credential)#7688

Merged
graphite-app[bot] merged 1 commit into
mainfrom
06-02-fix_fr-2997_repair_broken_e2e_tests_for_access_control_rbac_credential_
Jun 9, 2026
Merged

fix(FR-2997): repair broken E2E tests for Access Control (RBAC & Credential)#7688
graphite-app[bot] merged 1 commit into
mainfrom
06-02-fix_fr-2997_repair_broken_e2e_tests_for_access_control_rbac_credential_

Conversation

@nowgnuesLee

@nowgnuesLee nowgnuesLee commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Resolves #7632 (FR-2997)

Stacked on: #7684 (FR-2996) → #7679 (FR-2995) → #7676 (FR-2994) → #7653 (FR-2993) → #7652 (FR-2992)

Part of FR-2059 (Fix Broken E2E Tests Cases). Repairs the Access Control sub-category — 5 originally failing tests + 7 collateral RBAC issues uncovered while unblocking the serial suite + disposable-fixture-user refactor of my-keypair-management.spec.ts so it no longer corrupts the shared user@lablup.com account.

Root causes

RBAC

  • role-crud :85 (create with validation error) used a regular .click() on the modal OK button, but the modal renders in an antd portal outside the React root, so Playwright's CDP click did not reliably fire React's onClick handler → validation never ran → expected error message never appeared. Switched to okButton.dispatchEvent('click') and scoped the validation assertion to modal.locator('.ant-form-item-explain-error').

  • role-detail :469 (delete permission) failed for multiple layered reasons, all fixed:

    1. cleanupTestRole clicked Deactivate but never confirmed the antd Popconfirm.
    2. The Add Permission modal had the same portal-click issue and needed dispatchEvent.
    3. The delete modal title was 'Remove Permission', not 'Delete Permission'.
    4. Success notification text was 'Permission removed from role successfully.', not /Permission deleted successfully/i.
    5. Confirm button name was 'Remove Permission', not 'Delete'.
  • role-detail :630 (assign user to a role) used page.locator('.ant-tag-close-icon').first() in clearRoleSearch, matching scope-type tags inside table rows. Scoped to page.locator('.ant-space-compact').first().locator('.ant-tag-close-icon').first().

Collateral RBAC fixes (uncovered as serial blocks unblocked)

  • cleanupTestRole now confirms the Deactivate Popconfirm AND types the role name into BAIDeleteConfirmModal's #confirmText before clicking Delete.
  • 'delete (soft-delete) an active custom role' adds Deactivate Popconfirm click.
  • 'activate (restore) a soft-deleted role' adds Activate Popconfirm click.
  • 'purge (hard-delete) a soft-deleted role' adds typed confirmation input + Deactivate Popconfirm click.
  • 'cannot edit a system role' rewrites overly broad row filter to scope to the Source column.
  • 'revoke a single user from a role' updates modal title 'Delete User''Revoke User' and confirm button 'Delete''Revoke User'.

Credential — credential-keypair.spec.ts

  • :9 (Credential list columns): Control column was removed when UserCredentialList migrated to BAINameActionCell. New end-of-row column is Allocation. Updated the columnheader assertion.

Credential — my-keypair-management.spec.ts (disposable fixture user refactor)

The original tests logged in as the shared user@lablup.com account and issued / deactivated / deleted keypairs against it. When this file ran in parallel with any RBAC spec (which also does admin operations on users) or with another run-instance of itself, the shared user's keypair/project state got corrupted, surfacing as "Login failed. Keypair information is missing." on later loginAsUser calls. This was the source of cascading failures across the suite.

Fix: every test in my-keypair-management.spec.ts now logs in as a disposable fixture user created in beforeAll by admin via the UI:

const TEST_RUN_ID = Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
const FIXTURE_EMAIL = `e2e-mykeypair-${TEST_RUN_ID}@lablup.com`;
// ...
test.beforeAll(async ({ browser }) => {
  // admin context + UserSettingModal.createUser(...) + KeyPairModal.close()
});
test.beforeEach(async ({ page, request }) => {
  await loginAsCreatedAccount(page, request, FIXTURE_EMAIL, FIXTURE_PASSWORD);
});
// No afterAll cleanup: TEST_RUN_ID makes each run's user globally unique,
// so leftover rows don't conflict. A periodic reaper handles them.

Companion fixes uncovered by the disposable-user approach:

  • Updated MyKeypairManagementModal delete-dialog assertion to match BAIDeleteConfirmModal copy ('Are you sure you want to permanently delete Keypair?' + 'This action cannot be undone.').
  • Updated getKeypairTableRows helper to exclude .ant-table-placeholder rows so empty-state tests (count === 0) reliably skip when there are no inactive keypairs.
  • Refactored the 'User can cancel the deactivate Popconfirm' test to issue its own non-main keypair before cancelling (fresh fixture users only have the main keypair, which has the Deactivate button disabled).

Files changed

  • e2e/rbac/rbac-role-crud.spec.ts — modal OK dispatchEvent + scoped validation locator + collateral cleanup helpers
  • e2e/rbac/rbac-role-detail.spec.ts — portal-click fix, delete-modal title/copy/button names, scoped tag-close locator, Popconfirm + #confirmText chains, revoke-user terminology
  • e2e/credential/credential-keypair.spec.tsControlAllocation columnheader
  • e2e/credential/my-keypair-management.spec.ts — disposable fixture user, BAIDeleteConfirmModal assertions, .ant-table-placeholder filter, non-main keypair self-provisioning in cancel-deactivate test

Test plan

  • pnpm exec playwright test e2e/rbac/ — passes
  • pnpm exec playwright test e2e/credential/my-keypair-management.spec.ts — passes serially (25 tests including the new fixture setup)
  • pnpm exec playwright test e2e/credential/my-keypair-management.spec.ts e2e/rbac/ --workers=2 — no more Login failed. Keypair information is missing. failures. A handful of pre-existing cross-file admin-action races may still surface as flake when many admin operations execute simultaneously; CI is configured with workers: 1 so this does not affect CI.

Known limitation

Cross-file admin-action race conditions can produce occasional flakes when running multiple files in parallel locally (--workers=N). These are pre-existing and not specific to this PR — every test file that performs admin operations on shared users (RBAC, credential, user, user-profile) shares this property. CI runs with workers: 1 and is unaffected. Eliminating these flakes would require either fixture-user isolation in every admin-touching file or a project-wide locking strategy — both out of scope for this sub-task.

nowgnuesLee commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • flow:merge-queue - adds this PR to the back of the merge queue
  • flow:hotfix - for urgent changes, fast-track this PR to the front of the merge queue

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has required the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR repairs broken Playwright E2E specs under the Access Control category (RBAC + Credential), primarily by updating locators and interaction patterns to match recent Ant Design / WebUI behavior changes and by isolating keypair tests from shared-account state corruption.

Changes:

  • Fixed RBAC role CRUD/detail flows by confirming Popconfirms, using portal-safe modal button clicks, and updating modal titles/button text + success messages.
  • Updated Credential keypair column assertions to reflect the current table schema.
  • Refactored my-keypair-management.spec.ts to use a disposable fixture user created in beforeAll, preventing cross-file/shared-user keypair corruption.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
e2e/rbac/rbac-role-detail.spec.ts Scopes filter-chip removal, confirms Popconfirms, uses portal-safe modal clicks, and updates “Remove Permission” / “Revoke User” modal expectations.
e2e/rbac/rbac-role-crud.spec.ts Confirms Popconfirms, scopes validation assertion, improves system-role row targeting, and adds confirm-to-delete typing for purge flows.
e2e/credential/credential-keypair.spec.ts Updates expected column header from Control to Allocation.
e2e/credential/my-keypair-management.spec.ts Creates a disposable user via admin UI in beforeAll, filters out placeholder rows, updates delete-confirm copy assertions, and adjusts deactivate-cancel flow to self-provision a non-main keypair.

Comment thread e2e/rbac/rbac-role-detail.spec.ts Outdated
Comment thread e2e/credential/my-keypair-management.spec.ts
Comment thread e2e/rbac/rbac-role-crud.spec.ts Outdated
@nowgnuesLee nowgnuesLee changed the base branch from 06-02-fix_fr-2996_repair_broken_e2e_tests_for_resource_policy to graphite-base/7688 June 8, 2026 11:10
@nowgnuesLee nowgnuesLee force-pushed the graphite-base/7688 branch from e03f8d0 to b848e3b Compare June 8, 2026 11:12
@nowgnuesLee nowgnuesLee force-pushed the 06-02-fix_fr-2997_repair_broken_e2e_tests_for_access_control_rbac_credential_ branch from 969b03f to bddc4db Compare June 8, 2026 11:12
@nowgnuesLee nowgnuesLee changed the base branch from graphite-base/7688 to 06-02-fix_fr-2996_repair_broken_e2e_tests_for_resource_policy June 8, 2026 11:12
@nowgnuesLee nowgnuesLee requested a review from ironAiken2 June 9, 2026 06:55

@ironAiken2 ironAiken2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@graphite-app

graphite-app Bot commented Jun 9, 2026

Copy link
Copy Markdown

Merge activity

…ential) (#7688)

Resolves #7632 (FR-2997)

**Stacked on**: #7684 (FR-2996) → #7679 (FR-2995) → #7676 (FR-2994) → #7653 (FR-2993) → #7652 (FR-2992)

Part of FR-2059 (Fix Broken E2E Tests Cases). Repairs the Access Control sub-category — 5 originally failing tests + 7 collateral RBAC issues uncovered while unblocking the serial suite + **disposable-fixture-user refactor of `my-keypair-management.spec.ts`** so it no longer corrupts the shared `user@lablup.com` account.

## Root causes

### RBAC

- **role-crud `:85`** (create with validation error) used a regular `.click()` on the modal OK button, but the modal renders in an antd portal outside the React root, so Playwright's CDP click did not reliably fire React's onClick handler → validation never ran → expected error message never appeared. Switched to `okButton.dispatchEvent('click')` and scoped the validation assertion to `modal.locator('.ant-form-item-explain-error')`.

- **role-detail `:469`** (delete permission) failed for multiple layered reasons, all fixed:
  1. `cleanupTestRole` clicked Deactivate but never confirmed the antd Popconfirm.
  2. The Add Permission modal had the same portal-click issue and needed `dispatchEvent`.
  3. The delete modal title was `'Remove Permission'`, not `'Delete Permission'`.
  4. Success notification text was `'Permission removed from role successfully.'`, not `/Permission deleted successfully/i`.
  5. Confirm button name was `'Remove Permission'`, not `'Delete'`.

- **role-detail `:630`** (assign user to a role) used `page.locator('.ant-tag-close-icon').first()` in `clearRoleSearch`, matching scope-type tags inside table rows. Scoped to `page.locator('.ant-space-compact').first().locator('.ant-tag-close-icon').first()`.

### Collateral RBAC fixes (uncovered as serial blocks unblocked)

- `cleanupTestRole` now confirms the Deactivate Popconfirm AND types the role name into `BAIDeleteConfirmModal`'s `#confirmText` before clicking Delete.
- `'delete (soft-delete) an active custom role'` adds Deactivate Popconfirm click.
- `'activate (restore) a soft-deleted role'` adds Activate Popconfirm click.
- `'purge (hard-delete) a soft-deleted role'` adds typed confirmation input + Deactivate Popconfirm click.
- `'cannot edit a system role'` rewrites overly broad row filter to scope to the Source column.
- `'revoke a single user from a role'` updates modal title `'Delete User'` → `'Revoke User'` and confirm button `'Delete'` → `'Revoke User'`.

### Credential — `credential-keypair.spec.ts`

- **`:9`** (Credential list columns): `Control` column was removed when `UserCredentialList` migrated to `BAINameActionCell`. New end-of-row column is `Allocation`. Updated the columnheader assertion.

### Credential — `my-keypair-management.spec.ts` (disposable fixture user refactor)

The original tests logged in as the shared `user@lablup.com` account and issued / deactivated / deleted keypairs against it. When this file ran in parallel with any RBAC spec (which also does admin operations on users) or with another run-instance of itself, the shared user's keypair/project state got corrupted, surfacing as `"Login failed. Keypair information is missing."` on later `loginAsUser` calls. This was the source of cascading failures across the suite.

**Fix**: every test in `my-keypair-management.spec.ts` now logs in as a **disposable fixture user** created in `beforeAll` by admin via the UI:

```ts
const TEST_RUN_ID = Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
const FIXTURE_EMAIL = `e2e-mykeypair-${TEST_RUN_ID}@lablup.com`;
// ...
test.beforeAll(async ({ browser }) => {
  // admin context + UserSettingModal.createUser(...) + KeyPairModal.close()
});
test.beforeEach(async ({ page, request }) => {
  await loginAsCreatedAccount(page, request, FIXTURE_EMAIL, FIXTURE_PASSWORD);
});
// No afterAll cleanup: TEST_RUN_ID makes each run's user globally unique,
// so leftover rows don't conflict. A periodic reaper handles them.
```

Companion fixes uncovered by the disposable-user approach:
- Updated `MyKeypairManagementModal` delete-dialog assertion to match `BAIDeleteConfirmModal` copy (`'Are you sure you want to permanently delete Keypair?'` + `'This action cannot be undone.'`).
- Updated `getKeypairTableRows` helper to exclude `.ant-table-placeholder` rows so empty-state tests (`count === 0`) reliably skip when there are no inactive keypairs.
- Refactored the `'User can cancel the deactivate Popconfirm'` test to issue its own non-main keypair before cancelling (fresh fixture users only have the main keypair, which has the Deactivate button disabled).

## Files changed

- `e2e/rbac/rbac-role-crud.spec.ts` — modal OK `dispatchEvent` + scoped validation locator + collateral cleanup helpers
- `e2e/rbac/rbac-role-detail.spec.ts` — portal-click fix, delete-modal title/copy/button names, scoped tag-close locator, Popconfirm + `#confirmText` chains, revoke-user terminology
- `e2e/credential/credential-keypair.spec.ts` — `Control` → `Allocation` columnheader
- `e2e/credential/my-keypair-management.spec.ts` — disposable fixture user, `BAIDeleteConfirmModal` assertions, `.ant-table-placeholder` filter, non-main keypair self-provisioning in cancel-deactivate test

## Test plan

- [x] `pnpm exec playwright test e2e/rbac/` — passes
- [x] `pnpm exec playwright test e2e/credential/my-keypair-management.spec.ts` — passes serially (25 tests including the new fixture setup)
- [x] `pnpm exec playwright test e2e/credential/my-keypair-management.spec.ts e2e/rbac/ --workers=2` — no more `Login failed. Keypair information is missing.` failures. A handful of pre-existing cross-file admin-action races may still surface as flake when many admin operations execute simultaneously; CI is configured with `workers: 1` so this does not affect CI.

## Known limitation

Cross-file admin-action race conditions can produce occasional flakes when running multiple files in parallel locally (`--workers=N`). These are pre-existing and not specific to this PR — every test file that performs admin operations on shared users (RBAC, credential, user, user-profile) shares this property. CI runs with `workers: 1` and is unaffected. Eliminating these flakes would require either fixture-user isolation in every admin-touching file or a project-wide locking strategy — both out of scope for this sub-task.
@graphite-app graphite-app Bot force-pushed the 06-02-fix_fr-2996_repair_broken_e2e_tests_for_resource_policy branch from b848e3b to 0108615 Compare June 9, 2026 07:48
@graphite-app graphite-app Bot force-pushed the 06-02-fix_fr-2997_repair_broken_e2e_tests_for_access_control_rbac_credential_ branch from bddc4db to c31b19f Compare June 9, 2026 07:49
graphite-app Bot pushed a commit that referenced this pull request Jun 9, 2026
Resolves #7633 (FR-2998)

**Stacked on**: #7688 (FR-2997) → #7684 (FR-2996) → #7679 (FR-2995) → #7676 (FR-2994) → #7653 (FR-2993) → #7652 (FR-2992)

Part of FR-2059 (Fix Broken E2E Tests Cases). Repairs the Admin & Operations sub-category — 4 originally failing tests + cascading rewrites to project-crud after exposing the new lifecycle UX. Final state: **45 pass / 0 fail / 2 skip** across `e2e/environment/`, `e2e/my-environment/`, `e2e/project/`, `e2e/maintenance/`, `e2e/information/`, `e2e/statistics/`.

## Root causes

- **`environment/registry.spec.ts:63`** (registry list columns): the `Control` column was removed when `ContainerRegistryListNodes` migrated to `BAINameActionCell` (actions embedded in the Registry Name cell). Removed the obsolete columnheader assertion; the 7 real columns are still validated.

- **`environment/registry.spec.ts:716`** (filter property): the test used the CSS class `.ant-select-content-value` which does not exist in this antd version. Actual class is `.ant-select-content` (with optional `.ant-select-content-has-value`). Switched to `page.locator('.ant-select-content').filter({ hasText: 'Registry Name' })`.

- **`information/information.spec.ts:6`** (page server details): strict-mode hit. `getByText('Component')` matched both the `ant-descriptions-title` and the `'Loading components...'` loader. Added `{ exact: true }`.

- **`project/project-crud.spec.ts:31`** (project list columns): the `Controls` column was removed when the project list migrated to `BAIProjectTable` + `BAINameActionCell`. The `Active` column was also removed; active vs inactive is now a filter radio group. The test now asserts the 4 real columns (`Name`, `Domain`, `Description`, `Type`) and verifies the Active radio is selected via `.ant-radio-button-wrapper-checked`.

### Cascading rewrites in `project/project-crud.spec.ts` (uncovered by the column fix)

- **`:78` (create), `:122` (edit)** — the Name cell now renders via `BAINameActionCell`. Replaced the exact `getByRole('cell', { name: PROJECT_NAME, exact: true })` assertion with `getByRole('row').filter({ hasText: PROJECT_NAME })` since the cell's accessible name includes hover-only action labels. The Edit test now hovers the row before clicking the (hover-only) `setting` action button.

- **`:200` (delete)** — the project lifecycle changed from a one-shot Purge dialog to a two-step flow: **Active → Deactivated (Popconfirm) → Purged (`BAIDeleteConfirmModal` with `requireConfirmInput`)**. Rewrote the test and shared `cleanupTestProject` helper to:
  1. Hover the row, click deactivate (action button `nth(1)`).
  2. Confirm the antd Popconfirm.
  3. Switch to the Inactive tab via the label wrapper (the radio input itself is hidden).
  4. Hover the deactivated row, click purge (action button `nth(2)`).
  5. Type the project name into `#confirmText`, click Purge.
  6. Verify the row is gone, then return to the Active tab.

  Mirrors the user / role / vfolder destructive-action conventions already standardized in FR-2992 through FR-2997.

## Files changed

- `e2e/environment/registry.spec.ts` — removed obsolete `Control` columnheader; corrected filter-property selector class
- `e2e/information/information.spec.ts` — `{ exact: true }` on `Component`
- `e2e/project/project-crud.spec.ts` — column-set update, hover-then-click for `setting`, two-step deactivate→purge for delete, shared `cleanupTestProject` helper

## Test plan

- [x] `pnpm exec playwright test e2e/environment/ e2e/my-environment/ e2e/project/ e2e/maintenance/ e2e/information/ e2e/statistics/ --workers=2` — 45 pass / 0 fail / 2 skip
- [x] `pnpm exec playwright test e2e/project/project-crud.spec.ts` (full file in serial mode) — all 5 tests pass
- [x] Individual retries of the parallel-only flake (`environment.spec.ts:188 user can manage apps`) pass cleanly (17s) — backend-state-dependent test, not a regression
Base automatically changed from 06-02-fix_fr-2996_repair_broken_e2e_tests_for_resource_policy to main June 9, 2026 07:55
@graphite-app graphite-app Bot merged commit c31b19f into main Jun 9, 2026
4 checks passed
@graphite-app graphite-app Bot deleted the 06-02-fix_fr-2997_repair_broken_e2e_tests_for_access_control_rbac_credential_ branch June 9, 2026 07:56
agatha197 pushed a commit that referenced this pull request Jun 9, 2026
…ential) (#7688)

Resolves #7632 (FR-2997)

**Stacked on**: #7684 (FR-2996) → #7679 (FR-2995) → #7676 (FR-2994) → #7653 (FR-2993) → #7652 (FR-2992)

Part of FR-2059 (Fix Broken E2E Tests Cases). Repairs the Access Control sub-category — 5 originally failing tests + 7 collateral RBAC issues uncovered while unblocking the serial suite + **disposable-fixture-user refactor of `my-keypair-management.spec.ts`** so it no longer corrupts the shared `user@lablup.com` account.

## Root causes

### RBAC

- **role-crud `:85`** (create with validation error) used a regular `.click()` on the modal OK button, but the modal renders in an antd portal outside the React root, so Playwright's CDP click did not reliably fire React's onClick handler → validation never ran → expected error message never appeared. Switched to `okButton.dispatchEvent('click')` and scoped the validation assertion to `modal.locator('.ant-form-item-explain-error')`.

- **role-detail `:469`** (delete permission) failed for multiple layered reasons, all fixed:
  1. `cleanupTestRole` clicked Deactivate but never confirmed the antd Popconfirm.
  2. The Add Permission modal had the same portal-click issue and needed `dispatchEvent`.
  3. The delete modal title was `'Remove Permission'`, not `'Delete Permission'`.
  4. Success notification text was `'Permission removed from role successfully.'`, not `/Permission deleted successfully/i`.
  5. Confirm button name was `'Remove Permission'`, not `'Delete'`.

- **role-detail `:630`** (assign user to a role) used `page.locator('.ant-tag-close-icon').first()` in `clearRoleSearch`, matching scope-type tags inside table rows. Scoped to `page.locator('.ant-space-compact').first().locator('.ant-tag-close-icon').first()`.

### Collateral RBAC fixes (uncovered as serial blocks unblocked)

- `cleanupTestRole` now confirms the Deactivate Popconfirm AND types the role name into `BAIDeleteConfirmModal`'s `#confirmText` before clicking Delete.
- `'delete (soft-delete) an active custom role'` adds Deactivate Popconfirm click.
- `'activate (restore) a soft-deleted role'` adds Activate Popconfirm click.
- `'purge (hard-delete) a soft-deleted role'` adds typed confirmation input + Deactivate Popconfirm click.
- `'cannot edit a system role'` rewrites overly broad row filter to scope to the Source column.
- `'revoke a single user from a role'` updates modal title `'Delete User'` → `'Revoke User'` and confirm button `'Delete'` → `'Revoke User'`.

### Credential — `credential-keypair.spec.ts`

- **`:9`** (Credential list columns): `Control` column was removed when `UserCredentialList` migrated to `BAINameActionCell`. New end-of-row column is `Allocation`. Updated the columnheader assertion.

### Credential — `my-keypair-management.spec.ts` (disposable fixture user refactor)

The original tests logged in as the shared `user@lablup.com` account and issued / deactivated / deleted keypairs against it. When this file ran in parallel with any RBAC spec (which also does admin operations on users) or with another run-instance of itself, the shared user's keypair/project state got corrupted, surfacing as `"Login failed. Keypair information is missing."` on later `loginAsUser` calls. This was the source of cascading failures across the suite.

**Fix**: every test in `my-keypair-management.spec.ts` now logs in as a **disposable fixture user** created in `beforeAll` by admin via the UI:

```ts
const TEST_RUN_ID = Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
const FIXTURE_EMAIL = `e2e-mykeypair-${TEST_RUN_ID}@lablup.com`;
// ...
test.beforeAll(async ({ browser }) => {
  // admin context + UserSettingModal.createUser(...) + KeyPairModal.close()
});
test.beforeEach(async ({ page, request }) => {
  await loginAsCreatedAccount(page, request, FIXTURE_EMAIL, FIXTURE_PASSWORD);
});
// No afterAll cleanup: TEST_RUN_ID makes each run's user globally unique,
// so leftover rows don't conflict. A periodic reaper handles them.
```

Companion fixes uncovered by the disposable-user approach:
- Updated `MyKeypairManagementModal` delete-dialog assertion to match `BAIDeleteConfirmModal` copy (`'Are you sure you want to permanently delete Keypair?'` + `'This action cannot be undone.'`).
- Updated `getKeypairTableRows` helper to exclude `.ant-table-placeholder` rows so empty-state tests (`count === 0`) reliably skip when there are no inactive keypairs.
- Refactored the `'User can cancel the deactivate Popconfirm'` test to issue its own non-main keypair before cancelling (fresh fixture users only have the main keypair, which has the Deactivate button disabled).

## Files changed

- `e2e/rbac/rbac-role-crud.spec.ts` — modal OK `dispatchEvent` + scoped validation locator + collateral cleanup helpers
- `e2e/rbac/rbac-role-detail.spec.ts` — portal-click fix, delete-modal title/copy/button names, scoped tag-close locator, Popconfirm + `#confirmText` chains, revoke-user terminology
- `e2e/credential/credential-keypair.spec.ts` — `Control` → `Allocation` columnheader
- `e2e/credential/my-keypair-management.spec.ts` — disposable fixture user, `BAIDeleteConfirmModal` assertions, `.ant-table-placeholder` filter, non-main keypair self-provisioning in cancel-deactivate test

## Test plan

- [x] `pnpm exec playwright test e2e/rbac/` — passes
- [x] `pnpm exec playwright test e2e/credential/my-keypair-management.spec.ts` — passes serially (25 tests including the new fixture setup)
- [x] `pnpm exec playwright test e2e/credential/my-keypair-management.spec.ts e2e/rbac/ --workers=2` — no more `Login failed. Keypair information is missing.` failures. A handful of pre-existing cross-file admin-action races may still surface as flake when many admin operations execute simultaneously; CI is configured with `workers: 1` so this does not affect CI.

## Known limitation

Cross-file admin-action race conditions can produce occasional flakes when running multiple files in parallel locally (`--workers=N`). These are pre-existing and not specific to this PR — every test file that performs admin operations on shared users (RBAC, credential, user, user-profile) shares this property. CI runs with `workers: 1` and is unaffected. Eliminating these flakes would require either fixture-user isolation in every admin-touching file or a project-wide locking strategy — both out of scope for this sub-task.
agatha197 pushed a commit that referenced this pull request Jun 9, 2026
Resolves #7633 (FR-2998)

**Stacked on**: #7688 (FR-2997) → #7684 (FR-2996) → #7679 (FR-2995) → #7676 (FR-2994) → #7653 (FR-2993) → #7652 (FR-2992)

Part of FR-2059 (Fix Broken E2E Tests Cases). Repairs the Admin & Operations sub-category — 4 originally failing tests + cascading rewrites to project-crud after exposing the new lifecycle UX. Final state: **45 pass / 0 fail / 2 skip** across `e2e/environment/`, `e2e/my-environment/`, `e2e/project/`, `e2e/maintenance/`, `e2e/information/`, `e2e/statistics/`.

## Root causes

- **`environment/registry.spec.ts:63`** (registry list columns): the `Control` column was removed when `ContainerRegistryListNodes` migrated to `BAINameActionCell` (actions embedded in the Registry Name cell). Removed the obsolete columnheader assertion; the 7 real columns are still validated.

- **`environment/registry.spec.ts:716`** (filter property): the test used the CSS class `.ant-select-content-value` which does not exist in this antd version. Actual class is `.ant-select-content` (with optional `.ant-select-content-has-value`). Switched to `page.locator('.ant-select-content').filter({ hasText: 'Registry Name' })`.

- **`information/information.spec.ts:6`** (page server details): strict-mode hit. `getByText('Component')` matched both the `ant-descriptions-title` and the `'Loading components...'` loader. Added `{ exact: true }`.

- **`project/project-crud.spec.ts:31`** (project list columns): the `Controls` column was removed when the project list migrated to `BAIProjectTable` + `BAINameActionCell`. The `Active` column was also removed; active vs inactive is now a filter radio group. The test now asserts the 4 real columns (`Name`, `Domain`, `Description`, `Type`) and verifies the Active radio is selected via `.ant-radio-button-wrapper-checked`.

### Cascading rewrites in `project/project-crud.spec.ts` (uncovered by the column fix)

- **`:78` (create), `:122` (edit)** — the Name cell now renders via `BAINameActionCell`. Replaced the exact `getByRole('cell', { name: PROJECT_NAME, exact: true })` assertion with `getByRole('row').filter({ hasText: PROJECT_NAME })` since the cell's accessible name includes hover-only action labels. The Edit test now hovers the row before clicking the (hover-only) `setting` action button.

- **`:200` (delete)** — the project lifecycle changed from a one-shot Purge dialog to a two-step flow: **Active → Deactivated (Popconfirm) → Purged (`BAIDeleteConfirmModal` with `requireConfirmInput`)**. Rewrote the test and shared `cleanupTestProject` helper to:
  1. Hover the row, click deactivate (action button `nth(1)`).
  2. Confirm the antd Popconfirm.
  3. Switch to the Inactive tab via the label wrapper (the radio input itself is hidden).
  4. Hover the deactivated row, click purge (action button `nth(2)`).
  5. Type the project name into `#confirmText`, click Purge.
  6. Verify the row is gone, then return to the Active tab.

  Mirrors the user / role / vfolder destructive-action conventions already standardized in FR-2992 through FR-2997.

## Files changed

- `e2e/environment/registry.spec.ts` — removed obsolete `Control` columnheader; corrected filter-property selector class
- `e2e/information/information.spec.ts` — `{ exact: true }` on `Component`
- `e2e/project/project-crud.spec.ts` — column-set update, hover-then-click for `setting`, two-step deactivate→purge for delete, shared `cleanupTestProject` helper

## Test plan

- [x] `pnpm exec playwright test e2e/environment/ e2e/my-environment/ e2e/project/ e2e/maintenance/ e2e/information/ e2e/statistics/ --workers=2` — 45 pass / 0 fail / 2 skip
- [x] `pnpm exec playwright test e2e/project/project-crud.spec.ts` (full file in serial mode) — all 5 tests pass
- [x] Individual retries of the parallel-only flake (`environment.spec.ts:188 user can manage apps`) pass cleanly (17s) — backend-state-dependent test, not a regression
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100~500 LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix broken E2E tests — Access Control (RBAC & Credential)

3 participants