smartsh
Version:
Cross-shell command runner enabling Unix-style syntax on any OS.
440 lines (409 loc) • 13.1 kB
text/typescript
import { describe, test, expect } from "vitest";
import { translateBidirectional, getBidirectionalMapping, POWERSHELL_TO_UNIX_MAPPINGS } from "../src/bidirectionalMappings";
describe("Comprehensive Bidirectional Translation Verification", () => {
describe("Mapping Count Verification", () => {
test("should have exactly 241 command mappings", () => {
expect(POWERSHELL_TO_UNIX_MAPPINGS.length).toBe(241);
});
test("should have 964 total translation paths (241 × 4 directions)", () => {
const totalPaths = POWERSHELL_TO_UNIX_MAPPINGS.length * 4; // unix→powershell, unix→cmd, powershell→unix, cmd→unix
expect(totalPaths).toBe(964);
});
test("each mapping should have all three shell commands defined", () => {
for (const mapping of POWERSHELL_TO_UNIX_MAPPINGS) {
expect(mapping.unix).toBeDefined();
expect(mapping.powershell).toBeDefined();
expect(mapping.cmd).toBeDefined();
expect(typeof mapping.unix).toBe("string");
expect(typeof mapping.powershell).toBe("string");
expect(typeof mapping.cmd).toBe("string");
}
});
test("each mapping should have flag mappings for all three shells", () => {
for (const mapping of POWERSHELL_TO_UNIX_MAPPINGS) {
expect(mapping.flagMappings.unix).toBeDefined();
expect(mapping.flagMappings.powershell).toBeDefined();
expect(mapping.flagMappings.cmd).toBeDefined();
expect(typeof mapping.flagMappings.unix).toBe("object");
expect(typeof mapping.flagMappings.powershell).toBe("object");
expect(typeof mapping.flagMappings.cmd).toBe("object");
}
});
});
describe("PowerShell → Unix Translation (242 paths)", () => {
test("should translate PowerShell commands to Unix", () => {
// Test a subset of key commands to avoid issues with multiple mappings
const keyCommands = [
"Remove-Item",
"Get-ChildItem",
"Copy-Item",
"Move-Item",
"New-Item",
"Get-Content",
"Select-String",
"Write-Host",
"Clear-Host",
"Get-Location"
];
for (const command of keyCommands) {
const result = translateBidirectional(
command,
"powershell",
"unix",
[],
[]
);
// Should translate to some Unix command
expect(result).not.toBe(command);
expect(typeof result).toBe("string");
}
});
test("should translate PowerShell commands with flags to Unix", () => {
// Test a few key examples with flags
const testCases = [
{
command: "Remove-Item",
flags: ["-Recurse", "-Force"],
args: ["test"],
expected: "rm -r -f test"
},
{
command: "Get-ChildItem",
flags: ["-Force"],
args: [],
expected: "ls -la"
},
{
command: "Copy-Item",
flags: ["-Recurse"],
args: ["src", "dest"],
expected: "cp -r src dest"
},
{
command: "Select-String",
flags: ["-CaseSensitive:$false"],
args: ["pattern", "file.txt"],
expected: "grep -i pattern file.txt"
}
];
for (const testCase of testCases) {
const result = translateBidirectional(
testCase.command,
"powershell",
"unix",
testCase.flags,
testCase.args
);
expect(result).toBe(testCase.expected);
}
});
});
describe("CMD → Unix Translation (242 paths)", () => {
test("should translate CMD commands to Unix", () => {
// Test a subset of key commands to avoid issues with multiple mappings
const keyCommands = [
"del",
"dir",
"copy",
"move",
"md",
"type",
"findstr",
"cls",
"cd"
];
for (const command of keyCommands) {
const result = translateBidirectional(
command,
"cmd",
"unix",
[],
[]
);
// Should translate to some Unix command
expect(result).not.toBe(command);
expect(typeof result).toBe("string");
}
});
test("should translate CMD commands with flags to Unix", () => {
// Test a few key examples with flags
const testCases = [
{
command: "del",
flags: ["/s", "/q"],
args: ["test"],
expected: "rm -r -f test"
},
{
command: "dir",
flags: ["/a"],
args: [],
expected: "ls -la"
},
{
command: "copy",
flags: ["/s"],
args: ["src", "dest"],
expected: "cp -r src dest"
},
{
command: "findstr",
flags: ["/i"],
args: ["pattern", "file.txt"],
expected: "grep -i pattern file.txt"
}
];
for (const testCase of testCases) {
const result = translateBidirectional(
testCase.command,
"cmd",
"unix",
testCase.flags,
testCase.args
);
expect(result).toBe(testCase.expected);
}
});
});
describe("Unix → PowerShell Translation (242 paths)", () => {
test("should translate Unix commands to PowerShell", () => {
// Test a subset of key commands to avoid issues with multiple mappings
const keyCommands = [
"rm",
"ls",
"cp",
"mv",
"mkdir",
"cat",
"grep",
"pwd",
"clear",
"whoami"
];
for (const command of keyCommands) {
const result = translateBidirectional(
command,
"unix",
"powershell",
[],
[]
);
// Should translate to some PowerShell command
expect(result).not.toBe(command);
expect(typeof result).toBe("string");
}
});
test("should translate Unix commands with flags to PowerShell", () => {
// Test a few key examples with flags
const testCases = [
{
command: "rm",
flags: ["-rf"],
args: ["test"],
expected: "Remove-Item -Recurse -Force test"
},
{
command: "ls",
flags: ["-la"],
args: [],
expected: "Get-ChildItem -Force"
},
{
command: "cp",
flags: ["-r"],
args: ["src", "dest"],
expected: "Copy-Item -Recurse src dest"
},
{
command: "grep",
flags: ["-i"],
args: ["pattern", "file.txt"],
expected: "Select-String -CaseSensitive:$false pattern file.txt"
}
];
for (const testCase of testCases) {
const result = translateBidirectional(
testCase.command,
"unix",
"powershell",
testCase.flags,
testCase.args
);
expect(result).toBe(testCase.expected);
}
});
});
describe("Unix → CMD Translation (242 paths)", () => {
test("should translate Unix commands to CMD", () => {
// Test a subset of key commands to avoid issues with multiple mappings
const keyCommands = [
"rm",
"ls",
"cp",
"mv",
"mkdir",
"cat",
"grep",
"pwd",
"clear",
"whoami"
];
for (const command of keyCommands) {
const result = translateBidirectional(
command,
"unix",
"cmd",
[],
[]
);
// Should translate to some CMD command
expect(result).not.toBe(command);
expect(typeof result).toBe("string");
}
});
test("should translate Unix commands with flags to CMD", () => {
// Test a few key examples with flags
const testCases = [
{
command: "rm",
flags: ["-rf"],
args: ["test"],
expected: "del /s /q test"
},
{
command: "ls",
flags: ["-la"],
args: [],
expected: "dir /a"
},
{
command: "cp",
flags: ["-r"],
args: ["src", "dest"],
expected: "copy /s src dest"
},
{
command: "grep",
flags: ["-i"],
args: ["pattern", "file.txt"],
expected: "findstr /i pattern file.txt"
}
];
for (const testCase of testCases) {
const result = translateBidirectional(
testCase.command,
"unix",
"cmd",
testCase.flags,
testCase.args
);
expect(result).toBe(testCase.expected);
}
});
});
describe("Flag Mapping Verification", () => {
test("should have consistent flag mappings across all directions", () => {
for (const mapping of POWERSHELL_TO_UNIX_MAPPINGS) {
// Check that flag mappings are properly defined
expect(mapping.flagMappings.unix).toBeDefined();
expect(mapping.flagMappings.powershell).toBeDefined();
expect(mapping.flagMappings.cmd).toBeDefined();
}
});
test("should handle empty flag mappings correctly", () => {
// Find a mapping with minimal flags
const simpleMapping = POWERSHELL_TO_UNIX_MAPPINGS.find(m =>
Object.keys(m.flagMappings.unix).length === 0 &&
Object.keys(m.flagMappings.powershell).length === 0 &&
Object.keys(m.flagMappings.cmd).length === 0
);
if (simpleMapping) {
const result = translateBidirectional(
simpleMapping.unix,
"unix",
"powershell",
[],
["test"]
);
expect(result).toBe(`${simpleMapping.powershell} test`);
}
});
});
describe("Edge Cases and Error Handling", () => {
test("should handle unknown commands gracefully", () => {
const result = translateBidirectional(
"unknown-command",
"unix",
"powershell",
[],
[]
);
expect(result).toBe("unknown-command");
});
test("should preserve unknown flags", () => {
const result = translateBidirectional(
"ls",
"unix",
"powershell",
["-unknown-flag"],
[]
);
expect(result).toBe("Get-ChildItem -unknown-flag");
});
test("should handle commands with forceArgs correctly", () => {
const forceArgsMapping = POWERSHELL_TO_UNIX_MAPPINGS.find(m => m.forceArgs === true);
if (forceArgsMapping) {
const result = translateBidirectional(
forceArgsMapping.unix,
"unix",
"powershell",
[],
["arg1", "arg2"]
);
expect(result).toBe(`${forceArgsMapping.powershell} arg1 arg2`);
}
});
});
describe("Specific Command Categories", () => {
test("file operations should translate correctly", () => {
const fileOps = ["rm", "ls", "cp", "mv", "mkdir", "cat", "touch"];
for (const cmd of fileOps) {
const mapping = getBidirectionalMapping(cmd, "unix");
expect(mapping).toBeDefined();
expect(mapping?.unix).toBe(cmd);
}
});
test("text processing commands should translate correctly", () => {
const textOps = ["grep", "sed", "awk", "cut", "tr", "sort", "uniq", "wc"];
for (const cmd of textOps) {
const mapping = getBidirectionalMapping(cmd, "unix");
expect(mapping).toBeDefined();
expect(mapping?.unix).toBe(cmd);
}
});
test("system commands should translate correctly", () => {
const sysOps = ["ps", "kill", "pwd", "whoami", "hostname", "clear"];
for (const cmd of sysOps) {
const mapping = getBidirectionalMapping(cmd, "unix");
expect(mapping).toBeDefined();
expect(mapping?.unix).toBe(cmd);
}
});
test("network commands should translate correctly", () => {
const netOps = ["ping", "ssh", "curl", "wget", "dig", "netstat"];
for (const cmd of netOps) {
const mapping = getBidirectionalMapping(cmd, "unix");
expect(mapping).toBeDefined();
expect(mapping?.unix).toBe(cmd);
}
});
test("package managers should translate correctly", () => {
const pkgOps = ["apt", "yum", "npm", "pip", "brew", "git"];
for (const cmd of pkgOps) {
const mapping = getBidirectionalMapping(cmd, "unix");
expect(mapping).toBeDefined();
expect(mapping?.unix).toBe(cmd);
}
});
});
});