From 191694135f7b4e34aa4ed1621baef028a8127cac Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Mon, 10 Feb 2020 20:02:42 +0000 Subject: [PATCH 1/8] #45: adds support for finding elements in the scope of an iframe --- examples/iframes.ps1 | 26 ++++++++++++++++++++++++++ src/Private/Tools.ps1 | 12 +++++++++++- src/Public/Elements.ps1 | 37 +++++++++++++++++++++++++++++++++++++ src/Public/Flow.ps1 | 4 ++-- 4 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 examples/iframes.ps1 diff --git a/examples/iframes.ps1 b/examples/iframes.ps1 new file mode 100644 index 0000000..7009487 --- /dev/null +++ b/examples/iframes.ps1 @@ -0,0 +1,26 @@ +param( + [Parameter(Mandatory=$true)] + [string] + $Url +) + +$path = Split-Path -Parent -Path (Split-Path -Parent -Path $MyInvocation.MyCommand.Path) +$path = "$($path)/src/Monocle.psm1" +Import-Module $path -Force -ErrorAction Stop + +# Create a browser object +$browser = New-MonocleBrowser -Type Chrome + +# Monocle runs commands in web flows, for easy disposal and test tracking +Start-MonocleFlow -Name 'Elements in iFrames' -Browser $browser -ScriptBlock { + + Set-MonocleUrl -Url $Url + + Get-MonocleElement -Id 'fillform-frame-1' | Enter-MonocleFrame -ScriptBlock { + Get-MonocleElement -Id 'postcode_search' | Set-MonocleElementValue -Value 'NN1 1AA' + Get-MonocleElement -Id 'findAddressbtn' | Invoke-MonocleElementClick + } + + Start-Sleep -Seconds 5 + +} -CloseBrowser \ No newline at end of file diff --git a/src/Private/Tools.ps1 b/src/Private/Tools.ps1 index f938117..2d330e8 100644 --- a/src/Private/Tools.ps1 +++ b/src/Private/Tools.ps1 @@ -153,4 +153,14 @@ function Test-MonocleUrl function Get-MonocleCustomDriverPath { return './custom_drivers' -} \ No newline at end of file +} + +function Add-MonocleOutputDepth +{ + $env:MONOCLE_OUTPUT_DEPTH = [string](([int]$env:MONOCLE_OUTPUT_DEPTH) + 1) +} + +function Remove-MonocleOutputDepth +{ + $env:MONOCLE_OUTPUT_DEPTH = [string](([int]$env:MONOCLE_OUTPUT_DEPTH) - 1) +} diff --git a/src/Public/Elements.ps1 b/src/Public/Elements.ps1 index fabfc24..5a668e4 100644 --- a/src/Public/Elements.ps1 +++ b/src/Public/Elements.ps1 @@ -683,4 +683,41 @@ function Test-MonocleElementCSS ) return (Invoke-MonocleJavaScript -Script 'arguments[0].style[arguments[1]] == arguments[2]' -Arguments $Element, $Name, $Value) +} + +function Enter-MonocleFrame +{ + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true, ValueFromPipeline=$true)] + [OpenQA.Selenium.IWebElement] + $Element, + + [Parameter(Mandatory=$true)] + [scriptblock] + $ScriptBlock + ) + + # get the meta id of the element + $id = Get-MonocleElementId -Element $Element + + try { + # enter the iframe + Write-MonocleHost -Message "Entering iFrame: $($id)" + $Browser.SwitchTo().Frame($Element) | Out-Null + + # update the depth of output + Add-MonocleOutputDepth + + # run the scriptblock + . $ScriptBlock + } + finally { + # reset the depth + Remove-MonocleOutputDepth + + # exit the iframe back to the default frame + Write-MonocleHost -Message "Exiting iFrame: $($id)" + $Browser.SwitchTo().ParentFrame() | Out-Null + } } \ No newline at end of file diff --git a/src/Public/Flow.ps1 b/src/Public/Flow.ps1 index 8398cff..34351b4 100644 --- a/src/Public/Flow.ps1 +++ b/src/Public/Flow.ps1 @@ -165,7 +165,7 @@ function Invoke-MonocleRetryScript } # update the depth of output - $env:MONOCLE_OUTPUT_DEPTH = [string](([int]$env:MONOCLE_OUTPUT_DEPTH) + 1) + Add-MonocleOutputDepth # attempt the logic $attempt = 1 @@ -187,5 +187,5 @@ function Invoke-MonocleRetryScript } # reset the depth - $env:MONOCLE_OUTPUT_DEPTH = [string](([int]$env:MONOCLE_OUTPUT_DEPTH) - 1) + Remove-MonocleOutputDepth } \ No newline at end of file From d1a3dd583dc3d1913cf566f0c3526150b0f26eae Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Tue, 11 Feb 2020 19:17:53 +0000 Subject: [PATCH 2/8] #45: Updates readme, and bumps version --- README.md | 1 + src/Monocle.psd1 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2dc44da..accbbd3 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ The following is a list of available functions in Monocle: * Clear-MonocleElementValue * Close-MonocleBrowser * Edit-MonocleUrl +* Enter-MonocleFrame * Get-Monocle2FACode * Get-MonocleElement * Get-MonocleElementAttribute diff --git a/src/Monocle.psd1 b/src/Monocle.psd1 index 0d8f9bf..e8a7321 100644 --- a/src/Monocle.psd1 +++ b/src/Monocle.psd1 @@ -11,7 +11,7 @@ RootModule = 'Monocle.psm1' # Version number of this module. - ModuleVersion = '1.3.0' + ModuleVersion = '1.3.1' # ID used to uniquely identify this module GUID = '9dc3c8a1-664d-4253-a5d2-920250d3a15f' From 725e35eb4d8154be3dac228b5c7b69f4fe743cb8 Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Wed, 12 Feb 2020 20:00:39 +0000 Subject: [PATCH 3/8] #47: Adds support for waiting for element to be visible --- README.md | 2 ++ examples/iframes.ps1 | 15 +++++++--- src/Public/Elements.ps1 | 62 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index accbbd3..57b7bc0 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,8 @@ The following is a list of available functions in Monocle: * Test-MonocleElementCSS * Test-MonocleElementVisible * Wait-MonocleElement +* Wait-MonocleElement +* Wait-MonocleElementVisible * Wait-MonocleUrl * Wait-MonocleUrlDifferent * Wait-MonocleValue diff --git a/examples/iframes.ps1 b/examples/iframes.ps1 index 7009487..ff4c834 100644 --- a/examples/iframes.ps1 +++ b/examples/iframes.ps1 @@ -1,7 +1,15 @@ param( [Parameter(Mandatory=$true)] [string] - $Url + $Url, + + [Parameter(Mandatory=$true)] + [string] + $Postcode, + + [Parameter(Mandatory=$true)] + [string] + $Address ) $path = Split-Path -Parent -Path (Split-Path -Parent -Path $MyInvocation.MyCommand.Path) @@ -17,10 +25,9 @@ Start-MonocleFlow -Name 'Elements in iFrames' -Browser $browser -ScriptBlock { Set-MonocleUrl -Url $Url Get-MonocleElement -Id 'fillform-frame-1' | Enter-MonocleFrame -ScriptBlock { - Get-MonocleElement -Id 'postcode_search' | Set-MonocleElementValue -Value 'NN1 1AA' + Get-MonocleElement -Id 'postcode_search' | Set-MonocleElementValue -Value $Postcode Get-MonocleElement -Id 'findAddressbtn' | Invoke-MonocleElementClick + Get-MonocleElement -Id 'yourAddress' -WaitVisible | Set-MonocleElementValue -Value $Address } - Start-Sleep -Seconds 5 - } -CloseBrowser \ No newline at end of file diff --git a/src/Public/Elements.ps1 b/src/Public/Elements.ps1 index 5a668e4..ac81e92 100644 --- a/src/Public/Elements.ps1 +++ b/src/Public/Elements.ps1 @@ -34,6 +34,8 @@ function Set-MonocleElementValue $select.SelectByText($Value) } catch { + $select | Out-Default + $select.Options | Out-Default $select.SelectByValue($Value) } } @@ -317,10 +319,13 @@ function Wait-MonocleElement [Parameter()] [int] - $Timeout = 600 + $Timeout = 600, + + [switch] + $All ) - Get-MonocleElementInternal ` + $result = Get-MonocleElementInternal ` -FilterType $PSCmdlet.ParameterSetName ` -Id $Id ` -TagName $TagName ` @@ -329,7 +334,16 @@ function Wait-MonocleElement -ElementValue $ElementValue ` -XPath $XPath ` -Selector $Selector ` - -Timeout $Timeout | Out-Null + -Timeout $Timeout ` + -All:$All + + # set the meta id on the element + @($result.Element) | ForEach-Object { + Set-MonocleElementId -Element $_ -Id $result.Id + } + + # return the element + return $result.Element } function Get-MonocleElement @@ -365,6 +379,9 @@ function Get-MonocleElement [string] $Selector, + [switch] + $WaitVisible, + [switch] $All ) @@ -386,10 +403,49 @@ function Get-MonocleElement Set-MonocleElementId -Element $_ -Id $result.Id } + # wait for the elements to be visible + if ($WaitVisible) { + @($result.Element) | ForEach-Object { + $_ | Wait-MonocleElementVisible | Out-Null + } + } + # return the element return $result.Element } +function Wait-MonocleElementVisible +{ + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true, ValueFromPipeline=$true)] + [OpenQA.Selenium.IWebElement] + $Element, + + [Parameter()] + [int] + $Timeout = 30 + ) + + # get the meta id of the element + $id = Get-MonocleElementId -Element $Element + Write-MonocleHost -Message "Waiting for element to be visible: $($id)" + + # wait for the element to be visible + $seconds = 0 + + while ($seconds -le $Timeout) { + if (($Element | Test-MonocleElementVisible)) { + return $Element + } + + $seconds++ + Start-Sleep -Seconds 1 + } + + throw "Element '$($id)' was not visible after $($Timeout) seconds" +} + function Measure-MonocleElement { [CmdletBinding(DefaultParameterSetName='Id')] From d55b11e14c89d503b2b33fd8e1d708af521c420d Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Wed, 12 Feb 2020 20:02:13 +0000 Subject: [PATCH 4/8] #47: Remove dupe func --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 57b7bc0..a42637d 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,6 @@ The following is a list of available functions in Monocle: * Test-MonocleElementCSS * Test-MonocleElementVisible * Wait-MonocleElement -* Wait-MonocleElement * Wait-MonocleElementVisible * Wait-MonocleUrl * Wait-MonocleUrlDifferent From 76f112c7aa8bb24cfb0ba9b40283d53beec508ab Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Wed, 12 Feb 2020 20:05:43 +0000 Subject: [PATCH 5/8] #47: quick fixes on examples --- examples/google.ps1 | 2 +- examples/youtube.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/google.ps1 b/examples/google.ps1 index c174775..67d19bd 100644 --- a/examples/google.ps1 +++ b/examples/google.ps1 @@ -24,6 +24,6 @@ Start-MonocleFlow -Name 'Google Search' -Browser $browser -ScriptBlock { Get-MonocleElement -Id 'logo' | Invoke-MonocleElementClick # ensure we're back home - Wait-MonocleElement -Id 'q' + Wait-MonocleElement -Id 'q' | Out-Null } -CloseBrowser \ No newline at end of file diff --git a/examples/youtube.ps1 b/examples/youtube.ps1 index 50cb6ca..fbe14e8 100644 --- a/examples/youtube.ps1 +++ b/examples/youtube.ps1 @@ -19,7 +19,7 @@ Start-MonocleFlow -Name 'Load YouTube' -Browser $browser -ScriptBlock { #Get-MonocleElement -Id 'search_query' | Set-MonocleElementValue -Value 'Beerus Madness (Extended)' # Tells the browser to click the search button - Wait-MonocleElement -Id 'search-icon-legacy' + Wait-MonocleElement -Id 'search-icon-legacy' | Out-Null Get-MonocleElement -Id 'search-icon-legacy' | Invoke-MonocleElementClick # Though all commands sleep when the page is busy, some buttons use javascript From d600142ea1aabebab98bc014e083245d74db30ed Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Wed, 12 Feb 2020 20:13:59 +0000 Subject: [PATCH 6/8] #47: Add -WaitVisible to Wait-MonocleElement as well --- src/Public/Elements.ps1 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Public/Elements.ps1 b/src/Public/Elements.ps1 index ac81e92..a3687f5 100644 --- a/src/Public/Elements.ps1 +++ b/src/Public/Elements.ps1 @@ -321,6 +321,9 @@ function Wait-MonocleElement [int] $Timeout = 600, + [switch] + $WaitVisible, + [switch] $All ) @@ -342,6 +345,13 @@ function Wait-MonocleElement Set-MonocleElementId -Element $_ -Id $result.Id } + # wait for the elements to be visible + if ($WaitVisible) { + @($result.Element) | ForEach-Object { + $_ | Wait-MonocleElementVisible | Out-Null + } + } + # return the element return $result.Element } From c4c9ab5a73fd285bd1840938541d48e3979a280e Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Wed, 12 Feb 2020 20:38:20 +0000 Subject: [PATCH 7/8] #49: Adds support for scrolling to an element --- examples/scrolling.ps1 | 30 ++++++++++++++++++++++++++++++ src/Public/Page.ps1 | 38 +++++++++++++++++++++++++++----------- 2 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 examples/scrolling.ps1 diff --git a/examples/scrolling.ps1 b/examples/scrolling.ps1 new file mode 100644 index 0000000..58d9860 --- /dev/null +++ b/examples/scrolling.ps1 @@ -0,0 +1,30 @@ +$path = Split-Path -Parent -Path (Split-Path -Parent -Path $MyInvocation.MyCommand.Path) +$path = "$($path)/src/Monocle.psm1" +Import-Module $path -Force -ErrorAction Stop + +# Create a browser object +$browser = New-MonocleBrowser -Type Chrome + +# Monocle runs commands in web flows, for easy disposal and test tracking +Start-MonocleFlow -Name 'Scrolling' -Browser $browser -ScriptBlock { + + # navigate to google + Set-MonocleUrl -Url 'https://en.wikipedia.org/wiki/PowerShell' -Force + + # move to the middle of the page + Move-MonoclePage -To Middle + Start-MonocleSleep -Seconds 2 + + # move to a specific position + Move-MonoclePage -Position 2000 + Start-MonocleSleep -Seconds 2 + + # move to the top of the page + Move-MonoclePage -To Top + Start-MonocleSleep -Seconds 2 + + # move to the footer - by element + Get-MonocleElement -Id 'footer' | Move-MonoclePage + Start-MonocleSleep -Seconds 2 + +} -CloseBrowser \ No newline at end of file diff --git a/src/Public/Page.ps1 b/src/Public/Page.ps1 index cc05e14..3717e57 100644 --- a/src/Public/Page.ps1 +++ b/src/Public/Page.ps1 @@ -9,20 +9,36 @@ function Move-MonoclePage [Parameter(ParameterSetName='Position')] [int] - $Position + $Position, + + [Parameter(ParameterSetName='Element', ValueFromPipeline=$true)] + [OpenQA.Selenium.IWebElement] + $Element ) - if ($PSCmdlet.ParameterSetName -ieq 'to') { - $size = Get-MonoclePageSize - $Position = (@{ - Bottom = $size.Height - Middle = $size.Height * 0.5 - Top = 0 - })[$To] - } + switch ($PSCmdlet.ParameterSetName.ToLowerInvariant()) { + # literal positions + { @('to', 'position') -icontains $_ } { + if ($PSCmdlet.ParameterSetName -ieq 'to') { + $size = Get-MonoclePageSize + $Position = (@{ + Bottom = $size.Height + Middle = $size.Height * 0.5 + Top = 0 + })[$To] + } + + Write-MonocleHost -Message "Scrolling to: $Position" + Invoke-MonocleJavaScript -Arguments $Position -Script 'window.scrollTo(0, arguments[0])' | Out-Null + } - Write-MonocleHost -Message "Scrolling to: $Position" - Invoke-MonocleJavaScript -Arguments $Position -Script 'window.scrollTo(0, arguments[0])' | Out-Null + # elements + 'element' { + $id = Get-MonocleElementId -Element $Element + Write-MonocleHost -Message "Moving page to element: $($id)" + Invoke-MonocleJavaScript -Arguments $Element -Script 'arguments[0].scrollIntoView(true)' | Out-Null + } + } } function Get-MonoclePageSize From 1bf6f8ed22c8eb4059290724a879c249b441a1f3 Mon Sep 17 00:00:00 2001 From: Matthew Kelly Date: Thu, 13 Feb 2020 19:08:56 +0000 Subject: [PATCH 8/8] Remove unneeded log lines --- src/Public/Elements.ps1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Public/Elements.ps1 b/src/Public/Elements.ps1 index a3687f5..eda4c2e 100644 --- a/src/Public/Elements.ps1 +++ b/src/Public/Elements.ps1 @@ -34,8 +34,6 @@ function Set-MonocleElementValue $select.SelectByText($Value) } catch { - $select | Out-Default - $select.Options | Out-Default $select.SelectByValue($Value) } }