Simpl-Resultat/src/components/reports/HubReportNavCard.render.test.tsx
le king fu 00be2877f3 feat(onboarding): step cards of the Categories and Reports pages
The two visit steps get their card: /categories explains keywords and
points at "All keywords" (never "Reset"), /reports explains the hub and
points at the Trends card, with a padlock variant in the Free edition.
"Got it" acknowledges the step; opening the highlighted Trends card does
too (D17), since following the ring leaves the page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:45:05 -04:00

66 lines
2.5 KiB
TypeScript

// HubReportNavCard — the report card of the hub and its getting-started props
// (#432). No jsdom: react-dom/server renders the markup, and the component
// called as a function exposes the props of the link it returns (the
// FilterPanel.test.tsx pattern), for the click handler.
import { describe, it, expect, vi } from "vitest";
import { renderToStaticMarkup } from "react-dom/server";
import { MemoryRouter } from "react-router-dom";
import type { ReactElement } from "react";
vi.mock("react-i18next", async () => (await import("../../test/i18nMock")).i18nMock());
import HubReportNavCard, { REPORTS_TRENDS_TARGET, type HubReportNavCardProps } from "./HubReportNavCard";
const BASE: HubReportNavCardProps = {
to: "/reports/trends",
icon: null,
title: "Tendances",
description: "Évolution",
};
const HIGHLIGHT = 'data-onboarding-highlight="true"';
const render = (props: Partial<HubReportNavCardProps> = {}) =>
renderToStaticMarkup(
<MemoryRouter>
<HubReportNavCard {...BASE} {...props} />
</MemoryRouter>,
);
/** The link the card returns, read without rendering it. */
const link = (props: Partial<HubReportNavCardProps> = {}) =>
HubReportNavCard({ ...BASE, ...props }) as ReactElement<{ onClick?: () => void; to: string }>;
describe("HubReportNavCard — the getting-started target (#432)", () => {
it("carries the highlight on its link with onboardingTarget", () => {
const html = render({ onboardingTarget: true });
expect(html).toContain(`data-onboarding-target="${REPORTS_TRENDS_TARGET}" ${HIGHLIGHT}`);
expect(html.indexOf(HIGHLIGHT)).toBeLessThan(html.indexOf('href="/reports/trends"'));
expect(html.split(HIGHLIGHT).length - 1).toBe(1);
});
it("carries no highlight without it", () => {
for (const onboardingTarget of [undefined, false]) {
const html = render({ onboardingTarget });
expect(html).not.toContain("data-onboarding-target");
expect(html).not.toContain("data-onboarding-highlight");
}
});
it("a click calls onNavigate when it is given", () => {
const onNavigate = vi.fn();
const element = link({ onNavigate });
expect(element.props.to).toBe("/reports/trends");
element.props.onClick!();
expect(onNavigate).toHaveBeenCalledTimes(1);
});
it("without onNavigate, the link has no click handler of its own", () => {
expect(link().props.onClick).toBeUndefined();
});
it("keeps its lock badge, translated", () => {
expect(render({ locked: true })).toContain('aria-label="t(nav.locked)"');
expect(render()).not.toContain("t(nav.locked)");
});
});