feat: sprint 4 — UI polish + dark mode + workflow tightening + process hygiene #7

Merged
knacky merged 15 commits from sprint/4-ui-polish into main 2026-05-28 04:01:21 +00:00
Showing only changes of commit 43ab7073f1 - Show all commits

View File

@@ -144,8 +144,8 @@ test.describe('US-21 — tactic selection', () => {
const dialog = page.getByRole('dialog'); const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible({ timeout: 10_000 }); await expect(dialog).toBeVisible({ timeout: 10_000 });
// Wait for matrix to load — matrix returns slug IDs, tactic header title contains "discovery" // Wait for matrix to load — tactic header title: "Discovery (TA0007) — click to tag this tactic"
const discoveryHeader = dialog.locator('button[title*="discovery"]').first(); const discoveryHeader = dialog.locator('button[title*="TA0007"]');
await expect(discoveryHeader).toBeVisible({ timeout: 10_000 }); await expect(discoveryHeader).toBeVisible({ timeout: 10_000 });
await discoveryHeader.click(); await discoveryHeader.click();
@@ -158,16 +158,10 @@ test.describe('US-21 — tactic selection', () => {
await deleteSimulation(redteamToken, sim.id); await deleteSimulation(redteamToken, sim.id);
}); });
test.fail('AC-21.6 — Apply from modal includes tactic in result (auto-save)', async ({ test('AC-21.6 — Apply from modal includes tactic in result (auto-save)', async ({
page, page,
context, context,
}) => { }) => {
// KNOWN DEFECT: /api/mitre/matrix returns tactic_id as slug ("discovery") but
// PATCH /api/simulations/:id expects TA-format ("TA0007"). When a tactic is
// selected via the matrix modal and Apply is clicked, the PATCH body contains
// tactic_ids: ["discovery"] which the backend rejects with "unknown tactic id".
// Fix owner: backend-builder (matrix endpoint must return TA-format tactic IDs)
// OR frontend-builder (modal must map slug → TA format before saving).
const sim = await createSimulation(redteamToken, engagementId, 'AC-21.6 apply tactic'); const sim = await createSimulation(redteamToken, engagementId, 'AC-21.6 apply tactic');
await seedTokenInStorage(context, redteamToken); await seedTokenInStorage(context, redteamToken);
@@ -177,8 +171,8 @@ test.describe('US-21 — tactic selection', () => {
const dialog = page.getByRole('dialog'); const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible({ timeout: 10_000 }); await expect(dialog).toBeVisible({ timeout: 10_000 });
// Wait for matrix to load — tactic header title uses slug: "Discovery (discovery)..." // Tactic header title: "Discovery (TA0007) — click to tag this tactic"
const discoveryBtn = dialog.locator('button[title*="discovery"]').first(); const discoveryBtn = dialog.locator('button[title*="TA0007"]');
await expect(discoveryBtn).toBeVisible({ timeout: 10_000 }); await expect(discoveryBtn).toBeVisible({ timeout: 10_000 });
await discoveryBtn.click(); await discoveryBtn.click();
@@ -189,7 +183,7 @@ test.describe('US-21 — tactic selection', () => {
// Modal closes // Modal closes
await expect(dialog).not.toBeVisible({ timeout: 5_000 }); await expect(dialog).not.toBeVisible({ timeout: 5_000 });
// This assertion fails because PATCH with slug ID returns 400 // Tactic chip appears after auto-save
await expect(page.getByTestId('mitre-tactic-tag')).toBeVisible({ timeout: 8_000 }); await expect(page.getByTestId('mitre-tactic-tag')).toBeVisible({ timeout: 8_000 });
await expect(page.getByTestId('techniques-tag-list')).toContainText('TA0007'); await expect(page.getByTestId('techniques-tag-list')).toContainText('TA0007');