fix(pwa): экран баланса повторяет карточку CRM

Итог берётся с сервера, а не складывается из строк (1С округляет статьи до
рублей, итог держит с копейками: −8 976 против −8 976,25). Статья, в которую
платёж провести нечем, показывается, но не притворяется кнопкой — «Страховка».
Пустой снимок 1С даёт «Уточняется» вместо нулей.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 15:46:35 +10:00
co-authored by Claude Opus 5
parent 39ee2b7a49
commit 8b0ce4cf45
3 changed files with 65 additions and 19 deletions
@@ -3,12 +3,18 @@ import { render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
// Ответ как у настоящего водителя: шесть статей 1С, итог отдельным числом.
vi.mock("@/api/driver", () => ({
getBalance: vi.fn(async () => ({
accounts: [
{ bucket: "Долг аренда", balance: -3200 },
{ bucket: епозит", balance: 5000 },
{ bucket: "Долг аренда", balance: -3050, payable: true },
{ bucket: олг по штрафам", balance: -5156, payable: true },
{ bucket: "Прочее", balance: -770, payable: true },
{ bucket: "Страховка", balance: 0, payable: false },
],
total: -8976.25,
synced_at: null,
pending_topup: 0,
})),
}));
@@ -24,15 +30,22 @@ function wrap() {
}
describe("BalancePage", () => {
it("shows hero total (sum of negatives) and account rows", async () => {
it("итог берётся с сервера, а не складывается из строк", async () => {
wrap();
expect(await screen.findByText("Долг аренда")).toBeInTheDocument();
expect(screen.getByText("Депозит")).toBeInTheDocument();
// Appears in both the hero total and the single debt account row.
expect(screen.getAllByText("3 200 ₽").length).toBeGreaterThan(0);
// Сумма статей дала бы −8 976, а в CRM у водителя −8 976,25. Показываем её.
expect(screen.getByText("8 976,25 ₽")).toBeInTheDocument();
expect(screen.getByRole("button", { name: /Пополнить/i })).toBeInTheDocument();
});
it("статья, в которую платить нечем, не притворяется кнопкой", async () => {
wrap();
await screen.findByText("Страховка");
const buckets = screen.getAllByRole("button").map((b) => b.textContent ?? "");
expect(buckets.some((t) => t.includes("Долг аренда"))).toBe(true);
expect(buckets.some((t) => t.includes("Страховка"))).toBe(false);
});
it("shows an error state when balance fails to load", async () => {
const driver = await import("@/api/driver");
(driver.getBalance as any).mockRejectedValueOnce(new Error("boom"));