Merge pull request 'МЕРА v2: клик по «Предыдущим оценкам» после отправки открывает выбранную оценку' (#3549) from fix/v2-history-click into main
Some checks failed
Deploy Trade-In / build-backend (push) Has been cancelled
Deploy Trade-In / build-frontend (push) Has been cancelled
Deploy Trade-In / build-browser (push) Has been cancelled
Deploy Trade-In / deploy (push) Has been cancelled
Deploy Trade-In / test (push) Has been cancelled
Deploy Trade-In / perimeter-smoke (push) Has been cancelled
Deploy Trade-In / deploy-status (push) Has been cancelled
Deploy Trade-In / changes (push) Successful in 23s
Some checks failed
Deploy Trade-In / build-backend (push) Has been cancelled
Deploy Trade-In / build-frontend (push) Has been cancelled
Deploy Trade-In / build-browser (push) Has been cancelled
Deploy Trade-In / deploy (push) Has been cancelled
Deploy Trade-In / test (push) Has been cancelled
Deploy Trade-In / perimeter-smoke (push) Has been cancelled
Deploy Trade-In / deploy-status (push) Has been cancelled
Deploy Trade-In / changes (push) Successful in 23s
This commit is contained in:
commit
404b583682
2 changed files with 126 additions and 0 deletions
|
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
* #2425 — клик по строке «Предыдущие оценки» после отправки оценки в той же
|
||||
* SPA-сессии должен показать ВЫБРАННУЮ запись, а не только что посчитанную.
|
||||
*
|
||||
* Раньше `freshResult` оставался выставленным: `useEstimate` получал null
|
||||
* (восстановление по id не запускалось вовсе), а экран продолжал показывать
|
||||
* свежий результат. Проверяется по значению: какой id ушёл в `useEstimate`,
|
||||
* какой id получил HeroBar и чей адрес лёг в форму.
|
||||
*/
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { FIXTURE_ESTIMATE } from "@/app/ui-preview/estimate/fixture";
|
||||
import type { AggregatedEstimate } from "@/types/trade-in";
|
||||
|
||||
const FRESH: AggregatedEstimate = {
|
||||
...FIXTURE_ESTIMATE,
|
||||
estimate_id: "fresh-1",
|
||||
target_address: "Екатеринбург, ул. Свежая, 1",
|
||||
};
|
||||
const HIST: AggregatedEstimate = {
|
||||
...FIXTURE_ESTIMATE,
|
||||
estimate_id: "hist-1",
|
||||
target_address: "Екатеринбург, ул. Историческая, 2",
|
||||
};
|
||||
|
||||
const useEstimateMock = vi.hoisted(() => vi.fn());
|
||||
const router = vi.hoisted(() => ({ replace: vi.fn(), push: vi.fn() }));
|
||||
|
||||
vi.mock("next/navigation", () => ({ useRouter: () => router }));
|
||||
vi.mock("@tanstack/react-query", () => ({
|
||||
useQueryClient: () => ({ invalidateQueries: vi.fn() }),
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/trade-in-api", () => {
|
||||
const empty = () => ({ data: undefined });
|
||||
return {
|
||||
useEstimate: useEstimateMock,
|
||||
useEstimateMutation: () => ({
|
||||
mutate: (_input: unknown, opts: { onSuccess: (e: AggregatedEstimate) => void }) =>
|
||||
opts.onSuccess(FRESH),
|
||||
isPending: false,
|
||||
error: null,
|
||||
}),
|
||||
useEstimateHistory: empty,
|
||||
useEstimateHouseAnalytics: empty,
|
||||
useEstimatePlacementHistory: empty,
|
||||
useEstimateSellTimeSensitivity: empty,
|
||||
useLocationIndex: empty,
|
||||
useSalesVsListings: empty,
|
||||
useStreetDeals: empty,
|
||||
};
|
||||
});
|
||||
vi.mock("@/lib/useQuota", () => ({ useQuota: () => ({ data: undefined }) }));
|
||||
vi.mock("@/lib/useMe", () => ({ useMe: () => ({ data: undefined }) }));
|
||||
vi.mock("@/lib/useLogout", () => ({ useLogout: () => ({ mutate: vi.fn() }) }));
|
||||
|
||||
// Дочерние компоненты — заглушки: проверяется только, что страница им отдаёт.
|
||||
vi.mock("@/components/trade-in/v2/TopNav", () => ({
|
||||
default: ({ onNavigate }: { onNavigate: (n: number) => void }) => (
|
||||
<button onClick={() => onNavigate(4)}>open-history</button>
|
||||
),
|
||||
}));
|
||||
vi.mock("@/components/trade-in/v2/HeroBar", () => ({
|
||||
default: ({ estimateId }: { estimateId: string | null }) => (
|
||||
<div data-testid="hero-id">{estimateId ?? ""}</div>
|
||||
),
|
||||
}));
|
||||
vi.mock("@/components/trade-in/v2/ParamsPanel", () => ({
|
||||
default: ({
|
||||
onSubmit,
|
||||
initialValues,
|
||||
}: {
|
||||
onSubmit: (i: unknown) => void;
|
||||
initialValues?: { address?: string };
|
||||
}) => (
|
||||
<div>
|
||||
<div data-testid="form-address">{initialValues?.address ?? ""}</div>
|
||||
<button onClick={() => onSubmit({})}>submit</button>
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
vi.mock("@/components/trade-in/v2/SectionOverlay", () => ({
|
||||
default: ({ onSelectEstimate }: { onSelectEstimate: (id: string) => void }) => (
|
||||
<button onClick={() => onSelectEstimate("hist-1")}>row-hist-1</button>
|
||||
),
|
||||
}));
|
||||
vi.mock("@/components/trade-in/v2/ResultPanel", () => ({ default: () => null }));
|
||||
vi.mock("@/components/trade-in/v2/LowConfidenceBanner", () => ({
|
||||
LowConfidenceBanner: () => null,
|
||||
}));
|
||||
vi.mock("@/components/trade-in/v2/ObjectSummary", () => ({ ObjectSummary: () => null }));
|
||||
vi.mock("@/components/trade-in/v2/LeadForm", () => ({ LeadForm: () => null }));
|
||||
vi.mock("@/components/trade-in/v2/Footer", () => ({ Footer: () => null }));
|
||||
vi.mock("@/components/trade-in/v2/LocationDrawer", () => ({ LocationDrawer: () => null }));
|
||||
|
||||
import TradeInV2Page from "../page";
|
||||
|
||||
describe("#2425 — строка истории после submit", () => {
|
||||
it("клик по другой оценке показывает её, а не только что посчитанную", () => {
|
||||
useEstimateMock.mockImplementation((id: string | null) =>
|
||||
id === "hist-1"
|
||||
? { data: HIST, isPending: false, isError: false, error: null }
|
||||
: { data: undefined, isPending: id !== null, isError: false, error: null },
|
||||
);
|
||||
|
||||
render(<TradeInV2Page />);
|
||||
|
||||
fireEvent.click(screen.getByText("submit"));
|
||||
expect(screen.getByTestId("hero-id")).toHaveTextContent("fresh-1");
|
||||
expect(screen.getByTestId("form-address")).toHaveTextContent("ул. Свежая, 1");
|
||||
|
||||
fireEvent.click(screen.getByText("open-history"));
|
||||
fireEvent.click(screen.getByText("row-hist-1"));
|
||||
|
||||
expect(useEstimateMock).toHaveBeenLastCalledWith("hist-1");
|
||||
expect(router.replace).toHaveBeenLastCalledWith("/v2?id=hist-1", { scroll: false });
|
||||
expect(screen.getByTestId("hero-id")).toHaveTextContent("hist-1");
|
||||
expect(screen.getByTestId("form-address")).toHaveTextContent("ул. Историческая, 2");
|
||||
});
|
||||
});
|
||||
|
|
@ -1190,6 +1190,11 @@ export default function TradeInV2Page() {
|
|||
// hands `urlId` the correct target id, mirroring how
|
||||
// `freshResult` already overrides this same race for the
|
||||
// post-submit path (handleSubmit above).
|
||||
//
|
||||
// #2425: a fresh submit and restore-by-id are mutually exclusive
|
||||
// both ways (as in handleNew) — a leftover freshResult would
|
||||
// disable useEstimate(urlId) and keep shadowing the clicked row.
|
||||
setFreshResult(null);
|
||||
setPendingRestoreId(id);
|
||||
router.replace(`/v2?id=${id}`, { scroll: false });
|
||||
setNav(0);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue