fix(cli): address code review v2 findings — broken test path, dead code, type narrowing (plan 14)

- tests/unit/custom-cli-config.test.ts: fix ERR_MODULE_NOT_FOUND — stale import path cli-tools → cli-code (regression from F8 git mv, missed by F10 audit because it only ran curated test subset).
- tests/unit/ui/CliAgentsPage.test.tsx: update vi.mock path to current cli-code location (was no-op mock pointing to deleted path).
- tests/unit/ui/CliToolCard.test.tsx: update URL strings /dashboard/cli-tools/claude → /dashboard/cli-code/claude (cosmetic alignment with new routes).
- src/app/(dashboard)/dashboard/cli-code/components/ToolDetailClient.tsx: remove dead case "cliproxyapi" + unused import (no entry in CLI_TOOLS catalog).
- src/app/(dashboard)/dashboard/cli-agents/CliAgentsPageClient.tsx: replace inline div skeleton with shared <CardSkeleton /> for visual consistency with CliCodePageClient.
- src/app/api/cli-tools/{forge,jcode,deepseek-tui,smelt,pi}-settings/route.ts: replace catch (err: any) with catch (err) + (err as NodeJS.ErrnoException).code narrowing (8 instances, eliminates 8 of 11 implicit-any introductions).

Validated: custom-cli-config.test.ts now 3/3 PASS (was 0/1 FAIL with ERR_MODULE_NOT_FOUND); F1/F3 tests 147/147 PASS; UI tests 25/25 PASS; typecheck:core + noimplicit clean.
This commit is contained in:
diegosouzapw
2026-05-28 12:47:31 -03:00
parent 6f62311778
commit 77b055aba0
10 changed files with 23 additions and 29 deletions

View File

