fix(test): resolve 13 Windows-only Pester failures#139
Conversation
- secret-status: escape backslashes in Write-Manifest JSON here-string (Windows paths with backslashes produced invalid JSON → exit 2) - 01-path: use ';' sentinel instead of '' to disable registry sync; Windows deletes env vars set to empty string, causing Get-RegistryUserPath to fall through to the real registry - 30-mise: skip ghq mock tests when ghq is not installed on runner - set-openssh-default-shell, sync-openssh-authorized-keys: skip the non-elevated assertion when the session is running as Administrator (guards with $IsWindows to avoid WindowsIdentity on non-Windows) Closes #110 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> fix(test): resolve 13 Windows-only Pester failures - secret-status: escape backslashes in Write-Manifest JSON here-string (Windows paths with backslashes produced invalid JSON → exit 2) - 01-path: use ';' sentinel instead of '' to disable registry sync; Windows deletes env vars set to empty string, causing Get-RegistryUserPath to fall through to the real registry - 30-mise: skip ghq mock tests when ghq is not installed on runner - set-openssh-default-shell, sync-openssh-authorized-keys: skip the non-elevated assertion when the session is running as Administrator (guards with $IsWindows to avoid WindowsIdentity on non-Windows) Closes #110 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughPowerShell Pester tests updated: registry PATH sentinel set to ';', HomeDir/backslashes escaped for JSON, conditional ChangesWindows-only Pester test environment fixes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
HKLM (HKEY_LOCAL_MACHINE) appears in the OpenSSH default-shell and authorized-keys Pester tests; add it to the project dictionary so the linter does not flag it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> chore(cspell): add HKLM to project word list HKLM (HKEY_LOCAL_MACHINE) appears in the OpenSSH default-shell and authorized-keys Pester tests; add it to the project dictionary so the linter does not flag it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 01f504a38b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| It 'appends ghq-cloned owner paths from chezmoi-ghq-trusted-paths' { | ||
| It 'appends ghq-cloned owner paths from chezmoi-ghq-trusted-paths' -Skip:($null -eq (Get-Command 'ghq' -ErrorAction SilentlyContinue)) { |
There was a problem hiding this comment.
Do not skip mocked ghq tests based on host tools
On Windows CI or developer machines that do not have a real ghq executable installed, this -Skip condition prevents the test from running even though the test body immediately mocks both Get-Command ghq and the ghq root call. That means the ghq-trust path behavior is no longer covered in the common environment where ghq is absent; the same host-tool guard was also added to the blank-line case below, so regressions in this mocked flow can pass undetected.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Rejecting: Pester 5 cannot mock a non-existent external command — it must be discoverable via Get-Command before the mock can wrap it. When ghq is absent, Mock ghq { ... } throws CommandNotFoundException during test setup rather than deferring to the mock body. The -Skip guard is therefore the correct fix; the alternative (mocking Get-Command 'ghq' to return a fake object, then also providing a stand-in function named ghq) would be a more invasive rewrite of the test structure than warranted. The test already has a companion case ('skips ghq trusted paths when ghq is not installed') that exercises the no-ghq code path without mocking the binary.
|
|
||
| function script:Write-Manifest { | ||
| param([string]$CategoriesJson) | ||
| $escapedHomeDir = $script:HomeDir.Replace('\', '\\') |
There was a problem hiding this comment.
Escape every Windows path in generated manifest JSON
Escaping only homeDir still leaves Windows runs broken for test cases that embed other paths inside CategoriesJson: for example the unskipped “secret file missing is MISSING” case writes "absPath":"$f", where $f contains backslashes on Windows, so the manifest remains invalid JSON and secret-status.ps1 exits 2 before the test can assert MISSING. Build the manifest data with ConvertTo-Json or ensure all interpolated JSON strings in the categories are escaped, not just this top-level field.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in commit 9b17e70 — the 'secret file missing is MISSING' test embeds $f (a Windows path) directly into the categories JSON here-string. Added $fJson = $f.Replace('\\', '\\\\') and used $fJson in the interpolation. All other tests that embed Windows paths in JSON are already skipped on Windows (-Skip:($IsWindows -eq $true)).
| It 'Test-DotfilesAdminElevation returns false for non-elevated session' -Skip:( | ||
| $IsWindows -and | ||
| ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( |
There was a problem hiding this comment.
Use a PS5-safe elevated skip guard
On Windows PowerShell 5.1, $IsWindows is undefined and therefore $null, so this -and short-circuits to false and the elevated-session skip never applies; an elevated PS5 Invoke-Pester still runs the assertion and fails. The same guard was added to sync-openssh-authorized-keys.Tests.ps1, so use a PS5-safe Windows check for both elevated skips.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in commit 408397f — replaced $IsWindows -and ... with [System.Environment]::OSVersion.Platform -eq [System.PlatformID]::Win32NT -and .... This check is available in both PS5 and PS7, correctly returns false on non-Windows (short-circuiting the WindowsIdentity call), and is not affected by the undefined $IsWindows in Windows PowerShell 5.1.
The 'secret file missing is MISSING' test embeds a Windows path via $f directly into a JSON heredoc. Backslashes in the path produce invalid JSON on Windows. Escape before interpolation using the same .Replace pattern applied to Write-Manifest. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> fix(test): escape inline JSON path in secret-status missing test The 'secret file missing is MISSING' test embeds a Windows path via $f directly into a JSON heredoc. Backslashes in the path produce invalid JSON on Windows. Escape before interpolation using the same .Replace pattern applied to Write-Manifest. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR targets Windows-only Pester CI failures (issue #110) so the PowerShell tests (Pester) workflow can be promoted to a required check by removing environment-specific breakages on windows-latest.
Changes:
- Add Windows-admin-session skip guards for the
Test-DotfilesAdminElevation returns false...assertions in the OpenSSH-related test suites. - Make
01-pathtests reliably disable registry PATH syncing on Windows by using a non-empty sentinel value forDOTFILES_TEST_REGISTRY_USER_PATH. - Skip
30-miseghq-related tests whenghqis not available (to avoid Pester mock limitations).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/powershell/sync-openssh-authorized-keys.Tests.ps1 | Skips the “non-elevated session” assertion when running under an elevated Windows runner. |
| tests/powershell/set-openssh-default-shell.Tests.ps1 | Skips the “non-elevated session” assertion when running under an elevated Windows runner. |
| tests/powershell/secret-status.Tests.ps1 | Attempts to fix Windows JSON parsing failures by escaping backslashes in the manifest homeDir value. |
| tests/powershell/30-mise.Tests.ps1 | Skips ghq-dependent tests when ghq is missing (Windows runner environment). |
| tests/powershell/01-path.Tests.ps1 | Uses ; as a non-empty sentinel to prevent Windows from deleting the test override env var. |
| function script:Write-Manifest { | ||
| param([string]$CategoriesJson) | ||
| $escapedHomeDir = $script:HomeDir.Replace('\', '\\') | ||
| $body = @" | ||
| { | ||
| "version": 1, | ||
| "manager": "bitwarden", | ||
| "os": "linux", | ||
| "homeDir": "$script:HomeDir", | ||
| "homeDir": "$escapedHomeDir", | ||
| "ghqRoot": "", | ||
| "categories": $CategoriesJson |
There was a problem hiding this comment.
Fixed in commit 9b17e70 — the 'secret file missing is MISSING' test was the only non-Windows-skipped case that embedded a Windows path in the categories JSON. Added $fJson = $f.Replace('\\', '\\\\') there. All other tests that contain Windows paths in JSON categories are guarded with -Skip:($IsWindows -eq $true).
$IsWindows is undefined (null) in Windows PowerShell 5.1, so '$IsWindows -and ...' short-circuits to false on PS5, leaving elevated PS5 runners unguarded. Replace with OSVersion.Platform -eq Win32NT which is available in both PS5 and PS7 and short-circuits safely on non-Windows. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> fix(test): use OSVersion.Platform for PS5-safe elevation skip guard $IsWindows is undefined (null) in Windows PowerShell 5.1, so '$IsWindows -and ...' short-circuits to false on PS5, leaving elevated PS5 runners unguarded. Replace with OSVersion.Platform -eq Win32NT which is available in both PS5 and PS7 and short-circuits safely on non-Windows. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
E6 snapshot — all review threads acted on, CI green on head SHA 408397f. Dispositions:
claude-code-44806616: IDD automation marker. Do not edit. |
Summary
Fixes all 13 Windows-only Pester CI failures blocking promotion of
PowerShell tests (Pester)to a required check (issue #110).secret-status.Tests.ps1(8 failures): escape backslashes inWrite-Manifestbefore embedding the home-dir path into a JSONhere-string — Windows paths with backslashes produced invalid JSON,
causing the script under test to exit 2 on every invocation.
01-path.Tests.ps1(1 failure): change the registry-syncdisable sentinel from
''to';'; Windows silently deletesenvironment variables set to empty string, so
Get-RegistryUserPathfell through to the real registry andappended live user PATH entries to the reconciled result.
30-mise.Tests.ps1(2 failures): add-Skip:($null -eq (Get-Command 'ghq' ...))to the twoItblocksthat use
Mock ghq; Pester cannot mock a non-existent command, andghqis not installed on thewindows-latestrunner.set-openssh-default-shell.Tests.ps1andsync-openssh-authorized-keys.Tests.ps1(1 failure each):add a skip guard on the non-elevated assertion;
windows-latestruns as Administrator, so
Test-DotfilesAdminElevationreturns$trueand theShould -BeFalseassertion fails. The skipcondition uses
$IsWindows -and ...to avoid callingWindowsIdentity::GetCurrent()at discovery time on non-Windowshosts.
Test plan
PowerShell tests (Pester)passes onwindows-latestwith0 failures (13 environment-specific skips expected alongside the
existing 20 platform skips)
Bash tests (bats),Lua syntax check, andLinting workflowremain greenCloses #110
🤖 Generated with Claude Code
Summary by CodeRabbit
Tests
Chores