fix(frontend): complete audit remediation

This commit is contained in:
2026-09-06 19:49:02 +03:00
parent c97f62bd98
commit 9e42148f6a
11 changed files with 508 additions and 72 deletions
@@ -1,6 +1,6 @@
import { MantineProvider } from "@mantine/core";
import { render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router";
import { MemoryRouter, Route, Routes } from "react-router";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { useBrokerageEvents } from "@/entities/brokerage-event";
import { AccountEventsPage } from "./AccountEventsPage";
@@ -35,6 +35,37 @@ describe("AccountEventsPage", () => {
} as never);
});
it("passes the selected route account to the query", () => {
render(
<MantineProvider>
<MemoryRouter initialEntries={["/accounts/selected-account/events"]}>
<Routes>
<Route
path="/accounts/:accountId/events"
element={<AccountEventsPage />}
/>
</Routes>
</MemoryRouter>
</MantineProvider>,
);
expect(query).toHaveBeenCalledWith("selected-account");
});
it("keeps the loading fallback when no result or account is available", () => {
query.mockReturnValue({
data: undefined,
isError: false,
isLoading: false,
refetch: vi.fn(),
} as never);
renderPage();
expect(query).toHaveBeenCalledWith(undefined);
expect(screen.getByRole("status", { name: "Загрузка" })).toHaveAttribute(
"aria-busy",
"true",
);
});
it("renders events and marks an offer without an amount", () => {
query.mockReturnValue({
data: {
@@ -1,20 +1,17 @@
import type { FC } from "react";
import { useParams } from "react-router";
import { useBrokerageEvents } from "@/entities/brokerage-event";
import { useAccountEventsPageViewModel } from "./AccountEventsPage.vm";
import { AccountEventsPageEmpty } from "./components/AccountEventsPageEmpty.view";
import { AccountEventsPageError } from "./components/AccountEventsPageError.view";
import { AccountEventsPageLoaded } from "./components/AccountEventsPageLoaded.view";
import { AccountEventsPageLoading } from "./components/AccountEventsPageLoading.view";
const AccountEventsPage: FC = () => {
const { accountId } = useParams();
const events = useBrokerageEvents(accountId);
if (events.isLoading) return <AccountEventsPageLoading />;
if (events.isError)
return <AccountEventsPageError retry={() => events.refetch()} />;
if (!events.data) return <AccountEventsPageLoading />;
if (!events.data.events.length) return <AccountEventsPageEmpty />;
return <AccountEventsPageLoaded events={events.data.events} />;
const viewModel = useAccountEventsPageViewModel();
if (viewModel.state === "loading") return <AccountEventsPageLoading />;
if (viewModel.state === "error")
return <AccountEventsPageError retry={viewModel.retry} />;
if (viewModel.state === "empty") return <AccountEventsPageEmpty />;
return <AccountEventsPageLoaded events={viewModel.events} />;
};
export { AccountEventsPage };
@@ -0,0 +1,23 @@
import { useParams } from "react-router";
import {
type BrokerageEvent,
useBrokerageEvents,
} from "@/entities/brokerage-event";
type AccountEventsPageViewModel =
| { state: "loading" }
| { state: "empty" }
| { state: "error"; retry: () => void }
| { state: "loaded"; events: BrokerageEvent[] };
function useAccountEventsPageViewModel(): AccountEventsPageViewModel {
const { accountId } = useParams();
const events = useBrokerageEvents(accountId);
if (events.isLoading) return { state: "loading" };
if (events.isError) return { state: "error", retry: () => events.refetch() };
if (!events.data) return { state: "loading" };
if (!events.data.events.length) return { state: "empty" };
return { state: "loaded", events: events.data.events };
}
export { useAccountEventsPageViewModel };