smartsh
Version:
Cross-shell command runner enabling Unix-style syntax on any OS.
277 lines (234 loc) • 7.38 kB
text/typescript
console.log('translate.test.ts LOADED');
import { describe, expect, test } from "vitest";
import {
__test_splitByConnectors as splitByConnectors,
translateCommand,
} from "../src/translate";
describe("splitByConnectors", () => {
console.log('describe splitByConnectors ENTERED');
test("splits simple connectors", () => {
console.log('test splits simple connectors ENTERED');
expect(splitByConnectors("echo a && echo b || echo c")).toEqual([
"echo a",
"&&",
"echo b",
"||",
"echo c",
]);
expect(true).toBe(true);
});
test("ignores connectors inside quotes", () => {
expect(
splitByConnectors(
"node -e \"console.log('a && b')\" && echo after"
)
).toEqual([
"node -e \"console.log('a && b')\"",
"&&",
"echo after",
]);
});
test("filters empty tokens", () => {
expect(splitByConnectors("&& echo hi ||")).toEqual(["&&", "echo hi", "||"]);
});
test("handles nested quotes", () => {
expect(
splitByConnectors("echo \"outer 'inner && hidden'\" && echo after")
).toEqual([
"echo \"outer 'inner && hidden'\"",
"&&",
"echo after",
]);
});
test("ignores backtick-escaped connectors in PowerShell style", () => {
expect(splitByConnectors("echo a `&`& echo b || echo c")).toEqual([
"echo a `&`& echo b",
"||",
"echo c",
]);
});
});
describe("translateCommand", () => {
const legacyPS = {
type: "powershell",
supportsConditionalConnectors: false,
needsUnixTranslation: true,
targetShell: "powershell",
} as const;
test("translates for legacy PowerShell", () => {
expect(
translateCommand("echo ok && echo bad || echo fail", legacyPS)
).toBe("echo ok; if ($?) { echo bad }; if (-not $?) { echo fail }");
});
});
describe("translateCommand with Unix commands", () => {
const ps7 = { type: "powershell", supportsConditionalConnectors: true, needsUnixTranslation: true, targetShell: "powershell" } as const;
const ps5 = { type: "powershell", supportsConditionalConnectors: false, needsUnixTranslation: true, targetShell: "powershell" } as const;
test("translates rm -rf for PowerShell 7+", () => {
expect(translateCommand("rm -rf dist", ps7)).toBe(
"Remove-Item -Recurse -Force dist"
);
});
test("translates chain with connectors for legacy PowerShell", () => {
expect(
translateCommand("rm -rf dist && mkdir -p dist", ps5)
).toBe(
"Remove-Item -Recurse -Force dist; if ($?) { New-Item -ItemType Directory -Force dist }"
);
});
test("translates cp -r for PowerShell 7+", () => {
expect(translateCommand("cp -r src dist", ps7)).toBe(
"Copy-Item -Recurse src dist"
);
});
test("translates mv for PowerShell 7+", () => {
expect(translateCommand("mv a.txt b.txt", ps7)).toBe(
"Move-Item a.txt b.txt"
);
});
test("translates touch for PowerShell 7+", () => {
expect(translateCommand("touch new.txt", ps7)).toBe(
"New-Item -ItemType File new.txt"
);
});
test("translates pipeline with ls and grep", () => {
expect(translateCommand("ls -la | grep .js", ps7)).toBe(
"Get-ChildItem -Force | Select-String .js"
);
});
test("translates cat for PowerShell 7+", () => {
expect(translateCommand("cat file.txt", ps7)).toBe(
"Get-Content file.txt"
);
});
test("translates head -10", () => {
expect(translateCommand("head -10 file.txt", ps7)).toBe(
"Select-Object -First 10 file.txt"
);
});
test("translates tail -n 5", () => {
expect(translateCommand("tail -n 5 file.txt", ps7)).toBe(
"Select-Object -Last 5 file.txt"
);
});
test("translates wc -l", () => {
expect(translateCommand("wc -l", ps7)).toBe(
"Measure-Object -Line"
);
});
test("translates which", () => {
expect(translateCommand("which node", ps7)).toBe(
"Get-Command node"
);
});
test("translates sort", () => {
expect(translateCommand("sort", ps7)).toBe(
"Sort-Object"
);
});
test("translates uniq", () => {
expect(translateCommand("uniq", ps7)).toBe(
"Select-Object -Unique"
);
});
test("translates find -name pattern", () => {
expect(translateCommand("find . -name *.ts", ps7)).toBe(
"Get-ChildItem -Recurse -Filter . *.ts"
);
});
test("translates pwd", () => {
expect(translateCommand("pwd", ps7)).toBe(
"Get-Location"
);
});
test("translates date", () => {
expect(translateCommand("date", ps7)).toBe(
"Get-Date"
);
});
test("translates clear", () => {
expect(translateCommand("clear", ps7)).toBe(
"Clear-Host"
);
});
test("translates sleep 5", () => {
expect(translateCommand("sleep 5", ps7)).toBe(
"Start-Sleep 5"
);
});
test("translates ps", () => {
expect(translateCommand("ps", ps7)).toBe(
"Get-Process"
);
});
test("translates kill pid", () => {
expect(translateCommand("kill 1234", ps7)).toBe(
"Stop-Process 1234"
);
});
test("translates kill -9 pid", () => {
expect(translateCommand("kill -9 1234", ps7)).toBe(
"Stop-Process -Force 1234"
);
});
test("translates df -h", () => {
expect(translateCommand("df -h", ps7)).toBe(
"Get-PSDrive"
);
});
test("translates hostname", () => {
expect(translateCommand("hostname", ps7)).toBe(
"$env:COMPUTERNAME"
);
});
test("translates whoami", () => {
expect(translateCommand("whoami", ps7)).toBe(
"$env:USERNAME"
);
});
test("translates dirname", () => {
expect(translateCommand("dirname /etc/passwd", ps7)).toBe(
"Split-Path -Parent /etc/passwd"
);
});
test("translates basename", () => {
expect(translateCommand("basename /etc/passwd", ps7)).toBe(
"Split-Path -Leaf /etc/passwd"
);
});
test("translates tee -a", () => {
expect(translateCommand("echo foo | tee -a out.txt", ps7)).toBe(
"echo foo | Tee-Object -FilePath -Append out.txt"
);
});
test("translates sed substitution", () => {
expect(translateCommand("sed 's/foo/bar/' file.txt", ps7)).toBe(
"-replace 'foo','bar' file.txt"
);
});
test("translates pipeline with sed", () => {
expect(translateCommand("echo foo | sed 's/foo/bar/'", ps7)).toBe(
"echo foo | -replace 'foo','bar'"
);
});
test("translates sed substitution with g flag", () => {
expect(translateCommand("sed 's/foo/bar/g' file.txt", ps7)).toBe(
"-replace 'foo','bar' file.txt"
);
});
test("translates sed substitution with # delimiter", () => {
expect(translateCommand("sed 's#foo#bar#' file.txt", ps7)).toBe(
"-replace 'foo','bar' file.txt"
);
});
test("translates head -c N", () => {
expect(translateCommand("head -c 7 file.txt", ps7)).toBe(
"Select-Object -First 7 file.txt"
);
});
test("translates awk print $1", () => {
expect(translateCommand("awk '{print $1}'", ps7)).toBe(
"ForEach-Object { $_.Split()[0] }"
);
});
});