feat(investments): warn and offer retry after exhausted read retries (WealthLedger/frontend#55) (#136)
This commit was merged in pull request #136.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { MantineProvider } from "@mantine/core";
|
||||
import { type QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { render, screen, waitFor } from "@testing-library/react";
|
||||
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||
import { http, HttpResponse } from "msw";
|
||||
import { MemoryRouter } from "react-router";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
@@ -261,6 +261,101 @@ describe("AccountsPage", () => {
|
||||
});
|
||||
});
|
||||
|
||||
// Automatic read retries wait 1s + 2s before the failure is final.
|
||||
const RETRIES_EXHAUSTED_MS = 6000;
|
||||
const TEST_MS = 10_000;
|
||||
|
||||
describe("exhausted read retries", () => {
|
||||
it(
|
||||
"keeps the cached list, warns and retries the same accounts GET",
|
||||
{ timeout: TEST_MS },
|
||||
async () => {
|
||||
let isFailing = false;
|
||||
let requests = 0;
|
||||
server.use(
|
||||
http.get("*/api/v1/brokerage-accounts", () => {
|
||||
requests += 1;
|
||||
if (isFailing)
|
||||
return HttpResponse.json(
|
||||
{ code: "TBANK_UNAVAILABLE" },
|
||||
{ status: 503 },
|
||||
);
|
||||
|
||||
return HttpResponse.json(resource([account]));
|
||||
}),
|
||||
);
|
||||
const queryClient = createTestQueryClient();
|
||||
renderPage(queryClient);
|
||||
await screen.findByText("Основной");
|
||||
expect(screen.queryByRole("button", { name: "Повторить" }))
|
||||
.not.toBeInTheDocument();
|
||||
|
||||
isFailing = true;
|
||||
void queryClient.invalidateQueries({
|
||||
queryKey: brokerageAccountsQueryKey,
|
||||
});
|
||||
|
||||
const retry = await screen.findByRole(
|
||||
"button",
|
||||
{ name: "Повторить" },
|
||||
{ timeout: RETRIES_EXHAUSTED_MS },
|
||||
);
|
||||
|
||||
expect(screen.getByText("Не удалось обновить данные")).toBeInTheDocument();
|
||||
expect(screen.getByText("Основной")).toBeInTheDocument();
|
||||
expect(requests).toBe(4);
|
||||
|
||||
isFailing = false;
|
||||
fireEvent.click(retry);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByText("Не удалось обновить данные"))
|
||||
.not.toBeInTheDocument());
|
||||
expect(requests).toBe(5);
|
||||
expect(screen.getByText("Основной")).toBeInTheDocument();
|
||||
},
|
||||
);
|
||||
|
||||
it(
|
||||
"offers retry on the unavailable state after an initial failure",
|
||||
{ timeout: TEST_MS },
|
||||
async () => {
|
||||
let isFailing = true;
|
||||
server.use(
|
||||
http.get("*/api/v1/brokerage-accounts", () =>
|
||||
isFailing
|
||||
? HttpResponse.json({ code: "TBANK_UNAVAILABLE" }, { status: 503 })
|
||||
: HttpResponse.json(resource([account]))),
|
||||
);
|
||||
renderPage(createTestQueryClient());
|
||||
|
||||
const retry = await screen.findByRole(
|
||||
"button",
|
||||
{ name: "Повторить" },
|
||||
{ timeout: RETRIES_EXHAUSTED_MS },
|
||||
);
|
||||
|
||||
isFailing = false;
|
||||
fireEvent.click(retry);
|
||||
|
||||
expect(await screen.findByText("Основной")).toBeInTheDocument();
|
||||
},
|
||||
);
|
||||
|
||||
it("does not offer a plain retry when the connection is lost", async () => {
|
||||
server.use(
|
||||
http.get("*/api/v1/brokerage-accounts", () =>
|
||||
HttpResponse.json({ code: "TBANK_NOT_CONNECTED" }, { status: 409 })),
|
||||
);
|
||||
renderPage(createTestQueryClient());
|
||||
|
||||
expect(await screen.findByRole("link", { name: "Открыть настройки T-Bank" }))
|
||||
.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Повторить" }))
|
||||
.not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it.each(["none", "failed"] as const)(
|
||||
"keeps incomplete empty membership distinct from no accounts (attempt=%s)",
|
||||
async (state) => {
|
||||
|
||||
Reference in New Issue
Block a user