From 3d7ddfc5a0ea24fd0cb001169c217d5c15fbfcbf Mon Sep 17 00:00:00 2001 From: alejandrobailo Date: Wed, 22 Jul 2026 13:49:41 +0200 Subject: [PATCH] fix(ui): introduce multiple scans in compliance tour Add a dedicated scan-mode step, bump the tour version, and anchor it to the shared tabs without passing layout classes into Design System components. --- .../_components/compliance-page-tabs.test.tsx | 15 ++++++ .../_components/compliance-page-tabs.tsx | 51 ++++++++++--------- .../__tests__/view-compliance.tour.test.ts | 9 ++-- ui/lib/tours/view-compliance.tour.ts | 11 +++- 4 files changed, 55 insertions(+), 31 deletions(-) diff --git a/ui/app/(prowler)/compliance/_components/compliance-page-tabs.test.tsx b/ui/app/(prowler)/compliance/_components/compliance-page-tabs.test.tsx index 80103ec293..0671e43270 100644 --- a/ui/app/(prowler)/compliance/_components/compliance-page-tabs.test.tsx +++ b/ui/app/(prowler)/compliance/_components/compliance-page-tabs.test.tsx @@ -67,6 +67,21 @@ describe("CompliancePageTabs", () => { expect(pushMock).toHaveBeenCalledWith("/compliance"); }); + it("anchors the tour to the scan-mode controls", () => { + const { container } = render( + Per scan content} + crossProviderContent={
Cross provider content
} + />, + ); + + expect( + container.querySelector('[data-tour-id="view-compliance-tabs"]'), + ).toBeInTheDocument(); + }); + it("opens the cross-provider upgrade without changing tabs in Local Server", async () => { const user = userEvent.setup(); render( diff --git a/ui/app/(prowler)/compliance/_components/compliance-page-tabs.tsx b/ui/app/(prowler)/compliance/_components/compliance-page-tabs.tsx index 109ffe968c..c10bd239a0 100644 --- a/ui/app/(prowler)/compliance/_components/compliance-page-tabs.tsx +++ b/ui/app/(prowler)/compliance/_components/compliance-page-tabs.tsx @@ -57,32 +57,33 @@ export const CompliancePageTabs = ({ }; return ( - // Same layout spacing as the scans view tabs (scans-page-shell.tsx). - - - Single Scan - Cloud - ) : undefined - } - > - Multiple Scans - - + +
+
+ + + Single Scan + + Cloud + ) : undefined + } + > + Multiple Scans + + +
- - {perScanContent} - - - {crossProviderContent} - + + {perScanContent} + + + {crossProviderContent} + +
); }; diff --git a/ui/lib/tours/__tests__/view-compliance.tour.test.ts b/ui/lib/tours/__tests__/view-compliance.tour.test.ts index 4d6c042b51..f78cba202c 100644 --- a/ui/lib/tours/__tests__/view-compliance.tour.test.ts +++ b/ui/lib/tours/__tests__/view-compliance.tour.test.ts @@ -6,8 +6,7 @@ import { type ViewComplianceTourTarget, } from "../view-compliance.tour"; -// Only these two carry a `data-tour-id` in the UI; welcome step has no target. -const ALLOWED_TARGETS = ["frameworks", "search"] as const; +const ALLOWED_TARGETS = ["tabs", "frameworks", "search"] as const; const definedTargets = (): ViewComplianceTourTarget[] => viewComplianceTour.steps @@ -23,14 +22,14 @@ describe("viewComplianceTour shape", () => { it("declares a positive integer version", () => { expect(Number.isInteger(viewComplianceTour.version)).toBe(true); - expect(viewComplianceTour.version).toBeGreaterThan(0); + expect(viewComplianceTour.version).toBe(2); }); - it("anchors exactly the search and frameworks steps, in that order", () => { + it("introduces the scan modes before search and frameworks", () => { // Search sits above the cards in the DOM; the tour must follow top-to-bottom // so the spotlight never jumps back up the page. const targets = definedTargets(); - expect(targets).toEqual(["search", "frameworks"]); + expect(targets).toEqual(["tabs", "search", "frameworks"]); }); it("never targets an element outside the allowed anchor set", () => { diff --git a/ui/lib/tours/view-compliance.tour.ts b/ui/lib/tours/view-compliance.tour.ts index 5aa23c77ca..f2061e8eac 100644 --- a/ui/lib/tours/view-compliance.tour.ts +++ b/ui/lib/tours/view-compliance.tour.ts @@ -7,6 +7,7 @@ import { // Const map keeps the union narrow so `useDriverTour` can validate step keys. export const VIEW_COMPLIANCE_TOUR_TARGETS = { + TABS: "tabs", FRAMEWORKS: "frameworks", SEARCH: "search", } as const; @@ -16,7 +17,7 @@ export type ViewComplianceTourTarget = export const viewComplianceTour = defineTour({ id: "view-compliance", - version: 1, + version: 2, coversFiles: [ "ui/app/(prowler)/compliance/**", "ui/components/compliance/**", @@ -27,6 +28,14 @@ export const viewComplianceTour = defineTour({ description: "Compliance maps your findings to frameworks like CIS so you can see where you stand against each standard.", }, + { + target: "tabs", + side: TOUR_STEP_SIDES.BOTTOM, + align: TOUR_STEP_ALIGNMENTS.START, + title: "Choose how to combine scans", + description: + "Single Scan reviews one scan at a time. Multiple Scans combines results across provider types or across accounts of the same provider type.", + }, { target: "search", side: TOUR_STEP_SIDES.BOTTOM,