tests/direnv.Tests.ps1
|
BeforeAll { . "$PSScriptRoot/TestSupport.ps1" foreach ($f in Get-DFTestModuleFile) { . $f } $script:CompanionPath = Join-Path $PSScriptRoot '../Tools/direnv.ps1' $script:OriginalLocationChangedAction = $ExecutionContext.SessionState.InvokeCommand.LocationChangedAction } Describe 'direnv tool JSON' { It 'is natively XDG-compliant -- no xdg.vars needed' { $j = Get-Content (Join-Path $PSScriptRoot '../Tools/direnv.json') -Raw | ConvertFrom-Json $j.xdg.method | Should -Be 'default' } } # Scoped narrowly to the hook caching, mirroring zoxide.Tests.ps1/carapace.Tests.ps1. Describe 'direnv tool sidecar caching' -Skip:(-not (Get-Command direnv.exe -ErrorAction Ignore)) { BeforeEach { Set-DFTestXdg Remove-Item $Env:XDG_CACHE_HOME -Recurse -Force -ErrorAction Ignore } AfterEach { # Uninstall the real hook the test installed; see the last Describe. $ExecutionContext.SessionState.InvokeCommand.LocationChangedAction = $script:OriginalLocationChangedAction Restore-DFTestXdg } It 'caches the real hook script, and does not regenerate it on a second load' { # Genuinely calls the real direnv binary -- see carapace.Tests.ps1 for why # a function stand-in would defeat this test (no fingerprintable .Source). . $script:CompanionPath; . Initialize-DFRoleProjectEnv -Role project-env $cacheFile = Join-Path $Env:XDG_CACHE_HOME 'dotforge' 'direnv-hook.txt' Test-Path $cacheFile | Should -BeTrue $writtenAfterFirst = (Get-Item $cacheFile).LastWriteTimeUtc Start-Sleep -Milliseconds 50 . $script:CompanionPath; . Initialize-DFRoleProjectEnv -Role project-env (Get-Item $cacheFile).LastWriteTimeUtc | Should -Be $writtenAfterFirst } } Describe 'direnv companion helpers' { BeforeAll { . $script:CompanionPath } It 'finds Git bash from <Layout>' -ForEach @( @{ Layout = 'mingw64\bin\git.exe'; Git = 'Git\mingw64\bin\git.exe' } @{ Layout = 'cmd\git.exe'; Git = 'Git\cmd\git.exe' } ) { $root = Join-Path $TestDrive "g-$([guid]::NewGuid())" New-Item -ItemType Directory -Force (Join-Path $root 'Git\bin'), (Split-Path (Join-Path $root $Git)) | Out-Null New-Item -ItemType File (Join-Path $root 'Git\bin\bash.exe'), (Join-Path $root $Git) | Out-Null Find-DFGitBash -GitPath (Join-Path $root $Git) | Should -Be (Join-Path $root 'Git\bin\bash.exe') } It 'follows a scoop shim to the real git before walking up' { $root = Join-Path $TestDrive "s-$([guid]::NewGuid())" $real = Join-Path $root 'apps\git\current\cmd\git.exe' $bash = Join-Path $root 'apps\git\current\bin\bash.exe' $shim = Join-Path $root 'shims\git.exe' foreach ($f in $real, $bash, $shim) { New-Item -ItemType Directory -Force (Split-Path $f) | Out-Null; New-Item -ItemType File $f | Out-Null } "path = `"$real`"" | Set-Content (Join-Path $root 'shims\git.shim') Find-DFGitBash -GitPath $shim | Should -Be $bash } It 'never returns a bash under WINDIR' { $savedWindir = $Env:WINDIR try { $win = Join-Path $TestDrive "win-$([guid]::NewGuid())" $Env:WINDIR = $win $git = Join-Path $win 'tools\git.exe' foreach ($f in $git, (Join-Path $win 'bin\bash.exe')) { New-Item -ItemType Directory -Force (Split-Path $f) | Out-Null; New-Item -ItemType File $f | Out-Null } Find-DFGitBash -GitPath $git | Should -BeNullOrEmpty } finally { $Env:WINDIR = $savedWindir } } It 'returns nothing when no bin\bash.exe sits above git' { $git = Join-Path $TestDrive 'nobash\git.exe' New-Item -ItemType Directory -Force (Split-Path $git) | Out-Null New-Item -ItemType File $git | Out-Null Find-DFGitBash -GitPath $git | Should -BeNullOrEmpty } It 'flags <Text> as buggy: <Buggy>' -ForEach @( @{ Text = "2.37.1`n"; Buggy = $true } @{ Text = '2.36.0'; Buggy = $true } @{ Text = '2.38.0'; Buggy = $false } @{ Text = 'garbage'; Buggy = $false } ) { Test-DFDirenvBuggyVersion -VersionText $Text | Should -Be $Buggy } } Describe 'direnv project-env hook' { BeforeEach { $script:SavedBash = $Env:DIRENV_BASH $script:SavedLca = $ExecutionContext.SessionState.InvokeCommand.LocationChangedAction . $script:CompanionPath Mock Get-DFCachedCommandOutput { '$null' } -ParameterFilter { $Name -eq 'direnv-hook' } Mock Get-DFCachedCommandOutput { $script:VersionText } -ParameterFilter { $Name -eq 'direnv-version' } $script:VersionText = '2.37.1' } AfterEach { if ($null -eq $script:SavedBash) { Remove-Item Env:DIRENV_BASH -ErrorAction Ignore } else { $Env:DIRENV_BASH = $script:SavedBash } $ExecutionContext.SessionState.InvokeCommand.LocationChangedAction = $script:SavedLca } It 'leaves a DIRENV_BASH the user set alone' { $Env:DIRENV_BASH = 'C:\mine\bash.exe' . Initialize-DFRoleProjectEnv -Role project-env 3>$null $Env:DIRENV_BASH | Should -Be 'C:\mine\bash.exe' } It 'sets DIRENV_BASH from Git bash when unset' { Remove-Item Env:DIRENV_BASH -ErrorAction Ignore Mock Find-DFGitBash { 'C:\Git\bin\bash.exe' } . Initialize-DFRoleProjectEnv -Role project-env 3>$null $Env:DIRENV_BASH | Should -Be 'C:\Git\bin\bash.exe' } It 'warns when no Git bash is found' { Remove-Item Env:DIRENV_BASH -ErrorAction Ignore Mock Find-DFGitBash { } $w = . Initialize-DFRoleProjectEnv -Role project-env 3>&1 "$w" | Should -Match "needs Git for Windows' bash" } It 'warns about the Windows bug for 2.37.1, and not for 2.38.0' { $Env:DIRENV_BASH = 'C:\x\bash.exe' $w1 = . Initialize-DFRoleProjectEnv -Role project-env 3>&1 "$w1" | Should -Match 'direnv#1488' $script:VersionText = '2.38.0' $w2 = . Initialize-DFRoleProjectEnv -Role project-env 3>&1 "$w2" | Should -Not -Match 'direnv#1488' } } # Runs after the caching test. direnv's real hook attaches to the process-wide # LocationChangedAction; left installed, every later Set-Location in the run calls # direnv, which on Windows can unload variables such as PATH. Describe 'direnv tests clean up after themselves' { It 'leaves LocationChangedAction as it found it' { $ExecutionContext.SessionState.InvokeCommand.LocationChangedAction | Should -Be $script:OriginalLocationChangedAction } } |