feat: add quiet reading with rare confirmations
Part of the quiet-user-feedback change; docs and specs land in their own repositories.
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { MantineProvider } from "@mantine/core";
|
||||
import { type QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import {
|
||||
fireEvent,
|
||||
render,
|
||||
screen,
|
||||
waitFor,
|
||||
@@ -261,7 +260,7 @@ describe("AccountPage states", () => {
|
||||
it.each(["NOT_FOUND", "TBANK_NOT_CONNECTED", "INVALID_TBANK_TOKEN"])(
|
||||
"does not offer retry without cached data for %s",
|
||||
(code) => {
|
||||
renderPage(<AccountPageError code={code} retry={vi.fn()} />);
|
||||
renderPage(<AccountPageError code={code} />);
|
||||
expect(
|
||||
screen.queryByRole("button", { name: "Повторить" }),
|
||||
).not.toBeInTheDocument();
|
||||
@@ -274,12 +273,16 @@ describe("AccountPage states", () => {
|
||||
},
|
||||
);
|
||||
|
||||
it.each(["TBANK_UNAVAILABLE", "UNKNOWN"])("allows retry for %s", (code) => {
|
||||
const retry = vi.fn();
|
||||
renderPage(<AccountPageError code={code} retry={retry} />);
|
||||
fireEvent.click(screen.getByRole("button", { name: "Повторить" }));
|
||||
expect(retry).toHaveBeenCalledOnce();
|
||||
});
|
||||
it.each(["TBANK_UNAVAILABLE", "UNKNOWN"])(
|
||||
"shows neutral unavailable without retry for %s",
|
||||
(code) => {
|
||||
renderPage(<AccountPageError code={code} />);
|
||||
expect(screen.getByRole("heading", { name: "Пока недоступно" }))
|
||||
.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Повторить" }))
|
||||
.not.toBeInTheDocument();
|
||||
},
|
||||
);
|
||||
|
||||
it("shows supplied cash separately without adding currency instruments or recalculating totals", () => {
|
||||
renderPage(
|
||||
@@ -405,11 +408,9 @@ describe("AccountPage states", () => {
|
||||
expect(
|
||||
screen.getByRole("heading", { level: 1, name: "Портфель" }),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
"T-Bank временно недоступен. Показан последний успешный снимок.",
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.queryByText(/T-Bank временно недоступен/))
|
||||
.not.toBeInTheDocument();
|
||||
expect(screen.queryByText(/Данные получены/)).not.toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "Акции" })).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole("button", { name: "Облигации" }),
|
||||
@@ -573,7 +574,7 @@ describe("AccountPage states", () => {
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByText("Не удалось загрузить последние события."),
|
||||
screen.getByText("Пока недоступно"),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByText("Вторая")).toBeInTheDocument();
|
||||
});
|
||||
@@ -742,13 +743,13 @@ describe("AccountPage states", () => {
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByText("Не удалось загрузить будущие события."),
|
||||
screen.getByText("Данные появятся здесь, когда чтение восстановится."),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByText("Вторая")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.each([503])(
|
||||
"preserves totals and UTC snapshot through refresh error %i, retry and success",
|
||||
"preserves totals quietly through refresh error %i and success",
|
||||
async (status) => {
|
||||
const initialPortfolio: Portfolio
|
||||
= {
|
||||
@@ -821,40 +822,30 @@ describe("AccountPage states", () => {
|
||||
});
|
||||
|
||||
expect(structure).toHaveTextContent("10 ₽");
|
||||
const snapshotText = screen.getByText(/Данные получены/).textContent;
|
||||
expect(snapshotText).toContain("10:00");
|
||||
expect(screen.queryByText(/Данные получены/)).not.toBeInTheDocument();
|
||||
void queryClient.invalidateQueries({
|
||||
queryKey: portfolioQueryOptions("account-1").queryKey,
|
||||
});
|
||||
|
||||
expect(
|
||||
await screen.findByText(
|
||||
"Не удалось обновить портфель. Показан последний полученный снимок.",
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText(
|
||||
"T-Bank временно недоступен. Показан последний успешный снимок.",
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
await waitFor(() => expect(requestCount).toBe(2));
|
||||
expect(screen.queryByText(/Не удалось обновить портфель/))
|
||||
.not.toBeInTheDocument();
|
||||
expect(screen.queryByText(/T-Bank временно недоступен/))
|
||||
.not.toBeInTheDocument();
|
||||
expect(screen.getByText("Вторая")).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getAllByRole("definition").map(node => node.textContent),
|
||||
).toEqual(["1 234,5 ₽", "0,5 $"]);
|
||||
// eslint-disable-next-line jest-dom/prefer-to-have-text-content -- The cached timestamp must remain exactly unchanged.
|
||||
expect(screen.getByText(/Данные получены/).textContent).toBe(
|
||||
snapshotText,
|
||||
);
|
||||
fireEvent.click(screen.getByRole("button", { name: "Повторить" }));
|
||||
expect(screen.queryByRole("button", { name: "Повторить" }))
|
||||
.not.toBeInTheDocument();
|
||||
void queryClient.invalidateQueries({
|
||||
queryKey: portfolioQueryOptions("account-1").queryKey,
|
||||
});
|
||||
await waitFor(() => expect(requestCount).toBe(3));
|
||||
expect(structure).toHaveTextContent("10 ₽");
|
||||
expect(
|
||||
screen.getAllByRole("definition").map(node => node.textContent),
|
||||
).toEqual(["1 234,5 ₽", "0,5 $"]);
|
||||
// eslint-disable-next-line jest-dom/prefer-to-have-text-content -- The cached timestamp must remain exactly unchanged.
|
||||
expect(screen.getByText(/Данные получены/).textContent).toBe(
|
||||
snapshotText,
|
||||
);
|
||||
resolveRetry?.(
|
||||
HttpResponse.json(
|
||||
resource(
|
||||
@@ -875,7 +866,7 @@ describe("AccountPage states", () => {
|
||||
screen.getAllByRole("definition").map(node => node.textContent),
|
||||
).toEqual(["-0,5 $", "2,50 €"]),
|
||||
);
|
||||
expect(screen.getByText(/Данные получены/)).toHaveTextContent("11:30");
|
||||
expect(screen.queryByText(/Данные получены/)).not.toBeInTheDocument();
|
||||
expect(structure).not.toHaveTextContent("10 ₽");
|
||||
expect(structure).toHaveTextContent("Нет положительной стоимости");
|
||||
expect(
|
||||
@@ -916,13 +907,12 @@ describe("AccountPage states", () => {
|
||||
expect(
|
||||
screen.getAllByRole("definition").map(node => node.textContent),
|
||||
).toEqual(["1 234,5 ₽", "0,5 $"]);
|
||||
expect(screen.getByText(/Данные получены/)).toHaveTextContent("10:00");
|
||||
expect(screen.queryByText(/Данные получены/)).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByRole("status", { name: "Загрузка" }),
|
||||
).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole("status", { name: "Обновляем портфель" }),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.queryByRole("status", { name: "Обновляем портфель" }))
|
||||
.not.toBeInTheDocument();
|
||||
|
||||
resolveRefresh?.(HttpResponse.json(resource(portfolio)));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user