mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-15 11:22:15 +03:00
* chore(lint): batch 5 of #12146 — resolve the react-hooks compiler violations in combos, endpoint, provider-stats, api-manager and costs 40 violations across 14 files, all real refactors (no eslint-disable, no new suppressions; the areas' react-hooks entries are deleted from the freeze): - set-state-in-effect (30): fetch-on-mount effects moved behind an async continuation (usePools, usePoolUsage, useApiKeyUsageLimits, Notion/Obsidian source cards, A2A/MCP dashboards, ComboControlCenterClient, provider-stats, combos modal loaders, ApiManager initial load); prop/state sync converted to state adjustment during render with prev tracking (ApiKeyUsageLimitCard, PoolWizard dimensions/reset/group snap, combos sortMethod, builder reset, builder stage guard, single-provider default, stale intelligent selection); localStorage reads became lazy useState initializers (combos usage guide). - immutability / TDZ (8): effects that scheduled fetchers declared below them moved after the declarations (EndpointPageClient, ApiManagerPageClient, combos mount load); fetchData relocated below the per-key fetchers it calls. - static-components (7): provider-stats SortIcon hoisted to module level. - preserve-manual-memoization (2): ApiManager blockedModels dep destructured to a local; provider-scope derivation memoized so downstream memos see a stable dependency. Validation: eslint (CI command with suppressions, --max-warnings 0) clean on the 14 files; dashboard typecheck within baseline; mutation gate no drift; area tests 208/208 (node) + 29/29 (vitest). Refs #12146 * chore(lint): batch 5 follow-up — hoist the render-adjustment predicates so the new-code complexity gates stay flat The render adjustments added one cyclomatic branch to combos/page.tsx and one cognitive point to PoolWizard (caught by the new-code gate on the committed work); the compound conditions now live in pure module-level predicates. * chore(lint): batch 5 follow-up 2 — PoolWizard render adjustments live in two small hooks One consolidated hook tripped max-lines-per-function (>80) and the cognitive budget; the dimensions and open/close adjustments now live in two focused hooks with a shared WizardSetters type, and the group snap stays inline (one branch). complexityNewCode=0, cognitiveComplexityNewCode=0. * test(quota): repoint the two PoolWizard structural pins at the render-adjustment hook quota-edit-opens-wizard anchored the pre-fill block on the old '} else if (editPool)' effect literal and quota-pool-wizard-edit expected a bare 'if (editPool)' that only existed there; both now anchor on the batch-5 structure (submit still branches via if (!editPool)).
138 lines
4.7 KiB
TypeScript
138 lines
4.7 KiB
TypeScript
/**
|
|
* tests/unit/quota-edit-opens-wizard.test.ts
|
|
*
|
|
* Task 6 — source-scan assertions for:
|
|
* 1. QuotaSharePageClient no longer imports or renders EditAllocationsModal.
|
|
* 2. The `editing` pool is wired to a <PoolWizard via editPool prop.
|
|
* 3. editPoolExclusive is computed from apiKeys.allowedQuotas and passed through.
|
|
* 4. PoolWizard pre-fill uses editPoolExclusive (not a hard-coded false).
|
|
*
|
|
* Node native test runner — pure source analysis, no DOM needed.
|
|
*/
|
|
|
|
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
|
|
const PAGE_CLIENT_PATH = path.join(
|
|
ROOT,
|
|
"src",
|
|
"app",
|
|
"(dashboard)",
|
|
"dashboard",
|
|
"costs",
|
|
"quota-share",
|
|
"QuotaSharePageClient.tsx"
|
|
);
|
|
|
|
const WIZARD_PATH = path.join(
|
|
ROOT,
|
|
"src",
|
|
"app",
|
|
"(dashboard)",
|
|
"dashboard",
|
|
"costs",
|
|
"quota-share",
|
|
"components",
|
|
"PoolWizard.tsx"
|
|
);
|
|
|
|
const pageSrc = fs.readFileSync(PAGE_CLIENT_PATH, "utf-8");
|
|
const wizardSrc = fs.readFileSync(WIZARD_PATH, "utf-8");
|
|
|
|
// ── QuotaSharePageClient: EditAllocationsModal must be gone ───────────────────
|
|
|
|
test("QuotaSharePageClient: does NOT import EditAllocationsModal", () => {
|
|
assert.ok(
|
|
!pageSrc.includes("EditAllocationsModal"),
|
|
"EditAllocationsModal must not appear in QuotaSharePageClient (retired Task 6)"
|
|
);
|
|
});
|
|
|
|
// ── QuotaSharePageClient: editing pool wired to PoolWizard ────────────────────
|
|
|
|
test("QuotaSharePageClient: passes editing pool as editPool= to PoolWizard", () => {
|
|
assert.ok(
|
|
pageSrc.includes("editPool={editing"),
|
|
"Expected editPool={editing...} prop on the edit PoolWizard instance"
|
|
);
|
|
});
|
|
|
|
test("QuotaSharePageClient: opens edit wizard when editing is set (open={!!editing})", () => {
|
|
assert.ok(
|
|
pageSrc.includes("open={!!editing}"),
|
|
"Expected open={!!editing} on the edit PoolWizard instance"
|
|
);
|
|
});
|
|
|
|
// ── QuotaSharePageClient: editingExclusive computed and passed ────────────────
|
|
|
|
test("QuotaSharePageClient: computes editingExclusive from allowedQuotas", () => {
|
|
assert.ok(
|
|
pageSrc.includes("editingExclusive"),
|
|
"Expected editingExclusive to be defined in QuotaSharePageClient"
|
|
);
|
|
assert.ok(
|
|
pageSrc.includes("allowedQuotas"),
|
|
"Expected allowedQuotas referenced in editingExclusive computation"
|
|
);
|
|
});
|
|
|
|
test("QuotaSharePageClient: passes editPoolExclusive={editingExclusive} to edit PoolWizard", () => {
|
|
assert.ok(
|
|
pageSrc.includes("editPoolExclusive={editingExclusive}"),
|
|
"Expected editPoolExclusive={editingExclusive} on the edit PoolWizard instance"
|
|
);
|
|
});
|
|
|
|
test("QuotaSharePageClient: editingExclusive requires >=1 allocation", () => {
|
|
// The guard `editing.allocations.length > 0` must be present
|
|
assert.ok(
|
|
pageSrc.includes("allocations.length > 0"),
|
|
"Expected allocations.length > 0 guard in editingExclusive"
|
|
);
|
|
});
|
|
|
|
test("QuotaSharePageClient: editingExclusive checks every allocated key has pool id in allowedQuotas", () => {
|
|
assert.ok(
|
|
pageSrc.includes("aq.includes(editing.id)"),
|
|
"Expected aq.includes(editing.id) check in editingExclusive"
|
|
);
|
|
});
|
|
|
|
// ── PoolWizard: editPoolExclusive prop declared and used ─────────────────────
|
|
|
|
test("PoolWizard.tsx: declares editPoolExclusive prop in PoolWizardProps", () => {
|
|
assert.ok(
|
|
wizardSrc.includes("editPoolExclusive?"),
|
|
"Expected editPoolExclusive? field in PoolWizardProps"
|
|
);
|
|
});
|
|
|
|
test("PoolWizard.tsx: pre-fill uses editPoolExclusive ?? false (not setExclusive(false))", () => {
|
|
// The old hard-coded false must be replaced by the prop
|
|
assert.ok(
|
|
wizardSrc.includes("editPoolExclusive ?? false"),
|
|
"Expected setExclusive(editPoolExclusive ?? false) in PoolWizard pre-fill"
|
|
);
|
|
// The literal `setExclusive(false)` must NOT appear in the edit-mode pre-fill block
|
|
// (it may still appear in the close-reset block, which is correct)
|
|
// #12146 batch 5: the pre-fill moved from the reset effect ("} else if (editPool)")
|
|
// into useWizardOpenCloseAdjustment's render adjustment.
|
|
const editFillIdx = wizardSrc.indexOf("if (changed && open && editPool)");
|
|
assert.ok(editFillIdx >= 0, "Expected the editPool pre-fill adjustment block in PoolWizard");
|
|
const closingBrace = wizardSrc.indexOf("\n }", editFillIdx);
|
|
const editFillBlock = wizardSrc.slice(
|
|
editFillIdx,
|
|
closingBrace > 0 ? closingBrace + 4 : editFillIdx + 1200
|
|
);
|
|
assert.ok(
|
|
!editFillBlock.includes("setExclusive(false)"),
|
|
"setExclusive(false) must not appear in the editPool pre-fill block — must use editPoolExclusive"
|
|
);
|
|
});
|