Tests/Unit/MSFT_xWebsite.Tests.ps1
$DSCResourceName = 'MSFT_xWebsite' $Splat = @{ Path = $PSScriptRoot ChildPath = "..\..\DSCResources\$DSCResourceName\$DSCResourceName.psm1" Resolve = $true ErrorAction = 'Stop' } $DSCResourceModuleFile = Get-Item -Path (Join-Path @Splat) # should check for the server OS if($env:APPVEYOR_BUILD_VERSION) { Add-WindowsFeature Web-Server -Verbose } if (Get-Module -Name $DSCResourceName) { Remove-Module -Name $DSCResourceName } Import-Module -Name $DSCResourceModuleFile.FullName -Force $moduleRoot = "${env:ProgramFiles}\WindowsPowerShell\Modules\xWebAdministration" if(-not (Test-Path -Path $moduleRoot)) { $null = New-Item -Path $moduleRoot -ItemType Directory } Copy-Item -Path $PSScriptRoot\..\..\* -Destination $moduleRoot -Recurse -Force -Exclude '.git' InModuleScope $DSCResourceName { Describe "how Test-TargetResource to Ensure = 'Present'" { $MockSite = @{ Ensure = 'Present' Name = 'MockName' PhysicalPath = 'C:\NonExistant' ID = 1 State = 'MockState' ApplicationPool = 'MockPool' } Context 'WebAdminstration is not installed' { It 'should throw an error if WebAdministration is not installed' { Mock Get-Module -ModuleName $ModuleName { return $null } { Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath } | Should Throw 'Please ensure that WebAdministration module is installed.' } } Context 'Check Ensure is false' { It 'should return false' { Mock Get-Website { return $null } $result = Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath -Verbose:$VerbosePreference $result | Should Be $false } } Context 'Check Physical Property is false' { Mock Get-Website { return $MockSite } Mock Test-WebsitePath -ModuleName $ModuleName { return $true } $result = Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath -Verbose:$VerbosePreference It 'should return false' { $result | Should Be $false } } Context 'Check State is false' { Mock Get-Website { return $MockSite } Mock Test-WebsitePath -ModuleName $ModuleName { return $false } $result = Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath -State 'Started' -Verbose:$VerbosePreference It 'should return false' { $result | Should Be $false } } Context 'Check Application Pool is false' { $MockSite = @{ Ensure = 'Present' Name = 'MockName' PhysicalPath = 'C:\NonExistant' ID = 1 State = 'Started' ApplicationPool = 'MockPool' } Mock Get-Website { return $MockSite } Mock Test-WebsitePath -ModuleName $ModuleName { return $false } $result = Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -Verbose:$VerbosePreference It 'should return false' { $result | Should Be $false } } Context 'Binding Properties is false' { $MockSite = @{ Ensure = 'Present' Name = 'MockName' PhysicalPath = 'C:\NonExistant' ID = 1 State = 'Started' ApplicationPool = 'MockPool' } $BindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' } $MockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ Port = [System.UInt16] $BindingObject.Port Protocol = $BindingObject.Protocol IPAddress = $BindingObject.IPaddress HostName = $BindingObject.Hostname } -ClientOnly Mock Get-Website { return $MockSite } Mock Test-WebsitePath -ModuleName $ModuleName { return $true } Mock Test-WebsiteBindings -ModuleName $ModuleName -Name $Name -BindingInfo $BindingInfo { return $false } $result = Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool' -BindingInfo $MockBinding -Verbose:$VerbosePreference It 'should return false' { $result | Should Be $false } } Context 'Default Page is false' { $MockSite = @{ Ensure = 'Present' Name = 'MockName' PhysicalPath = 'C:\NonExistant' ID = 1 State = 'Started' ApplicationPool = 'MockPool' DefaultPage = 'something' } $BindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' } $MockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ Port = [System.UInt16] $BindingObject.Port Protocol = $BindingObject.Protocol IPAddress = $BindingObject.IPaddress HostName = $BindingObject.Hostname } -ClientOnly Mock Get-Website { return $MockSite } Mock Test-WebsitePath { return $true } Mock Test-WebsiteBindings -Name $Name -BindingInfo $BindingInfo { return $true } Mock Get-WebConfiguration { return 'Notsomething' } $result = Test-TargetResource -Name $MockSite.Name -Ensure $MockSite.Ensure -PhysicalPath $MockSite.PhysicalPath -State $MockSite.State -ApplicationPool $MockSite.ApplicationPool -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage -Verbose:$VerbosePreference It 'should return false' { $result | Should Be $false } } } Describe "how Get-TargetResource responds to Ensure = 'Present'" { $MockSite = @{ Ensure = 'Present' Name = 'MockName' PhysicalPath = 'C:\NonExistant' ID = 1 State = 'Started' ApplicationPool = 'MockPool' } $BindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' } $MockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ Port = [System.UInt16] $BindingObject.Port Protocol = $BindingObject.Protocol IPAddress = $BindingObject.IPaddress HostName = $BindingObject.Hostname } -ClientOnly Context 'WebAdminstration is not installed' { It 'should throw an error if WebAdministration is not installed' { Mock Get-Module -ModuleName $ModuleName { return $null } { Get-TargetResource -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath } | Should Throw 'Please ensure that WebAdministration module is installed.' } } Context 'No Website exists' { Mock Get-Website { return $null } $result = Get-TargetResource -Name 'MockName' -PhysicalPath $MockSite.PhysicalPath It 'should return absent' { $result.Ensure | Should Be 'Absent' } } Context 'Multiple Websites of the same name exist' { Mock Get-Website -ModuleName 'MSFT_xWebsite' { return @( [PSCustomObject] @{ Name = 'Site1' }, [PSCustomObject] @{ Name = 'Site1' } ) } $errorId = 'WebsiteDiscoveryFailure,Get-TargetResource' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult $errorMessage = $($LocalizedData.WebsiteDiscoveryFailureError) -f 'Site1' $exception = New-Object System.InvalidOperationException $errorMessage $errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $errorId, $errorCategory, $null It 'should throw "WebsiteDiscoveryFailure"' { { Get-TargetResource -Name 'Site1' -PhysicalPath 'C:\somePath' } | Should Throw $errorRecord } } Context 'Single website exists' { $BindingObject = [PSCustomObject] @{ Protocol = 'https' IPAddress = '127.0.0.1' Port = 443 HostName = 'MockHostName' } $BindingInfo = [PSCustomObject] @{ bindingInformation = '127.0.0.1:443:MockHostName' protocol = 'https' SslFlags = 1 CertificateHash = '3E09CCC8DFDCB8E3D4A83CFF164CC4754C25E9E5' CertificateStoreName = 'My' } $Website = [PSCustomObject] @{ Name = 'MockHostName' PhysicalPath = 'C:\SomePath' State = 'Started' ID = 0 ApplicationPool = 'Pool' Count = 1 } Mock Get-Website { return $Website } Mock Get-ItemProperty { return @{ collection = $BindingInfo } } Mock Get-WebConfiguration { return $null } It 'should not throw' { { Get-TargetResource -Name 'MockHostName' -PhysicalPath 'C:\somePath' } | Should Not throw } $result = Get-TargetResource -Name 'MockHostName' -PhysicalPath 'C:\somePath' It 'should call Get-Website once' { Assert-MockCalled -commandName Get-Website } It 'should call Get-itemProperty once' { Assert-MockCalled -commandName Get-ItemProperty } It 'should return the name' { $result.Name | Should Be 'MockHostName' } It 'should return the EnsureResult' { $result.Ensure | Should Be 'Present' } It 'should return the PhysicalPath' { $result.PhysicalPath | Should Be 'C:\SomePath' } It 'should return the correct bindings' { $result.BindingInfo.Port | Should Be $BindingObject.Port $result.BindingInfo.Protocol | Should Be $BindingInfo.Protocol $result.BindingInfo.IPAddress | Should Be $BindingObject.IPAddress $result.BindingInfo.HostName | Should Be $BindingObject.HostName $result.BindingInfo.CertificateThumbprint | Should Be $BindingInfo.Certificatehash $result.BindingInfo.CertificateStoreName | Should Be $BindingInfo.CertificateStoreName $result.BindingInfo.SSLFlags | Should Be $BindingInfo.SSLFlags } It 'should return the State' { $result.State | Should Be 'Started' } It 'should return the ID' { $result.ID | Should Be 0 } } } Describe "how Set-TargetResource responds to Ensure = 'Present'" { $MockSite = @{ Ensure = 'Present' Name = 'MockName' PhysicalPath = 'C:\NonExistant' ID = 1 State = 'Stopped' ApplicationPool = 'MockPool' DefaultPage = 'index.htm' } $BindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' } $MockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ Port = [System.UInt16] $BindingObject.Port Protocol = $BindingObject.Protocol IPAddress = $BindingObject.IPaddress HostName = $BindingObject.Hostname } -ClientOnly $MockSite2 = @{ Ensure = 'Present' Name = 'MockName2' PhysicalPath = 'C:\NonExistant2' ID = 1 State = 'Stopped' ApplicationPool = 'MockPool2' DefaultPage = 'index.htm' BindingInfo = $MockBinding } Context 'Everything needs to be updated and application is started' { Mock Get-Website { return @($MockSite, $MockSite2) } Mock Start-Website {return $null} Mock Test-WebsitePath { return $true } Mock Set-ItemProperty { return $null } Mock Test-WebsiteBindings { return $true } Mock Update-WebsiteBinding { return $null } Mock Update-DefaultPages { return $null } Mock Confirm-PortIPHostisUnique { return $true } Mock Get-TargetResource { return $MockSite2 } $result = Set-TargetResource -Ensure 'Present' -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage It 'should call all the mocks' { Assert-MockCalled Test-WebsitePath Assert-MockCalled Set-ItemProperty 2 Assert-MockCalled Update-WebsiteBinding Assert-MockCalled Update-DefaultPages Assert-MockCalled Confirm-PortIPHostisUnique Assert-MockCalled Get-TargetResource Assert-MockCalled Start-Website } } Context 'Confirm-PortIPHostisUnique returns false' { Mock Get-Website { return @($MockSite, $MockSite2) } Mock Start-Website {return $null} Mock Test-WebsitePath { return $true } Mock Set-ItemProperty { return $null } Mock Test-WebsiteBindings { return $true } Mock Update-WebsiteBinding { return $null } Mock Update-DefaultPages { return $null } Mock Confirm-PortIPHostisUnique { return $false } Mock Get-TargetResource { return $MockSite2 } It 'should throw the right error' { $errorId = 'WebsiteBindingConflictOnStart' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult $errorMessage = $($LocalizedData.WebsiteBindingConflictOnStartError) -f $MockSite.Name $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null { Set-TargetResource -Ensure 'Present' -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage } | should throw $errorRecord } } Context 'Start-Website throws an error' { Mock Get-Website { return @($MockSite, $MockSite2) } Mock Start-Website {return throw} Mock Test-WebsitePath { return $true } Mock Set-ItemProperty { return $null } Mock Test-WebsiteBindings { return $true } Mock Update-WebsiteBinding { return $null } Mock Update-DefaultPages { return $null } Mock Confirm-PortIPHostisUnique { return $true } Mock Get-TargetResource { return $MockSite2 } It 'Should throw the correct error' { $errorId = 'WebsiteStateFailure' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation $errorMessage = $($LocalizedData.WebsiteStateFailureError) -f $MockSite.Name $errorMessage += $_.Exception.Message $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null { Set-TargetResource -Ensure 'Present' -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage } | should throw $errorRecord } } Context 'Everything needs to be updated and application is stopped' { $MockSite = @{ Ensure = 'Present' Name = 'MockName' PhysicalPath = 'C:\NonExistant' ID = 1 State = 'Started' ApplicationPool = 'MockPool' DefaultPage = 'index.htm' } Mock Get-Website { return @($MockSite, $MockSite2) } Mock Stop-Website {return $null} Mock Test-WebsitePath { return $true } Mock Set-ItemProperty { return $null } Mock Test-WebsiteBindings { return $true } Mock Update-WebsiteBinding { return $null } Mock Update-DefaultPages { return $null } Mock Confirm-PortIPHostisUnique { return $true } $result = Set-TargetResource -Ensure 'Present' -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -State 'Stopped' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage It 'should call all the mocks' { Assert-MockCalled Test-WebsitePath Assert-MockCalled Set-ItemProperty 2 Assert-MockCalled Update-WebsiteBinding Assert-MockCalled Update-DefaultPages Assert-MockCalled Stop-Website } } Context 'Website does not exist' { $MockSite = @{ Ensure = 'Present' Name = 'MockName' PhysicalPath = 'C:\NonExistant' ID = 1 State = 'Started' ApplicationPool = 'MockPool' DefaultPage = 'index.htm' } Mock Get-Website { return $MockSite } Mock New-Website { return $null } Mock Stop-Website { return $null } Mock Test-WebsiteBindings { return $true } Mock Update-WebsiteBinding { return $null } Mock Update-DefaultPages { return $null } Mock Start-Website { return $true } Mock Get-ItemProperty { return $null } $result = Set-TargetResource -Ensure 'Present' -Name 'MockName2' -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage It 'should call all the mocks' { Assert-MockCalled New-Website Assert-MockCalled Stop-Website Assert-MockCalled Test-WebsiteBindings Assert-MockCalled Update-WebsiteBinding Assert-MockCalled Update-DefaultPages Assert-MockCalled Start-Website } } Context 'Error in non-existant site' { Mock New-Website {throw;} It 'Should throw the correct error' { $errorId = 'WebsiteCreationFailure' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation $errorMessage = $($LocalizedData.WebsiteCreationFailureError) -f 'MockName2' $errorMessage += $_.Exception.Message $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null {$result = Set-TargetResource -Ensure 'Present' -Name 'MockName2' -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage } | Should throw $errorRecord } } } Describe "how Set-TargetResource responds to Ensure = 'Absent'" { It 'should call Remove-Website' { $MockSite = @{ Ensure = 'Present' Name = 'MockName' PhysicalPath = 'C:\NonExistant' ID = 1 State = 'Stopped' ApplicationPool = 'MockPool' DefaultPage = 'index.htm' } $BindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' } $MockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ Port = [System.UInt16] $BindingObject.Port Protocol = $BindingObject.Protocol IPAddress = $BindingObject.IPaddress HostName = $BindingObject.Hostname } -ClientOnly Mock Get-Website {return $MockSite} Mock Remove-Website {return $null} $result = Set-TargetResource -Ensure 'Absent' -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage Assert-MockCalled Get-Website Assert-MockCalled Remove-Website } It 'should throw the right error' { $MockSite = @{ Ensure = 'Present' Name = 'MockName' PhysicalPath = 'C:\NonExistant' ID = 1 State = 'Stopped' ApplicationPool = 'MockPool' DefaultPage = 'index.htm' } $BindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' } $MockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ Port = [System.UInt16] $BindingObject.Port Protocol = $BindingObject.Protocol IPAddress = $BindingObject.IPaddress HostName = $BindingObject.Hostname } -ClientOnly Mock Get-Website {return $MockSite} Mock Remove-Website {throw } $errorId = 'WebsiteRemovalFailure' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation $errorMessage = $($LocalizedData.WebsiteRemovalFailureError) -f $MockSite.Name $errorMessage += $_.Exception.Message $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null { Set-TargetResource -Ensure 'Absent' -Name $MockSite.Name -PhysicalPath $MockSite.PhysicalPath -State 'Started' -ApplicationPool 'MockPool2' -BindingInfo $MockBinding -DefaultPage $MockSite.DefaultPage } | should throw $errorRecord } } Describe 'how Get-WebBindingObject responds' { Context 'IPv6 address is passed and the protocol is http' { $BindingInfo = [PSCustomObject] @{ bindingInformation = '[0:0:0:0:0:0:0:1]:80:MockHostName' protocol = 'http' } $result = Get-WebBindingObject -BindingInfo $BindingInfo It 'should return the IPv6 address' { $result.IPaddress | Should be '0:0:0:0:0:0:0:1' } It 'should return http' { $result.Protocol | Should Be 'http' } It 'should return the hostname' { $result.Hostname | Should Be 'MockHostName' } It 'should return the port' { $result.Port | Should Be '80' } } Context 'IPv4 address is passed and the protocol is http' { $BindingInfo = [PSCustomObject] @{ bindingInformation = '127.0.0.1:80:MockHostName' protocol = 'http' } $result = Get-WebBindingObject -BindingInfo $BindingInfo It 'should return the IPv6 address' { $result.IPaddress | Should be '127.0.0.1' } It 'should return http' { $result.Protocol | Should Be 'http' } It 'should return the hostname' { $result.Hostname | Should Be 'MockHostName' } It 'should return the port' { $result.Port | Should Be '80' } } Context 'IPv4 SSL Certificate is passed' { $BindingInfo = [PSCustomObject] @{ bindingInformation = '127.0.0.1:443:MockHostName' protocol = 'https' CertificateHash = '3E09CCC8DFDCB8E3D4A83CFF164CC4754C25E9E5' CertificateStoreName = 'My' SSLFlags = '1' } $result = Get-WebBindingObject -BindingInfo $BindingInfo It 'should return the IPv6 address' { $result.IPaddress | Should be '127.0.0.1' } It 'should return http' { $result.Protocol | Should Be 'https' } It 'should return the hostname' { $result.Hostname | Should Be 'MockHostName' } It 'should return the port' { $result.Port | Should Be '443' } It 'should return the Hash' { $result.CertificateThumbprint | Should Be '3E09CCC8DFDCB8E3D4A83CFF164CC4754C25E9E5' } It 'should return the store' { $result.CertificateStoreName | Should Be 'My' } It 'should return the SSLFlags' { $result.SSLFlags | Should Be '1' } } Context 'IPv6 SSL Certificate is passed' { $BindingInfo = [PSCustomObject] @{ bindingInformation = '[0:0:0:0:0:0:0:1]:443:MockHostName' protocol = 'https' CertificateHash = '3E09CCC8DFDCB8E3D4A83CFF164CC4754C25E9E5' CertificateStoreName = 'My' SSLFlags = '1' } $result = Get-WebBindingObject -BindingInfo $BindingInfo It 'should return the IPv6 address' { $result.IPaddress | Should be '0:0:0:0:0:0:0:1' } It 'should return http' { $result.Protocol | Should Be 'https' } It 'should return the hostname' { $result.Hostname | Should Be 'MockHostName' } It 'should return the port' { $result.Port | Should Be '443' } It 'should return the Hash' { $result.CertificateThumbprint | Should Be '3E09CCC8DFDCB8E3D4A83CFF164CC4754C25E9E5' } It 'should return the store' { $result.CertificateStoreName | Should Be 'My' } It 'should return the SSLFlags' { $result.SSLFlags | Should Be '1' } } } Describe 'Test-WebsitePath' { Context 'the path is wrong' { It 'Should return true' { Mock Get-ItemProperty { return 'C:\WrongPath' } Test-WebsitePath -Name 'SomeSite' -PhysicalPath 'C:\RightPath' | Should be $true } } Context 'the path is correct' { It 'Should return false if the path does not need to be updated' { Mock Get-ItemProperty { return 'C:\RightPath' } Test-WebsitePath -Name 'SomeSite' -PhysicalPath 'C:\RightPath' | Should be $false } } } Describe 'Confirm-PortIPHostisUnique' { Context 'bindings are not unique' { It 'should return false' { $BindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' } $bindingArray = @() $mockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ Port = [System.UInt16] $BindingObject.Port Protocol = $BindingObject.Protocol IPAddress = $BindingObject.IPaddress HostName = $BindingObject.Hostname } -ClientOnly $bindingArray += $MockBinding, $MockBinding Confirm-PortIPHostisUnique -Port $BindingObject.Port -IPAddress $BindingObject.IPAddress -HostName $BindingObject.Hostname -BindingInfo $bindingArray | should be $false } } Context 'bindings are unique' { It 'should return true' { $BindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' } $mockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ Port = [System.UInt16] $BindingObject.Port Protocol = $BindingObject.Protocol IPAddress = $BindingObject.IPaddress HostName = $BindingObject.Hostname } -ClientOnly $bindingArray = $MockBinding Confirm-PortIPHostisUnique -Port $BindingObject.Port -IPAddress $BindingObject.IPAddress -HostName $BindingObject.Hostname -BindingInfo $bindingArray | should be $true } } } Describe 'Test-WebsiteBindings' { $MockSite = @{ Ensure = 'Present' Name = 'MockHostName' PhysicalPath = 'C:\NonExistant' ID = 1 State = 'Started' ApplicationPool = 'MockPool' BindingInformation = '127.0.0.1:80:' } $BindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' SSLFlags = 0 } $mockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ Port = [System.UInt16] $BindingObject.Port Protocol = $BindingObject.Protocol IPAddress = $BindingObject.IPaddress HostName = $BindingObject.Hostname SSLFlags = $BindingObject.SSLFlags } -ClientOnly Context 'Confirm-PortIPHostisUnique returns false' { It 'should throw an error' { Mock Confirm-PortIPHostisUnique {return $false} $errorId = 'WebsiteBindingInputInvalidation' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult $errorMessage = $($LocalizedData.WebsiteBindingInputInvalidationError) -f $BindingObject.Hostname $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null {Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $mockBinding } | Should throw $errorRecord } } Context 'Comparing bindings throws an error' { $badBindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' } Mock Confirm-PortIPHostisUnique {return $true} Mock Get-WebBinding {return $BindingObject} Mock Get-Website {return $MockSite} Mock Get-WebBindingObject { return $MockBinding } $errorId = 'WebsiteCompareFailure' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult $errorMessage = $($LocalizedData.WebsiteCompareFailureError) -f $BindingObject.Hostname $errorMessage += $_.Exception.Message $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null It 'should return an error' { {Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $badBindingObject } | Should not throw $errorRecord # currently broken } } Context 'Port is incorrect' { $badBindingObject = @{ Port = 81 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' } Mock Confirm-PortIPHostisUnique {return $true} Mock Get-WebBinding {return $BindingObject} Mock Get-Website {return $MockSite} Mock Get-WebBindingObject { return $badBindingObject } It 'should return true' { Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true } } Context 'Protocol is incorrect' { $badBindingObject = @{ Port = 80 Protocol = 'https' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' } Mock Confirm-PortIPHostisUnique {return $true} Mock Get-WebBinding {return $BindingObject} Mock Get-Website {return $MockSite} Mock Get-WebBindingObject { return $badBindingObject } It 'should return true' { Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true } } Context 'IPAddress is incorrect' { $badBindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.2' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' } Mock Confirm-PortIPHostisUnique {return $true} Mock Get-WebBinding {return $BindingObject} Mock Get-Website {return $MockSite} Mock Get-WebBindingObject { return $badBindingObject } It 'should return true' { Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true } } Context 'IPAddress is *' { $BindingObjectIP = @{ Port = 80 Protocol = 'http' IPAddress = '' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' SSLFlags = 0 } $mockBindingIP = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ Port = [System.UInt16] $BindingObjectIP.Port Protocol = $BindingObjectIP.Protocol IPAddress = $BindingObjectIP.IPaddress HostName = $BindingObjectIP.Hostname } -ClientOnly $badBindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '*' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' } Mock Confirm-PortIPHostisUnique {return $true} Mock Get-WebBinding {return $BindingObjectIP } Mock Get-Website {return $MockSite} Mock Get-WebBindingObject { return $badBindingObject } It 'should return false' { Test-WebsiteBindings -Name $BindingObjectIP.hostname -BindingInfo $mockBindingIP | Should be $false } } Context 'Hostname is incorrect' { $badBindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName2' CertificateThumbprint = '' CertificateStoreName = '' } Mock Confirm-PortIPHostisUnique {return $true} Mock Get-WebBinding {return $BindingObject} Mock Get-Website {return $MockSite} Mock Get-WebBindingObject { return $badBindingObject } It 'should return true' { Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true } } Context 'CertificateThumbprint is incorrect' { $badBindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '1234560215616' CertificateStoreName = '' } Mock Confirm-PortIPHostisUnique {return $true} Mock Get-WebBinding {return $BindingObject} Mock Get-Website {return $MockSite} Mock Get-WebBindingObject { return $badBindingObject } It 'should return true' { Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true } } Context 'CertificateStoreName is incorrect' { $badBindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '1234560215616' CertificateStoreName = 'WebHosting' } Mock Confirm-PortIPHostisUnique {return $true} Mock Get-WebBinding {return $BindingObject} Mock Get-Website {return $MockSite} Mock Get-WebBindingObject { return $badBindingObject } It 'should return true' { Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true } } Context 'CertificateStoreName is incorrect and no thumbrpint is specified' { $badBindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = 'WebHosting' SSLFlags = 0 } Mock Confirm-PortIPHostisUnique {return $true} Mock Get-WebBinding {return $BindingObject} Mock Get-Website {return $MockSite} Mock Get-WebBindingObject { return $badBindingObject } It 'should return false' { Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $false } } Context 'SSLFlags is incorrect' { $badBindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' SSLFlags = 1 } Mock Confirm-PortIPHostisUnique {return $true} Mock Get-WebBinding {return $BindingObject} Mock Get-Website {return $MockSite} Mock Get-WebBindingObject { return $badBindingObject } It 'should return true' { Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $true } } Context 'Everything is the same' { $badBindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '' CertificateStoreName = '' SSLFlags = 0 } Mock Confirm-PortIPHostisUnique {return $true} Mock Get-WebBinding {return $BindingObject} Mock Get-Website {return $MockSite} Mock Get-WebBindingObject { return $badBindingObject } It 'should return false' { Test-WebsiteBindings -Name $BindingObject.hostname -BindingInfo $MockBinding | Should be $false } } } Describe 'Update-WebsiteBinding' { $MockSite = @{ Ensure = 'Present' Name = 'MockHostName' PhysicalPath = 'C:\NonExistant' ID = 1 State = 'Started' ApplicationPool = 'MockPool' BindingInformation = '127.0.0.1:443:' } $BindingObject = @{ Port = 443 Protocol = 'https' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '1234561651481561891481654891651' CertificateStoreName = 'MY' SSLFlags = 1 } $mockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ Port = [System.UInt16] $BindingObject.Port Protocol = $BindingObject.Protocol IPAddress = $BindingObject.IPaddress HostName = $BindingObject.Hostname SSLFlags = $BindingObject.SSLFlags } -ClientOnly Context 'expected behavior' { Mock Clear-ItemProperty { return $null } Mock New-WebBinding { return @{ Name = $Name; Protocol = $Protocol; Port = $Port; IPaddress = $IPaddress; Hostheader = $Hostheader; SslFlags = $SslFlags; } } -Verifiable $result = Update-WebsiteBinding -Name $MockSite.Name -BindingInfo $mockBinding It 'should call all the mocks' { Assert-MockCalled New-WebBinding } It 'should use the right name' { $result.Name | Should be $MockSite.Name } It 'should use the right protocol' { $result.Protocol | Should be $mockBinding.Protocol } It 'should use the right IPaddress' { $result.IPaddress | Should be $mockBinding.IPaddress } It 'should use the right Hostheader' { $result.Hostheader | Should be $mockBinding.HostName } It 'should use the right SSLFlags' { $result.SslFlags | Should be $mockBinding.SslFlags } } Context 'New-WebBinding throws an error' { It 'should throw the right error' { $errorId = 'WebsiteBindingUpdateFailure' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult $errorMessage = $($LocalizedData.WebsiteBindingUpdateFailureError) -f $MockSite.Name $errorMessage += $_.Exception.Message $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null Mock Clear-ItemProperty { return $null } Mock New-WebBinding { throw} { Update-WebsiteBinding -Name $MockSite.Name -BindingInfo $mockBinding } | should throw $errorRecord } } Context 'Get-WebBinding throws an error' { $MockSite = @{ Ensure = 'Present' Name = 'MockHostName' PhysicalPath = 'C:\NonExistant' ID = 1 State = 'Started' ApplicationPool = 'MockPool' BindingInformation = '127.0.0.1:80:' } $BindingObject = @{ Port = 80 Protocol = 'http' IPAddress = '127.0.0.1' HostName = 'MockHostName' CertificateThumbprint = '1234561651481561891481654891651' CertificateStoreName = 'MY' } $mockBinding = New-CimInstance -ClassName MSFT_xWebBindingInformation -Namespace root/microsoft/Windows/DesiredStateConfiguration -Property @{ Port = [System.UInt16] $BindingObject.Port Protocol = $BindingObject.Protocol IPAddress = $BindingObject.IPaddress HostName = $BindingObject.Hostname CertificateThumbprint = $BindingObject.CertificateThumbprint CertificateStoreName = $BindingObject.CertificateStoreName } -ClientOnly It 'should throw the right error' { $obj = New-Module -AsCustomObject -ScriptBlock { function AddSslCertificate { throw; } } Mock Clear-ItemProperty { return $null } Mock New-WebBinding { return $null } Mock Get-WebBinding { return throw; } $errorId = 'WebBindingCertifcateError' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidOperation $errorMessage = $($LocalizedData.WebBindingCertifcateError) -f $BindingObject.CertificateThumbprint $errorMessage += $_.Exception.Message $exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList $exception, $errorId, $errorCategory, $null { Update-WebsiteBinding -Name $MockSite.Name -BindingInfo $mockBinding } | should throw $errorRecord } } } Describe 'Update-DefaultPages' { Context 'Does not find the default page' { It 'should call Add-WebConfiguration' { Mock Get-WebConfiguration { return 'index.htm' } Mock Add-WebConfiguration { return $null } $result = Update-DefaultPages -Name 'Default Web Site' -DefaultPage 'index2.htm' Assert-MockCalled -commandName Add-WebConfiguration } } } } # Cleanup after the test Remove-Item -Path $moduleRoot -Recurse -Force |