Skip to content

Commit

Permalink
Merge pull request #14 from Badgerati/develop
Browse files Browse the repository at this point in the history
v1.1.0
  • Loading branch information
Badgerati authored Oct 16, 2019
2 parents 4b4824b + a76f764 commit 74c018a
Show file tree
Hide file tree
Showing 12 changed files with 464 additions and 461 deletions.
30 changes: 20 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/Badgerati/Monocle/master/LICENSE.txt)
[![PowerShell](https://img.shields.io/powershellgallery/dt/monocle.svg?label=PowerShell&colorB=085298)](https://www.powershellgallery.com/packages/Monocle)
[![Docker](https://img.shields.io/docker/pulls/badgerati/monocle.svg?label=Docker)](https://hub.docker.com/r/badgerati/monocle/)

Monocle is a Cross-Platform PowerShell Web Automation module, made to make automating and testing websites easier. It's a PowerShell wrapper around Selenium, with the aim of abstracting Selenium away from the user.

Expand All @@ -10,7 +11,7 @@ Monocle is a Cross-Platform PowerShell Web Automation module, made to make autom
* [Documentation](#documentation)
* [Functions](#functions)
* [Screenshots](#screenshots)
* [Waiting](#waiting)
* [2FA Codes](#2fa-codes)
* [Docker](#docker)

Monocle currently supports the following browsers:
Expand Down Expand Up @@ -40,19 +41,19 @@ Start-MonocleFlow -Name 'Load YouTube' -Browser $browser -ScriptBlock {
Set-MonocleUrl -Url 'https://www.youtube.com'
# sets the element's value, selecting the element by ID/Name
Set-MonocleElementValue -Id 'search_query' -Value 'Beerus Madness (Extended)'
Get-MonocleElement -Id 'search_query' | Set-MonocleElementValue -Value 'Beerus Madness (Extended)'
# click the search button
Invoke-MonocleElementClick -Id 'search-btn'
Get-MonocleElement -Id 'search-icon-legacy' | Invoke-MonocleElementClick
# wait for the URL to change to start with the following value
Wait-MonocleUrl -Url 'https://www.youtube.com/results?search_query=' -StartsWith
# downloads an image from the page, selcted by using an XPath to an element
Save-MonocleImage -XPath "//div[@data-context-item-id='SI6Yyr-iI6M']/img[1]" -Path '.\beerus.jpg'
Get-MonocleElement -XPath "//div[@data-context-item-id='SI6Yyr-iI6M']/img[1]" | Save-MonocleImage -FilePath '.\beerus.jpg'
# tells the browser to click the video in the results
Invoke-MonocleElementClick -XPath "//a[@title='Dragon Ball Super Soundtrack - Beerus Madness (Extended)']"
Get-MonocleElement -XPath "//a[@title='Dragon Ball Super Soundtrack - Beerus Madness (Extended)']" | Invoke-MonocleElementClick
# wait for the URL to be loaded
Wait-MonocleUrl -Url 'https://www.youtube.com/watch?v=SI6Yyr-iI6M'
Expand All @@ -71,25 +72,33 @@ The following is a list of available functions in Monocle:

* Assert-MonocleBodyValue
* Assert-MonocleElementValue
* Clear-MonocleElementValue
* Close-MonocleBrowser
* Edit-MonocleUrl
* Get-Monocle2FACode
* Get-MonocleElement
* Get-MonocleElementAttribute
* Get-MonocleElementValue
* Get-MonocleHtml
* Get-MonocleTimeout
* Get-MonocleUrl
* Invoke-MonocleElementCheck
* Invoke-MonocleElementClick
* Invoke-MonocleJavaScript
* Invoke-MonocleRetryScript
* Invoke-MonocleScreenshot
* New-MonocleBrowser
* Restart-MonocleBrowser
* Save-MonocleImage
* Set-MonocleElementAttribute
* Set-MonocleElementValue
* Set-MonocleTimeout
* Set-MonocleUrl
* Start-MonocleFlow
* Start-MonocleSleep
* Submit-MonocleForm
* Test-MonocleElement
* Wait-MonocleElement
* Test-MonocleElementAttribute
* Wait-MonocleUrl
* Wait-MonocleUrlDifferent
* Wait-MonocleValue
Expand All @@ -112,17 +121,18 @@ Invoke-MonocoleScreenshot -Name 'screenshot.png' -Path './path'

> Not supplying `-ScreenshotPath` or `-Path` will default to the current path.
### Waiting
### 2FA Codes

There are inbuilt function to wait for a URL or element. However, to wait for an element during a Set/Click call you can use the `-Wait` switch:
Monocle has inbuilt support for generating 2FA codes. To do this you need the Secret Code that is normally presented with the QR code, and you pass this to the `Get-Monocle2FACode` function with a date - which is defaulted to now:

```powershell
Invoke-MonocleElementClick -Id 'element-id' -Wait
$code = Get-Monocle2FACode -Secret 'FAKENDMYJWLLB'
Get-MonocleElement -Id '2fa-code' | Set-MonocleElementValue -Value $code -Mask
```

### Docker

Monocle has an offical Docker image, which comes preloaded with:
Monocle has an official Docker image, which comes preloaded with:

* Monocle (obviously!)
* Firefox
Expand Down
8 changes: 4 additions & 4 deletions examples/youtube.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ Start-MonocleFlow -Name 'Load YouTube' -Browser $browser -ScriptBlock {
Set-MonocleUrl -Url 'https://www.youtube.com'

# Sets the search bar element to the passed value to query
Set-MonocleElementValue -Id 'search_query' -Value 'Beerus Madness (Extended)'
Get-MonocleElement -Id 'search_query' | Set-MonocleElementValue -Value 'Beerus Madness (Extended)'

# Tells the browser to click the search button
Invoke-MonocleElementClick -Id 'search-icon-legacy'
Get-MonocleElement -Id 'search-icon-legacy' | Invoke-MonocleElementClick

# Though all commands sleep when the page is busy, some buttons use javascript
# to reform the page. The following will sleep the browser until the passed URL is loaded.
# If (default) 10 seconds passes and no URL, then the flow fails
Wait-MonocleUrl -Url 'https://www.youtube.com/results?search_query=' -StartsWith

# Downloads an image from the page. This time it's using XPath
#Save-MonocleImage -XPath "//div[@data-context-item-id='SI6Yyr-iI6M']/img[1]" -Path '.\beerus.jpg'
#Get-MonocleElement -XPath "//div[@data-context-item-id='SI6Yyr-iI6M']/img[1]" | Save-MonocleImage -FilePath '.\beerus.jpg'

# Tells the browser to click the video in the results. The video link is found via XPath
Invoke-MonocleElementClick -XPath "//a[@title='Dragon Ball Super Soundtrack - Beerus Madness (Extended)']" -Wait
Get-MonocleElement -XPath "//a[@title='Dragon Ball Super Soundtrack - Beerus Madness (Extended)']" | Invoke-MonocleElementClick

# Again, we expect the URL to be loaded
Wait-MonocleUrl -Url 'https://www.youtube.com/watch?v=SI6Yyr-iI6M'
Expand Down
4 changes: 2 additions & 2 deletions src/Monocle.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
RootModule = 'Monocle.psm1'

# Version number of this module.
ModuleVersion = '1.0.0'
ModuleVersion = '1.1.0'

# ID used to uniquely identify this module
GUID = '9dc3c8a1-664d-4253-a5d2-920250d3a15f'
Expand All @@ -33,7 +33,7 @@
PSData = @{

# Tags applied to this module. These help with module discovery in online galleries.
Tags = @('powershell', 'web', 'automation', 'testing', 'ie', 'internet-explorer', 'websites', 'chrome',
Tags = @('powershell', 'web', 'automation', 'testing', 'ie', 'internet-explorer', 'websites', 'chrome', '2fa',
'firefox', 'selenium', 'cross-platform', 'PSEdition_Core', 'PSEdition_Desktop', 'linux', 'google-chrome')

# A URL to the license for this module.
Expand Down
52 changes: 34 additions & 18 deletions src/Private/Elements.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,32 @@
function Get-MonocleElement
function Get-MonocleElementId
{
[CmdletBinding()]
param (
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[OpenQA.Selenium.IWebElement]
$Element
)

return (Get-MonocleElementAttribute -Element $Element -Name 'meta-monocle-id')
}

function Set-MonocleElementId
{
[CmdletBinding()]
param (
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[OpenQA.Selenium.IWebElement]
$Element,

[Parameter(Mandatory=$true)]
[string]
$Id
)

return (Set-MonocleElementAttribute -Element $Element -Name 'meta-monocle-id' -Value $Id)
}

function Get-MonocleElementInternal
{
[CmdletBinding()]
param (
Expand Down Expand Up @@ -31,21 +59,11 @@ function Get-MonocleElement
[string]
$XPath,

[Parameter()]
[int]
$Timeout,

[switch]
$NoThrow,

[switch]
$Wait
$NoThrow
)

if ($Timeout -le 0) {
$Timeout = 10
}

$timeout = Get-MonocleTimeout
$seconds = 0

while ($true) {
Expand All @@ -72,7 +90,7 @@ function Get-MonocleElement
catch {
$seconds++

if (!$Wait -or ($seconds -ge $Timeout)) {
if ($seconds -ge $timeout) {
throw $_.Exception
}

Expand Down Expand Up @@ -109,7 +127,7 @@ function Get-MonocleElementById

return @{
Element = $element
Id = "<$($Id)>"
Id = "<[@id=$($Id)]>"
}
}

Expand Down Expand Up @@ -137,8 +155,6 @@ function Get-MonocleElementByTagName
$NoThrow
)

#$document = $Browser.Document

# get all elements for the tag
Write-Verbose -Message "Finding element with tag <$TagName>"
$elements = $Browser.FindElementsByTagName($TagName)
Expand Down Expand Up @@ -170,7 +186,7 @@ function Get-MonocleElementByTagName
throw "Element <$TagName> with attribute '$AttributeName' and value of '$AttributeValue' not found"
}

$id += "[$($AttributeName)=$($AttributeValue)]"
$id += "[@$($AttributeName)=$($AttributeValue)]"
}

if (![string]::IsNullOrWhiteSpace($ElementValue))
Expand Down
29 changes: 13 additions & 16 deletions src/Private/Tools.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ function Start-MonocleSleepWhileBusy
param ()

$count = 0
$timeout = $Browser.Manage().Timeouts().PageLoad
$timeout = Get-MonocleTimeout

while ($Browser.ExecuteScript('return document.readyState') -ine 'complete')
while ((Invoke-MonocleJavaScript -Script 'return document.readyState') -ine 'complete')
{
if ($count -ge $timeout) {
throw "Loading URL has timed-out after $timeout second(s)"
Expand Down Expand Up @@ -82,30 +82,27 @@ function Test-MonocleUrl
[Parameter(Mandatory=$true)]
[ValidateNotNull()]
[string]
$Url,

[Parameter()]
[int]
$Attempts = 1
$Url
)

# truncate the URL of any query parameters
$Url = ([System.Uri]$Url).GetLeftPart([System.UriPartial]::Path)

# initial code setting as success
$code = 200
$timeout = Get-MonocleTimeout
$message = [string]::Empty

$attempt = 1
while ($attempt -le $Attempts) {
$count = 1
while ($count -le $timeout) {
try {
Write-MonocleHost -Message "Testing: $url [attempt: $($attempt)]"
Write-MonocleHost -Message "Testing: $url [attempt: $($count)]"

if ($PSVersionTable.PSVersion.Major -le 5) {
$result = Invoke-WebRequest -Uri $Url -TimeoutSec 30 -UseBasicParsing -ErrorAction Stop
$result = Invoke-WebRequest -Uri $Url -TimeoutSec $timeout -UseBasicParsing -ErrorAction Stop
}
else {
$result = Invoke-WebRequest -Uri $Url -TimeoutSec 30 -ErrorAction Stop
$result = Invoke-WebRequest -Uri $Url -TimeoutSec $timeout -ErrorAction Stop
}

$code = [int]$result.StatusCode
Expand All @@ -131,12 +128,12 @@ function Test-MonocleUrl
}

if (($code -eq -1) -or ($code -ge 400)) {
$attempt++
Start-Sleep -Seconds 1

if ($attempt -gt $Attempts) {
$count++
if ($count -gt $timeout) {
break
}

Start-Sleep -Seconds 1
}
else {
break
Expand Down
Loading

0 comments on commit 74c018a

Please sign in to comment.