microsoft/hve-core

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
feat/collections-overview-docs

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

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