diff --git a/frontend/e2e/user-blocking-session.spec.ts b/frontend/e2e/user-blocking-session.spec.ts index ef17c96..db55a2b 100644 --- a/frontend/e2e/user-blocking-session.spec.ts +++ b/frontend/e2e/user-blocking-session.spec.ts @@ -36,6 +36,18 @@ test.describe('User Blocking Mid-Session [P1]', () => { ); // Ensure target user is unblocked before tests start + resetTargetUser(); + }); + + /** + * Resets the target user to active state via SQL. + * Called at the start of tests that need the user unblocked, + * so that Playwright retries don't fail because a previous + * attempt already blocked the user server-side. + */ + function resetTargetUser() { + const projectRoot = join(__dirname, '../..'); + const composeFile = join(projectRoot, 'compose.yaml'); try { execSync( `docker compose -f "${composeFile}" exec -T php php bin/console dbal:run-sql "UPDATE users SET statut = 'active', blocked_at = NULL, blocked_reason = NULL WHERE email = '${TARGET_EMAIL}'" 2>&1`, @@ -44,7 +56,7 @@ test.describe('User Blocking Mid-Session [P1]', () => { } catch { // Ignore cleanup errors } - }); + } async function loginAsAdmin(page: import('@playwright/test').Page) { await page.goto(`${ALPHA_URL}/login`); @@ -92,7 +104,7 @@ test.describe('User Blocking Mid-Session [P1]', () => { await page.getByRole('button', { name: /confirmer le blocage/i }).click(); // Wait for the success message - await expect(page.locator('.alert-success')).toBeVisible({ timeout: 5000 }); + await expect(page.locator('.alert-success')).toBeVisible({ timeout: 10000 }); } async function unblockUserViaAdmin(page: import('@playwright/test').Page) { @@ -112,13 +124,16 @@ test.describe('User Blocking Mid-Session [P1]', () => { await expect(unblockButton).toBeVisible(); await unblockButton.click(); - await expect(page.locator('.alert-success')).toBeVisible({ timeout: 5000 }); + await expect(page.locator('.alert-success')).toBeVisible({ timeout: 10000 }); } // ============================================================================ // AC1: Admin blocks a user mid-session // ============================================================================ test('[P1] admin blocks user mid-session - blocked user next request results in redirect', async ({ browser }) => { + // Reset target user state so retries work (a previous attempt may have blocked the user server-side) + resetTargetUser(); + // Use two separate browser contexts to simulate two concurrent sessions const adminContext = await browser.newContext(); const targetContext = await browser.newContext(); @@ -142,8 +157,8 @@ test.describe('User Blocking Mid-Session [P1]', () => { // The blocked user should be redirected to login (API returns 401/403) await expect(targetPage).toHaveURL(/\/login/, { timeout: 10000 }); } finally { - await adminContext.close(); - await targetContext.close(); + await adminContext.close().catch(() => {}); + await targetContext.close().catch(() => {}); } }); @@ -179,7 +194,7 @@ test.describe('User Blocking Mid-Session [P1]', () => { const updatedRow = adminPage.locator('tr', { has: adminPage.locator(`text=${TARGET_EMAIL}`) }); await expect(updatedRow.locator('.status-active')).toContainText('Actif'); } finally { - await adminContext.close(); + await adminContext.close().catch(() => {}); } // Now the user should be able to log in again (use a new context) @@ -195,7 +210,7 @@ test.describe('User Blocking Mid-Session [P1]', () => { // Should redirect to dashboard (successful login) await expect(userPage).toHaveURL(/\/dashboard/, { timeout: 30000 }); } finally { - await userContext.close(); + await userContext.close().catch(() => {}); } }); diff --git a/frontend/e2e/user-blocking.spec.ts b/frontend/e2e/user-blocking.spec.ts index c888938..10f6e41 100644 --- a/frontend/e2e/user-blocking.spec.ts +++ b/frontend/e2e/user-blocking.spec.ts @@ -34,6 +34,16 @@ test.describe('User Blocking', () => { `docker compose -f "${composeFile}" exec -T php php bin/console app:dev:create-test-user --tenant=ecole-alpha --email=${TARGET_EMAIL} --password=${TARGET_PASSWORD} --role=ROLE_PROF 2>&1`, { encoding: 'utf-8' } ); + + // Ensure target user is unblocked before tests start (idempotent cleanup) + try { + execSync( + `docker compose -f "${composeFile}" exec -T php php bin/console dbal:run-sql "UPDATE users SET statut = 'active', blocked_at = NULL, blocked_reason = NULL WHERE email = '${TARGET_EMAIL}'" 2>&1`, + { encoding: 'utf-8' } + ); + } catch { + // Ignore cleanup errors + } }); async function loginAsAdmin(page: import('@playwright/test').Page) {