1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-15 18:40:05 +00:00

feat(windows): add Windows support Phase 4 - testing and CI

- Pester test suite for PowerShell scripts (Core, Clean, Commands)
- Go tests for TUI tools (analyze, status)
- GitHub Actions workflow for Windows CI
- Build and test automation scripts (test.ps1, build.ps1)
This commit is contained in:
Bhadra
2026-01-08 16:41:03 +05:30
parent 8a37f63bc7
commit 230ca07c7f
8 changed files with 1475 additions and 0 deletions

View File

@@ -0,0 +1,199 @@
# Mole Windows - Cleanup Module Tests
# Pester tests for lib/clean functionality
BeforeAll {
# Get the windows directory path (tests are in windows/tests/)
$script:WindowsDir = Split-Path -Parent $PSScriptRoot
$script:LibDir = Join-Path $script:WindowsDir "lib"
# Import core modules first
. "$script:LibDir\core\base.ps1"
. "$script:LibDir\core\log.ps1"
. "$script:LibDir\core\ui.ps1"
. "$script:LibDir\core\file_ops.ps1"
# Import cleanup modules
. "$script:LibDir\clean\user.ps1"
. "$script:LibDir\clean\caches.ps1"
. "$script:LibDir\clean\dev.ps1"
. "$script:LibDir\clean\apps.ps1"
. "$script:LibDir\clean\system.ps1"
# Enable dry-run mode for all tests
$env:MOLE_DRY_RUN = "1"
Set-DryRunMode -Enabled $true
}
AfterAll {
$env:MOLE_DRY_RUN = $null
Set-DryRunMode -Enabled $false
}
Describe "User Cleanup Module" {
Context "Clear-UserTempFiles" {
It "Should have Clear-UserTempFiles function" {
Get-Command Clear-UserTempFiles -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
It "Should run without error in dry-run mode" {
{ Clear-UserTempFiles } | Should -Not -Throw
}
}
Context "Clear-OldDownloads" {
It "Should have Clear-OldDownloads function" {
Get-Command Clear-OldDownloads -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Clear-RecycleBin" {
It "Should have Clear-RecycleBin function" {
Get-Command Clear-RecycleBin -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Invoke-UserCleanup" {
It "Should have main user cleanup function" {
Get-Command Invoke-UserCleanup -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
}
Describe "Cache Cleanup Module" {
Context "Browser Cache Functions" {
It "Should have Clear-BrowserCaches function" {
Get-Command Clear-BrowserCaches -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
It "Should run browser cache cleanup without error" {
{ Clear-BrowserCaches } | Should -Not -Throw
}
}
Context "Application Cache Functions" {
It "Should have Clear-AppCaches function" {
Get-Command Clear-AppCaches -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Windows Update Cache" {
It "Should have Clear-WindowsUpdateCache function" {
Get-Command Clear-WindowsUpdateCache -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Invoke-CacheCleanup" {
It "Should have main cache cleanup function" {
Get-Command Invoke-CacheCleanup -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
}
Describe "Developer Tools Cleanup Module" {
Context "Node.js Cleanup" {
It "Should have npm cache cleanup function" {
Get-Command Clear-NpmCache -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Python Cleanup" {
It "Should have Python cache cleanup function" {
Get-Command Clear-PythonCaches -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Go Cleanup" {
It "Should have Go cache cleanup function" {
Get-Command Clear-GoCaches -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Rust Cleanup" {
It "Should have Rust cache cleanup function" {
Get-Command Clear-RustCaches -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Docker Cleanup" {
It "Should have Docker cache cleanup function" {
Get-Command Clear-DockerCaches -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Invoke-DevToolsCleanup" {
It "Should have main dev tools cleanup function" {
Get-Command Invoke-DevToolsCleanup -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
It "Should run without error in dry-run mode" {
{ Invoke-DevToolsCleanup } | Should -Not -Throw
}
}
}
Describe "Apps Cleanup Module" {
Context "Orphan Detection" {
It "Should have Find-OrphanedAppData function" {
Get-Command Find-OrphanedAppData -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
It "Should have Clear-OrphanedAppData function" {
Get-Command Clear-OrphanedAppData -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Specific App Cleanup" {
It "Should have Clear-OfficeCache function" {
Get-Command Clear-OfficeCache -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
It "Should have Clear-AdobeData function" {
Get-Command Clear-AdobeData -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Invoke-AppCleanup" {
It "Should have main app cleanup function" {
Get-Command Invoke-AppCleanup -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
}
Describe "System Cleanup Module" {
Context "System Temp" {
It "Should have Clear-SystemTempFiles function" {
Get-Command Clear-SystemTempFiles -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Windows Logs" {
It "Should have Clear-WindowsLogs function" {
Get-Command Clear-WindowsLogs -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Windows Update Cleanup" {
It "Should have Clear-WindowsUpdateFiles function" {
Get-Command Clear-WindowsUpdateFiles -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Memory Dumps" {
It "Should have Clear-MemoryDumps function" {
Get-Command Clear-MemoryDumps -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
Context "Admin Requirements" {
It "Should check for admin when needed" {
# System cleanup should handle non-admin gracefully
{ Clear-SystemTempFiles } | Should -Not -Throw
}
}
Context "Invoke-SystemCleanup" {
It "Should have main system cleanup function" {
Get-Command Invoke-SystemCleanup -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
}

View File

@@ -0,0 +1,140 @@
# Mole Windows - Command Tests
# Pester tests for bin/ command scripts
BeforeAll {
# Get the windows directory path (tests are in windows/tests/)
$script:WindowsDir = Split-Path -Parent $PSScriptRoot
$script:BinDir = Join-Path $script:WindowsDir "bin"
}
Describe "Clean Command" {
Context "Help Display" {
It "Should show help without error" {
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\clean.ps1" -ShowHelp 2>&1
$result | Should -Not -BeNullOrEmpty
$LASTEXITCODE | Should -Be 0
}
It "Should mention dry-run in help" {
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\clean.ps1" -ShowHelp 2>&1
$result -join "`n" | Should -Match "DryRun"
}
}
Context "Dry Run Mode" {
It "Should support -DryRun parameter" {
# Just verify it starts without immediate error
$job = Start-Job -ScriptBlock {
param($binDir)
& powershell -ExecutionPolicy Bypass -File "$binDir\clean.ps1" -DryRun 2>&1
} -ArgumentList $script:BinDir
Start-Sleep -Seconds 3
Stop-Job $job -ErrorAction SilentlyContinue
Remove-Job $job -Force -ErrorAction SilentlyContinue
# If we got here without exception, test passes
$true | Should -Be $true
}
}
}
Describe "Uninstall Command" {
Context "Help Display" {
It "Should show help without error" {
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\uninstall.ps1" -ShowHelp 2>&1
$result | Should -Not -BeNullOrEmpty
$LASTEXITCODE | Should -Be 0
}
}
}
Describe "Optimize Command" {
Context "Help Display" {
It "Should show help without error" {
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\optimize.ps1" -ShowHelp 2>&1
$result | Should -Not -BeNullOrEmpty
$LASTEXITCODE | Should -Be 0
}
It "Should mention optimization options in help" {
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\optimize.ps1" -ShowHelp 2>&1
$result -join "`n" | Should -Match "DryRun|Disk|DNS"
}
}
}
Describe "Purge Command" {
Context "Help Display" {
It "Should show help without error" {
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\purge.ps1" -ShowHelp 2>&1
$result | Should -Not -BeNullOrEmpty
$LASTEXITCODE | Should -Be 0
}
It "Should list artifact types in help" {
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\purge.ps1" -ShowHelp 2>&1
$result -join "`n" | Should -Match "node_modules|vendor|venv"
}
}
}
Describe "Analyze Command" {
Context "Help Display" {
It "Should show help without error" {
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\analyze.ps1" -ShowHelp 2>&1
$result | Should -Not -BeNullOrEmpty
$LASTEXITCODE | Should -Be 0
}
It "Should mention keybindings in help" {
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\analyze.ps1" -ShowHelp 2>&1
$result -join "`n" | Should -Match "Navigate|Enter|Quit"
}
}
}
Describe "Status Command" {
Context "Help Display" {
It "Should show help without error" {
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\status.ps1" -ShowHelp 2>&1
$result | Should -Not -BeNullOrEmpty
$LASTEXITCODE | Should -Be 0
}
It "Should mention system metrics in help" {
$result = & powershell -ExecutionPolicy Bypass -File "$script:BinDir\status.ps1" -ShowHelp 2>&1
$result -join "`n" | Should -Match "CPU|Memory|Disk|health"
}
}
}
Describe "Main Entry Point" {
Context "mole.ps1" {
BeforeAll {
$script:MolePath = Join-Path $script:WindowsDir "mole.ps1"
}
It "Should show help without error" {
$result = & powershell -ExecutionPolicy Bypass -File $script:MolePath -ShowHelp 2>&1
$result | Should -Not -BeNullOrEmpty
}
It "Should show version without error" {
$result = & powershell -ExecutionPolicy Bypass -File $script:MolePath -Version 2>&1
$result | Should -Not -BeNullOrEmpty
$result -join "`n" | Should -Match "Mole|v\d+\.\d+"
}
It "Should list available commands in help" {
$result = & powershell -ExecutionPolicy Bypass -File $script:MolePath -ShowHelp 2>&1
$helpText = $result -join "`n"
$helpText | Should -Match "clean"
$helpText | Should -Match "uninstall"
$helpText | Should -Match "optimize"
$helpText | Should -Match "purge"
$helpText | Should -Match "analyze"
$helpText | Should -Match "status"
}
}
}

View File

@@ -0,0 +1,242 @@
# Mole Windows - Core Module Tests
# Pester tests for lib/core functionality
BeforeAll {
# Get the windows directory path (tests are in windows/tests/)
$script:WindowsDir = Split-Path -Parent $PSScriptRoot
$script:LibDir = Join-Path $script:WindowsDir "lib"
# Import core modules
. "$script:LibDir\core\base.ps1"
. "$script:LibDir\core\log.ps1"
. "$script:LibDir\core\ui.ps1"
. "$script:LibDir\core\file_ops.ps1"
}
Describe "Base Module" {
Context "Color Definitions" {
It "Should define color codes" {
$script:Colors | Should -Not -BeNullOrEmpty
$script:Colors.Cyan | Should -Not -BeNullOrEmpty
$script:Colors.Green | Should -Not -BeNullOrEmpty
$script:Colors.Red | Should -Not -BeNullOrEmpty
$script:Colors.NC | Should -Not -BeNullOrEmpty
}
It "Should define icon set" {
$script:Icons | Should -Not -BeNullOrEmpty
$script:Icons.Success | Should -Not -BeNullOrEmpty
$script:Icons.Error | Should -Not -BeNullOrEmpty
$script:Icons.Warning | Should -Not -BeNullOrEmpty
}
}
Context "Test-IsAdmin" {
It "Should return a boolean" {
$result = Test-IsAdmin
$result | Should -BeOfType [bool]
}
}
Context "Get-WindowsVersion" {
It "Should return version info" {
$result = Get-WindowsVersion
$result | Should -Not -BeNullOrEmpty
$result.Name | Should -Not -BeNullOrEmpty
$result.Version | Should -Not -BeNullOrEmpty
$result.Build | Should -Not -BeNullOrEmpty
}
}
Context "Get-FreeSpace" {
It "Should return free space string" {
$result = Get-FreeSpace
$result | Should -Not -BeNullOrEmpty
# Format is like "100.00GB" or "50.5MB" (no space between number and unit)
$result | Should -Match "\d+(\.\d+)?(B|KB|MB|GB|TB)"
}
It "Should accept drive parameter" {
$result = Get-FreeSpace -Drive "C:"
$result | Should -Not -BeNullOrEmpty
}
}
}
Describe "File Operations Module" {
BeforeAll {
# Create temp test directory
$script:TestDir = Join-Path $env:TEMP "mole_test_$(Get-Random)"
New-Item -ItemType Directory -Path $script:TestDir -Force | Out-Null
}
AfterAll {
# Cleanup test directory
if (Test-Path $script:TestDir) {
Remove-Item -Path $script:TestDir -Recurse -Force -ErrorAction SilentlyContinue
}
}
Context "Format-ByteSize" {
It "Should format bytes correctly" {
# Actual format: no space, uses N0/N1/N2 formatting
Format-ByteSize -Bytes 0 | Should -Be "0B"
Format-ByteSize -Bytes 1024 | Should -Be "1KB"
Format-ByteSize -Bytes 1048576 | Should -Be "1.0MB"
Format-ByteSize -Bytes 1073741824 | Should -Be "1.00GB"
}
It "Should handle large numbers" {
Format-ByteSize -Bytes 1099511627776 | Should -Be "1.00TB"
}
}
Context "Get-PathSize" {
BeforeEach {
# Create test file
$testFile = Join-Path $script:TestDir "testfile.txt"
"Hello World" | Set-Content -Path $testFile
}
It "Should return size for file" {
$testFile = Join-Path $script:TestDir "testfile.txt"
$result = Get-PathSize -Path $testFile
$result | Should -BeGreaterThan 0
}
It "Should return size for directory" {
$result = Get-PathSize -Path $script:TestDir
$result | Should -BeGreaterThan 0
}
It "Should return 0 for non-existent path" {
$result = Get-PathSize -Path "C:\NonExistent\Path\12345"
$result | Should -Be 0
}
}
Context "Test-ProtectedPath" {
It "Should protect Windows directory" {
Test-ProtectedPath -Path "C:\Windows" | Should -Be $true
Test-ProtectedPath -Path "C:\Windows\System32" | Should -Be $true
}
It "Should protect Windows Defender paths" {
Test-ProtectedPath -Path "C:\Program Files\Windows Defender" | Should -Be $true
Test-ProtectedPath -Path "C:\ProgramData\Microsoft\Windows Defender" | Should -Be $true
}
It "Should not protect temp directories" {
Test-ProtectedPath -Path $env:TEMP | Should -Be $false
}
}
Context "Test-SafePath" {
It "Should return false for protected paths" {
Test-SafePath -Path "C:\Windows" | Should -Be $false
Test-SafePath -Path "C:\Windows\System32" | Should -Be $false
}
It "Should return true for safe paths" {
Test-SafePath -Path $env:TEMP | Should -Be $true
}
It "Should return false for empty paths" {
# Test-SafePath has mandatory path parameter, so empty/null throws
# But internally it should handle empty strings gracefully
{ Test-SafePath -Path "" } | Should -Throw
}
}
Context "Remove-SafeItem" {
BeforeEach {
$script:TestFile = Join-Path $script:TestDir "safe_remove_test.txt"
"Test content" | Set-Content -Path $script:TestFile
}
It "Should remove file successfully" {
$result = Remove-SafeItem -Path $script:TestFile
$result | Should -Be $true
Test-Path $script:TestFile | Should -Be $false
}
It "Should respect DryRun mode" {
$env:MOLE_DRY_RUN = "1"
try {
# Reset the module's DryRun state
Set-DryRunMode -Enabled $true
$result = Remove-SafeItem -Path $script:TestFile
$result | Should -Be $true
Test-Path $script:TestFile | Should -Be $true # File should still exist
}
finally {
$env:MOLE_DRY_RUN = $null
Set-DryRunMode -Enabled $false
}
}
It "Should not remove protected paths" {
$result = Remove-SafeItem -Path "C:\Windows\System32"
$result | Should -Be $false
}
}
}
Describe "Logging Module" {
Context "Write-Log Functions" {
It "Should have Write-Info function" {
{ Write-Info "Test message" } | Should -Not -Throw
}
It "Should have Write-Success function" {
{ Write-Success "Test message" } | Should -Not -Throw
}
It "Should have Write-Warning function" {
# Note: The actual function is Write-Warning (conflicts with built-in)
{ Write-Warning "Test message" } | Should -Not -Throw
}
It "Should have Write-Error function" {
# Note: The actual function is Write-Error (conflicts with built-in)
{ Write-Error "Test message" } | Should -Not -Throw
}
}
Context "Section Functions" {
It "Should start and stop sections without error" {
{ Start-Section -Title "Test Section" } | Should -Not -Throw
{ Stop-Section } | Should -Not -Throw
}
}
}
Describe "UI Module" {
Context "Show-Banner" {
It "Should display banner without error" {
{ Show-Banner } | Should -Not -Throw
}
}
Context "Show-Header" {
It "Should display header without error" {
{ Show-Header -Title "Test Header" } | Should -Not -Throw
}
It "Should accept subtitle parameter" {
{ Show-Header -Title "Test" -Subtitle "Subtitle" } | Should -Not -Throw
}
}
Context "Show-Summary" {
It "Should display summary without error" {
{ Show-Summary -SizeBytes 1024 -ItemCount 5 } | Should -Not -Throw
}
}
Context "Read-Confirmation" {
It "Should have Read-Confirmation function" {
Get-Command Read-Confirmation -ErrorAction SilentlyContinue | Should -Not -BeNullOrEmpty
}
}
}