Tests/Intune-ComplianceReport.Tests.ps1
|
BeforeAll { $modulePath = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) $moduleName = 'Intune-ComplianceReport' $manifestPath = Join-Path $modulePath "$moduleName\$moduleName.psd1" if (Get-Module $moduleName) { Remove-Module $moduleName -Force } Import-Module $manifestPath -Force } Describe 'Module: Intune-ComplianceReport' { Context 'Module Loading' { It 'Imports without errors' { { Import-Module $manifestPath -Force } | Should -Not -Throw } It 'Exports exactly 5 public functions' { $exported = (Get-Module $moduleName).ExportedFunctions.Keys $exported.Count | Should -Be 5 } It 'Exports Invoke-IntuneComplianceAudit' { Get-Command -Module $moduleName -Name 'Invoke-IntuneComplianceAudit' | Should -Not -BeNullOrEmpty } It 'Exports Get-IntuneDeviceComplianceReport' { Get-Command -Module $moduleName -Name 'Get-IntuneDeviceComplianceReport' | Should -Not -BeNullOrEmpty } It 'Exports Get-IntuneAppInventory' { Get-Command -Module $moduleName -Name 'Get-IntuneAppInventory' | Should -Not -BeNullOrEmpty } It 'Exports Get-IntunePolicyAssignmentReview' { Get-Command -Module $moduleName -Name 'Get-IntunePolicyAssignmentReview' | Should -Not -BeNullOrEmpty } It 'Exports Get-IntuneAutopilotStatus' { Get-Command -Module $moduleName -Name 'Get-IntuneAutopilotStatus' | Should -Not -BeNullOrEmpty } It 'Does not export private functions' { $exported = (Get-Module $moduleName).ExportedFunctions.Keys $exported | Should -Not -Contain 'Test-GraphConnection' $exported | Should -Not -Contain 'New-HtmlDashboard' } } Context 'Parameter Validation' { It 'Invoke-IntuneComplianceAudit has OutputPath parameter' { (Get-Command Invoke-IntuneComplianceAudit).Parameters.Keys | Should -Contain 'OutputPath' } It 'Invoke-IntuneComplianceAudit has StaleDays with ValidateRange 1-180' { $param = (Get-Command Invoke-IntuneComplianceAudit).Parameters['StaleDays'] $param | Should -Not -BeNullOrEmpty $rangeAttr = $param.Attributes | Where-Object { $_ -is [System.Management.Automation.ValidateRangeAttribute] } $rangeAttr.MinRange | Should -Be 1 $rangeAttr.MaxRange | Should -Be 180 } It 'Invoke-IntuneComplianceAudit has SkipAutopilot switch' { $param = (Get-Command Invoke-IntuneComplianceAudit).Parameters['SkipAutopilot'] $param.SwitchParameter | Should -Be $true } It 'Get-IntuneDeviceComplianceReport has OSFilter with ValidateSet' { $param = (Get-Command Get-IntuneDeviceComplianceReport).Parameters['OSFilter'] $validateSet = $param.Attributes | Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] } $validateSet.ValidValues | Should -Contain 'Windows' $validateSet.ValidValues | Should -Contain 'iOS' $validateSet.ValidValues | Should -Contain 'Android' $validateSet.ValidValues | Should -Contain 'macOS' $validateSet.ValidValues | Should -Contain 'All' } It 'Get-IntuneAppInventory has FailureThresholdPercent parameter' { $param = (Get-Command Get-IntuneAppInventory).Parameters['FailureThresholdPercent'] $param | Should -Not -BeNullOrEmpty $rangeAttr = $param.Attributes | Where-Object { $_ -is [System.Management.Automation.ValidateRangeAttribute] } $rangeAttr.MinRange | Should -Be 1 $rangeAttr.MaxRange | Should -Be 100 } It 'Get-IntuneAppInventory has IncludeStore switch' { $param = (Get-Command Get-IntuneAppInventory).Parameters['IncludeStore'] $param.SwitchParameter | Should -Be $true } } Context 'Mock-Based Execution' { It 'Get-IntuneDeviceComplianceReport flags non-compliant and stale devices' { Mock -ModuleName $moduleName Get-MgContext { @{ Scopes = @('DeviceManagementManagedDevices.Read.All'); Account = 'test@contoso.com'; TenantId = 'test-tenant' } } Mock -ModuleName $moduleName Get-MgDeviceManagementManagedDevice { @( [PSCustomObject]@{ Id = 'dev-001'; DeviceName = 'DESKTOP-GOOD'; UserPrincipalName = 'alice@contoso.com' OperatingSystem = 'Windows'; OsVersion = '10.0.22631.1234' ComplianceState = 'compliant'; IsEncrypted = $true LastSyncDateTime = (Get-Date).AddDays(-2); EnrolledDateTime = (Get-Date).AddMonths(-6) OwnerType = 'company'; ManagementAgent = 'mdm' Model = 'ThinkPad T14'; Manufacturer = 'Lenovo'; SerialNumber = 'SN001' }, [PSCustomObject]@{ Id = 'dev-002'; DeviceName = 'DESKTOP-BAD'; UserPrincipalName = 'bob@contoso.com' OperatingSystem = 'Windows'; OsVersion = '10.0.19045.1234' ComplianceState = 'noncompliant'; IsEncrypted = $false LastSyncDateTime = (Get-Date).AddDays(-60); EnrolledDateTime = (Get-Date).AddMonths(-12) OwnerType = 'company'; ManagementAgent = 'mdm' Model = 'OptiPlex 7090'; Manufacturer = 'Dell'; SerialNumber = 'SN002' } ) } $result = Get-IntuneDeviceComplianceReport -StaleDays 30 $result.Count | Should -Be 2 ($result | Where-Object { $_.Finding -eq 'OK' }).Count | Should -Be 1 ($result | Where-Object { $_.Finding -match 'NON-COMPLIANT' }).Count | Should -Be 1 ($result | Where-Object { $_.Finding -match 'NOT ENCRYPTED' }).Count | Should -Be 1 ($result | Where-Object { $_.Finding -match 'STALE' }).Count | Should -Be 1 } It 'Get-IntunePolicyAssignmentReview flags unassigned policies' { Mock -ModuleName $moduleName Get-MgContext { @{ Scopes = @('DeviceManagementConfiguration.Read.All'); Account = 'test@contoso.com'; TenantId = 'test-tenant' } } Mock -ModuleName $moduleName Get-MgDeviceManagementDeviceConfiguration { @( [PSCustomObject]@{ Id = 'prof-001'; DisplayName = 'Assigned Profile' '@odata.type' = '#microsoft.graph.windows10GeneralConfiguration' LastModifiedDateTime = (Get-Date).AddDays(-30); Version = 1 AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.windows10GeneralConfiguration' } }, [PSCustomObject]@{ Id = 'prof-002'; DisplayName = 'Orphaned Profile' '@odata.type' = '#microsoft.graph.windows10GeneralConfiguration' LastModifiedDateTime = (Get-Date).AddDays(-400); Version = 1 AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.windows10GeneralConfiguration' } } ) } Mock -ModuleName $moduleName Get-MgDeviceManagementDeviceConfigurationAssignment { param($DeviceConfigurationId) if ($DeviceConfigurationId -eq 'prof-001') { @([PSCustomObject]@{ Target = @{ AdditionalProperties = @{ '@odata.type' = '#microsoft.graph.groupAssignmentTarget' } } }) } else { @() } } Mock -ModuleName $moduleName Get-MgDeviceManagementDeviceConfigurationDeviceStatusOverview { [PSCustomObject]@{ ErrorCount = 0; ConflictCount = 0 } } Mock -ModuleName $moduleName Get-MgDeviceManagementDeviceCompliancePolicy { @() } $result = Get-IntunePolicyAssignmentReview ($result | Where-Object { $_.Finding -match 'UNASSIGNED' }).Count | Should -Be 1 ($result | Where-Object { $_.Finding -match 'NOT MODIFIED' }).Count | Should -Be 1 } } Context 'HTML Report Generation' { It 'New-HtmlDashboard creates valid HTML file' { $testSections = @( @{ Title = 'Test Section' Data = @([PSCustomObject]@{ DeviceName = 'TEST-PC'; Finding = 'OK' }) Summary = '1 device tested' } ) $testFile = Join-Path $TestDrive 'test-report.html' & (Get-Module $moduleName) { New-HtmlDashboard -Sections $args[0] -OutputFile $args[1] -ReportTitle 'Test Report' } $testSections $testFile Test-Path $testFile | Should -Be $true $content = Get-Content $testFile -Raw $content | Should -Match '<title>Test Report</title>' $content | Should -Match 'Intune-ComplianceReport' $content | Should -Match 'Test Section' } } Context 'Module Manifest' { It 'Has a valid manifest' { { Test-ModuleManifest -Path $manifestPath } | Should -Not -Throw } It 'Has the correct version' { (Test-ModuleManifest -Path $manifestPath).Version | Should -Be '1.0.0' } It 'Has the correct author' { (Test-ModuleManifest -Path $manifestPath).Author | Should -Be 'Larry Roberts' } It 'Has ProjectUri set' { (Test-ModuleManifest -Path $manifestPath).ProjectUri | Should -Not -BeNullOrEmpty } It 'Has LicenseUri set' { (Test-ModuleManifest -Path $manifestPath).LicenseUri | Should -Not -BeNullOrEmpty } It 'Has relevant tags' { $tags = (Test-ModuleManifest -Path $manifestPath).Tags $tags | Should -Contain 'Intune' $tags | Should -Contain 'Compliance' } } } |