import { describe, expect, it } from "vitest";
import { collectCodeRuntimeContext } from "../src/extension/runtime/codeRuntimeContext";
const workspaceRoot = "E:\\zz\\loopagent-vscode";
describe("collectCodeRuntimeContext", () => {
it("uses selected text before a cursor snippet", () => {
const context = collectCodeRuntimeContext(
{
workspace: {
name: "LoopAgent",
roots: [workspaceRoot],
},
activeEditor: {
document: {
path: `${workspaceRoot}\\src\\shared\\messages.ts`,
languageId: "typescript",
text: ["type A = string;", "const selected = true;", "const after = false;"].join("\n"),
isDirty: true,
},
cursor: {
line: 2,
character: 7,
},
selection: {
startLine: 2,
startCharacter: 1,
endLine: 2,
endCharacter: 23,
text: "const selected = true;",
},
},
projectFiles: [
{
path: `${workspaceRoot}\\package.json`,
kind: "manifest",
text: JSON.stringify({
name: "loopagent-vscode",
scripts: { test: "vitest run", compile: "node esbuild.js" },
dependencies: { react: "^19.2.7" },
devDependencies: { vitest: "^4.1.9" },
}),
},
],
},
{ maxChars: 2_000, now: "2026-07-07T00:00:00.000Z" },
);
expect(context.workspace).toEqual({
name: "LoopAgent",
roots: ["loopagent-vscode"],
});
expect(context.activeEditor?.path).toBe("src/shared/messages.ts");
expect(context.activeEditor?.selection?.text).toBe("const selected = true;");
expect(context.activeEditor?.snippet).toBeUndefined();
expect(context.projectFiles).toEqual([
expect.objectContaining({
path: "package.json",
kind: "manifest",
summary: expect.stringContaining("name: loopagent-vscode"),
}),
]);
expect(context.budget.truncated).toBe(false);
});
it("collects a nearby snippet when there is no selection", () => {
const context = collectCodeRuntimeContext(
{
workspace: {
roots: [workspaceRoot],
},
activeEditor: {
document: {
path: `${workspaceRoot}\\src\\extension.ts`,
languageId: "typescript",
text: ["line 1", "line 2", "line 3", "line 4", "line 5", "line 6"].join("\n"),
},
cursor: {
line: 4,
character: 1,
},
},
},
{ snippetRadiusLines: 1, now: "2026-07-07T00:00:00.000Z" },
);
expect(context.activeEditor?.snippet).toEqual({
startLine: 3,
endLine: 5,
text: ["line 3", "line 4", "line 5"].join("\n"),
truncated: false,
});
});
it("filters sensitive paths, excluded directories, and low severity diagnostics", () => {
const context = collectCodeRuntimeContext(
{
workspace: {
roots: [workspaceRoot],
},
visibleEditors: [
{
path: `${workspaceRoot}\\src\\extension.ts`,
languageId: "typescript",
text: "export {};",
},
{
path: `${workspaceRoot}\\node_modules\\left-pad\\index.js`,
languageId: "javascript",
text: "module.exports = {};",
},
{
path: `${workspaceRoot}\\.env`,
languageId: "dotenv",
text: "IGNORED=value",
},
],
openTabs: [
{
path: `${workspaceRoot}\\src\\extension.ts`,
languageId: "typescript",
isDirty: false,
},
{
path: `${workspaceRoot}\\.local-vscode-user-data\\User\\settings.json`,
languageId: "json",
},
],
projectFiles: [
{
path: `${workspaceRoot}\\README.md`,
kind: "doc",
text: "# LoopAgent",
},
{
path: `${workspaceRoot}\\secrets\\api-token.txt`,
kind: "doc",
text: "token",
},
],
diagnostics: [
{
path: `${workspaceRoot}\\src\\extension.ts`,
severity: "error",
line: 12,
character: 3,
message: "Cannot find name",
},
{
path: `${workspaceRoot}\\src\\extension.ts`,
severity: "information",
line: 14,
character: 1,
message: "Informational only",
},
],
},
{ now: "2026-07-07T00:00:00.000Z" },
);
expect(context.visibleEditors).toEqual([
expect.objectContaining({
path: "src/extension.ts",
}),
]);
expect(context.openTabs).toEqual([
expect.objectContaining({
path: "src/extension.ts",
}),
]);
expect(context.projectFiles).toEqual([
expect.objectContaining({
path: "README.md",
}),
]);
expect(context.diagnostics).toEqual([
{
path: "src/extension.ts",
severity: "error",
line: 12,
character: 3,
message: "Cannot find name",
},
]);
});
});