Tests/Test-O365MailboxUsage-Manual.ps1

<#
.SYNOPSIS
    Manual integration tests for Get-O365MailboxUsage function
 
.DESCRIPTION
    This script provides manual test scenarios that can be run against a real Exchange Online environment
    to verify the Get-O365MailboxUsage function works correctly with actual data.
 
.NOTES
    Prerequisites:
    1. Install ExchangeOnlineManagement module: Install-Module -Name ExchangeOnlineManagement
    2. Connect to Exchange Online: Connect-ExchangeOnline
    3. Ensure you have appropriate permissions to read mailbox statistics
 
.EXAMPLE
    .\Test-O365MailboxUsage-Manual.ps1
    Runs all manual test scenarios
#>


#Requires -Module ExchangeOnlineManagement

param(
    [Parameter(HelpMessage = "Test user email address for single user tests")]
    [string]$TestUserEmail = "",
    
    [Parameter(HelpMessage = "Run tests that require all mailboxes (may take a long time)")]
    [switch]$IncludeAllMailboxTests,
    
    [Parameter(HelpMessage = "Show verbose output during testing")]
    [switch]$Verbose
)

# Import the function to test
$functionPath = Join-Path $PSScriptRoot "..\Public\Get-O365MailboxUsage.ps1"
if (-not (Test-Path $functionPath)) {
    Write-Error "Cannot find Get-O365MailboxUsage.ps1 at: $functionPath"
    exit 1
}

Write-Host "Loading Get-O365MailboxUsage function..." -ForegroundColor Green
. $functionPath

# Test helper functions
function Write-TestHeader {
    param([string]$TestName)
    Write-Host "`n" + "="*60 -ForegroundColor Yellow
    Write-Host "TEST: $TestName" -ForegroundColor Yellow
    Write-Host "="*60 -ForegroundColor Yellow
}

function Write-TestResult {
    param(
        [string]$TestName,
        [bool]$Passed,
        [string]$Details = ""
    )
    
    $status = if ($Passed) { "PASS" } else { "FAIL" }
    $color = if ($Passed) { "Green" } else { "Red" }
    
    Write-Host "[$status] $TestName" -ForegroundColor $color
    if ($Details) {
        Write-Host " Details: $Details" -ForegroundColor Gray
    }
}

function Test-FunctionExists {
    Write-TestHeader "Function Availability Test"
    
    try {
        $command = Get-Command Get-O365MailboxUsage -ErrorAction Stop
        Write-TestResult "Function Get-O365MailboxUsage exists" $true "Found in module: $($command.ModuleName)"
        return $true
    }
    catch {
        Write-TestResult "Function Get-O365MailboxUsage exists" $false $_.Exception.Message
        return $false
    }
}

function Test-ExchangeConnection {
    Write-TestHeader "Exchange Online Connection Test"
    
    try {
        $connectionInfo = Get-ConnectionInformation -ErrorAction Stop
        if ($connectionInfo) {
            Write-TestResult "Exchange Online connection" $true "Connected to: $($connectionInfo.Name)"
            return $true
        } else {
            Write-TestResult "Exchange Online connection" $false "No active connection found"
            return $false
        }
    }
    catch {
        Write-TestResult "Exchange Online connection" $false $_.Exception.Message
        Write-Host " Tip: Run Connect-ExchangeOnline first" -ForegroundColor Cyan
        return $false
    }
}

function Test-ParameterValidation {
    Write-TestHeader "Parameter Validation Tests"
    
    # Test valid SortBy parameters
    $validSortBy = @("PercentFull", "UsedSpaceGB", "TotalQuotaGB", "DisplayName")
    $allPassed = $true
    
    foreach ($sortBy in $validSortBy) {
        try {
            $null = Get-O365MailboxUsage -SortBy $sortBy -WhatIf -ErrorAction Stop
            Write-TestResult "Valid SortBy parameter: $sortBy" $true
        }
        catch {
            Write-TestResult "Valid SortBy parameter: $sortBy" $false $_.Exception.Message
            $allPassed = $false
        }
    }
    
    # Test invalid SortBy parameter
    try {
        $null = Get-O365MailboxUsage -SortBy "InvalidSort" -ErrorAction Stop
        Write-TestResult "Invalid SortBy parameter rejection" $false "Should have thrown an error"
        $allPassed = $false
    }
    catch {
        Write-TestResult "Invalid SortBy parameter rejection" $true "Correctly rejected invalid parameter"
    }
    
    return $allPassed
}

