litellm/ui/litellm-dashboard/tests/lint-budget-lib.test.ts
ryan-crabbe-berri f2f6cacb19
Some checks are pending
LiteLLM Rust / rustfmt, clippy, test (push) Waiting to run
GitHub Actions Security Analysis / zizmor (push) Waiting to run
feat(ui): track frontend lint counts in a committed snapshot (#31157)
* feat(ui): track frontend lint counts in a committed snapshot

Persist the eslint budget-rule counts (no-explicit-any, complexity,
max-depth) to eslint-metrics.json so the trend is queryable straight
from git history and can later feed a dashboard. A CI drift check
regenerated from the same lint report keeps the snapshot honest, so a
PR that shifts a count has to run npm run lint:metrics and commit it

* fix(ui): harden lint-metrics drift check and eslint failure handling

Make the drift comparison symmetric over the union of committed and
actual keys so a phantom rule left in eslint-metrics.json (for example
after a rule is dropped from eslint-budgets.json) is caught instead of
silently passing. Only swallow eslint's lint-errors exit code in the
generator and rethrow anything else, so a fatal eslint failure surfaces
its real output rather than a confusing ENOENT on the missing report
2026-06-24 11:35:32 -07:00

55 lines
2 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { countBudgetViolations, findDrift } from "../scripts/lint-budget-lib.mjs";
const budgets = {
"@typescript-eslint/no-explicit-any": { max: 10, target: 5 },
complexity: { max: 10, target: 5 },
};
const file = (...ruleIds: (string | null)[]) => ({ messages: ruleIds.map((ruleId) => ({ ruleId })) });
describe("countBudgetViolations", () => {
it("counts only budgeted rules and sums across files", () => {
const report = [
file("@typescript-eslint/no-explicit-any", "complexity", "max-depth"),
file("@typescript-eslint/no-explicit-any", "no-var", null),
];
expect(countBudgetViolations(report, budgets)).toEqual({
"@typescript-eslint/no-explicit-any": 2,
complexity: 1,
});
});
it("reports 0 for a budgeted rule with no violations", () => {
expect(countBudgetViolations([file("complexity")], budgets)).toEqual({
"@typescript-eslint/no-explicit-any": 0,
complexity: 1,
});
});
it("emits keys in sorted order so the committed snapshot diffs stably", () => {
const unsorted = { complexity: { max: 1, target: 1 }, "@typescript-eslint/no-explicit-any": { max: 1, target: 1 } };
expect(Object.keys(countBudgetViolations([], unsorted))).toEqual([
"@typescript-eslint/no-explicit-any",
"complexity",
]);
});
});
describe("findDrift", () => {
it("reports no drift when the snapshot matches the actual counts", () => {
expect(findDrift({ complexity: 5 }, { complexity: 5 })).toEqual([]);
});
it("detects a changed count", () => {
expect(findDrift({ complexity: 5 }, { complexity: 7 })).toEqual([{ rule: "complexity", committed: 5, actual: 7 }]);
});
it("detects a rule missing from the committed snapshot", () => {
expect(findDrift({}, { complexity: 7 })).toEqual([{ rule: "complexity", committed: null, actual: 7 }]);
});
it("detects a phantom rule the committed snapshot still carries", () => {
expect(findDrift({ "removed-rule": 3 }, {})).toEqual([{ rule: "removed-rule", committed: 3, actual: null }]);
});
});