diff --git a/replay-ui/src/lib/property-status.ts b/replay-ui/src/lib/property-status.ts new file mode 100644 index 0000000..adc398c --- /dev/null +++ b/replay-ui/src/lib/property-status.ts @@ -0,0 +1,29 @@ +import type { ResidualNode, Step } from "../types"; + +export type Status = "violated" | "pending" | "holds"; + +export const STATUS_ORDER: Record = { + violated: 0, + pending: 1, + holds: 2, +}; + +export function statusFor( + name: string, + violations: Set, + residuals?: Record, +): Status { + if (violations.has(name)) { + return "violated"; + } + const residual = residuals?.[name]; + if (residual && residual.op === "true") { + return "holds"; + } + return "pending"; +} + +export function statusForStep(name: string, step: Step | null): Status { + if (!step) return "pending"; + return statusFor(name, new Set(step.violations ?? []), step.residuals); +} diff --git a/replay-ui/src/panels/ViolationsPanel.tsx b/replay-ui/src/panels/ViolationsPanel.tsx index 8266ffc..1c6a73e 100644 --- a/replay-ui/src/panels/ViolationsPanel.tsx +++ b/replay-ui/src/panels/ViolationsPanel.tsx @@ -1,5 +1,6 @@ import { useMemo } from "react"; import type { ResidualNode, Witness } from "../types"; +import { STATUS_ORDER, statusFor } from "../lib/property-status"; import ResidualNodeView from "../components/ResidualNode"; import "./ViolationsPanel.css"; @@ -15,29 +16,6 @@ export interface ViolationsPanelProps { violationsOnly?: boolean; } -type Status = "violated" | "pending" | "holds"; - -const STATUS_ORDER: Record = { - violated: 0, - pending: 1, - holds: 2, -}; - -function statusFor( - name: string, - violations: Set, - residuals?: Record, -): Status { - if (violations.has(name)) { - return "violated"; - } - const residual = residuals?.[name]; - if (residual && residual.op === "true") { - return "holds"; - } - return "pending"; -} - function formatValue(value: unknown): string { const encoded = JSON.stringify(value); return encoded === undefined ? String(value) : encoded;