Tests/Unit/Clear-SPCRecycleBin.Tests.ps1
|
#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0.0' } BeforeAll { . (Join-Path $PSScriptRoot '../../Private/Test-SPCConnection.ps1') . (Join-Path $PSScriptRoot '../../Private/LicenseManager.ps1') . (Join-Path $PSScriptRoot '../../Private/Connect-SPCSiteInternal.ps1') . (Join-Path $PSScriptRoot '../../Private/Test-SPCPurviewHoldInternal.ps1') . (Join-Path $PSScriptRoot '../../Private/Write-SPCAuditLogInternal.ps1') . (Join-Path $PSScriptRoot '../../Private/Invoke-SPCSafeRecycleBinPurgeInternal.ps1') . (Join-Path $PSScriptRoot '../../Public/Remediate/Clear-SPCRecycleBin.ps1') $script:SPCContext = [PSCustomObject]@{ TenantName = 'contoso' AuthMethod = 'Interactive' PnPContext = [PSCustomObject]@{} GraphAccessToken = 'mock_token' } } Describe 'Clear-SPCRecycleBin Unit Tests' -Tag 'Remediate', 'Storage' { Context 'AC-08: DryRun and WhatIf Simulation' { It 'AC-08: Should calculate potential freed storage without deleting items when -DryRun is used' { Mock Test-SPCPurviewHoldInternal { [PSCustomObject]@{ IsHoldActive = $false; HoldType = 'None' } } Mock Invoke-SPCSafeRecycleBinPurgeInternal { [PSCustomObject]@{ DeletedCount = 25; StorageFreedMB = 1024.0; ErrorCount = 0 } } $result = Clear-SPCRecycleBin -SiteUrl 'https://contoso.sharepoint.com/sites/hr' -DryRun $result.IsDryRun | Should -BeTrue $result.Status | Should -Be 'Simulated' $result.StorageFreedMB | Should -Be 1024.0 $result.MonthlyCostSavedUSD | Should -Be 0.20 } } Context 'AC-10: Actual Purge with Pro License' { It 'AC-10: Should perform actual purge and call Invoke-SPCSafeRecycleBinPurgeInternal when licensed' { Mock Assert-SPCProLicense {} Mock Test-SPCPurviewHoldInternal { [PSCustomObject]@{ IsHoldActive = $false; HoldType = 'None' } } Mock Invoke-SPCSafeRecycleBinPurgeInternal { param($SiteUrl, $OlderThanDays, $Stage, $DryRun, $AuditLogPath) $Stage | Should -Be '2ndStage' $DryRun | Should -BeFalse [PSCustomObject]@{ DeletedCount = 50; StorageFreedMB = 2048.0; ErrorCount = 0 } } $result = Clear-SPCRecycleBin -SiteUrl 'https://contoso.sharepoint.com/sites/ops' -SecondStageOnly -OlderThanDays 30 -Force $result.IsDryRun | Should -BeFalse $result.Status | Should -Be 'Success' $result.StorageFreedMB | Should -Be 2048.0 } } Context 'AC-11: Purview Hold Immunity' { It 'AC-11: Should skip purge and log SKIPPED_COMPLIANCE_HOLD when Purview Hold is active' { Mock Assert-SPCProLicense {} Mock Test-SPCPurviewHoldInternal { [PSCustomObject]@{ IsHoldActive = $true; HoldType = 'PurviewRetentionPolicy' } } Mock Write-SPCAuditLogInternal { param($ExecutionStatus) $ExecutionStatus | Should -Be 'SKIPPED_COMPLIANCE_HOLD' } Mock Invoke-SPCSafeRecycleBinPurgeInternal { throw "Should not be called" } $result = Clear-SPCRecycleBin -SiteUrl 'https://contoso.sharepoint.com/sites/heldsite' -Force $result | Should -BeNullOrEmpty } } Context 'ERR-LIC-003: License Gate Protection' { It 'Throws license error when executed in Free Tier without -DryRun' { Mock Assert-SPCProLicense { throw "ERR-LIC-003: Clear-SPCRecycleBin requires a Pro or Consultant license." } { Clear-SPCRecycleBin -SiteUrl 'https://contoso.sharepoint.com/sites/unlic' -Force } | Should -Throw -ExpectedMessage "*ERR-LIC-*" } } } |