From bc38a0cbbdc9cea1c5cfa19ba7855a3e191a7245 Mon Sep 17 00:00:00 2001 From: James Ruskin Date: Sat, 6 May 2023 18:01:19 +0100 Subject: [PATCH] (#66) Adds Tests to ChocoCCM Adds test covering public functions within ChocoCCM. Admittedly, currently only ~66% code coverage. This does, however, hit pretty much every _working_ command - most of the missing percentage are argument completers (which I am to improve), `if not session throw` blocks (which I aim to remove), and those commands that aren't working. Exceptions to be improved include: - Set-CCMDeploymentStep, which isn't implemented fully and should probably just be removed for now. - Remove-CCMStaleDeployment, which is currently broken - Import-PDQDeployPackage, because I couldn't find an example of an importable file. --- .gitignore | 2 + src/Tests/Public/Add-CCMGroup.Tests.ps1 | 414 +++++++++++++++++ src/Tests/Public/Add-CCMGroupMember.Tests.ps1 | 420 ++++++++++++++++++ src/Tests/Public/Connect-CCMServer.Tests.ps1 | 93 ++++ .../Public/Disable-CCMDeployment.Tests.ps1 | 70 +++ .../Public/Export-CCMDeployment.Tests.ps1 | 150 +++++++ .../Export-CCMDeploymentReport.Tests.ps1 | 134 ++++++ ...Export-CCMOutdatedSoftwareReport.Tests.ps1 | 132 ++++++ src/Tests/Public/Get-CCMComputer.Tests.ps1 | 116 +++++ src/Tests/Public/Get-CCMDeployment.Tests.ps1 | 188 ++++++++ .../Public/Get-CCMDeploymentStep.Tests.ps1 | 110 +++++ src/Tests/Public/Get-CCMGroup.Tests.ps1 | 165 +++++++ src/Tests/Public/Get-CCMGroupMember.Tests.ps1 | 55 +++ .../Public/Get-CCMOutdatedSoftware.Tests.ps1 | 47 ++ .../Get-CCMOutdatedSoftwareMember.Tests.ps1 | 100 +++++ .../Get-CCMOutdatedSoftwareReport.Tests.ps1 | 62 +++ ...-CCMOutdatedSoftwareReportDetail.Tests.ps1 | 56 +++ src/Tests/Public/Get-CCMRole.Tests.ps1 | 104 +++++ src/Tests/Public/Get-CCMSoftware.Tests.ps1 | 152 +++++++ .../Public/Get-DeploymentResult.Tests.ps1 | 58 +++ .../Public/Import-PDQDeployPackage.Tests.ps1 | 48 ++ .../Move-CCMDeploymentToReady.Tests.ps1 | 65 +++ src/Tests/Public/New-CCMDeployment.Tests.ps1 | 52 +++ .../Public/New-CCMDeploymentStep.Tests.ps1 | 136 ++++++ .../New-CCMOutdatedSoftwareReport.Tests.ps1 | 30 ++ .../Public/Remove-CCMDeployment.Tests.ps1 | 76 ++++ .../Public/Remove-CCMDeploymentStep.Tests.ps1 | 51 +++ src/Tests/Public/Remove-CCMGroup.Tests.ps1 | 79 ++++ .../Public/Remove-CCMGroupMember.Tests.ps1 | 99 +++++ .../Remove-CCMStaleDeployment.Tests.ps1 | 47 ++ .../Public/Set-CCMDeploymentStep.Tests.ps1 | 111 +++++ src/Tests/Public/Set-CCMGroup.Tests.ps1 | 134 ++++++ .../Set-CCMNotificationStatus.Tests.ps1 | 70 +++ .../Public/Start-CCMDeployment.Tests.ps1 | 51 +++ src/Tests/Public/Stop-CCMDeployment.Tests.ps1 | 51 +++ src/Tests/chococcm.tests.ps1 | 2 - test.ps1 | 36 ++ 37 files changed, 3764 insertions(+), 2 deletions(-) create mode 100644 src/Tests/Public/Add-CCMGroup.Tests.ps1 create mode 100644 src/Tests/Public/Add-CCMGroupMember.Tests.ps1 create mode 100644 src/Tests/Public/Connect-CCMServer.Tests.ps1 create mode 100644 src/Tests/Public/Disable-CCMDeployment.Tests.ps1 create mode 100644 src/Tests/Public/Export-CCMDeployment.Tests.ps1 create mode 100644 src/Tests/Public/Export-CCMDeploymentReport.Tests.ps1 create mode 100644 src/Tests/Public/Export-CCMOutdatedSoftwareReport.Tests.ps1 create mode 100644 src/Tests/Public/Get-CCMComputer.Tests.ps1 create mode 100644 src/Tests/Public/Get-CCMDeployment.Tests.ps1 create mode 100644 src/Tests/Public/Get-CCMDeploymentStep.Tests.ps1 create mode 100644 src/Tests/Public/Get-CCMGroup.Tests.ps1 create mode 100644 src/Tests/Public/Get-CCMGroupMember.Tests.ps1 create mode 100644 src/Tests/Public/Get-CCMOutdatedSoftware.Tests.ps1 create mode 100644 src/Tests/Public/Get-CCMOutdatedSoftwareMember.Tests.ps1 create mode 100644 src/Tests/Public/Get-CCMOutdatedSoftwareReport.Tests.ps1 create mode 100644 src/Tests/Public/Get-CCMOutdatedSoftwareReportDetail.Tests.ps1 create mode 100644 src/Tests/Public/Get-CCMRole.Tests.ps1 create mode 100644 src/Tests/Public/Get-CCMSoftware.Tests.ps1 create mode 100644 src/Tests/Public/Get-DeploymentResult.Tests.ps1 create mode 100644 src/Tests/Public/Import-PDQDeployPackage.Tests.ps1 create mode 100644 src/Tests/Public/Move-CCMDeploymentToReady.Tests.ps1 create mode 100644 src/Tests/Public/New-CCMDeployment.Tests.ps1 create mode 100644 src/Tests/Public/New-CCMDeploymentStep.Tests.ps1 create mode 100644 src/Tests/Public/New-CCMOutdatedSoftwareReport.Tests.ps1 create mode 100644 src/Tests/Public/Remove-CCMDeployment.Tests.ps1 create mode 100644 src/Tests/Public/Remove-CCMDeploymentStep.Tests.ps1 create mode 100644 src/Tests/Public/Remove-CCMGroup.Tests.ps1 create mode 100644 src/Tests/Public/Remove-CCMGroupMember.Tests.ps1 create mode 100644 src/Tests/Public/Remove-CCMStaleDeployment.Tests.ps1 create mode 100644 src/Tests/Public/Set-CCMDeploymentStep.Tests.ps1 create mode 100644 src/Tests/Public/Set-CCMGroup.Tests.ps1 create mode 100644 src/Tests/Public/Set-CCMNotificationStatus.Tests.ps1 create mode 100644 src/Tests/Public/Start-CCMDeployment.Tests.ps1 create mode 100644 src/Tests/Public/Stop-CCMDeployment.Tests.ps1 create mode 100644 test.ps1 diff --git a/.gitignore b/.gitignore index 0b3f986..69a4344 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ gen/generated .DS_Store Output/ .dotnet/ +coverage.xml +testResults.xml \ No newline at end of file diff --git a/src/Tests/Public/Add-CCMGroup.Tests.ps1 b/src/Tests/Public/Add-CCMGroup.Tests.ps1 new file mode 100644 index 0000000..883a673 --- /dev/null +++ b/src/Tests/Public/Add-CCMGroup.Tests.ps1 @@ -0,0 +1,414 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Add-CCMGroup" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMComputer -ModuleName ChocoCCM { + 1..10 | ForEach-Object { + @{ + name = "Computer $_" + id = $_ + } + } + } + Mock Get-CCMGroup -ModuleName ChocoCCM { + 1..10 | ForEach-Object { + @{ + name = "Group $_" + id = $_ + } + } + } + } + + Context "Adding a new group with no members" { + BeforeAll { + $TestParams = @{ + Name = "$(New-Guid)" + Description = "$(New-Guid)" + # Group = @() + # Computer = @() + } + + $Result = Add-CCMGroup @TestParams + } + + It "Calls the API to create the new group with no members" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Name -eq $TestParams.Name -and + $Body.Description -eq $TestParams.Description -and + $Body.Groups.Count -eq 0 -and + $Body.Computers.Count -eq 0 + } + } + + It "Returns the new group" { + $Result | Should -BeOfType [PSCustomObject] + $Result.name | Should -Be $TestParams.Name + $Result.description | Should -Be $TestParams.Description + $Result.groups | Should -Be $TestParams.Group + $Result.computers | Should -Be $TestParams.Computer + } + } + + Context "Adding a new group containing a computer" { + BeforeAll { + $TestParams = @{ + Name = "$(New-Guid)" + Description = "$(New-Guid)" + # Group = @() + Computer = "Computer $(Get-Random -Minimum 1 -Maximum 10)" + } + + $Result = Add-CCMGroup @TestParams + } + + It "Calls the API to create the new group with the computer" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Name -eq $TestParams.Name -and + $Body.Description -eq $TestParams.Description -and + $Body.Groups.Count -eq 0 -and + $Body.Computers.computerId -eq $TestParams.Computer.Split(' ')[-1] + } + } + + It "Returns the new group" { + $Result | Should -BeOfType [PSCustomObject] + $Result.name | Should -Be $TestParams.Name + $Result.description | Should -Be $TestParams.Description + $Result.groups | Should -Be $TestParams.Group + $Result.computers | Should -Be $TestParams.Computer + } + } + + # Containing multiple computers + Context "Adding a new group containing multiple computers" { + BeforeAll { + $TestParams = @{ + Name = "$(New-Guid)" + Description = "$(New-Guid)" + # Group = @() + Computer = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { "Computer $_" } + } + + $Result = Add-CCMGroup @TestParams + } + + It "Calls the API to create the new group with the computers" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Name -eq $TestParams.Name -and + $Body.Description -eq $TestParams.Description -and + $Body.Groups.Count -eq 0 -and + $Body.Computers.computerId -eq $TestParams.Computer.Split(' ')[-1] + + $script:ResultComputers = $Body.Computers + } + + $script:ResultComputers | Should -HaveCount $TestParams.Computer.Count + } + + It "Returns the new group" { + $Result | Should -BeOfType [PSCustomObject] + $Result.name | Should -Be $TestParams.Name + $Result.description | Should -Be $TestParams.Description + $Result.groups | Should -Be $TestParams.Group + $Result.computers | Should -Be $TestParams.Computer + } + } + + Context "Adding a new group containing another group" { + BeforeAll { + $TestParams = @{ + Name = "$(New-Guid)" + Description = "$(New-Guid)" + Group = "Group $(Get-Random -Minimum 1 -Maximum 10)" + } + + $Result = Add-CCMGroup @TestParams + } + + It "Calls the API to create the new group with the computer" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Name -eq $TestParams.Name -and + $Body.Description -eq $TestParams.Description -and + $Body.Groups.subGroupId -eq $TestParams.Group.Split(' ')[-1] -and + $Body.Computers.Count -eq 0 + } + } + + It "Returns the new group" { + $Result | Should -BeOfType [PSCustomObject] + $Result.name | Should -Be $TestParams.Name + $Result.description | Should -Be $TestParams.Description + $Result.groups | Should -Be $TestParams.Group + $Result.computers | Should -Be $TestParams.Computer + } + } + + Context "Adding a new group containing multiple groups" { + BeforeAll { + $TestParams = @{ + Name = "$(New-Guid)" + Description = "$(New-Guid)" + Group = 1..10 | Get-Random -Count (Get-Random -Minimum 2 -Maximum 10) | ForEach-Object { "Group $_" } + } + + $Result = Add-CCMGroup @TestParams + } + + It "Calls the API to create the new group with the computer" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Name -eq $TestParams.Name -and + $Body.Description -eq $TestParams.Description -and + $Body.Groups.subGroupId -eq $TestParams.Group.Split(' ')[-1] -and + $Body.Computers.Count -eq 0 + } + } + + It "Returns the new group" { + $Result | Should -BeOfType [PSCustomObject] + $Result.name | Should -Be $TestParams.Name + $Result.description | Should -Be $TestParams.Description + $Result.groups | Should -Be $TestParams.Group + $Result.computers | Should -Be $TestParams.Computer + } + } + + Context "Adding a new group containing a group and a computer" { + BeforeAll { + $TestParams = @{ + Name = "$(New-Guid)" + Description = "$(New-Guid)" + Group = "Group $(Get-Random -Minimum 1 -Maximum 10)" + Computer = "Computer $(Get-Random -Minimum 1 -Maximum 10)" + } + + $Result = Add-CCMGroup @TestParams + } + + It "Calls the API to create the new group with the computer" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Name -eq $TestParams.Name -and + $Body.Description -eq $TestParams.Description -and + $Body.Groups.subGroupId -eq $TestParams.Group.Split(' ')[-1] -and + $Body.Computers.computerId -eq $TestParams.Computer.Split(' ')[-1] + } + } + + It "Returns the new group" { + $Result | Should -BeOfType [PSCustomObject] + $Result.name | Should -Be $TestParams.Name + $Result.description | Should -Be $TestParams.Description + $Result.groups | Should -Be $TestParams.Group + $Result.computers | Should -Be $TestParams.Computer + } + } + + Context "Adding a new group containing a group and multiple computers" { + BeforeAll { + $TestParams = @{ + Name = "$(New-Guid)" + Description = "$(New-Guid)" + Group = "Group $(Get-Random -Minimum 1 -Maximum 10)" + Computer = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { "Computer $_" } + } + + $Result = Add-CCMGroup @TestParams + } + + It "Calls the API to create the new group with the computer" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Name -eq $TestParams.Name -and + $Body.Description -eq $TestParams.Description -and + $Body.Groups.subGroupId -eq $TestParams.Group.Split(' ')[-1] -and + $Body.Computers.computerId -eq $TestParams.Computer.Split(' ')[-1] + } + } + + It "Returns the new group" { + $Result | Should -BeOfType [PSCustomObject] + $Result.name | Should -Be $TestParams.Name + $Result.description | Should -Be $TestParams.Description + $Result.groups | Should -Be $TestParams.Group + $Result.computers | Should -Be $TestParams.Computer + } + } + + Context "Adding a new group containing multiple groups and a computer" { + BeforeAll { + $TestParams = @{ + Name = "$(New-Guid)" + Description = "$(New-Guid)" + Group = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { "Group $_" } + Computer = "Computer $(Get-Random -Minimum 1 -Maximum 10)" + } + + $Result = Add-CCMGroup @TestParams + } + + It "Calls the API to create the new group with the computer" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Name -eq $TestParams.Name -and + $Body.Description -eq $TestParams.Description -and + $Body.Groups.subGroupId -eq $TestParams.Group.Split(' ')[-1] -and + $Body.Computers.computerId -eq $TestParams.Computer.Split(' ')[-1] + } + } + + It "Returns the new group" { + $Result | Should -BeOfType [PSCustomObject] + $Result.name | Should -Be $TestParams.Name + $Result.description | Should -Be $TestParams.Description + $Result.groups | Should -Be $TestParams.Group + $Result.computers | Should -Be $TestParams.Computer + } + } + + Context "Adding a new group containing multiple groups and multiple computers" { + BeforeAll { + $TestParams = @{ + Name = "$(New-Guid)" + Description = "$(New-Guid)" + Group = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { "Group $_" } + Computer = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { "Computer $_" } + } + + $Result = Add-CCMGroup @TestParams + } + + It "Calls the API to create the new group with the computer" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Name -eq $TestParams.Name -and + $Body.Description -eq $TestParams.Description -and + $Body.Groups.subGroupId -eq $TestParams.Group.Split(' ')[-1] -and + $Body.Computers.computerId -eq $TestParams.Computer.Split(' ')[-1] + } + } + + It "Returns the new group" { + $Result | Should -BeOfType [PSCustomObject] + $Result.name | Should -Be $TestParams.Name + $Result.description | Should -Be $TestParams.Description + $Result.groups | Should -Be $TestParams.Group + $Result.computers | Should -Be $TestParams.Computer + } + } + + # Creating an already existing group name + Context "Adding a new group with an already existing name" -Skip { + # This is apparently fine to do. Hmph. + # Given the way it's written (e.g. using $Current to update the object?), + # I can't tell if this is good or bad. It seems to be modelled on Add-CCMGroupMember... sort of. + } + + Context "Failing to create a group" { + BeforeAll { + Mock Invoke-RestMethod -ModuleName ChocoCCM { + throw "A server error occurred" + } + + $TestParams = @{ + Name = "$(New-Guid)" + Description = "$(New-Guid)" + } + } + + It "Surfaces the error" { + { $Result = Add-CCMGroup @TestParams } | Should -Throw + } + + It "Calls the API to create the new group with no members" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Name -eq $TestParams.Name -and + $Body.Description -eq $TestParams.Description -and + $Body.Groups.Count -eq 0 -and + $Body.Computers.Count -eq 0 + } + } + + It "Returns nothing." { + $Result | Should -BeNullOrEmpty + } + } + + # Creating a group containing non-existent computers + # Similarly, this won't complain. Maybe it should? + + # Creating a group containing non-existent groups + # Similarly, this won't complain. Maybe it should? +} \ No newline at end of file diff --git a/src/Tests/Public/Add-CCMGroupMember.Tests.ps1 b/src/Tests/Public/Add-CCMGroupMember.Tests.ps1 new file mode 100644 index 0000000..86d6086 --- /dev/null +++ b/src/Tests/Public/Add-CCMGroupMember.Tests.ps1 @@ -0,0 +1,420 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Add-CCMGroupMember" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Get-CCMComputer -ModuleName ChocoCCM { + 1..10 | ForEach-Object { + @{ + name = "Computer $_" + id = $_ + computerId = $_ + } + } + } + Mock Get-CCMGroup -ModuleName ChocoCCM { + 1..10 | ForEach-Object { + @{ + name = "Group $_" + id = $_ + } + } + } + Mock Get-CCMGroupMember -ModuleName ChocoCCM { + [pscustomobject]@{ + Id = "$(New-Guid)" + Name = $Group + Description = "Definitely a real group" + Groups = $script:ExistingMemberGroups + Computers = $script:ExistingMemberComputers + CanDeploy = $true + } + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" + } { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Body.Computers.ForEach{ + if ($script:ExistingMemberComputers.computerId -notcontains $_.computerId) { + $script:ExistingMemberComputers += @{ computerId = $_.computerId ; computerName = "Computer $($_.computerId)" } + } + } + $Body.Groups.ForEach{ + if ($script:ExistingMemberGroups.subGroupId -notcontains $_.subGroupId) { + $script:ExistingMemberGroups += @{ subGroupId = $_.subGroupId ; subGroupName = "Group $($_.subGroupId)" } + } + } + } + + } + + Context "Adding a computer to an existing group" { + BeforeAll { + $script:ExistingMemberGroups = @() + $script:ExistingMemberComputers = @() # No existing members + + $TestParams = @{ + Name = "$(New-Guid)" + Computer = @("Computer $(Get-Random -Minimum 1 -Maximum 10)") + } + + $Result = Add-CCMGroupMember @TestParams + } + + It "Calls the API to add group members" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Computers.computerId -eq $TestParams.Computer.Split(' ')[-1] -and + $Body.Groups.Count -eq 0 + } + } + + It "Returns the updated group" { + $Result | Should -BeOfType [PSCustomObject] + + $Result.Name | Should -Be $TestParams.Name + $Result.Computers | Should -Be $TestParams.Computer + } + } + + Context "Adding multiple computers to an existing group" { + BeforeAll { + $script:ExistingMemberGroups = @() + $script:ExistingMemberComputers = @() # No existing members + + $TestParams = @{ + Name = "$(New-Guid)" + Computer = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { "Computer $_" } + } + + $Result = Add-CCMGroupMember @TestParams + } + + It "Calls the API to add group members" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Computers.computerId -eq $TestParams.Computer.Split(' ')[-1] -and + $Body.Groups.Count -eq 0 + } + } + + It "Returns the updated group" { + $Result | Should -BeOfType [PSCustomObject] + + $Result.Name | Should -Be $TestParams.Name + $Result.Computers | Should -Be $TestParams.Computer + } + } + + Context "Adding a group to an existing group" { + BeforeAll { + $script:ExistingMemberGroups = @() # No existing members + $script:ExistingMemberComputers = @() + + $TestParams = @{ + Name = "$(New-Guid)" + Group = "Group $(Get-Random -Minimum 1 -Maximum 10)" + } + + $Result = Add-CCMGroupMember @TestParams + } + + It "Calls the API to add group members" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Groups.subGroupId -eq $TestParams.Group.Split(' ')[-1] -and + $Body.Computers.Count -eq 0 + } + } + + It "Returns the updated group" { + $Result | Should -BeOfType [PSCustomObject] + + $Result.Name | Should -Be $TestParams.Name + $Result.Groups | Should -Be $TestParams.Group + } + } + + Context "Adding multiple groups to an existing group" { + BeforeAll { + $script:ExistingMemberGroups = @() # No existing members + $script:ExistingMemberComputers = @() + + $TestParams = @{ + Name = "$(New-Guid)" + Group = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { "Group $_" } + } + + $Result = Add-CCMGroupMember @TestParams + } + + It "Calls the API to add group members" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Groups.subGroupId -eq $TestParams.Group.Split(' ')[-1] -and + $Body.Computers.Count -eq 0 + } + } + + It "Returns the updated group" { + $Result | Should -BeOfType [PSCustomObject] + + $Result.Name | Should -Be $TestParams.Name + $Result.Groups | Should -Be $TestParams.Group + } + } + + Context "Adding multiple computers and groups to an existing group" { + BeforeAll { + $script:ExistingMemberGroups = @() # No existing members + $script:ExistingMemberComputers = @() # No existing members + + $TestParams = @{ + Name = "$(New-Guid)" + Computer = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { "Computer $_" } + Group = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { "Group $_" } + } + + $Result = Add-CCMGroupMember @TestParams + } + + It "Calls the API to add group members" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Groups.subGroupId -eq $TestParams.Group.Split(' ')[-1] -and + $Body.Computers.computerId -eq $TestParams.Computer.Split(' ')[-1] + } + } + + It "Returns the updated group" { + $Result | Should -BeOfType [PSCustomObject] + + $Result.Name | Should -Be $TestParams.Name + $Result.Groups | Should -Be $TestParams.Group + $Result.Computers | Should -Be $TestParams.Computer + } + } + + Context "Adding members that are already present in the group" { + BeforeAll { + $script:ExistingMemberGroups = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { @{ subGroupId = $_ ; subGroupName = "Group $($_)" } } + $script:ExistingMemberComputers = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { @{ computerId = $_ ; computerName = "Computer $($_)" } } + + $TestParams = @{ + Name = "$(New-Guid)" + Computer = $script:ExistingMemberComputers.computerName + Group = $script:ExistingMemberGroups.subGroupName + } + + $Result = Add-CCMGroupMember @TestParams + } + + It "Calls the API to add group members" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + Write-Host $Body.Groups + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Groups.Count -eq 0 -and + ($Body.Computers.computerId | Sort-Object) -eq ($TestParams.Computer.Split(' ')[-1] | Sort-Object) + } + } + + It "Returns the updated group" { + $Result | Should -BeOfType [PSCustomObject] + + $Result.Name | Should -Be $TestParams.Name + $Result.Groups | Should -Be $script:ExistingMemberGroups.subGroupName + $Result.Computers | Should -Be $script:ExistingMemberComputers.computerName + } + } + + Context "Adding a non-existent computer to a group" { + BeforeAll { + $script:ExistingMemberGroups = @() + $script:ExistingMemberComputers = @(1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { @{ computerId = $_ ; computerName = "Computer $($_)" } }) + + $TestParams = @{ + Name = "$(New-Guid)" + Computer = @("Saturn") + } + + $Result = Add-CCMGroupMember @TestParams -WarningVariable "StoredWarning" + } + + It "Warns that the computer doesn't exist and it's not being added" { + # Not a great test, but it will mean that if someone is relying on this message and we change it, we'll have to consider it. + $StoredWarning | Should -Be "A computer with the name $($TestParams.Computer) could not be found, skipping adding it to the group" + } + + It "Calls the API to add group members without including the non-existent computer" { + # It's possible that if nothing changes, this shouldn't be called - but that's somewhat confused by us passing existing computers and not existing groups. + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Computers.Count -eq $script:ExistingMemberComputers.Count -and # This should not have increased. + $Body.Groups.Count -eq 0 + } + } + + It "Returns the updated group" { + $Result | Should -BeOfType [PSCustomObject] + + $Result.Name | Should -Be $TestParams.Name + $Result.Computers | Should -Be $script:ExistingMemberComputers.computerName + } + } + + Context "Adding a non-existent group to a group" { + BeforeAll { + $script:ExistingMemberGroups = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { @{ subGroupId = $_ ; subGroupName = "Group $($_)" } } + $script:ExistingMemberComputers = @() + + $TestParams = @{ + Name = "$(New-Guid)" + Group = @("Solar System") + } + + $Result = Add-CCMGroupMember @TestParams -WarningVariable "StoredWarning" + } + + It "Warns that the computer doesn't exist and it's not being added" { + # Not a great test, but it will mean that if someone is relying on this message and we change it, we'll have to consider it. + $StoredWarning | Should -Be "A group with the name $($TestParams.Group) could not be found, skipping adding it to the group" + } + + It "Calls the API to add group members without including the non-existent group" { + # It's possible that if nothing changes, this shouldn't be called - but that's somewhat confused by us passing existing computers and not existing groups. + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + Write-Host $Body + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Groups.Count -eq 0 -and # Groups do not get passed back, even if they already are there. See the comment above! + $Body.Computers.Count -eq 0 + + Write-Host "$($Body.Groups.Count)" "$($script:ExistingMemberGroups.Count)" + } + } + + It "Returns the updated group" { + $Result | Should -BeOfType [PSCustomObject] + + $Result.Name | Should -Be $TestParams.Name + $Result.Computers | Should -Be $script:ExistingMemberComputers.computerName + } + } + + Context "Adding members to a group that doesn't exist" { + BeforeAll { + Mock Get-CCMGroupMember -ModuleName ChocoCCM { + throw [Microsoft.PowerShell.Commands.HttpResponseException]::new("Response status code does not indicate success: 400 (Bad Request).") + } + + $TestParams = @{ + Name = "$(New-Guid)" + Computer = "Some Computer" + } + } + + # This may be a terrible test. + It "Throws an error when the group doesn't exist." { + {Add-CCMGroupMember @TestParams} | Should -Throw + } + } + + # Skipping: This needs thought, as it currently just responds with handy content for the PWD + Context "Completing Parameter Arguments" -Skip { + BeforeAll { + Mock Get-CCMGroup -ModuleName ChocoCCM { + "Alpha", "Bravo", "Charlie", "Delta" | ForEach-Object { + @{ Name = $_ } + } + } + } + + It "Has an argument completer for Name that lists all group names by default" { + $Command = "Add-CCMGroupMember -Name ''" + $Completions = [System.Management.Automation.CommandCompletion]::CompleteInput($Command, $Command.Length, $null) + + $Completions.CompletionMatches.CompletionText | Should -HaveCount 4 + } + + It "Has an argument completer for Name that filters group names by entered text" { + $Command = "Add-CCMGroupMember -Name 'Alph'" + $Completions = [System.Management.Automation.CommandCompletion]::CompleteInput($Command, $Command.Length, $null) + + $Completions.CompletionMatches.CompletionText | Should -HaveCount 1 + $Completions.CompletionMatches.CompletionText | Should -Be "Alpha" + } + } + + Context "Failing to add a group member" { + BeforeAll { + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" + } { + throw [Microsoft.PowerShell.Commands.HttpResponseException]::new("Response status code does not indicate success: 400 (Bad Request).") + } + + $TestParams = @{ + Name = "$(New-Guid)" + Group = "Group $(Get-Random -Minimum 1 -Maximum 10)" + } + } + + It "Throws an error when the group doesn't exist." { + {Add-CCMGroupMember @TestParams} | Should -Throw + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Connect-CCMServer.Tests.ps1 b/src/Tests/Public/Connect-CCMServer.Tests.ps1 new file mode 100644 index 0000000..b3fb1ea --- /dev/null +++ b/src/Tests/Public/Connect-CCMServer.Tests.ps1 @@ -0,0 +1,93 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Connect-CCMServer" { + BeforeAll { + Mock Invoke-WebRequest -ModuleName ChocoCCM -MockWith { + if ($SessionVariable -eq "Session") { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + } + } + } + + Context "Logging into a HTTP Host" { + BeforeAll { + $TestValues = @{ + Hostname = "New-Guid" + Credential = [pscredential]::new( + "$(New-Guid)", + ("$(New-Guid)" | ConvertTo-SecureString -AsPlainText -Force) + ) + UseSSL = $false + } + $Result = Connect-CCMServer @TestValues + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + + It "Called /Account/Login using the provided Credentials" { + Should -Invoke Invoke-WebRequest -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "POST" -and + $Uri -eq "http://$($TestValues.Hostname)/Account/Login" -and + $ContentType -eq "application/x-www-form-urlencoded" -and + $Body.usernameOrEmailAddress -eq $TestValues.Credential.UserName -and + $Body.password -eq $TestValues.Credential.GetNetworkCredential().Password + } + } + + It "Sets the Protocol Variable" { + InModuleScope ChocoCCM { $script:Protocol } | Should -Be "http" + } + + It "Sets the Session Variable" -Skip { + # TODO: Fix this test. + InModuleScope ChocoCCM { $script:Session } | Should -Not -BeNullOrEmpty + } + + It "Sets the Hostname Variable" { + InModuleScope ChocoCCM { $script:Hostname } | Should -Be $TestValues.Hostname + } + } + + Context "Logging into a HTTPS Host" { + BeforeAll { + $TestValues = @{ + Hostname = "New-Guid" + Credential = [pscredential]::new( + "$(New-Guid)", + ("$(New-Guid)" | ConvertTo-SecureString -AsPlainText -Force) + ) + UseSSL = $true + } + $Result = Connect-CCMServer @TestValues + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + + It "Called /Account/Login using the provided Credentials" { + Should -Invoke Invoke-WebRequest -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "POST" -and + $Uri -eq "https://$($TestValues.Hostname)/Account/Login" -and + $ContentType -eq "application/x-www-form-urlencoded" -and + $Body.usernameOrEmailAddress -eq $TestValues.Credential.UserName -and + $Body.password -eq $TestValues.Credential.GetNetworkCredential().Password + } + } + + It "Sets the Protocol Variable" { + InModuleScope ChocoCCM { $script:Protocol } | Should -Be "https" + } + + It "Sets the Session Variable" -Skip { + # TODO: Fix this test. + InModuleScope ChocoCCM { $script:Session } | Should -Not -BeNullOrEmpty + } + + It "Sets the Hostname Variable" { + InModuleScope ChocoCCM { $script:Hostname } | Should -Be $TestValues.Hostname + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Disable-CCMDeployment.Tests.ps1 b/src/Tests/Public/Disable-CCMDeployment.Tests.ps1 new file mode 100644 index 0000000..b7544f3 --- /dev/null +++ b/src/Tests/Public/Disable-CCMDeployment.Tests.ps1 @@ -0,0 +1,70 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Disable-CCMDeployment" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Get-CCMDeployment -ModuleName ChocoCCM { + @{Id = $script:TestGuid} + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + } + + Context "Disabling a deployment" { + BeforeAll { + $script:TestGuid = "$(New-Guid)" + $TestParams = @{ + Deployment = "Your Deployment" + } + + $Result = Disable-CCMDeployment @TestParams -Confirm:$false + } + + It "Calls the API to disable the deployment" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/Archive" -and + $ContentType -eq "application/json" -and + $Body.id -eq $script:TestGuid + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Disabling a non-existent deployment" -Skip { + BeforeAll { + Mock Get-CCMDeployment -ModuleName ChocoCCM { + throw [Microsoft.PowerShell.Commands.HttpResponseException]::new("Response status code does not indicate success: 400 (Bad Request).") + } + Mock Invoke-RestMethod -ModuleName ChocoCCM { + throw [System.Management.Automation.RuntimeException]::new("Response status code does not indicate success: 400 (Bad Request).") + } + } + + It "Throws an error when the deployment doesn't exist" { + {Disable-CCMDeployment @TestParams -Confirm:$false} | Should -Throw + } + } + + Context "Failing to disable a deployment" { + BeforeAll { + Mock Invoke-RestMethod -ModuleName ChocoCCM { + throw [System.Management.Automation.RuntimeException]::new("Response status code does not indicate success: 400 (Bad Request).") + } + } + + It "Throws an error when the API call fails" { + {Disable-CCMDeployment @TestParams -Confirm:$false} | Should -Throw + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Export-CCMDeployment.Tests.ps1 b/src/Tests/Public/Export-CCMDeployment.Tests.ps1 new file mode 100644 index 0000000..4d02e4f --- /dev/null +++ b/src/Tests/Public/Export-CCMDeployment.Tests.ps1 @@ -0,0 +1,150 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Export-CCMDeployment" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Get-CCMDeployment -ModuleName ChocoCCM { + @{ + Name = $Name + Description = "This is a deployment" + DeploymentSteps = @( + @{ + Name = "Step 1" + Description = "This is a step" + Type = "Install" + Package = @{ + Name = "7zip" + Version = "19.00" + } + } + @{ + Name = "Step 2" + Description = "This is a step" + Type = "Install" + Package = @{ + Name = "Firefox" + Version = "21.00" + } + } + ) + } + } + } + + Context "Exporting a Deployment" { + BeforeAll { + $TestParams = @{ + Deployment = "$(New-Guid)" + OutFile = Join-Path $TestDrive "TestFile.xml" + } + + $Result = Export-CCMDeployment @TestParams + } + + It "Calls the API to get the content of the specified deployment" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Name -eq $TestParams.Deployment + } + } + + It "Exports the content to the specified file" { + $TestParams.OutFile | Should -FileContentMatch "This is a deployment" + $TestParams.OutFile | Should -FileContentMatch $TestParams.Deployment + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Exporting Deployment Steps Only" { + BeforeAll { + $TestParams = @{ + Deployment = "$(New-Guid)" + DeploymentStepsOnly = $true + OutFile = Join-Path $TestDrive "TestFile.xml" + } + + $Result = Export-CCMDeployment @TestParams + } + + It "Calls the API to get the content of the specified deployment" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Name -eq $TestParams.Deployment + } + } + + It "Exports the deployment steps to the specified file" { + $TestParams.OutFile | Should -Not -FileContentMatch "This is a deployment" + $TestParams.OutFile | Should -Not -FileContentMatch $TestParams.Deployment + $TestParams.OutFile | Should -FileContentMatch "This is a step" + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Exporting to an existing file" { + BeforeAll { + $TestParams = @{ + Deployment = "$(New-Guid)" + OutFile = Join-Path $TestDrive "TestFile.xml" + AllowClobber = $false + } + + New-Item -Path $TestParams.OutFile -Value "This is an old deployment" + + $Result = Export-CCMDeployment @TestParams + } + + It "Calls the API to get the content of the specified deployment" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Name -eq $TestParams.Deployment + } + } + + It "Does not overwrite the deployment steps in the specified file" -Skip { + # This currently fails because the file is overwritten regardless of the AllowClobber parameter + $TestParams.OutFile | Should -FileContentMatch "This is an old deployment" + $TestParams.OutFile | Should -Not -FileContentMatch "This is a deployment" + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Overwriting an existing file" { + BeforeAll { + $TestParams = @{ + Deployment = "$(New-Guid)" + OutFile = Join-Path $TestDrive "TestFile.xml" + AllowClobber = $true + } + + New-Item -Path $TestParams.OutFile -Value "This is an old deployment" + + $Result = Export-CCMDeployment @TestParams + } + + It "Calls the API to get the content of the specified deployment" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Name -eq $TestParams.Deployment + } + } + + It "Exports the deployment to the specified file" { + $TestParams.OutFile | Should -Not -FileContentMatch "This is an old deployment" + $TestParams.OutFile | Should -FileContentMatch "This is a deployment" + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Export-CCMDeploymentReport.Tests.ps1 b/src/Tests/Public/Export-CCMDeploymentReport.Tests.ps1 new file mode 100644 index 0000000..7a744f6 --- /dev/null +++ b/src/Tests/Public/Export-CCMDeploymentReport.Tests.ps1 @@ -0,0 +1,134 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Export-CCMDeploymentReport" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath.StartsWith("/api/services/app/DeploymentPlans/GetDeploymentPlanDetailsTo") + } { + $Extension = @("xlsx", "pdf")[[int]($Uri.AbsolutePath.EndsWith("Pdf"))] + [pscustomobject]@{ + result = @{ + fileName = $Uri.Query.Split('=')[-1] + '.' + $Extension + fileType = $Extension + fileToken = "$(New-Guid)" + } + } + } + Mock Get-CCMDeployment -ModuleName ChocoCCM { + [PSCustomObject]@{Name = $Deployment; Id = "$(New-Guid)"} + } + } + + Context "Exporting a PDF Deployment Report" { + BeforeAll { + $TestParams = @{ + Deployment = "Complex" + Type = "PDF" + OutputFolder = $TestDrive + } + + $Result = Export-CCMDeploymentReport @TestParams + } + + It "Calls the API to get a file type, token, and name" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/GetDeploymentPlanDetailsToPdf" -and + $Method -eq "GET" -and + $ContentType -eq "application/json" + } + } + + It "Downloads the file" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/File/DownloadTempFile" -and + $Method -eq "GET" -and + $ContentType -eq "PDF" -and + $OutFile + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Exporting an Excel Deployment Report" { + BeforeAll { + $TestParams = @{ + Deployment = "Complex" + Type = "Excel" + OutputFolder = $TestDrive + } + + $Result = Export-CCMDeploymentReport @TestParams + } + + It "Calls the API to get a file type, token, and name" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/GetDeploymentPlanDetailsToExcel" -and + $Method -eq "GET" -and + $ContentType -eq "application/json" + } + } + + It "Downloads the file" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/File/DownloadTempFile" -and + $Method -eq "GET" -and + $ContentType -eq "xlsx" -and + $OutFile + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Failing to find a deployment plan" { + BeforeAll { + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath.StartsWith("/api/services/app/DeploymentPlans/GetDeploymentPlanDetailsTo") + } -MockWith { + throw [System.Net.WebException]::new("Report not found") + } + + $TestParams = @{ + Deployment = "Not Found" + Type = "Excel" + OutputFolder = $TestDrive + } + } + + It "Throws an error" { + { Export-CCMDeploymentReport @TestParams } | Should -Throw + } + } + + Context "Failing to export a deployment plan" { + BeforeAll { + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + -not $Uri.AbsolutePath.StartsWith("/api/services/app/DeploymentPlans/GetDeploymentPlanDetailsTo") + } -MockWith { + throw [System.Net.WebException]::new("File not found.") + } + + $TestParams = @{ + Deployment = "Not Found" + Type = "PDF" + OutputFolder = $TestDrive + } + } + + # Skipping: Despite the block around this, we don't actually throw. We just output the error details. + It "Throws an error" -Skip { + { Export-CCMDeploymentReport @TestParams } | Should -Throw + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Export-CCMOutdatedSoftwareReport.Tests.ps1 b/src/Tests/Public/Export-CCMOutdatedSoftwareReport.Tests.ps1 new file mode 100644 index 0000000..541c697 --- /dev/null +++ b/src/Tests/Public/Export-CCMOutdatedSoftwareReport.Tests.ps1 @@ -0,0 +1,132 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Export-CCMOutdatedSoftwareReport" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath.StartsWith("/api/services/app/OutdatedReports/GetOutdatedSoftwareTo") + } { + $Extension = @("xlsx", "pdf")[[int]($Uri.AbsolutePath.EndsWith("Pdf"))] + [pscustomobject]@{ + result = @{ + fileName = $Uri.Query.Split('=')[-1] + '.' + $Extension + fileType = $Extension + fileToken = "$(New-Guid)" + } + } + } + Mock Get-CCMOutdatedSoftwareReport -ModuleName ChocoCCM + } + + Context "Exporting a PDF Report" { + BeforeAll { + $TestParams = @{ + Report = "7/4/2020 6:44:40 PM" + Type = "PDF" + OutputFolder = $TestDrive + } + + $Result = Export-CCMOutdatedSoftwareReport @TestParams + } + + It "Calls the API to get a file type, token, and name" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/OutdatedReports/GetOutdatedSoftwareToPdf" -and + $Method -eq "GET" -and + $ContentType -eq "application/json" + } + } + + It "Calls the API to download the appropriate file" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/File/DownloadTempFile" -and + $Method -eq "GET" -and + $ContentType -eq "pdf" -and + $OutFile + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Exporting an Excel Report" { + BeforeAll { + $TestParams = @{ + Report = "7/4/2020 6:44:40 PM" + Type = "Excel" + OutputFolder = $TestDrive + } + + $Result = Export-CCMOutdatedSoftwareReport @TestParams + } + + It "Calls the API to get a file type, token, and name" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/OutdatedReports/GetOutdatedSoftwareToExcel" -and + $Method -eq "GET" -and + $ContentType -eq "application/json" + } + } + + It "Calls the API to download the appropriate file" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/File/DownloadTempFile" -and + $Method -eq "GET" -and + $ContentType -eq "xlsx" -and + $OutFile + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Failing to find an outdated report" { + BeforeAll { + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath.StartsWith("/api/services/app/OutdatedReports/GetOutdatedSoftwareTo") + } -MockWith { + throw [System.Net.WebException]::new("Report not found") + } + + $TestParams = @{ + Report = "Not Found" + Type = "Excel" + OutputFolder = $TestDrive + } + } + + It "Throws an error" { + { Export-CCMOutdatedSoftwareReport @TestParams } | Should -Throw + } + } + + Context "Failing to export an outdated report" { + BeforeAll { + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + -not $Uri.AbsolutePath.StartsWith("/api/services/app/OutdatedReports/GetOutdatedSoftwareTo") + } -MockWith { + throw [System.Net.WebException]::new("File not found.") + } + + $TestParams = @{ + Report = "Not Found" + Type = "Excel" + OutputFolder = $TestDrive + } + } + + # Skipping: Despite the block around this, we don't actually throw. We just output the error details. + It "Throws an error" -Skip { + { Export-CCMOutdatedSoftwareReport @TestParams } | Should -Throw + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Get-CCMComputer.Tests.ps1 b/src/Tests/Public/Get-CCMComputer.Tests.ps1 new file mode 100644 index 0000000..675a065 --- /dev/null +++ b/src/Tests/Public/Get-CCMComputer.Tests.ps1 @@ -0,0 +1,116 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Get-CCMComputer" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Computers/GetAll" + } { + @{ + result = 1..9 | ForEach-Object { + [PSCustomObject]@{ + name = "Computer $_" + } + } + } + } + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Computers/GetComputerForEdit" + } { + @{ + computerGuid = "$(New-Guid)" + name = "Computer $($Uri.Query.Split('=')[-1])" + id = $Uri.Query.Split('=')[-1] + } + } + } + + Context "Getting all computers" { + BeforeAll { + $Result = Get-CCMComputer + } + + It "Calls the API to get all computers" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Computers/GetAll" + } + } + + It "Returns All Computers" { + $Result | Should -HaveCount 9 + } + } + + Context "Getting a computer by Name" { + BeforeAll { + $TestParams = @{ + Computer = "Computer $(Get-Random -Minimum 1 -Maximum 10)" + } + $Result = Get-CCMComputer @TestParams + } + + It "Calls the API to get all computers" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Computers/GetAll" + } + } + + It "Returns the computer requested" { + $Result | Should -HaveCount 1 + $Result.name | Should -Be $TestParams.Computer + } + } + + Context "Getting computers by Name" { + BeforeAll { + $TestParams = @{ + # This test fails when Computer 1 and Computer 10 are both selected, due to the naive match + Computer = 1..9 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 9) | ForEach-Object { "Computer $($_)" } + # Computer = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object { "Computer $($_)" } + } + $Result = Get-CCMComputer @TestParams + } + + It "Calls the API to get all computers" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Computers/GetAll" + } + } + + It "Returns the computer requested" { + $Result | Should -HaveCount $TestParams.Computer.Count + $Result.name | Should -Be $TestParams.Computer + } + } + + Context "Getting a computer by ID" { + BeforeAll { + $TestParams = @{ + ID = Get-Random -Minimum 1 -Maximum 10 + } + $Result = Get-CCMComputer @TestParams + } + + It "Doesn't call the API to get all computers" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 0 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Computers/GetAll" + } + } + + It "Calls the API to get the exact computer" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 0 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Computers/GetComputerForEdit" -and + $Uri.Query.EndsWith($TestParams.ID) + } + } + + It "Returns the computer requested" { + $Result | Should -HaveCount 1 + $Result.name | Should -Be "Computer $($TestParams.ID)" + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Get-CCMDeployment.Tests.ps1 b/src/Tests/Public/Get-CCMDeployment.Tests.ps1 new file mode 100644 index 0000000..3bc21e4 --- /dev/null +++ b/src/Tests/Public/Get-CCMDeployment.Tests.ps1 @@ -0,0 +1,188 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Get-CCMDeployment" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/GetAll" + } -MockWith { + $result = @{ + result = @() + } + $result.result += [PSCustomObject]@{ + name = "bob" + id = 0 + deploymentPlan = @{ + name = "planbob" + } + } + $result.result += 1..9 | ForEach-Object { + [PSCustomObject]@{ + name = "Deployment $_" + id = $_ + deploymentPlan = @{ + name = "plan$_" + } + } + } + $result + } + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/GetDeploymentPlanForEdit" + } -MockWith { + @{ + result = @{ + name = "Deployment $($Uri.Query.Split("=")[-1])" + id = $Uri.Query.Split("=")[-1] + deploymentPlan = @{ + name = "plan$($Uri.Query.Split("=")[-1])" + } + } + } + } + Mock Get-CCMDeploymentStep -ModuleName ChocoCCM -MockWith { + @{content = $true} + } + } + + Context "Getting all deployments" { + BeforeAll { + $Result = Get-CCMDeployment + } + + It "Calls the API to get all deployments" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/GetAll" + } + } + + It "Returns all deployments, including deploymentPlans" { + $Result | Should -HaveCount 10 + $Result.deploymentPlan.deploymentSteps | Should -BeNullOrEmpty + $Result.deploymentPlan | Should -Not -BeNullOrEmpty + } + } + + Context "Getting a deployment by name" { + BeforeAll { + $TestParams = @{ + Name = "bob" + } + + $Result = Get-CCMDeployment @TestParams + } + + It "Calls the API to get all deployments" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/GetAll" + } + } + + It "Calls the API to get the specific deployment" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/GetDeploymentPlanForEdit" -and + $Uri.Query -eq "?Id=0" + } + } + + It "Returns the correct deployment plan" { + $Result.name | Should -Be "plan0" + $Result.deploymentSteps | Should -BeNullOrEmpty + $Result | Should -HaveCount 1 + } + } + + Context "Getting a deployment by ID" { + BeforeAll { + $TestParams = @{ + Id = Get-Random -Minimum 1 -Maximum 9 + } + + $Result = Get-CCMDeployment @TestParams + } + + It "Does not call the API to get all deployments" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 0 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/GetAll" + } + } + + It "Calls the API to get the specific deployment" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/GetDeploymentPlanForEdit" -and + $Uri.Query -eq "?Id=$($TestParams.Id)" + } + } + + It "Returns the correct deployment plan" { + $Result.name | Should -Be "plan$($TestParams.Id)" + $Result.deploymentSteps | Should -BeNullOrEmpty + $Result | Should -HaveCount 1 + } + } + + Context "Including Step Results with ID" { + BeforeAll { + $TestParams = @{ + Id = Get-Random -Minimum 1 -Maximum 9 + IncludeStepResults = $true + } + + $Result = Get-CCMDeployment @TestParams + } + + It "Does not call the API to get all deployments" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 0 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/GetAll" + } + } + + It "Calls the API to get the specific deployment" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/GetDeploymentPlanForEdit" -and + $Uri.Query -eq "?Id=$($TestParams.Id)" + } + } + + It "Returns the correct deployment plan" { + $Result.name | Should -Be "plan$($TestParams.Id)" + $Result.deploymentSteps | Should -Not -BeNullOrEmpty + $Result | Should -HaveCount 1 + } + } + + Context "Including Step Results with Name" { + BeforeAll { + $TestParams = @{ + Name = "bob" + IncludeStepResults = $true + } + + $Result = Get-CCMDeployment @TestParams + } + + It "Calls the API to get all deployments" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/GetAll" + } + } + + It "Calls the API to get the specific deployment" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/GetDeploymentPlanForEdit" -and + $Uri.Query -eq "?Id=0" + } + } + + It "Returns the correct deployment plan, including deployment steps" { + $Result.name | Should -Be "plan0" + $Result | Should -HaveCount 1 + $Result.deploymentSteps | Should -Not -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Get-CCMDeploymentStep.Tests.ps1 b/src/Tests/Public/Get-CCMDeploymentStep.Tests.ps1 new file mode 100644 index 0000000..a3189be --- /dev/null +++ b/src/Tests/Public/Get-CCMDeploymentStep.Tests.ps1 @@ -0,0 +1,110 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Get-CCMDeploymentStep" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath.EndsWith("GetDeploymentStepForEdit") + } { + @{ + name = "Deployment Step $($Body.Id)" + deploymentStepComputers = @{ + overwritten = $false + } + } + } + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath.EndsWith("GetAllByDeploymentStepId") + } { + @{ + result = @{ + overwritten = $true + } + } + } + } + + Context "Getting Deployment Steps by ID, including results" { + BeforeAll { + $TestParams = @{ + ID = "583" + IncludeResults = $true + } + + $Result = Get-CCMDeploymentStep @TestParams + } + + It "Calls the API to get the Deployment Step" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Uri.AbsolutePath -eq "/api/services/app/DeploymentSteps/GetDeploymentStepForEdit" -and + $Body.Id -eq $TestParams.ID + } + } + + It "Returns the deployment step, overwriting the deploymentStepComputers results" { + $Result | Should -Not -BeNullOrEmpty + $Result.deploymentStepComputers.overwritten | Should -Be $true + } + } + + Context "Getting Deployment Steps by InputObject, not including results" { + BeforeAll { + $TestParams = @{ + InputObject = @{id = "583"} + IncludeResults = $false + } + + $Result = Get-CCMDeploymentStep @TestParams + } + + It "Calls the API to get the Deployment Step" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Uri.AbsolutePath -eq "/api/services/app/DeploymentSteps/GetDeploymentStepForEdit" -and + $Body.Id -eq $TestParams.InputObject.Id + } + } + + It "Returns the deployment step, overwriting the deploymentStepComputers results" { + $Result | Should -Not -BeNullOrEmpty + $Result.deploymentStepComputers.overwritten | Should -Be $false + } + } + + Context "Getting Deployment Steps by pipelined input" { + BeforeAll { + $TestParams = [PSCustomObject]@{ + ID = "583" + } + + $Result = $TestParams | Get-CCMDeploymentStep + } + + It "Calls the API to get the Deployment Step" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Uri.AbsolutePath -eq "/api/services/app/DeploymentSteps/GetDeploymentStepForEdit" -and + $Body.Id -eq $TestParams.ID + } + } + + It "Returns the deployment step, overwriting the deploymentStepComputers results" { + $Result | Should -Not -BeNullOrEmpty + $Result.deploymentStepComputers.overwritten | Should -Be $false + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Get-CCMGroup.Tests.ps1 b/src/Tests/Public/Get-CCMGroup.Tests.ps1 new file mode 100644 index 0000000..c45ccfc --- /dev/null +++ b/src/Tests/Public/Get-CCMGroup.Tests.ps1 @@ -0,0 +1,165 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Get-CCMGroup" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath.EndsWith("GetAll") + } { + @{ + result = 1..10 | ForEach-Object { + @{ + id = $_ + name = "Group $_" + } + } + } + } + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath.EndsWith("GetGroupForEdit") + } { + @{ + result = @{ + id = $Uri.Query.Split('=')[1] + name = "Group $($Uri.Query.Split('=')[1])" + } + } + } + } + + Context "Getting all groups" { + BeforeAll { + $Result = Get-CCMGroup + } + + It "Calls the API to get all groups" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "GET" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/GetAll" + } + } + + It "Returns all groups" { + $Result | Should -HaveCount 10 + } + } + + Context "Getting a group by ID" { + BeforeAll { + $TestParams = @{ + Id = "1" + } + + $Result = Get-CCMGroup @TestParams + } + + It "Does not call the API to get all groups" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 0 -Exactly -ParameterFilter { + $Method -eq "GET" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/GetAll" + } + } + + It "Calls the API to get the exact group requested" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Groups/GetGroupForEdit" -and + $Uri.Query -eq "?Id=$($TestParams.Id)" + } + } + + It "Returns the requested group" { + $Result | Should -HaveCount 1 + $Result.Id | Should -Be $TestParams.Id + $Result.Name | Should -Be "Group $($TestParams.Id)" + } + } + + Context "Getting a group by name" { + BeforeAll { + $TestParams = @{ + Group = "Group $(Get-Random -Minimum 1 -Maximum 10)" + } + + $Result = Get-CCMGroup @TestParams + } + + It "Calls the API to get all groups" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "GET" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/GetAll" + } + } + + It "Returns the correct group" { + $Result.name | Should -Be $TestParams.Group + } + } + + # These two appear to not work well, and should probably be rewritten or removed from the functionality + Context "Getting multiple groups by name" -Skip { + BeforeAll { + $TestParams = @{ + Group = 1..10 | Get-Random -Count (Get-Random -Minimum 1 -Maximum 10) | ForEach-Object {"Group $($_)"} | Sort-Object {[int]($_.Split(' ')[-1])} + } + + $Result = Get-CCMGroup @TestParams + } + + It "Calls the API to get all groups" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "GET" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/GetAll" + } + } + + It "Returns the correct groups" { + $Result.Name | Sort-Object {[int]($_.Split(' ')[-1])} | Should -Be $TestParams.Group + $Results.Name | Should -HaveCount $TestParams.Group.Count + } + } + + + # Getting multiple groups by ID is very likely to fail badly, as there's no handling for [string[]] + Context "Getting multiple groups by ID" -Skip { + BeforeAll { + $TestParams = @{ + Id = "1","2","3" + } + + $Result = Get-CCMGroup @TestParams + } + + It "Does not call the API to get all groups" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 0 -Exactly -ParameterFilter { + $Method -eq "GET" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/GetAll" + } + } + + It "Calls the API to get the exact group requested once per group requested" { + foreach ($Id in $TestParams.Id) { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Groups/GetGroupForEdit" -and + $Uri.Query -eq "?Id=$($Id)" + } + } + } + + It "Should absolutely not call the API to get the exact group requested once with all the IDs concatenated" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 0 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Groups/GetGroupForEdit" -and + $Uri.Query -eq "?Id=$($TestParams.Id -join '%20')" + } + } + + It "Returns the requested group" { + $Result | Should -HaveCount $TestParams.Id.Count + $Result.Id | Should -Be $TestParams.Id + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Get-CCMGroupMember.Tests.ps1 b/src/Tests/Public/Get-CCMGroupMember.Tests.ps1 new file mode 100644 index 0000000..7aaad2b --- /dev/null +++ b/src/Tests/Public/Get-CCMGroupMember.Tests.ps1 @@ -0,0 +1,55 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Get-CCMGroupMember" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMGroup -ModuleName ChocoCCM { + @{ + Id = if ($Id) {$Id} else {$Group.Split(' ')[-1]} + Name = if ($Group) {$Group} else {"Group $Id"} + Description = "A real group." + Groups = @("Groups") + Computers = @("Computers") + isEligibleForDeployments = "ValueOfIsEligibleForDeployments" + } + } + } + + Context "Getting group membership" { + BeforeAll { + $TestParams = @{ + Group = "Group 1" + } + + $Result = Get-CCMGroupMember @TestParams + } + + It "Calls Get-CCMGroup to get the group ID" { + Should -Invoke Get-CCMGroup -Module ChocoCCM -Scope Context -ParameterFilter { + $Group -eq $TestParams.Group + } + } + + It "Calls Get-CCMGroup to get the group details based on the returned ID" { + Should -Invoke Get-CCMGroup -Module ChocoCCM -Scope Context -ParameterFilter { + $Id -eq $TestParams.Group.Split(' ')[-1] + } + } + + It "Returns a new object containing information on the group membership" { + # This test is rubbish, but we want to show that if we break "the contract" (e.g. the keys returned not matching the API returns) + # then we need to be mindful that we are changing the output a customer _may_ expect, and have to adjust tests accordingly. + $Result.Id | Should -Be "1" + $Result.Name | Should -Be "Group 1" + $Result.Description | Should -Be "A real group." + $Result.Groups | Should -Be @( "Groups" ) + $Result.Computers | Should -Be @( "Computers" ) + $Result.CanDeploy | Should -Be "ValueOfIsEligibleForDeployments" + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Get-CCMOutdatedSoftware.Tests.ps1 b/src/Tests/Public/Get-CCMOutdatedSoftware.Tests.ps1 new file mode 100644 index 0000000..5ed6795 --- /dev/null +++ b/src/Tests/Public/Get-CCMOutdatedSoftware.Tests.ps1 @@ -0,0 +1,47 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Get-CCMOutdatedSoftware" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Get-CCMSoftware -ModuleName ChocoCCM -MockWith { + @( + @{ + id = 1 + name = "Software 1" + version = "1.0.0" + isOutdated = $true + }, + @{ + id = 2 + name = "Software 2" + version = "1.0.0" + isOutdated = $false + }, + @{ + id = 3 + name = "Software 3" + version = "1.0.0" + isOutdated = $true + } + ) + } + } + + Context "Getting Outdated Software" { + BeforeAll { + $Result = Get-CCMOutdatedSoftware + } + + It "Calls Get-CCMSoftware" { + Should -Invoke Get-CCMSoftware -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly + } + + It "Returns only software where isOutdated is true" { + $Result.isOutdated | Should -Not -Contain $false + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Get-CCMOutdatedSoftwareMember.Tests.ps1 b/src/Tests/Public/Get-CCMOutdatedSoftwareMember.Tests.ps1 new file mode 100644 index 0000000..cc0d051 --- /dev/null +++ b/src/Tests/Public/Get-CCMOutdatedSoftwareMember.Tests.ps1 @@ -0,0 +1,100 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Get-CCMOutdatedSoftwareMember" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMSoftware -ModuleName ChocoCCM -MockWith { + @(1..3 | ForEach-Object {@{softwareId = $_}}) + } + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/ComputerSoftware/GetAllPagedBySoftwareId" + } { + if ($Uri.Query -match "softwareId=(?\d+)") { + $SoftwareId = $Matches.SoftwareId + } + @{ + result = @{ + items = foreach ($ComputerId in 1..4) { + @{ + softwareId = $SoftwareId + software = @{ + name = "VLC Media Player" + packageId = $SoftwareId + packageVersion = "1.0.$($SoftwareId)" + } + computer = @{ + name = "Computer$($ComputerId)" + friendlyName = "Computer $($ComputerId)" + ipaddress = "10.0.0.$($ComputerId)" + fqdn = "computer$($ComputerId).local" + computerid = "$(New-Guid)" + } + } + } + } + } + } + } + + Context "Getting computers that have the specified software installed and requiring an update, using the software name" { + BeforeAll { + $TestParams = @{ + Software = "VLC Media Player" + } + + $Result = Get-CCMOutdatedSoftwareMember @TestParams + } + + # It does seem that this will only ever get the first 100 results per piece of software + It "Calls the API to get computers with the specified software installed" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 3 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/ComputerSoftware/GetAllPagedBySoftwareId" -and + $Uri.Query -match "softwareId=(1|2|3)" + } + } + + It "Returns a record per outdated-software-per-computer combination" { + $Result | Should -HaveCount 12 + } + } + + Context "Getting computers that have the specified software installed and requiring an update, using the package id" { + BeforeAll { + $TestParams = @{ + Package = "vlc" + } + + $Result = Get-CCMOutdatedSoftwareMember @TestParams + } + + # It does seem that this will only ever get the first 100 results per piece of software + It "Calls the API to get computers with the specified software installed" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 3 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/ComputerSoftware/GetAllPagedBySoftwareId" -and + $Uri.Query -match "softwareId=(1|2|3)" + } + } + + It "Returns a record per outdated-software-per-computer combination" { + $Result | Should -HaveCount 12 + } + } + + Context "Failing to return installs of the specified software" { + BeforeAll { + Mock Invoke-RestMethod -ModuleName ChocoCCM { + throw [System.Net.WebException]::new("Failed to get software") + } + } + + # Skipping: Again, we are simply returning the exception message to output, polluting the output + It "Throws an exception" -Skip { + { Get-CCMOutdatedSoftwareMember -Software "vlc" } | Should -Throw + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Get-CCMOutdatedSoftwareReport.Tests.ps1 b/src/Tests/Public/Get-CCMOutdatedSoftwareReport.Tests.ps1 new file mode 100644 index 0000000..57d45c6 --- /dev/null +++ b/src/Tests/Public/Get-CCMOutdatedSoftwareReport.Tests.ps1 @@ -0,0 +1,62 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Get-CCMOutdatedSoftwareReport" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Reports/GetAllPaged" + } { + @{ + result = @{ + items = @( + 1..3 | ForEach-Object { + @{ + reportType = "OutdatedSoftware" + creationTime = "$(Get-Date)" + id = "$(New-Guid)" + } + } + ) + } + } + } + } + + Context "Getting an outdated report (that is actually up to date)" { + BeforeAll { + $Result = Get-CCMOutdatedSoftwareReport + } + + It "Calls the API to get all existing reports" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "GET" -and + $Uri.AbsolutePath -eq "/api/services/app/Reports/GetAllPaged" -and + $Uri.Query -eq "?reportTypeFilter=1" -and + $ContentType -eq "application/json" + } + } + + It "Returns all report objects" { + # Is this the correct behaviour? Check on ReportTypeFilter=1 + $Result | Should -HaveCount 3 + } + } + + Context "Failing to get all reports" { + BeforeAll { + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Reports/GetAllPaged" + } -MockWith { + throw [System.Net.WebException]::new("Failed") + } + } + + It "Throws an exception when failing to get all reports" { + { Get-CCMOutdatedSoftwareReport } | Should -Throw "Failed" + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Get-CCMOutdatedSoftwareReportDetail.Tests.ps1 b/src/Tests/Public/Get-CCMOutdatedSoftwareReportDetail.Tests.ps1 new file mode 100644 index 0000000..55e4e8b --- /dev/null +++ b/src/Tests/Public/Get-CCMOutdatedSoftwareReportDetail.Tests.ps1 @@ -0,0 +1,56 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Get-CCMOutdatedSoftwareReportDetail" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMOutdatedSoftwareReport -ModuleName ChocoCCM { + @( + @{ + reportType = "OutdatedSoftware" + creationTime = "7/4/2020 6:44:40 PM" + id = $script:TestGuid + } + 1..3 | ForEach-Object { + @{ + reportType = "OutdatedSoftware" + creationTime = "$(Get-Date)" + id = "$(New-Guid)" + } + } + ) + } + } + + Context "Getting a specific Outdated Software Report" { + BeforeAll { + $script:TestGuid = "$(New-Guid)" + $TestParams = @{ + Report = "7/4/2020 6:44:40 PM" + } + + $Result = Get-CCMOutdatedSoftwareReportDetail @TestParams + } + + It "Calls Get-CCMOutdatedSoftwareReport to get the report ID" { + Should -Invoke Get-CCMOutdatedSoftwareReport -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly + } + + It "Calls the API to get the report details" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "GET" -and + $Uri.AbsolutePath -eq "/api/services/app/OutdatedReports/GetAllByReportId" -and + $Uri.Query -match "reportId=$($script:TestGuid)" -and + $ContentType -eq "application/json" + } + } + + It "Returns the requested result" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Get-CCMRole.Tests.ps1 b/src/Tests/Public/Get-CCMRole.Tests.ps1 new file mode 100644 index 0000000..9f7a51b --- /dev/null +++ b/src/Tests/Public/Get-CCMRole.Tests.ps1 @@ -0,0 +1,104 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Get-CCMRole" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM -MockWith { + @{ + result = @{ + items = @( + @{ + name = "CCMAdmin" + id = 1 + } + @{ + name = "CCMUser" + id = 2 + } + ) + } + } + } + } + + Context "Getting a specific CCM Role" { + BeforeAll { + $TestValues = @{ + Name = "CCMAdmin" + } + + $Result = Get-CCMRole @TestValues + } + + It "Calls the API to get roles" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "GET" -and + $Uri.AbsolutePath -eq "/api/services/app/Role/GetRoles" -and + $Uri.Query -eq "?permission=" -and + $ContentType -eq "application/json" + } + } + + It "Returns the correct role" { + $Result.Name | Should -Be $TestValues.Name + $Result | Should -HaveCount 1 + } + } + + Context "Getting a non-existent CCM Role" { + BeforeAll { + $TestValues = @{ + Name = "OtherAdmin" + } + + $Result = Get-CCMRole @TestValues + } + + It "Calls the API to get roles" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "GET" -and + $Uri.AbsolutePath -eq "/api/services/app/Role/GetRoles" -and + $Uri.Query -eq "?permission=" -and + $ContentType -eq "application/json" + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + Context "Getting all CCM Roles" { + BeforeAll { + $Result = Get-CCMRole + } + + It "Calls the API to get roles" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "GET" -and + $Uri.AbsolutePath -eq "/api/services/app/Role/GetRoles" -and + $Uri.Query -eq "?permission=" -and + $ContentType -eq "application/json" + } + } + + It "Returns All Returned Roles" { + $Result | Should -HaveCount 2 + } + } + + Context "Failing to get a specified role" { + BeforeAll { + Mock Invoke-RestMethod -ModuleName ChocoCCM -MockWith { + throw [System.Net.WebException]::new("Failed") + } + } + + It "Throws an exception when failing to get a specified role" { + { Get-CCMRole -Name "CCMBadmin" } | Should -Throw "Failed" + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Get-CCMSoftware.Tests.ps1 b/src/Tests/Public/Get-CCMSoftware.Tests.ps1 new file mode 100644 index 0000000..894932d --- /dev/null +++ b/src/Tests/Public/Get-CCMSoftware.Tests.ps1 @@ -0,0 +1,152 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Get-CCMSoftware" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Software/GetAll" + } { + @{ + result = @{ + items = @( + @{ + id = 37 + name = "VLC Media Player" + packageId = "vlc" + } + @{ + id = 38 + name = "Mozilla Firefox" + packageId = "mozillafirefox" + } + ) + } + } + } + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/ComputerSoftware/GetAllPagedBySoftwareId" + } { + @{ + result = @( + @{ + id = 37 + name = "VLC Media Player" + packageId = "vlc" + } + ) + } + } + } + + Context "Gets all software" { + BeforeAll { + $Result = Get-CCMSoftware + } + + It "Calls the API to get all software IDs" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Software/GetAll" + } + } + + It "Returns Nothing" { + $Result | Should -HaveCount 2 + $Result.name | Should -Contain "VLC Media Player" + $Result.name | Should -Contain "Mozilla Firefox" + } + } + + Context "Gets software by name" { + BeforeAll { + $TestParams = @{ + Software = "VLC Media Player" + } + + $Result = Get-CCMSoftware @TestParams + } + + It "Calls the API to get all software IDs" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Software/GetAll" + } + } + + It "Calls the API to get the specific software ID" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/ComputerSoftware/GetAllPagedBySoftwareId" -and + $Uri.Query -match "softwareId=37" + } + } + + It "Returns the VLC Software Details" { + $Result | Should -HaveCount 1 + $Result.Name | Should -Be "VLC Media Player" + $Result.packageId | Should -Be "vlc" + } + } + + Context "Gets software by package id" { + BeforeAll { + $TestParams = @{ + Package = "vlc" + } + + $Result = Get-CCMSoftware @TestParams + } + + It "Calls the API to get all software IDs" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Software/GetAll" + } + } + + It "Calls the API to get the specific software ID" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/ComputerSoftware/GetAllPagedBySoftwareId" -and + $Uri.Query -match "softwareId=37" + } + } + + It "Returns the VLC Software Details" { + $Result | Should -HaveCount 1 + $Result.Name | Should -Be "VLC Media Player" + $Result.packageId | Should -Be "vlc" + } + } + + Context "Gets software by software id" { + BeforeAll { + $TestParams = @{ + Id = "37" + } + + $Result = Get-CCMSoftware @TestParams + } + + It "Does not call the API to get all software IDs" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 0 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/Software/GetAll" + } + } + + It "Calls the API to get the specific software ID" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/ComputerSoftware/GetAllPagedBySoftwareId" -and + $Uri.Query -match "softwareId=37" + } + } + + # Why is ID not expanding .items? + # Potential bug around items vs not items, given the same call in all cases. + It "Returns the VLC Software Details" -Skip { + $Result | Should -HaveCount 1 + $Result.Name | Should -Be "VLC Media Player" + $Result.packageId | Should -Be "vlc" + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Get-DeploymentResult.Tests.ps1 b/src/Tests/Public/Get-DeploymentResult.Tests.ps1 new file mode 100644 index 0000000..64aa54a --- /dev/null +++ b/src/Tests/Public/Get-DeploymentResult.Tests.ps1 @@ -0,0 +1,58 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Get-DeploymentResult" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMDeployment -ModuleName ChocoCCM { + @{Id = 13} + } + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Uri.AbsolutePath -eq "/api/services/app/DeploymentSteps/GetAllPagedByDeploymentPlanId" + } { + @{ + result = @{ + items = @( + @{ + id = 13 + name = "Google Chrome Upgrade" + } + ) + } + } + } + } + + Context "Getting a deployment result" { + BeforeAll { + $TestParams = @{ + Deployment = "Google Chrome Upgrade" + } + + $Result = Get-DeploymentResult @TestParams + } + + It "Retrieves the deployment ID for the requested Deployment Name" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Name -eq $TestParams.Deployment + } + } + + It "Calls the API to retrieve the deployment result based on the ID" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "GET" -and + $Uri.AbsolutePath -eq "/api/services/app/DeploymentSteps/GetAllPagedByDeploymentPlanId" -and + $ContentType -eq "application/json" -and + $Uri.Query -match "deploymentPlanId=13" + } + } + + It "Returns the result items" { + $Result.name | Should -Be "Google Chrome Upgrade" + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Import-PDQDeployPackage.Tests.ps1 b/src/Tests/Public/Import-PDQDeployPackage.Tests.ps1 new file mode 100644 index 0000000..b1dfd3c --- /dev/null +++ b/src/Tests/Public/Import-PDQDeployPackage.Tests.ps1 @@ -0,0 +1,48 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Import-PDQDeployPackage" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock New-CCMDeployment -ModuleName ChocoCCM + Mock New-CCMDeploymentStep -ModuleName ChocoCCM + } + + # Skipping: I need an example of the XML file. + Context "Importing an Example Package" -Skip { + BeforeAll { + New-Item -Path $TestDrive -Name "ExamplePackage.xml" -Value @" + +"@ + $TestParams = @{ + PdqXml = "$TestDrive\ExamplePackage.xml" + } + + $Result = Import-PDQDeployPackage @TestParams + } + + It "Creates a new deployment with the name from the package" { + Should -Invoke New-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Name -eq "PDQ Import: Example Package" + } + } + + It "Creates a step for each step within the PDQ Deployment" { + Should -Invoke New-CCMDeploymentStep -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Deployment -eq "PDQ Import: Example Package" -and + $Name -eq "Install Example Package" -and + $Type -eq "Basic" -and + $ValidExitCodes -eq @("0") -and + $FailOnError -eq $false + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Move-CCMDeploymentToReady.Tests.ps1 b/src/Tests/Public/Move-CCMDeploymentToReady.Tests.ps1 new file mode 100644 index 0000000..107fde8 --- /dev/null +++ b/src/Tests/Public/Move-CCMDeploymentToReady.Tests.ps1 @@ -0,0 +1,65 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Move-CCMDeploymentToReady" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMDeployment -ModuleName ChocoCCM { + @{Id = $script:IdUnderTest} + } + } + + Context "Moving a depoloyment to Ready" { + BeforeAll { + $script:IdUnderTest = Get-Random -Minimum 1 -Maximum 100 + $TestParams = @{ + Deployment = "Complex Deployment" + } + + $Result = Move-CCMDeploymentToReady @TestParams + } + + It "Retrieves the deployment ID for the requested Deployment Name" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Name -eq $TestParams.Deployment + } + } + + It "Calls the API to move the returned ID to Ready" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/MoveToReady" -and + $ContentType -eq "application/json" -and + $Body.id -eq $script:IdUnderTest + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Failing to move a deployment step to ready" { + BeforeAll { + Mock Invoke-RestMethod -ModuleName ChocoCCM { + throw [webexception]::new("The remote server returned an error: (500) Internal Server Error.") + } + + $TestParams = @{ + Deployment = "Complex Deployment" + } + } + + It "Throws an error when failing to move a deployment step to ready" { + { Move-CCMDeploymentToReady @TestParams } | Should -Throw + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/New-CCMDeployment.Tests.ps1 b/src/Tests/Public/New-CCMDeployment.Tests.ps1 new file mode 100644 index 0000000..ac2491c --- /dev/null +++ b/src/Tests/Public/New-CCMDeployment.Tests.ps1 @@ -0,0 +1,52 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "New-CCMDeployment" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/CreateOrEdit" + } { + @{ + result = @{ + id = $script:GuidUnderTest + } + } + } + } + + Context "Creating a new deployment" { + BeforeAll { + $script:GuidUnderTest = "$(New-Guid)" + $TestParams = @{ + Name = "$(New-Guid)" + } + + $Result = New-CCMDeployment @TestParams + } + + It "Calls the API to create a new deployment" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Name -eq $TestParams.Name + } + } + + It "Returns Nothing" { + $Result.name | Should -Be $TestParams.Name + + # This should be returned by the request to DeploymentPlans/CreateOrEdit + $Result.id | Should -Be $script:GuidUnderTest + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/New-CCMDeploymentStep.Tests.ps1 b/src/Tests/Public/New-CCMDeploymentStep.Tests.ps1 new file mode 100644 index 0000000..de35a1c --- /dev/null +++ b/src/Tests/Public/New-CCMDeploymentStep.Tests.ps1 @@ -0,0 +1,136 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "New-CCMDeploymentStep" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMDeployment -ModuleName ChocoCCM { + @{Id = "ID:$Name"} + } + Mock Get-CCMGroup -ModuleName ChocoCCM { + foreach ($Group in $Group) { + @{ + Name = $Group + Id = "ID:$Group" + } + } + } + } + + Context "Creating a basic deployment step" { + BeforeAll { + $TestParams = @{ + Deployment = "PowerShell" + Name = "From ChocoCCM" + TargetGroup = "WebServers" + Type = "Basic" + ChocoCommand = "upgrade" + PackageName = "firefox" + } + + $Result = New-CCMDeploymentStep @TestParams + } + + It "Calls the API to create the basic deployment step" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/DeploymentSteps/CreateOrEdit" -and + $ContentType -eq "application/json" -and + + $Body.Name -eq $TestParams.Name -and + $Body.DeploymentPlanId -eq "ID:$($TestParams.Deployment)" -and + $Body.DeploymentStepGroups.groupname -eq $TestParams.TargetGroup -and + $Body.script -eq "$($TestParams.ChocoCommand.ToLower())|$($TestParams.PackageName)" + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Creating an advanced deployment step" { + BeforeAll { + $TestParams = @{ + Deployment = "PowerShell" + Name = "From ChocoCCM" + TargetGroup = "All", "PowerShell" + Type = "Advanced" + Script = { + foreach ($p in Get-Process) { + Write-Host $p.PID + } + Write-Host "end" + } + } + + $Result = New-CCMDeploymentStep @TestParams + } + + It "Calls the API to create the basic deployment step" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/DeploymentSteps/CreateOrEditPrivileged" -and + $ContentType -eq "application/json" -and + + $Body.Name -eq $TestParams.Name -and + $Body.DeploymentPlanId -eq "ID:$($TestParams.Deployment)" -and + "$($Body.DeploymentStepGroups.groupname)" -eq "$($TestParams.TargetGroup)" -and + $Body.script -eq $TestParams.Script.ToString() + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Creating an advanced deployment step from a file" { + # New-CCMDeploymentStep -Deployment PowerShell -Name 'From ChocoCCM' -TargetGroup All,PowerShell -Type Advanced -Script {(Get-Content C:\script.txt)} + BeforeAll { + New-Item $TestDrive\script.txt -ItemType File -Value 'foreach ($p in Get-Process) { Write-Host $p.PID } Write-Host "end"' + $TestParams = @{ + Deployment = "PowerShell" + Name = "From ChocoCCM" + TargetGroup = "All", "PowerShell" + Type = "Advanced" + Script = { (Get-Content $TestDrive\script.txt) } + } + + $Result = New-CCMDeploymentStep @TestParams + } + + It "Calls the API to create the basic deployment step" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/DeploymentSteps/CreateOrEditPrivileged" -and + $ContentType -eq "application/json" -and + + $Body.Name -eq $TestParams.Name -and + $Body.DeploymentPlanId -eq "ID:$($TestParams.Deployment)" -and + "$($Body.DeploymentStepGroups.groupname)" -eq "$($TestParams.TargetGroup)" -and + $Body.script -eq $TestParams.Script.ToString() + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/New-CCMOutdatedSoftwareReport.Tests.ps1 b/src/Tests/Public/New-CCMOutdatedSoftwareReport.Tests.ps1 new file mode 100644 index 0000000..5ff469a --- /dev/null +++ b/src/Tests/Public/New-CCMOutdatedSoftwareReport.Tests.ps1 @@ -0,0 +1,30 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "New-CCMOutdatedSoftwareReport" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + } + + Context "Creating a new outdated software report" { + BeforeAll { + $Result = New-CCMOutdatedSoftwareReport + } + + It "Calls the API to create a new outdated report" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/OutdatedReports/Create" -and + $ContentType -eq "application/json" + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Remove-CCMDeployment.Tests.ps1 b/src/Tests/Public/Remove-CCMDeployment.Tests.ps1 new file mode 100644 index 0000000..301af36 --- /dev/null +++ b/src/Tests/Public/Remove-CCMDeployment.Tests.ps1 @@ -0,0 +1,76 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Remove-CCMDeployment" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMDeployment -ModuleName ChocoCCM { @{Id = $script:IDUnderTest} } + } + + Context "Removing a deployment" { + BeforeAll { + $TestParams = @{ + Deployment = "Super Complex Deployment" + } + + $Result = Remove-CCMDeployment @TestParams -Confirm:$false + } + + It "Gets the ID for the deployment to delete" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Name -eq $TestParams.Deployment + } + } + + It "Calls the API to delete the deployment" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "DELETE" -and + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/Delete" -and + $Uri.Query -eq "?Id=$($script:IDUnderTest)" -and + $ContentType -eq "application/json" + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Removing multiple deployments" { + BeforeAll { + $TestParams = @{ + Deployment = @( + "Super Complex Deployment" + "Deployment Alpha" + ) + } + + $Result = Remove-CCMDeployment @TestParams -Confirm:$false + } + + It "Gets the ID for the deployment to delete" { + foreach ($Deployment in $TestParams.Deployment) { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Name -eq $Deployment + } + } + } + + It "Calls the API to delete each deployment" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times $TestParams.Deployment.Count -Exactly -ParameterFilter { + $Method -eq "DELETE" -and + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/Delete" -and + $Uri.Query -eq "?Id=$($script:IDUnderTest)" -and + $ContentType -eq "application/json" + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Remove-CCMDeploymentStep.Tests.ps1 b/src/Tests/Public/Remove-CCMDeploymentStep.Tests.ps1 new file mode 100644 index 0000000..99231b5 --- /dev/null +++ b/src/Tests/Public/Remove-CCMDeploymentStep.Tests.ps1 @@ -0,0 +1,51 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Remove-CCMDeploymentStep" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMDeployment -ModuleName ChocoCCM { + @{ + Id = "1" + deploymentSteps = @( + @{ + id = "2" + Name = "Copy Files" + } + @{ + id = "1" + Name = "Kill web services" + } + ) + } + } + } + + Context "Removing a deployment step" { + BeforeAll { + $TestParams = @{ + Deployment = "Deployment Alpha" + Step = "Copy Files" + } + + $Result = Remove-CCMDeploymentStep @TestParams -Confirm:$false + } + + It "Calls the API to remove the deployment step" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "DELETE" -and + $Uri.AbsolutePath -eq "/api/services/app/DeploymentSteps/Delete" -and + $Uri.Query -eq "?Id=2" -and + $ContentType -eq "application/json" + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Remove-CCMGroup.Tests.ps1 b/src/Tests/Public/Remove-CCMGroup.Tests.ps1 new file mode 100644 index 0000000..1da7fa4 --- /dev/null +++ b/src/Tests/Public/Remove-CCMGroup.Tests.ps1 @@ -0,0 +1,79 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Remove-CCMGroup" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMGroup -ModuleName ChocoCCM { + @{ + Id = "$($Group)ID" + } + } + } + + Context "Removing a group" { + BeforeAll { + $TestParams = @{ + Group = "WebServers" + } + + $Result = Remove-CCMGroup @TestParams -Confirm:$false + } + + It "Calls Get-CCMGroup to get the ID for the group" { + Should -Invoke Get-CCMGroup -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Group -eq $TestParams.Group + } + } + + It "Calls the API to remove the group" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "DELETE" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/Delete" -and + $Uri.Query -eq "?id=$($TestParams.Group)ID" -and + $ContentType -eq "application/json" + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Removing multiple groups" { + BeforeAll { + $TestParams = @{ + Group = "WebServers", "TestAppDeployment" + } + + $Result = Remove-CCMGroup @TestParams -Confirm:$false + } + + It "Calls Get-CCMGroup to get the ID for the group" { + foreach ($GroupName in $TestParams.Group) { + Should -Invoke Get-CCMGroup -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Group -eq $GroupName + } + } + } + + It "Calls the API to remove the group" { + foreach ($GroupName in $TestParams.Group) { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Method -eq "DELETE" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/Delete" -and + $Uri.Query -eq "?id=$($GroupName)ID" -and + $ContentType -eq "application/json" + } + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Remove-CCMGroupMember.Tests.ps1 b/src/Tests/Public/Remove-CCMGroupMember.Tests.ps1 new file mode 100644 index 0000000..edbb85a --- /dev/null +++ b/src/Tests/Public/Remove-CCMGroupMember.Tests.ps1 @@ -0,0 +1,99 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Remove-CCMGroupMember" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM -ParameterFilter { + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" + } { + @{ + success = $true + } + } + Mock Get-CCMGroupMember -ModuleName ChocoCCM { + @{ + Id = 1 + Name = "TestLab" + Computers = @( + @{ + computerId = 1 + name = "TestPC1" + } + @{ + computerId = 2 + name = "TestPC2" + } + ) + Groups = @( + @{ + subGroupId = 3 + name = "FirstLab" + } + @{ + subGroupId = 4 + name = "SecondLab" + } + ) + } + } + Mock Get-CCMComputer -ModuleName ChocoCCM { + @{ + Id = 1 + Name = "TestPC1" + } + @{ + Id = 2 + Name = "TestPC2" + } + @{ + Id = 3 + Name = "Test1" + } + @{ + Id = 4 + Name = "Test2" + } + } + Mock Get-CCMGroup -ModuleName ChocoCCM + } + + Context "Removing a computer from a group" { + BeforeAll { + $TestParams = @{ + Group = "TestLab" + ComputerMember = "TestPC1" + } + + $Result = Remove-CCMGroupMember @TestParams + } + + It "Calls the API to update the group object" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + $Body.Computers.name -eq @("TestPC2") -and + "$($Body.Groups.name)" -eq "FirstLab SecondLab" + } + } + + # TODO: This seems broken, but I'm not yet sure why. Returns [system.string[]] as if cast to string. + It "Returns an updated object representing the group" -Skip { + $Result | Should -Be [PSCustomObject]@{ + Status = $true + Group = $TestParams.Group + AffectedComputers = $TestParams.ComputerMember + AffectedGroups = $null + } + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Remove-CCMStaleDeployment.Tests.ps1 b/src/Tests/Public/Remove-CCMStaleDeployment.Tests.ps1 new file mode 100644 index 0000000..7887fee --- /dev/null +++ b/src/Tests/Public/Remove-CCMStaleDeployment.Tests.ps1 @@ -0,0 +1,47 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Remove-CCMStaleDeployment" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMDeployment -ModuleName ChocoCCM { + 1..60 | ForEach-Object { + @{ + Deployment = $_ + CreationDate = (Get-Date).AddDays(-$_) + Result = 0 # Is 0 really a bad state? + } + } + } + Mock Remove-CCMDeployment -ModuleName ChocoCCM + } + + # This function is broken. It tries to use the -All parameter of Get-CCMDeployment, but that parameter doesn't exist. + Context "Removing Stale Deployments" -Skip { + BeforeAll { + $TestParams = @{ + Age = "30" + } + + $Result = Remove-CCMStaleDeployment @TestParams -Confirm:$false + } + + It "Calls Get-CCMDeployment to find all existing deployments" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly + } + + It "Calls Remove-CCMDeployment to remove deployments with age greater than 30 days" { + Should -Invoke Remove-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 30 -Exactly -ParameterFilter { + $Deployment -ge 30 # This test could be improved, but as the function is broken it is what it is. + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Set-CCMDeploymentStep.Tests.ps1 b/src/Tests/Public/Set-CCMDeploymentStep.Tests.ps1 new file mode 100644 index 0000000..9bc1446 --- /dev/null +++ b/src/Tests/Public/Set-CCMDeploymentStep.Tests.ps1 @@ -0,0 +1,111 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Set-CCMDeploymentStep" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMDeployment -ModuleName ChocoCCM + } + + # Skipping: This function is currently not fully implemented + Context "Setting a basic deployment step" -Skip { + BeforeAll { + $TestParams = @{ + Deployment = "Google Chrome Update" + Step = "Upgrade" + TargetGroup = "LabPCs" + ExecutionTimeoutSeconds = 14400 + ChocoCommand = "Upgrade" + PackageName = "googlechrome" + } + + $Result = Set-CCMDeploymentStep @TestParams + } + + It "Calls Get-CCMDeployment to get the deployment ID" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Name -eq $TestParams.Deployment + } + } + + It "Calls Get-CCMDeployment to get the existing configuration" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Id -eq "$($TestParams.Deployment)ID" + } + } + + It "Calls the API to update the deployment" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "GET" -and + $Uri.AbsolutePath -eq "/api/services/app/Role/GetRoles" -and + $Uri.Query -eq "?permission=" -and + $ContentType -eq "application/json" -and + $Body.usernameOrEmailAddress -eq $TestParams.Credential.UserName -and + $Body.password -eq $TestParams.Credential.GetNetworkCredential().Password + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + # Skipping: This function is currently not fully implemented + Context "Setting a complex deployment step" -Skip { + BeforeAll { + $TestParams = @{ + Deployment = "OS Version" + Step = "Gather Info" + TargetGroup = "US-East servers" + Script = { + $data = Get-WMIObject win32_OperatingSystem + [pscustomobject]@{ + Name = $data.caption + Version = $data.version + } + } + } + + $Result = Set-CCMDeploymentStep @TestParams + } + + It "Calls Get-CCMDeployment to get the deployment ID" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Name -eq $TestParams.Deployment + } + } + + It "Calls Get-CCMDeployment to get the existing configuration" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Id -eq "$($TestParams.Deployment)ID" + } + } + + It "Calls the API to update the deployment" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "GET" -and + $Uri.AbsolutePath -eq "/api/services/app/Role/GetRoles" -and + $Uri.Query -eq "?permission=" -and + $ContentType -eq "application/json" -and + $Body.usernameOrEmailAddress -eq $TestParams.Credential.UserName -and + $Body.password -eq $TestParams.Credential.GetNetworkCredential().Password + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Set-CCMGroup.Tests.ps1 b/src/Tests/Public/Set-CCMGroup.Tests.ps1 new file mode 100644 index 0000000..50566f2 --- /dev/null +++ b/src/Tests/Public/Set-CCMGroup.Tests.ps1 @@ -0,0 +1,134 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Set-CCMGroup" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMGroupMember -ModuleName ChocoCCM { + @{ + Id = 1 + Name = $Group + Description = "An existing description" + Computers = @() + Groups = @() + } + } + } + + Context "Updating a description" { + BeforeAll { + $TestParams = @{ + Group = "Finance" + NewDescription = "Computers in the finance division" + } + + $Result = Set-CCMGroup @TestParams + } + + It "Gets the existing group information" { + Should -Invoke Get-CCMGroupMember -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Group -eq $TestParams.Group + } + } + + It "Calls the API to update the group" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + + $Body.Id -eq 1 -and + $Body.Name -eq $TestParams.Group -and + $Body.Description -eq $TestParams.NewDescription + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Updating a name" { + BeforeAll { + $TestParams = @{ + Group = "IT" + NewName = "TheBestComputers" + } + + $Result = Set-CCMGroup @TestParams + } + + It "Gets the existing group information" { + Should -Invoke Get-CCMGroupMember -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Group -eq $TestParams.Group + } + } + + It "Calls the API to update the group" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + + $Body.Id -eq 1 -and + $Body.Name -eq $TestParams.NewName -and + $Body.Description -eq "An existing description" # Has not been changed + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Updating a name and description" { + # Set-CCMGroup -Group Test -NewName NewMachineImaged -Description 'Group for freshly imaged machines needing a baseline package pushed to them' + BeforeAll { + $TestParams = @{ + Group = "Test" + NewName = "NewMachineImaged" + NewDescription = "Group for freshly imaged machines needing a baseline package pushed to them" + } + + $Result = Set-CCMGroup @TestParams + } + + It "Gets the existing group information" { + Should -Invoke Get-CCMGroupMember -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Group -eq $TestParams.Group + } + } + + It "Calls the API to update the group" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/Groups/CreateOrEdit" -and + $ContentType -eq "application/json" -and + + $Body.Id -eq 1 -and + $Body.Name -eq $TestParams.NewName -and + $Body.Description -eq $TestParams.NewDescription + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Set-CCMNotificationStatus.Tests.ps1 b/src/Tests/Public/Set-CCMNotificationStatus.Tests.ps1 new file mode 100644 index 0000000..1e1da1a --- /dev/null +++ b/src/Tests/Public/Set-CCMNotificationStatus.Tests.ps1 @@ -0,0 +1,70 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Set-CCMNotificationStatus" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + } + + Context "Setting notification On" { + BeforeAll { + $TestParams = @{ + Enable = $true + } + + $Result = Set-CCMNotificationStatus @TestParams + } + + It "Calls the API to set the notification status" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "PUT" -and + $Uri.AbsolutePath -eq "/api/services/app/Notification/UpdateNotificationSettings" -and + $ContentType -eq "application/json" -and + $Body.receiveNotifications -eq $true -and + $Body.notifications.name -eq "App.NewUserRegistered" -and + $Body.notifications.isSubscribed -eq $true + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } + + Context "Setting notification Off" { + BeforeAll { + $TestParams = @{ + Disable = $true + } + + $Result = Set-CCMNotificationStatus @TestParams + } + + It "Calls the API to set the notification status" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "PUT" -and + $Uri.AbsolutePath -eq "/api/services/app/Notification/UpdateNotificationSettings" -and + $ContentType -eq "application/json" -and + $Body.receiveNotifications -eq $false -and + $Body.notifications.name -eq "App.NewUserRegistered" -and + $Body.notifications.isSubscribed -eq $true + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Start-CCMDeployment.Tests.ps1 b/src/Tests/Public/Start-CCMDeployment.Tests.ps1 new file mode 100644 index 0000000..6d324c6 --- /dev/null +++ b/src/Tests/Public/Start-CCMDeployment.Tests.ps1 @@ -0,0 +1,51 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Start-CCMDeployment" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMDeployment -ModuleName ChocoCCM { + @{ + Id = "$($Name)ID" + Name = $Name + } + } + } + + Context "Starting a deployment" { + BeforeAll { + $TestParams = @{ + Deployment = "Complex Deployment" + } + + $Result = Start-CCMDeployment @TestParams + } + + It "Gets the deployment ID from Get-CCMDeployment" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Name -eq $TestParams.Deployment + } + } + + It "Calls the API to start the deployment" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/Start" -and + $ContentType -eq "application/json" -and + $Body.id -eq "$($TestParams.Deployment)ID" + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/Public/Stop-CCMDeployment.Tests.ps1 b/src/Tests/Public/Stop-CCMDeployment.Tests.ps1 new file mode 100644 index 0000000..247c41d --- /dev/null +++ b/src/Tests/Public/Stop-CCMDeployment.Tests.ps1 @@ -0,0 +1,51 @@ +Import-Module $PSScriptRoot\..\..\ChocoCCM.psd1 + +Describe "Stop-CCMDeployment" { + BeforeAll { + InModuleScope -ModuleName ChocoCCM { + $script:Session = [Microsoft.PowerShell.Commands.WebRequestSession]::new() + $script:HostName = "localhost" + $script:Protocol = "http" + } + Mock Invoke-RestMethod -ModuleName ChocoCCM + Mock Get-CCMDeployment -ModuleName ChocoCCM { + @{ + Id = "$($Name)ID" + Name = $Name + } + } + } + + Context "Stopping a deployment" { + BeforeAll { + $TestParams = @{ + Deployment = "Upgrade VLC" + } + + $Result = Stop-CCMDeployment @TestParams -Confirm:$false + } + + It "Gets the Deployment ID from Get-CCMDeployment" { + Should -Invoke Get-CCMDeployment -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + $Name -eq $TestParams.Deployment + } + } + + It "Calls the API to stop the deployment" { + Should -Invoke Invoke-RestMethod -ModuleName ChocoCCM -Scope Context -Times 1 -Exactly -ParameterFilter { + if ($Body -is [string]) { + $Body = $Body | ConvertFrom-Json + } + + $Method -eq "POST" -and + $Uri.AbsolutePath -eq "/api/services/app/DeploymentPlans/Cancel" -and + $ContentType -eq "application/json" -and + $Body.id -eq "$($TestParams.Deployment)ID" + } + } + + It "Returns Nothing" { + $Result | Should -BeNullOrEmpty + } + } +} \ No newline at end of file diff --git a/src/Tests/chococcm.tests.ps1 b/src/Tests/chococcm.tests.ps1 index 05c757e..24367ce 100644 --- a/src/Tests/chococcm.tests.ps1 +++ b/src/Tests/chococcm.tests.ps1 @@ -16,5 +16,3 @@ Describe "Module Import Checks" { { Get-Command -Module ChocoCCM } | Should -Not -Throw } } - -#TODO: Lots of mocks for actual function tests diff --git a/test.ps1 b/test.ps1 new file mode 100644 index 0000000..70e43b0 --- /dev/null +++ b/test.ps1 @@ -0,0 +1,36 @@ +param ( + [String] $Path = ".", + [String] $Output = "Detailed", + [Switch] $CodeCoverage +) + +Import-Module Pester -MinimumVersion 5.2.0 + +$Configuration = [PesterConfiguration]::Default + +$Configuration.Run.Path = $Path + +$Configuration.Output.Verbosity = $Output + +$Configuration.CodeCoverage.Enabled = [bool] $CodeCoverage +# CoverageGutters is new option in Pester 5.2 +$Configuration.CodeCoverage.UseBreakpoints = $false +$Configuration.CodeCoverage.OutputFormat = "CoverageGutters" +$Configuration.CodeCoverage.Path = "$PSScriptRoot/src" +$Configuration.CodeCoverage.OutputPath = "$PSScriptRoot/coverage.xml" +$Configuration.CodeCoverage.CoveragePercentTarget = 90 + +$Configuration.Debug.WriteDebugMessages = $true +$Configuration.Debug.WriteDebugMessagesFrom = "CodeCoverage" + + +# for convenience just run the passed file when we invoke this via launchConfig.json when +# the file is a non-test file +$isDirectory = (Get-Item $Path).PSIsContainer +$isTestFile = $Path.EndsWith($Configuration.Run.TestExtension.Value) +if (-not $isDirectory -and -not $isTestFile) { + & $Path + return +} + +Invoke-Pester -Configuration $Configuration \ No newline at end of file