functions/Move-RegentSolution.Tests.ps1

$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
. "$here\$sut"
. "$here\Export-RegentSolution.ps1"
. "$here\Import-RegentSolution.ps1"
. "$here\Push-RegentSolutionChanges.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
$configPath = "$env:APPDATA\solution-imports.json"

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}
  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 `
        -Credential $global:cred `
        -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(5) `
        -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 `
        -Credential $global:cred `
        -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" `
          -and $Credential -eq $global:cred
      }
    }

    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;
      }
      Move-RegentSolution `
        -Credential $global:cred `
        -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
      
      Test-Path $configPath | Should -Be $true
      #Grab the config, but exclude the password
      $config = (Get-Content $configPath) | ConvertFrom-Json | Select-Object -Property "*" -ExcludeProperty "Password"

      Assert-PropertiesMatch -Expected $expectedConfig -Actual $config
    }

    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
    }

    It "Should handle existing jobs by appending the new job to the existing file" {
      $preExistingConfig = [pscustomobject] @{
        UserName              = $env:USERNAME;
        CrmInstance           = "CRMRECRUIT";
        PublishCustomizations = $true;
        Managed               = $true;
        SolutionName          = "RegentUniversity";
        Emails                = "dhines@regent.edu;bryatho@regent.edu;acofer@regent.edu";
        Time                  = "13:00"
        Password              = $global:cred.Password | ConvertFrom-SecureString
      }
      $preExistingConfig | ConvertTo-Json > $configPath

      $time = (Get-Date).AddHours(1).ToUniversalTime()
      $expectedConfig = [pscustomobject] @{
        UserName              = $env:USERNAME;
        CrmInstance           = "CRMRECRUIT";
        PublishCustomizations = $true;
        Managed               = $true;
        SolutionName          = "RecordLocked";
        Emails                = "dhines@regent.edu;";
        Time                  = $time;
      }
  
      Move-RegentSolution `
        -Credential $global:cred `
        -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

      $newConfig = Get-Content $configPath `
        | ConvertFrom-Json | Select-Object -Property "*" -ExcludeProperty "Password"

      Assert-PropertiesMatch -Expected $preExistingConfig -Actual $newConfig.SyncRoot[0]
      Assert-PropertiesMatch -Expected $expectedConfig -Actual $newConfig.SyncRoot[1]
    }
  }
}