Selenium.psm1
$Script:SeKeys = [OpenQA.Selenium.Keys] | Get-Member -MemberType Property -Static | Select-Object -Property Name, @{N = "ObjectString"; E = { "[OpenQA.Selenium.Keys]::$($_.Name)" } } #region Set path to assemblies on Linux and MacOS and Grant Execution permissions on them if ($IsLinux) { $AssembliesPath = "$PSScriptRoot/assemblies/linux" } elseif ($IsMacOS) { $AssembliesPath = "$PSScriptRoot/assemblies/macos" } # Grant Execution permission to assemblies on Linux and MacOS if ($AssembliesPath) { # Check if powershell is NOT running as root Get-Item -Path "$AssembliesPath/chromedriver", "$AssembliesPath/geckodriver" | ForEach-Object { if ($IsLinux) { $FileMod = stat -c "%a" $_.FullName } elseif ($IsMacOS) { $FileMod = /usr/bin/stat -f "%A" $_.FullName } Write-Verbose "$($_.FullName) $Filemod" if ($FileMod[2] -ne '5' -and $FileMod[2] -ne '7') { Write-Host "Granting $($AssemblieFile.fullname) Execution Permissions ..." chmod +x $_.fullname } } } #endregion function ValidateURL { [Alias("Validate-Url")] param( [Parameter(Mandatory = $true)] $URL ) $Out = $null [uri]::TryCreate($URL, [System.UriKind]::Absolute, [ref]$Out) } function Start-SeNewEdge { [cmdletbinding(DefaultParameterSetName = 'default')] [Alias('CrEdge', 'NewEdge')] param( [ValidateURIAttribute()] [Parameter(Position = 0)] [string]$StartURL, [switch]$HideVersionHint, [parameter(ParameterSetName = 'min', Mandatory = $true)] [switch]$Minimized, [parameter(ParameterSetName = 'max', Mandatory = $true)] [switch]$Maximized, [parameter(ParameterSetName = 'ful', Mandatory = $true)] [switch]$FullScreen, [parameter(ParameterSetName = 'hl', Mandatory = $true)] [switch]$Headless, $BinaryPath = "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe", $ProfileDirectoryPath, $DefaultDownloadPath, [switch]$AsDefaultDriver, [switch]$Quiet, [Alias('Incognito')] [switch]$PrivateBrowsing, [int]$ImplicitWait = 10, $WebDriverDirectory = $env:EdgeWebDriver ) $OptionSettings = @{ browserName = '' } #region check / set paths for browser and web driver and edge options if ($PSBoundParameters['BinaryPath'] -and -not (Test-Path -Path $BinaryPath)) { throw "Could not find $BinaryPath"; return } #Were we given a driver location and is msedgedriver there ? #If were were given a location (which might be from an environment variable) is the driver THERE ? # if not, were we given a path for the browser executable, and is the driver THERE ? # and if not there either, is there one in the assemblies sub dir ? And if not bail if ($WebDriverDirectory -and -not (Test-Path -Path (Join-Path -Path $WebDriverDirectory -ChildPath 'msedgedriver.exe'))) { throw "Could not find msedgedriver.exe in $WebDriverDirectory"; return } elseif ($WebDriverDirectory -and (Test-Path (Join-Path -Path $WebDriverDirectory -ChildPath 'msedge.exe'))) { Write-Verbose -Message "Using browser from $WebDriverDirectory" $optionsettings['BinaryLocation'] = Join-Path -Path $WebDriverDirectory -ChildPath 'msedge.exe' } elseif ($BinaryPath) { $optionsettings['BinaryLocation'] = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($BinaryPath) $binaryDir = Split-Path -Path $BinaryPath -Parent Write-Verbose -Message "Will request $($OptionSettings['BinaryLocation']) as the browser" } if (-not $WebDriverDirectory -and $binaryDir -and (Test-Path (Join-Path -Path $binaryDir -ChildPath 'msedgedriver.exe'))) { $WebDriverDirectory = $binaryDir } # No linux or mac driver to test for yet if (-not $WebDriverDirectory -and (Test-Path (Join-Path -Path "$PSScriptRoot\Assemblies\" -ChildPath 'msedgedriver.exe'))) { $WebDriverDirectory = "$PSScriptRoot\Assemblies\" Write-Verbose -Message "Using Web driver from the default location" } if (-not $WebDriverDirectory) { throw "Could not find msedgedriver.exe"; return } # The "credge" web driver will work with the edge selenium objects, but works better with the chrome ones. $service = [OpenQA.Selenium.Chrome.ChromeDriverService]::CreateDefaultService($WebDriverDirectory, 'msedgedriver.exe') $options = New-Object -TypeName OpenQA.Selenium.Chrome.ChromeOptions -Property $OptionSettings #The command line args may now be --inprivate --headless but msedge driver V81 does not pass them if ($PrivateBrowsing) { $options.AddArguments('InPrivate') } if ($Headless) { $options.AddArguments('headless') } if ($Quiet) { $service.HideCommandPromptWindow = $true } if ($ProfileDirectoryPath) { $ProfileDirectoryPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($ProfileDirectoryPath) Write-Verbose "Setting Profile directory: $ProfileDirectoryPath" $options.AddArgument("user-data-dir=$ProfileDirectoryPath") } if ($DefaultDownloadPath) { $DefaultDownloadPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($DefaultDownloadPath) Write-Verbose "Setting Default Download directory: $DefaultDownloadPath" $Options.AddUserProfilePreference('download', @{'default_directory' = $DefaultDownloadPath; 'prompt_for_download' = $false; }) } #endregion $Driver = [OpenQA.Selenium.Chrome.ChromeDriver]::new($service, $options) #region post driver checks and option checks If we have a version know to have problems with passing arguments, generate a warning if we tried to send any. if (-not $Driver) { Write-Warning "Web driver was not created"; return } else { $driverversion = $Driver.Capabilities.ToDictionary().msedge.msedgedriverVersion -replace '^([\d.]+).*$', '$1' if (-not $driverversion) { $driverversion = $driver.Capabilities.ToDictionary().chrome.chromedriverVersion -replace '^([\d.]+).*$', '$1' } Write-Verbose "Web Driver version $driverversion" Write-Verbose ("Browser: {0,9} {1}" -f $Driver.Capabilities.ToDictionary().browserName, $Driver.Capabilities.ToDictionary().browserVersion) if (!$HideVersionHint) { Write-Verbose "You can download the right webdriver from 'https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/'" } $browserCmdline = (Get-CimInstance -Verbose:$false -Query ( "Select * From win32_process " + "Where parentprocessid = $($service.ProcessId) " + "And name = 'msedge.exe'")).commandline $options.arguments | Where-Object { $browserCmdline -notlike "*$_*" } | ForEach-Object { Write-Warning "Argument $_ was not passed to the Browser. This is a known issue with some web driver versions." } } $Driver.Manage().Timeouts().ImplicitWait = [TimeSpan]::FromSeconds($ImplicitWait) if ($StartURL) { $Driver.Navigate().GoToUrl($StartURL) } if ($Minimized) { $Driver.Manage().Window.Minimize(); } if ($Maximized) { $Driver.Manage().Window.Maximize() } if ($FullScreen) { $Driver.Manage().Window.FullScreen() } #endregion if ($AsDefaultDriver) { if ($Global:SeDriver) { $Global:SeDriver.Dispose() } $Global:SeDriver = $Driver } else { $Driver } } function Start-SeChrome { [cmdletbinding(DefaultParameterSetName = 'default')] [Alias('SeChrome')] param( [ValidateURIAttribute()] [Parameter(Position = 0)] [string]$StartURL, [Parameter(Mandatory = $false)] [array]$Arguments, [switch]$HideVersionHint, [System.IO.FileInfo]$DefaultDownloadPath, [System.IO.FileInfo]$ProfileDirectoryPath, [Parameter(DontShow)] [bool]$DisableBuiltInPDFViewer = $true, [switch]$EnablePDFViewer, [Alias('PrivateBrowsing')] [switch]$Incognito, [parameter(ParameterSetName = 'hl', Mandatory = $true)] [switch]$Headless, [parameter(ParameterSetName = 'Min', Mandatory = $true)] [switch]$Maximized, [parameter(ParameterSetName = 'Max', Mandatory = $true)] [switch]$Minimized, [parameter(ParameterSetName = 'Ful', Mandatory = $true)] [switch]$Fullscreen, [switch]$DisableAutomationExtension, [Alias('ChromeBinaryPath')] $BinaryPath, $WebDriverDirectory = $env:ChromeWebDriver, [switch]$Quiet, [switch]$AsDefaultDriver, [int]$ImplicitWait = 10 ) process { #region chrome set-up options $Chrome_Options = [OpenQA.Selenium.Chrome.ChromeOptions]::new() if ($DefaultDownloadPath) { Write-Verbose "Setting Default Download directory: $DefaultDownloadPath" $Chrome_Options.AddUserProfilePreference('download', @{'default_directory' = $($DefaultDownloadPath.FullName); 'prompt_for_download' = $false; }) } if ($ProfileDirectoryPath) { Write-Verbose "Setting Profile directory: $ProfileDirectoryPath" $Chrome_Options.AddArgument("user-data-dir=$ProfileDirectoryPath") } if ($BinaryPath) { Write-Verbose "Setting Chrome Binary directory: $BinaryPath" $Chrome_Options.BinaryLocation = "$BinaryPath" } if ($DisableBuiltInPDFViewer -and -not $EnablePDFViewer) { $Chrome_Options.AddUserProfilePreference('plugins', @{'always_open_pdf_externally' = $true; }) } if ($Headless) { $Chrome_Options.AddArguments('headless') } if ($Incognito) { $Chrome_Options.AddArguments('Incognito') } if ($Maximized) { $Chrome_Options.AddArguments('start-maximized') } if ($Fullscreen) { $Chrome_Options.AddArguments('start-fullscreen') } if ($DisableAutomationExtension) { $Chrome_Options.AddAdditionalCapability('useAutomationExtension', $false) $Chrome_Options.AddExcludedArgument('enable-automation') } if ($Arguments) { foreach ($Argument in $Arguments) { $Chrome_Options.AddArguments($Argument) } } if (!$HideVersionHint) { Write-Verbose "Download the right chromedriver from 'http://chromedriver.chromium.org/downloads'" } if ($WebDriverDirectory) { $service = [OpenQA.Selenium.Chrome.ChromeDriverService]::CreateDefaultService($WebDriverDirectory) } elseif ($AssembliesPath) { $service = [OpenQA.Selenium.Chrome.ChromeDriverService]::CreateDefaultService($AssembliesPath) } else { $service = [OpenQA.Selenium.Chrome.ChromeDriverService]::CreateDefaultService() } if ($Quiet) { $service.HideCommandPromptWindow = $true } #endregion $Driver = [OpenQA.Selenium.Chrome.ChromeDriver]::new($service, $Chrome_Options) if (-not $Driver) { Write-Warning "Web driver was not created"; return } #region post creation options $Driver.Manage().Timeouts().ImplicitWait = [TimeSpan]::FromSeconds($ImplicitWait) if ($Minimized) { $Driver.Manage().Window.Minimize(); } if ($Headless -and $DefaultDownloadPath) { $HeadlessDownloadParams = [system.collections.generic.dictionary[[System.String], [System.Object]]]::new() $HeadlessDownloadParams.Add('behavior', 'allow') $HeadlessDownloadParams.Add('downloadPath', $DefaultDownloadPath.FullName) $Driver.ExecuteChromeCommand('Page.setDownloadBehavior', $HeadlessDownloadParams) } if ($StartURL) { $Driver.Navigate().GoToUrl($StartURL) } #endregion if ($AsDefaultDriver) { if ($Global:SeDriver) { $Global:SeDriver.Dispose() } $Global:SeDriver = $Driver } else { $Driver } } } function Start-SeInternetExplorer { [cmdletbinding(DefaultParameterSetName = 'Default')] [Alias('SeInternetExplorer', 'SeIE')] param( [ValidateURIAttribute()] [Parameter(Position = 0)] [string]$StartURL, [switch]$Quiet, [switch]$AsDefaultDriver, [parameter(ParameterSetName = 'Max', Mandatory = $true)] [switch]$Maximized, [parameter(ParameterSetName = 'Min', Mandatory = $true)] [switch]$Minimized, [parameter(ParameterSetName = 'Min', Mandatory = $true)] [switch]$FullScreen, [Parameter(DontShow)] [parameter(ParameterSetName = 'HL', Mandatory = $true)] [switch]$Headless, [Parameter(DontShow)] [Alias('Incognito')] [switch]$PrivateBrowsing, [switch]$IgnoreProtectedModeSettings, [int]$ImplicitWait = 10, $WebDriverDirectory = $env:IEWebDriver ) #region IE set-up options if ($Headless -or $PrivateBrowsing) { Write-Warning 'The Internet explorer driver does not support headless or Inprivate operation; these switches are ignored' } $InternetExplorer_Options = [OpenQA.Selenium.IE.InternetExplorerOptions]::new() $InternetExplorer_Options.IgnoreZoomLevel = $true if ($IgnoreProtectedModeSettings) { $InternetExplorer_Options.IntroduceInstabilityByIgnoringProtectedModeSettings = $true } if ($StartURL) { $InternetExplorer_Options.InitialBrowserUrl = $StartURL } if ($WebDriverDirectory) { $Service = [OpenQA.Selenium.IE.InternetExplorerDriverService]::CreateDefaultService($WebDriverDirectory) } else { $Service = [OpenQA.Selenium.IE.InternetExplorerDriverService]::CreateDefaultService() } if ($Quiet) { $Service.HideCommandPromptWindow = $true } #endregion $Driver = [OpenQA.Selenium.IE.InternetExplorerDriver]::new($service, $InternetExplorer_Options) if (-not $Driver) { Write-Warning "Web driver was not created"; return } #region post creation options $Driver.Manage().Timeouts().ImplicitWait = [TimeSpan]::FromSeconds($ImplicitWait) if ($Minimized) { $Driver.Manage().Window.Minimize(); } if ($Maximized) { $Driver.Manage().Window.Maximize() } if ($FullScreen) { $Driver.Manage().Window.FullScreen() } #endregion if ($AsDefaultDriver) { if ($Global:SeDriver) { $Global:SeDriver.Dispose() } $Global:SeDriver = $Driver } else { $Driver } } function Start-SeEdge { [cmdletbinding(DefaultParameterSetName = 'default')] [Alias('MSEdge', 'LegacyEdge', 'Start-SeLegacyEdge')] param( [ValidateURIAttribute()] [Parameter(Position = 0)] [string]$StartURL, [parameter(ParameterSetName = 'Min', Mandatory = $true)] [switch]$Maximized, [parameter(ParameterSetName = 'Max', Mandatory = $true)] [switch]$Minimized, [parameter(ParameterSetName = 'Full', Mandatory = $true)] [switch]$FullScreen, [Alias('Incognito')] [switch]$PrivateBrowsing, [switch]$Quiet, [switch]$AsDefaultDriver, [Parameter(DontShow)] [switch]$Headless, [int]$ImplicitWait = 10 ) #region Edge set-up options if ($Headless) { Write-Warning 'Pre-Chromium Edge does not support headless operation; the Headless switch is ignored' } $service = [OpenQA.Selenium.Edge.EdgeDriverService]::CreateDefaultService() $options = [OpenQA.Selenium.Edge.EdgeOptions]::new() if ($Quiet) { $service.HideCommandPromptWindow = $true } if ($PrivateBrowsing) { $options.UseInPrivateBrowsing = $true } if ($StartURL) { $options.StartPage = $StartURL } #endregion try { $Driver = [OpenQA.Selenium.Edge.EdgeDriver]::new($service , $options) } catch { $driverversion = (Get-Item .\assemblies\MicrosoftWebDriver.exe).VersionInfo.ProductVersion $WindowsVersion = [System.Environment]::OSVersion.Version.ToString() Write-Warning -Message "Edge driver is $driverversion. Windows is $WindowsVersion. If the driver is out-of-date, update it as a Windows feature,`r`nand then delete $PSScriptRoot\assemblies\MicrosoftWebDriver.exe" throw $_ ; return } if (-not $Driver) { Write-Warning "Web driver was not created"; return } #region post creation options $Driver.Manage().Timeouts().ImplicitWait = [TimeSpan]::FromSeconds($ImplicitWait) if ($Minimized) { $Driver.Manage().Window.Minimize() } if ($Maximized) { $Driver.Manage().Window.Maximize() } if ($FullScreen) { $Driver.Manage().Window.FullScreen() } #endregion if ($AsDefaultDriver) { if ($Global:SeDriver) { $Global:SeDriver.Dispose() } $Global:SeDriver = $Driver } else { $Driver } } function Start-SeFirefox { [cmdletbinding(DefaultParameterSetName = 'default')] [Alias('SeFirefox')] param( [ValidateURIAttribute()] [Parameter(Position = 0)] [string]$StartURL, [array]$Arguments, [System.IO.FileInfo]$DefaultDownloadPath, [alias('Incognito')] [switch]$PrivateBrowsing, [parameter(ParameterSetName = 'HL', Mandatory = $true)] [switch]$Headless, [parameter(ParameterSetName = 'Min', Mandatory = $true)] [switch]$Maximized, [parameter(ParameterSetName = 'Max', Mandatory = $true)] [switch]$Minimized, [parameter(ParameterSetName = 'Ful', Mandatory = $true)] [switch]$Fullscreen, [switch]$SuppressLogging, [switch]$Quiet, [switch]$AsDefaultDriver, [int]$ImplicitWait = 10, $WebDriverDirectory = $env:GeckoWebDriver ) process { #region firefox set-up options $Firefox_Options = [OpenQA.Selenium.Firefox.FirefoxOptions]::new() if ($Headless) { $Firefox_Options.AddArguments('-headless') } if ($DefaultDownloadPath) { Write-Verbose "Setting Default Download directory: $DefaultDownloadPath" $Firefox_Options.setPreference("browser.download.folderList", 2); $Firefox_Options.SetPreference("browser.download.dir", "$DefaultDownloadPath"); } if ($PrivateBrowsing) { $Firefox_Options.SetPreference("browser.privatebrowsing.autostart", $true) } if ($Arguments) { foreach ($Argument in $Arguments) { $Firefox_Options.AddArguments($Argument) } } if ($SuppressLogging) { # Sets GeckoDriver log level to Fatal. $Firefox_Options.LogLevel = 6 } if ($WebDriverDirectory) { $service = [OpenQA.Selenium.Firefox.FirefoxDriverService]::CreateDefaultService($WebDriverDirectory) } elseif ($AssembliesPath) { $service = [OpenQA.Selenium.Firefox.FirefoxDriverService]::CreateDefaultService($AssembliesPath) } else { $service = [OpenQA.Selenium.Firefox.FirefoxDriverService]::CreateDefaultService() } if ($Quiet) { $service.HideCommandPromptWindow = $true } #endregion $Driver = [OpenQA.Selenium.Firefox.FirefoxDriver]::new($service, $Firefox_Options) if (-not $Driver) { Write-Warning "Web driver was not created"; return } #region post creation options $Driver.Manage().Timeouts().ImplicitWait = [TimeSpan]::FromSeconds($ImplicitWait) if ($Minimized) { $Driver.Manage().Window.Minimize() } if ($Maximized) { $Driver.Manage().Window.Maximize() } if ($Fullscreen) { $Driver.Manage().Window.FullScreen() } if ($StartURL) { $Driver.Navigate().GoToUrl($StartURL) } #endregion if ($AsDefaultDriver) { if ($Global:SeDriver) { $Global:SeDriver.Dispose() } $Global:SeDriver = $Driver } else { $Driver } } } function Start-SeRemote { <# .example #you can a remote testing account with testing bot at https://testingbot.com/users/sign_up #Set $key and $secret and then ... #see also https://crossbrowsertesting.com/freetrial / https://help.crossbrowsertesting.com/selenium-testing/getting-started/c-sharp/ #and https://www.browserstack.com/automate/c-sharp $RemoteDriverURL = [uri]"http://$key`:$secret@hub.testingbot.com/wd/hub" #See https://testingbot.com/support/getting-started/csharp.html for values for different browsers/platforms $caps = @{ platform = 'HIGH-SIERRA' version = '11' browserName = 'safari' } Start-SeRemote -RemoteAddress $remoteDriverUrl -DesiredCapabilties $caps #> [cmdletbinding(DefaultParameterSetName = 'default')] param( [string]$RemoteAddress, [hashtable]$DesiredCapabilities, [ValidateURIAttribute()] [Parameter(Position = 0)] [string]$StartURL, [switch]$AsDefaultDriver, [int]$ImplicitWait = 10 ) $desired = [OpenQA.Selenium.Remote.DesiredCapabilities]::new() if (-not $DesiredCapabilities.Name) { $desired.SetCapability('name', [datetime]::now.tostring("yyyyMMdd-hhmmss")) } foreach ($k in $DesiredCapabilities.keys) { $desired.SetCapability($k, $DesiredCapabilities[$k]) } $Driver = [OpenQA.Selenium.Remote.RemoteWebDriver]::new($RemoteAddress, $desired) if (-not $Driver) { Write-Warning "Web driver was not created"; return } $Driver.Manage().Timeouts().ImplicitWait = [TimeSpan]::FromSeconds($ImplicitWait) if ($StartURL) { $Driver.Navigate().GotoUrl($StartURL) } if ($AsDefaultDriver) { if ($Global:SeDriver) { $Global:SeDriver.Dispose() } $Global:SeDriver = $Driver } else { $Driver } } <# @jhoneill Shouldn't -default be assumed if not feed a webdriver? see alternate below function Stop-SeDriver { [alias('SeClose')] param( [Parameter(ValueFromPipeline = $true, position = 0, ParameterSetName = 'Driver')] [ValidateIsWebDriverAttribute()] $Driver, [Parameter(Mandatory = $true, ParameterSetName = 'Default')] [switch]$Default ) if (-not $PSBoundParameters.ContainsKey('Driver') -and $Global:SeDriver -and ($Default -or $MyInvocation.InvocationName -eq 'SeClose')) { Write-Verbose -Message "Closing $($Global:SeDriver.Capabilities.browsername)..." $Global:SeDriver.Close() $Global:SeDriver.Dispose() Remove-Variable -Name SeDriver -Scope global } elseif ($Driver) { $Driver.Close() $Driver.Dispose() } else { Write-Warning -Message 'No Driver Specified' } } #> function Stop-SeDriver { [alias('SeClose')] param( [Parameter(Mandatory = $false, ValueFromPipeline = $true)] [Alias('Driver')] [ValidateNotNullOrEmpty()] [OpenQA.Selenium.IWebDriver] $Target = $Global:SeDriver ) if (($null -ne $Target) -and ($Target -is [OpenQA.Selenium.IWebDriver])) { Write-Verbose -Message "Closing $($Target.Capabilities.browsername)..." $Target.Close() $Target.Dispose() if ($Target -eq $Global:SeDriver) { Remove-Variable -Name SeDriver -Scope global } } else { throw "A valid <IWebDriver> Target must be provided." } } <# function Enter-SeUrl { param($Driver, $Url) $Driver.Navigate().GoToUrl($Url) } #> function Open-SeUrl { [cmdletbinding(DefaultParameterSetName = 'default')] [Alias('SeNavigate', "Enter-SeUrl")] param( [Parameter(Mandatory = $true, position = 0, ParameterSetName = 'url')] [ValidateURIAttribute()] [string]$Url, [Parameter(Mandatory = $true, ParameterSetName = 'back')] [switch]$Back, [Parameter(Mandatory = $true, ParameterSetName = 'forward')] [switch]$Forward, [Parameter(Mandatory = $true, ParameterSetName = 'refresh')] [switch]$Refresh, [Parameter(ValueFromPipeline = $true)] [Alias("Driver")] [ValidateIsWebDriverAttribute()] $Target = $Global:SeDriver ) switch ($PSCmdlet.ParameterSetName) { 'url' { $Target.Navigate().GoToUrl($Url); break } 'back' { $Target.Navigate().Back(); break } 'forward' { $Target.Navigate().Forward(); break } 'refresh' { $Target.Navigate().Refresh(); break } default { throw 'Unexpected ParameterSet' } } } <# function Find-SeElement { param( [Parameter()] $Driver, [Parameter()] $Element, [Parameter()][Switch]$Wait, [Parameter()]$Timeout = 30, [Parameter(ParameterSetName = "ByCss")] $Css, [Parameter(ParameterSetName = "ByName")] $Name, [Parameter(ParameterSetName = "ById")] $Id, [Parameter(ParameterSetName = "ByClassName")] $ClassName, [Parameter(ParameterSetName = "ByLinkText")] $LinkText, [Parameter(ParameterSetName = "ByPartialLinkText")] $PartialLinkText, [Parameter(ParameterSetName = "ByTagName")] $TagName, [Parameter(ParameterSetName = "ByXPath")] $XPath ) process { if ($null -ne $Driver -and $null -ne $Element) { throw "Driver and Element may not be specified together." } elseif ($null -ne $Driver) { $Target = $Driver } elseif (-ne $Null $Element) { $Target = $Element } else { "Driver or element must be specified" } if ($Wait) { if ($PSCmdlet.ParameterSetName -eq "ByName") { $TargetElement = [OpenQA.Selenium.By]::Name($Name) } if ($PSCmdlet.ParameterSetName -eq "ById") { $TargetElement = [OpenQA.Selenium.By]::Id($Id) } if ($PSCmdlet.ParameterSetName -eq "ByLinkText") { $TargetElement = [OpenQA.Selenium.By]::LinkText($LinkText) } if ($PSCmdlet.ParameterSetName -eq "ByPartialLinkText") { $TargetElement = [OpenQA.Selenium.By]::PartialLinkText($PartialLinkText) } if ($PSCmdlet.ParameterSetName -eq "ByClassName") { $TargetElement = [OpenQA.Selenium.By]::ClassName($ClassName) } if ($PSCmdlet.ParameterSetName -eq "ByTagName") { $TargetElement = [OpenQA.Selenium.By]::TagName($TagName) } if ($PSCmdlet.ParameterSetName -eq "ByXPath") { $TargetElement = [OpenQA.Selenium.By]::XPath($XPath) } if ($PSCmdlet.ParameterSetName -eq "ByCss") { $TargetElement = [OpenQA.Selenium.By]::CssSelector($Css) } $WebDriverWait = New-Object -TypeName OpenQA.Selenium.Support.UI.WebDriverWait($Driver, (New-TimeSpan -Seconds $Timeout)) $Condition = [OpenQA.Selenium.Support.UI.ExpectedConditions]::ElementExists($TargetElement) $WebDriverWait.Until($Condition) } else { if ($PSCmdlet.ParameterSetName -eq "ByName") { $Target.FindElements([OpenQA.Selenium.By]::Name($Name)) } if ($PSCmdlet.ParameterSetName -eq "ById") { $Target.FindElements([OpenQA.Selenium.By]::Id($Id)) } if ($PSCmdlet.ParameterSetName -eq "ByLinkText") { $Target.FindElements([OpenQA.Selenium.By]::LinkText($LinkText)) } if ($PSCmdlet.ParameterSetName -eq "ByPartialLinkText") { $Target.FindElements([OpenQA.Selenium.By]::PartialLinkText($PartialLinkText)) } if ($PSCmdlet.ParameterSetName -eq "ByClassName") { $Target.FindElements([OpenQA.Selenium.By]::ClassName($ClassName)) } if ($PSCmdlet.ParameterSetName -eq "ByTagName") { $Target.FindElements([OpenQA.Selenium.By]::TagName($TagName)) } if ($PSCmdlet.ParameterSetName -eq "ByXPath") { $Target.FindElements([OpenQA.Selenium.By]::XPath($XPath)) } if ($PSCmdlet.ParameterSetName -eq "ByCss") { $Target.FindElements([OpenQA.Selenium.By]::CssSelector($Css)) } } } } #> function Get-SeElement { [Alias('Find-SeElement', 'SeElement')] param( #Specifies whether the selction text is to select by name, ID, Xpath etc [ValidateSet("CssSelector", "Name", "Id", "ClassName", "LinkText", "PartialLinkText", "TagName", "XPath")] [ByTransformAttribute()] [string]$By = "XPath", #Text to select on [Alias("CssSelector", "Name", "Id", "ClassName", "LinkText", "PartialLinkText", "TagName", "XPath")] [Parameter(Position = 1, Mandatory = $true)] [string]$Selection, #Specifies a time out [Parameter(Position = 2)] [Int]$Timeout = 0, #The driver or Element where the search should be performed. [Parameter(Position = 3, ValueFromPipeline = $true)] [Alias('Element', 'Driver')] $Target = $Global:SeDriver, [parameter(DontShow)] [Switch]$Wait ) process { #if one of the old parameter names was used and BY was NIT specified, look for # <cmd/alias name> [anything which doesn't mean end of command] -Param # capture Param and set it as the value for by $mi = $MyInvocation.InvocationName if (-not $PSBoundParameters.ContainsKey("By") -and ($MyInvocation.Line -match "$mi[^>\|;]*-(CssSelector|Name|Id|ClassName|LinkText|PartialLinkText|TagName|XPath)")) { $By = $Matches[1] } if ($wait -and $Timeout -eq 0) { $Timeout = 30 } if ($TimeOut -and $Target -is [OpenQA.Selenium.Remote.RemoteWebDriver]) { $TargetElement = [OpenQA.Selenium.By]::$By($Selection) $WebDriverWait = [OpenQA.Selenium.Support.UI.WebDriverWait]::new($Target, (New-TimeSpan -Seconds $Timeout)) $Condition = [OpenQA.Selenium.Support.UI.ExpectedConditions]::ElementExists($TargetElement) $WebDriverWait.Until($Condition) } elseif ($Target -is [OpenQA.Selenium.Remote.RemoteWebElement] -or $Target -is [OpenQA.Selenium.Remote.RemoteWebDriver]) { if ($Timeout) { Write-Warning "Timeout does not apply when searching an Element" } $Target.FindElements([OpenQA.Selenium.By]::$By($Selection)) } else { throw "No valid target was provided." } } } function Invoke-SeClick { [CmdletBinding(DefaultParameterSetName = 'Default')] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'Default')] [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'JavaScript')] [OpenQA.Selenium.IWebElement]$Element, [Parameter(Mandatory = $true, ParameterSetName = 'JavaScript')] [Switch]$JavaScriptClick, [Parameter(ParameterSetName = 'JavaScript')] [ValidateIsWebDriverAttribute()] $Driver = $global:SeDriver ) if ($JavaScriptClick) { try { $Driver.ExecuteScript("arguments[0].click()", $Element) } catch { $PSCmdlet.ThrowTerminatingError($_) } } else { $Element.Click() } } function Send-SeClick { [alias('SeClick')] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)] [OpenQA.Selenium.IWebElement]$Element, [Alias('JS')] [Switch]$JavaScriptClick, $SleepSeconds = 0 , [Parameter(DontShow)] $Driver, [Alias('PT')] [switch]$PassThru ) Process { if ($JavaScriptClick) { $Element.WrappedDriver.ExecuteScript("arguments[0].click()", $Element) } else { $Element.Click() } if ($SleepSeconds) { Start-Sleep -Seconds $SleepSeconds } if ($PassThru) { $Element } } } function Get-SeKeys { [OpenQA.Selenium.Keys] | Get-Member -MemberType Property -Static | Select-Object -Property Name, @{N = "ObjectString"; E = { "[OpenQA.Selenium.Keys]::$($_.Name)" } } } function Send-SeKeys { param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [OpenQA.Selenium.IWebElement]$Element, [Parameter(Mandatory = $true, Position = 1)] [string]$Keys, [Parameter()] [Alias('PT')] [switch]$PassThru ) foreach ($Key in $Script:SeKeys.Name) { $Keys = $Keys -replace "{{$Key}}", [OpenQA.Selenium.Keys]::$Key } $Element.SendKeys($Keys) if ($PassThru) { $Element } } function Get-SeCookie { param( [Parameter(Mandatory = $false, ValueFromPipeline = $true)] [Alias("Driver")] [ValidateIsWebDriverAttribute()] $Target = $Global:SeDriver ) $Target.Manage().Cookies.AllCookies.GetEnumerator() } function Remove-SeCookie { param( [Parameter(Mandatory = $false, ValueFromPipeline = $true)] [Alias('Driver')] [OpenQA.Selenium.IWebDriver] $Target = $Global:SeDriver, [Parameter(Mandatory = $true, ParameterSetName = 'DeleteAllCookies')] [Alias('Purge')] [switch]$DeleteAllCookies, [Parameter(Mandatory = $true, ParameterSetName = 'NamedCookie')] [string]$Name ) if ($DeleteAllCookies) { $Target.Manage().Cookies.DeleteAllCookies() } else { $Target.Manage().Cookies.DeleteCookieNamed($Name) } } function Set-SeCookie { [cmdletbinding()] param( [string]$Name, [string]$Value, [string]$Path, [string]$Domain, $ExpiryDate, [Parameter(ValueFromPipeline = $true)] [Alias("Driver")] [ValidateIsWebDriverAttribute()] $Target = $Global:SeDriver ) <# Selenium Cookie Information Cookie(String, String) Initializes a new instance of the Cookie class with a specific name and value. Cookie(String, String, String) Initializes a new instance of the Cookie class with a specific name, value, and path. Cookie(String, String, String, Nullable<DateTime>) Initializes a new instance of the Cookie class with a specific name, value, path and expiration date. Cookie(String, String, String, String, Nullable<DateTime>) Initializes a new instance of the Cookie class with a specific name, value, domain, path and expiration date. #> begin { if ($null -ne $ExpiryDate -and $ExpiryDate.GetType().Name -ne 'DateTime') { throw '$ExpiryDate can only be $null or TypeName: System.DateTime' } } process { if ($Name -and $Value -and (!$Path -and !$Domain -and !$ExpiryDate)) { $cookie = [OpenQA.Selenium.Cookie]::new($Name, $Value) } Elseif ($Name -and $Value -and $Path -and (!$Domain -and !$ExpiryDate)) { $cookie = [OpenQA.Selenium.Cookie]::new($Name, $Value, $Path) } Elseif ($Name -and $Value -and $Path -and $ExpiryDate -and !$Domain) { $cookie = [OpenQA.Selenium.Cookie]::new($Name, $Value, $Path, $ExpiryDate) } Elseif ($Name -and $Value -and $Path -and $Domain -and (!$ExpiryDate -or $ExpiryDate)) { if ($Target.Url -match $Domain) { $cookie = [OpenQA.Selenium.Cookie]::new($Name, $Value, $Domain, $Path, $ExpiryDate) } else { Throw 'In order to set the cookie the browser needs to be on the cookie domain URL' } } else { Throw "Incorrect Cookie Layout: Cookie(String, String) Initializes a new instance of the Cookie class with a specific name and value. Cookie(String, String, String) Initializes a new instance of the Cookie class with a specific name, value, and path. Cookie(String, String, String, Nullable<DateTime>) Initializes a new instance of the Cookie class with a specific name, value, path and expiration date. Cookie(String, String, String, String, Nullable<DateTime>) Initializes a new instance of the Cookie class with a specific name, value, domain, path and expiration date." } $Target.Manage().Cookies.AddCookie($cookie) } } function Get-SeElementCssValue { param( [Parameter(ValueFromPipeline = $true, Mandatory = $true)] [OpenQA.Selenium.IWebElement]$Element, [Parameter(Mandatory = $true)] [string]$Name ) Process { $Element.GetCssValue($Name) } } function Get-SeElementAttribute { param( [Parameter(ValueFromPipeline = $true, Mandatory = $true)] [OpenQA.Selenium.IWebElement]$Element, [Parameter(Mandatory = $true)] [string]$Attribute ) process { $Element.GetAttribute($Attribute) } } function Invoke-SeScreenshot { param( [Parameter(ValueFromPipeline = $true)] [Alias("Driver")] [ValidateIsWebDriverAttribute()] $Target = $Global:SeDriver, [Parameter(Mandatory = $false)] [Switch]$AsBase64EncodedString ) $Screenshot = [OpenQA.Selenium.Support.Extensions.WebDriverExtensions]::TakeScreenshot($Target) if ($AsBase64EncodedString) { $Screenshot.AsBase64EncodedString } else { $Screenshot } } function Save-SeScreenshot { param( [Parameter(ValueFromPipeline = $true, Mandatory = $true)] [OpenQA.Selenium.Screenshot]$Screenshot, [Parameter(Mandatory = $true)] [string]$Path, [Parameter()] [OpenQA.Selenium.ScreenshotImageFormat]$ImageFormat = [OpenQA.Selenium.ScreenshotImageFormat]::Png) process { $Screenshot.SaveAsFile($Path, $ImageFormat) } } function New-SeScreenshot { [Alias('SeScreenshot')] [cmdletbinding(DefaultParameterSetName = 'Path')] param( [Parameter(ParameterSetName = 'Path' , Position = 0, Mandatory = $true)] [Parameter(ParameterSetName = 'PassThru', Position = 0)] $Path, [Parameter(ParameterSetName = 'Path', Position = 1)] [Parameter(ParameterSetName = 'PassThru', Position = 1)] [OpenQA.Selenium.ScreenshotImageFormat]$ImageFormat = [OpenQA.Selenium.ScreenshotImageFormat]::Png, [Parameter(ValueFromPipeline = $true)] [Alias("Driver")] [ValidateIsWebDriverAttribute()] $Target = $Global:SeDriver , [Parameter(ParameterSetName = 'Base64', Mandatory = $true)] [Switch]$AsBase64EncodedString, [Parameter(ParameterSetName = 'PassThru', Mandatory = $true)] [Alias('PT')] [Switch]$PassThru ) $Screenshot = [OpenQA.Selenium.Support.Extensions.WebDriverExtensions]::TakeScreenshot($Target) if ($AsBase64EncodedString) { $Screenshot.AsBase64EncodedString } elseif ($Path) { $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) $Screenshot.SaveAsFile($Path, $ImageFormat) } if ($Passthru) { $Screenshot } } function Get-SeWindow { param( [Parameter(Mandatory = $false, ValueFromPipeline = $true)] [Alias('Driver')] [OpenQA.Selenium.IWebDriver] $Target = $Global:SeDriver ) process { $Target.WindowHandles } } function Switch-SeWindow { param( [Parameter(Mandatory = $false, ValueFromPipeline = $true)] [Alias('Driver')] [OpenQA.Selenium.IWebDriver] $Target = $Global:SeDriver, [Parameter(Mandatory = $true)]$Window ) process { $Target.SwitchTo().Window($Window) | Out-Null } } function Switch-SeFrame { [Alias('SeFrame')] param ( [Parameter(Mandatory = $true, ParameterSetName = 'Frame', Position = 0)] $Frame, [Parameter(Mandatory = $true, ParameterSetName = 'Parent')] [switch]$Parent, [Parameter(Mandatory = $true, ParameterSetName = 'Root')] [Alias('defaultContent')] [switch]$Root, [Parameter(ValueFromPipeline = $true)] [Alias("Driver")] [ValidateIsWebDriverAttribute()] $Target = $Global:SeDriver ) if ($frame) { [void]$Target.SwitchTo().Frame($Frame) } elseif ($Parent) { [void]$Target.SwitchTo().ParentFrame() } elseif ($Root) { [void]$Target.SwitchTo().defaultContent() } } function Clear-SeAlert { [Alias('SeAccept', 'SeDismiss')] param ( [parameter(ParameterSetName = 'Alert', Position = 0, ValueFromPipeline = $true)] $Alert, [parameter(ParameterSetName = 'Driver')] [ValidateIsWebDriverAttribute()] [Alias("Driver")] $Target = $Global:SeDriver, [ValidateSet('Accept', 'Dismiss')] $Action = 'Dismiss', [Alias('PT')] [switch]$PassThru ) if ($Target) { try { $Alert = $Target.SwitchTo().alert() } catch { Write-Warning 'No alert was displayed'; return } } if (-not $PSBoundParameters.ContainsKey('Action') -and $MyInvocation.InvocationName -match 'Accept') { $Action = 'Accept' } if ($Alert) { $alert.$action() } if ($PassThru) { $Alert } } function SeOpen { [CmdletBinding()] Param( [ValidateSet('Chrome', 'CrEdge', 'FireFox', 'InternetExplorer', 'IE', 'MSEdge', 'NewEdge')] $In, [ValidateURIAttribute()] [Parameter(Mandatory = $False, Position = 1)] $URL, [hashtable]$Options = @{'Quiet' = $true }, [int]$SleepSeconds ) #Allow the browser to specified in an Environment variable if not passed as a parameter if ($env:DefaultBrowser -and -not $PSBoundParameters.ContainsKey('In')) { $In = $env:DefaultBrowser } #It may have been passed as a parameter, in an environment variable, or a parameter default, but if not, bail out if (-not $In) { throw 'No Browser was selected' } $StartParams = @{ } $StartParams += $Options $StartParams['AsDefaultDriver'] = $true $StartParams['Verbose'] = $false $StartParams['ErrorAction'] = 'Stop' $StartParams['Quiet'] = $true if ($url) { $StartParams['StartUrl'] = $url } switch -regex ($In) { 'Chrome' { Start-SeChrome @StartParams; continue } 'FireFox' { Start-SeFirefox @StartParams; continue } 'MSEdge' { Start-SeEdge @StartParams; continue } 'Edge$' { Start-SeNewEdge @StartParams; continue } '^I' { Start-SeInternetExplorer @StartParams; continue } } Write-Verbose -Message "Opened $($Global:SeDriver.Capabilities.browsername) $($Global:SeDriver.Capabilities.ToDictionary().browserVersion)" if ($SleepSeconds) { Start-Sleep -Seconds $SleepSeconds } }` function SeType { param( [Parameter(Mandatory = $true, Position = 0)] [string]$Keys, [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [OpenQA.Selenium.IWebElement]$Element, [switch]$ClearFirst, $SleepSeconds = 0 , [switch]$Submit, [Alias('PT')] [switch]$PassThru ) begin { foreach ($Key in $Script:SeKeys.Name) { $Keys = $Keys -replace "{{$Key}}", [OpenQA.Selenium.Keys]::$Key } } process { if ($ClearFirst) { $Element.Clear() } $Element.SendKeys($Keys) if ($Submit) { $Element.Submit() } if ($SleepSeconds) { Start-Sleep -Seconds $SleepSeconds } if ($PassThru) { $Element } } } function Get-SeSelectionOption { [Alias('SeSelection')] [cmdletbinding(DefaultParameterSetName = 'default')] param ( [Parameter(Mandatory = $true, ParameterSetName = 'byValue', Position = 0, ValueFromPipelineByPropertyName = $true)] [String]$ByValue, [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 1)] [OpenQA.Selenium.IWebElement]$Element, [Parameter(Mandatory = $true, ParameterSetName = 'byText', ValueFromPipelineByPropertyName = $true)] [String]$ByFullText, [Parameter(Mandatory = $true, ParameterSetName = 'bypart', ValueFromPipelineByPropertyName = $true)] [String]$ByPartialText, [Parameter(Mandatory = $true, ParameterSetName = 'byIndex', ValueFromPipelineByPropertyName = $true)] [int]$ByIndex, [Parameter(Mandatory = $false, ParameterSetName = 'default')] [Parameter(Mandatory = $false, ParameterSetName = 'byValue')] [Parameter(Mandatory = $false, ParameterSetName = 'byText')] [Parameter(Mandatory = $false, ParameterSetName = 'byIndex')] [switch]$Clear, [Parameter(Mandatory = $false, ParameterSetName = 'default')] [switch]$ListOptionText, [Parameter(Mandatory = $true, ParameterSetName = 'multi')] [switch]$IsMultiSelect, [Parameter(Mandatory = $true, ParameterSetName = 'selected')] [Parameter(Mandatory = $false, ParameterSetName = 'byValue')] [Parameter(Mandatory = $false, ParameterSetName = 'byText')] [Parameter(Mandatory = $false, ParameterSetName = 'bypart')] [Parameter(Mandatory = $false, ParameterSetName = 'byIndex')] [switch]$GetSelected, [Parameter(Mandatory = $true, ParameterSetName = 'allSelected')] [Parameter(Mandatory = $false, ParameterSetName = 'byValue')] [Parameter(Mandatory = $false, ParameterSetName = 'byText')] [Parameter(Mandatory = $false, ParameterSetName = 'bypart')] [Parameter(Mandatory = $false, ParameterSetName = 'byIndex')] [switch]$GetAllSelected, [Parameter(Mandatory = $false, ParameterSetName = 'byValue')] [Parameter(Mandatory = $false, ParameterSetName = 'byText')] [Parameter(Mandatory = $false, ParameterSetName = 'bypart')] [Parameter(Mandatory = $false, ParameterSetName = 'byIndex')] [Alias('PT')] [switch]$PassThru ) try { #byindex can be 0, but ByText and ByValue can't be empty strings if ($ByFullText -or $ByPartialText -or $ByValue -or $PSBoundParameters.ContainsKey('ByIndex')) { if ($Clear) { if ($ByText) { [SeleniumSelection.Option]::DeselectByText($Element, $ByText) } elseif ($ByValue) { [SeleniumSelection.Option]::DeselectByValue($Element, $ByValue) } else { [SeleniumSelection.Option]::DeselectByIndex($Element, $ByIndex) } } else { if ($ByText) { [SeleniumSelection.Option]::SelectByText($Element, $ByText, $false) } if ($ByPartialText) { [SeleniumSelection.Option]::SelectByText($Element, $ByPartialText, $true) } elseif ($ByValue) { [SeleniumSelection.Option]::SelectByValue($Element, $ByValue) } else { [SeleniumSelection.Option]::SelectByIndex($Element, $ByIndex) } } } elseif ($Clear) { [SeleniumSelection.Option]::DeselectAll($Element) } if ($IsMultiSelect) { return [SeleniumSelection.Option]::IsMultiSelect($Element) } if ($PassThru -and ($GetAllSelected -or $GetAllSelected)) { Write-Warning -Message "-Passthru option ignored because other values are returned" } if ($GetSelected) { return [SeleniumSelection.Option]::GetSelectedOption($Element).text } if ($GetAllSelected) { return [SeleniumSelection.Option]::GetAllSelectedOptions($Element).text } if ($PSCmdlet.ParameterSetName -eq 'default') { [SeleniumSelection.Option]::GetOptions($Element) | Select-Object -ExpandProperty Text } elseif ($PassThru) { $Element } } catch { throw "An error occured checking the selection box, the message was:`r`n $($_.exception.message)" } } function SeShouldHave { [cmdletbinding(DefaultParameterSetName = 'DefaultPS')] param( [Parameter(ParameterSetName = 'DefaultPS', Mandatory = $true , Position = 0, ValueFromPipeline = $true)] [Parameter(ParameterSetName = 'Element' , Mandatory = $true , Position = 0, ValueFromPipeline = $true)] [string[]]$Selection, [Parameter(ParameterSetName = 'DefaultPS', Mandatory = $false)] [Parameter(ParameterSetName = 'Element' , Mandatory = $false)] [ValidateSet('CssSelector', 'Name', 'Id', 'ClassName', 'LinkText', 'PartialLinkText', 'TagName', 'XPath')] [ByTransformAttribute()] [string]$By = 'XPath', [Parameter(ParameterSetName = 'Element' , Mandatory = $true , Position = 1)] [string]$With, [Parameter(ParameterSetName = 'Alert' , Mandatory = $true)] [switch]$Alert, [Parameter(ParameterSetName = 'NoAlert' , Mandatory = $true)] [switch]$NoAlert, [Parameter(ParameterSetName = 'Title' , Mandatory = $true)] [switch]$Title, [Parameter(ParameterSetName = 'URL' , Mandatory = $true)] [Alias('URI')] [switch]$URL, [Parameter(ParameterSetName = 'Element' , Mandatory = $false, Position = 3)] [Parameter(ParameterSetName = 'Alert' , Mandatory = $false, Position = 3)] [Parameter(ParameterSetName = 'Title' , Mandatory = $false, Position = 3)] [Parameter(ParameterSetName = 'URL' , Mandatory = $false, Position = 3)] [ValidateSet('like', 'notlike', 'match', 'notmatch', 'contains', 'eq', 'ne', 'gt', 'lt')] [OperatorTransformAttribute()] [String]$Operator = 'like', [Parameter(ParameterSetName = 'Element' , Mandatory = $false, Position = 4)] [Parameter(ParameterSetName = 'Alert' , Mandatory = $false, Position = 4)] [Parameter(ParameterSetName = 'Title' , Mandatory = $true , Position = 4)] [Parameter(ParameterSetName = 'URL' , Mandatory = $true , Position = 4)] [Alias('contains', 'like', 'notlike', 'match', 'notmatch', 'eq', 'ne', 'gt', 'lt')] [AllowEmptyString()] $Value, [Parameter(ParameterSetName = 'DefaultPS')] [Parameter(ParameterSetName = 'Element')] [Parameter(ParameterSetName = 'Alert')] [Alias('PT')] [switch]$PassThru, [Int]$Timeout = 0 ) begin { $endTime = [datetime]::now.AddSeconds($Timeout) $lineText = $MyInvocation.Line.TrimEnd("$([System.Environment]::NewLine)") $lineNo = $MyInvocation.ScriptLineNumber $file = $MyInvocation.ScriptName Function expandErr { param ($message) [Management.Automation.ErrorRecord]::new( [System.Exception]::new($message), 'PesterAssertionFailed', [Management.Automation.ErrorCategory]::InvalidResult, @{ Message = $message File = $file Line = $lineNo Linetext = $lineText } ) } function applyTest { param( $Testitems, $Operator, $Value ) Switch ($Operator) { 'Contains' { return ($testitems -contains $Value) } 'eq' { return ($TestItems -eq $Value) } 'ne' { return ($TestItems -ne $Value) } 'like' { return ($TestItems -like $Value) } 'notlike' { return ($TestItems -notlike $Value) } 'match' { return ($TestItems -match $Value) } 'notmatch' { return ($TestItems -notmatch $Value) } 'gt' { return ($TestItems -gt $Value) } 'le' { return ($TestItems -lt $Value) } } } #if operator was not passed, allow it to be taken from an alias for the -value if (-not $PSBoundParameters.ContainsKey('operator') -and $lineText -match ' -(eq|ne|contains|match|notmatch|like|notlike|gt|lt) ') { $Operator = $matches[1] } $Success = $false $foundElements = @() } process { #If we have been asked to check URL or title get them from the driver. Otherwise call Get-SEElement. if ($URL) { do { $Success = applyTest -testitems $Global:SeDriver.Url -operator $Operator -value $Value Start-Sleep -Milliseconds 500 } until ($Success -or [datetime]::now -gt $endTime) if (-not $Success) { throw (expandErr "PageURL was $($Global:SeDriver.Url). The comparison '-$operator $value' failed.") } } elseif ($Title) { do { $Success = applyTest -testitems $Global:SeDriver.Title -operator $Operator -value $Value Start-Sleep -Milliseconds 500 } until ($Success -or [datetime]::now -gt $endTime) if (-not $Success) { throw (expandErr "Page title was $($Global:SeDriver.Title). The comparison '-$operator $value' failed.") } } elseif ($Alert -or $NoAlert) { do { try { $a = $Global:SeDriver.SwitchTo().alert() $Success = $true } catch { Start-Sleep -Milliseconds 500 } finally { if ($NoAlert -and $a) { throw (expandErr "Expected no alert but an alert of '$($a.Text)' was displayed") } } } until ($Success -or [datetime]::now -gt $endTime) if ($Alert -and -not $Success) { throw (expandErr "Expected an alert but but none was displayed") } elseif ($value -and -not (applyTest -testitems $a.text -operator $Operator -value $value)) { throw (expandErr "Alert text was $($a.text). The comparison '-$operator $value' failed.") } elseif ($PassThru) { return $a } } else { foreach ($s in $Selection) { $GSEParams = @{By = $By; Selection = $s } if ($Timeout) { $GSEParams['Timeout'] = $Timeout } try { $e = Get-SeElement @GSEParams } catch { throw (expandErr $_.Exception.Message) } #throw if we didn't get the element; if were only asked to check it was there, return gracefully if (-not $e) { throw (expandErr "Didn't find '$s' by $by") } else { Write-Verbose "Matched element(s) for $s" $foundElements += $e } } } } end { if ($PSCmdlet.ParameterSetName -eq "DefaultPS" -and $PassThru) { return $e } elseif ($PSCmdlet.ParameterSetName -eq "DefaultPS") { return } else { foreach ($e in $foundElements) { switch ($with) { 'Text' { $testItem = $e.Text } 'Displayed' { $testItem = $e.Displayed } 'Enabled' { $testItem = $e.Enabled } 'TagName' { $testItem = $e.TagName } 'X' { $testItem = $e.Location.X } 'Y' { $testItem = $e.Location.Y } 'Width' { $testItem = $e.Size.Width } 'Height' { $testItem = $e.Size.Height } 'Choice' { $testItem = (Get-SeSelectionOption -Element $e -ListOptionText) } default { $testItem = $e.GetAttribute($with) } } if (-not $testItem -and ($Value -ne '' -and $foundElements.count -eq 1)) { throw (expandErr "Didn't find '$with' on element") } if (applyTest -testitems $testItem -operator $Operator -value $Value) { $Success = $true if ($PassThru) { $e } } } if (-not $Success) { if ($foundElements.count -gt 1) { throw (expandErr "$Selection match $($foundElements.Count) elements, none has a value for $with which passed the comparison '-$operator $value'.") } else { throw (expandErr "$with had a value of $testitem which did not pass the the comparison '-$operator $value'.") } } } } } |