Enable every plugin recommended preset and replace Biome with ESLint formatting. Preserve API contracts and JSX whitespace; verify source, tests, builds and tooling.
113 lines
3.4 KiB
TypeScript
113 lines
3.4 KiB
TypeScript
import type { FC } from "react";
|
|
|
|
import { QueryClientProvider } from "@tanstack/react-query";
|
|
import {
|
|
act,
|
|
fireEvent,
|
|
render,
|
|
screen,
|
|
waitFor,
|
|
} from "@testing-library/react";
|
|
import { http, HttpResponse } from "msw";
|
|
import { MemoryRouter, useNavigate } from "react-router";
|
|
import { beforeEach, describe, expect, it } from "vitest";
|
|
|
|
import { AuthProvider } from "@/features/auth";
|
|
import { createTestQueryClient } from "@/test/query";
|
|
import { resource } from "@/test/resource";
|
|
import { server } from "@/test/server";
|
|
|
|
import { ProtectedDocumentTitle } from "./DocumentTitle";
|
|
|
|
const Navigation: FC = () => {
|
|
const navigate = useNavigate();
|
|
return (
|
|
<>
|
|
<button onClick={() => navigate("/accounts/all/income")} type="button">
|
|
Все счета
|
|
</button>
|
|
<button onClick={() => navigate(-1)} type="button">
|
|
Назад
|
|
</button>
|
|
</>
|
|
);
|
|
};
|
|
|
|
const renderTitle = (path: string) =>
|
|
render(
|
|
<QueryClientProvider client={createTestQueryClient()}>
|
|
<MemoryRouter initialEntries={[path]}>
|
|
<AuthProvider>
|
|
<ProtectedDocumentTitle />
|
|
<Navigation />
|
|
</AuthProvider>
|
|
</MemoryRouter>
|
|
</QueryClientProvider>,
|
|
);
|
|
|
|
beforeEach(() => {
|
|
document.title = "Previous page";
|
|
server.use(
|
|
http.post("*/api/v1/auth/refresh", () =>
|
|
HttpResponse.json({
|
|
accessToken: "test-token",
|
|
user: { email: "user@example.com", id: "user-1" },
|
|
}),
|
|
),
|
|
);
|
|
});
|
|
|
|
describe("document titles", () => {
|
|
it("updates a loading account name and follows account scope and history", async () => {
|
|
const { promise: accountsReady, resolve: resolveAccounts } = Promise.withResolvers<void>();
|
|
server.use(
|
|
http.get("*/api/v1/brokerage-accounts", async () => {
|
|
await accountsReady;
|
|
return HttpResponse.json(resource([{ id: "a", name: "ИИС" }]));
|
|
}),
|
|
);
|
|
renderTitle("/accounts/a/income?from=2026-01-01&to=2026-08-31");
|
|
expect(document.title).toBe("Пассивный доход — Счет — WealthLedger");
|
|
await act(() => Promise.resolve(resolveAccounts()));
|
|
await waitFor(() =>
|
|
expect(document.title).toBe("Пассивный доход — ИИС — WealthLedger"),
|
|
);
|
|
fireEvent.click(screen.getByRole("button", { name: "Все счета" }));
|
|
expect(document.title).toBe("Пассивный доход — Все счета — WealthLedger");
|
|
fireEvent.click(screen.getByRole("button", { name: "Назад" }));
|
|
expect(document.title).toBe("Пассивный доход — ИИС — WealthLedger");
|
|
});
|
|
|
|
it.each([
|
|
["bonds", "SU26238RMFS4", "Облигация", "ОФЗ 26238"],
|
|
["stocks", "SBER", "Акция", "Сбербанк"],
|
|
])(
|
|
"updates the %s title when instrument data arrives",
|
|
async (kind, id, fallback, name) => {
|
|
server.use(
|
|
http.get(`*/api/v1/${kind}/by-ticker/:ticker`, () =>
|
|
HttpResponse.json(resource({ name })),
|
|
),
|
|
);
|
|
renderTitle(`/${kind}/${id}`);
|
|
expect(document.title).toBe(`${fallback} — WealthLedger`);
|
|
await waitFor(() =>
|
|
expect(document.title).toBe(`${name} — WealthLedger`),
|
|
);
|
|
},
|
|
);
|
|
|
|
it("keeps a useful title when the instrument is unavailable", async () => {
|
|
let isRequested = false;
|
|
server.use(
|
|
http.get("*/api/v1/stocks/by-ticker/:ticker", () => {
|
|
isRequested = true;
|
|
return HttpResponse.json({ code: "NOT_FOUND" }, { status: 404 });
|
|
}),
|
|
);
|
|
renderTitle("/stocks/missing");
|
|
await waitFor(() => expect(isRequested).toBe(true));
|
|
expect(document.title).toBe("Акция — WealthLedger");
|
|
});
|
|
});
|