Skip to content

Commit b3d0411

Browse files
alerizzoclaude
andcommitted
refactor: address PR review on ls/directories commands
Resolve the Codacy quality-gate findings and Gemini review feedback on PR #26: - Extract shared presentation into src/commands/tree-view.ts (metric cells, JSON projections, glyphs) and split each command's action handler into small helpers, bringing both under the Lizard complexity/length thresholds and removing the ls/directories duplication. - Replace the non-literal `new RegExp(String.fromCharCode(27)...)` in the test files with a shared `consoleOutput()` helper (src/test-support.ts, excluded from the build) that uses a plain regex literal — fixes the Opengrep non-literal-regexp finding and the duplicated helper. - Handle null (not just undefined) in formatCountCell/formatCoverageCell, since the API may return null for an uncomputed metric. - Normalize `.`/`./` paths to the repository root in normalizeRepoPath. - Bound the --plus-children children fetches with a concurrency cap (mapWithConcurrency) instead of an unbounded Promise.all. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 529f6ad commit b3d0411

11 files changed

Lines changed: 519 additions & 385 deletions

src/commands/directories.test.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest";
22
import { Command } from "commander";
33
import { registerDirectoriesCommand } from "./directories";
44
import { RepositoryService } from "../api/client/services/RepositoryService";
5+
import { consoleOutput } from "../test-support";
56

67
vi.mock("../api/client/services/RepositoryService");
78
vi.mock("../utils/credentials", () => ({ loadCredentials: vi.fn(() => null) }));
@@ -22,15 +23,6 @@ function createProgram(): Command {
2223
return program;
2324
}
2425

25-
// Joined console output with ANSI color/style codes stripped, so assertions can
26-
// match plain text (dim() otherwise splits the tree connector from its name).
27-
function getOutput(): string {
28-
return (console.log as ReturnType<typeof vi.fn>).mock.calls
29-
.map((c) => c[0])
30-
.join("\n")
31-
.replace(new RegExp(String.fromCharCode(27) + "\\[[0-9;]*m", "g"), "");
32-
}
33-
3426
function dir(name: string, path = name) {
3527
return {
3628
path,
@@ -66,7 +58,7 @@ describe("directories command", () => {
6658
"repo",
6759
]);
6860

69-
const out = getOutput();
61+
const out = consoleOutput();
7062
expect(out).toContain("▸ pages");
7163
expect(out).toContain("▸ components");
7264
expect(out).toContain("2 directories");
@@ -101,7 +93,7 @@ describe("directories command", () => {
10193
vi.mocked(RepositoryService.listDirectories).mock.calls[1][4],
10294
).toBe("pages");
10395

104-
const out = getOutput();
96+
const out = consoleOutput();
10597
expect(out).toContain("▸ pages");
10698
expect(out).toContain("└─ account");
10799
expect(out).toContain("└─ admin");
@@ -131,7 +123,7 @@ describe("directories command", () => {
131123
"--plus-children",
132124
]);
133125

134-
expect(getOutput()).toContain("2 directories, 3 subdirectories");
126+
expect(consoleOutput()).toContain("2 directories, 3 subdirectories");
135127
});
136128

137129
it("forwards --sort/--direction to the root and children listings", async () => {
@@ -206,7 +198,7 @@ describe("directories command", () => {
206198
"--plus-children",
207199
]);
208200

209-
const out = getOutput();
201+
const out = consoleOutput();
210202
expect(out).toContain('"children"');
211203
expect(out).toContain('"name": "account"');
212204
});
@@ -226,7 +218,7 @@ describe("directories command", () => {
226218
"repo",
227219
]);
228220

229-
const out = getOutput();
221+
const out = consoleOutput();
230222
expect(out).toContain("No directories found");
231223
});
232224

0 commit comments

Comments
 (0)