fix(ui): gate scan tour behind full launch condition

- Suppress view-first-scan tour when manage_scans permission is missing
- Assert scans table renders for all provider states in the page test
This commit is contained in:
Pablo F.G
2026-07-21 11:57:07 +02:00
parent 87637d08a8
commit b516c0928d
3 changed files with 25 additions and 9 deletions
+4 -4
View File
@@ -63,11 +63,11 @@ vi.mock("@/components/shadcn/content-layout", () => ({
}));
vi.mock("@/components/scans/scans-page-shell", () => ({
ScansPageShell: (props: {
children: unknown;
children: ReactNode;
providers: ProviderProps[];
}) => {
scansPageShellSpy(props);
return <div data-testid="scans-page-shell" />;
return <div data-testid="scans-page-shell">{props.children}</div>;
},
}));
@@ -123,8 +123,8 @@ describe("scans page rendering", () => {
const shellProps = scansPageShellSpy.mock.calls.at(-1)?.[0];
expect(shellProps?.providers).toEqual(providers);
// The table subtree is always wired, regardless of provider connection state.
expect(shellProps?.children).toBeTruthy();
// The scans table subtree actually renders, regardless of provider state.
expect(await screen.findByRole("table")).toBeInTheDocument();
},
);
@@ -575,6 +575,21 @@ describe("ScansPageShell", () => {
expect(screen.queryByTestId("onboarding-trigger")).not.toBeInTheDocument();
});
it("suppresses the view-first-scan tour when a provider is connected but manage scans is missing", () => {
vi.stubEnv("NEXT_PUBLIC_IS_CLOUD_ENV", "false");
render(
<ScansPageShell providers={providers} hasManageScansPermission={false}>
<div>Scans table</div>
</ScansPageShell>,
);
// Launch Scan is disabled without manage_scans, so the tour must not anchor to it.
expect(screen.queryByTestId("onboarding-trigger")).not.toBeInTheDocument();
// The table (and therefore imported scans) must still render.
expect(screen.getByText("Scans table")).toBeInTheDocument();
});
it("still signals page-ready without a connected provider so the navbar replay fallback works", () => {
vi.stubEnv("NEXT_PUBLIC_IS_CLOUD_ENV", "false");
+6 -5
View File
@@ -108,12 +108,13 @@ 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). */}
{/* Gate on the full launch condition: the tour anchors on Launch Scan, which is
disabled without a connected provider AND manage_scans — starting it would
point at an unusable button. Every start path (?onboarding= URL, active
sequence, navbar replay) funnels through this trigger, so gating here covers
them all. */}
{/* Suspense required: OnboardingTrigger reads useSearchParams */}
{hasConnectedProviders && (
{!launchDisabled && (
<Suspense fallback={null}>
<OnboardingTrigger
flow={{