Skip to content

Commit 321aadf

Browse files
test(scripts): add error and edge case tests for Generate-PrReference (#279)
## Description Added comprehensive error path and edge case tests for [Generate-PrReference.ps1](../../scripts/dev-tools/Generate-PrReference.ps1) to improve test coverage. The tests verify proper error handling when git commands fail and validate edge case behavior for empty results and detached HEAD states. - Added error path tests for `Test-GitAvailability`, `Get-RepositoryRoot`, `Resolve-ComparisonReference`, `Get-ShortCommitHash`, `Get-CommitEntry`, `Get-CommitCount`, `Get-DiffOutput`, and `Get-DiffSummary` - Added edge case tests for empty results in `Get-CommitCount` and `Get-DiffSummary` - Added `Get-CurrentBranchOrRef` tests for detached HEAD state and unknown branch fallback scenarios - Added `Invoke-PrReferenceGeneration` test for `ExcludeMarkdownDiff` console output verification ## Related Issue(s) N/A ## Type of Change Select all that apply: **Code & Documentation:** - [ ] Bug fix (non-breaking change fixing an issue) - [ ] New feature (non-breaking change adding functionality) - [ ] Breaking change (fix or feature causing existing functionality to change) - [ ] Documentation update **Infrastructure & Configuration:** - [ ] GitHub Actions workflow - [ ] Linting configuration (markdown, PowerShell, etc.) - [ ] Security configuration - [ ] DevContainer configuration - [ ] Dependency update **AI Artifacts:** - [ ] Reviewed contribution with `prompt-builder` agent and addressed all feedback - [ ] Copilot instructions (`.github/instructions/*.instructions.md`) - [ ] Copilot prompt (`.github/prompts/*.prompt.md`) - [ ] Copilot agent (`.github/agents/*.agent.md`) > **Note for AI Artifact Contributors**: > > - **Agents**: Research, indexing/referencing other project (using standard VS Code GitHub Copilot/MCP tools), planning, and general implementation agents likely already exist. Review `.github/agents/` before creating new ones. > - **Model Versions**: Only contributions targeting the **latest Anthropic and OpenAI models** will be accepted. Older model versions (e.g., GPT-3.5, Claude 3) will be rejected. > - See [Agents Not Accepted](../docs/contributing/custom-agents.md#agents-not-accepted) and [Model Version Requirements](../docs/contributing/ai-artifacts-common.md#model-version-requirements). **Other:** - [x] Script/automation (`.ps1`, `.sh`, `.py`) - [ ] Other (please describe): ## Sample Prompts (for AI Artifact Contributions) N/A - This PR contains test code, not AI artifacts. ## Testing - All 351 Pester tests pass (`npm run test:ps`) - PSScriptAnalyzer validation passes (`npm run lint:ps`) ## Checklist ### Required Checks - [ ] Documentation is updated (if applicable) - [x] Files follow existing naming conventions - [x] Changes are backwards compatible (if applicable) - [x] Tests added for new functionality (if applicable) ### AI Artifact Contributions N/A - No AI artifacts in this PR. ### Required Automated Checks The following validation commands must pass before merging: - [x] Markdown linting: `npm run lint:md` - [x] Spell checking: `npm run spell-check` - [x] Frontmatter validation: `npm run lint:frontmatter` - [x] Link validation: `npm run lint:md-links` - [x] PowerShell analysis: `npm run lint:ps` ## Security Considerations - [x] This PR does not contain any sensitive or NDA information - [x] Any new dependencies have been reviewed for security issues - [x] Security-related scripts follow the principle of least privilege ## Additional Notes This PR improves test coverage for Generate-PrReference.ps1 by adding tests for error conditions and edge cases that were previously untested. 🧪 - Generated by Copilot
1 parent 1e45ad6 commit 321aadf

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed

scripts/tests/dev-tools/Generate-PrReference.Tests.ps1

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ Describe 'Test-GitAvailability' {
99
# This test assumes git is installed in the test environment
1010
{ Test-GitAvailability } | Should -Not -Throw
1111
}
12+
13+
It 'Should throw when git is not available' {
14+
Mock Get-Command { $null } -ParameterFilter { $Name -eq 'git' }
15+
{ Test-GitAvailability } | Should -Throw '*Git is required*'
16+
}
1217
}
1318

