microsoft/hve-core

Public

mirrored from https://github.com/microsoft/hve-coreAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
c53de22371068ecf93097f06d59d95290c201df2

Branches

Tags

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

Clone

HTTPS

Download ZIP

scripts/tests/linting/Invoke-LinkLanguageCheck.Tests.ps1

386lines · modecode

1#Requires -Modules Pester
2# Copyright (c) Microsoft Corporation.
3# SPDX-License-Identifier: MIT
4<#
5.SYNOPSIS
6 Pester tests for Invoke-LinkLanguageCheck.ps1 script
7.DESCRIPTION
8 Tests for Link Language Check wrapper script:
9 - Link-Lang-Check.ps1 invocation
10 - JSON parsing
11 - GitHub Actions integration
12 - Exit code handling
13#>
14
15BeforeAll {
16 $script:ScriptPath = Join-Path $PSScriptRoot '../../linting/Invoke-LinkLanguageCheck.ps1'
17 $script:ModulePath = Join-Path $PSScriptRoot '../../linting/Modules/LintingHelpers.psm1'
18 $script:CIHelpersPath = Join-Path $PSScriptRoot '../../lib/Modules/CIHelpers.psm1'
19
20 # Import modules for mocking
21 Import-Module $script:ModulePath -Force
22 Import-Module $script:CIHelpersPath -Force
23
24 $script:OriginalSkipMain = $env:HVE_SKIP_MAIN
25 $env:HVE_SKIP_MAIN = '1'
26 . $script:ScriptPath
27}
28
29AfterAll {
30 Remove-Module LintingHelpers -Force -ErrorAction SilentlyContinue
31 Remove-Module CIHelpers -Force -ErrorAction SilentlyContinue
32 $env:HVE_SKIP_MAIN = $script:OriginalSkipMain
33}
34
35#region Link-Lang-Check Invocation Tests
36
37Describe 'Link-Lang-Check.ps1 Invocation' -Tag 'Unit' {
38 Context 'Script discovery' {
39 It 'Link-Lang-Check.ps1 exists' {
40 $linkLangCheckPath = Join-Path $PSScriptRoot '../../linting/Link-Lang-Check.ps1'
41 Test-Path $linkLangCheckPath | Should -BeTrue
42 }
43 }
44
45 Context 'Normal execution' {
46 It 'Invoke-LinkLanguageCheck.ps1 exists' {
47 $scriptExists = Test-Path $script:ScriptPath
48 $scriptExists | Should -BeTrue
49 }
50 }
51}
52
53#endregion
54
55#region Invoke-LinkLanguageCheckCore Tests
56
57Describe 'Invoke-LinkLanguageCheckCore' -Tag 'Unit' {
58 Context 'Not in git repository' {
59 BeforeEach {
60 Mock git {
61 $global:LASTEXITCODE = 128
62 return 'fatal: not a git repository'
63 } -ParameterFilter { $args -contains 'rev-parse' }
64
65 Mock Write-Error { }
66 }
67
68 It 'Returns failure exit code' {
69 Invoke-LinkLanguageCheckCore -ExcludePaths @() | Should -Be 1
70 }
71 }
72
73 Context 'Issues found in link scan' {
74 BeforeEach {
75 $script:RepoRoot = $TestDrive
76 $script:MockLinkLang = Join-Path $TestDrive 'mock-link-lang.ps1'
77
78 @'
79param([string[]]$ExcludePaths = @())
80$json = @"
81[
82 {"file":"docs/a.md","line_number":1,"original_url":"https://docs.microsoft.com/en-us/a"},
83 {"file":"docs/b.md","line_number":2,"original_url":"https://docs.microsoft.com/en-us/b"}
84]
85"@
86
87Write-Output $json
88'@ | Set-Content -Path $script:MockLinkLang -Encoding utf8
89
90 Mock git {
91 $global:LASTEXITCODE = 0
92 return $script:RepoRoot
93 } -ParameterFilter { $args -contains 'rev-parse' }
94
95 Mock Join-Path {
96 return $script:MockLinkLang
97 } -ParameterFilter { $ChildPath -eq 'Link-Lang-Check.ps1' }
98
99 Mock Write-CIAnnotation { }
100 Mock Set-CIOutput { }
101 Mock Set-CIEnv { }
102 Mock Write-CIStepSummary { }
103 Mock Write-Host { }
104 }
105
106 It 'Returns failure exit code and records outputs' {
107 Invoke-LinkLanguageCheckCore -ExcludePaths @('scripts/tests/**') | Should -Be 1
108 Should -Invoke Set-CIOutput -Times 1
109 Should -Invoke Set-CIEnv -Times 1
110 Should -Invoke Write-CIAnnotation -Times 2
111 }
112 }
113
114 Context 'No issues found' {
115 BeforeEach {
116 $script:RepoRoot = $TestDrive
117 $script:MockLinkLang = Join-Path $TestDrive 'mock-link-lang-empty.ps1'
118
119 @'
120param([string[]]$ExcludePaths = @())
121$json = @"
122[]
123"@
124
125Write-Output $json
126'@ | Set-Content -Path $script:MockLinkLang -Encoding utf8
127
128 Mock git {
129 $global:LASTEXITCODE = 0
130 return $script:RepoRoot
131 } -ParameterFilter { $args -contains 'rev-parse' }
132
133 Mock Join-Path {
134 return $script:MockLinkLang
135 } -ParameterFilter { $ChildPath -eq 'Link-Lang-Check.ps1' }
136
137 Mock Set-CIOutput { }
138 Mock Write-CIStepSummary { }
139 Mock Write-Host { }
140 }
141
142 It 'Returns success exit code and records outputs' {
143 Invoke-LinkLanguageCheckCore -ExcludePaths @() | Should -Be 0
144 Should -Invoke Set-CIOutput -Times 1
145 Should -Invoke Write-CIStepSummary -Times 1
146 }
147 }
148}
149
150#endregion
151
152#region JSON Parsing Tests
153
154Describe 'JSON Output Parsing' -Tag 'Unit' {
155 Context 'Valid JSON with issues' {
156 BeforeEach {
157 $script:JsonWithIssues = @'
158[
159 {
160 "file": "docs/guide.md",
161 "line_number": 15,
162 "original_url": "https://docs.microsoft.com/en-us/azure"
163 },
164 {
165 "file": "README.md",
166 "line_number": 42,
167 "original_url": "https://learn.microsoft.com/en-us/dotnet"
168 }
169]
170'@
171 }
172
173 It 'Parses JSON array correctly' {
174 $result = $script:JsonWithIssues | ConvertFrom-Json
175 $result | Should -HaveCount 2
176 }
177
178 It 'Extracts file property' {
179 $result = $script:JsonWithIssues | ConvertFrom-Json
180 $result[0].file | Should -Be 'docs/guide.md'
181 }
182
183 It 'Extracts line_number property' {
184 $result = $script:JsonWithIssues | ConvertFrom-Json
185 $result[0].line_number | Should -Be 15
186 }
187
188 It 'Extracts original_url property' {
189 $result = $script:JsonWithIssues | ConvertFrom-Json
190 $result[0].original_url | Should -Be 'https://docs.microsoft.com/en-us/azure'
191 }
192 }
193
194 Context 'Empty JSON array' {
195 It 'Handles empty array' {
196 $result = '[]' | ConvertFrom-Json
197 $result | Should -BeNullOrEmpty
198 }
199 }
200
201 Context 'Invalid JSON' {
202 It 'Throws on malformed JSON' {
203 { 'not valid json' | ConvertFrom-Json } | Should -Throw
204 }
205 }
206}
207
208#endregion
209
210#region GitHub Actions Integration Tests
211
212Describe 'GitHub Actions Integration' -Tag 'Unit' {
213 Context 'Module exports verification' {
214 It 'Write-CIAnnotation is available in module' {
215 $module = Get-Module CIHelpers
216 $module.ExportedFunctions.Keys | Should -Contain 'Write-CIAnnotation'
217 }
218
219 It 'Set-CIOutput is available in module' {
220 $module = Get-Module CIHelpers
221 $module.ExportedFunctions.Keys | Should -Contain 'Set-CIOutput'
222 }
223
224 It 'Write-CIStepSummary is available in module' {
225 $module = Get-Module CIHelpers
226 $module.ExportedFunctions.Keys | Should -Contain 'Write-CIStepSummary'
227 }
228 }
229
230 Context 'GitHub Actions detection' {
231 It 'Detects GitHub Actions via GITHUB_ACTIONS env var' {
232 $originalValue = $env:GITHUB_ACTIONS
233 try {
234 $env:GITHUB_ACTIONS = 'true'
235 $env:GITHUB_ACTIONS | Should -Be 'true'
236
237 $env:GITHUB_ACTIONS = $null
238 $env:GITHUB_ACTIONS | Should -BeNullOrEmpty
239 }
240 finally {
241 $env:GITHUB_ACTIONS = $originalValue
242 }
243 }
244 }
245}
246
247#endregion
248
249#region Annotation Generation Tests
250
251Describe 'Annotation Generation' -Tag 'Unit' {
252 Context 'Annotation content' {
253 BeforeEach {
254 $script:Issue = [PSCustomObject]@{
255 file = 'docs/test.md'
256 line_number = 25
257 original_url = 'https://docs.microsoft.com/en-us/azure/overview'
258 }
259 }
260
261 It 'Issue object has required properties' {
262 $script:Issue.file | Should -Not -BeNullOrEmpty
263 $script:Issue.line_number | Should -BeGreaterThan 0
264 $script:Issue.original_url | Should -Match 'en-us'
265 }
266
267 It 'File path is workspace-relative' {
268 $script:Issue.file | Should -Not -Match '^[A-Z]:\\'
269 $script:Issue.file | Should -Not -Match '^/'
270 }
271 }
272
273 Context 'Annotation severity mapping' {
274 It 'Language path issues are warnings' {
275 # Link language issues are warnings, not errors
276 $severity = 'warning'
277 $severity | Should -Be 'warning'
278 }
279 }
280}
281
282#endregion
283
284#region Exit Code Tests
285
286Describe 'Exit Code Handling' -Tag 'Unit' {
287 Context 'No issues found' {
288 It 'Empty result indicates success' {
289 $issues = @()
290 $issues.Count | Should -Be 0
291 }
292 }
293
294 Context 'Issues found' {
295 BeforeEach {
296 $script:Issues = @(
297 [PSCustomObject]@{ file = 'test.md'; line_number = 1; original_url = 'https://example.com/en-us/page' }
298 )
299 }
300
301 It 'Non-empty result indicates issues present' {
302 $script:Issues.Count | Should -BeGreaterThan 0
303 }
304
305 It 'Script should warn but not fail on issues' {
306 # Link language issues are warnings, script continues
307 $warningExpected = $true
308 $warningExpected | Should -BeTrue
309 }
310 }
311}
312
313#endregion
314
315#region Output Format Tests
316
317Describe 'Output Format' -Tag 'Unit' {
318 Context 'Console output' {
319 BeforeEach {
320 $script:SampleIssue = [PSCustomObject]@{
321 file = 'README.md'
322 line_number = 10
323 original_url = 'https://docs.microsoft.com/en-us/azure'
324 }
325 }
326
327 It 'Issue can be formatted as string' {
328 $formatted = "[$($script:SampleIssue.file):$($script:SampleIssue.line_number)] $($script:SampleIssue.original_url)"
329 $formatted | Should -Be '[README.md:10] https://docs.microsoft.com/en-us/azure'
330 }
331 }
332
333 Context 'Summary statistics' {
334 BeforeEach {
335 $script:Issues = @(
336 [PSCustomObject]@{ file = 'a.md'; line_number = 1; original_url = 'url1' },
337 [PSCustomObject]@{ file = 'a.md'; line_number = 2; original_url = 'url2' },
338 [PSCustomObject]@{ file = 'b.md'; line_number = 1; original_url = 'url3' }
339 )
340 }
341
342 It 'Can count total issues' {
343 $script:Issues.Count | Should -Be 3
344 }
345
346 It 'Can count affected files' {
347 $fileCount = ($script:Issues | Select-Object -ExpandProperty file -Unique).Count
348 $fileCount | Should -Be 2
349 }
350 }
351}
352
353#endregion
354
355#region Integration with Link-Lang-Check Tests
356
357Describe 'Link-Lang-Check Integration' -Tag 'Integration' {
358 Context 'Script dependencies' {
359 It 'LintingHelpers module can be imported' {
360 { Import-Module $script:ModulePath -Force } | Should -Not -Throw
361 }
362
363 It 'Link-Lang-Check.ps1 exists at expected path' {
364 $linkLangCheckPath = Join-Path $PSScriptRoot '../../linting/Link-Lang-Check.ps1'
365 Test-Path $linkLangCheckPath | Should -BeTrue
366 }
367 }
368
369 Context 'Output compatibility' {
370 It 'Link-Lang-Check output can be parsed as JSON' {
371 # Sample output format from Link-Lang-Check.ps1
372 $sampleOutput = '[{"file":"test.md","line_number":1,"original_url":"https://example.com/en-us/page"}]'
373 { $sampleOutput | ConvertFrom-Json } | Should -Not -Throw
374 }
375
376 It 'Parsed output has expected structure' {
377 $sampleOutput = '[{"file":"test.md","line_number":1,"original_url":"https://example.com/en-us/page"}]'
378 $parsed = $sampleOutput | ConvertFrom-Json
379 $parsed[0].PSObject.Properties.Name | Should -Contain 'file'
380 $parsed[0].PSObject.Properties.Name | Should -Contain 'line_number'
381 $parsed[0].PSObject.Properties.Name | Should -Contain 'original_url'
382 }
383 }
384}
385
386#endregion
387