Tests/Unit/AdfsDsc.Common.Tests.ps1
$script:resourceModulePath = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent $script:modulesFolderPath = Join-Path -Path $script:resourceModulePath -ChildPath 'Modules\AdfsDsc.Common' Import-Module -Name (Join-Path -Path $script:modulesFolderPath -ChildPath 'AdfsDsc.Common.psm1') -Force InModuleScope 'AdfsDsc.Common' { Describe 'AdfsDsc.Common\Get-LocalizedData' { BeforeAll { $mockImportLocalizedData = { $BaseDirectory | Should -Be $mockExpectedLanguagePath } Mock -CommandName Import-LocalizedData -MockWith $mockImportLocalizedData -Verifiable } Context 'When loading localized data for Swedish' { Context 'When the Swedish language path exists' { BeforeAll { $mockExpectedLanguagePath = 'sv-SE' $mockTestPathReturnValue = $true Mock -CommandName Test-Path -MockWith { $mockTestPathReturnValue } -Verifiable Mock -CommandName Join-Path -MockWith { $mockExpectedLanguagePath } -Verifiable } It 'Should not throw an error' { { Get-LocalizedData -ResourceName 'DummyResource' } | Should -Not -Throw } It 'Should call the expected mocks' { Assert-MockCalled -CommandName Join-Path -Exactly -Times 3 Assert-MockCalled -CommandName Test-Path -Exactly -Times 1 Assert-MockCalled -CommandName Import-LocalizedData -Exactly -Times 1 } } Context ' When the Swedish language path does not exist' { BeforeAll { $mockExpectedLanguagePath = 'en-US' $mockTestPathReturnValue = $false Mock -CommandName Test-Path -MockWith { $mockTestPathReturnValue } -Verifiable Mock -CommandName Join-Path -MockWith { $ChildPath } -Verifiable } It 'Should not throw an error' { { Get-LocalizedData -ResourceName 'DummyResource' } | Should -Not -Throw } It 'Should call the expected mocks' { Assert-MockCalled -CommandName Join-Path -Exactly -Times 4 Assert-MockCalled -CommandName Test-Path -Exactly -Times 1 Assert-MockCalled -CommandName Import-LocalizedData -Exactly -Times 1 } } Context 'When $ScriptRoot is set to a path' { Context 'When the Swedish language path exists' { BeforeAll { $mockExpectedLanguagePath = 'sv-SE' $mockTestPathReturnValue = $true Mock -CommandName Test-Path -MockWith { $mockTestPathReturnValue } -Verifiable Mock -CommandName Join-Path -MockWith { $mockExpectedLanguagePath } -Verifiable } It 'Should not throw an error' { { Get-LocalizedData -ResourceName 'DummyResource' -ScriptRoot '.' } | Should -Not -Throw } It 'Should call the expected mocks' { Assert-MockCalled -CommandName Join-Path -Exactly -Times 1 Assert-MockCalled -CommandName Test-Path -Exactly -Times 1 Assert-MockCalled -CommandName Import-LocalizedData -Exactly -Times 1 } } Context 'When the Swedish language path does not exist' { BeforeAll { $mockExpectedLanguagePath = 'en-US' $mockTestPathReturnValue = $false Mock -CommandName Test-Path -MockWith { $mockTestPathReturnValue } -Verifiable Mock -CommandName Join-Path -MockWith { $ChildPath } -Verifiable } It 'Should not throw an error' { { Get-LocalizedData -ResourceName 'DummyResource' -ScriptRoot '.' } | Should -Not -Throw } It 'Should call the expected mocks' { Assert-MockCalled -CommandName Join-Path -Exactly -Times 2 Assert-MockCalled -CommandName Test-Path -Exactly -Times 1 Assert-MockCalled -CommandName Import-LocalizedData -Exactly -Times 1 } } } } Context 'When loading localized data for US English' { BeforeAll { $mockExpectedLanguagePath = 'en-US' $mockTestPathReturnValue = $true Mock -CommandName Test-Path -MockWith { $mockTestPathReturnValue } -Verifiable Mock -CommandName Join-Path -MockWith { $mockExpectedLanguagePath } -Verifiable } It 'Should not throw an error' { { Get-LocalizedData -ResourceName 'DummyResource' } | Should -Not -Throw } It 'Should call the expected mocks' { Assert-MockCalled -CommandName Join-Path -Exactly -Times 3 Assert-MockCalled -CommandName Test-Path -Exactly -Times 1 Assert-MockCalled -CommandName Import-LocalizedData -Exactly -Times 1 } } Assert-VerifiableMock } Describe 'AdfsDsc.Common\New-InvalidArgumentException' { Context 'When calling with both the Message and ArgumentName parameter' { BeforeAll { $mockErrorMessage = 'Mocked error' $mockArgumentName = 'MockArgument' } It 'Should throw the correct error' { { New-InvalidArgumentException -Message $mockErrorMessage -ArgumentName $mockArgumentName } | Should -Throw ('Parameter name: {0}' -f $mockArgumentName) } } } Describe 'AdfsDsc.Common\New-InvalidOperationException' { Context 'When calling with Message parameter only' { BeforeAll { $mockErrorMessage = 'Mocked error' } It 'Should throw the correct error' { { New-InvalidOperationException -Message $mockErrorMessage } | Should -Throw $mockErrorMessage } } Context 'When calling with both the Message and ErrorRecord parameter' { BeforeAll { $mockErrorMessage = 'Mocked error' $mockExceptionErrorMessage = 'Mocked exception error message' $mockException = New-Object -TypeName 'System.Exception' -ArgumentList $mockExceptionErrorMessage $mockErrorRecord = New-Object -TypeName 'System.Management.Automation.ErrorRecord' ` -ArgumentList @($mockException, $null, 'InvalidResult', $null) } It 'Should throw the correct error' { { New-InvalidOperationException -Message $mockErrorMessage -ErrorRecord $mockErrorRecord } | Should -Throw ('System.InvalidOperationException: {0} ---> System.Exception: {1}' -f $mockErrorMessage, $mockExceptionErrorMessage) } } } Describe 'AdfsDsc.Common\New-ObjectNotFoundException' { Context 'When calling with Message parameter only' { BeforeAll { $mockErrorMessage = 'Mocked error' } It 'Should throw the correct error' { { New-ObjectNotFoundException -Message $mockErrorMessage } | Should -Throw $mockErrorMessage } } Context 'When calling with both the Message and ErrorRecord parameter' { BeforeAll { $mockErrorMessage = 'Mocked error' $mockExceptionErrorMessage = 'Mocked exception error message' $mockException = New-Object -TypeName 'System.Exception' -ArgumentList $mockExceptionErrorMessage $mockErrorRecord = New-Object -TypeName 'System.Management.Automation.ErrorRecord' ` -ArgumentList @($mockException, $null, 'InvalidResult', $null) } It 'Should throw the correct error' { { New-ObjectNotFoundException -Message $mockErrorMessage -ErrorRecord $mockErrorRecord } | Should -Throw ('System.Exception: {0} ---> System.Exception: {1}' -f $mockErrorMessage, $mockExceptionErrorMessage) } } } Describe 'AdfsDsc.Common\New-InvalidResultException' { Context 'When calling with Message parameter only' { BeforeAll { $mockErrorMessage = 'Mocked error' } It 'Should throw the correct error' { { New-InvalidResultException -Message $mockErrorMessage } | Should -Throw $mockErrorMessage } } Context 'When calling with both the Message and ErrorRecord parameter' { BeforeAll { $mockErrorMessage = 'Mocked error' $mockExceptionErrorMessage = 'Mocked exception error message' $mockException = New-Object -TypeName 'System.Exception' -ArgumentList $mockExceptionErrorMessage $mockErrorRecord = New-Object -TypeName 'System.Management.Automation.ErrorRecord' ` -ArgumentList @($mockException, $null, 'InvalidResult', $null) } It 'Should throw the correct error' { { New-InvalidResultException -Message $mockErrorMessage -ErrorRecord $mockErrorRecord } | Should -Throw ('System.Exception: {0} ---> System.Exception: {1}' -f $mockErrorMessage, $mockExceptionErrorMessage) } } } Describe 'AdfsDsc.Common\New-NotImplementedException' { Context 'When calling with Message parameter only' { BeforeAll { $mockErrorMessage = 'Mocked error' } It 'Should throw the correct error' { { New-NotImplementedException -Message $mockErrorMessage } | Should -Throw $mockErrorMessage } } Context 'When calling with both the Message and ErrorRecord parameter' { BeforeAll { $mockErrorMessage = 'Mocked error' $mockExceptionErrorMessage = 'Mocked exception error message' $mockException = New-Object -TypeName 'System.Exception' -ArgumentList $mockExceptionErrorMessage $mockErrorRecord = New-Object -TypeName 'System.Management.Automation.ErrorRecord' ` -ArgumentList @($mockException, $null, 'NotImplemented', $null) } It 'Should throw the correct error' { { New-NotImplementedException -Message $mockErrorMessage -ErrorRecord $mockErrorRecord } | Should -Throw ('System.NotImplementedException: {0} ---> System.Exception: {1}' -f $mockErrorMessage, $mockExceptionErrorMessage) } } } Describe 'AdfsDsc.Common\ConvertTo-Timespan' { It "Returns 'System.TimeSpan' object type" { $testIntTimeSpan = 60 $result = ConvertTo-TimeSpan -TimeSpan $testIntTimeSpan -TimeSpanType Minutes $result -is [System.TimeSpan] | Should -Be $true } It 'Creates TimeSpan from seconds' { $testIntTimeSpan = 60 $result = ConvertTo-TimeSpan -TimeSpan $testIntTimeSpan -TimeSpanType Seconds $result.TotalSeconds | Should -Be $testIntTimeSpan } It 'Creates TimeSpan from minutes' { $testIntTimeSpan = 60 $result = ConvertTo-TimeSpan -TimeSpan $testIntTimeSpan -TimeSpanType Minutes $result.TotalMinutes | Should -Be $testIntTimeSpan } It 'Creates TimeSpan from hours' { $testIntTimeSpan = 60 $result = ConvertTo-TimeSpan -TimeSpan $testIntTimeSpan -TimeSpanType Hours $result.TotalHours | Should -Be $testIntTimeSpan } It 'Creates TimeSpan from days' { $testIntTimeSpan = 60 $result = ConvertTo-TimeSpan -TimeSpan $testIntTimeSpan -TimeSpanType Days $result.TotalDays | Should -Be $testIntTimeSpan } } Describe 'AdfsDsc.Common\ConvertFrom-Timespan' { It "Returns 'System.UInt32' object type" { $testIntTimeSpan = 60 $testTimeSpan = New-TimeSpan -Seconds $testIntTimeSpan $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Seconds $result -is [System.UInt32] | Should -Be $true } It 'Converts TimeSpan to total seconds' { $testIntTimeSpan = 60 $testTimeSpan = New-TimeSpan -Seconds $testIntTimeSpan $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Seconds $result | Should -Be $testTimeSpan.TotalSeconds } It 'Converts TimeSpan to total minutes' { $testIntTimeSpan = 60 $testTimeSpan = New-TimeSpan -Minutes $testIntTimeSpan $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Minutes $result | Should -Be $testTimeSpan.TotalMinutes } It 'Converts TimeSpan to total hours' { $testIntTimeSpan = 60 $testTimeSpan = New-TimeSpan -Hours $testIntTimeSpan $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Hours $result | Should -Be $testTimeSpan.TotalHours } It 'Converts TimeSpan to total days' { $testIntTimeSpan = 60 $testTimeSpan = New-TimeSpan -Days $testIntTimeSpan $result = ConvertFrom-TimeSpan -TimeSpan $testTimeSpan -TimeSpanType Days $result | Should -Be $testTimeSpan.TotalDays } } Describe 'AdfsDsc.Common\Compare-ResourcePropertyState' { Context 'When one property is in desired state' { BeforeAll { $mockCurrentValues = @{ ComputerName = 'DC01' } $mockDesiredValues = @{ ComputerName = 'DC01' } } It 'Should return the correct values' { $compareTargetResourceStateParameters = @{ CurrentValues = $mockCurrentValues DesiredValues = $mockDesiredValues } $compareTargetResourceStateResult = Compare-ResourcePropertyState @compareTargetResourceStateParameters $compareTargetResourceStateResult | Should -HaveCount 1 $compareTargetResourceStateResult.ParameterName | Should -Be 'ComputerName' $compareTargetResourceStateResult.Expected | Should -Be 'DC01' $compareTargetResourceStateResult.Actual | Should -Be 'DC01' $compareTargetResourceStateResult.InDesiredState | Should -BeTrue } } Context 'When two properties are in desired state' { BeforeAll { $mockCurrentValues = @{ ComputerName = 'DC01' Location = 'Sweden' } $mockDesiredValues = @{ ComputerName = 'DC01' Location = 'Sweden' } } It 'Should return the correct values' { $compareTargetResourceStateParameters = @{ CurrentValues = $mockCurrentValues DesiredValues = $mockDesiredValues } $compareTargetResourceStateResult = Compare-ResourcePropertyState @compareTargetResourceStateParameters $compareTargetResourceStateResult | Should -HaveCount 2 $compareTargetResourceStateResult[0].ParameterName | Should -Be 'ComputerName' $compareTargetResourceStateResult[0].Expected | Should -Be 'DC01' $compareTargetResourceStateResult[0].Actual | Should -Be 'DC01' $compareTargetResourceStateResult[0].InDesiredState | Should -BeTrue $compareTargetResourceStateResult[1].ParameterName | Should -Be 'Location' $compareTargetResourceStateResult[1].Expected | Should -Be 'Sweden' $compareTargetResourceStateResult[1].Actual | Should -Be 'Sweden' $compareTargetResourceStateResult[1].InDesiredState | Should -BeTrue } } Context 'When passing just one property and that property is not in desired state' { BeforeAll { $mockCurrentValues = @{ ComputerName = 'DC01' } $mockDesiredValues = @{ ComputerName = 'APP01' } } It 'Should return the correct values' { $compareTargetResourceStateParameters = @{ CurrentValues = $mockCurrentValues DesiredValues = $mockDesiredValues } $compareTargetResourceStateResult = Compare-ResourcePropertyState @compareTargetResourceStateParameters $compareTargetResourceStateResult | Should -HaveCount 1 $compareTargetResourceStateResult.ParameterName | Should -Be 'ComputerName' $compareTargetResourceStateResult.Expected | Should -Be 'APP01' $compareTargetResourceStateResult.Actual | Should -Be 'DC01' $compareTargetResourceStateResult.InDesiredState | Should -BeFalse } } Context 'When passing two properties and one property is not in desired state' { BeforeAll { $mockCurrentValues = @{ ComputerName = 'DC01' Location = 'Sweden' } $mockDesiredValues = @{ ComputerName = 'DC01' Location = 'Europe' } } It 'Should return the correct values' { $compareTargetResourceStateParameters = @{ CurrentValues = $mockCurrentValues DesiredValues = $mockDesiredValues } $compareTargetResourceStateResult = Compare-ResourcePropertyState @compareTargetResourceStateParameters $compareTargetResourceStateResult | Should -HaveCount 2 $compareTargetResourceStateResult[0].ParameterName | Should -Be 'ComputerName' $compareTargetResourceStateResult[0].Expected | Should -Be 'DC01' $compareTargetResourceStateResult[0].Actual | Should -Be 'DC01' $compareTargetResourceStateResult[0].InDesiredState | Should -BeTrue $compareTargetResourceStateResult[1].ParameterName | Should -Be 'Location' $compareTargetResourceStateResult[1].Expected | Should -Be 'Europe' $compareTargetResourceStateResult[1].Actual | Should -Be 'Sweden' $compareTargetResourceStateResult[1].InDesiredState | Should -BeFalse } } Context 'When passing a common parameter set to desired value' { BeforeAll { $mockCurrentValues = @{ ComputerName = 'DC01' } $mockDesiredValues = @{ ComputerName = 'DC01' Verbose = $true } } It 'Should return the correct values' { $compareTargetResourceStateParameters = @{ CurrentValues = $mockCurrentValues DesiredValues = $mockDesiredValues } $compareTargetResourceStateResult = Compare-ResourcePropertyState @compareTargetResourceStateParameters $compareTargetResourceStateResult | Should -HaveCount 1 $compareTargetResourceStateResult.ParameterName | Should -Be 'ComputerName' $compareTargetResourceStateResult.Expected | Should -Be 'DC01' $compareTargetResourceStateResult.Actual | Should -Be 'DC01' $compareTargetResourceStateResult.InDesiredState | Should -BeTrue } } Context 'When using parameter Properties to compare desired values' { BeforeAll { $mockCurrentValues = @{ ComputerName = 'DC01' Location = 'Sweden' } $mockDesiredValues = @{ ComputerName = 'DC01' Location = 'Europe' } } It 'Should return the correct values' { $compareTargetResourceStateParameters = @{ CurrentValues = $mockCurrentValues DesiredValues = $mockDesiredValues Properties = @( 'ComputerName' ) } $compareTargetResourceStateResult = Compare-ResourcePropertyState @compareTargetResourceStateParameters $compareTargetResourceStateResult | Should -HaveCount 1 $compareTargetResourceStateResult.ParameterName | Should -Be 'ComputerName' $compareTargetResourceStateResult.Expected | Should -Be 'DC01' $compareTargetResourceStateResult.Actual | Should -Be 'DC01' $compareTargetResourceStateResult.InDesiredState | Should -BeTrue } } Context 'When using parameter Properties and IgnoreProperties to compare desired values' { BeforeAll { $mockCurrentValues = @{ ComputerName = 'DC01' Location = 'Sweden' Ensure = 'Present' } $mockDesiredValues = @{ ComputerName = 'DC01' Location = 'Europe' Ensure = 'Absent' } } It 'Should return the correct values' { $compareTargetResourceStateParameters = @{ CurrentValues = $mockCurrentValues DesiredValues = $mockDesiredValues IgnoreProperties = @( 'Ensure' ) } $compareTargetResourceStateResult = Compare-ResourcePropertyState @compareTargetResourceStateParameters $compareTargetResourceStateResult | Should -HaveCount 2 $compareTargetResourceStateResult[0].ParameterName | Should -Be 'ComputerName' $compareTargetResourceStateResult[0].Expected | Should -Be 'DC01' $compareTargetResourceStateResult[0].Actual | Should -Be 'DC01' $compareTargetResourceStateResult[0].InDesiredState | Should -BeTrue $compareTargetResourceStateResult[1].ParameterName | Should -Be 'Location' $compareTargetResourceStateResult[1].Expected | Should -Be 'Europe' $compareTargetResourceStateResult[1].Actual | Should -Be 'Sweden' $compareTargetResourceStateResult[1].InDesiredState | Should -BeFalse } } Context 'When using parameter Properties and IgnoreProperties to compare desired values' { BeforeAll { $mockCurrentValues = @{ ComputerName = 'DC01' Location = 'Sweden' Ensure = 'Present' } $mockDesiredValues = @{ ComputerName = 'DC01' Location = 'Europe' Ensure = 'Absent' } } It 'Should return an empty array' { $compareTargetResourceStateParameters = @{ CurrentValues = $mockCurrentValues DesiredValues = $mockDesiredValues Properties = @( 'ComputerName' ) IgnoreProperties = @( 'ComputerName' ) } $compareTargetResourceStateResult = Compare-ResourcePropertyState @compareTargetResourceStateParameters $compareTargetResourceStateResult | Should -BeNullOrEmpty } } } Describe 'DscResource.Common\Test-DscPropertyState' -Tag 'TestDscPropertyState' { Context 'When comparing strings' { Context 'When the strings match' { BeforeAll { $mockValues = @{ CurrentValue = [System.String] 'Test' DesiredValue = [System.String] 'Test' } } It 'Should return true' { Test-DscPropertyState -Values $mockValues | Should -Be $true } } Context 'When the strings do not match' { BeforeAll { $mockValues = @{ CurrentValue = [System.String] 'something' DesiredValue = [System.String] 'test' } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } Context 'When the string current value is missing' { BeforeAll { $mockValues = @{ CurrentValue = $null DesiredValue = [System.String] 'Something' } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } Context 'When the string desired value is missing' { BeforeAll { $mockValues = @{ CurrentValue = [System.String] 'Something' DesiredValue = $null } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } } Context 'When comparing Int16' { Context 'When the integers match' { BeforeAll { $mockValues = @{ CurrentValue = [System.Int16] 1 DesiredValue = [System.Int16] 1 } } It 'Should return true' { Test-DscPropertyState -Values $mockValues | Should -Be $true } } Context 'When the integers do not match' { BeforeAll { $mockValues = @{ CurrentValue = [System.Int16] 1 DesiredValue = [System.Int16] 2 } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } Context 'When the integers current value is missing' { BeforeAll { $mockValues = @{ CurrentValue = $null DesiredValue = [System.Int16] 1 } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } Context 'When the integers desired value is missing' { BeforeAll { $mockValues = @{ CurrentValue = [System.Int16] 1 DesiredValue = $null } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } } Context 'When comparing UInt16' { Context 'When the integers match' { BeforeAll { $mockValues = @{ CurrentValue = [System.UInt16] 1 DesiredValue = [System.UInt16] 1 } } It 'Should return true' { Test-DscPropertyState -Values $mockValues | Should -Be $true } } Context 'When the integers do not match' { BeforeAll { $mockValues = @{ CurrentValue = [System.UInt16] 1 DesiredValue = [System.UInt16] 2 } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } Context 'When the integers current value is missing' { BeforeAll { $mockValues = @{ CurrentValue = $null DesiredValue = [System.UInt16] 1 } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } Context 'When the integers desired value is missing' { BeforeAll { $mockValues = @{ CurrentValue = [System.UInt16] 1 DesiredValue = $null } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } } Context 'When comparing Int32' { Context 'When the integers match' { BeforeAll { $mockValues = @{ CurrentValue = [System.Int32] 1 DesiredValue = [System.Int32] 1 } } It 'Should return true' { Test-DscPropertyState -Values $mockValues | Should -Be $true } } Context 'When the integers do not match' { BeforeAll { $mockValues = @{ CurrentValue = [System.Int32] 1 DesiredValue = [System.Int32] 2 } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } Context 'When the integers current value is missing' { BeforeAll { $mockValues = @{ CurrentValue = $null DesiredValue = [System.Int32] 1 } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } Context 'When the integers desired value is missing' { BeforeAll { $mockValues = @{ CurrentValue = [System.Int32] 1 DesiredValue = $null } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } } Context 'When comparing UInt32' { Context 'When the integers match' { BeforeAll { $mockValues = @{ CurrentValue = [System.UInt32] 1 DesiredValue = [System.UInt32] 1 } } It 'Should return true' { Test-DscPropertyState -Values $mockValues | Should -Be $true } } Context 'When the integers do not match' { BeforeAll { $mockValues = @{ CurrentValue = [System.UInt32] 1 DesiredValue = [System.UInt32] 2 } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } Context 'When the integers current value is missing' { BeforeAll { $mockValues = @{ CurrentValue = $null DesiredValue = [System.UInt32] 1 } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } Context 'When the integers desired value is missing' { BeforeAll { $mockValues = @{ CurrentValue = [System.UInt32] 1 DesiredValue = $null } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } } Context 'When comparing Single' { Context 'When the singles match' { BeforeAll { $mockValues = @{ CurrentValue = [System.Single] 1.5 DesiredValue = [System.Single] 1.5 } } It 'Should return true' { Test-DscPropertyState -Values $mockValues | Should -Be $true } } Context 'When the singles do not match' { BeforeAll { $mockValues = @{ CurrentValue = [System.Single] 1.5 DesiredValue = [System.Single] 2.5 } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } Context 'When the single current value is missing' { BeforeAll { $mockValues = @{ CurrentValue = $null DesiredValue = [System.Single] 1.5 } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } Context 'When the single desired value is missing' { BeforeAll { $mockValues = @{ CurrentValue = [System.Single] 1.5 DesiredValue = $null } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } } Context 'When comparing booleans' { Context 'When the booleans match' { BeforeAll { $mockValues = @{ CurrentValue = [System.Boolean] $true DesiredValue = [System.Boolean] $true } } It 'Should return true' { Test-DscPropertyState -Values $mockValues | Should -Be $true } } Context 'When the booleans do not match' { BeforeAll { $mockValues = @{ CurrentValue = [System.Boolean] $true DesiredValue = [System.Boolean] $false } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } Context 'When a boolean value is missing' { BeforeAll { $mockValues = @{ CurrentValue = $null DesiredValue = [System.Boolean] $true } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } } } Context 'When comparing arrays' { Context 'When the arrays match' { BeforeAll { $mockValues = @{ CurrentValue = @('1', '2') DesiredValue = @('1', '2') } } It 'Should return true' { Test-DscPropertyState -Values $mockValues | Should -BeTrue } } Context 'When the arrays do not match' { BeforeAll { $mockValues = @{ CurrentValue = @('CurrentValueA', 'CurrentValueB') DesiredValue = @('DesiredValue1', 'DesiredValue2') } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -BeFalse } } Context 'When the current value is $null' { BeforeAll { $mockValues = @{ CurrentValue = $null DesiredValue = @('1', '2') } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -BeFalse } } Context 'When the desired value is $null' { BeforeAll { $mockValues = @{ CurrentValue = @('1', '2') DesiredValue = $null } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -BeFalse } } Context 'When the current value is an empty array' { BeforeAll { $mockValues = @{ CurrentValue = @() DesiredValue = @('1', '2') } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -BeFalse } } Context 'when the desired value is an empty array' { BeforeAll { $mockValues = @{ CurrentValue = @('1', '2') DesiredValue = @() } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -BeFalse } } Context 'when both values are $null' { BeforeAll { $mockValues = @{ CurrentValue = $null DesiredValue = $null } } It 'Should return true ' { Test-DscPropertyState -Values $mockValues -Verbose | Should -BeTrue } } Context 'When both values are an empty array' { BeforeAll { $mockValues = @{ CurrentValue = @() DesiredValue = @() } } It 'Should return true' { Test-DscPropertyState -Values $mockValues -Verbose | Should -BeTrue } } } Context -Name 'When passing unsupported types for DesiredValue' { BeforeAll { Mock -CommandName Write-Warning -Verifiable $mockUnknownType = 'MockUnknowntype' # This is a dummy type to test with a type that could never be a correct one. class MockUnknownType { [ValidateNotNullOrEmpty()] [System.String] $Property1 [ValidateNotNullOrEmpty()] [System.String] $Property2 MockUnknownType() { } } $mockValues = @{ CurrentValue = New-Object -TypeName $mockUnknownType DesiredValue = New-Object -TypeName $mockUnknownType } } It 'Should return false' { Test-DscPropertyState -Values $mockValues | Should -Be $false } It 'Should write the correct warning' { Assert-MockCalled -CommandName Write-Warning ` -ParameterFilter { $Message -eq ($script:localizedData.UnableToCompareType -f $mockUnknownType) } ` -Exactly -Times 1 } } Assert-VerifiableMock } Describe 'AdfsDsc.Common\New-CimCredentialInstance' { Context 'When creating a new MSFT_Credential CIM instance credential object' { BeforeAll { $mockAdministratorUser = 'admin@contoso.com' $mockAdministratorPassword = 'P@ssw0rd-12P@ssw0rd-12' $mockAdministratorCredential = New-Object -TypeName 'System.Management.Automation.PSCredential' ` -ArgumentList @( $mockAdministratorUser, ($mockAdministratorPassword | ConvertTo-SecureString -AsPlainText -Force) ) } Context 'When the Credential parameter is specified' { It 'Should return the correct values' { $newCimCredentialInstanceResult = New-CimCredentialInstance -Credential $mockAdministratorCredential $newCimCredentialInstanceResult | Should -BeOfType 'Microsoft.Management.Infrastructure.CimInstance' $newCimCredentialInstanceResult.CimClass.CimClassName | Should -Be 'MSFT_Credential' $newCimCredentialInstanceResult.UserName | Should -Be $mockAdministratorUser $newCimCredentialInstanceResult.Password | Should -BeNullOrEmpty } } Context 'When the UserName parameter is specified' { It 'Should return the correct values' { $newCimCredentialInstanceResult = New-CimCredentialInstance -UserName $mockAdministratorUser $newCimCredentialInstanceResult | Should -BeOfType 'Microsoft.Management.Infrastructure.CimInstance' $newCimCredentialInstanceResult.CimClass.CimClassName | Should -Be 'MSFT_Credential' $newCimCredentialInstanceResult.UserName | Should -Be $mockAdministratorUser $newCimCredentialInstanceResult.Password | Should -BeNullOrEmpty } } } } Describe 'AdfsDsc.Common\Assert-Module' { BeforeAll { $testModuleName = 'TestModule' } Context 'When module is not installed' { BeforeAll { Mock -CommandName Get-Module } It 'Should throw the correct error' { { Assert-Module -ModuleName $testModuleName } | Should -Throw ($script:localizedData.ModuleNotFoundError -f $testModuleName) } } Context 'When module is available' { BeforeAll { Mock -CommandName Import-Module Mock -CommandName Get-Module -MockWith { return @{ Name = $testModuleName } } } Context 'When module should not be imported' { It 'Should not throw an error' { { Assert-Module -ModuleName $testModuleName } | Should -Not -Throw Assert-MockCalled -CommandName Import-Module -Exactly -Times 0 } } Context 'When module should be imported' { It 'Should not throw an error' { { Assert-Module -ModuleName $testModuleName -ImportModule } | Should -Not -Throw Assert-MockCalled -CommandName Import-Module -Exactly -Times 1 } } } } Describe 'AdfsDsc.Common\Assert-DomainMember' { BeforeAll { $mockGetCimInstanceDomainMemberResult = @{ PartOfDomain = $true } $mockGetCimInstanceNotDomainMemberResult = @{ PartOfDomain = $false } } Context 'When the computer is a domain member' { BeforeAll { Mock -CommandName Get-CimInstance -MockWith { $mockGetCimInstanceDomainMemberResult } } It 'Should not throw an error' { { Assert-DomainMember } | Should -Not -Throw } It 'Should call the correct mocks' { Assert-MockCalled -CommandName Get-CimInstance ` -ParameterFilter { $ClassName -eq 'Win32_ComputerSystem' } ` -Exactly -Times 1 } } Context 'When the computer is not a domain member' { BeforeAll { Mock -CommandName Get-CimInstance -MockWith { $mockGetCimInstanceNotDomainMemberResult } } It 'Should throw the correct error' { { Assert-DomainMember } | Should -Throw $script:localizedData.NotDomainMemberError } } } Describe 'AdfsDsc.Common\Assert-AdfsService' { BeforeAll { $mockGetCimInstanceResult = @{ LastBootUpTime = [DateTime]'05 October 2019 01:00:00' } $mockGetDateInsideResult = [DateTime]'05 October 2019 01:10:00' $mockGetDateOutsideResult = [DateTime]'05 October 2019 02:00:00' $mockGetServiceRunningResult = @{ Status = 'Running' } $mockGetServiceNotRunningResult = @{ Status = 'Stopped' } } Mock -CommandName Start-Sleep Context 'When it is inside the retry window' { BeforeAll { Mock -CommandName Get-CimInstance -MockWith { $mockGetCimInstanceResult } Mock -CommandName Get-Date -MockWith { $mockGetDateInsideResult } } Context 'When the ADFS service is running' { BeforeAll { Mock -CommandName Get-Service -MockWith { $mockGetServiceRunningResult } } It 'Should not throw an error' { { Assert-AdfsService } | Should -Not -Throw } It 'Should call the correct mocks' { Assert-MockCalled -CommandName Get-CimInstance ` -ParameterFilter { $ClassName -eq 'Win32_OperatingSystem' } ` -Exactly -Times 1 Assert-MockCalled -CommandName Get-Date -Exactly -Times 1 Assert-MockCalled -CommandName Get-Service ` -ParameterFilter { $Name -eq $script:adfsServiceName } ` -Exactly -Times 1 Assert-MockCalled -CommandName Start-Sleep -Exactly -Times 0 } } Context 'When the ADFS service is not running' { BeforeAll { Mock -CommandName Get-Service -MockWith { $mockGetServiceNotRunningResult } } It 'Should throw the correct error' { { Assert-AdfsService } | Should -Throw $script:localizedData.AdfsServiceNotRunningError } It 'Should call the correct mocks' { Assert-MockCalled -CommandName Get-CimInstance ` -ParameterFilter { $ClassName -eq 'Win32_OperatingSystem' } ` -Exactly -Times 1 Assert-MockCalled -CommandName Get-Date -Exactly -Times 10 Assert-MockCalled -CommandName Get-Service ` -ParameterFilter { $Name -eq $script:adfsServiceName } ` -Exactly -Times 10 Assert-MockCalled -CommandName Start-Sleep -Exactly -Times 10 } } Context 'When Get-Service throws an error' { BeforeAll { Mock -CommandName Get-Service -MockWith { Throw 'Error' } } It 'Should throw the correct error' { { Assert-AdfsService } | Should -Throw $script:localizedData.GetAdfsServiceError } } } Context 'When it is outside the retry window' { BeforeAll { Mock -CommandName Get-CimInstance -MockWith { $mockGetCimInstanceResult } Mock -CommandName Get-Date -MockWith { $mockGetDateOutsideResult } } Context 'When the ADFS service is running' { BeforeAll { Mock -CommandName Get-Service -MockWith { $mockGetServiceRunningResult } } It 'Should not throw an error' { { Assert-AdfsService } | Should -Not -Throw } It 'Should call the correct mocks' { Assert-MockCalled -CommandName Get-CimInstance ` -ParameterFilter { $ClassName -eq 'Win32_OperatingSystem' } ` -Exactly -Times 1 Assert-MockCalled -CommandName Get-Date -Exactly -Times 1 Assert-MockCalled -CommandName Get-Service ` -ParameterFilter { $Name -eq $script:adfsServiceName } ` -Exactly -Times 1 Assert-MockCalled -CommandName Start-Sleep -Exactly -Times 0 } } Context 'When Get-Service throws an error' { BeforeAll { Mock -CommandName Get-Service -MockWith { Throw 'Error' } } It 'Should throw the correct error' { { Assert-AdfsService } | Should -Throw $script:localizedData.GetAdfsServiceError } } Context 'When the ADFS service is not running' { BeforeAll { Mock -CommandName Get-Service -MockWith { $mockGetServiceNotRunningResult } } It 'Should throw the correct error' { { Assert-AdfsService } | Should -Throw $script:localizedData.AdfsServiceNotRunningError } } } } Describe 'AdfsDsc.Common\Assert-Command' { BeforeAll { $mockCommand = 'Get-MockCommand' $mockModule = 'MockModule' $mockGetCommandExistsResult = @{ CommandType = 'Cmdlet' Name = $mockCommand Source = $mockModule } } Context 'When the specified command exists' { BeforeAll { Mock -CommandName Get-Command -MockWith { $mockGetCommandExistsResult } } It 'Should not throw an error' { { Assert-Command -Command $mockCommand -Module $mockModule } | Should -Not -Throw } It 'Should call the correct mocks' { Assert-MockCalled -CommandName Get-Command ` -ParameterFilter { $Name -eq $mockCommand -and $Module -eq $mockModule } ` -Exactly -Times 1 } } Context 'When the specified command does not exist' { BeforeAll { Mock -CommandName Get-Command } It 'Should throw the correct error' { { Assert-Command -Command $mockCommand -Module $mockModule } | Should -Throw ( ` $script:localizedData.ResourceNotImplementedError -f $mockModule, $mockCommand) } } } Describe 'AdfsDsc.Common\Assert-GroupServiceAccount' { BeforeAll { $mockDomainDn = 'DC=contoso,DC=com' $mockGmsaName = 'mockgmsa' $mockGetADObjectByNameGmsaResult = @{ Path = "LDAP://CN=$mockGmsaName,CN=Managed Service Accounts,$mockDomainDn" Properties = @{ objectcategory = "CN=ms-DS-Group-Managed-Service-Account,CN=Schema,CN=Configuration,$mockDomainDn" } } $mockDomainDn = 'DC=contoso,DC=com' $mockSmsaName = 'mocksmsa' $mockGetADObjectByNameSmsaResult = @{ Path = "LDAP://CN=$mockSmsaName,CN=Managed Service Accounts,$mockDomainDn" Properties = @{ objectcategory = "CN=ms-DS-Managed-Service-Account,CN=Schema,CN=Configuration,$mockDomainDn" } } $mockUserName = 'mockUserAccount' $mockGetADObjectByNameUserResult = @{ Path = "LDAP://CN=$mockUserName,CN=Users,$mockDomainDn" Properties = @{ objectcategory = "CN=Person,CN=Schema,CN=Configuration,$mockDomainDn" } } $mockComputerName = 'mockComputerAccount' $mockGetADObjectByNameComputerResult = @{ Path = "LDAP://CN=$mockComputerName,CN=Computers,$mockDomainDn" Properties = @{ objectcategory = "CN=Computer,CN=Schema,CN=Configuration,$mockDomainDn" } } $mockUnknownAccountName = 'UnknownAccount' } Context 'When the account is a Group Managed Service Account' { BeforeAll { Mock -CommandName Get-ADObjectByQualifiedName -MockWith { $mockGetADObjectByNameGmsaResult } } It 'Should return true' { Assert-GroupServiceAccount -Name $mockGmsaName | Should -BeTrue } } Context 'When the account is a Standalone Managed Service Account' { BeforeAll { Mock -CommandName Get-ADObjectByQualifiedName -MockWith { $mockGetADObjectByNameSmsaResult } } It 'Should return false' { Assert-GroupServiceAccount -Name $mockSmsaName | Should -BeFalse } } Context 'When the account is a User Account' { BeforeAll { Mock -CommandName Get-ADObjectByQualifiedName -MockWith { $mockGetADObjectByNameUserResult } } It 'Should return false' { Assert-GroupServiceAccount -Name $mockUserName | Should -BeFalse } } Context 'When the account is not a User/Service Account' { BeforeAll { Mock -CommandName Get-ADObjectByQualifiedName -MockWith { $mockGetADObjectByNameComputerResult } } It 'Should throw the correct error' { { Assert-GroupServiceAccount -Name $mockComputerName } | Should -Throw ( $script:localizedData.UnexpectedServiceAccountCategoryError -f $mockGetADObjectByNameComputerResult.Properties.ObjectCategory, $mockComputerName) } } Context 'When the account is not found' { BeforeAll { Mock -CommandName Get-ADObjectByQualifiedName } It 'Should throw the correct error' { { Assert-GroupServiceAccount -Name $mockUnknownAccountName } | Should -Throw ( $script:localizedData.ServiceAccountNotFoundError -f $mockUnknownAccountName) } } } Describe 'AdfsDsc.Common\Get-AdfsConfigurationStatus' { BeforeAll { $mockGetItemPropertyFsConfigurationStatusNotConfigured0Result = @{ FSConfigurationStatus = 0 } $mockGetItemPropertyFsConfigurationStatusNotConfigured1Result = @{ FSConfigurationStatus = 1 } $mockGetItemPropertyFsConfigurationStatusConfiguredResult = @{ FSConfigurationStatus = 2 } $mockUnexpectedStatus = 99 $mockGetItemPropertyFsConfigurationStatusUnexpectedResult = @{ FSConfigurationStatus = $mockUnexpectedStatus } } Context 'When the ADFS Configuration Status is Configured' { BeforeAll { Mock -CommandName Get-ItemProperty -MockWith { $mockGetItemPropertyFsConfigurationStatusConfiguredResult } } It 'Should return the correct result' { Get-AdfsConfigurationStatus | Should -Be 'Configured' } It 'Should call the correct mocks' { Assert-MockCalled -CommandName Get-ItemProperty ` -ParameterFilter { $Path -eq 'HKLM:\SOFTWARE\Microsoft\ADFS' } ` -Exactly -Times 1 } } Context 'When the ADFS Configuration Status is NotConfigured with a value of 1' { BeforeAll { Mock -CommandName Get-ItemProperty -MockWith { $mockGetItemPropertyFsConfigurationStatusNotConfigured0Result } } It 'Should return the correct result' { Get-AdfsConfigurationStatus | Should -Be 'NotConfigured' } It 'Should call the correct mocks' { Assert-MockCalled -CommandName Get-ItemProperty ` -ParameterFilter { $Path -eq 'HKLM:\SOFTWARE\Microsoft\ADFS' } ` -Exactly -Times 1 } } Context 'When the ADFS Configuration Status is NotConfigured with a value of 2' { BeforeAll { Mock -CommandName Get-ItemProperty -MockWith { $mockGetItemPropertyFsConfigurationStatusNotConfigured1Result } } It 'Should return the correct result' { Get-AdfsConfigurationStatus | Should -Be 'NotConfigured' } It 'Should call the correct mocks' { Assert-MockCalled -CommandName Get-ItemProperty ` -ParameterFilter { $Path -eq 'HKLM:\SOFTWARE\Microsoft\ADFS' } ` -Exactly -Times 1 } } Context 'When Get-ItemProperty throws an error' { BeforeAll { Mock -CommandName Get-ItemProperty -MockWith { Throw 'Error' } } It 'Should throw the correct error' { { Get-AdfsConfigurationStatus } | Should -Throw $script:localizedData.ConfigurationStatusNotFoundError } } Context 'When FSConfigurationStatus is an unexpected value' { BeforeAll { Mock -CommandName Get-ItemProperty -MockWith { $mockGetItemPropertyFsConfigurationStatusUnexpectedResult } } It 'Should throw the correct error' { { Get-AdfsConfigurationStatus } | Should -Throw ($script:localizedData.UnknownConfigurationStatusError -f $mockUnexpectedStatus) } } } Describe 'AdfsDsc.Common\Get-ObjectType' { BeforeAll { $mockStringObject = [System.String]'StringObject' } It 'Should return the correct result' { Get-ObjectType -Object $mockStringObject | Should -Be 'System.String' } } Describe 'AdfsDsc.Common\ConvertTo-IssuanceTransformRule' { BeforeAll { mock -CommandName Get-AdGroupSid } Context 'When the transform rule is of type LdapClaims' { BeforeAll { $mockLdapAttributes = @( 'mail' 'sn' ) $mockOutgoingClaimTypes = @( 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress' 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname' ) $MSFT_AdfsLdapMappingProperties = @( @{ LdapAttribute = $mockLdapAttributes[0] OutgoingClaimType = $mockOutgoingClaimTypes[0] } @{ LdapAttribute = $mockLdapAttributes[1] OutgoingClaimType = $mockOutgoingClaimTypes[1] } ) $mockLdapClaimsTemplateName = 'LdapClaims' $mockLdapClaimsRuleName = 'Test' $mockLdapMapping = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsLdapMapping ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $MSFT_AdfsLdapMappingProperties[0] -ClientOnly New-CimInstance -ClassName MSFT_AdfsLdapMapping ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $MSFT_AdfsLdapMappingProperties[1] -ClientOnly ) $mockLdapClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockLdapClaimsTemplateName Name = $mockLdapClaimsRuleName AttributeStore = 'Active Directory' LdapMapping = $mockLdapMapping } $mockLdapClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockLdapClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) $mockLdapClaimsTransformRule = @( '@RuleTemplate = "{0}"' -f $mockLdapClaimsTemplateName '@RuleName = "{0}"' -f $mockLdapClaimsRuleName 'c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]' '=> issue(store = "Active Directory", types = ("{1}", "{2}"), query = ";{3},{4};{0}", param = c.Value);' -f ` '{0}', $mockOutgoingClaimTypes[0], $mockOutgoingClaimTypes[1], $mockLdapAttributes[0], $mockLdapAttributes[1] ) | Out-String } It 'Should return the correct result' { ConvertTo-IssuanceTransformRule -InputObject $mockLdapClaimsIssuanceTransformRules | ` Should -Be $mockLdapClaimsTransformRule } It 'Should call the expected mocks' { Assert-MockCalled -CommandName Get-AdGroupSid -Exactly -Times 0 } } Context 'When the transform rule is of type EmitGroupClaims' { BeforeAll { $mockEmitGroupClaimsTemplateName = 'EmitGroupClaims' $mockEmitGroupClaimsRuleName = 'Test' $mockAdGroupName = 'Test Group' $mockAdGroupSid = 'd382a151-2a2c-4f0f-a6e7-8de159333cd2' $mockOutgoingClaimType = 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role' $mockOutgoingClaimValue = 'User' $mockEmitGroupClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockEmitGroupClaimsTemplateName Name = $mockEmitGroupClaimsRuleName GroupName = $mockAdGroupName OutgoingClaimType = $mockOutgoingClaimType OutgoingClaimValue = $mockOutgoingClaimValue } $mockEmitGroupClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockEmitGroupClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) $mockEmitGroupClaimsTransformRule = @( '@RuleTemplate = "{0}"' -f $mockEmitGroupClaimsTemplateName '@RuleName = "{0}"' -f $mockEmitGroupClaimsRuleName 'c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Value == "{0}", Issuer == "AD AUTHORITY"]' -f ` $mockAdGroupSid '=> issue(Type = "{0}", Value = "{1}", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, ValueType = c.ValueType);' -f ` $mockOutgoingClaimType, $mockOutgoingClaimValue ) | Out-String mock -CommandName Get-AdGroupSid -MockWith { $mockAdGroupSid } } It 'Should return the correct result' { ConvertTo-IssuanceTransformRule -InputObject $mockEmitGroupClaimsIssuanceTransformRules | ` Should -Be $mockEmitGroupClaimsTransformRule } It 'Should call the expected mocks' { Assert-MockCalled -CommandName Get-AdGroupSid ` -ParameterFilter { $GroupName -eq $mockAdGroupName } ` -Exactly -Times 1 } } Context 'When the transform rule is of type CustomClaims' { BeforeAll { $mockCustomClaimsTemplateName = 'CustomClaims' $mockCustomClaimsRuleName = 'Test' $customRule = 'Custom Claim Rule Text' $mockCustomClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockCustomClaimsTemplateName Name = $mockCustomClaimsRuleName CustomRule = $customRule } $mockCustomClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockCustomClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) $mockCustomClaimsTransformRule = @( '@RuleName = "{0}"' -f $mockCustomClaimsRuleName $customRule ) | Out-String } It 'Should return the correct result' { ConvertTo-IssuanceTransformRule -InputObject $mockCustomClaimsIssuanceTransformRules | ` Should -Be $mockCustomClaimsTransformRule } It 'Should call the expected mocks' { Assert-MockCalled -CommandName Get-AdGroupSid -Exactly -Times 0 } } Context 'When the transform rule template is of an unknown type' { BeforeAll { $mockUnknownTemplateName = 'UnknownClaims' $mockUnknownRuleName = 'Test' $mockUnknownMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockUnknownTemplateName Name = $mockUnknownRuleName } $mockUnknownIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockUnknownMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) It 'Should return the correct error' { { ConvertTo-IssuanceTransformRule -InputObject $mockUnknownIssuanceTransformRules } | Should Throw ($script:localizedData.UnknownIssuanceTransformRuleTemplateError -f $mockUnknownTemplateName) } It 'Should call the expected mocks' { Assert-MockCalled -CommandName Get-AdGroupSid -Exactly -Times 0 } } } } Describe 'AdfsDsc.Common\ConvertFrom-IssuanceTransformRule' { BeforeAll { mock -CommandName Get-AdGroupNameFromSid } Context 'When the transform rule is of type LdapClaims' { BeforeAll { $mockLdapAttributes = @( 'mail' 'sn' ) $mockOutgoingClaimTypes = @( 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress' 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname' ) $MSFT_AdfsLdapMappingProperties = @( @{ LdapAttribute = $mockLdapAttributes[0] OutgoingClaimType = $mockOutgoingClaimTypes[0] } @{ LdapAttribute = $mockLdapAttributes[1] OutgoingClaimType = $mockOutgoingClaimTypes[1] } ) $mockLdapClaimsTemplateName = 'LdapClaims' $mockLdapClaimsRuleName = 'Test' } Context 'When the Ldap Mapping has a single entry' { BeforeAll { $mockSingleLdapMapping = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsLdapMapping ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $MSFT_AdfsLdapMappingProperties[0] -ClientOnly ) $mockSingleLdapClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockLdapClaimsTemplateName Name = $mockLdapClaimsRuleName AttributeStore = 'Active Directory' LdapMapping = $mockSingleLdapMapping } $mockSingleLdapClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockSingleLdapClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) $mockSingleLdapClaimsTransformRule = @( '@RuleTemplate = "{0}"' -f $mockLdapClaimsTemplateName '@RuleName = "{0}"' -f $mockLdapClaimsRuleName 'c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]' '=> issue(store = "Active Directory", types = ("{1}"), query = ";{2};{0}", param = c.Value);' -f ` '{0}', $mockOutgoingClaimTypes[0], $mockLdapAttributes[0] ) | Out-String } It 'Should return the correct result' { $issuanceTransformRule = ConvertFrom-IssuanceTransformRule -Rule $mockSingleLdapClaimsTransformRule (Compare-IssuanceTransformRule -CurrentValue $issuanceTransformRule ` -DesiredValue $mockSingleLdapClaimsIssuanceTransformRules).InDesiredState | Should -BeTrue } It 'Should call the expected mocks' { Assert-MockCalled -CommandName Get-AdGroupNameFromSid -Exactly -Times 0 } } Context 'When the LDAP mapping has multiple entries' { BeforeAll { $mockMultiLdapMapping = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsLdapMapping ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $MSFT_AdfsLdapMappingProperties[0] -ClientOnly New-CimInstance -ClassName MSFT_AdfsLdapMapping ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $MSFT_AdfsLdapMappingProperties[1] -ClientOnly ) $mockMultiLdapClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockLdapClaimsTemplateName Name = $mockLdapClaimsRuleName AttributeStore = 'Active Directory' LdapMapping = $mockMultiLdapMapping } $mockMultiLdapClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockMultiLdapClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) $mockMultiLdapClaimsTransformRule = @( '@RuleTemplate = "{0}"' -f $mockLdapClaimsTemplateName '@RuleName = "{0}"' -f $mockLdapClaimsRuleName 'c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]' '=> issue(store = "Active Directory", types = ("{1}", "{2}"), query = ";{3},{4};{0}", param = c.Value);' -f ` '{0}', $mockOutgoingClaimTypes[0], $mockOutgoingClaimTypes[1], $mockLdapAttributes[0], $mockLdapAttributes[1] ) | Out-String } It 'Should return the correct result' { $issuanceTransformRule = ConvertFrom-IssuanceTransformRule -Rule $mockMultiLdapClaimsTransformRule (Compare-IssuanceTransformRule -CurrentValue $issuanceTransformRule ` -DesiredValue $mockMultiLdapClaimsIssuanceTransformRules).InDesiredState | Should -BeTrue } It 'Should call the expected mocks' { Assert-MockCalled -CommandName Get-AdGroupNameFromSid -Exactly -Times 0 } } } Context 'When the transform rule is of type EmitGroupClaims' { BeforeAll { $mockEmitGroupClaimsTemplateName = 'EmitGroupClaims' $mockEmitGroupClaimsRuleName = 'Test' $mockAdGroupName = 'Test Group' $mockAdGroupSid = 'd382a151-2a2c-4f0f-a6e7-8de159333cd2' $mockOutgoingClaimType = 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role' $mockOutgoingClaimValue = 'User' $mockEmitGroupClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockEmitGroupClaimsTemplateName Name = $mockEmitGroupClaimsRuleName GroupName = $mockAdGroupName OutgoingClaimType = $mockOutgoingClaimType OutgoingClaimValue = $mockOutgoingClaimValue } $mockEmitGroupClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockEmitGroupClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) $mockEmitGroupClaimsTransformRule = @( '@RuleTemplate = "{0}"' -f $mockEmitGroupClaimsTemplateName '@RuleName = "{0}"' -f $mockEmitGroupClaimsRuleName 'c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid", Value == "{0}", Issuer == "AD AUTHORITY"]' -f ` $mockAdGroupSid '=> issue(Type = "{0}", Value = "{1}", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, ValueType = c.ValueType);' -f ` $mockOutgoingClaimType, $mockOutgoingClaimValue ) | Out-String mock -CommandName Get-AdGroupNameFromSid -MockWith { $mockAdGroupName } } It 'Should return the correct result' { $issuanceTransformRule = ConvertFrom-IssuanceTransformRule -Rule $mockEmitGroupClaimsTransformRule (Compare-IssuanceTransformRule -CurrentValue $issuanceTransformRule ` -DesiredValue $mockEmitGroupClaimsIssuanceTransformRules).InDesiredState | Should -BeTrue } It 'Should call the expected mocks' { Assert-MockCalled -CommandName Get-AdGroupNameFromSid ` -ParameterFilter { $Sid -eq $mockAdGroupSid } ` -Exactly -Times 1 } } Context 'When the transform rule is of type CustomClaims' { BeforeAll { $mockCustomClaimsTemplateName = 'CustomClaims' $mockCustomClaimsRuleName = 'Test' $customRule = 'Custom Claim Rule Text' $mockCustomClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockCustomClaimsTemplateName Name = $mockCustomClaimsRuleName CustomRule = $customRule } $mockCustomClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockCustomClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) $mockCustomClaimsTransformRule = @( '@RuleName = "{0}"' -f $mockCustomClaimsRuleName $customRule ) | Out-String } It 'Should return the correct result' { $issuanceTransformRule = ConvertFrom-IssuanceTransformRule -Rule $mockCustomClaimsTransformRule (Compare-IssuanceTransformRule -CurrentValue $issuanceTransformRule ` -DesiredValue $mockCustomClaimsIssuanceTransformRules).InDesiredState | Should -BeTrue } It 'Should call the expected mocks' { Assert-MockCalled -CommandName Get-AdGroupNameFromSid -Exactly -Times 0 } } } Describe 'AdfsDsc.Common\Compare-IssuanceTransformRule' { Context 'When the transform rule contains an LdapClaims rule' { BeforeAll { $mockLdapAttributes = @( 'mail' 'sn' ) $mockOutgoingClaimTypes = @( 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress' 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname' ) $CurrentMSFT_AdfsLdapMappingProperties = @( @{ LdapAttribute = $mockLdapAttributes[0] OutgoingClaimType = $mockOutgoingClaimTypes[0] } ) $mockLdapClaimsTemplateName = 'LdapClaims' $mockLdapClaimsRuleName = 'Test' $mockCurrentLdapMapping = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsLdapMapping ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $CurrentMSFT_AdfsLdapMappingProperties[0] -ClientOnly ) $mockCurrentLdapClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockLdapClaimsTemplateName Name = $mockLdapClaimsRuleName AttributeStore = 'Active Directory' LdapMapping = $mockCurrentLdapMapping } $mockCurrentLdapClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockCurrentLdapClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) $DesiredMSFT_AdfsLdapMappingProperties = @( @{ LdapAttribute = $mockLdapAttributes[1] OutgoingClaimType = $mockOutgoingClaimTypes[1] } ) $mockDesiredLdapMapping = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsLdapMapping ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $DesiredMSFT_AdfsLdapMappingProperties[1] -ClientOnly ) $mockDesiredLdapClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockLdapClaimsTemplateName Name = $mockLdapClaimsRuleName AttributeStore = 'Active Directory' LdapMapping = $mockDesiredLdapMapping } $mockDesiredLdapClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockDesiredLdapClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) } Context 'When both LdapClaims rules are the same' { BeforeAll { $compareIssuanceTransformRuleResult = Compare-IssuanceTransformRule ` -CurrentValue $mockCurrentLdapClaimsIssuanceTransformRules ` -DesiredValue $mockCurrentLdapClaimsIssuanceTransformRules } It 'Should return the correct result' { $compareIssuanceTransformRuleResult | Should -HaveCount 1 $compareIssuanceTransformRuleResult.ParameterName | Should -Be 'IssuanceTransformRules' $compareIssuanceTransformRuleResult.InDesiredState | Should -BeTrue } } Context 'When the LdapClaims rules are different' { BeforeAll { $compareIssuanceTransformRuleResult = Compare-IssuanceTransformRule ` -CurrentValue $mockCurrentLdapClaimsIssuanceTransformRules ` -DesiredValue $mockDesiredLdapClaimsIssuanceTransformRules } It 'Should return the correct result' { $compareIssuanceTransformRuleResult | Should -HaveCount 1 $compareIssuanceTransformRuleResult.ParameterName | Should -Be 'IssuanceTransformRules' $compareIssuanceTransformRuleResult.InDesiredState | Should -BeFalse } } } Context 'When the transform rule contains an EmitGroupClaims rule' { BeforeAll { $mockEmitGroupClaimsTemplateName = 'EmitGroupClaims' $mockEmitGroupClaimsRuleName = 'Test' $mockCurrentAdGroupName = 'Test Group' $mockOutgoingClaimType = 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role' $mockOutgoingClaimValue = 'User' $mockCurrentEmitGroupClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockEmitGroupClaimsTemplateName Name = $mockEmitGroupClaimsRuleName GroupName = $mockCurrentAdGroupName OutgoingClaimType = $mockOutgoingClaimType OutgoingClaimValue = $mockOutgoingClaimValue } $mockCurrentEmitGroupClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockCurrentEmitGroupClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) $mockDesiredAdGroupName = 'Test Group 2' $mockDesiredEmitGroupClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockEmitGroupClaimsTemplateName Name = $mockEmitGroupClaimsRuleName GroupName = $mockDesiredAdGroupName OutgoingClaimType = $mockOutgoingClaimType OutgoingClaimValue = $mockOutgoingClaimValue } $mockDesiredEmitGroupClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockDesiredEmitGroupClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) } Context 'When both EmitGroupClaims rules are the same' { BeforeAll { $compareIssuanceTransformRuleResult = Compare-IssuanceTransformRule ` -CurrentValue $mockCurrentEmitGroupClaimsIssuanceTransformRules ` -DesiredValue $mockCurrentEmitGroupClaimsIssuanceTransformRules } It 'Should return the correct result' { $compareIssuanceTransformRuleResult | Should -HaveCount 1 $compareIssuanceTransformRuleResult.ParameterName | Should -Be 'IssuanceTransformRules' $compareIssuanceTransformRuleResult.InDesiredState | Should -BeTrue } } Context 'When the EmitGroupClaims rules are different' { BeforeAll { $compareIssuanceTransformRuleResult = Compare-IssuanceTransformRule ` -CurrentValue $mockCurrentEmitGroupClaimsIssuanceTransformRules ` -DesiredValue $mockDesiredEmitGroupClaimsIssuanceTransformRules } It 'Should return the correct result' { $compareIssuanceTransformRuleResult | Should -HaveCount 1 $compareIssuanceTransformRuleResult.ParameterName | Should -Be 'IssuanceTransformRules' $compareIssuanceTransformRuleResult.InDesiredState | Should -BeFalse } } } Context 'When the transform rule contains a CustomClaims rule' { BeforeAll { $mockCustomClaimsTemplateName = 'CustomClaims' $mockCustomClaimsRuleName = 'Test' $mockCustomRule = 'Custom Claim Rule Text' $mockCurrentCustomClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockCustomClaimsTemplateName Name = $mockCustomClaimsRuleName CustomRule = $mockCustomRule } $mockCurrentCustomClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockCurrentCustomClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) } Context 'When both CustomClaims rules are the same' { BeforeAll { $compareIssuanceTransformRuleResult = Compare-IssuanceTransformRule ` -CurrentValue $mockCurrentCustomClaimsIssuanceTransformRules ` -DesiredValue $mockCurrentCustomClaimsIssuanceTransformRules } It 'Should return the correct result' { $compareIssuanceTransformRuleResult | Should -HaveCount 1 $compareIssuanceTransformRuleResult.ParameterName | Should -Be 'IssuanceTransformRules' $compareIssuanceTransformRuleResult.InDesiredState | Should -BeTrue } } Context 'When the CustomClaims rules are different' { BeforeAll { $mockDesiredCustomRule = 'Custom Claim Rule Text 2' $mockDesiredCustomClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockCustomClaimsTemplateName Name = $mockCustomClaimsRuleName CustomRule = $mockDesiredCustomRule } $mockDesiredCustomClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockDesiredCustomClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) $compareIssuanceTransformRuleResult = Compare-IssuanceTransformRule ` -CurrentValue $mockCurrentCustomClaimsIssuanceTransformRules ` -DesiredValue $mockDesiredCustomClaimsIssuanceTransformRules } It 'Should return the correct result' { $compareIssuanceTransformRuleResult | Should -HaveCount 1 $compareIssuanceTransformRuleResult.ParameterName | Should -Be 'IssuanceTransformRules' $compareIssuanceTransformRuleResult.InDesiredState | Should -BeFalse } } Context 'When the Rule Name has changed' { BeforeAll { $mockDesiredCustomClaimsRuleName = 'Test2' $mockDesiredCustomClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockCustomClaimsTemplateName Name = $mockDesiredCustomClaimsRuleName CustomRule = $mockCustomRule } $mockDesiredCustomClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockDesiredCustomClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) $compareIssuanceTransformRuleResult = Compare-IssuanceTransformRule ` -CurrentValue $mockCurrentCustomClaimsIssuanceTransformRules ` -DesiredValue $mockDesiredCustomClaimsIssuanceTransformRules } It 'Should return the correct result' { $compareIssuanceTransformRuleResult | Should -HaveCount 1 $compareIssuanceTransformRuleResult.ParameterName | Should -Be 'IssuanceTransformRules' $compareIssuanceTransformRuleResult.InDesiredState | Should -BeFalse } } } Context 'When the Template Name has changed' { BeforeAll { $mockCustomClaimsTemplateName = 'CustomClaims' $mockCustomClaimsRuleName = 'Test' $mockCurrentCustomClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockCustomClaimsTemplateName Name = $mockCustomClaimsRuleName } $mockCurrentCustomClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockCurrentCustomClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) $mockLdapClaimsTemplateName = 'LdapClaims' $mockLdapClaimsRuleName = 'Test' $mockCurrentCustomClaimsMSFT_AdfsIssuanceTransformRuleProperties = @{ TemplateName = $mockLdapClaimsTemplateName Name = $mockLdapClaimsRuleName } $mockDesiredLdapClaimsIssuanceTransformRules = [CIMInstance[]]@( New-CimInstance -ClassName MSFT_AdfsIssuanceTransformRule ` -Namespace root/microsoft/Windows/DesiredStateConfiguration ` -Property $mockDesiredLdapClaimsMSFT_AdfsIssuanceTransformRuleProperties -ClientOnly ) $compareIssuanceTransformRuleResult = Compare-IssuanceTransformRule ` -CurrentValue $mockCurrentCustomClaimsIssuanceTransformRules ` -DesiredValue $mockDesiredLdapClaimsIssuanceTransformRules } It 'Should return the correct result' { $compareIssuanceTransformRuleResult | Should -HaveCount 1 $compareIssuanceTransformRuleResult.ParameterName | Should -Be 'IssuanceTransformRules' $compareIssuanceTransformRuleResult.InDesiredState | Should -BeFalse } } } } |