Functions/Import-BT_Module.Tests.ps1
describe "BitTitan.Runbooks.Modules/Import-BT_Module" -Tag "module", "unit" { # Import the function to test . "$($PSScriptRoot)\Import-BT_Module.ps1" # Declare external functions and mocks function Get-Module { param ($Name, [Switch]$ListAvailable) } function Install-Module { param ($Name) } function Find-Module { param ($Name) } function Get-ChildItem {} function Test-Path { return $true } # Retrieve the current BitTitan Runbook Environment settings $previousPSDefaultParameterValues = $Global:PSDefaultParameterValues context "when running on the Prod local machine environment" { # Declare mocks mock Install-Module {} mock Import-Module {} mock Get-Module { return [PSCustomObject]@{ Path = "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" Version = [Version]"0.1.0" } } mock Get-ChildItem { return [PSCustomObject]@{ FullName = "NestedModuleFullName" } } # Set up the settings $Global:PSDefaultParameterValues["*-BT_*:Environment"] = "BT" $Global:PSDefaultParameterValues["*-BT_*:IsRunningOnLocalMachine"] = $true it "imports the module" { # Call the function Import-BT_Module BitTitan.Runbooks.TestModule -ErrorAction SilentlyContinue -ErrorVariable errorVariable # Verify the mocks Assert-MockCalled Install-Module -Times 0 -Exactly -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "NestedModuleFullName" } -Scope it Assert-MockCalled Get-Module -Times 2 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it # Verify the output $errorVariable | Should BeNullOrEmpty } } context "when running on the Beta local machine environment" { # Declare mocks mock Install-Module {} mock Import-Module {} mock Get-Module { return [PSCustomObject]@{ Path = "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" Version = [Version]"0.1.0" } } mock Get-ChildItem { return [PSCustomObject]@{ FullName = "NestedModuleFullName" } } # Set up the settings $Global:PSDefaultParameterValues["*-BT_*:Environment"] = "Beta" $Global:PSDefaultParameterValues["*-BT_*:IsRunningOnLocalMachine"] = $true it "imports the module" { # Call the function Import-BT_Module BitTitan.Runbooks.TestModule -ErrorAction SilentlyContinue -ErrorVariable errorVariable # Verify the mocks Assert-MockCalled Install-Module -Times 0 -Exactly -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "NestedModuleFullName" } -Scope it Assert-MockCalled Get-Module -Times 2 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it # Verify the output $errorVariable | Should BeNullOrEmpty } } context "when running on the Prod MSPComplete environment" { # Declare mocks mock Install-Module {} mock Import-Module {} $Script:numberTimesGetChildItemCalled = 0 mock Get-ChildItem { if ($Script:numberTimesGetChildItemCalled -eq 0) { $Script:numberTimesGetChildItemCalled += 1 return } elseif ($Script:numberTimesGetChildItemCalled -eq 1) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ Name = "0.1.0" } } return [PSCustomObject]@{ FullName = "NestedModuleFullName" } } mock Get-Module { return [PSCustomObject]@{ Path = "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" Version = [Version]"0.1.0" } } # Set up the settings $Global:PSDefaultParameterValues["*-BT_*:Environment"] = "BT" $Global:PSDefaultParameterValues["*-BT_*:IsRunningOnLocalMachine"] = $false it "installs and imports the module if the module is currently not installed" { # Call the function Import-BT_Module BitTitan.Runbooks.TestModule -ErrorAction continue -ErrorVariable errorVariable # Verify the mocks Assert-MockCalled Install-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "NestedModuleFullName" } -Scope it Assert-MockCalled Get-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it # Verify the output $errorVariable | Should BeNullOrEmpty } # Declare mocks $Script:numberTimesGetChildItemCalled = 0 mock Get-ChildItem { if ($Script:numberTimesGetChildItemCalled -eq 0) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ FullName = "BitTitan.Runbooks.TestModule" } } elseif ($Script:numberTimesGetChildItemCalled -eq 1) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ Name = "0.1.0" } } elseif ($Script:numberTimesGetChildItemCalled -eq 2) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ Name = "0.2.0" } } return [PSCustomObject]@{ FullName = "NestedModuleFullName" } } mock Get-Module { return [PSCustomObject]@{ Path = "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" Version = [Version]"0.2.0" } } mock Find-Module { return [PSCustomObject]@{ Version = [Version]"0.2.0" } } it "installs and imports the module if the module currently installed is not the latest version" { # Call the function Import-BT_Module BitTitan.Runbooks.TestModule -ErrorAction Continue -ErrorVariable errorVariable # Verify the mocks Assert-MockCalled Find-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Install-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "NestedModuleFullName" } -Scope it Assert-MockCalled Get-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it # Verify the output $errorVariable | Should BeNullOrEmpty } # Declare mocks $Script:numberTimesGetChildItemCalled = 0 mock Get-ChildItem { if ($Script:numberTimesGetChildItemCalled -eq 0) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ FullName = "BitTitan.Runbooks.TestModule" } } elseif ($Script:numberTimesGetChildItemCalled -eq 1) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ Name = "0.1.0" } } return [PSCustomObject]@{ FullName = "NestedModuleFullName" } } mock Get-Module { return [PSCustomObject]@{ Path = "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" Version = [Version]"0.1.0" } } mock Find-Module { return [PSCustomObject]@{ Version = [Version]"0.1.0" } } it "only imports the module if the module currently installed is the latest version" { # Call the function Import-BT_Module BitTitan.Runbooks.TestModule -ErrorAction Continue -ErrorVariable errorVariable # Verify the mocks Assert-MockCalled Find-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Install-Module -Times 0 -Exactly -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "NestedModuleFullName" } -Scope it Assert-MockCalled Get-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it # Verify the output $errorVariable | Should BeNullOrEmpty } } context "when running on the Beta MSPComplete environment" { # Declare mocks mock Install-Module {} mock Import-Module {} $Script:numberTimesGetChildItemCalled = 0 mock Get-ChildItem { if ($Script:numberTimesGetChildItemCalled -eq 0) { $Script:numberTimesGetChildItemCalled += 1 return } elseif ($Script:numberTimesGetChildItemCalled -eq 1) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ Name = "0.1.0" } } return [PSCustomObject]@{ FullName = "NestedModuleFullName" } } mock Get-Module { return [PSCustomObject]@{ Path = "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" Version = [Version]"0.1.0" } } mock Get-Item { return [PSCustomObject]@{ FullName = "FullName" } } mock Move-Item {} # Set up the settings $Global:PSDefaultParameterValues["*-BT_*:Environment"] = "Beta" $Global:PSDefaultParameterValues["*-BT_*:IsRunningOnLocalMachine"] = $false it "installs and imports the module if the module is currently not installed" { # Call the function Import-BT_Module BitTitan.Runbooks.TestModule -ErrorAction SilentlyContinue -ErrorVariable errorVariable # Verify the mocks Assert-MockCalled Install-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule.Beta" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "NestedModuleFullName" } -Scope it Assert-MockCalled Get-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it # Verify the output $errorVariable | Should BeNullOrEmpty } # Declare mocks $Script:numberTimesGetChildItemCalled = 0 mock Get-ChildItem { if ($Script:numberTimesGetChildItemCalled -eq 0) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ FullName = "BitTitan.Runbooks.TestModule" } } elseif ($Script:numberTimesGetChildItemCalled -eq 1) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ Name = "0.1.0" } } elseif ($Script:numberTimesGetChildItemCalled -eq 2) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ Name = "0.2.0" } } return [PSCustomObject]@{ FullName = "NestedModuleFullName" } } mock Get-Module { return [PSCustomObject]@{ Path = "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" Version = [Version]"0.2.0" } } mock Find-Module { return [PSCustomObject]@{ Version = [Version]"0.2.0" } } it "installs and imports the module if the module currently installed is not the latest version" { # Call the function Import-BT_Module BitTitan.Runbooks.TestModule -ErrorAction Continue -ErrorVariable errorVariable # Verify the mocks Assert-MockCalled Find-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Install-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule.Beta" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "NestedModuleFullName" } -Scope it Assert-MockCalled Get-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it # Verify the output $errorVariable | Should BeNullOrEmpty } # Declare mocks $Script:numberTimesGetChildItemCalled = 0 mock Get-ChildItem { if ($Script:numberTimesGetChildItemCalled -eq 0) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ FullName = "BitTitan.Runbooks.TestModule" } } elseif ($Script:numberTimesGetChildItemCalled -eq 1) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ Name = "0.1.0" } } return [PSCustomObject]@{ FullName = "NestedModuleFullName" } } mock Get-Module { return [PSCustomObject]@{ Path = "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" Version = [Version]"0.1.0" } } mock Find-Module { return [PSCustomObject]@{ Version = [Version]"0.1.0" } } it "only imports the module if the module currently installed is the latest version" { # Call the function Import-BT_Module BitTitan.Runbooks.TestModule -ErrorAction Continue -ErrorVariable errorVariable # Verify the mocks Assert-MockCalled Find-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Install-Module -Times 0 -Exactly -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "NestedModuleFullName" } -Scope it Assert-MockCalled Get-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it # Verify the output $errorVariable | Should BeNullOrEmpty } } context "when running on the default environment (Beta MSPComplete)" { # Declare mocks mock Install-Module {} mock Import-Module {} $Script:numberTimesGetChildItemCalled = 0 mock Get-ChildItem { if ($Script:numberTimesGetChildItemCalled -eq 0) { $Script:numberTimesGetChildItemCalled += 1 return } elseif ($Script:numberTimesGetChildItemCalled -eq 1) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ Name = "0.1.0" } } return [PSCustomObject]@{ FullName = "NestedModuleFullName" } } mock Get-Module { return [PSCustomObject]@{ Path = "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" Version = [Version]"0.1.0" } } mock Get-Item { return [PSCustomObject]@{ FullName = "FullName" } } mock Move-Item {} # Set up the settings $Global:PSDefaultParameterValues = @{} it "installs and imports the module" { # Call the function Import-BT_Module BitTitan.Runbooks.TestModule -ErrorAction SilentlyContinue -ErrorVariable errorVariable # Verify the mocks Assert-MockCalled Install-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule.Beta" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" } -Scope it Assert-MockCalled Import-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "NestedModuleFullName" } -Scope it Assert-MockCalled Get-Module -Times 1 -Exactly -ParameterFilter { $Name -eq "BitTitan.Runbooks.TestModule" } -Scope it # Verify the output $errorVariable | Should BeNullOrEmpty } } # Declare the functions to throw an exception $functionsToThrowExceptions = @( "Install-Module", "Import-Module" ) foreach ($function in $functionsToThrowExceptions) { context "when $($function) throws an exception" { # Declare mocks mock Install-Module {} mock Import-Module {} mock Get-ChildItem { if ($Script:numberTimesGetChildItemCalled -eq 0) { $Script:numberTimesGetChildItemCalled += 1 return } elseif ($Script:numberTimesGetChildItemCalled -eq 1) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ Name = "0.1.0" } } return [PSCustomObject]@{ FullName = "NestedModuleFullName" } } mock Get-Module { return [PSCustomObject]@{ Path = "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" Version = [Version]"0.1.0" } } mock Get-Item { return [PSCustomObject]@{ FullName = "FullName" } } mock Move-Item {} # Mock the function to throw an exception mock $function { throw "throws exception" } it -TestCases @( @{ Environment = "Beta" IsRunningOnLocalMachine = $false }, @{ Environment = "Beta" IsRunningOnLocalMachine = $true }, @{ Environment = "BT" IsRunningOnLocalMachine = $false }, @{ Environment = "BT" IsRunningOnLocalMachine = $true } ) "fails to install and/or import the module in the <Environment> environment and when IsRunningOnLocalMachine is <IsRunningOnLocalMachine>, and outputs an error." { param ($Environment, $IsRunningOnLocalMachine) # Set up the settings $Global:PSDefaultParameterValues["*-BT_*:Environment"] = $Environment $Global:PSDefaultParameterValues["*-BT_*:IsRunningOnLocalMachine"] = $IsRunningOnLocalMachine $Script:numberTimesGetChildItemCalled = 0 # Call the function Import-BT_Module BitTitan.Runbooks.TestModule -ErrorAction SilentlyContinue -ErrorVariable errorVariable # Verify the output # If running on local machine and the function to throw is Install-Module, # there will be no error output as Install-Module will not be called. if ($function -ne "Install-Module" -and !$IsRunningOnLocalMachine) { $errorVariable | Should Not BeNullOrEmpty } } } } context "when the module fails to be imported" { # Declare mocks mock Install-Module {} mock Import-Module {} mock Get-ChildItem { if ($Script:numberTimesGetChildItemCalled -eq 0) { $Script:numberTimesGetChildItemCalled += 1 return } elseif ($Script:numberTimesGetChildItemCalled -eq 1) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ Name = "0.1.0" } } return [PSCustomObject]@{ FullName = "NestedModuleFullName" } } mock Get-Module {} mock Get-Item { return [PSCustomObject]@{ FullName = "FullName" } } mock Move-Item {} it -TestCases @( @{ Environment = "Beta" IsRunningOnLocalMachine = $false }, @{ Environment = "BT" IsRunningOnLocalMachine = $false } ) "it outputs an error in the <Environment> environment and when IsRunningOnLocalMachine is <IsRunningOnLocalMachine>." { param ($Environment, $IsRunningOnLocalMachine) # Set up the settings $Global:PSDefaultParameterValues["*-BT_*:Environment"] = $Environment $Global:PSDefaultParameterValues["*-BT_*:IsRunningOnLocalMachine"] = $IsRunningOnLocalMachine $Script:numberTimesGetChildItemCalled = 0 # Call the function Import-BT_Module BitTitan.Runbooks.TestModule -ErrorAction SilentlyContinue -ErrorVariable errorVariable # Verify the output $errorVariable | Should Not BeNullOrEmpty } # Declare mocks mock Install-Module {} mock Import-Module {} mock Get-ChildItem { return [PSCustomObject]@{ FullName = "NestedModuleFullName" } } $Script:numberTimesGetModuleCalled = 0 mock Get-Module { if ($Script:numberTimesGetChildItemCalled -eq 0) { $Script:numberTimesGetChildItemCalled += 1 return [PSCustomObject]@{ Path = "$($env:USERPROFILE)\Documents\WindowsPowerShell\Modules\BitTitan.Runbooks.TestModule" Version = [Version]"0.1.0" } } } it -TestCases @( @{ Environment = "Beta" IsRunningOnLocalMachine = $true }, @{ Environment = "BT" IsRunningOnLocalMachine = $true } ) "it outputs an error in the <Environment> environment and when IsRunningOnLocalMachine is <IsRunningOnLocalMachine>." { param ($Environment, $IsRunningOnLocalMachine) # Set up the settings $Global:PSDefaultParameterValues["*-BT_*:Environment"] = $Environment $Global:PSDefaultParameterValues["*-BT_*:IsRunningOnLocalMachine"] = $IsRunningOnLocalMachine $Script:numberTimesGetChildItemCalled = 0 # Call the function Import-BT_Module BitTitan.Runbooks.TestModule -ErrorAction SilentlyContinue -ErrorVariable errorVariable # Verify the output $errorVariable | Should Not BeNullOrEmpty } } # Reset the BitTitan Runbook Environment settings $Global:PSDefaultParameterValues = $previousPSDefaultParameterValues } |