functions/Invoke-RegentScheduledImports.Tests.ps1
$here = Split-Path -Parent $MyInvocation.MyCommand.Path $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.' . "$here\$sut" . "$here\Import-RegentSolution.ps1" . "$here\TestingUtils.ps1" Import-Module -Name Microsoft.Xrm.Data.Powershell if (-not $global:cred) { $global:cred = Get-Credential -Message "Enter Credentials to run the tests with" -UserName $env:USERNAME } # This var is used in almost all the tests, so it's declared here Describe "Move-RegentSolution" { Mock -CommandName Import-RegentSolution -Verifiable -MockWith {return} New-Item TestDrive:\solutions -ItemType Directory Mock 'Get-Config' { [PSCustomObject]@{ RepositoryPath = "TestDrive:\solutions"; DefaultBranch = "master"; } } $configPath = "TestDrive:\solutions\solution-imports.json" Context "Given no import jobs" { if (Test-Path $configPath) { Remove-Item $configPath } It "Should throw an error if the config file doesn't exist" { { Invoke-RegentScheduledImports } | Should -Throw } It "Should do nothing if there are no scheduled jobs" { "" > $configPath { Invoke-RegentScheduledImports } | Should -Not -Throw } } Context "Given only one import job that's due on runtime" { BeforeEach { $time = (Get-Date).ToUniversalTime() $testConfig = [pscustomobject] @{ UserName = $env:USERNAME; CrmInstance = "CRMRECRUIT"; PublishCustomizations = $true; Managed = $true; SolutionName = "RegentUniversity"; Emails = "dhines@regent.edu;bryatho@regent.edu;acofer@regent.edu"; Time = $time; Password = $global:cred.Password | ConvertFrom-SecureString } $testConfig | ConvertTo-Json > $configPath } It "Should call Import-RegentSolution, then remove it" { Invoke-RegentScheduledImports Assert-MockCalled -CommandName "Import-RegentSolution" -Scope It -Exactly 1 ` -ParameterFilter { $SolutionName -eq $testConfig.SolutionName ` -and $CrmInstance -eq $testConfig.CrmInstance ` -and $Managed -eq $testConfig.Managed ` -and $PublishCustomizations -eq $testConfig.PublishCustomizations ` -and $Emails -eq $testConfig.Emails ` -and $Credential.UserName -eq $testConfig.UserName } $results = Get-Content $configPath | ConvertFrom-Json $results | Should -Be $null } } Context "Given only one import job that's not due yet" { BeforeEach { $time = (Get-Date).AddHours(1).ToUniversalTime() $testConfig = [pscustomobject] @{ UserName = $env:USERNAME; CrmInstance = "CRMRECRUIT"; PublishCustomizations = $true; Managed = $true; SolutionName = "RegentUniversity"; Emails = "dhines@regent.edu;bryatho@regent.edu;acofer@regent.edu"; Time = $time; Password = $global:cred.Password | ConvertFrom-SecureString } $testConfig | ConvertTo-Json > $configPath } It "Should skip the job if it's not due" { Invoke-RegentScheduledImports Assert-MockCalled -CommandName "Import-RegentSolution" -Scope It -Exactly 0 $results = Get-Content $configPath | ConvertFrom-Json ` | Select-Object -Property * -ExcludeProperty Password $expected = $testConfig | Select-Object -Property * -ExcludeProperty Password Assert-PropertiesMatch -Expected $expected -Actual $results } } Context "Given multiple import jobs" { BeforeEach { $time1 = (Get-Date).ToUniversalTime() $time2 = (Get-Date).AddHours(2).ToUniversalTime() $time3 = (Get-date).AddHours(-1).ToUniversalTime() # Configs 1 and two are identical except for the time, # so asserting Import-RegentSolution is only called once will test the filtering capabilitiy $config1 = [pscustomobject] @{ UserName = $env:USERNAME; CrmInstance = "CRMRECRUIT"; PublishCustomizations = $true; Managed = $true; SolutionName = "RegentUniversity"; Emails = "dhines@regent.edu;bryatho@regent.edu;acofer@regent.edu"; Time = $time1; Password = $global:cred.Password | ConvertFrom-SecureString } $config2 = [pscustomobject] @{ UserName = $env:USERNAME; CrmInstance = "CRMRECRUIT"; PublishCustomizations = $true; Managed = $true; SolutionName = "RegentUniversity"; Emails = "dhines@regent.edu;bryatho@regent.edu;acofer@regent.edu"; Time = $time2; Password = $global:cred.Password | ConvertFrom-SecureString } $config3 = [pscustomobject] @{ UserName = $env:USERNAME; CrmInstance = "CRMADVISE"; PublishCustomizations = $true; Managed = $true; SolutionName = "FooSolution"; Emails = "bam@baz.com"; Time = $time3; Password = $global:cred.Password | ConvertFrom-SecureString } @($config1, $config2, $config3) | ConvertTo-Json > $configPath } It "Should call Import-RegentSolution on each job that is due" { Invoke-RegentScheduledImports Assert-MockCalled -CommandName "Import-RegentSolution" -Scope It -Exactly 1 ` -ParameterFilter { $SolutionName -eq $config1.SolutionName ` -and $CrmInstance -eq $config1.CrmInstance ` -and $Managed -eq $config1.Managed ` -and $PublishCustomizations -eq $config1.PublishCustomizations ` -and $Emails -eq $config1.Emails ` -and $Credential.UserName -eq $config1.UserName } Assert-MockCalled -CommandName "Import-RegentSolution" -Scope It -Exactly 1 ` -ParameterFilter { $SolutionName -eq $config3.SolutionName ` -and $CrmInstance -eq $config3.CrmInstance ` -and $Managed -eq $config3.Managed ` -and $PublishCustomizations -eq $config3.PublishCustomizations ` -and $Emails -eq $config3.Emails ` -and $Credential.UserName -eq $config3.UserName } } It "Should remove a job from the config after a successful import" { Invoke-RegentScheduledImports $results = Get-Content $configPath | ConvertFrom-Json ` | Select-Object -Property * -ExcludeProperty Password $expected = $config2 | Select-Object -Property * -ExcludeProperty Password Assert-PropertiesMatch -Expected $expected -Actual $results } } } |