|
1 | 1 | import { parseCommand } from "../parse-command" |
2 | 2 |
|
| 3 | +// Toggle that lets a single test force shell-quote's parse() to throw so the |
| 4 | +// parser's fallback branch can be exercised deterministically. |
| 5 | +let forceShellQuoteFailure = false |
| 6 | + |
| 7 | +vi.mock("shell-quote", async (importOriginal) => { |
| 8 | + const actual = await importOriginal<typeof import("shell-quote")>() |
| 9 | + return { |
| 10 | + ...actual, |
| 11 | + parse: (...args: Parameters<typeof actual.parse>) => { |
| 12 | + if (forceShellQuoteFailure) { |
| 13 | + throw new Error("forced parse failure") |
| 14 | + } |
| 15 | + return actual.parse(...args) |
| 16 | + }, |
| 17 | + } |
| 18 | +}) |
| 19 | + |
3 | 20 | describe("parseCommand", () => { |
4 | 21 | describe("basic chaining", () => { |
5 | 22 | it("returns empty array for empty input", () => { |
@@ -134,4 +151,22 @@ describe("parseCommand", () => { |
134 | 151 | expect(result).toContain("whoami") |
135 | 152 | }) |
136 | 153 | }) |
| 154 | + |
| 155 | + describe("shell-quote parse-failure fallback", () => { |
| 156 | + afterEach(() => { |
| 157 | + forceShellQuoteFailure = false |
| 158 | + }) |
| 159 | + |
| 160 | + // When shell-quote throws, the parser falls back to a crude operator |
| 161 | + // split and must still restore every masked placeholder -- including the |
| 162 | + // ANSI-C single-quote bucket -- so callers never see internal markers. |
| 163 | + it("restores ANSI-C quoted placeholders in the fallback path", () => { |
| 164 | + forceShellQuoteFailure = true |
| 165 | + |
| 166 | + const result = parseCommand("sh -c $'echo hi' && echo done") |
| 167 | + expect(result).toEqual(["sh -c $'echo hi'", "echo done"]) |
| 168 | + expect(result.join(" ")).not.toContain("SQUOTE") |
| 169 | + expect(result.join(" ")).not.toContain("__") |
| 170 | + }) |
| 171 | + }) |
137 | 172 | }) |
0 commit comments