src/crm-ci.Tests.ps1
$here = Split-Path -Parent $MyInvocation.MyCommand.Path $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.' . "$here\$sut" $path = "$env:HOME\$env:USERNAME" + "_$env:COMPUTERNAME.xml" if (-not (Test-Path $path)) { Set-StoredCredentials } Function Assert-PropertiesMatch { Param ( $Expected, $Actual ) Process { foreach ($prop in ($Expected.psobject.properties.name)) { if ($Expected."$prop".GetType().Name -eq "DateTime") { [string]$Actual."$prop".ToString() | Should -Be $Expected."$prop".ToString() } else { [string]$Actual."$prop" | Should -Be $Expected."$prop" } } } } Describe "Get-CrmConnectionString" { It "Returns either a connection string or just the url depending on the -UrlOnly switch" { [string]$connString = Get-CrmConnectionString -CrmInstance CRMADVISE $connString.StartsWith("RequireNewInstance=True;AuthType=AD;Url=") | Should -Be $true [string]$urlOnly = Get-CrmConnectionString -CrmInstance CRMADVISE -UrlOnly $urlOnly.StartsWith("https://") | Should -Be $true } It "Returns the correct address based on the crm instance" { [string]$connString = Get-CrmConnectionString -CrmInstance CRMADVISETEST $connString | Should -Be "RequireNewInstance=True;AuthType=AD;Url=https://advisedevcrm.regent.edu/CRMADVISETEST;" } } Describe "Get-RegentConnection" { It "should call through to Get-CrmConnection" { $regent = Get-RegentConnection -CrmInstance CRMRECRUITTEST $datatTools = (Get-CrmConnection -ConnectionString "RequireNewInstance=True;AuthType=AD;Url=https://rctrdevcrm.regent.edu/CRMRECRUITTEST;") $regent.GetType() | Should -Be $datatTools.GetType() } } Describe "Export-RegentSolution" { Context "Given a config file specifying repository path TestDrive:/solutions" { New-Item TestDrive:\solutions -ItemType Directory Mock 'Get-Config' { [PSCustomObject]@{ RepositoryPath = "TestDrive:\solutions"; DefaultBranch = "master"; } } It "should download the solution as both managed and unmanged, and export it to the path specified in the config" { $conn = Get-RegentConnection -CrmInstance CRMRECRUITTEST $results = Export-RegentSolution -SolutionName "RecordLocked" -conn $conn -Verbose $results[0].ExportSolutionResponse.GetType().Name | Should -Be "ExportSolutionResponse" $results[1].ExportSolutionResponse.GetType().Name | Should -Be "ExportSolutionResponse" Test-Path "TestDrive:/solutions/RecordLocked/" | Should -Be $true } } } Describe "Get-SolutionImportLog" { Context "Given an ImportJob existing in CRM CRMRECRUITTEST with an ID of 60255876-6aae-e511-80c2-0050569b65f8" { $exportPath = "TestDrive:\logs\log.xml" $id = "60255876-6aae-e511-80c2-0050569b65f8" It "Should return the formatted xml results and export them if specified" { $results = Get-SolutionImportLog ` -CrmInstance CRMRECRUITTEST ` -ImportJobId $id ` -ExportPath $exportPath ` $results | Should -Not -BeNullOrEmpty Test-Path $exportPath | Should -Be $true $contents = Get-Content $exportPath $contents | Should -Be $results[1] } } } Describe "Import-RegentSolution" { Context "Given a config file specifying repository path TestDrive:/solutions" { New-Item TestDrive:\solutions -ItemType Directory Mock 'Get-Config' { [PSCustomObject]@{ RepositoryPath = "C:\repos\ps\crm-ci\test-data\unpacked"; DefaultBranch = "master"; } } It "Should Import the solution by default" { Import-RegentSolution ` -SolutionName RecordLocked ` -CrmInstance CRMRECRUITTEST ` -Emails "dhines@regent.edu" ` -Managed $false ` -Verbose } It "Should throw any import errors and email the error message" { # In this example, I'm importing a managed version of solution into a CRM that # has the unmanged version intalled, which will cause an import error { Import-RegentSolution ` -SolutionName RecordLocked ` -CrmInstance CRMRECRUITTEST ` -Managed $true ` -Emails "dhines@regent.edu" ` -Verbose } | Should -Throw } } } # Describe "Invoke-RegentScheduledImports" { # 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 # } # # On reconsideration, I don't think it should throw an error, since it will be run all the time by the task scheduler, whether or not a config file has been created # # 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 # } # } # } Describe "Move-RegentSolution" { Mock -CommandName Import-RegentSolution -Verifiable -MockWith {"Hello World!" > success.txt} Mock -CommandName Export-RegentSolution -Verifiable -MockWith {return} Mock -CommandName Push-RegentSolutionChanges -Verifiable -MockWith {return} $configPath = "$env:APPDATA\solution-imports.json" Context "Given a config file with a repository path TestDrive:/" { BeforeEach { if (Test-Path $configPath) { Remove-Item $configPath -Force } } It "Should export the specified solution, unpack it, and push the changes" { Move-RegentSolution ` -SolutionName "RegentUniversity" ` -SourceCrmInstance CRMRECRUIT ` -DestinationCrmInstance CRMRECRUIT ` -Managed $true ` -PublishCustomizations $true ` -Emails "dhines@regent.edu;bryatho@regent.edu;acofer@regent.edu" ` -UpdateVersion "2.5" ` -CommitMessage "Initial Commit" ` -Branch "mybranch" ` -ImportTime (Get-Date).AddSeconds(3) ` -Force Assert-MockCalled -Scope It -CommandName Export-RegentSolution ` -Exactly 1 ` -ParameterFilter { $SolutionName -eq "RegentUniversity" ` -and $UpdateVersion -eq "2.5" } Assert-MockCalled -Scope It -CommandName Push-RegentSolutionChanges ` -Exactly 1 ` -ParameterFilter { $CommitMessage -eq "Initial Commit" ` -and $Branch -eq "mybranch" } } It "Should import the solution immediately if no time is specified" { Move-RegentSolution ` -SolutionName "RegentUniversity" ` -SourceCrmInstance CRMRECRUIT ` -DestinationCrmInstance CRMRECRUIT ` -Managed $true ` -PublishCustomizations $true ` -Emails "dhines@regent.edu;bryatho@regent.edu;acofer@regent.edu" ` -UpdateVersion "2.5" ` -CommitMessage "Initial Commit" ` -Branch "mybranch" ` -Force Assert-MockCalled -Scope It -CommandName Import-RegentSolution ` -Exactly 1 ` -ParameterFilter { $SolutionName -eq "RegentUniversity" ` -and $CrmInstance -eq "CRMRECRUIT" ` -and $Managed -eq $true ` -and $PublishCustomizations -eq $true ` -and $Emails -eq "dhines@regent.edu;bryatho@regent.edu;acofer@regent.edu" ` } } It "Should schedule the import job for the specified time by adding it to the config" { $time = (Get-Date).AddHours(1).ToUniversalTime() $expectedConfig = [pscustomobject] @{ UserName = $env:USERNAME; CrmInstance = "CRMRECRUIT"; PublishCustomizations = $true; Managed = $true; SolutionName = "RegentUniversity"; Emails = "dhines@regent.edu;bryatho@regent.edu;acofer@regent.edu"; Time = $time; } $Result = Move-RegentSolution ` -SolutionName $expectedConfig.SolutionName ` -SourceCrmInstance CRMRECRUIT ` -DestinationCrmInstance $expectedConfig.CrmInstance ` -Managed $expectedConfig.Managed ` -PublishCustomizations $expectedConfig.PublishCustomizations ` -Emails $expectedConfig.Emails ` -CommitMessage "Initial Commit" ` -Branch "mybranch" ` -ImportTime $time ` -Force $Result.Command | Should -Be ` "Import-RegentSolution -Verbose @{PublishCustomizations=`$true; SolutionName=RegentUniversity; Managed=`$true; CrmInstance=CRMRECRUIT} -Emails ""dhines@regent.edu;bryatho@regent.edu;acofer@regent.edu""" } It "Should throw an error if the specified solution isn't found" { {Move-RegentSolution ` -Credential $global:cred ` -SolutionName "NonExistingSolution" ` -SourceCrmInstance CRMRECRUIT ` -DestinationCrmInstance CRMRECRUIT ` -Managed $true ` -PublishCustomizations $true ` -Emails "dhines@regent.edu;bryatho@regent.edu;acofer@regent.edu" ` -UpdateVersion "2.5" ` -CommitMessage "Initial Commit" ` -Branch "mybranch" ` -ImportTime (Get-Date).AddSeconds(5) ` -Force} | Should -Throw } } } |