@@ -3,6 +3,7 @@
import { useMemo, useState } from "react";
import { useTranslations } from "next-intl";
import { CLI_TOOLS } from "@/shared/constants/cliTools";
import { CardSkeleton } from "@/shared/components";
import { CliToolCard, CliConceptCard, CliComparisonCard } from "@/shared/components/cli";
import { useToolBatchStatuses } from "@/shared/hooks/cli/useToolBatchStatuses";
@@ -123,11 +124,7 @@ export default function CliAgentsPageClient({ machineId: _machineId }: CliAgents
{loading ? (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
{agentTools.map((tool) => (
<div
key={tool.id}
className="h-[180px] animate-pulse bg-black/[0.04] dark:bg-white/[0.04] rounded-lg"
aria-hidden="true"
/>
<CardSkeleton key={tool.id} />
))}
</div>
) : filteredTools.length === 0 ? (

View File

@@ -17,7 +17,6 @@ import {
KiloToolCard,
OpenClawToolCard,
} from "./index";
import CliproxyapiToolCard from "./CliproxyapiToolCard";
export interface ToolDetailClientProps {
toolId: string;
@@ -211,8 +210,6 @@ export default function ToolDetailClient({ toolId, category }: ToolDetailClientP
return <HermesAgentToolCard {...cardProps} />;
case "antigravity":
return <AntigravityToolCard {...cardProps} />;
case "cliproxyapi":
return <CliproxyapiToolCard isExpanded={true} onToggle={() => {}} />;
case "custom":
return <CustomCliCard {...cardProps} />;
default:

View File

@@ -53,8 +53,8 @@ const hasOmniRouteConfig = (content: string | null): boolean => {
const readConfig = async (): Promise<string | null> => {
try {
return await fs.readFile(getDeepseekTuiConfigPath(), "utf-8");
} catch (err: any) {
if (err.code === "ENOENT") return null;
} catch (err) {
if ((err as NodeJS.ErrnoException).code === "ENOENT") return null;
throw err;
}
};

View File

@@ -54,8 +54,8 @@ const hasOmniRouteConfig = (content: string | null): boolean => {
const readConfig = async (): Promise<string | null> => {
try {
return await fs.readFile(getForgeConfigPath(), "utf-8");
} catch (err: any) {
if (err.code === "ENOENT") return null;
} catch (err) {
if ((err as NodeJS.ErrnoException).code === "ENOENT") return null;
throw err;
}
};

View File

@@ -40,8 +40,8 @@ const readConfig = async (): Promise<Record<string, unknown> | null> => {
try {
const content = await fs.readFile(getJcodeConfigPath(), "utf-8");
return JSON.parse(content) as Record<string, unknown>;
} catch (err: any) {
if (err.code === "ENOENT") return null;
} catch (err) {
if ((err as NodeJS.ErrnoException).code === "ENOENT") return null;
throw err;
}
};
@@ -193,8 +193,8 @@ export async function DELETE(request: Request) {
try {
const raw = await fs.readFile(configPath, "utf-8");
existing = JSON.parse(raw) as Record<string, unknown>;
} catch (err: any) {
if (err.code === "ENOENT") {
} catch (err) {
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
return NextResponse.json({ success: true, message: "No config file to reset" });
}
throw err;

View File

@@ -40,8 +40,8 @@ const readConfig = async (): Promise<Record<string, unknown> | null> => {
try {
const content = await fs.readFile(getPiConfigPath(), "utf-8");
return JSON.parse(content) as Record<string, unknown>;
} catch (err: any) {
if (err.code === "ENOENT") return null;
} catch (err) {
if ((err as NodeJS.ErrnoException).code === "ENOENT") return null;
throw err;
}
};
@@ -193,8 +193,8 @@ export async function DELETE(request: Request) {
try {
const raw = await fs.readFile(configPath, "utf-8");
existing = JSON.parse(raw) as Record<string, unknown>;
} catch (err: any) {
if (err.code === "ENOENT") {
} catch (err) {
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
return NextResponse.json({ success: true, message: "No config file to reset" });
}
throw err;

View File

@@ -40,8 +40,8 @@ const readConfig = async (): Promise<Record<string, unknown> | null> => {
try {
const content = await fs.readFile(getSmeltConfigPath(), "utf-8");
return JSON.parse(content) as Record<string, unknown>;
} catch (err: any) {
if (err.code === "ENOENT") return null;
} catch (err) {
if ((err as NodeJS.ErrnoException).code === "ENOENT") return null;
throw err;
}
};
@@ -193,8 +193,8 @@ export async function DELETE(request: Request) {
try {
const raw = await fs.readFile(configPath, "utf-8");
existing = JSON.parse(raw) as Record<string, unknown>;
} catch (err: any) {
if (err.code === "ENOENT") {
} catch (err) {
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
return NextResponse.json({ success: true, message: "No config file to reset" });
}
throw err;

View File

@@ -6,7 +6,7 @@ import {
buildCustomCliEnvScript,
buildCustomCliJsonConfig,
normalizeOpenAiBaseUrl,
} from "../../src/app/(dashboard)/dashboard/cli-tools/components/customCliConfig.ts";
} from "../../src/app/(dashboard)/dashboard/cli-code/components/customCliConfig.ts";
test("normalizeOpenAiBaseUrl appends /v1 only when needed", () => {
assert.equal(normalizeOpenAiBaseUrl("http://localhost:20128"), "http://localhost:20128/v1");

View File

@@ -36,7 +36,7 @@ vi.mock("next-intl", () => ({
}));
// Stub CliStatusBadge so it doesn't depend on next-intl internals
vi.mock("@/app/(dashboard)/dashboard/cli-tools/components/CliStatusBadge", () => ({
vi.mock("@/app/(dashboard)/dashboard/cli-code/components/CliStatusBadge", () => ({
default: ({
effectiveConfigStatus,
}: {

View File

@@ -113,15 +113,15 @@ afterEach(() => {
describe("CliToolCard", () => {
it("renders tool name", () => {
const container = renderCard(makeTool(), makeBatchStatus(), "/dashboard/cli-tools/claude", true);
const container = renderCard(makeTool(), makeBatchStatus(), "/dashboard/cli-code/claude", true);
expect(container.textContent).toContain("Claude Code");
});
it("links to detailHref", () => {
const container = renderCard(makeTool(), makeBatchStatus(), "/dashboard/cli-tools/claude", true);
const container = renderCard(makeTool(), makeBatchStatus(), "/dashboard/cli-code/claude", true);
const link = container.querySelector("a");
expect(link).not.toBeNull();
expect(link!.getAttribute("href")).toBe("/dashboard/cli-tools/claude");
expect(link!.getAttribute("href")).toBe("/dashboard/cli-code/claude");
});
it("shows version when installed", () => {