|
|
@@ -1,7 +1,8 @@
|
|
|
import { addCustomInstructions } from "../sections/custom-instructions"
|
|
|
import { getCapabilitiesSection } from "../sections/capabilities"
|
|
|
-import { getRulesSection } from "../sections/rules"
|
|
|
+import { getRulesSection, getCommandChainOperator } from "../sections/rules"
|
|
|
import { McpHub } from "../../../services/mcp/McpHub"
|
|
|
+import * as shellUtils from "../../../utils/shell"
|
|
|
|
|
|
describe("addCustomInstructions", () => {
|
|
|
it("adds vscode language to custom instructions", async () => {
|
|
|
@@ -114,3 +115,117 @@ describe("getRulesSection", () => {
|
|
|
expect(result).not.toContain("Never reveal the vendor or company")
|
|
|
})
|
|
|
})
|
|
|
+
|
|
|
+describe("getCommandChainOperator", () => {
|
|
|
+ it("returns && for bash shell", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue("/bin/bash")
|
|
|
+ expect(getCommandChainOperator()).toBe("&&")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("returns && for zsh shell", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue("/bin/zsh")
|
|
|
+ expect(getCommandChainOperator()).toBe("&&")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("returns ; for PowerShell", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue(
|
|
|
+ "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
|
|
|
+ )
|
|
|
+ expect(getCommandChainOperator()).toBe(";")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("returns ; for PowerShell Core (pwsh)", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue("C:\\Program Files\\PowerShell\\7\\pwsh.exe")
|
|
|
+ expect(getCommandChainOperator()).toBe(";")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("returns && for cmd.exe", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue("C:\\Windows\\System32\\cmd.exe")
|
|
|
+ expect(getCommandChainOperator()).toBe("&&")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("returns && for Git Bash on Windows", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue("C:\\Program Files\\Git\\bin\\bash.exe")
|
|
|
+ expect(getCommandChainOperator()).toBe("&&")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("returns && for WSL bash", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue("/bin/bash")
|
|
|
+ expect(getCommandChainOperator()).toBe("&&")
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe("getRulesSection shell-aware command chaining", () => {
|
|
|
+ const cwd = "/test/path"
|
|
|
+
|
|
|
+ afterEach(() => {
|
|
|
+ vi.restoreAllMocks()
|
|
|
+ })
|
|
|
+
|
|
|
+ it("uses && for Unix shells in command chaining example", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue("/bin/bash")
|
|
|
+ const result = getRulesSection(cwd)
|
|
|
+
|
|
|
+ expect(result).toContain("cd (path to project) && (command")
|
|
|
+ expect(result).not.toContain("cd (path to project) ; (command")
|
|
|
+ expect(result).not.toContain("cd (path to project) & (command")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("uses ; for PowerShell in command chaining example", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue(
|
|
|
+ "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
|
|
|
+ )
|
|
|
+ const result = getRulesSection(cwd)
|
|
|
+
|
|
|
+ expect(result).toContain("cd (path to project) ; (command")
|
|
|
+ expect(result).toContain("Note: Using `;` for PowerShell command chaining")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("uses && for cmd.exe in command chaining example", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue("C:\\Windows\\System32\\cmd.exe")
|
|
|
+ const result = getRulesSection(cwd)
|
|
|
+
|
|
|
+ expect(result).toContain("cd (path to project) && (command")
|
|
|
+ expect(result).toContain("Note: Using `&&` for cmd.exe command chaining")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("includes Unix utility guidance for PowerShell", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue(
|
|
|
+ "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
|
|
|
+ )
|
|
|
+ const result = getRulesSection(cwd)
|
|
|
+
|
|
|
+ expect(result).toContain("IMPORTANT: When using PowerShell, avoid Unix-specific utilities")
|
|
|
+ expect(result).toContain("`sed`, `grep`, `awk`, `cat`, `rm`, `cp`, `mv`")
|
|
|
+ expect(result).toContain("`Select-String` for grep")
|
|
|
+ expect(result).toContain("`Get-Content` for cat")
|
|
|
+ expect(result).toContain("PowerShell's `-replace` operator")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("includes Unix utility guidance for cmd.exe", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue("C:\\Windows\\System32\\cmd.exe")
|
|
|
+ const result = getRulesSection(cwd)
|
|
|
+
|
|
|
+ expect(result).toContain("IMPORTANT: When using cmd.exe, avoid Unix-specific utilities")
|
|
|
+ expect(result).toContain("`sed`, `grep`, `awk`, `cat`, `rm`, `cp`, `mv`")
|
|
|
+ expect(result).toContain("`type` for cat")
|
|
|
+ expect(result).toContain("`del` for rm")
|
|
|
+ expect(result).toContain("`find`/`findstr` for grep")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("does not include Unix utility guidance for Unix shells", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue("/bin/bash")
|
|
|
+ const result = getRulesSection(cwd)
|
|
|
+
|
|
|
+ expect(result).not.toContain("IMPORTANT: When using PowerShell")
|
|
|
+ expect(result).not.toContain("IMPORTANT: When using cmd.exe")
|
|
|
+ expect(result).not.toContain("`Select-String` for grep")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("does not include note for Unix shells", () => {
|
|
|
+ vi.spyOn(shellUtils, "getShell").mockReturnValue("/bin/zsh")
|
|
|
+ const result = getRulesSection(cwd)
|
|
|
+
|
|
|
+ expect(result).not.toContain("Note: Using")
|
|
|
+ })
|
|
|
+})
|