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
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
46 lines
1.8 KiB
TypeScript
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();
|
|
});
|
|
});
|