Tests/PSWatchdog.Tests.ps1
|
# PSWatchdog.Tests.ps1 # Pester tests for PSWatchdog module BeforeAll { # Import the module - handle both Windows and Linux paths $ModulePath = if ($PSScriptRoot) { Join-Path $PSScriptRoot "..\PSWatchdog.psm1" } else { Join-Path $PSCommandPath "..\PSWatchdog.psm1" } Import-Module $ModulePath -Force # Store captured events for testing $script:CapturedEvents = @() # Setup test directory $script:TestDir = Join-Path $env:TEMP "PSWatchdog_Test_$(Get-Random)" New-Item -ItemType Directory -Path $script:TestDir -Force | Out-Null } AfterAll { # Clean up test directory if (Test-Path $script:TestDir) { Remove-Item -Path $script:TestDir -Recurse -Force -ErrorAction SilentlyContinue } # Ensure all watchers are stopped Stop-AllFileWatchers -ErrorAction SilentlyContinue # Remove module Remove-Module PSWatchdog -ErrorAction SilentlyContinue } Describe "PSWatchdog Module Tests" { Context "Module Loading" { It "Should load the module successfully" { $module = Get-Module -Name PSWatchdog $module | Should -Not -BeNullOrEmpty } It "Should export all required functions" { $functions = Get-Command -Module PSWatchdog | Select-Object -ExpandProperty Name $functions | Should -Contain 'Start-FileWatcher' $functions | Should -Contain 'Get-FileWatcher' $functions | Should -Contain 'Stop-FileWatcher' $functions | Should -Contain 'Stop-AllFileWatchers' } } Context "Start-FileWatcher Parameter Validation" { It "Should require Path parameter" { { Start-FileWatcher -Path "" -ErrorAction Stop } | Should -Throw } It "Should require existing path" { { Start-FileWatcher -Path "C:\NonExistentPath_12345" -ErrorAction Stop } | Should -Throw } It "Should accept valid path" { $result = Start-FileWatcher -Path $script:TestDir -ErrorAction Stop $result | Should -Not -BeNullOrEmpty $result.Path | Should -Be $script:TestDir Stop-FileWatcher -Id $result.Id } It "Should have default filter of *.*" { $result = Start-FileWatcher -Path $script:TestDir -ErrorAction Stop $result.Filter | Should -Be "*.*" Stop-FileWatcher -Id $result.Id } It "Should accept custom filter" { $result = Start-FileWatcher -Path $script:TestDir -Filter "*.txt" -ErrorAction Stop $result.Filter | Should -Be "*.txt" Stop-FileWatcher -Id $result.Id } It "Should accept ChangeType parameter" { $result = Start-FileWatcher -Path $script:TestDir -ChangeType Created -ErrorAction Stop $result.ChangeType | Should -Be "Created" Stop-FileWatcher -Id $result.Id } It "Should accept multiple ChangeType values" { $result = Start-FileWatcher -Path $script:TestDir -ChangeType Created, Changed -ErrorAction Stop $result.ChangeType.Count | Should -Be 2 Stop-FileWatcher -Id $result.Id } It "Should accept IncludeSubdirectories switch" { $result = Start-FileWatcher -Path $script:TestDir -IncludeSubdirectories -ErrorAction Stop $result.IncludeSubdirectories | Should -Be $true Stop-FileWatcher -Id $result.Id } It "Should return object with required properties" { $result = Start-FileWatcher -Path $script:TestDir -ErrorAction Stop $result.Id | Should -Not -BeNullOrEmpty $result.Watcher | Should -Not -BeNullOrEmpty Stop-FileWatcher -Id $result.Id } It "Should set InternalBufferSize to 65536" { $result = Start-FileWatcher -Path $script:TestDir -ErrorAction Stop $result.Watcher.InternalBufferSize | Should -Be 65536 Stop-FileWatcher -Id $result.Id } It "Should enable events by default" { $result = Start-FileWatcher -Path $script:TestDir -ErrorAction Stop $result.Watcher.EnableRaisingEvents | Should -Be $true Stop-FileWatcher -Id $result.Id } } Context "Start-FileWatcher Action ScriptBlock" { It "Should accept Action parameter" { $action = { param($event) } $watcher = Start-FileWatcher -Path $script:TestDir -Filter "*.txt" -ChangeType Created -Action $action -ErrorAction Stop $watcher | Should -Not -BeNullOrEmpty Stop-FileWatcher -Id $watcher.Id } It "Should work without Action parameter" { $watcher = Start-FileWatcher -Path $script:TestDir -Filter "*.txt" -ChangeType Created -ErrorAction Stop $watcher.Action | Should -BeNullOrEmpty Stop-FileWatcher -Id $watcher.Id } } Context "Get-FileWatcher Tests" { It "Should return empty when no watchers active" { Stop-AllFileWatchers -ErrorAction SilentlyContinue $result = Get-FileWatcher $result.Count | Should -Be 0 } It "Should return all active watchers" { $w1 = Start-FileWatcher -Path $script:TestDir -Filter "*.txt" -ErrorAction Stop $w2 = Start-FileWatcher -Path $script:TestDir -Filter "*.log" -ErrorAction Stop $result = Get-FileWatcher $result.Count | Should -BeGreaterOrEqual 2 Stop-AllFileWatchers } It "Should return watcher with correct properties" { $watcher = Start-FileWatcher -Path $script:TestDir -Filter "*.txt" -ErrorAction Stop $result = Get-FileWatcher | Where-Object { $_.Id -eq $watcher.Id } $result | Should -Not -BeNullOrEmpty $result.Filter | Should -Be "*.txt" Stop-FileWatcher -Id $watcher.Id } It "Should update list when watcher is stopped" { $watcher = Start-FileWatcher -Path $script:TestDir -ErrorAction Stop $before = @(Get-FileWatcher).Count Stop-FileWatcher -Id $watcher.Id Start-Sleep -Milliseconds 100 $after = @(Get-FileWatcher).Count $after | Should -Be ($before - 1) } } Context "Stop-FileWatcher Tests" { It "Should stop watcher by Id" { $watcher = Start-FileWatcher -Path $script:TestDir -ErrorAction Stop $result = Stop-FileWatcher -Id $watcher.Id $result.Status | Should -Be "Stopped" } It "Should stop watcher by Path" { $watcher = Start-FileWatcher -Path $script:TestDir -ErrorAction Stop $result = Stop-FileWatcher -Path $script:TestDir $result.Status | Should -Be "Stopped" } It "Should throw error for non-existent Id" { { Stop-FileWatcher -Id "NonExistentId_12345" -ErrorAction Stop } | Should -Throw } It "Should throw error for non-existent Path" { { Stop-FileWatcher -Path "C:\NonExistentPath_12345" -ErrorAction Stop } | Should -Throw } } Context "Stop-AllFileWatchers Tests" { It "Should stop all active watchers" { Start-FileWatcher -Path $script:TestDir -Filter "*.txt" -ErrorAction Stop | Out-Null Start-FileWatcher -Path $script:TestDir -Filter "*.log" -ErrorAction Stop | Out-Null $result = Stop-AllFileWatchers $result.Count | Should -BeGreaterOrEqual 2 } It "Should return zero count when no watchers active" { Stop-AllFileWatchers -ErrorAction SilentlyContinue $result = Stop-AllFileWatchers $result.Count | Should -Be 0 } } Context "Integration Tests" { It "Should handle multiple watchers on same path" { Start-FileWatcher -Path $script:TestDir -Filter "*.txt" -ErrorAction Stop | Out-Null Start-FileWatcher -Path $script:TestDir -Filter "*.log" -ErrorAction Stop | Out-Null $all = Get-FileWatcher $all.Count | Should -BeGreaterOrEqual 2 Stop-AllFileWatchers } It "Should handle IncludeSubdirectories flag" { $watcher = Start-FileWatcher -Path $script:TestDir -Filter "*.txt" -IncludeSubdirectories -ErrorAction Stop $watcher.IncludeSubdirectories | Should -Be $true Stop-FileWatcher -Id $watcher.Id } It "Should create watcher with all ChangeType options" { $watcher = Start-FileWatcher -Path $script:TestDir -ChangeType Created, Changed, Deleted, Renamed -ErrorAction Stop $watcher.ChangeType.Count | Should -Be 4 Stop-FileWatcher -Id $watcher.Id } } Context "Error Handling" { It "Should handle invalid path gracefully" { { Start-FileWatcher -Path "C:\" -ErrorAction Stop } | Should -Not -Throw } It "Should handle module reload correctly" { $watcher = Start-FileWatcher -Path $script:TestDir -ErrorAction Stop $reloadPath = if ($PSScriptRoot) { Join-Path $PSScriptRoot "..\PSWatchdog.psm1" } else { Join-Path $PSCommandPath "..\PSWatchdog.psm1" } Import-Module $reloadPath -Force Stop-FileWatcher -Id $watcher.Id -ErrorAction SilentlyContinue } } } |