microsoft/hve-core

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
docs/621-ai-artifacts

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

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