microsoft/hve-core

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
fix/1124-exclude-python-env-dirs-from-skill-validation

Branches

Tags

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

Clone

HTTPS

Download ZIP

scripts/tests/linting/LintingHelpers.Tests.ps1

612lines · modecode

1#Requires -Modules Pester
2# Copyright (c) Microsoft Corporation.
3# SPDX-License-Identifier: MIT
4<#
5.SYNOPSIS
6 Pester tests for LintingHelpers.psm1 module
7.DESCRIPTION
8 Comprehensive tests for all 3 exported functions in the LintingHelpers module:
9 - Get-ChangedFilesFromGit
10 - Get-FilesRecursive
11 - Get-GitIgnorePatterns
12#>
13
14BeforeAll {
15 $modulePath = Join-Path $PSScriptRoot '../../linting/Modules/LintingHelpers.psm1'
16 Import-Module $modulePath -Force
17}
18
19#region Get-ChangedFilesFromGit Tests
20
21Describe 'Get-ChangedFilesFromGit' {
22 Context 'Merge-base succeeds' {
23 BeforeEach {
24 # Mock git commands at module scope with proper LASTEXITCODE handling
25 $changedFiles = @('scripts/test.ps1', 'docs/readme.md', 'config/settings.json')
26
27 Mock git {
28 $global:LASTEXITCODE = 0
29 return 'abc123def456789'
30 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
31
32 Mock git {
33 $global:LASTEXITCODE = 0
34 return $changedFiles
35 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'diff' }
36
37 Mock Test-Path { return $true } -ModuleName 'LintingHelpers' -ParameterFilter { $PathType -eq 'Leaf' }
38 }
39
40 It 'Returns changed files filtered by extension' {
41 $result = Get-ChangedFilesFromGit -FileExtensions @('*.ps1')
42 $result | Should -Contain 'scripts/test.ps1'
43 $result | Should -Not -Contain 'docs/readme.md'
44 $result | Should -Not -Contain 'config/settings.json'
45 }
46
47 It 'Returns all files with wildcard extension' {
48 $result = Get-ChangedFilesFromGit -FileExtensions @('*')
49 $result.Count | Should -Be 3
50 }
51
52 It 'Returns files matching multiple extension patterns' {
53 $result = Get-ChangedFilesFromGit -FileExtensions @('*.ps1', '*.md')
54 $result | Should -Contain 'scripts/test.ps1'
55 $result | Should -Contain 'docs/readme.md'
56 $result | Should -Not -Contain 'config/settings.json'
57 }
58
59 It 'Uses default extension pattern when not specified' {
60 $result = Get-ChangedFilesFromGit
61 $result.Count | Should -Be 3
62 }
63 }
64
65 Context 'Merge-base fails, HEAD~1 fallback' {
66 BeforeEach {
67 # Merge-base fails
68 Mock git {
69 $global:LASTEXITCODE = 128
70 return $null
71 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
72
73 # rev-parse succeeds for HEAD~1 check
74 Mock git {
75 $global:LASTEXITCODE = 0
76 return 'HEAD~1-sha'
77 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'rev-parse' }
78
79 # diff returns fallback file
80 Mock git {
81 $global:LASTEXITCODE = 0
82 return @('fallback-file.ps1')
83 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'diff' }
84
85 Mock Test-Path { return $true } -ModuleName 'LintingHelpers' -ParameterFilter { $PathType -eq 'Leaf' }
86 }
87
88 It 'Falls back to HEAD~1 comparison and returns files' {
89 $result = Get-ChangedFilesFromGit -FileExtensions @('*.ps1')
90 $result | Should -Contain 'fallback-file.ps1'
91 }
92 }
93
94 Context 'Empty results' {
95 BeforeEach {
96 Mock git {
97 $global:LASTEXITCODE = 0
98 return 'abc123def456789'
99 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
100
101 Mock git {
102 $global:LASTEXITCODE = 0
103 return @()
104 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'diff' }
105 }
106
107 It 'Returns empty array when no files changed' {
108 $result = Get-ChangedFilesFromGit
109 $result | Should -BeNullOrEmpty
110 }
111 }
112
113 Context 'File existence filtering' {
114 BeforeEach {
115 Mock git {
116 $global:LASTEXITCODE = 0
117 return 'abc123def456789'
118 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
119
120 Mock git {
121 $global:LASTEXITCODE = 0
122 return @('exists.ps1', 'deleted.ps1')
123 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'diff' }
124
125 Mock Test-Path {
126 param($Path)
127 return $Path -eq 'exists.ps1'
128 } -ModuleName 'LintingHelpers' -ParameterFilter { $PathType -eq 'Leaf' }
129 }
130
131 It 'Excludes files that no longer exist' {
132 $result = Get-ChangedFilesFromGit -FileExtensions @('*.ps1')
133 $result | Should -Contain 'exists.ps1'
134 $result | Should -Not -Contain 'deleted.ps1'
135 }
136 }
137
138 Context 'Empty and whitespace file entries' {
139 BeforeEach {
140 Mock git {
141 $global:LASTEXITCODE = 0
142 return 'abc123def456789'
143 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
144
145 Mock git {
146 $global:LASTEXITCODE = 0
147 return @('valid.ps1', '', ' ', 'another.ps1')
148 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'diff' }
149
150 Mock Test-Path { return $true } -ModuleName 'LintingHelpers' -ParameterFilter { $PathType -eq 'Leaf' }
151 }
152
153 It 'Filters out empty and whitespace entries' {
154 $result = Get-ChangedFilesFromGit -FileExtensions @('*.ps1')
155 $result | Should -Contain 'valid.ps1'
156 $result | Should -Contain 'another.ps1'
157 $result | Should -Not -Contain ''
158 $result | Should -Not -Contain ' '
159 }
160 }
161
162 Context 'Both merge-base and HEAD~1 fail, third fallback' {
163 BeforeEach {
164 # Merge-base fails
165 Mock git {
166 $global:LASTEXITCODE = 128
167 return $null
168 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
169
170 # rev-parse fails for HEAD~1 check
171 Mock git {
172 $global:LASTEXITCODE = 128
173 return $null
174 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'rev-parse' }
175
176 # diff returns files from third fallback (git diff --name-only HEAD)
177 Mock git {
178 $global:LASTEXITCODE = 0
179 return @('unstaged-file.ps1')
180 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'diff' }
181
182 Mock Test-Path { return $true } -ModuleName 'LintingHelpers' -ParameterFilter { $PathType -eq 'Leaf' }
183 }
184
185 It 'Falls back to git diff --name-only HEAD and returns files' {
186 $result = Get-ChangedFilesFromGit -FileExtensions @('*.ps1')
187 $result | Should -Contain 'unstaged-file.ps1'
188 }
189 }
190
191 Context 'Git diff command fails' {
192 BeforeEach {
193 Mock git {
194 $global:LASTEXITCODE = 0
195 return 'abc123def456789'
196 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
197
198 # Diff fails with non-zero exit code
199 Mock git {
200 $global:LASTEXITCODE = 1
201 return $null
202 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'diff' }
203 }
204
205 It 'Returns empty array when git diff fails' {
206 $result = Get-ChangedFilesFromGit
207 $result | Should -BeNullOrEmpty
208 }
209 }
210
211 Context 'Exception during execution' {
212 BeforeEach {
213 Mock git {
214 throw "Simulated git failure"
215 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
216 }
217
218 It 'Catches exceptions and returns empty array' {
219 $result = Get-ChangedFilesFromGit
220 $result | Should -BeNullOrEmpty
221 }
222 }
223
224 Context 'Warning and verbose output' {
225 It 'Emits warning when git diff returns non-zero exit code' {
226 Mock git {
227 $global:LASTEXITCODE = 0
228 return 'abc123def456789'
229 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
230
231 Mock git {
232 $global:LASTEXITCODE = 1
233 return $null
234 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'diff' }
235
236 $output = Get-ChangedFilesFromGit 3>&1
237 $warnings = @($output | Where-Object { $_ -is [System.Management.Automation.WarningRecord] })
238 $warnings | Should -Not -BeNullOrEmpty
239 }
240
241 It 'Emits warning when exception occurs' {
242 Mock git {
243 throw "Simulated git failure"
244 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
245
246 $warnings = Get-ChangedFilesFromGit 3>&1 | Where-Object { $_ -is [System.Management.Automation.WarningRecord] }
247 $warnings | Should -Not -BeNullOrEmpty
248 }
249
250 It 'Emits verbose message when merge-base succeeds' {
251 Mock git {
252 $global:LASTEXITCODE = 0
253 return 'abc123def456789'
254 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
255
256 Mock git {
257 $global:LASTEXITCODE = 0
258 return @('file.ps1')
259 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'diff' }
260
261 Mock Test-Path { return $true } -ModuleName 'LintingHelpers' -ParameterFilter { $PathType -eq 'Leaf' }
262
263 $verbose = Get-ChangedFilesFromGit -Verbose 4>&1 | Where-Object { $_ -is [System.Management.Automation.VerboseRecord] }
264 $verbose | Should -Not -BeNullOrEmpty
265 }
266
267 It 'Emits verbose message when falling back to HEAD~1' {
268 Mock git {
269 $global:LASTEXITCODE = 128
270 return $null
271 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
272
273 Mock git {
274 $global:LASTEXITCODE = 0
275 return 'HEAD~1-sha'
276 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'rev-parse' }
277
278 Mock git {
279 $global:LASTEXITCODE = 0
280 return @('file.ps1')
281 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'diff' }
282
283 Mock Test-Path { return $true } -ModuleName 'LintingHelpers' -ParameterFilter { $PathType -eq 'Leaf' }
284
285 $verbose = Get-ChangedFilesFromGit -Verbose 4>&1 | Where-Object { $_ -is [System.Management.Automation.VerboseRecord] }
286 $verbose | Should -Not -BeNullOrEmpty
287 ($verbose | Where-Object { $_.Message -match 'HEAD~1' }) | Should -Not -BeNullOrEmpty
288 }
289 }
290
291 Context 'Custom BaseBranch parameter' {
292 BeforeEach {
293 Mock git {
294 $global:LASTEXITCODE = 0
295 return 'abc123def456789'
296 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
297
298 Mock git {
299 $global:LASTEXITCODE = 0
300 return @('file.md')
301 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'diff' }
302
303 Mock Test-Path { return $true } -ModuleName 'LintingHelpers' -ParameterFilter { $PathType -eq 'Leaf' }
304 }
305
306 It 'Passes custom BaseBranch to merge-base' {
307 Get-ChangedFilesFromGit -BaseBranch 'origin/develop' -FileExtensions @('*.md')
308 Should -Invoke git -ModuleName 'LintingHelpers' -ParameterFilter {
309 $args[0] -eq 'merge-base' -and $args -contains 'origin/develop'
310 }
311 }
312
313 It 'Uses default BaseBranch when not specified' {
314 Get-ChangedFilesFromGit -FileExtensions @('*.md')
315 Should -Invoke git -ModuleName 'LintingHelpers' -ParameterFilter {
316 $args[0] -eq 'merge-base' -and $args -contains 'origin/main'
317 }
318 }
319 }
320
321 Context 'Mixed path separators' {
322 BeforeEach {
323 Mock git {
324 $global:LASTEXITCODE = 0
325 return 'abc123def456789'
326 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'merge-base' }
327
328 Mock git {
329 $global:LASTEXITCODE = 0
330 return @('src/docs/readme.md', 'src\tests\test.md', 'docs/guide.md')
331 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'diff' }
332
333 Mock Test-Path { return $true } -ModuleName 'LintingHelpers' -ParameterFilter { $PathType -eq 'Leaf' }
334 }
335
336 It 'Handles files with forward slashes' {
337 $result = Get-ChangedFilesFromGit -FileExtensions @('*.md')
338 $result | Should -Contain 'src/docs/readme.md'
339 }
340
341 It 'Handles files with backslashes' {
342 $result = Get-ChangedFilesFromGit -FileExtensions @('*.md')
343 $result | Should -Contain 'src\tests\test.md'
344 }
345
346 It 'Returns correct count with mixed separators' {
347 $result = Get-ChangedFilesFromGit -FileExtensions @('*.md')
348 $result.Count | Should -Be 3
349 }
350 }
351}
352
353#endregion
354
355#region Get-FilesRecursive Tests
356
357Describe 'Get-FilesRecursive' {
358 Context 'Basic file enumeration' {
359 BeforeEach {
360 New-Item -Path 'TestDrive:/scripts' -ItemType Directory -Force | Out-Null
361 New-Item -Path 'TestDrive:/scripts/test.ps1' -ItemType File -Force | Out-Null
362 New-Item -Path 'TestDrive:/scripts/readme.md' -ItemType File -Force | Out-Null
363 New-Item -Path 'TestDrive:/scripts/sub' -ItemType Directory -Force | Out-Null
364 New-Item -Path 'TestDrive:/scripts/sub/nested.ps1' -ItemType File -Force | Out-Null
365 }
366
367 It 'Finds files matching Include pattern' {
368 $result = Get-FilesRecursive -Path 'TestDrive:/scripts' -Include @('*.ps1')
369 $result.Count | Should -Be 2
370 $result.Name | Should -Contain 'test.ps1'
371 $result.Name | Should -Contain 'nested.ps1'
372 }
373
374 It 'Finds files with multiple Include patterns' {
375 $result = Get-FilesRecursive -Path 'TestDrive:/scripts' -Include @('*.ps1', '*.md')
376 $result.Count | Should -Be 3
377 }
378
379 It 'Does not include directories in results' {
380 $result = Get-FilesRecursive -Path 'TestDrive:/scripts' -Include @('*')
381 $result | ForEach-Object { $_.PSIsContainer | Should -BeFalse }
382 }
383 }
384
385 Context 'Gitignore filtering' {
386 BeforeEach {
387 New-Item -Path 'TestDrive:/project' -ItemType Directory -Force | Out-Null
388 New-Item -Path 'TestDrive:/project/src' -ItemType Directory -Force | Out-Null
389 New-Item -Path 'TestDrive:/project/src/app.ps1' -ItemType File -Force | Out-Null
390 New-Item -Path 'TestDrive:/project/node_modules' -ItemType Directory -Force | Out-Null
391 New-Item -Path 'TestDrive:/project/node_modules/pkg.ps1' -ItemType File -Force | Out-Null
392 'node_modules/' | Set-Content 'TestDrive:/project/.gitignore'
393 }
394
395 It 'Excludes files matching gitignore patterns' {
396 $result = Get-FilesRecursive -Path 'TestDrive:/project' `
397 -Include @('*.ps1') `
398 -GitIgnorePath 'TestDrive:/project/.gitignore'
399 $result.Name | Should -Contain 'app.ps1'
400 $result.Name | Should -Not -Contain 'pkg.ps1'
401 }
402
403 It 'Returns all files when gitignore path not provided' {
404 $result = Get-FilesRecursive -Path 'TestDrive:/project' -Include @('*.ps1')
405 $result.Count | Should -Be 2
406 }
407 }
408
409 Context 'Invalid paths' {
410 It 'Returns empty for non-existent path' {
411 $result = Get-FilesRecursive -Path 'TestDrive:/nonexistent' -Include @('*.ps1')
412 $result | Should -BeNullOrEmpty
413 }
414 }
415
416 Context 'No gitignore file' {
417 BeforeEach {
418 New-Item -Path 'TestDrive:/simple' -ItemType Directory -Force | Out-Null
419 New-Item -Path 'TestDrive:/simple/file.ps1' -ItemType File -Force | Out-Null
420 }
421
422 It 'Returns files when gitignore does not exist' {
423 $result = Get-FilesRecursive -Path 'TestDrive:/simple' `
424 -Include @('*.ps1') `
425 -GitIgnorePath 'TestDrive:/simple/.gitignore'
426 $result.Count | Should -Be 1
427 }
428 }
429
430 Context 'Git ls-files code path at repo root' {
431 BeforeEach {
432 Mock git {
433 $global:LASTEXITCODE = 0
434 return '/mock/repo'
435 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'rev-parse' }
436
437 Mock git {
438 $global:LASTEXITCODE = 0
439 return @('src/app.ps1', 'src/helper.psm1', 'tests/run.ps1')
440 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'ls-files' }
441
442 Mock Resolve-Path {
443 [PSCustomObject]@{ Path = '/mock/repo' }
444 } -ModuleName 'LintingHelpers'
445
446 Mock Test-Path { $true } -ModuleName 'LintingHelpers' -ParameterFilter {
447 $LiteralPath -or ($Path -and $PathType -eq 'Leaf')
448 }
449
450 Mock Get-Item {
451 [PSCustomObject]@{
452 FullName = $LiteralPath
453 Name = [System.IO.Path]::GetFileName($LiteralPath)
454 PSIsContainer = $false
455 }
456 } -ModuleName 'LintingHelpers'
457 }
458
459 It 'Calls git ls-files when path is inside the repository' {
460 Get-FilesRecursive -Path '.' -Include @('*.ps1')
461 Should -Invoke git -ModuleName 'LintingHelpers' -ParameterFilter {
462 $args[0] -eq 'ls-files'
463 }
464 }
465
466 It 'Returns FileInfo objects from git ls-files output' {
467 $result = Get-FilesRecursive -Path '.' -Include @('*.ps1')
468 $result | Should -Not -BeNullOrEmpty
469 $result | ForEach-Object { $_.PSIsContainer | Should -BeFalse }
470 }
471
472 It 'Passes Include patterns as pathspecs at repo root' {
473 Get-FilesRecursive -Path '.' -Include @('*.ps1', '*.psm1')
474 Should -Invoke git -ModuleName 'LintingHelpers' -ParameterFilter {
475 $args -contains '*.ps1' -and $args -contains '*.psm1'
476 }
477 }
478
479 It 'Accepts GitIgnorePath without error on git path' {
480 { Get-FilesRecursive -Path '.' -Include @('*.ps1') -GitIgnorePath '/nonexistent/.gitignore' } |
481 Should -Not -Throw
482 }
483 }
484
485 Context 'Git ls-files subdirectory scoping' {
486 BeforeEach {
487 Mock git {
488 $global:LASTEXITCODE = 0
489 return '/mock/repo'
490 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'rev-parse' }
491
492 Mock git {
493 $global:LASTEXITCODE = 0
494 return @('src/app.ps1', 'src/helper.psm1')
495 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'ls-files' }
496
497 Mock Resolve-Path {
498 [PSCustomObject]@{ Path = '/mock/repo/src' }
499 } -ModuleName 'LintingHelpers'
500
501 Mock Test-Path { $true } -ModuleName 'LintingHelpers' -ParameterFilter {
502 $LiteralPath -or ($Path -and $PathType -eq 'Leaf')
503 }
504
505 Mock Get-Item {
506 [PSCustomObject]@{
507 FullName = $LiteralPath
508 Name = [System.IO.Path]::GetFileName($LiteralPath)
509 PSIsContainer = $false
510 }
511 } -ModuleName 'LintingHelpers'
512 }
513
514 It 'Scopes git ls-files to the specified subdirectory' {
515 Get-FilesRecursive -Path './src' -Include @('*.ps1')
516 Should -Invoke git -ModuleName 'LintingHelpers' -ParameterFilter {
517 $args -contains '--' -and $args -contains 'src/'
518 }
519 }
520
521 It 'Filters subdirectory results by Include patterns' {
522 $result = Get-FilesRecursive -Path './src' -Include @('*.ps1')
523 $result.Name | Should -Contain 'app.ps1'
524 $result.Name | Should -Not -Contain 'helper.psm1'
525 }
526 }
527
528 Context 'Git unavailable' {
529 BeforeEach {
530 Mock git {
531 $global:LASTEXITCODE = 128
532 return $null
533 } -ModuleName 'LintingHelpers' -ParameterFilter { $args[0] -eq 'rev-parse' }
534
535 New-Item -Path 'TestDrive:/nogit' -ItemType Directory -Force | Out-Null
536 New-Item -Path 'TestDrive:/nogit/script.ps1' -ItemType File -Force | Out-Null
537 }
538
539 It 'Falls back to Get-ChildItem when git is unavailable' {
540 $result = Get-FilesRecursive -Path 'TestDrive:/nogit' -Include @('*.ps1')
541 $result.Count | Should -Be 1
542 $result.Name | Should -Contain 'script.ps1'
543 }
544 }
545}
546
547#endregion
548
549#region Get-GitIgnorePatterns Tests
550
551Describe 'Get-GitIgnorePatterns' {
552 Context 'Non-existent file' {
553 It 'Returns empty for non-existent file' {
554 $result = Get-GitIgnorePatterns -GitIgnorePath 'TestDrive:/nonexistent/.gitignore'
555 $result | Should -BeNullOrEmpty
556 }
557 }
558
559 Context 'Empty file' {
560 BeforeEach {
561 New-Item -Path 'TestDrive:/.gitignore-empty' -ItemType File -Force | Out-Null
562 }
563
564 It 'Returns empty for empty file' {
565 $result = Get-GitIgnorePatterns -GitIgnorePath 'TestDrive:/.gitignore-empty'
566 $result | Should -BeNullOrEmpty
567 }
568 }
569
570 Context 'Pattern parsing' {
571 It 'Skips comments and empty lines' {
572 @('# Comment', '', 'node_modules/', ' ', '*.log') | Set-Content 'TestDrive:/.gitignore'
573 $result = Get-GitIgnorePatterns -GitIgnorePath 'TestDrive:/.gitignore'
574 $result.Count | Should -Be 2
575 }
576
577 It 'Converts directory patterns correctly' {
578 $gitignorePath = Join-Path $TestDrive '.gitignore-dir'
579 'node_modules/' | Set-Content $gitignorePath
580 $result = @(Get-GitIgnorePatterns -GitIgnorePath $gitignorePath)
581 $sep = [System.IO.Path]::DirectorySeparatorChar
582 # Function wraps directory patterns with platform separator
583 $result[0] | Should -Be "*${sep}node_modules${sep}*"
584 }
585
586 It 'Converts file patterns with paths correctly' {
587 $gitignorePath = Join-Path $TestDrive '.gitignore-path'
588 'build/output.log' | Set-Content $gitignorePath
589 $result = @(Get-GitIgnorePatterns -GitIgnorePath $gitignorePath)
590 $sep = [System.IO.Path]::DirectorySeparatorChar
591 # Function normalizes paths and wraps with wildcards
592 $result[0] | Should -Be "*${sep}build${sep}output.log*"
593 }
594
595 It 'Handles simple file patterns' {
596 $gitignorePath = Join-Path $TestDrive '.gitignore-simple'
597 '*.log' | Set-Content $gitignorePath
598 $result = @(Get-GitIgnorePatterns -GitIgnorePath $gitignorePath)
599 $sep = [System.IO.Path]::DirectorySeparatorChar
600 # Function wraps simple patterns with wildcards
601 $result[0] | Should -Be "*${sep}*.log${sep}*"
602 }
603
604 It 'Processes multiple patterns' {
605 @('node_modules/', 'dist/', '*.tmp', 'logs/debug.log') | Set-Content 'TestDrive:/.gitignore-multi'
606 $result = Get-GitIgnorePatterns -GitIgnorePath 'TestDrive:/.gitignore-multi'
607 $result.Count | Should -Be 4
608 }
609 }
610}
611
612#endregion
613