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>
66 lines
2.5 KiB
TypeScript
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)");
|
|
});
|
|
});
|