gendesign/frontend/src/components/site-finder/__tests__/GateVerdictBanner.test.tsx
bot-backend 9f00fe8819
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Successful in 1m3s
CI / openapi-codegen-check (pull_request) Successful in 2m31s
fix(frontend): нейтральный fallback для нераспознанных gate/velocity enum-значений (#2445-B2/B3)
GateVerdictBanner и VelocityBlock искали backend-enum строки (verdict_label,
confidence) в object-literal картах без runtime-guard. Неожиданное значение
(schema drift / partial deploy) → lookup undefined → краш компонента на
следующем .bg/.fg/.Icon доступе. Добавлен ?? нейтральный fallback (серый +
HelpCircle / «—»), паттерн ParcelDrawer STATUS_COLORS ?? '#73767E'.

Refs #2445
2026-07-06 00:03:13 +05:00

46 lines
1.8 KiB
TypeScript

/**
* B2 (#2445) — COLOR_BY_LABEL[verdict.verdict_label] had no fallback: an
* unrecognized verdict_label (schema drift / partial deploy — backend ships a
* new enum value before frontend redeploys) made the lookup `undefined`, and
* the next `.Icon`/`.bg` access threw, crashing the whole banner render.
*
* These tests pin the defensive fallback (mirrors ParcelDrawer's
* `STATUS_COLORS[...] ?? '#73767E'` pattern): an unknown verdict_label must
* render a neutral style, not throw.
*/
import { render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import { GateVerdictBanner } from "../GateVerdictBanner";
import type { GateVerdict, GateVerdictLabel } from "@/types/site-finder";
function makeVerdict(overrides: Partial<GateVerdict> = {}): GateVerdict {
return {
can_build_mkd: true,
verdict_label: "Можно",
blockers: [],
warnings: [],
checks_performed: [],
source: "nspd_dump",
...overrides,
};
}
describe("GateVerdictBanner", () => {
it("renders known verdict_label without throwing", () => {
render(
<GateVerdictBanner verdict={makeVerdict({ verdict_label: "Можно" })} />,
);
expect(screen.getByText(/МКД: Можно/)).toBeInTheDocument();
});
it("unrecognized verdict_label renders a neutral fallback instead of throwing", () => {
const drifted = makeVerdict({
// Simulates schema drift: backend sends a value outside the closed
// GateVerdictLabel union (cast through unknown, not `any`).
verdict_label: "НовыйВердикт" as unknown as GateVerdictLabel,
});
expect(() => render(<GateVerdictBanner verdict={drifted} />)).not.toThrow();
expect(screen.getByText(/МКД: НовыйВердикт/)).toBeInTheDocument();
});
});