sprint/2-simulations #5

Merged
knacky merged 3 commits from sprint/2-simulations into main 2026-05-26 17:06:31 +00:00
5 changed files with 29 additions and 29 deletions
Showing only changes of commit da2ce68660 - Show all commits

View File

@@ -167,7 +167,7 @@ test.describe('US-11 — workflow transitions', () => {
}) => { }) => {
const rtClient = makeClient(redteamToken); const rtClient = makeClient(redteamToken);
// pending → "Marquer en revue" visible for redteam; "Clôturer" hidden // pending → "Mark for review" visible for redteam; "Close" hidden
const simPending = await createSimulation( const simPending = await createSimulation(
redteamToken, redteamToken,
engagementId, engagementId,
@@ -175,34 +175,34 @@ test.describe('US-11 — workflow transitions', () => {
); );
await seedTokenInStorage(context, redteamToken); await seedTokenInStorage(context, redteamToken);
await page.goto(`/engagements/${engagementId}/simulations/${simPending.id}/edit`); await page.goto(`/engagements/${engagementId}/simulations/${simPending.id}/edit`);
await expect(page.getByRole('button', { name: /marquer en revue/i })).toBeVisible(); await expect(page.getByRole('button', { name: /mark for review/i })).toBeVisible();
await expect(page.getByRole('button', { name: /clôturer/i })).toHaveCount(0); await expect(page.getByRole('button', { name: /^close$/i })).toHaveCount(0);
// in_progress → "Marquer en revue" visible // in_progress → "Mark for review" visible
const simIP = await createSimulation(redteamToken, engagementId, 'AC-11.4 in_progress UI'); const simIP = await createSimulation(redteamToken, engagementId, 'AC-11.4 in_progress UI');
await rtClient.patch(`/simulations/${simIP.id}`, { name: 'trigger' }); await rtClient.patch(`/simulations/${simIP.id}`, { name: 'trigger' });
await page.goto(`/engagements/${engagementId}/simulations/${simIP.id}/edit`); await page.goto(`/engagements/${engagementId}/simulations/${simIP.id}/edit`);
await expect(page.getByRole('button', { name: /marquer en revue/i })).toBeVisible(); await expect(page.getByRole('button', { name: /mark for review/i })).toBeVisible();
await expect(page.getByRole('button', { name: /clôturer/i })).toHaveCount(0); await expect(page.getByRole('button', { name: /^close$/i })).toHaveCount(0);
// review_required → "Clôturer" visible for redteam; "Marquer en revue" hidden // review_required → "Close" visible for redteam; "Mark for review" hidden
const simRR = await createSimulation(redteamToken, engagementId, 'AC-11.4 review UI'); const simRR = await createSimulation(redteamToken, engagementId, 'AC-11.4 review UI');
await rtClient.post(`/simulations/${simRR.id}/transition`, { to: 'review_required' }); await rtClient.post(`/simulations/${simRR.id}/transition`, { to: 'review_required' });
await page.goto(`/engagements/${engagementId}/simulations/${simRR.id}/edit`); await page.goto(`/engagements/${engagementId}/simulations/${simRR.id}/edit`);
await expect(page.getByRole('button', { name: /clôturer/i })).toBeVisible(); await expect(page.getByRole('button', { name: /^close$/i })).toBeVisible();
await expect(page.getByRole('button', { name: /marquer en revue/i })).toHaveCount(0); await expect(page.getByRole('button', { name: /mark for review/i })).toHaveCount(0);
// review_required → "Clôturer" also visible for SOC // review_required → "Close" also visible for SOC
await seedTokenInStorage(context, socToken); await seedTokenInStorage(context, socToken);
await page.goto(`/engagements/${engagementId}/simulations/${simRR.id}/edit`); await page.goto(`/engagements/${engagementId}/simulations/${simRR.id}/edit`);
await expect(page.getByRole('button', { name: /clôturer/i })).toBeVisible(); await expect(page.getByRole('button', { name: /^close$/i })).toBeVisible();
// done → both buttons hidden // done → both buttons hidden
await rtClient.post(`/simulations/${simRR.id}/transition`, { to: 'done' }); await rtClient.post(`/simulations/${simRR.id}/transition`, { to: 'done' });
await seedTokenInStorage(context, redteamToken); await seedTokenInStorage(context, redteamToken);
await page.goto(`/engagements/${engagementId}/simulations/${simRR.id}/edit`); await page.goto(`/engagements/${engagementId}/simulations/${simRR.id}/edit`);
await expect(page.getByRole('button', { name: /marquer en revue/i })).toHaveCount(0); await expect(page.getByRole('button', { name: /mark for review/i })).toHaveCount(0);
await expect(page.getByRole('button', { name: /clôturer/i })).toHaveCount(0); await expect(page.getByRole('button', { name: /^close$/i })).toHaveCount(0);
await deleteSimulation(redteamToken, simPending.id); await deleteSimulation(redteamToken, simPending.id);
await deleteSimulation(redteamToken, simIP.id); await deleteSimulation(redteamToken, simIP.id);
@@ -223,14 +223,14 @@ test.describe('US-11 — workflow transitions', () => {
const badge = page.getByTestId('simulation-status-badge'); const badge = page.getByTestId('simulation-status-badge');
await expect(badge).toHaveAttribute('data-status', 'pending'); await expect(badge).toHaveAttribute('data-status', 'pending');
// Click "Marquer en revue" // Click "Mark for review"
await page.getByRole('button', { name: /marquer en revue/i }).click(); await page.getByRole('button', { name: /mark for review/i }).click();
// Badge updates to review_required without page reload // Badge updates to review_required without page reload
await expect(badge).toHaveAttribute('data-status', 'review_required', { timeout: 5_000 }); await expect(badge).toHaveAttribute('data-status', 'review_required', { timeout: 5_000 });
// "Clôturer" now visible; click it // "Close" now visible; click it
await page.getByRole('button', { name: /clôturer/i }).click(); await page.getByRole('button', { name: /^close$/i }).click();
await expect(badge).toHaveAttribute('data-status', 'done', { timeout: 5_000 }); await expect(badge).toHaveAttribute('data-status', 'done', { timeout: 5_000 });
// Verify list is also updated: navigate to engagement detail and check badge there // Verify list is also updated: navigate to engagement detail and check badge there

View File

@@ -123,26 +123,26 @@ test.describe('US-12 — simulation delete', () => {
await page.goto(`/engagements/${engagementId}/simulations/${sim.id}/edit`); await page.goto(`/engagements/${engagementId}/simulations/${sim.id}/edit`);
// Delete button is visible for redteam // Delete button is visible for redteam
const deleteBtn = page.getByRole('button', { name: /supprimer/i }); const deleteBtn = page.getByRole('button', { name: /^delete$/i });
await expect(deleteBtn).toBeVisible(); await expect(deleteBtn).toBeVisible();
// SOC should NOT see delete button // SOC should NOT see delete button
await seedTokenInStorage(context, socToken); await seedTokenInStorage(context, socToken);
await page.goto(`/engagements/${engagementId}/simulations/${sim.id}/edit`); await page.goto(`/engagements/${engagementId}/simulations/${sim.id}/edit`);
await expect(page.getByRole('button', { name: /supprimer/i })).toHaveCount(0); await expect(page.getByRole('button', { name: /^delete$/i })).toHaveCount(0);
// Back to redteam — click delete, confirm modal appears // Back to redteam — click delete, confirm modal appears
await seedTokenInStorage(context, redteamToken); await seedTokenInStorage(context, redteamToken);
await page.goto(`/engagements/${engagementId}/simulations/${sim.id}/edit`); await page.goto(`/engagements/${engagementId}/simulations/${sim.id}/edit`);
await page.getByRole('button', { name: /supprimer/i }).click(); await page.getByRole('button', { name: /^delete$/i }).click();
// Confirmation dialog must appear // Confirmation dialog must appear
const dialog = page.getByRole('dialog'); const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible(); await expect(dialog).toBeVisible();
await expect(dialog.getByText(/supprimer la simulation/i)).toBeVisible(); await expect(dialog.getByText(/delete simulation/i)).toBeVisible();
// Confirm deletion // Confirm deletion
await dialog.getByRole('button', { name: /supprimer/i }).click(); await dialog.getByRole('button', { name: /^delete$/i }).click();
// Should navigate back to engagement detail // Should navigate back to engagement detail
await page.waitForURL(new RegExp(`/engagements/${engagementId}$`)); await page.waitForURL(new RegExp(`/engagements/${engagementId}$`));

View File

@@ -265,9 +265,9 @@ test.describe('US-4 — engagement CRUD', () => {
await expect(page.getByRole('heading', { name: /AC-4.9 detail target/i })).toBeVisible(); await expect(page.getByRole('heading', { name: /AC-4.9 detail target/i })).toBeVisible();
// Sprint 2 replaced the placeholder with the real SimulationList — covered by AC-7.5. // Sprint 2 replaced the placeholder with the real SimulationList — covered by AC-7.5.
await expect(page.getByRole('heading', { name: /simulations/i })).toBeVisible(); await expect(page.getByRole('heading', { name: /simulations/i })).toBeVisible();
// admin/redteam see the "Nouvelle simulation" button // admin/redteam see the "New simulation" button
await expect( await expect(
page.getByRole('link', { name: /nouvelle simulation/i }), page.getByRole('link', { name: /new simulation/i }),
).toBeVisible(); ).toBeVisible();
}); });
}); });

View File

@@ -156,15 +156,15 @@ test.describe('US-7 — simulation create', () => {
// The created simulation row is visible // The created simulation row is visible
await expect(page.getByRole('row', { name: /Visible sim/i })).toBeVisible(); await expect(page.getByRole('row', { name: /Visible sim/i })).toBeVisible();
// "Nouvelle simulation" button visible for redteam // "New simulation" button visible for redteam
await expect( await expect(
page.getByRole('link', { name: /nouvelle simulation/i }), page.getByRole('link', { name: /new simulation/i }),
).toBeVisible(); ).toBeVisible();
// SOC should NOT see "Nouvelle simulation" button // SOC should NOT see "New simulation" button
await seedTokenInStorage(context, socToken); await seedTokenInStorage(context, socToken);
await page.goto(`/engagements/${engagementId}`); await page.goto(`/engagements/${engagementId}`);
await expect(page.getByRole('link', { name: /nouvelle simulation/i })).toHaveCount(0); await expect(page.getByRole('link', { name: /new simulation/i })).toHaveCount(0);
await deleteSimulation(redteamToken, sim.id); await deleteSimulation(redteamToken, sim.id);
}); });

View File

@@ -178,7 +178,7 @@ test.describe('US-9 — SOC restricted edit', () => {
// Banner must be visible // Banner must be visible
await expect(page.getByTestId('soc-blocked-banner')).toBeVisible(); await expect(page.getByTestId('soc-blocked-banner')).toBeVisible();
await expect( await expect(
page.getByText(/simulation pas encore en revue/i), page.getByText(/simulation not yet ready for review/i),
).toBeVisible(); ).toBeVisible();
// SOC fields are disabled // SOC fields are disabled