| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- 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("handles undefined profile gracefully", () => {
- // Mock a case where defaultProfileName exists but the profile doesn't
- mockVsCodeConfig("windows", "NonexistentProfile", {})
- 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")
- })
- })
- })
|