1419
Describe 'Get-RepositoryRoot' {
@@ -22,6 +27,11 @@ Describe 'Get-RepositoryRoot' {
2227
$result = Get-RepositoryRoot
2328
Test-Path -Path (Join-Path $result '.git') | Should -BeTrue
2429
}
30+
31+
It 'Should throw when repository root cannot be determined' {
32+
Mock git { $global:LASTEXITCODE = 0; return '' }
33+
{ Get-RepositoryRoot } | Should -Throw '*Unable to determine repository root*'
34+
}
2535
}
2636

2737
Describe 'New-PrDirectory' {
@@ -61,6 +71,11 @@ Describe 'Resolve-ComparisonReference' {
6171
$result = Resolve-ComparisonReference -BaseBranch 'main'
6272
$result.Ref | Should -Not -BeNullOrEmpty
6373
}
74+
75+
It 'Should throw when base branch does not exist' {
76+
Mock git { $global:LASTEXITCODE = 1; return $null }
77+
{ Resolve-ComparisonReference -BaseBranch 'nonexistent-branch-xyz' } | Should -Throw '*does not exist*'
78+
}
6479
}
6580

6681
Describe 'Get-ShortCommitHash' {
@@ -74,6 +89,11 @@ Describe 'Get-ShortCommitHash' {
7489
$second = Get-ShortCommitHash -Ref 'HEAD'
7590
$first | Should -Be $second
7691
}
92+
93+
It 'Should throw when ref resolution fails' {
94+
Mock git { $global:LASTEXITCODE = 128; return '' }
95+
{ Get-ShortCommitHash -Ref 'invalid-ref-xyz' } | Should -Throw "*Failed to resolve ref*"
96+
}
7797
}
7898

7999
Describe 'Get-CommitEntry' {
@@ -86,6 +106,11 @@ Describe 'Get-CommitEntry' {
86106
$result = Get-CommitEntry -ComparisonRef 'HEAD'
87107
$result | Should -BeNullOrEmpty
88108
}
109+
110+
It 'Should throw when commit history retrieval fails' {
111+
Mock git { $global:LASTEXITCODE = 128; return $null }
112+
{ Get-CommitEntry -ComparisonRef 'main' } | Should -Throw '*Failed to retrieve commit history*'
113+
}
89114
}
90115

91116
Describe 'Get-CommitCount' {
@@ -100,6 +125,17 @@ Describe 'Get-CommitCount' {
100125
$result = Get-CommitCount -ComparisonRef 'HEAD'
101126
$result | Should -Be 0
102127
}
128+
129+
It 'Should throw when commit count fails' {
130+
Mock git { $global:LASTEXITCODE = 128; return '' }
131+
{ Get-CommitCount -ComparisonRef 'main' } | Should -Throw '*Failed to count commits*'
132+
}
133+
134+
It 'Should return 0 when commit count text is empty' {
135+
Mock git { $global:LASTEXITCODE = 0; return '' }
136+
$result = Get-CommitCount -ComparisonRef 'main'
137+
$result | Should -Be 0
138+
}
103139
}
104140

105141
Describe 'Get-DiffOutput' {
@@ -113,13 +149,29 @@ Describe 'Get-DiffOutput' {
113149
# The result may be empty if only markdown files were changed
114150
{ Get-DiffOutput -ComparisonRef 'HEAD~1' -ExcludeMarkdownDiff } | Should -Not -Throw
115151
}
152+
153+
It 'Should throw when diff output fails' {
154+
Mock git { $global:LASTEXITCODE = 128; return $null }
155+
{ Get-DiffOutput -ComparisonRef 'main' } | Should -Throw '*Failed to retrieve diff output*'
156+
}
116157
}
117158

