Files

216 lines
4.3 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { mkdtempSync, writeFileSync, mkdirSync, rmSync } from "fs";
import { join } from "path";
import { tmpdir } from "os";
import { execSync } from "child_process";
import { fileURLToPath } from "url";
const projectRoot = fileURLToPath(new URL("..", import.meta.url));
function runCli(
args: string,
cwd: string,
): { stdout: string; stderr: string; exitCode: number } {
try {
const stdout = execSync(
`npx tsx ${join(projectRoot, "src/cli/cli.ts")} ${args}`,
{
cwd,
encoding: "utf8",
stdio: ["pipe", "pipe", "pipe"],
},
);
return { stdout: stdout.trim(), stderr: "", exitCode: 0 };
} catch (err: any) {
return {
stdout: err.stdout?.toString().trim() || "",
stderr: err.stderr?.toString().trim() || "",
exitCode: err.status || 1,
};
}
}
describe("cli context", () => {
let dir: string;
beforeEach(() => {
dir = mkdtempSync(join(tmpdir(), "pi-map-cli-"));
});
afterEach(() => {
rmSync(dir, { recursive: true });
});
it("context command returns a bundle for a matching query", () => {
mkdirSync(join(dir, "src"));
mkdirSync(join(dir, "src", "auth"));
writeFileSync(
join(dir, "src", "auth", "tokens.ts"),
`export function validateToken() {}\n`,
);
writeFileSync(
join(dir, "src", "auth", ".pi-map.md"),
`# src/auth
dir: src/auth
index: src/auth/.pi-map.index.md
## role
Authentication and token validation.
## files
- tokens.ts | Token validation | exp: validateToken | dep: -
## arch
Guard pattern.
## tags
auth, token, validate
## symbols
validateToken
## workflows
- validate token
files: tokens.ts
## dirty
-
`,
);
writeFileSync(
join(dir, "src", "auth", ".pi-map.index.md"),
`# src/auth (index)
dir: src/auth
## role
Auth layer.
## parent
index: ./.pi-map.index.md
map: ./.pi-map.md
## children
-
## files
- tokens.ts
## links
index: src/auth/.pi-map.index.md
map: src/auth/.pi-map.md
## workflows
- validate token
## dirty
-
`,
);
const { stdout, exitCode } = runCli('context "token validation"', dir);
expect(exitCode).toBe(0);
expect(stdout).toContain("# Context bundle: token validation");
expect(stdout).toContain("## relevant indexes");
expect(stdout).toContain("src/auth/.pi-map.index.md");
expect(stdout).toContain("## relevant maps");
expect(stdout).toContain("src/auth/.pi-map.md");
expect(stdout).toContain("## likely files");
expect(stdout).toContain("src/auth/tokens.ts");
expect(stdout).toContain("## instructions");
});
it("context command omits symbols section when no symbols exist", () => {
mkdirSync(join(dir, "src"));
writeFileSync(
join(dir, "src", ".pi-map.md"),
`# src
dir: src
index: src/.pi-map.index.md
## role
Core source.
## files
- index.ts | Entry | exp: main | dep: -
## arch
Entrypoint.
## tags
-
## symbols
-
## workflows
-
## dirty
-
`,
);
writeFileSync(
join(dir, "src", ".pi-map.index.md"),
`# src (index)
dir: src
## role
Core source.
## parent
-
## children
-
## files
- index.ts
## links
index: src/.pi-map.index.md
map: src/.pi-map.md
## workflows
-
## dirty
-
`,
);
const { stdout, exitCode } = runCli('context "core source"', dir);
expect(exitCode).toBe(0);
expect(stdout).toContain("# Context bundle: core source");
expect(stdout).not.toContain("## relevant symbols");
});
it("context command returns no-results bundle when nothing matches", () => {
mkdirSync(join(dir, "src"));
writeFileSync(
join(dir, "src", ".pi-map.md"),
`# src
dir: src
index: src/.pi-map.index.md
## role
Core source.
## files
- index.ts | Entry | exp: main | dep: -
## arch
Entrypoint.
## tags
-
## symbols
-
## workflows
-
## dirty
-
`,
);
writeFileSync(
join(dir, "src", ".pi-map.index.md"),
`# src (index)
dir: src
## role
Core source.
## parent
-
## children
-
## files
- index.ts
## links
index: src/.pi-map.index.md
map: src/.pi-map.md
## workflows
-
## dirty
-
`,
);
const { stdout, exitCode } = runCli('context "zzzzzzzz"', dir);
expect(exitCode).toBe(0);
expect(stdout).toContain("# Context bundle: zzzzzzzz");
expect(stdout).toContain("No relevant directories found");
});
it("context command errors when query is missing", () => {
const { stderr, exitCode } = runCli("context", dir);
expect(exitCode).toBe(1);
expect(stderr).toContain("Missing query");
});
});