Merge branch 'fix/demo-dashboard' into release/v1.43.9

This commit is contained in:
Marc-André Bombeck committed 2026-10-20 22:43:38 +02:00
commit fed16a4c43
4 files changed
+79 -7

No files matched your search

@@ -0,0 +1,35 @@
import { describe, it, expect } from "vitest";
import { readFileSync } from "node:fs";
import { join } from "node:path";
/**
* The setup checklist on a demo instance.
*
* The demo is one shared, read-only account carrying onboarding answers, so
* `isStillInSetup` keeps the checklist on screen for every visitor although
* none of its rows can be done there. The shell already leaves out the tour
* under `DEMO_MODE`; the dashboard leaves out the checklist the same way.
* Pinned here: every render path of the page threads the flag, and the
* client mounts the checklist only without it.
*/
const PAGE_PATH = join(process.cwd(), "src/app/page.tsx");
const CLIENT_PATH = join(process.cwd(), "src/app/page-client.tsx");
describe("dashboard setup checklist on a demo instance", () => {
it("threads DEMO_MODE into every render of the dashboard client", () => {
const src = readFileSync(PAGE_PATH, "utf8");
expect(src).toContain('process.env.DEMO_MODE === "true"');
const renders = src.match(/<DashboardPageClient\b[^>]*>/g) ?? [];
expect(renders.length).toBeGreaterThan(0);
for (const render of renders) {
expect(render).toContain("demoMode={demoMode}");
}
});
it("mounts the checklist only outside demo mode", () => {
const src = readFileSync(CLIENT_PATH, "utf8");
const mounts = src.match(/<GettingStartedChecklist\b[^>]*\/>/g) ?? [];
expect(mounts).toHaveLength(1);
expect(src).toContain("{demoMode ? null : <GettingStartedChecklist />}");
});
});
+8 -1
View File
@@ -193,6 +193,7 @@ import {
export default function DashboardPageClient({
batchWindow: batchWindowProp,
demoMode = false,
}: {
/**
* v1.30.9 — the batched-series ISO window computed server-side from the
@@ -204,6 +205,12 @@ export default function DashboardPageClient({
* under, so the prefetched slice lands instead of triggering a refetch.
*/
batchWindow?: BatchWindow;
/**
* True on a `DEMO_MODE` instance. The demo is one shared, read-only
* account a visitor cannot set up, so the setup checklist has nothing to
* offer there, as the shell already leaves out the tour.
*/
demoMode?: boolean;
} = {}) {
const { isAuthenticated } = useAuth();
const mounted = useMounted();
@@ -2312,7 +2319,7 @@ export default function DashboardPageClient({
* content (tiles, charts) keeps a stable position, and the
* near-empty dashboards of the new accounts the card targets keep
* it visible without scrolling anyway. */}
<GettingStartedChecklist />
{demoMode ? null : <GettingStartedChecklist />}
</div>
);
}
+8 -3
View File
@@ -76,12 +76,15 @@ const DIGEST_SOFT_BUDGET_MS = 400;
* others.
*/
export default async function DashboardPage() {
// `DEMO_MODE` is a server-only env var; resolved here and threaded in, as
// the layout does for the shell.
const demoMode = process.env.DEMO_MODE === "true";
// Operator/test escape hatch: `DASHBOARD_SSR_PREFETCH=false` renders the
// pure client-fetch dashboard (pre-prefetch behaviour). The e2e server
// sets it so Playwright route mocks — which only see CLIENT fetches —
// keep governing what the dashboard paints. It gates EVERY prefetch below.
if (process.env.DASHBOARD_SSR_PREFETCH === "false") {
return <DashboardPageClient />;
return <DashboardPageClient demoMode={demoMode} />;
}
let dehydratedState = null;
let batchWindow: BatchWindow | undefined;
@@ -171,11 +174,13 @@ export default async function DashboardPage() {
}
if (dehydratedState === null) {
return <DashboardPageClient batchWindow={batchWindow} />;
return (
<DashboardPageClient batchWindow={batchWindow} demoMode={demoMode} />
);
}
return (
<HydrationBoundary state={dehydratedState}>
<DashboardPageClient batchWindow={batchWindow} />
<DashboardPageClient batchWindow={batchWindow} demoMode={demoMode} />
</HydrationBoundary>
);
}