mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 20:42:02 +00:00
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.
This commit is contained in:
@@ -67,6 +67,21 @@ describe("CompliancePageTabs", () => {
|
||||
expect(pushMock).toHaveBeenCalledWith("/compliance");
|
||||
});
|
||||
|
||||
it("anchors the tour to the scan-mode controls", () => {
|
||||
const { container } = render(
|
||||
<CompliancePageTabs
|
||||
activeTab={COMPLIANCE_TAB.PER_SCAN}
|
||||
crossProviderEnabled
|
||||
perScanContent={<div>Per scan content</div>}
|
||||
crossProviderContent={<div>Cross provider content</div>}
|
||||
/>,
|
||||
);
|
||||
|
||||
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(
|
||||
|
||||
@@ -57,32 +57,33 @@ export const CompliancePageTabs = ({
|
||||
};
|
||||
|
||||
return (
|
||||
// Same layout spacing as the scans view tabs (scans-page-shell.tsx).
|
||||
<Tabs
|
||||
value={activeTab}
|
||||
onValueChange={handleTabChange}
|
||||
className="flex flex-col gap-[18px]"
|
||||
>
|
||||
<TabsList className="overflow-x-auto">
|
||||
<TabsTrigger value={COMPLIANCE_TAB.PER_SCAN}>Single Scan</TabsTrigger>
|
||||
<TabsTrigger
|
||||
value={COMPLIANCE_TAB.CROSS_PROVIDER}
|
||||
adornment={
|
||||
!crossProviderEnabled ? (
|
||||
<Badge variant="cloud">Cloud</Badge>
|
||||
) : undefined
|
||||
}
|
||||
>
|
||||
Multiple Scans
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<Tabs value={activeTab} onValueChange={handleTabChange}>
|
||||
<div className="flex flex-col gap-[18px]">
|
||||
<div data-tour-id="view-compliance-tabs" className="overflow-x-auto">
|
||||
<TabsList>
|
||||
<TabsTrigger value={COMPLIANCE_TAB.PER_SCAN}>
|
||||
Single Scan
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
value={COMPLIANCE_TAB.CROSS_PROVIDER}
|
||||
adornment={
|
||||
!crossProviderEnabled ? (
|
||||
<Badge variant="cloud">Cloud</Badge>
|
||||
) : undefined
|
||||
}
|
||||
>
|
||||
Multiple Scans
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</div>
|
||||
|
||||
<TabsContent value={COMPLIANCE_TAB.PER_SCAN}>
|
||||
{perScanContent}
|
||||
</TabsContent>
|
||||
<TabsContent value={COMPLIANCE_TAB.CROSS_PROVIDER}>
|
||||
{crossProviderContent}
|
||||
</TabsContent>
|
||||
<TabsContent value={COMPLIANCE_TAB.PER_SCAN}>
|
||||
{perScanContent}
|
||||
</TabsContent>
|
||||
<TabsContent value={COMPLIANCE_TAB.CROSS_PROVIDER}>
|
||||
{crossProviderContent}
|
||||
</TabsContent>
|
||||
</div>
|
||||
</Tabs>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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", () => {
|
||||
|
||||
@@ -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<ViewComplianceTourTarget>({
|
||||
id: "view-compliance",
|
||||
version: 1,
|
||||
version: 2,
|
||||
coversFiles: [
|
||||
"ui/app/(prowler)/compliance/**",
|
||||
"ui/components/compliance/**",
|
||||
@@ -27,6 +28,14 @@ export const viewComplianceTour = defineTour<ViewComplianceTourTarget>({
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user