Files
OmniRoute/tests/unit/usage-quota-row-visibility.test.ts
Diego Rodrigues de Sa e Souza bf943e0a7c [needs-vps] feat(dashboard): add per-operator quota row visibility on usage tab (#7251)
* feat(dashboard): add per-operator quota row visibility on usage tab

Adds a "hide this quota row" action (visibility_off icon button) to
each model-quota row on the provider limits card, and a "Hidden: …"
strip at the bottom of the card to restore any hidden row. The
visibility preference is keyed per-provider (settings.quotaVisibility)
and persisted via PATCH /api/settings, so it survives refresh/reload.

Distinct from the existing model-catalog isHidden/isDeleted mechanism
(collectHiddenQuotaModelIds/filterHiddenModelQuotas in
ProviderLimits/utils.tsx), which hides rows the ADMIN marked hidden in
the model catalog. This is a personal dashboard preference an operator
can toggle without touching the catalog — e.g. temporarily decluttering
a quota card with many low-signal rows.

New pure helpers (getQuotaVisibilityKey, filterQuotasByVisibility,
getHiddenQuotaRows) live in ProviderLimits/utils.tsx and are unit
tested directly; the settings key is added to DEFAULT_SETTINGS and
validated via updateSettingsSchema like the existing
providerStrategies field. New UI strings are filled in en.json and
synced to the other 42 locales as `__MISSING__` placeholders.

Co-authored-by: nguyenha935 <208228297+nguyenha935@users.noreply.github.com>
Inspired-by: https://github.com/decolua/9router/pull/2371

* chore(changelog): fragment for #7251

* refactor(usage): extract useQuotaVisibility hook (file-size budget)

ProviderLimits/index.tsx grew past its frozen 1127-line budget with the
quota-visibility wiring; extract the state + persistence + hide/show handlers
into a dedicated hook (same pattern as useCodexResetCreditRedemption).
No behavior change — the live validation evidence on the PR covers this flow
end-to-end.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* refactor(dashboard): shed QuotaCard complexity to baseline + type useQuotaVisibility settings fetch (#7251 CI green)

* test(dashboard): rename quota-row visibility test (path claimed by #7360)

* fix(dashboard): restore providerTierField case-collision fix dropped by merge auto-resolve

The git merge of origin/release/v3.8.49 auto-resolved providerTierFieldApi.ts
(added post-merge-base by commit 3ba3cd145e to fix a case-only filename
collision with ProviderTierField.tsx that breaks webpack on case-insensitive
filesystems) back down to its pre-fix name providerTierField.ts, silently
reverting that base-red fix and dropping its stryker tap.testFiles
registration and changelog fragment. Restore all four: the renamed helper
file, the import path in ProviderTierField.tsx, the import path in
tests/unit/provider-tier-field-helpers.test.ts, and the
combo-skip-conn-disable-plugin-block-7806.test.ts stryker registration.

---------

Co-authored-by: nguyenha935 <208228297+nguyenha935@users.noreply.github.com>
2026-07-20 16:10:42 -03:00

60 lines
2.2 KiB
TypeScript

import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
filterQuotasByVisibility,
getHiddenQuotaRows,
getQuotaVisibilityKey,
} from "../../src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.tsx";
describe("provider quota visibility (upstream 9router#2371 port)", () => {
const quotas = [
{ modelKey: "gemini-pro-agent", name: "Gemini 3.1 Pro (High)", used: 200, total: 1000 },
{
modelKey: "claude-opus-4-6-thinking",
name: "Claude Opus 4.6 (Thinking)",
used: 100,
total: 1000,
},
];
it("derives a stable key preferring modelKey over name", () => {
assert.equal(getQuotaVisibilityKey(quotas[0]), "gemini-pro-agent");
assert.equal(getQuotaVisibilityKey({ name: "no-model-key" }), "no-model-key");
assert.equal(getQuotaVisibilityKey(null), "");
assert.equal(getQuotaVisibilityKey(undefined), "");
});
it("shows all quotas by default (no visibility config)", () => {
assert.equal(filterQuotasByVisibility("antigravity", quotas, {}).length, 2);
assert.deepEqual(getHiddenQuotaRows("antigravity", quotas, {}), []);
});
it("hides the configured provider row and reports it separately", () => {
const visibility = { antigravity: { hidden: ["claude-opus-4-6-thinking"] } };
const visible = filterQuotasByVisibility("antigravity", quotas, visibility);
const hidden = getHiddenQuotaRows("antigravity", quotas, visibility);
assert.deepEqual(
visible.map((q) => q.modelKey),
["gemini-pro-agent"]
);
assert.deepEqual(
hidden.map((q) => q.modelKey),
["claude-opus-4-6-thinking"]
);
});
it("never applies one provider's hidden list to another provider", () => {
const visibility = { codex: { hidden: ["gemini-pro-agent"] } };
assert.equal(filterQuotasByVisibility("antigravity", quotas, visibility).length, 2);
assert.deepEqual(getHiddenQuotaRows("antigravity", quotas, visibility), []);
});
it("returns an empty array for non-array quotas input", () => {
assert.deepEqual(filterQuotasByVisibility("antigravity", undefined as unknown as [], {}), []);
assert.deepEqual(getHiddenQuotaRows("antigravity", undefined as unknown as [], {}), []);
});
});