118159
Describe 'Get-DiffSummary' {
119160
It 'Returns shortstat summary string' {
120161
$result = Get-DiffSummary -ComparisonRef 'HEAD~1'
121162
$result | Should -BeOfType [string]
122163
}
164+
165+
It 'Should throw when diff summary fails' {
166+
Mock git { $global:LASTEXITCODE = 128; return $null }
167+
{ Get-DiffSummary -ComparisonRef 'main' } | Should -Throw '*Failed to summarize diff output*'
168+
}
169+
170+
It 'Should return "0 files changed" when diff summary is empty' {
171+
Mock git { $global:LASTEXITCODE = 0; return '' }
172+
$result = Get-DiffSummary -ComparisonRef 'main'
173+
$result | Should -Be '0 files changed'
174+
}
123175
}
124176

125177
Describe 'Get-PrXmlContent' {
@@ -191,6 +243,33 @@ Describe 'Get-CurrentBranchOrRef' {
191243
# Either a branch name or detached@<sha>
192244
($result -match '^detached@' -or $result -notmatch '^detached@') | Should -BeTrue
193245
}
246+
247+
It 'Should return detached@sha when in detached HEAD state' {
248+
# Use call sequence to distinguish git commands (cross-platform safe)
249+
$script:gitCallCount = 0
250+
Mock git {
251+
$script:gitCallCount++
252+
if ($script:gitCallCount -eq 1) {
253+
# First call: git branch --show-current returns empty (detached)
254+
$global:LASTEXITCODE = 0
255+
return ''
256+
}
257+
# Second call: git rev-parse --short HEAD returns SHA
258+
$global:LASTEXITCODE = 0
259+
return 'abc1234'
260+
}
261+
$result = Get-CurrentBranchOrRef
262+
$result | Should -Be 'detached@abc1234'
263+
}
264+
265+
It 'Should return unknown when both branch and rev-parse fail' {
266+
Mock git {
267+
$global:LASTEXITCODE = 128
268+
return $null
269+
}
270+
$result = Get-CurrentBranchOrRef
271+
$result | Should -Be 'unknown'
272+
}
194273
}
195274

196275
Describe 'Invoke-PrReferenceGeneration' {
@@ -221,4 +300,35 @@ Describe 'Invoke-PrReferenceGeneration' {
221300
$result | Should -BeOfType [System.IO.FileInfo]
222301
$result.Extension | Should -Be '.xml'
223302
}
303+
304+
It 'Should include markdown exclusion note when ExcludeMarkdownDiff is specified' {
305+
# Skip if not in a git repo or no commits
306+
$commitCount = Get-CommitCount -ComparisonRef 'HEAD~1'
307+
if ($commitCount -eq 0) {
308+
Set-ItResult -Skipped -Because 'No commits available for comparison'
309+
return
310+
}
311+
312+
$baseBranch = $null
313+
foreach ($candidate in @('origin/main', 'main', 'HEAD~1')) {
314+
& git rev-parse --verify $candidate 2>$null | Out-Null
315+
if ($LASTEXITCODE -eq 0) {
316+
$baseBranch = $candidate
317+
break
318+
}
319+
}
320+
321+
if (-not $baseBranch) {
322+
Set-ItResult -Skipped -Because 'No suitable base branch available for comparison'
323+
return
324+
}
325+
326+
Mock Write-Host {}
327+
328+
$result = Invoke-PrReferenceGeneration -BaseBranch $baseBranch -ExcludeMarkdownDiff
329+
$result | Should -BeOfType [System.IO.FileInfo]
330+
331+
# Verify the markdown exclusion note was output
332+
Should -Invoke Write-Host -ParameterFilter { $Object -eq 'Note: Markdown files were excluded from diff output' }
333+
}
224334
}

0 commit comments

Comments
 (0)