22# Pester tests for Deep Clean Pro scripts
33# Requires Pester v5+
44
5- # Set up test environment at module level
6- $script :TestRoot = $PSScriptRoot
7- Write-Host " Test root: $TestRoot " - ForegroundColor Cyan
8-
9- # Try multiple methods to find the project root
10- $script :ModuleRoot = $null
11-
12- # Method 1: Navigate from .github/tests to project root
13- $potentialRoot1 = Split-Path - Parent (Split-Path - Parent $TestRoot )
14- if (Test-Path (Join-Path $potentialRoot1 " Scripts" )) {
15- $script :ModuleRoot = $potentialRoot1
16- Write-Host " Found project root via .github/tests navigation: $ModuleRoot " - ForegroundColor Green
17- }
18-
19- # Method 2: Look for Scripts folder in current directory or parent directories
20- if (-not $script :ModuleRoot ) {
21- $currentDir = $TestRoot
22- for ($i = 0 ; $i -lt 5 ; $i ++ ) {
23- if (Test-Path (Join-Path $currentDir " Scripts" )) {
24- $script :ModuleRoot = $currentDir
25- Write-Host " Found project root via Scripts folder search: $ModuleRoot " - ForegroundColor Green
26- break
27- }
28- $currentDir = Split-Path - Parent $currentDir
29- if ([string ]::IsNullOrEmpty($currentDir ) -or $currentDir -eq (Split-Path - Parent $currentDir )) {
30- break
31- }
32- }
33- }
34-
35- # Method 3: Use GitHub Actions environment variables if available
36- if (-not $script :ModuleRoot -and $env: GITHUB_WORKSPACE ) {
37- $script :ModuleRoot = $env: GITHUB_WORKSPACE
38- Write-Host " Using GitHub Actions workspace: $ModuleRoot " - ForegroundColor Green
39- }
40-
41- # Method 4: Use current working directory as fallback
42- if (-not $script :ModuleRoot ) {
43- $script :ModuleRoot = Get-Location
44- Write-Host " Using current working directory as fallback: $ModuleRoot " - ForegroundColor Yellow
45- }
46-
47- Write-Host " Final module root: $ModuleRoot " - ForegroundColor Cyan
48-
49- # Import scripts to test from Scripts folder
50- $script :ScriptsPath = Join-Path $script :ModuleRoot " Scripts"
51- Write-Host " Scripts path: $ScriptsPath " - ForegroundColor Cyan
52-
53- $script :ValidateScript = Join-Path $script :ScriptsPath " VALIDATE.ps1"
54- $script :DeepCleanScript = Join-Path $script :ScriptsPath " DeepCleanPro.ps1"
55-
56- Write-Host " VALIDATE.ps1 path: $ValidateScript " - ForegroundColor Yellow
57- Write-Host " DeepCleanPro.ps1 path: $DeepCleanScript " - ForegroundColor Yellow
58-
59- # Verify paths exist and provide detailed error information
60- if (-not (Test-Path $script :ValidateScript )) {
61- Write-Warning " VALIDATE.ps1 not found at: $script :ValidateScript "
62- Write-Warning " Scripts directory exists: $ ( Test-Path $script :ScriptsPath ) "
63- Write-Warning " Scripts directory contents: $ ( if (Test-Path $script :ScriptsPath ) { Get-ChildItem $script :ScriptsPath - Name } else { ' Directory not found' }) "
64- } else {
65- Write-Host " VALIDATE.ps1 found successfully" - ForegroundColor Green
66- }
67-
68- if (-not (Test-Path $script :DeepCleanScript )) {
69- Write-Warning " DeepCleanPro.ps1 not found at: $script :DeepCleanScript "
70- Write-Warning " Scripts directory exists: $ ( Test-Path $script :ScriptsPath ) "
71- Write-Warning " Scripts directory contents: $ ( if (Test-Path $script :ScriptsPath ) { Get-ChildItem $script :ScriptsPath - Name } else { ' Directory not found' }) "
72- } else {
73- Write-Host " DeepCleanPro.ps1 found successfully" - ForegroundColor Green
5+ BeforeAll {
6+ # Set up test environment - use simple relative paths from repo root
7+ $script :ValidateScript = " .\Scripts\VALIDATE.ps1"
8+ $script :DeepCleanScript = " .\Scripts\DeepCleanPro.ps1"
9+
10+ # Debug output
11+ Write-Host " Looking for scripts at:" - ForegroundColor Yellow
12+ Write-Host " VALIDATE.ps1: $script :ValidateScript (Exists: $ ( Test-Path $script :ValidateScript ) )" - ForegroundColor Cyan
13+ Write-Host " DeepCleanPro.ps1: $script :DeepCleanScript (Exists: $ ( Test-Path $script :DeepCleanScript ) )" - ForegroundColor Cyan
14+
15+ # Mock data
16+ $script :TestTempPath = Join-Path $env: TEMP " PesterTest_$ ( Get-Random ) "
7417}
7518
76- # Mock data
77- $script :TestTempPath = Join-Path $env: TEMP " PesterTest_$ ( Get-Random ) "
78-
79- # Cleanup function
80- function Remove-TestEnvironment {
19+ AfterAll {
20+ # Cleanup
8121 if (Test-Path $script :TestTempPath ) {
8222 Remove-Item $script :TestTempPath - Recurse - Force - ErrorAction SilentlyContinue
8323 }
@@ -86,11 +26,11 @@ function Remove-TestEnvironment {
8626Describe " VALIDATE.ps1 Tests" - Tags ' Validate' , ' Unit' {
8727
8828 Context " Script Existence and Syntax" {
89- It " Should exist at expected location" - Skip:( -not ( Test-Path $ script :ValidateScript )) {
29+ It " Should exist at expected location" {
9030 Test-Path $script :ValidateScript | Should - BeTrue
9131 }
9232
93- It " Should have valid PowerShell syntax" - Skip:( -not ( Test-Path $ script :ValidateScript )) {
33+ It " Should have valid PowerShell syntax" {
9434 $errors = $null
9535 $tokens = $null
9636 $null = [System.Management.Automation.Language.Parser ]::ParseFile(
@@ -101,13 +41,13 @@ Describe "VALIDATE.ps1 Tests" -Tags 'Validate', 'Unit' {
10141 $errors.Count | Should - Be 0
10242 }
10343
104- It " Should require RunAsAdministrator" - Skip:( -not ( Test-Path $ script :ValidateScript )) {
44+ It " Should require RunAsAdministrator" {
10545 $content = Get-Content $script :ValidateScript - Raw
10646 $content | Should -Match ' #Requires -RunAsAdministrator'
10747 }
10848 }
10949
110- Context " Parameters" - Skip:( -not ( Test-Path $ script :ValidateScript )) {
50+ Context " Parameters" {
11151 BeforeAll {
11252 # Parse script to get parameters
11353 $ast = [System.Management.Automation.Language.Parser ]::ParseFile(
@@ -136,36 +76,52 @@ Describe "VALIDATE.ps1 Tests" -Tags 'Validate', 'Unit' {
13676 }
13777 }
13878
139- Context " Test-Feature Function" - Skip:( -not ( Test-Path $ script :ValidateScript )) {
140- It " Should have Test-Feature function defined in script " {
141- $content = Get-Content $ script :ValidateScript - Raw
142- $content | Should -Match ' function Test-Feature '
79+ Context " Test-Feature Function" {
80+ BeforeAll {
81+ # Load just the Test-Feature function for isolated testing
82+ . $ script :ValidateScript - QuickCheck
14383 }
14484
145- It " Should have proper function parameters" {
146- $content = Get-Content $script :ValidateScript - Raw
147- $content | Should -Match ' param\s*\(\s*\[string\]\$Name'
148- $content | Should -Match ' \[scriptblock\]\$Test'
149- $content | Should -Match ' \[string\]\$SuccessMessage'
150- $content | Should -Match ' \[string\]\$FailureMessage'
85+ It " Should execute and return true for passing tests" {
86+ Mock Write-Host {}
87+
88+ $result = Test-Feature - Name " TestPass" - Test {
89+ return $true
90+ } - SuccessMessage " Pass" - FailureMessage " Fail"
91+
92+ $result | Should - BeTrue
15193 }
15294
153- It " Should have error handling in Test-Feature" {
154- $content = Get-Content $script :ValidateScript - Raw
155- $content | Should -Match ' try\s*\{'
156- $content | Should -Match ' catch\s*\{'
95+ It " Should execute and return false for failing tests" {
96+ Mock Write-Host {}
97+
98+ $result = Test-Feature - Name " TestFail" - Test {
99+ return $false
100+ } - SuccessMessage " Pass" - FailureMessage " Fail"
101+
102+ $result | Should - BeFalse
103+ }
104+
105+ It " Should handle exceptions gracefully" {
106+ Mock Write-Host {}
107+
108+ $result = Test-Feature - Name " TestError" - Test {
109+ throw " Test exception"
110+ } - SuccessMessage " Pass" - FailureMessage " Fail"
111+
112+ $result | Should - BeFalse
157113 }
158114 }
159115}
160116
161117Describe " DeepCleanPro.ps1 Tests" - Tags ' DeepClean' , ' Unit' {
162118
163119 Context " Script Existence and Syntax" {
164- It " Should exist at expected location" - Skip:( -not ( Test-Path $ script :DeepCleanScript )) {
120+ It " Should exist at expected location" {
165121 Test-Path $script :DeepCleanScript | Should - BeTrue
166122 }
167123
168- It " Should have valid PowerShell syntax" - Skip:( -not ( Test-Path $ script :DeepCleanScript )) {
124+ It " Should have valid PowerShell syntax" {
169125 $errors = $null
170126 $tokens = $null
171127 $null = [System.Management.Automation.Language.Parser ]::ParseFile(
@@ -176,13 +132,13 @@ Describe "DeepCleanPro.ps1 Tests" -Tags 'DeepClean', 'Unit' {
176132 $errors.Count | Should - Be 0
177133 }
178134
179- It " Should require RunAsAdministrator" - Skip:( -not ( Test-Path $ script :DeepCleanScript )) {
135+ It " Should require RunAsAdministrator" {
180136 $content = Get-Content $script :DeepCleanScript - Raw
181137 $content | Should -Match ' #Requires -RunAsAdministrator'
182138 }
183139 }
184140
185- Context " Parameters" - Skip:( -not ( Test-Path $ script :DeepCleanScript )) {
141+ Context " Parameters" {
186142 It " Should have SkipUpdates parameter" {
187143 $content = Get-Content $script :DeepCleanScript - Raw
188144 $content | Should -Match ' \[switch\]\$SkipUpdates'
@@ -214,7 +170,7 @@ Describe "DeepCleanPro.ps1 Tests" -Tags 'DeepClean', 'Unit' {
214170 }
215171 }
216172
217- Context " Helper Functions" - Skip:( -not ( Test-Path $ script :DeepCleanScript )) {
173+ Context " Helper Functions" {
218174 It " Should define Write-Step function" {
219175 $content = Get-Content $script :DeepCleanScript - Raw
220176 $content | Should -Match ' function Write-Step'
@@ -236,7 +192,7 @@ Describe "DeepCleanPro.ps1 Tests" -Tags 'DeepClean', 'Unit' {
236192 }
237193 }
238194
239- Context " Error Handling" - Skip:( -not ( Test-Path $ script :DeepCleanScript )) {
195+ Context " Error Handling" {
240196 It " Should not have empty catch blocks" {
241197 $content = Get-Content $script :DeepCleanScript - Raw
242198 # Look for empty catch blocks (catch {})
@@ -306,7 +262,7 @@ Describe "PSScriptAnalyzer Compliance" -Tags 'ScriptAnalyzer', 'Quality' {
306262
307263 It " Should have minimal warnings" {
308264 $analysis = Invoke-ScriptAnalyzer - Path $script :ValidateScript - Severity Warning
309- $analysis.Count | Should - BeLessThan 50
265+ $analysis.Count | Should - BeLessThan 5
310266 }
311267 }
312268
@@ -319,7 +275,7 @@ Describe "PSScriptAnalyzer Compliance" -Tags 'ScriptAnalyzer', 'Quality' {
319275 It " Should have minimal warnings" {
320276 $analysis = Invoke-ScriptAnalyzer - Path $script :DeepCleanScript - Severity Warning
321277 # DeepCleanPro is complex, allow more warnings but should be reasonable
322- $analysis.Count | Should - BeLessThan 100
278+ $analysis.Count | Should - BeLessThan 10
323279 }
324280 }
325281}
@@ -328,16 +284,7 @@ Describe "Security Tests" -Tags 'Security' {
328284
329285 Context " Privilege Requirements" {
330286 It " Scripts should explicitly require Administrator" {
331- $scriptsToTest = @ ()
332- if (Test-Path $script :ValidateScript ) { $scriptsToTest += $script :ValidateScript }
333- if (Test-Path $script :DeepCleanScript ) { $scriptsToTest += $script :DeepCleanScript }
334-
335- if ($scriptsToTest.Count -eq 0 ) {
336- Set-ItResult - Skipped - Because " No scripts found to test"
337- return
338- }
339-
340- $scriptsToTest | ForEach-Object {
287+ @ ($script :ValidateScript , $script :DeepCleanScript ) | ForEach-Object {
341288 $content = Get-Content $_ - Raw
342289 $content | Should -Match ' #Requires -RunAsAdministrator'
343290 }
@@ -346,33 +293,15 @@ Describe "Security Tests" -Tags 'Security' {
346293
347294 Context " Sensitive Operations" {
348295 It " Should not contain hardcoded passwords" {
349- $scriptsToTest = @ ()
350- if (Test-Path $script :ValidateScript ) { $scriptsToTest += $script :ValidateScript }
351- if (Test-Path $script :DeepCleanScript ) { $scriptsToTest += $script :DeepCleanScript }
352-
353- if ($scriptsToTest.Count -eq 0 ) {
354- Set-ItResult - Skipped - Because " No scripts found to test"
355- return
356- }
357-
358- $scriptsToTest | ForEach-Object {
296+ @ ($script :ValidateScript , $script :DeepCleanScript ) | ForEach-Object {
359297 $content = Get-Content $_ - Raw
360298 $content | Should -Not -Match ' password\s*=\s*["'' ].*["'' ]'
361299 $content | Should -Not -Match ' pwd\s*=\s*["'' ].*["'' ]'
362300 }
363301 }
364302
365303 It " Should not contain hardcoded API keys" {
366- $scriptsToTest = @ ()
367- if (Test-Path $script :ValidateScript ) { $scriptsToTest += $script :ValidateScript }
368- if (Test-Path $script :DeepCleanScript ) { $scriptsToTest += $script :DeepCleanScript }
369-
370- if ($scriptsToTest.Count -eq 0 ) {
371- Set-ItResult - Skipped - Because " No scripts found to test"
372- return
373- }
374-
375- $scriptsToTest | ForEach-Object {
304+ @ ($script :ValidateScript , $script :DeepCleanScript ) | ForEach-Object {
376305 $content = Get-Content $_ - Raw
377306 $content | Should -Not -Match ' api[_-]?key\s*=\s*["'' ].*["'' ]'
378307 $content | Should -Not -Match ' token\s*=\s*["'' ].*["'' ]'
@@ -384,7 +313,7 @@ Describe "Security Tests" -Tags 'Security' {
384313Describe " Performance Tests" - Tags ' Performance' {
385314
386315 Context " Script Loading" {
387- It " VALIDATE.ps1 should parse quickly" - Skip:( -not ( Test-Path $ script :ValidateScript )) {
316+ It " VALIDATE.ps1 should parse quickly" {
388317 $measure = Measure-Command {
389318 $null = [System.Management.Automation.Language.Parser ]::ParseFile(
390319 $script :ValidateScript ,
@@ -395,7 +324,7 @@ Describe "Performance Tests" -Tags 'Performance' {
395324 $measure.TotalMilliseconds | Should - BeLessThan 1000
396325 }
397326
398- It " DeepCleanPro.ps1 should parse quickly" - Skip:( -not ( Test-Path $ script :DeepCleanScript )) {
327+ It " DeepCleanPro.ps1 should parse quickly" {
399328 $measure = Measure-Command {
400329 $null = [System.Management.Automation.Language.Parser ]::ParseFile(
401330 $script :DeepCleanScript ,
@@ -407,6 +336,3 @@ Describe "Performance Tests" -Tags 'Performance' {
407336 }
408337 }
409338}
410-
411- # Cleanup after all tests
412- Remove-TestEnvironment
0 commit comments