Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
84 lines
2.7 KiB
TypeScript
84 lines
2.7 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import { parseShellArgs, formatShellArgs } from "./shellArgs";
|
|
|
|
test("parseShellArgs splits plain space-separated args", () => {
|
|
assert.deepEqual(parseShellArgs("--login -i"), ["--login", "-i"]);
|
|
});
|
|
|
|
test("parseShellArgs returns empty array for empty or whitespace input", () => {
|
|
assert.deepEqual(parseShellArgs(""), []);
|
|
assert.deepEqual(parseShellArgs(" "), []);
|
|
});
|
|
|
|
test("parseShellArgs collapses surrounding and repeated whitespace", () => {
|
|
assert.deepEqual(parseShellArgs(" --login -i "), ["--login", "-i"]);
|
|
assert.deepEqual(parseShellArgs("\t--login\t-i\n"), ["--login", "-i"]);
|
|
});
|
|
|
|
test("parseShellArgs keeps double-quoted args with spaces intact", () => {
|
|
assert.deepEqual(
|
|
parseShellArgs('--rcfile "C:\\Program Files\\rc"'),
|
|
["--rcfile", "C:\\Program Files\\rc"],
|
|
);
|
|
});
|
|
|
|
test("parseShellArgs keeps single-quoted args with spaces intact", () => {
|
|
assert.deepEqual(parseShellArgs("--msg 'hello world'"), ["--msg", "hello world"]);
|
|
});
|
|
|
|
test("parseShellArgs allows quotes in the middle of a token", () => {
|
|
assert.deepEqual(parseShellArgs('a"b c"d'), ["ab cd"]);
|
|
});
|
|
|
|
test("formatShellArgs joins plain args with single spaces", () => {
|
|
assert.equal(formatShellArgs(["--login", "-i"]), "--login -i");
|
|
});
|
|
|
|
test("formatShellArgs returns empty string for empty array", () => {
|
|
assert.equal(formatShellArgs([]), "");
|
|
});
|
|
|
|
test("formatShellArgs single-quotes tokens containing whitespace", () => {
|
|
assert.equal(formatShellArgs(["--msg", "hello world"]), "--msg 'hello world'");
|
|
});
|
|
|
|
test("formatShellArgs keeps Windows backslash paths intact (no escaping)", () => {
|
|
assert.equal(formatShellArgs(["--rcfile", "C:\\Program Files\\rc"]), "--rcfile 'C:\\Program Files\\rc'");
|
|
});
|
|
|
|
test("parse and format round-trip", () => {
|
|
const cases: string[][] = [
|
|
[],
|
|
["--login", "-i"],
|
|
["--msg", "hello world"],
|
|
["--rcfile", "C:\\Program Files\\rc"],
|
|
["-c", 'echo "hello world"'],
|
|
["--msg", "it's fine"],
|
|
["-c", `echo "it's ok"`],
|
|
["a'b", 'c"d'],
|
|
["C:\\dir\\"],
|
|
["-c", ""],
|
|
];
|
|
for (const args of cases) {
|
|
assert.deepEqual(parseShellArgs(formatShellArgs(args)), args);
|
|
}
|
|
});
|
|
|
|
test("parseShellArgs preserves a trailing backslash inside double quotes", () => {
|
|
assert.deepEqual(parseShellArgs('"C:\\dir\\"'), ["C:\\dir\\"]);
|
|
});
|
|
|
|
test("formatShellArgs uses single quotes for tokens containing double quotes", () => {
|
|
assert.equal(formatShellArgs(['echo "x"']), `'echo "x"'`);
|
|
});
|
|
|
|
test("formatShellArgs uses the POSIX '\\'' idiom for embedded single quotes", () => {
|
|
assert.equal(formatShellArgs(["it's"]), "'it'\\''s'");
|
|
});
|
|
|
|
test("formatShellArgs emits an explicit empty arg as ''", () => {
|
|
assert.equal(formatShellArgs(["-c", ""]), "-c ''");
|
|
});
|