Tests/Get-ADLocalDC.Tests.ps1

[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "")]
param()

BeforeAll {
    # Import the script file
    $sPath = ($PSScriptRoot).Replace("Tests","Public") + "\Get-ADLocalDC.ps1"

    . $sPath

    # Declare custom functions used within the Get-ADLocalDC script
    Function Get-ADComputerSite() {}
    Function Get-ADDomainControllersBySite() {}
}

Describe "Get-ADLocalDC" {
    Context "Test-NormalOperation-AcceptFirstDC" {
        BeforeAll {
            Function Get-ADDomainControllerRootEntry() {}
            Function Test-QuickTcpConnection() {}

            Mock Get-ADComputerSite { return "ADSite1"}
            Mock Get-ADDomainControllersBySite { return @(@{Name="DC1.mydomain.com"},@{Name="DC2.mydomain.com"}) }
            Mock Get-ADDomainControllerRootEntry { return [PSCustomObject]@{ defaultNamingContext = "mydomain.com" } }
            Mock Test-QuickTcpConnection { return $true}

            $sRtnDcName = Get-ADLocalDC
        }

        It "Should return DC1.mydomain.com" {
            $sRtnDcName | Should -Be "DC1.mydomain.com"
        }
    }

    Context "Test-NormalOperation-SkipFirstDC" {
        BeforeAll {
            Function Get-ADDomainControllerRootEntry() {
                [CmdletBinding()]
                param (
                    [string]$sDCName
                )

                # Required to stop lint tests failing
                $sDCName = $null
            }

            Function Test-QuickTcpConnection() {}

            Mock Get-ADComputerSite { return "ADSite1"}
            Mock Get-ADDomainControllersBySite { return @(@{Name="DC1.mydomain.com"},@{Name="DC2.mydomain.com"}) }
            Mock Test-QuickTcpConnection { return $true}
            Mock Get-ADDomainControllerRootEntry { return $null} -ParameterFilter { $sDCName -eq "DC1.mydomain.com" }
            Mock Get-ADDomainControllerRootEntry { return [PSCustomObject]@{ defaultNamingContext = "mydomain.com" } } -ParameterFilter { $sDCName -eq "DC2.mydomain.com" }

            $sRtnDcName = Get-ADLocalDC
        }

        It "Should return DC2.mydomain.com" {
            $sRtnDcName | Should -Be "DC2.mydomain.com"
        }
    }

    Context "No DCs return correct RootDSE Information" {
        BeforeAll {
            Function Get-ADDomainControllerRootEntry() {}

            Mock Get-ADComputerSite { return "ADSite1"}
            Mock Get-ADDomainControllersBySite { return @(@{Name="DC1.mydomain.com"},@{Name="DC2.mydomain.com"}) }
            Mock Get-ADDomainControllerRootEntry { return $null }
        }

        It "Should return error reporting no DCs available in site" {
            try {
                $sRtnDcName = Get-ADLocalDC
            }
            catch {
                $Error[0].Exception.Message | Should -Be "Failed to discover an available Domain Controller in the local site"
            }
        }
    }

    Context "No computer site returned" {
        BeforeAll {
            Function Get-ADDomainControllerRootEntry() {}

            Mock Get-ADComputerSite { throw "Failed to discover computer site"}
        }

        It "Should return error about the site" {
            try {
                $sRtnDcName = Get-ADLocalDC
            }
            catch {
                $Error[0].Exception.Message | Should -BeLike "Failed to discover computer site*"
            }
        }
    }

    Context "Test-ADWebServicesTcpCheck" {
        BeforeAll {
            Function Get-ADDomainControllerRootEntry() {}

            Function Test-QuickTcpConnection() {
                [CmdletBinding()]
                [OutputType([System.Boolean])]
                param (
                    [string]$sComputerName,
                    [int]$iPort
                )

                # Required to stop lint warnings
                $sComputerName = $null
                $iPort = $null
            }

            Mock Get-ADComputerSite { return "ADSite1"}
            Mock Get-ADDomainControllersBySite { return @(@{Name="DC1.mydomain.com"},@{Name="DC2.mydomain.com"}) }
            Mock Get-ADDomainControllerRootEntry { return [PSCustomObject]@{ defaultNamingContext = "mydomain.com" } }
            Mock Test-QuickTcpConnection { return $false } -ParameterFilter { $sComputerName -eq "DC1.mydomain.com"}
            Mock Test-QuickTcpConnection { return $true }

            $sRtnDcName = Get-ADLocalDC
        }

        It "Should return DC2.mydomain.com" {
            $sRtnDcName | Should -Be "DC2.mydomain.com"
        }
    }

    Context "Use PS AD Module to test DC" {
        BeforeAll {
            Function Get-ADDomainControllerRootEntry() {}
            Function Test-QuickTcpConnection() {}
            Function Get-ADDomain() {}

            Mock Get-ADComputerSite { return "ADSite1"}
            Mock Get-ADDomainControllersBySite { return @(@{Name="DC1.mydomain.com"},@{Name="DC2.mydomain.com"}) }
            Mock Get-ADDomain { return $true }

            $sRtnDcName = Get-ADLocalDC -UsePsAdCommand
        }

        It "Should return DC1.mydomain.com" {
            $sRtnDcName | Should -Be "DC1.mydomain.com"
        }
    }

    Context "Use PS AD Module to test DC and fail each DC test" {
        BeforeAll {
            Function Get-ADDomainControllerRootEntry() {}
            Function Test-QuickTcpConnection() {}
            Function Get-ADDomain() {}

            Mock Get-ADComputerSite { return "ADSite1"}
            Mock Get-ADDomainControllersBySite { return @(@{Name="DC1.mydomain.com"},@{Name="DC2.mydomain.com"}) }
            Mock Get-ADDomain { return $false }
        }

        It "Should return error reporting no DCs available" {
            try {
                $sRtnDcName = Get-ADLocalDC
            }
            catch {
                $Error[0].Exception.Message | Should -Be "Failed to discover an available Domain Controller in the local site"
            }
        }
    }
}