106 lines
2.9 KiB
TypeScript
106 lines
2.9 KiB
TypeScript
import { MantineProvider } from "@mantine/core";
|
|
import { render, screen, within } from "@testing-library/react";
|
|
import { MemoryRouter } from "react-router";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import { AppBreadcrumbs } from "./AppBreadcrumbs";
|
|
|
|
const { useBrokerageAccounts } = vi.hoisted(() => ({
|
|
useBrokerageAccounts: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("@/entities/brokerage-account", () => ({ useBrokerageAccounts }));
|
|
|
|
function renderBreadcrumbs(
|
|
path: string,
|
|
accounts?: { id: string; name: string }[],
|
|
) {
|
|
useBrokerageAccounts.mockReturnValue({ data: accounts });
|
|
|
|
return render(
|
|
<MantineProvider>
|
|
<MemoryRouter initialEntries={[path]}>
|
|
<AppBreadcrumbs />
|
|
</MemoryRouter>
|
|
</MantineProvider>,
|
|
);
|
|
}
|
|
|
|
describe("AppBreadcrumbs", () => {
|
|
afterEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it("shows the current accounts page without a link", () => {
|
|
renderBreadcrumbs("/accounts");
|
|
|
|
expect(
|
|
screen.getByRole("navigation", { name: "Хлебные крошки" }),
|
|
).toBeInTheDocument();
|
|
expect(screen.getByText("Брокерские счета")).toHaveAttribute(
|
|
"aria-current",
|
|
"page",
|
|
);
|
|
expect(screen.queryByRole("link")).not.toBeInTheDocument();
|
|
});
|
|
|
|
it("shows settings as the current page without a link", () => {
|
|
renderBreadcrumbs("/settings");
|
|
|
|
expect(screen.getByText("Настройки")).toHaveAttribute(
|
|
"aria-current",
|
|
"page",
|
|
);
|
|
expect(screen.queryByRole("link")).not.toBeInTheDocument();
|
|
});
|
|
|
|
it.each([
|
|
["operations", "История операций"],
|
|
["OPERATIONS", "История операций"],
|
|
["events", "Предстоящие события"],
|
|
["income", "Пассивный доход"],
|
|
])("links to the account hierarchy from %s", (section, title) => {
|
|
renderBreadcrumbs(`/accounts/account-1/${section}`, [
|
|
{ id: "account-1", name: "ИИС" },
|
|
]);
|
|
|
|
expect(
|
|
screen.getByRole("link", { name: "Брокерские счета" }),
|
|
).toHaveAttribute("href", "/accounts");
|
|
expect(screen.getByRole("link", { name: "ИИС" })).toHaveAttribute(
|
|
"href",
|
|
"/accounts/account-1",
|
|
);
|
|
expect(screen.getByText(title)).toHaveAttribute(
|
|
"aria-current",
|
|
"page",
|
|
);
|
|
expect(screen.getByRole("navigation")).toHaveAttribute("data-depth", "3");
|
|
|
|
for (const separator of screen.getAllByText("→")) {
|
|
expect(separator).toHaveAttribute("aria-hidden", "true");
|
|
}
|
|
});
|
|
|
|
it("uses the account fallback without exposing the identifier", () => {
|
|
renderBreadcrumbs("/accounts/account-1");
|
|
|
|
expect(
|
|
within(screen.getByRole("navigation")).getByText("Счет"),
|
|
).toHaveAttribute("aria-current", "page");
|
|
expect(screen.queryByText("account-1")).not.toBeInTheDocument();
|
|
});
|
|
|
|
it.each([
|
|
"/login",
|
|
"/unknown",
|
|
"/accounts/account-1/unknown",
|
|
])("does not render on %s", (path) => {
|
|
renderBreadcrumbs(path);
|
|
|
|
expect(
|
|
screen.queryByRole("navigation", { name: "Хлебные крошки" }),
|
|
).not.toBeInTheDocument();
|
|
});
|
|
});
|