fix(ui): now onboarding is gated again behind hasConnectedProviders

This commit is contained in:
Pablo F.G
2026-07-17 09:37:30 +02:00
parent 6b2bb712c1
commit 29005810b6
2 changed files with 79 additions and 8 deletions
@@ -17,6 +17,10 @@ const { scansFilterBarSpy } = vi.hoisted(() => ({
scansFilterBarSpy: vi.fn(),
}));
const { onboardingTriggerSpy } = vi.hoisted(() => ({
onboardingTriggerSpy: vi.fn(),
}));
const localStorageMock = (() => {
let store: Record<string, string> = {};
@@ -103,6 +107,14 @@ vi.mock("@/components/providers/muted-findings-config-button", () => ({
MutedFindingsConfigButton: () => <a href="/mutelist">Configure Mutelist</a>,
}));
vi.mock("@/components/onboarding", () => ({
OnboardingTrigger: (props: unknown) => {
onboardingTriggerSpy(props);
return <div data-testid="onboarding-trigger" />;
},
PageReady: () => <div data-testid="page-ready" />,
}));
const providers: ProviderProps[] = [
{
id: "provider-1",
@@ -476,4 +488,57 @@ describe("ScansPageShell", () => {
screen.queryByText("No Providers Configured"),
).not.toBeInTheDocument();
});
it("starts the view-first-scan tour when a provider is connected", () => {
vi.stubEnv("NEXT_PUBLIC_IS_CLOUD_ENV", "false");
render(
<ScansPageShell providers={providers} hasManageScansPermission>
<div>Scans table</div>
</ScansPageShell>,
);
expect(screen.getByTestId("onboarding-trigger")).toBeInTheDocument();
});
it("suppresses the view-first-scan tour when no provider is connected, since Launch Scan is disabled", () => {
vi.stubEnv("NEXT_PUBLIC_IS_CLOUD_ENV", "false");
render(
<ScansPageShell
providers={disconnectedProviders}
hasManageScansPermission
>
<div>Scans table</div>
</ScansPageShell>,
);
expect(screen.queryByTestId("onboarding-trigger")).not.toBeInTheDocument();
// The table (and therefore imported scans) must still render even with the tour suppressed.
expect(screen.getByText("Scans table")).toBeInTheDocument();
});
it("suppresses the view-first-scan tour when there are no providers", () => {
vi.stubEnv("NEXT_PUBLIC_IS_CLOUD_ENV", "false");
render(
<ScansPageShell providers={[]} hasManageScansPermission>
<div>Scans table</div>
</ScansPageShell>,
);
expect(screen.queryByTestId("onboarding-trigger")).not.toBeInTheDocument();
});
it("still signals page-ready without a connected provider so the navbar replay fallback works", () => {
vi.stubEnv("NEXT_PUBLIC_IS_CLOUD_ENV", "false");
render(
<ScansPageShell providers={[]} hasManageScansPermission>
<div>Scans table</div>
</ScansPageShell>,
);
expect(screen.getByTestId("page-ready")).toBeInTheDocument();
});
});
+14 -8
View File
@@ -107,15 +107,21 @@ export function ScansPageShell({
return (
<div className="flex flex-col gap-[18px]">
{/* Only start the scan tour when a provider is connected: its primary target
(Launch Scan) is disabled otherwise, so a `?onboarding=view-first-scan`
URL or active sequence would anchor to an unusable button. The navbar
replay falls back to the add-provider flow in this state (see page.tsx). */}
{/* Suspense required: OnboardingTrigger reads useSearchParams */}
<Suspense fallback={null}>
<OnboardingTrigger
flow={{
...viewFirstScanFlow,
tour: buildViewFirstScanTour(hasInProgressScan),
}}
/>
</Suspense>
{hasConnectedProviders && (
<Suspense fallback={null}>
<OnboardingTrigger
flow={{
...viewFirstScanFlow,
tour: buildViewFirstScanTour(hasInProgressScan),
}}
/>
</Suspense>
)}
{/* Signals the navbar that this route's data has loaded (enables the replay icon). */}
<PageReady />
{showProvidersHint && (