tests/Orchestrator.Tests.ps1

#Requires -Version 7.0

<#
.SYNOPSIS
Pester tests for the Start-IntuneBackup orchestrator
#>


BeforeAll {
    Import-Module "$PSScriptRoot/../IntuneBackup.psm1" -Force
    $script:token = ConvertTo-SecureString -String 'test-token' -AsPlainText -Force
}

Describe "Start-IntuneBackup" {

    BeforeEach {
        # Mock Get-ScopeTags so no real Graph calls occur
        Mock Get-ScopeTags -ModuleName IntuneBackup { return @{} }

        # Mock all 35 standard backup functions
        Mock Backup-APNs                    -ModuleName IntuneBackup {}
        Mock Backup-AppConfiguration        -ModuleName IntuneBackup {}
        Mock Backup-AppProtection           -ModuleName IntuneBackup {}
        Mock Backup-AppleEnrollmentProfiles -ModuleName IntuneBackup {}
        Mock Backup-Applications            -ModuleName IntuneBackup {}
        Mock Backup-Compliance              -ModuleName IntuneBackup {}
        Mock Backup-CompliancePartner       -ModuleName IntuneBackup {}
        Mock Backup-ComplianceScripts       -ModuleName IntuneBackup {}
        Mock Backup-ConditionalAccess       -ModuleName IntuneBackup {}
        Mock Backup-CustomAttributes        -ModuleName IntuneBackup {}
        Mock Backup-DeviceCategories        -ModuleName IntuneBackup {}
        Mock Backup-DeviceCompliance        -ModuleName IntuneBackup {}
        Mock Backup-DeviceConfigurations    -ModuleName IntuneBackup {}
        Mock Backup-DeviceManagementSettings -ModuleName IntuneBackup {}
        Mock Backup-EnrollmentConfigurations -ModuleName IntuneBackup {}
        Mock Backup-EnrollmentStatusPage    -ModuleName IntuneBackup {}
        Mock Backup-Filters                 -ModuleName IntuneBackup {}
        Mock Backup-GroupPolicyConfigurations -ModuleName IntuneBackup {}
        Mock Backup-ManagedGooglePlay       -ModuleName IntuneBackup {}
        Mock Backup-ManagementIntents       -ModuleName IntuneBackup {}
        Mock Backup-ManagementPartner       -ModuleName IntuneBackup {}
        Mock Backup-NotificationTemplates   -ModuleName IntuneBackup {}
        Mock Backup-PowerShellScripts       -ModuleName IntuneBackup {}
        Mock Backup-ProactiveRemediation    -ModuleName IntuneBackup {}
        Mock Backup-RemoteAssistancePartner -ModuleName IntuneBackup {}
        Mock Backup-ReusableSettings        -ModuleName IntuneBackup {}
        Mock Backup-Roles                   -ModuleName IntuneBackup {}
        Mock Backup-ScopeTags               -ModuleName IntuneBackup {}
        Mock Backup-SettingsCatalog         -ModuleName IntuneBackup {}
        Mock Backup-ShellScripts            -ModuleName IntuneBackup {}
        Mock Backup-VolumePurchaseProgram   -ModuleName IntuneBackup {}
        Mock Backup-WindowsDriverUpdates    -ModuleName IntuneBackup {}
        Mock Backup-WindowsEnrollmentProfiles -ModuleName IntuneBackup {}
        Mock Backup-WindowsFeatureUpdates   -ModuleName IntuneBackup {}
        Mock Backup-WindowsQualityUpdates   -ModuleName IntuneBackup {}

        # Mock the two opt-in backup functions
        Mock Backup-ActivationLock    -ModuleName IntuneBackup {}
        Mock Backup-AutopilotDevices  -ModuleName IntuneBackup {}

        # Mock the assignment report
        Mock Build-AssignmentReport   -ModuleName IntuneBackup {}
    }

    It "should throw when no token is provided" {
        $savedToken = $env:GRAPH_TOKEN
        try {
            $env:GRAPH_TOKEN = $null
            { Start-IntuneBackup -BackupPath 'TestDrive:\backup' } | Should -Throw
        }
        finally {
            $env:GRAPH_TOKEN = $savedToken
        }
    }

    It "should create BackupPath if it does not exist" {
        $newPath = "TestDrive:\newbackupdir_$([System.IO.Path]::GetRandomFileName())"
        Test-Path $newPath | Should -BeFalse
        Start-IntuneBackup -BackupPath $newPath -Token $script:token -Sequential
        Test-Path $newPath | Should -BeTrue
    }

    It "should not call Get-ScopeTags when ResolveScopeTagIds is not set" {
        Start-IntuneBackup -BackupPath 'TestDrive:\backup' -Token $script:token -Sequential
        Assert-MockCalled Get-ScopeTags -ModuleName IntuneBackup -Times 0 -Exactly
    }

    It "should call Get-ScopeTags exactly once when ResolveScopeTagIds is set" {
        Start-IntuneBackup -BackupPath 'TestDrive:\backup' -Token $script:token -Sequential -ResolveScopeTagIds
        Assert-MockCalled Get-ScopeTags -ModuleName IntuneBackup -Times 1 -Exactly
    }

    It "passes non-empty ScopeTagMap to modules when ResolveScopeTagIds is set" {
        Mock Get-ScopeTags -ModuleName IntuneBackup { return @{ '0' = 'Default' } }
        Start-IntuneBackup -BackupPath 'TestDrive:\backup' -Token $script:token -Sequential -ResolveScopeTagIds
        Assert-MockCalled Backup-Filters -ModuleName IntuneBackup -Times 1 -ParameterFilter {
            $ScopeTagMap.Count -gt 0
        }
    }

    It "passes empty ScopeTagMap to modules when ResolveScopeTagIds is not set" {
        Start-IntuneBackup -BackupPath 'TestDrive:\backup' -Token $script:token -Sequential
        Assert-MockCalled Backup-Filters -ModuleName IntuneBackup -Times 1 -ParameterFilter {
            $ScopeTagMap.Count -eq 0
        }
    }

    It "should call each standard module function" {
        Start-IntuneBackup -BackupPath 'TestDrive:\backup' -Token $script:token -Sequential
        Assert-MockCalled Backup-Filters              -ModuleName IntuneBackup -Times 1
        Assert-MockCalled Backup-Applications         -ModuleName IntuneBackup -Times 1
        Assert-MockCalled Backup-DeviceConfigurations -ModuleName IntuneBackup -Times 1
        Assert-MockCalled Backup-SettingsCatalog      -ModuleName IntuneBackup -Times 1
        Assert-MockCalled Backup-Compliance           -ModuleName IntuneBackup -Times 1
        Assert-MockCalled Build-AssignmentReport      -ModuleName IntuneBackup -Times 1
    }

    It "should not call Build-AssignmentReport when AssignmentReport is excluded" {
        Start-IntuneBackup -BackupPath 'TestDrive:\backup' -Token $script:token -Exclude @('AssignmentReport') -Sequential
        Assert-MockCalled Build-AssignmentReport -ModuleName IntuneBackup -Times 0
        Assert-MockCalled Backup-Filters         -ModuleName IntuneBackup -Times 1
    }

    It "should not call excluded module" {
        Start-IntuneBackup -BackupPath 'TestDrive:\backup' -Token $script:token -Exclude @('Filters') -Sequential
        Assert-MockCalled Backup-Filters     -ModuleName IntuneBackup -Times 0
        Assert-MockCalled Backup-Applications -ModuleName IntuneBackup -Times 1
    }

    It "should not call ActivationLock when IncludeActivationLock switch is not set" {
        Start-IntuneBackup -BackupPath 'TestDrive:\backup' -Token $script:token -Sequential
        Assert-MockCalled Backup-ActivationLock -ModuleName IntuneBackup -Times 0
    }

    It "should call ActivationLock when IncludeActivationLock switch is set" {
        Start-IntuneBackup -BackupPath 'TestDrive:\backup' -Token $script:token -IncludeActivationLock -Sequential
        Assert-MockCalled Backup-ActivationLock -ModuleName IntuneBackup -Times 1
    }

    It "should not call AutopilotDevices when IncludeAutopilotDevices switch is not set" {
        Start-IntuneBackup -BackupPath 'TestDrive:\backup' -Token $script:token -Sequential
        Assert-MockCalled Backup-AutopilotDevices -ModuleName IntuneBackup -Times 0
    }

    It "should call AutopilotDevices when IncludeAutopilotDevices switch is set" {
        Start-IntuneBackup -BackupPath 'TestDrive:\backup' -Token $script:token -IncludeAutopilotDevices -Sequential
        Assert-MockCalled Backup-AutopilotDevices -ModuleName IntuneBackup -Times 1
    }
}