Tests/Src/LabHostConfiguration.Tests.ps1
#requires -RunAsAdministrator #requires -Version 4 $moduleName = 'Lability'; $repoRoot = (Resolve-Path "$PSScriptRoot\..\..").Path; Import-Module (Join-Path -Path $RepoRoot -ChildPath "$moduleName.psm1") -Force; Describe 'Src\LabHostConfiguration' { InModuleScope $moduleName { Context 'Validates "GetLabHostSetupConfiguration" method' { It 'Installs "Microsoft-Hyper-V-All" feature with "WindowsOptionalFeature" on a desktop OS' { Mock Get-CimInstance -ParameterFilter { $ClassName -eq 'Win32_OperatingSystem' } -MockWith { return [PSCustomObject] @{ ProductType = 1; } } $windowsOptionalFeature = GetLabHostSetupConfiguration | Where { $_.Parameters['Name'] -eq 'Microsoft-Hyper-V-All' } $windowsOptionalFeature | Should Not BeNullOrEmpty; } It 'Installs "Hyper-V" feature using "WindowsFeature" on a server OS' { Mock Get-CimInstance -ParameterFilter { $ClassName -eq 'Win32_OperatingSystem' } -MockWith { return [PSCustomObject] @{ ProductType = 2; } } $windowsFeature = GetLabHostSetupConfiguration | Where { $_.Parameters['Name'] -eq 'Hyper-V' } $windowsFeature | Should Not BeNullOrEmpty; } It 'Installs "RSAT-Hyper-V-Tools" feature using "WindowsFeature" on a server OS' { Mock Get-CimInstance -ParameterFilter { $ClassName -eq 'Win32_OperatingSystem' } -MockWith { return [PSCustomObject] @{ ProductType = 2; } } $windowsFeature = GetLabHostSetupConfiguration | Where { $_.Parameters['Name'] -eq 'RSAT-Hyper-V-Tools' } $windowsFeature | Should Not BeNullOrEmpty; } It 'Checks for a pending reboot' { $pendingReboot = GetLabHostSetupConfiguration | Where { $_.ModuleName -eq 'xPendingReboot' -and $_.ResourceName -eq 'MSFT_xPendingReboot' } $pendingReboot | Should Not BeNullOrEmpty; } } #end context Validates "GetLabHostSetupConfiguration" method Context 'Validates "Get-LabHostConfiguration" method' { It 'Calls "ImportDscResource once for each host configuration item' { $fakeConfiguration = @( @{ ModuleName = 'TestModule1'; ResourceName = 'TestResource1'; Prefix = 'Prefix1'; Parameters = @{ P1 = 1; } } @{ ModuleName = 'TestModule2'; ResourceName = 'TestResource2'; Prefix = 'PendingReboot'; Parameters = @{ P1 = 1; } } ) Mock GetLabHostSetupConfiguration -MockWith { return $fakeConfiguration; } Mock GetDscResource -MockWith { return $fakeConfiguration[0]; } Mock ImportDscResource -MockWith { } Get-LabHostConfiguration; Assert-MockCalled ImportDscResource -Exactly $fakeConfiguration.Count -Scope It; } It 'Calls "GetDscResource once for each host configuration item' { $fakeConfiguration = @( @{ ModuleName = 'TestModule1'; ResourceName = 'TestResource1'; Prefix = 'Prefix1'; Parameters = @{ P1 = 1; } } @{ ModuleName = 'TestModule2'; ResourceName = 'TestResource2'; Prefix = 'PendingReboot'; Parameters = @{ P1 = 1; } } ) Mock GetLabHostSetupConfiguration -MockWith { return $fakeConfiguration; } Mock GetDscResource -MockWith { return $fakeConfiguration[0]; } Mock ImportDscResource -MockWith { } Get-LabHostConfiguration; Assert-MockCalled GetDscResource -Exactly $fakeConfiguration.Count -Scope It; } } #end context Validates "Get-LabHostConfiguration" method Context 'Validates "Test-LabHostConfiguration" method' { It 'Passes when target paths exist' { $fakeHostDefaults = '{ "APath": "TestDrive:\\", "TestShare": "TestShare", "BPath": "C:\\" }' | ConvertFrom-Json; Mock GetConfigurationData -ParameterFilter { $Configuration -eq 'Host' } -MockWith { return $fakeHostDefaults; } Mock ImportDscResource -MockWith { } Mock TestDscResource -MockWith { return $true; } Test-LabHostConfiguration | Should Be $true; } It 'Fails when a target path does not exist' { $fakeHostDefaults = '{ "APath": "TestDrive:\\NonExistentFolderPath", "TestShare": "TestShare", "BPath": "C:\\" }' | ConvertFrom-Json; Mock GetConfigurationData -ParameterFilter { $Configuration -eq 'Host' } -MockWith { return $fakeHostDefaults; } Mock ImportDscResource -MockWith { } Mock TestDscResource -MockWith { return $true; } Test-LabHostConfiguration | Should Be $false; } It 'Passes when host configuration is correct' { $fakeConfiguration = @( @{ ModuleName = 'TestModule1'; ResourceName = 'TestResource1'; Prefix = 'Passes'; Parameters = @{ P1 = 1; } } @{ ModuleName = 'TestModule2'; ResourceName = 'TestResource2'; Prefix = 'Passes'; Parameters = @{ P1 = 1; } } ) $fakeHostDefaults = '{ }' | ConvertFrom-Json; Mock GetConfigurationData -MockWith { return $fakeHostDefaults; } Mock GetLabHostSetupConfiguration -MockWith { return $fakeConfiguration; } Mock Test-Path -MockWith { return $true; } Mock ImportDscResource -MockWith { } Mock TestDscResource -ParameterFilter { $ResourceName -eq 'Passes' } -MockWith { return $true; } Mock TestDscResource -ParameterFilter { $ResourceName -eq 'Fails' } -MockWith { return $false; } Test-LabHostConfiguration | Should Be $true; } It 'Fails when host configuration is incorrect' { $fakeConfiguration = @( @{ ModuleName = 'TestModule1'; ResourceName = 'TestResource1'; Prefix = 'Passes'; Parameters = @{ P1 = 1; } } @{ ModuleName = 'TestModule2'; ResourceName = 'TestResource2'; Prefix = 'Fails'; Parameters = @{ P1 = 1; } } ) $fakeHostDefaults = '{ }' | ConvertFrom-Json; Mock GetConfigurationData -MockWith { return $fakeHostDefaults; } Mock GetLabHostSetupConfiguration -MockWith { return $fakeConfiguration; } Mock Test-Path -MockWith { return $true; } Mock ImportDscResource -MockWith { } Mock TestDscResource -ParameterFilter { $ResourceName -eq 'Passes' } -MockWith { return $true; } Mock TestDscResource -ParameterFilter { $ResourceName -eq 'Fails' } -MockWith { return $false; } Test-LabHostConfiguration | Should Be $false; } It 'Fails when host configuration has a pending reboot' { $fakeConfiguration = @( @{ ModuleName = 'TestModule1'; ResourceName = 'TestResource1'; Prefix = 'Passes'; Parameters = @{ P1 = 1; } } @{ ModuleName = 'TestModule2'; ResourceName = 'TestResource2'; Prefix = 'PendingReboot'; Parameters = @{ P1 = 1; } } ) $fakeHostDefaults = '{ }' | ConvertFrom-Json; Mock GetConfigurationData -MockWith { return $fakeHostDefaults; } Mock GetLabHostSetupConfiguration -MockWith { return $fakeConfiguration; } Mock Test-Path -MockWith { return $true; } Mock ImportDscResource -MockWith { } Mock TestDscResource -ParameterFilter { $ResourceName -eq 'Passes' } -MockWith { return $true; } Mock TestDscResource -ParameterFilter { $ResourceName -eq 'PendingReboot' } -MockWith { return $false; } Test-LabHostConfiguration 3> $null | Should Be $false; } It 'Passes when host configuration has a pending reboot but -IgnorePendingReboot is specified' { $fakeConfiguration = @( @{ ModuleName = 'TestModule1'; ResourceName = 'TestResource1'; Prefix = 'Passes'; Parameters = @{ P1 = 1; } } @{ ModuleName = 'TestModule2'; ResourceName = 'TestResource2'; Prefix = 'PendingReboot'; Parameters = @{ P1 = 1; } } ) $fakeHostDefaults = '{ }' | ConvertFrom-Json; Mock GetConfigurationData -MockWith { return $fakeHostDefaults; } Mock GetLabHostSetupConfiguration -MockWith { return $fakeConfiguration; } Mock Test-Path -MockWith { return $true; } Mock ImportDscResource -MockWith { } Mock TestDscResource -ParameterFilter { $ResourceName -eq 'Passes' } -MockWith { return $true; } Mock TestDscResource -ParameterFilter { $ResourceName -eq 'PendingReboot' } -MockWith { return $false; } Test-LabHostConfiguration -IgnorePendingReboot 3> $null | Should Be $true; } } #end context Validates "Test-LabHostConfiguration" method' Context 'Validates "Start-LabHostConfiguration" method' { It 'Does not attempt to create an empty path' { $fakeHostDefaults = '{ "APath": "" }' | ConvertFrom-Json; Mock GetConfigurationData -ParameterFilter { $Configuration -eq 'Host' } -MockWith { return $fakeHostDefaults; } Mock GetLabHostSetupConfiguration -MockWith { } Mock ImportDscResource -MockWith { } Mock InvokeDscResource -MockWith { } Mock NewDirectory -MockWith { } Start-LabHostConfiguration; Assert-MockCalled NewDirectory -Exactly 0 -Scope It; } It 'Calls "NewDirectory" for each path' { $fakeHostDefaults = '{ "APath": "TestDrive:\\", "BPath": "C:\\" }' | ConvertFrom-Json; Mock GetConfigurationData -ParameterFilter { $Configuration -eq 'Host' } -MockWith { return $fakeHostDefaults; } Mock GetLabHostSetupConfiguration -MockWith { } Mock ImportDscResource -MockWith { } Mock InvokeDscResource -MockWith { } Mock NewDirectory -MockWith { } Start-LabHostConfiguration; Assert-MockCalled NewDirectory -Exactly ($fakeHostDefaults.PSObject.Properties | Measure | Select -ExpandProperty Count) -Scope It; } It 'Calls "InvokeDscResource" for each host configuration item' { $fakeHostDefaults = '{ "APath": "TestDrive:\\", "BPath": "C:\\" }' | ConvertFrom-Json; Mock GetConfigurationData -ParameterFilter { $Configuration -eq 'Host' } -MockWith { return $fakeHostDefaults; } $fakeConfiguration = @( @{ ModuleName = 'TestModule1'; ResourceName = 'TestResource1'; Prefix = 'Prefix1'; Parameters = @{ P1 = 1; } } @{ ModuleName = 'TestModule2'; ResourceName = 'TestResource2'; Prefix = 'PendingReboot'; Parameters = @{ P1 = 1; } } ) Mock GetLabHostSetupConfiguration -MockWith { return $fakeConfiguration; } Mock ImportDscResource -MockWith { } Mock InvokeDscResource -MockWith { } Mock NewDirectory -MockWith { } Start-LabHostConfiguration; Assert-MockCalled InvokeDscResource -Exactly $fakeConfiguration.Count -Scope It; } } #end context Validates "Start-LabHostConfiguration" method } #end InModuleScope } #end describe Src\LabHostConfiguration |