All checks were successful
CI / changes (push) Successful in 7s
CI / backend-tests (push) Has been skipped
CI / changes (pull_request) Successful in 9s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (push) Successful in 49s
CI / frontend-tests (pull_request) Successful in 48s
Section 1 mini-map (/site-finder/analysis/[cad] — единственная карта
страницы) оборачивал SiteMap в height:320 + overflow:hidden. SiteMap
рендерит карту фиксированной высотой 420px + ПОД ней (flow) кнопку
"Добавить POI", легенду и CpLayerControlPanel с тумблерами
competitors/pipeline/risk/opportunity/redlines. Нижние 100px карты и
ВСЕ контролы обрезались clip-обёрткой → недостижимы кликом.
visibleMarketLayers init = {"competitors"} — единственный способ
включить остальные слои (#999 zone-of-risk, #958 §12.1-13 opportunity
parcels / red lines) — те самые скрытые чекбоксы → слои физически
невозможно было включить на странице анализа, хотя данные пробрасывались
props'ами ради них.
Patch (Вариант A из issue):
- SiteMap.tsx: новый prop mapHeight?: number (default 420 — backward-
compat для /site-finder/[cad]).
- MiniMap.tsx: снято height:320 + overflow:hidden; передаём mapHeight=280
(компактнее но не клипает); только width-constraint (maxWidth 400)
на обёртке.
2 новых vitest: mapHeight=280 пробрасывается в SiteMap (mocked stub),
clipping-стили отсутствуют. 82/82 frontend тестов зелёные. tsc + lint clean.
Closes #1218
67 lines
2.5 KiB
TypeScript
67 lines
2.5 KiB
TypeScript
import { render, screen, waitFor } from "@testing-library/react";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
|
|
import { MiniMap } from "../MiniMap";
|
|
import type { ParcelAnalyzeResponse } from "@/lib/site-finder-api";
|
|
|
|
// Stub SiteMap so we can assert the props MiniMap passes through (mapHeight
|
|
// in particular — #1218: ранее MiniMap клипал layer-панель/легенду через
|
|
// `overflow: hidden + height: 320`; теперь высота карты задаётся через prop).
|
|
// Stub does NOT use `unknown` — we capture a typed snapshot of the relevant
|
|
// props (mapHeight) for the assertion.
|
|
|
|
interface CapturedProps {
|
|
mapHeight?: number;
|
|
}
|
|
|
|
const captured: { last: CapturedProps | null } = { last: null };
|
|
|
|
vi.mock("@/components/site-finder/SiteMap", () => ({
|
|
SiteMap: (props: CapturedProps) => {
|
|
captured.last = { mapHeight: props.mapHeight };
|
|
return <div data-testid="sitemap-stub">map(h={props.mapHeight ?? "?"})</div>;
|
|
},
|
|
}));
|
|
|
|
// Minimal ParcelAnalyzeResponse — only fields MiniMap touches (toSiteMapData).
|
|
const FIXTURE: ParcelAnalyzeResponse = {
|
|
cad_num: "66:41:0000000:1",
|
|
source: "cad_building",
|
|
geom_geojson: null,
|
|
district: null,
|
|
score: 0,
|
|
score_breakdown: {},
|
|
poi_count: 0,
|
|
competitors: [],
|
|
pipeline_24mo: null,
|
|
nspd_risk_zones: [],
|
|
nspd_opportunity_parcels: [],
|
|
nspd_red_lines: [],
|
|
};
|
|
|
|
describe("MiniMap (#1218)", () => {
|
|
it("passes mapHeight=280 to SiteMap (compact tile, controls flow below)", async () => {
|
|
render(<MiniMap data={FIXTURE} />);
|
|
// SiteMap is dynamically imported (ssr:false) — wait until our stub renders.
|
|
await waitFor(() =>
|
|
expect(screen.getByTestId("sitemap-stub")).toBeInTheDocument(),
|
|
);
|
|
expect(captured.last?.mapHeight).toBe(280);
|
|
});
|
|
|
|
it("wrapper does NOT clip overflow — layer controls must remain visible", async () => {
|
|
const { container } = render(<MiniMap data={FIXTURE} />);
|
|
await waitFor(() =>
|
|
expect(screen.getByTestId("sitemap-stub")).toBeInTheDocument(),
|
|
);
|
|
// The outer wrapper is the first element child — SiteMap stub lives inside.
|
|
const wrapper = container.firstElementChild as HTMLElement | null;
|
|
expect(wrapper).not.toBeNull();
|
|
// No fixed height (must be empty so flow children — legend + control panel —
|
|
// are not clipped to 320px), and no overflow: hidden.
|
|
expect(wrapper?.style.height).toBe("");
|
|
expect(wrapper?.style.overflow).toBe("");
|
|
// Width constraint preserved (column slot is 400px in Section 1 grid).
|
|
expect(wrapper?.style.maxWidth).toBe("400px");
|
|
});
|
|
});
|