|
|
@@ -0,0 +1,222 @@
|
|
|
+import * as vscode from "vscode"
|
|
|
+import { userInfo } from "os"
|
|
|
+import { getShell } from "../shell"
|
|
|
+
|
|
|
+describe("Shell Detection Tests", () => {
|
|
|
+ let originalPlatform: string
|
|
|
+ let originalEnv: NodeJS.ProcessEnv
|
|
|
+ let originalGetConfig: any
|
|
|
+ let originalUserInfo: any
|
|
|
+
|
|
|
+ // Helper to mock VS Code configuration
|
|
|
+ function mockVsCodeConfig(platformKey: string, defaultProfileName: string | null, profiles: Record<string, any>) {
|
|
|
+ vscode.workspace.getConfiguration = () =>
|
|
|
+ ({
|
|
|
+ get: (key: string) => {
|
|
|
+ if (key === `defaultProfile.${platformKey}`) {
|
|
|
+ return defaultProfileName
|
|
|
+ }
|
|
|
+ if (key === `profiles.${platformKey}`) {
|
|
|
+ return profiles
|
|
|
+ }
|
|
|
+ return undefined
|
|
|
+ },
|
|
|
+ }) as any
|
|
|
+ }
|
|
|
+
|
|
|
+ beforeEach(() => {
|
|
|
+ // Store original references
|
|
|
+ originalPlatform = process.platform
|
|
|
+ originalEnv = { ...process.env }
|
|
|
+ originalGetConfig = vscode.workspace.getConfiguration
|
|
|
+ originalUserInfo = userInfo
|
|
|
+
|
|
|
+ // Clear environment variables for a clean test
|
|
|
+ delete process.env.SHELL
|
|
|
+ delete process.env.COMSPEC
|
|
|
+
|
|
|
+ // Default userInfo() mock
|
|
|
+ ;(userInfo as any) = () => ({ shell: null })
|
|
|
+ })
|
|
|
+
|
|
|
+ afterEach(() => {
|
|
|
+ // Restore everything
|
|
|
+ Object.defineProperty(process, "platform", { value: originalPlatform })
|
|
|
+ process.env = originalEnv
|
|
|
+ vscode.workspace.getConfiguration = originalGetConfig
|
|
|
+ ;(userInfo as any) = originalUserInfo
|
|
|
+ })
|
|
|
+
|
|
|
+ // --------------------------------------------------------------------------
|
|
|
+ // Windows Shell Detection
|
|
|
+ // --------------------------------------------------------------------------
|
|
|
+ describe("Windows Shell Detection", () => {
|
|
|
+ beforeEach(() => {
|
|
|
+ Object.defineProperty(process, "platform", { value: "win32" })
|
|
|
+ })
|
|
|
+
|
|
|
+ it("uses explicit PowerShell 7 path from VS Code config (profile path)", () => {
|
|
|
+ mockVsCodeConfig("windows", "PowerShell", {
|
|
|
+ PowerShell: { path: "C:\\Program Files\\PowerShell\\7\\pwsh.exe" },
|
|
|
+ })
|
|
|
+ expect(getShell()).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("uses PowerShell 7 path if source is 'PowerShell' but no explicit path", () => {
|
|
|
+ mockVsCodeConfig("windows", "PowerShell", {
|
|
|
+ PowerShell: { source: "PowerShell" },
|
|
|
+ })
|
|
|
+ expect(getShell()).toBe("C:\\Program Files\\PowerShell\\7\\pwsh.exe")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("falls back to legacy PowerShell if profile includes 'powershell' but no path/source", () => {
|
|
|
+ mockVsCodeConfig("windows", "PowerShell", {
|
|
|
+ PowerShell: {},
|
|
|
+ })
|
|
|
+ expect(getShell()).toBe("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("uses WSL bash when profile indicates WSL source", () => {
|
|
|
+ mockVsCodeConfig("windows", "WSL", {
|
|
|
+ WSL: { source: "WSL" },
|
|
|
+ })
|
|
|
+ expect(getShell()).toBe("/bin/bash")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("uses WSL bash when profile name includes 'wsl'", () => {
|
|
|
+ mockVsCodeConfig("windows", "Ubuntu WSL", {
|
|
|
+ "Ubuntu WSL": {},
|
|
|
+ })
|
|
|
+ expect(getShell()).toBe("/bin/bash")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("defaults to cmd.exe if no special profile is matched", () => {
|
|
|
+ mockVsCodeConfig("windows", "CommandPrompt", {
|
|
|
+ CommandPrompt: {},
|
|
|
+ })
|
|
|
+ expect(getShell()).toBe("C:\\Windows\\System32\\cmd.exe")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("respects userInfo() if no VS Code config is available", () => {
|
|
|
+ vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
|
|
|
+ ;(userInfo as any) = () => ({ shell: "C:\\Custom\\PowerShell.exe" })
|
|
|
+
|
|
|
+ expect(getShell()).toBe("C:\\Custom\\PowerShell.exe")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("respects an odd COMSPEC if no userInfo shell is available", () => {
|
|
|
+ vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
|
|
|
+ process.env.COMSPEC = "D:\\CustomCmd\\cmd.exe"
|
|
|
+
|
|
|
+ expect(getShell()).toBe("D:\\CustomCmd\\cmd.exe")
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ // --------------------------------------------------------------------------
|
|
|
+ // macOS Shell Detection
|
|
|
+ // --------------------------------------------------------------------------
|
|
|
+ describe("macOS Shell Detection", () => {
|
|
|
+ beforeEach(() => {
|
|
|
+ Object.defineProperty(process, "platform", { value: "darwin" })
|
|
|
+ })
|
|
|
+
|
|
|
+ it("uses VS Code profile path if available", () => {
|
|
|
+ mockVsCodeConfig("osx", "MyCustomShell", {
|
|
|
+ MyCustomShell: { path: "/usr/local/bin/fish" },
|
|
|
+ })
|
|
|
+ expect(getShell()).toBe("/usr/local/bin/fish")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("falls back to userInfo().shell if no VS Code config is available", () => {
|
|
|
+ vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
|
|
|
+ ;(userInfo as any) = () => ({ shell: "/opt/homebrew/bin/zsh" })
|
|
|
+ expect(getShell()).toBe("/opt/homebrew/bin/zsh")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("falls back to SHELL env var if no userInfo shell is found", () => {
|
|
|
+ vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
|
|
|
+ process.env.SHELL = "/usr/local/bin/zsh"
|
|
|
+ expect(getShell()).toBe("/usr/local/bin/zsh")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("falls back to /bin/zsh if no config, userInfo, or env variable is set", () => {
|
|
|
+ vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
|
|
|
+ expect(getShell()).toBe("/bin/zsh")
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ // --------------------------------------------------------------------------
|
|
|
+ // Linux Shell Detection
|
|
|
+ // --------------------------------------------------------------------------
|
|
|
+ describe("Linux Shell Detection", () => {
|
|
|
+ beforeEach(() => {
|
|
|
+ Object.defineProperty(process, "platform", { value: "linux" })
|
|
|
+ })
|
|
|
+
|
|
|
+ it("uses VS Code profile path if available", () => {
|
|
|
+ mockVsCodeConfig("linux", "CustomProfile", {
|
|
|
+ CustomProfile: { path: "/usr/bin/fish" },
|
|
|
+ })
|
|
|
+ expect(getShell()).toBe("/usr/bin/fish")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("falls back to userInfo().shell if no VS Code config is available", () => {
|
|
|
+ vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
|
|
|
+ ;(userInfo as any) = () => ({ shell: "/usr/bin/zsh" })
|
|
|
+ expect(getShell()).toBe("/usr/bin/zsh")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("falls back to SHELL env var if no userInfo shell is found", () => {
|
|
|
+ vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
|
|
|
+ process.env.SHELL = "/usr/bin/fish"
|
|
|
+ expect(getShell()).toBe("/usr/bin/fish")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("falls back to /bin/bash if nothing is set", () => {
|
|
|
+ vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
|
|
|
+ expect(getShell()).toBe("/bin/bash")
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ // --------------------------------------------------------------------------
|
|
|
+ // Unknown Platform & Error Handling
|
|
|
+ // --------------------------------------------------------------------------
|
|
|
+ describe("Unknown Platform / Error Handling", () => {
|
|
|
+ it("falls back to /bin/sh for unknown platforms", () => {
|
|
|
+ Object.defineProperty(process, "platform", { value: "sunos" })
|
|
|
+ vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
|
|
|
+ expect(getShell()).toBe("/bin/sh")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("handles VS Code config errors gracefully, falling back to userInfo shell if present", () => {
|
|
|
+ Object.defineProperty(process, "platform", { value: "linux" })
|
|
|
+ vscode.workspace.getConfiguration = () => {
|
|
|
+ throw new Error("Configuration error")
|
|
|
+ }
|
|
|
+ ;(userInfo as any) = () => ({ shell: "/bin/bash" })
|
|
|
+ expect(getShell()).toBe("/bin/bash")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("handles userInfo errors gracefully, falling back to environment variable if present", () => {
|
|
|
+ Object.defineProperty(process, "platform", { value: "darwin" })
|
|
|
+ vscode.workspace.getConfiguration = () => ({ get: () => undefined }) as any
|
|
|
+ ;(userInfo as any) = () => {
|
|
|
+ throw new Error("userInfo error")
|
|
|
+ }
|
|
|
+ process.env.SHELL = "/bin/zsh"
|
|
|
+ expect(getShell()).toBe("/bin/zsh")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("falls back fully to default shell paths if everything fails", () => {
|
|
|
+ Object.defineProperty(process, "platform", { value: "linux" })
|
|
|
+ vscode.workspace.getConfiguration = () => {
|
|
|
+ throw new Error("Configuration error")
|
|
|
+ }
|
|
|
+ ;(userInfo as any) = () => {
|
|
|
+ throw new Error("userInfo error")
|
|
|
+ }
|
|
|
+ delete process.env.SHELL
|
|
|
+ expect(getShell()).toBe("/bin/bash")
|
|
|
+ })
|
|
|
+ })
|
|
|
+})
|