function Test-SingleUserProcessing {
    param([string]$UserEmail)
    
    Write-TestHeader "Single User Processing Test"
    
    if (-not $UserEmail) {
        Write-TestResult "Single user test" $false "No test user email provided. Use -TestUserEmail parameter."
        return $false
    }
    
    try {
        Write-Host "Testing with user: $UserEmail" -ForegroundColor Cyan
        
        $result = Get-O365MailboxUsage -UserPrincipalName $UserEmail -Verbose:$Verbose
        
        if ($result) {
            Write-TestResult "Single user retrieval" $true "Retrieved data for: $($result.DisplayName)"
            
            # Validate required properties
            $requiredProps = @("DisplayName", "UserPrincipalName", "UsedSpaceGB", "TotalQuotaGB", "PercentFull")
            $propTest = $true
            
            foreach ($prop in $requiredProps) {
                if ($null -eq $result.$prop) {
                    Write-TestResult "Property '$prop' exists" $false "Property is null or missing"
                    $propTest = $false
                } else {
                    Write-TestResult "Property '$prop' exists" $true "Value: $($result.$prop)"
                }
            }
            
            # Validate percentage calculation
            if ($result.TotalQuotaGB -gt 0) {
                $expectedPercent = [math]::Round(($result.UsedSpaceGB / $result.TotalQuotaGB) * 100, 1)
                $percentTest = $result.PercentFull -eq $expectedPercent
                Write-TestResult "Percentage calculation accuracy" $percentTest "Expected: $expectedPercent, Got: $($result.PercentFull)"
            }
            
            return $propTest
        } else {
            Write-TestResult "Single user retrieval" $false "No data returned"
            return $false
        }
    }
    catch {
        Write-TestResult "Single user retrieval" $false $_.Exception.Message
        return $false
    }
}

function Test-PipelineInput {
    param([string]$UserEmail)
    
    Write-TestHeader "Pipeline Input Test"
    
    if (-not $UserEmail) {
        Write-TestResult "Pipeline input test" $false "No test user email provided"
        return $false
    }
    
    try {
        Write-Host "Testing pipeline input with user: $UserEmail" -ForegroundColor Cyan
        
        $result = $UserEmail | Get-O365MailboxUsage -Verbose:$Verbose
        
        if ($result -and $result.UserPrincipalName -eq $UserEmail) {
            Write-TestResult "Pipeline input processing" $true "Successfully processed pipeline input"
            return $true
        } else {
            Write-TestResult "Pipeline input processing" $false "Pipeline input not processed correctly"
            return $false
        }
    }
    catch {
        Write-TestResult "Pipeline input processing" $false $_.Exception.Message
        return $false
    }
}

function Test-SortingFunctionality {
    param([string]$UserEmail)
    
    Write-TestHeader "Sorting Functionality Test"
    
    if (-not $UserEmail) {
        Write-Host "Limited sorting test without test user email" -ForegroundColor Yellow
    }
    
    # Test with small mailbox sample
    try {
        Write-Host "Getting sample mailboxes for sorting test..." -ForegroundColor Cyan
        
        # Get a few mailboxes to test sorting
        $sampleMailboxes = Get-Mailbox -ResultSize 3 -WarningAction SilentlyContinue
        
        if ($sampleMailboxes.Count -ge 2) {
            $userList = $sampleMailboxes | Select-Object -First 2 | ForEach-Object { $_.PrimarySmtpAddress }
            
            # Test different sort options
            $sortTests = @("PercentFull", "UsedSpaceGB", "TotalQuotaGB", "DisplayName")
            $allPassed = $true
            
            foreach ($sortBy in $sortTests) {
                try {
                    $results = $userList | Get-O365MailboxUsage -SortBy $sortBy -Verbose:$Verbose
                    
                    if ($results.Count -eq $userList.Count) {
                        Write-TestResult "Sort by $sortBy" $true "Returned $($results.Count) results"
                        
                        # Verify sort order for PercentFull (should be descending)
                        if ($sortBy -eq "PercentFull" -and $results.Count -ge 2) {
                            $sortedCorrectly = $results[0].PercentFull -ge $results[1].PercentFull
                            Write-TestResult "Sort order validation for $sortBy" $sortedCorrectly "First: $($results[0].PercentFull)%, Second: $($results[1].PercentFull)%"
                        }
                    } else {
                        Write-TestResult "Sort by $sortBy" $false "Expected $($userList.Count) results, got $($results.Count)"
                        $allPassed = $false
                    }
                }
                catch {
                    Write-TestResult "Sort by $sortBy" $false $_.Exception.Message
                    $allPassed = $false
                }
            }
            
            return $allPassed
        } else {
            Write-TestResult "Sorting test" $false "Insufficient mailboxes for sorting test"
            return $false
        }
    }
    catch {
        Write-TestResult "Sorting test" $false $_.Exception.Message
        return $false
    }
}

