microsoft/hve-core

Public

mirrored fromhttps://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
hve-core-v2.1.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

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

336lines · modecode

1#Requires -Modules Pester
2# Copyright (c) Microsoft Corporation.
3# SPDX-License-Identifier: MIT
4
5BeforeAll {
6 . $PSScriptRoot/../../dev-tools/Generate-PrReference.ps1
7}
8
9Describe 'Test-GitAvailability' {
10 It 'Does not throw when git is available' {
11 # This test assumes git is installed in the test environment
12 { Test-GitAvailability } | Should -Not -Throw
13 }
14
15 It 'Should throw when git is not available' {
16 Mock Get-Command { $null } -ParameterFilter { $Name -eq 'git' }
17 { Test-GitAvailability } | Should -Throw '*Git is required*'
18 }
19}
20
21Describe 'Get-RepositoryRoot' {
22 It 'Returns a valid directory path' {
23 $result = Get-RepositoryRoot
24 $result | Should -Not -BeNullOrEmpty
25 Test-Path -Path $result -PathType Container | Should -BeTrue
26 }
27
28 It 'Returns path containing .git directory' {
29 $result = Get-RepositoryRoot
30 Test-Path -Path (Join-Path $result '.git') | Should -BeTrue
31 }
32
33 It 'Should throw when repository root cannot be determined' {
34 Mock git { $global:LASTEXITCODE = 0; return '' }
35 { Get-RepositoryRoot } | Should -Throw '*Unable to determine repository root*'
36 }
37}
38
39Describe 'New-PrDirectory' {
40 BeforeAll {
41 $script:tempRepo = Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString())
42 New-Item -ItemType Directory -Path $script:tempRepo -Force | Out-Null
43 }
44
45 AfterAll {
46 Remove-Item -Path $script:tempRepo -Recurse -Force -ErrorAction SilentlyContinue
47 }
48
49 It 'Creates .copilot-tracking/pr directory' {
50 $result = New-PrDirectory -RepoRoot $script:tempRepo
51 $result | Should -Not -BeNullOrEmpty
52 Test-Path -Path $result -PathType Container | Should -BeTrue
53 $result | Should -Match '\.copilot-tracking[\\/]pr$'
54 }
55
56 It 'Returns existing directory without error' {
57 $firstCall = New-PrDirectory -RepoRoot $script:tempRepo
58 $secondCall = New-PrDirectory -RepoRoot $script:tempRepo
59 $secondCall | Should -Be $firstCall
60 }
61}
62
63Describe 'Resolve-ComparisonReference' {
64 It 'Returns PSCustomObject with Ref and Label properties' {
65 $result = Resolve-ComparisonReference -BaseBranch 'main'
66 $result | Should -BeOfType [PSCustomObject]
67 $result.PSObject.Properties.Name | Should -Contain 'Ref'
68 $result.PSObject.Properties.Name | Should -Contain 'Label'
69 }
70
71 It 'Uses merge-base when remote branch exists' {
72 # This test assumes main branch exists
73 $result = Resolve-ComparisonReference -BaseBranch 'main'
74 $result.Ref | Should -Not -BeNullOrEmpty
75 }
76
77 It 'Should throw when base branch does not exist' {
78 Mock git { $global:LASTEXITCODE = 1; return $null }
79 { Resolve-ComparisonReference -BaseBranch 'nonexistent-branch-xyz' } | Should -Throw '*does not exist*'
80 }
81}
82
83Describe 'Get-ShortCommitHash' {
84 It 'Returns 7-character hash for HEAD' {
85 $result = Get-ShortCommitHash -Ref 'HEAD'
86 $result | Should -Match '^[a-f0-9]{7,}$'
87 }
88
89 It 'Returns consistent result for same ref' {
90 $first = Get-ShortCommitHash -Ref 'HEAD'
91 $second = Get-ShortCommitHash -Ref 'HEAD'
92 $first | Should -Be $second
93 }
94
95 It 'Should throw when ref resolution fails' {
96 Mock git { $global:LASTEXITCODE = 128; return '' }
97 { Get-ShortCommitHash -Ref 'invalid-ref-xyz' } | Should -Throw "*Failed to resolve ref*"
98 }
99}
100
101Describe 'Get-CommitEntry' {
102 It 'Returns array of formatted commit entries' {
103 $result = Get-CommitEntry -ComparisonRef 'HEAD~1'
104 $result | Should -BeOfType [string]
105 }
106
107 It 'Returns empty array when no commits in range' {
108 $result = Get-CommitEntry -ComparisonRef 'HEAD'
109 $result | Should -BeNullOrEmpty
110 }
111
112 It 'Should throw when commit history retrieval fails' {
113 Mock git { $global:LASTEXITCODE = 128; return $null }
114 { Get-CommitEntry -ComparisonRef 'main' } | Should -Throw '*Failed to retrieve commit history*'
115 }
116}
117
118Describe 'Get-CommitCount' {
119 It 'Returns integer count' {
120 $result = Get-CommitCount -ComparisonRef 'HEAD~5'
121 $result | Should -BeOfType [int]
122 # Merge commits can inflate the count, so just verify it returns a positive integer
123 $result | Should -BeGreaterOrEqual 1
124 }
125
126 It 'Returns 0 when no commits in range' {
127 $result = Get-CommitCount -ComparisonRef 'HEAD'
128 $result | Should -Be 0
129 }
130
131 It 'Should throw when commit count fails' {
132 Mock git { $global:LASTEXITCODE = 128; return '' }
133 { Get-CommitCount -ComparisonRef 'main' } | Should -Throw '*Failed to count commits*'
134 }
135
136 It 'Should return 0 when commit count text is empty' {
137 Mock git { $global:LASTEXITCODE = 0; return '' }
138 $result = Get-CommitCount -ComparisonRef 'main'
139 $result | Should -Be 0
140 }
141}
142
143Describe 'Get-DiffOutput' {
144 It 'Returns array of diff lines' {
145 $result = Get-DiffOutput -ComparisonRef 'HEAD~1'
146 $result | Should -Not -BeNullOrEmpty
147 }
148
149 It 'Excludes markdown when specified' {
150 # Verify the function executes without error when excluding markdown
151 # The result may be empty if only markdown files were changed
152 { Get-DiffOutput -ComparisonRef 'HEAD~1' -ExcludeMarkdownDiff } | Should -Not -Throw
153 }
154
155 It 'Should throw when diff output fails' {
156 Mock git { $global:LASTEXITCODE = 128; return $null }
157 { Get-DiffOutput -ComparisonRef 'main' } | Should -Throw '*Failed to retrieve diff output*'
158 }
159}
160
161Describe 'Get-DiffSummary' {
162 It 'Returns shortstat summary string' {
163 $result = Get-DiffSummary -ComparisonRef 'HEAD~1'
164 $result | Should -BeOfType [string]
165 }
166
167 It 'Should throw when diff summary fails' {
168 Mock git { $global:LASTEXITCODE = 128; return $null }
169 { Get-DiffSummary -ComparisonRef 'main' } | Should -Throw '*Failed to summarize diff output*'
170 }
171
172 It 'Should return "0 files changed" when diff summary is empty' {
173 Mock git { $global:LASTEXITCODE = 0; return '' }
174 $result = Get-DiffSummary -ComparisonRef 'main'
175 $result | Should -Be '0 files changed'
176 }
177}
178
179Describe 'Get-PrXmlContent' {
180 It 'Returns valid XML string' {
181 $result = Get-PrXmlContent -CurrentBranch 'feature/test' -BaseBranch 'main' -CommitEntries @('commit 1', 'commit 2') -DiffOutput @('diff line 1', 'diff line 2')
182 $result | Should -Not -BeNullOrEmpty
183 $result | Should -Match '<commit_history>'
184 $result | Should -Match '</commit_history>'
185 }
186
187 It 'Includes branch information' {
188 $result = Get-PrXmlContent -CurrentBranch 'feature/my-branch' -BaseBranch 'main' -CommitEntries @() -DiffOutput @()
189 $result | Should -Match 'feature/my-branch'
190 $result | Should -Match 'main'
191 }
192
193 It 'Includes commit entries' {
194 $result = Get-PrXmlContent -CurrentBranch 'feature/test' -BaseBranch 'main' -CommitEntries @('abc123 Test commit') -DiffOutput @()
195 $result | Should -Match 'abc123 Test commit'
196 }
197
198 It 'Handles empty inputs' {
199 $result = Get-PrXmlContent -CurrentBranch 'branch' -BaseBranch 'main' -CommitEntries @() -DiffOutput @()
200 $result | Should -Not -BeNullOrEmpty
201 }
202}
203
204Describe 'Get-LineImpact' {
205 It 'Parses insertions and deletions from shortstat' {
206 $result = Get-LineImpact -DiffSummary '5 files changed, 100 insertions(+), 50 deletions(-)'
207 $result | Should -Be 150
208 }
209
210 It 'Handles insertions only' {
211 $result = Get-LineImpact -DiffSummary '2 files changed, 25 insertions(+)'
212 $result | Should -Be 25
213 }
214
215 It 'Handles deletions only' {
216 $result = Get-LineImpact -DiffSummary '1 file changed, 10 deletions(-)'
217 $result | Should -Be 10
218 }
219
220 It 'Returns 0 for summary without insertions or deletions' {
221 $result = Get-LineImpact -DiffSummary 'no changes'
222 $result | Should -Be 0
223 }
224
225 It 'Returns 0 for no changes' {
226 $result = Get-LineImpact -DiffSummary '0 files changed'
227 $result | Should -Be 0
228 }
229}
230
231Describe 'Get-CurrentBranchOrRef' {
232 BeforeAll {
233 . $PSScriptRoot/../../dev-tools/Generate-PrReference.ps1
234 }
235
236 It 'Returns branch name when on a branch' {
237 # This test runs in a real git repo, so it should return something
238 $result = Get-CurrentBranchOrRef
239 $result | Should -Not -BeNullOrEmpty
240 $result | Should -BeOfType [string]
241 }
242
243 It 'Returns string starting with detached@ or branch name' {
244 $result = Get-CurrentBranchOrRef
245 # Either a branch name or detached@<sha>
246 ($result -match '^detached@' -or $result -notmatch '^detached@') | Should -BeTrue
247 }
248
249 It 'Should return detached@sha when in detached HEAD state' {
250 # Use call sequence to distinguish git commands (cross-platform safe)
251 $script:gitCallCount = 0
252 Mock git {
253 $script:gitCallCount++
254 if ($script:gitCallCount -eq 1) {
255 # First call: git branch --show-current returns empty (detached)
256 $global:LASTEXITCODE = 0
257 return ''
258 }
259 # Second call: git rev-parse --short HEAD returns SHA
260 $global:LASTEXITCODE = 0
261 return 'abc1234'
262 }
263 $result = Get-CurrentBranchOrRef
264 $result | Should -Be 'detached@abc1234'
265 }
266
267 It 'Should return unknown when both branch and rev-parse fail' {
268 Mock git {
269 $global:LASTEXITCODE = 128
270 return $null
271 }
272 $result = Get-CurrentBranchOrRef
273 $result | Should -Be 'unknown'
274 }
275}
276
277Describe 'Invoke-PrReferenceGeneration' {
278 It 'Returns FileInfo object' {
279 # Skip if not in a git repo or no commits to compare
280 $commitCount = Get-CommitCount -ComparisonRef 'HEAD~1'
281 if ($commitCount -eq 0) {
282 Set-ItResult -Skipped -Because 'No commits available for comparison'
283 return
284 }
285
286 # Determine available base branch - prefer origin/main, fall back to main, then HEAD~1
287 $baseBranch = $null
288 foreach ($candidate in @('origin/main', 'main', 'HEAD~1')) {
289 & git rev-parse --verify $candidate 2>$null | Out-Null
290 if ($LASTEXITCODE -eq 0) {
291 $baseBranch = $candidate
292 break
293 }
294 }
295
296 if (-not $baseBranch) {
297 Set-ItResult -Skipped -Because 'No suitable base branch available for comparison'
298 return
299 }
300
301 $result = Invoke-PrReferenceGeneration -BaseBranch $baseBranch
302 $result | Should -BeOfType [System.IO.FileInfo]
303 $result.Extension | Should -Be '.xml'
304 }
305
306 It 'Should include markdown exclusion note when ExcludeMarkdownDiff is specified' {
307 # Skip if not in a git repo or no commits
308 $commitCount = Get-CommitCount -ComparisonRef 'HEAD~1'
309 if ($commitCount -eq 0) {
310 Set-ItResult -Skipped -Because 'No commits available for comparison'
311 return
312 }
313
314 $baseBranch = $null
315 foreach ($candidate in @('origin/main', 'main', 'HEAD~1')) {
316 & git rev-parse --verify $candidate 2>$null | Out-Null
317 if ($LASTEXITCODE -eq 0) {
318 $baseBranch = $candidate
319 break
320 }
321 }
322
323 if (-not $baseBranch) {
324 Set-ItResult -Skipped -Because 'No suitable base branch available for comparison'
325 return
326 }
327
328 Mock Write-Host {}
329
330 $result = Invoke-PrReferenceGeneration -BaseBranch $baseBranch -ExcludeMarkdownDiff
331 $result | Should -BeOfType [System.IO.FileInfo]
332
333 # Verify the markdown exclusion note was output
334 Should -Invoke Write-Host -ParameterFilter { $Object -eq 'Note: Markdown files were excluded from diff output' }
335 }
336}
337