mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-03 05:45:04 +03:00
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:
@@ -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 ? (
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
}: {
|
||||
|
||||
@@ -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", () => {
|
||||
|
||||
Reference in New Issue
Block a user