function Test-ArchiveFunctionality {
    param([string]$UserEmail)
    
    Write-TestHeader "Archive Functionality Test"
    
    if (-not $UserEmail) {
        Write-TestResult "Archive test" $false "No test user email provided"
        return $false
    }
    
    try {
        Write-Host "Testing archive functionality with user: $UserEmail" -ForegroundColor Cyan
        
        # First check if user has archive enabled
        $mailbox = Get-Mailbox -Identity $UserEmail
        
        if ($mailbox.ArchiveStatus -eq "Active") {
            Write-Host "User has archive enabled, testing archive retrieval..." -ForegroundColor Cyan
            
            $result = Get-O365MailboxUsage -UserPrincipalName $UserEmail -IncludeArchive -Verbose:$Verbose
            
            $archiveProps = @("ArchiveUsedSpaceGB", "ArchiveTotalQuotaGB", "ArchivePercentFull", "ArchiveItemCount")
            $archiveTest = $true
            
            foreach ($prop in $archiveProps) {
                if ($null -eq $result.$prop) {
                    Write-TestResult "Archive property '$prop'" $false "Property missing or null"
                    $archiveTest = $false
                } else {
                    Write-TestResult "Archive property '$prop'" $true "Value: $($result.$prop)"
                }
            }
            
            return $archiveTest
        } else {
            Write-TestResult "Archive test" $true "User has no archive (testing skipped archive correctly)"
            return $true
        }
    }
    catch {
        Write-TestResult "Archive test" $false $_.Exception.Message
        return $false
    }
}

function Test-AllMailboxes {
    Write-TestHeader "All Mailboxes Test (WARNING: This may take a long time!)"
    
    try {
        Write-Host "Retrieving all mailboxes (this may take several minutes)..." -ForegroundColor Yellow
        
        $startTime = Get-Date
        $results = Get-O365MailboxUsage -Verbose:$Verbose
        $endTime = Get-Date
        
        $duration = $endTime - $startTime
        
        if ($results -and $results.Count -gt 0) {
            Write-TestResult "All mailboxes retrieval" $true "Retrieved $($results.Count) mailboxes in $($duration.TotalSeconds) seconds"
            
            # Test that results are sorted by PercentFull (descending)
            if ($results.Count -ge 2) {
                $sortTest = $results[0].PercentFull -ge $results[1].PercentFull
                Write-TestResult "Default sort order" $sortTest "First: $($results[0].PercentFull)%, Second: $($results[1].PercentFull)%"
            }
            
            # Show top 5 most full mailboxes
            Write-Host "`nTop 5 Most Full Mailboxes:" -ForegroundColor Cyan
            $results | Select-Object -First 5 | Format-Table DisplayName, UserPrincipalName, UsedSpaceGB, TotalQuotaGB, PercentFull -AutoSize
            
            return $true
        } else {
            Write-TestResult "All mailboxes retrieval" $false "No results returned"
            return $false
        }
    }
    catch {
        Write-TestResult "All mailboxes retrieval" $false $_.Exception.Message
        return $false
    }
}

# Main test execution
Write-Host "Starting Get-O365MailboxUsage Manual Integration Tests" -ForegroundColor Green
Write-Host "DateTime: $(Get-Date)" -ForegroundColor Gray

# Track test results
$testResults = @{}

# Run tests
$testResults["FunctionExists"] = Test-FunctionExists
$testResults["ExchangeConnection"] = Test-ExchangeConnection

# Only continue if basic prerequisites are met
if ($testResults["FunctionExists"] -and $testResults["ExchangeConnection"]) {
    $testResults["ParameterValidation"] = Test-ParameterValidation
    $testResults["SingleUserProcessing"] = Test-SingleUserProcessing -UserEmail $TestUserEmail
    $testResults["PipelineInput"] = Test-PipelineInput -UserEmail $TestUserEmail
    $testResults["SortingFunctionality"] = Test-SortingFunctionality -UserEmail $TestUserEmail
    $testResults["ArchiveFunctionality"] = Test-ArchiveFunctionality -UserEmail $TestUserEmail
    
    if ($IncludeAllMailboxTests) {
        $testResults["AllMailboxes"] = Test-AllMailboxes
    } else {
        Write-Host "`nSkipping all mailboxes test (use -IncludeAllMailboxTests to run)" -ForegroundColor Yellow
    }
} else {
    Write-Host "`nSkipping remaining tests due to prerequisite failures" -ForegroundColor Red
}

# Summary
Write-TestHeader "Test Summary"
$passedTests = ($testResults.Values | Where-Object { $_ -eq $true }).Count
$totalTests = $testResults.Count

Write-Host "Tests Passed: $passedTests / $totalTests" -ForegroundColor $(if ($passedTests -eq $totalTests) { "Green" } else { "Yellow" })

foreach ($test in $testResults.GetEnumerator()) {
    $status = if ($test.Value) { "PASS" } else { "FAIL" }
    $color = if ($test.Value) { "Green" } else { "Red" }
    Write-Host " [$status] $($test.Key)" -ForegroundColor $color
}

if ($passedTests -eq $totalTests) {
    Write-Host "`nAll tests passed! The function appears to be working correctly." -ForegroundColor Green
} else {
    Write-Host "`nSome tests failed. Please review the output above for details." -ForegroundColor Yellow
}

Write-Host "`nTesting completed at $(Get-Date)" -ForegroundColor Gray