Tests/M365-SecurityBaseline.Tests.ps1
|
BeforeAll { $modulePath = Split-Path -Parent $PSScriptRoot Import-Module "$modulePath\M365-SecurityBaseline.psd1" -Force } Describe 'M365-SecurityBaseline Module' { Context 'Module Loading' { It 'Should import without errors' { { Import-Module "$PSScriptRoot\..\M365-SecurityBaseline.psd1" -Force } | Should -Not -Throw } It 'Should export exactly 5 public functions' { $commands = Get-Command -Module M365-SecurityBaseline $commands.Count | Should -Be 5 } It 'Should export all expected functions' { $expected = @('Invoke-M365SecurityAudit', 'Get-MFAStatus', 'Get-MailboxForwardingRules', 'Get-ConditionalAccessReview', 'Get-GuestAccessReport') foreach ($func in $expected) { Get-Command -Module M365-SecurityBaseline -Name $func | Should -Not -BeNullOrEmpty } } It 'Should not export private functions' { { Get-Command -Module M365-SecurityBaseline -Name _New-M365AuditHtml -ErrorAction Stop } | Should -Throw } } Context 'Get-MFAStatus Parameter Validation' { It 'Should validate UserType to All, Member, or Guest' { $validateSet = (Get-Command Get-MFAStatus).Parameters['UserType'].Attributes | Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] } $validateSet.ValidValues | Should -Contain 'All' $validateSet.ValidValues | Should -Contain 'Member' $validateSet.ValidValues | Should -Contain 'Guest' } It 'Should default UserType to Member' { # Verify the parameter exists and has a default (Get-Command Get-MFAStatus).Parameters.ContainsKey('UserType') | Should -BeTrue } It 'Should have IncludeDisabled switch' { (Get-Command Get-MFAStatus).Parameters['IncludeDisabled'].SwitchParameter | Should -BeTrue } } Context 'Get-MailboxForwardingRules Parameter Validation' { It 'Should have ExternalOnly switch' { (Get-Command Get-MailboxForwardingRules).Parameters['ExternalOnly'].SwitchParameter | Should -BeTrue } } Context 'Get-ConditionalAccessReview Parameter Validation' { It 'Should have IncludeDisabled switch' { (Get-Command Get-ConditionalAccessReview).Parameters['IncludeDisabled'].SwitchParameter | Should -BeTrue } } Context 'Get-GuestAccessReport Parameter Validation' { It 'Should have DaysInactive parameter' { (Get-Command Get-GuestAccessReport).Parameters.ContainsKey('DaysInactive') | Should -BeTrue } It 'Should have UnredeemedOnly switch' { (Get-Command Get-GuestAccessReport).Parameters['UnredeemedOnly'].SwitchParameter | Should -BeTrue } } Context 'Invoke-M365SecurityAudit Parameter Validation' { It 'Should have SkipConnect switch' { (Get-Command Invoke-M365SecurityAudit).Parameters['SkipConnect'].SwitchParameter | Should -BeTrue } It 'Should default OutputPath to .\Reports' { (Get-Command Invoke-M365SecurityAudit).Parameters.ContainsKey('OutputPath') | Should -BeTrue } } Context 'HTML Report Generation' { It 'Should generate valid HTML with all sections' { $mockResults = @{ MFA = @( [PSCustomObject]@{ DisplayName = 'User1'; UserPrincipalName = 'user1@contoso.com'; MFAEnabled = $true; LastSignIn = (Get-Date) } [PSCustomObject]@{ DisplayName = 'User2'; UserPrincipalName = 'user2@contoso.com'; MFAEnabled = $false; LastSignIn = (Get-Date) } ) Forwarding = @( [PSCustomObject]@{ Mailbox = 'user1@contoso.com'; RuleType = 'InboxRule'; ForwardTo = 'external@gmail.com'; IsExternal = $true; RuleName = 'FWD' } ) ConditionalAccess = @( [PSCustomObject]@{ PolicyName = 'Require MFA'; State = 'enabled'; TargetUsers = 'All Users'; TargetApps = 'All Apps'; RequiresMFA = $true; BlocksLegacy = $false } ) Guests = @( [PSCustomObject]@{ DisplayName = 'Guest1'; Email = 'guest@vendor.com'; InviteState = 'Accepted'; LastSignIn = (Get-Date).AddDays(-100); StaleGuest = $true; Groups = 'Project-A' } ) } $html = & (Get-Module M365-SecurityBaseline) { param($results) _New-M365AuditHtml -AuditResults $results -TenantName 'Contoso Corp' } $mockResults $html | Should -Match '<!DOCTYPE html>' $html | Should -Match 'Microsoft 365 Security Baseline Audit' $html | Should -Match 'Contoso Corp' $html | Should -Match 'MFA Adoption' $html | Should -Match 'Forwarding' $html | Should -Match 'Conditional Access' $html | Should -Match 'Guest Accounts' } It 'Should calculate MFA percentage correctly' { $mockResults = @{ MFA = @( [PSCustomObject]@{ DisplayName = 'A'; UserPrincipalName = 'a@c.com'; MFAEnabled = $true; LastSignIn = $null } [PSCustomObject]@{ DisplayName = 'B'; UserPrincipalName = 'b@c.com'; MFAEnabled = $true; LastSignIn = $null } [PSCustomObject]@{ DisplayName = 'C'; UserPrincipalName = 'c@c.com'; MFAEnabled = $true; LastSignIn = $null } [PSCustomObject]@{ DisplayName = 'D'; UserPrincipalName = 'd@c.com'; MFAEnabled = $false; LastSignIn = $null } ) Forwarding = @() ConditionalAccess = @() Guests = @() } $html = & (Get-Module M365-SecurityBaseline) { param($results) _New-M365AuditHtml -AuditResults $results -TenantName 'Test' } $mockResults # 3 out of 4 = 75% $html | Should -Match '75%' } } } |