diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fb9c8a8..9555239 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,13 +6,12 @@ on: jobs: build: - runs-on: ubuntu-latest - secrets: ["api_key"] - + env: + ApiKey: ${{ secrets.API_KEY }} + steps: - - uses: actions/checkout@v1 - - name: Publish - run: | - pwsh -Command "Publish-Module -Path ./Selenium.psd1 -NuGetApiKey $Env:api_key" - + - uses: actions/checkout@v1 + - name: Publish + run: | + pwsh -Command "Publish-Module -Path ${{ github.workspace }}/Output/Selenium/ -NuGetApiKey ${{secrets.API_KEY}}" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..02f0eb1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.vscode +CI/LocalPostProcessing.ps1 +Scratchpad.ps1 +Output/testResults*.xml +Output/stats.json +debug.log diff --git a/CI/CI.ps1 b/CI/CI.ps1 new file mode 100644 index 0000000..25ac684 --- /dev/null +++ b/CI/CI.ps1 @@ -0,0 +1,99 @@ +param ( + [String]$ModulePath, + [string[]]$BrowserList = @('Chrome', 'Firefox'), + [Switch]$UseDebugVersion +) + +if ([String]::IsNullOrEmpty($ModulePath)) { $ModulePath = $pwd.path.Replace('\', '/') } +$env:ModulePath = $ModulePath +Write-Host "ModulePath: $ModulePath" +Write-Host "BrowserList: $($BrowserList -join ',')" +$Global:BrowserList = $BrowserList +#Get the OS/PS version info for later. On Linux run headless On windows and PS 6 (but not 7) add WindowsPowershell to the module path. +$Platform = ([environment]::OSVersion.Platform).ToString() + ' PS' + $PSVersionTable.PSVersion.Major +if ($Platform -notlike 'win*') { $Global:HeadlessOnly = $true } +if ($Platform -like 'win*6') { + $env:PSModulePath -split ';' | Where-Object { $_ -match "\w:\\Prog.*PowerShell\\modules" } | ForEach-Object { + $env:PSModulePath = ($_ -replace "PowerShell", "WindowsPowerShell") + ";" + $env:PSModulePath + } +} + + + +#Make sure we have the modules we need +$ModulePathSuffix = 'Output/Selenium/' +if ($UseDebugVersion) { $ModulePathSuffix = ''; Write-Host 'Debug version will be used' -ForegroundColor Yellow } +Import-Module "$ModulePath/$($ModulePathSuffix)Selenium.psd1" -Force -ErrorAction Stop + +# $checkImportExcel = Get-Module -ListAvailable ImportExcel +# if (-not ($checkImportExcel)) { +# Write-Verbose -Verbose 'Installing ImportExcel' +# Install-Module ImportExcel -Force -SkipPublisherCheck +# } +# else { $checkImportExcel | Out-Host } +# $PesterLock = @{MinimumVersion = '4.10.0.0' ; MaximumVersion = '4.99.0.0' } +# $checkPester = Get-Module -ListAvailable Pester | Where-Object { $_.version.major -ge 4 -and $_.version.minor -ge 4 } +# if (-not $checkPester) { +# Write-Verbose -Verbose 'Installing Pester' +# Install-Module Pester -Force -SkipPublisherCheck @PesterLock +# } +# else { $checkPester | Out-Host } + +#Import-Module Pester -RequiredVersion 4.10.1 +#Import-Module ImportExcel -RequiredVersion 7.1.1 + +if (Test-path "$ModulePath/Modules") { + Import-Module "$ModulePath/Modules/Pester/5.0.3/Pester.psd1" + Import-Module "$ModulePath/Modules/ImportExcel/7.1.1/ImportExcel.psd1" +} +else { + Import-Module -Name Pester -RequiredVersion 5.0.3 + Import-Module -Name ImportExcel -RequiredVersion 7.1.1 +} + + +Write-verbose -Verbose "Pester $((Get-Module -Name Pester).Version.ToString()) loaded" +Write-verbose -Verbose "ImportExcel $((Get-Module -Name ImportExcel).Version.ToString()) loaded" + +# #Run the test and results export to an Excel file for current OS - Test picks up the selected browser from an environment variable. +$RunParameters = @{ + XLFile = '{0}/results/Results-{1}.xlsx' -f $env:BUILD_ARTIFACTSTAGINGDIRECTORY, [environment]::OSVersion.Platform.ToString() + Path = "$ModulePath/Examples/Combined.tests.ps1" +} +foreach ( $b in $BrowserList) { + $Global:DefaultBrowser = $b + $RunParameters['OutputFile'] = Join-Path $pwd "TestResults-$platform$b.xml" + $RunParameters['WorkSheetName'] = "$B $Platform" + $RunParameters | Out-Host + & "$PSScriptRoot\Pester-To-XLSx.ps1" @RunParameters +} + +#Merge the results sheets into a sheet named 'combined'. +# $excel = Open-ExcelPackage $RunParameters.XLFile +# $wslist = $excel.Workbook.Worksheets.name +# Close-ExcelPackage -NoSave $excel +# Merge-MultipleSheets -path $RunParameters.XLFile -WorksheetName $wslist -OutputSheetName combined -OutputFile $RunParameters.XLFile -HideRowNumbers -Property name, result + +# #Hide everything on 'combined' except test name, results for each browser, and test group, Set column widths, tweak titles, apply conditional formatting. +# $excel = Open-ExcelPackage $RunParameters.XLFile +# $ws = $excel.combined +# 2..$ws.Dimension.end.Column | ForEach-Object { +# if ($ws.Cells[1, $_].value -notmatch '^Name|Result$|PS\dGroup$') { +# Set-ExcelColumn -Worksheet $ws -Column $_ -Hid +# } +# elseif ($ws.Cells[1, $_].value -match 'Result$' ) { +# Set-ExcelColumn -Worksheet $ws -Column $_ -Width 17 +# Set-ExcelRange $ws.Cells[1, $_] -WrapText +# } +# if ($ws.cells[1, $_].value -match 'PS\dGroup$') { +# Set-ExcelRange $ws.Cells[1, $_] -WrapText -Value 'Group' +# } +# if ($ws.cells[1, $_].value -match '^Name|PS\dGroup$' -and ($ws.Column($_).Width -gt 80)) { +# $ws.Column($_).Width = 80 +# } +# } +# Set-ExcelRow -Worksheet $ws -Height 28.5 +# $cfRange = [OfficeOpenXml.ExcelAddress]::new(2, 3, $ws.Dimension.end.Row, (3 * $wslist.count - 2)).Address +# Add-ConditionalFormatting -WorkSheet $ws -range $cfRange -RuleType ContainsText -ConditionValue "Failure" -BackgroundPattern None -ForegroundColor Red -Bold +# Add-ConditionalFormatting -WorkSheet $ws -range $cfRange -RuleType ContainsText -ConditionValue "Success" -BackgroundPattern None -ForeGroundColor Green +# Close-ExcelPackage $excel diff --git a/CI/Pester-To-XLSx.ps1 b/CI/Pester-To-XLSx.ps1 new file mode 100644 index 0000000..2939843 --- /dev/null +++ b/CI/Pester-To-XLSx.ps1 @@ -0,0 +1,145 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSPossibleIncorrectComparisonWithNull', '', Justification = 'Intentional use to select non null array items')] +[CmdletBinding(DefaultParameterSetName = 'Default')] +param( + [Parameter(Position = 0)] + [string]$XLFile, + + [Parameter(ParameterSetName = 'Default', Position = 1)] + [String]$Path = '.', + + [Parameter(ParameterSetName = 'Existing', Mandatory = $true)] + [switch] + $UseExisting, + + [Parameter(ParameterSetName = 'Default', Position = 2)] + [Parameter(ParameterSetName = 'Existing', Position = 2, Mandatory = $true)] + [string]$OutputFile, + + [Parameter(ParameterSetName = 'Default')] + [Alias("Name")] + [string[]]$TestName, + + [Parameter(ParameterSetName = 'Default')] + [switch]$EnableExit, + + [Parameter(ParameterSetName = 'Default')] + [Alias('Tags')] + [string[]]$Tag, + [string[]]$ExcludeTag, + + [Parameter(ParameterSetName = 'Default')] + [switch]$Strict, + + [string]$WorkSheetName = 'PesterResults', + [switch]$append, + [switch]$Show +) + +$InvokePesterParams = $PSBoundParameters + +if ($InvokePesterParams['XLFile']) { $InvokePesterParams.Remove('XLFile') } +else { $XLFile = $InvokePesterParams['OutputFile'] -replace '.xml$', '.xlsx' } +if (-not $UseExisting) { + $InvokePesterParams.Remove('Append') | Out-Null + $InvokePesterParams.Remove('UseExisting') | Out-Null + $InvokePesterParams.Remove('Show') | Out-Null + $InvokePesterParams.Remove('WorkSheetName') | Out-Null + $InvokePesterParams.Remove('OutputFile') | Out-Null + Set-Location $env:ModulePath + Invoke-Pester @InvokePesterParams -CI -Output Detailed -ErrorAction Continue +} + +# if (-not (Test-Path -Path $InvokePesterParams['OutputFile'])) { +# throw "Could not output file $($InvokePesterParams['OutputFile'])"; return +# } + +$resultXML = ([xml](Get-Content -Path (Join-Path $env:ModulePath 'testResults.xml'))).'test-results' +$startDate = [datetime]$resultXML.date +$startTime = $resultXML.time +$machine = $resultXML.environment.'machine-name' +$user = $resultXML.environment.'user-domain' + '\' + $resultXML.environment.user +$os = $resultXML.environment.platform -replace '\|.*$', " $($resultXML.environment.'os-version')" +<#hierarchy goes + root, [date], start [time], [Name] (always "Pester"), test results broken down as [total],[errors],[failures],[not-run] etc. + Environment (user & machine info) + Culture-Info (current, and currentUi culture) + Test-Suite [name] = "Pester" [result], [time] to execute, etc. + Results + Test-Suite [name] = filename,[result], [Time] to Execute etc + Results + Test-Suite [Name] = Describe block Name, [result], [Time] to execute etc.. + Results + Test-Suite [Name] = Context block name [result], [Time] to execute etc. + Results + Test-Case [name] = Describe.Context.It block names [description]= it block name, result], [Time] to execute etc + or if the tests are parameterized + Test suite [description] - name in the the it block with not filled in + Results + Test-case [description] - name as rendered for display with filled in +#> +$testResults = foreach ($test in $resultXML.'test-suite'.results.'test-suite') { + $testPs1File = $test.name + #Test if there are context blocks in the hierarchy OR if we go straight from Describe to test-case + if ($test.results.'test-suite'.results.'test-suite' -ne $null) { + foreach ($suite in $test.results.'test-suite') { + $Describe = $suite.description + foreach ($subsuite in $suite.results.'test-suite') { + $Context = $subsuite.description + if ($subsuite.results.'test-suite'.results.'test-case') { + $testCases = $subsuite.results.'test-suite'.results.'test-case' + } + else { $testCases = $subsuite.results.'test-case' } + $testCases | ForEach-Object { + New-Object -TypeName psobject -Property ([ordered]@{ + Machine = $machine ; OS = $os + Date = $startDate ; Time = $startTime + Executed = $(if ($_.executed -eq 'True') { 1 }) + Success = $(if ($_.success -eq 'True') { 1 }) + Duration = $_.time + File = $testPs1File; Group = $Describe + SubGroup = $Context ; Name = ($_.Description -replace '\s{2,}', ' ') + Result = $_.result ; FullDesc = '=Group&" "&SubGroup&" "&Name' + }) + } + } + } + } + else { + $test.results.'test-suite' | ForEach-Object { + $Describe = $_.description + $_.results.'test-case' | ForEach-Object { + New-Object -TypeName psobject -Property ([ordered]@{ + Machine = $machine ; OS = $os + Date = $startDate ; Time = $startTime + Executed = $(if ($_.executed -eq 'True') { 1 }) + Success = $(if ($_.success -eq 'True') { 1 }) + Duration = $_.time + File = $testPs1File; Group = $Describe + SubGroup = $null ; Name = ($_.Description -replace '\s{2,}', ' ') + Result = $_.result ; FullDesc = '=Group&" "&Test' + }) + } + } + } +} +if (-not $testResults) { Write-Warning 'No Results found' ; return } +$clearSheet = -not $Append +$excel = $testResults | Export-Excel -Path $xlFile -WorkSheetname $WorkSheetName -ClearSheet:$clearSheet -Append:$append -PassThru -BoldTopRow -FreezeTopRow -AutoSize -AutoFilter -AutoNameRange +$ws = $excel.Workbook.Worksheets[$WorkSheetName] +<# Worksheet should look like .. + |A |B |C D |E |F |G |H |I |J |K |L |M + 1|Machine |OS |Date Time |Executed |Success |Duration |File |Group |SubGroup |Name |Result |FullDescription + 2|Flatfish |Name_Version |[run started] |Boolean |Boolean |In seconds |xx.ps1 |Describe |Context |It |Success |Desc_Context_It +#> + +#Display Date as a date, not a date time +Set-Column -Worksheet $ws -Column 3 -NumberFormat 'Short Date' # -AutoSize + +#Hide columns E to J (Executed, Success, Duration, File, Group and Subgroup) +(5..10) | ForEach-Object { Set-ExcelColumn -Worksheet $ws -Column $_ -Hide } + +#Use conditional formatting to make Failures red, and Successes green (skipped remains black ) ... and save +$endRow = $ws.Dimension.End.Row +Add-ConditionalFormatting -WorkSheet $ws -range "L2:L$endrow" -RuleType ContainsText -ConditionValue "Failure" -BackgroundPattern None -ForegroundColor Red -Bold +Add-ConditionalFormatting -WorkSheet $ws -range "L2:L$endRow" -RuleType ContainsText -ConditionValue "Success" -BackgroundPattern None -ForeGroundColor Green +Close-ExcelPackage -ExcelPackage $excel -Show:$show diff --git a/CI/RunTest.yml b/CI/RunTest.yml new file mode 100644 index 0000000..3097588 --- /dev/null +++ b/CI/RunTest.yml @@ -0,0 +1,54 @@ +# https://aka.ms/yaml + +parameters: + - name: Browser + type: string + values: + - Chrome + - Edge + - Firefox + - InternetExplorer + - MSEdge + - name: OS + type: string + default: ubuntu + values: + - ubuntu + - windows + - name: Stack + type: string + default: pwsh + values: + - powershell + - pwsh + +jobs: + - job: "${{ parameters.OS }}_${{ parameters.Browser }}_${{ parameters.Stack }}" + displayName: "${{ parameters.Browser }} - ${{ parameters.OS }} (${{ parameters.Stack }})" + pool: + vmImage: "${{ parameters.OS }}-latest" + steps: + - checkout: none + - task: DownloadPipelineArtifact@2 + inputs: + artifactName: "dependencies_pwsh" + #artifactName: "dependencies_${{ parameters.Stack }}" + - task: DownloadPipelineArtifact@2 + inputs: + artifactName: "checkout" + - ${{ if eq(parameters.Stack, 'Powershell') }}: + - powershell: "$(Pipeline.Workspace)/CI/CI.ps1 -ModulePath '$(Pipeline.Workspace)' -browserlist ${{ parameters.Browser }}" + displayName: "Run ${{ parameters.Browser }} Test on ${{ parameters.OS }} (ps)" + - ${{ if eq(parameters.Stack, 'pwsh') }}: + - pwsh: "$(Pipeline.Workspace)/CI/CI.ps1 -ModulePath '$(Pipeline.Workspace)' -browserlist ${{ parameters.Browser }}" + displayName: "Run ${{ parameters.Browser }} Test on ${{ parameters.OS }} (pwsh)" + - task: PublishPipelineArtifact@1 + inputs: + targetPath: "$(Build.ArtifactStagingDirectory)/results" + artifact: "${{ parameters.OS }} - ${{ parameters.Browser }} - ${{ parameters.Stack }} Results" + - task: PublishTestResults@2 + condition: succeededOrFailed() + inputs: + testResultsFormat: "NUnit" + testResultsFiles: "$(Pipeline.Workspace)/testResults.xml" + failTaskOnFailedTests: true diff --git a/CI/pipeline.yml b/CI/pipeline.yml new file mode 100644 index 0000000..7b036bc --- /dev/null +++ b/CI/pipeline.yml @@ -0,0 +1,113 @@ +# https://aka.ms/yaml + +trigger: + branches: + include: + - "*" + # - master + # - releases/* + paths: + exclude: + - additions.md + - ChangeLog.Txt + - README.md + +stages: + - stage: Checkout + displayName: "Checkout and dependencies" + jobs: + # - job: "Savedependencies" + # displayName: "Save dependencies" + # pool: + # vmImage: "windows-latest" + # steps: + # - checkout: none + # - powershell: | + # New-Item -ItemType Directory -Path './Modules' + # $Params = @{Path = './Modules';Repository = 'PSGallery'} + # Save-Module -Name Pester -RequiredVersion 4.10.1 @Params + # Save-Module -Name ImportExcel -RequiredVersion 7.1.1 @Params + # displayName: "Upload Powershell dependencies to pipeline" + # - task: CopyFiles@2 + # inputs: + # SourceFolder: $(Build.SourcesDirectory) + # TargetFolder: $(Build.ArtifactStagingDirectory) + # - task: PublishPipelineArtifact@1 + # inputs: + # TargetPath: $(Build.ArtifactStagingDirectory) + # artifact: dependencies_powershell + - job: "SaveCoreDependencies" + displayName: "Save core dependencies" + pool: + vmImage: "ubuntu-latest" + steps: + - checkout: none + - pwsh: | + New-Item -ItemType Directory -Path './Modules' + $Params = @{Path = './Modules';Repository = 'PSGallery'} + Save-Module -Name Pester -RequiredVersion 5.0.3 @Params + Save-Module -Name ImportExcel -RequiredVersion 7.1.1 @Params + displayName: "Upload pwsh dependencies to pipeline" + - task: CopyFiles@2 + inputs: + SourceFolder: $(Build.SourcesDirectory) + TargetFolder: $(Build.ArtifactStagingDirectory) + - task: PublishPipelineArtifact@1 + inputs: + TargetPath: $(Build.ArtifactStagingDirectory) + artifact: dependencies_pwsh + - job: "Checkout" + pool: + vmImage: "ubuntu-latest" + steps: + - checkout: self + - task: CopyFiles@2 + inputs: + SourceFolder: $(Build.SourcesDirectory) + TargetFolder: $(Build.ArtifactStagingDirectory) + - task: PublishPipelineArtifact@1 + inputs: + TargetPath: $(Build.ArtifactStagingDirectory) + artifact: checkout + + - stage: Tests + jobs: + - template: RunTest.yml + parameters: + Browser: Chrome + - template: RunTest.yml + parameters: + Browser: Firefox + - template: RunTest.yml + parameters: + Browser: Chrome + OS: windows + - template: RunTest.yml + parameters: + Browser: Firefox + OS: windows + - template: RunTest.yml + parameters: + Browser: Chrome + OS: windows + Stack: powershell + - template: RunTest.yml + parameters: + Browser: Firefox + OS: windows + Stack: powershell + - template: RunTest.yml + parameters: + Browser: InternetExplorer + OS: windows + Stack: powershell + # - template: RunTest.yml + # parameters: + # Browser: Edge + # OS: windows + # Stack: powershell + # - template: RunTest.yml + # parameters: + # Browser: MSEdge + # OS: windows + # Stack: powershell diff --git a/ChangeLog.md b/ChangeLog.md new file mode 100644 index 0000000..011923f --- /dev/null +++ b/ChangeLog.md @@ -0,0 +1,436 @@ + +# 4.0.0-preview3 +## Added / Modified +- Get-SeElementAttribute now return a hashtable instead of a pscustom object when multiple attributes are queried + + + +## Fixes +- Get-SeElement now make use of Get-SeElementAttribute internally to query attributes. +- Get-SeElement error when using filter / attribute +- Update-SeDriver default path typo (#206) +- New-SeScreenshot documentation update (#200) +- Casing issue with Types.ps1xml filename (#203) + +# 4.0.0-preview2 (Prerelease) +## Added / Modified +- Get-SeElement -Filter; Add a new parameter to do additional filtering before returning. This is equivalent to doing a Where afterward but with the Get-SeElement error management logic applied before returning. (#192) +- AcceptInsecureCertificates switch added to Start-SeDriver / New-SeDriverOptions (Supported by: Chrome, Firefox, Edge) (#189) +- Chrome web drivers assemblies updated to latest version + +## Fixes +- Starting Edge browser broken (#188,#195) +- custom driver options, when specified, are not used (#191,#193) +- Processes management internal logic error (#190) +- Get-SeInput not working properly with -Single switch (#186) +- Screenshots fail when attempting to screenshot the page (#187) + +# 4.0.0-preview1 (Prerelease) +Note: V4 have an enormous amount of breakchanges. Most of the cmdlet have been rewriten in a way or another. +Important changes includes, but are not limited to: +- Removing all aliases and duplicate functions +- Removal of -AsDefaultDriver and $Driver parameter in favor of an internal implementation which make the last driver started the active driver. Should you need to switch between 1 or more driver, this can be accomplished through the Switch-SeDriver cmdlet. + + +## Added +- Convert-toSeSelenium to convert IDE projects to Selenium-Powershell script +- Update-SeDriver to download the latest driver (Support only Chrome currently) +- Support for UserAgent in Start-SeDriver (#91) +- New view for IwebDriver (#111). IWebDriver will now display as a table in the console by default instead of a list. +- Get-SeElement - New view. Elements will now be returned in a table view to show the essential only. This make it significantly easier to deal with elements in the console interactively (#115) +- Get-SeElement - Bychained support. The cmdlet will now drilldown when multiple by / value are provided to allow for instance the selection of links in a div containing a specific classname. This is an alternative for those less savy with Xpath (#116) +- Get-SeHtml - Allow the retrieval of the html of an element (or driver is no element is provided). Essentially a wrapper around $Element.GetAttribute('xxHTML') (xx: Inner /Outer) (#118) +- New-SeDriverService - Allow the creation of a driver service to be used later on with Start-SeDriver. Only useful if you need to do change to the service parameters native object before starting the driver (#119) +- Invoke-SeMouseAction - Support for interactions (#122) +- Wait-SeDriver / Wait-SeElement expliciti wait support (#125) +- Get-SeElement -Attributes. Allow getting specific attributes (or all using *) to the elements to be returned. Attributes will be available in an Attributes string dictionary attached to each elements. (#133) +- Position / Size parameter for Start-SeDriver. Allow starting the driver at a specified position and size. If no command line available (or not implemented), the driver will start with the default settings and the be moved. (#134) +- Get-SeElement -Single switch added. Define the expectaction that only one element should be returned (#144) +- Get/Set-SeDriverTimeout - Allow changing driver timeouts easily (#150) +- Invoke-SeJavascript - A wrapper around $Driver.ExecuteScript (#151) +- Get-SeFrame, wrapper around Get-SeElement to show iframe along with their name / id in a convenient view (#159) +- New-SeWindow / Remove-SeWindow cmdlet added to complement the existing Get/Switch (#170) +- Get-SeInput (#178) - A wrapper around Get-SeElement to get input element. + + + +## Changed +- AsDefaultDriver implementation changed. Instead, Start-SeDriver automatically make the started driver the default. (#93) +- Driver parameter was removed on most cmdleet. It is now expected to use the Switch-SeDriver cmdlet to change the active driver if multiple are open. +- Start-SeChrome and other have been removed in favor of Start-SeDriver -Browser Chrome (#100) +- #98 Removed duplicate functions that performed the same thing or overlapped significantly +- Removed all the aliases everywhere on all the parameter / functions in favor of a more rigid way of writing things (#99) +- Standardize parameters. Some parameters had different names to mean the same thing (#100) +- Revamp Get-SeSelectionOption. The cmdlet have been separated in 3 cmdlet Get/Clear/Set -SeSelectValue. The get cmdlet will also now return the Text & Value of the selected element instead of the text only. (#112) +- Set-SeUrl now have a -Depth parameter to navigate forward or back x times (#124) +- Get-SeElement now returns visible elements by default. To view hidden elements, the All switch parameter need to be used (#126) +- Start-SeDriver -Quiet parameter removal. Quiet is now the default. This remove the extra Selenium verbose and resolves an issue with Driver not being usable in jobs. (#127) +- Get-SeElement now write an error if no element are returned. (#135) +- cmdlet that expect urls will now accept urls without protocol defined. Assumptions in these cases is that the url is https thus google.ca will be treated as https://www.google.ca (#153) +- Get-SeElementAttribute - Accept multiple values and wildcard to load all attributes (#161) +- Get-SeElement - support for multiple classname (#160) +- Get-SeElementCssValue - support for multiple values / wildcard character (#162) +- Sleep / Timeout parameters type changed from int to double (Still seconds, but provide more granularity) +- Invoke-SeScreenshot - support for Element screenshot. You can now easily produce a screenshot of a specific element instead of the whole page. (#168) + + + +## Bugfixes +- Get-SeElement no longer support splatting (#82) +- Getck driver abysmal performance (#113). Gecko service need to be configured to use localhost ::1. Otherwise, it take significantly more time to do everything with it (#113) +- Get-SeElement with Timeout return only the first element instead of the collection (#139) +- Implcit-Wait - Default reduced to 0.3 seconds instead of 10 seconds. One of the problem of implicit wait is that some operation will wait 100% of the defined implicit wait before performing an action. (#146) +- Implicit / Explicit wait management. Some cmdlet (old an new) uses explicit wait. Explicit wait and Implicit wait should not be mixed together. Therefore, when an explicit wait is used, implicit wait (if present) get temporary disabled(#149) + + +# 3.1.0 - Unreleased + +## Added +- Added -IgnoreProtectedModeSettings to Start-SeInternetExplorer - https://github.com/adamdriscoll/selenium-powershell/issues/79 - Thanks, @MysticRyuujin! + +- Added Markdown documentation (See Help subfolder) for all the cmdlets (PlatyPS is used behind the scene to maintain it) +- Added MAML embedded help that can be accessed through `Get-Help`(eg: `Get-Help Start-SeChrome -Examples`) +- Added Get-SeUrl / Pop-SeUrl / Push-SeUrl / Set-SeUrl (Thanks @vexx32) + +## Changed + - Converted monolythic module into a scaffolded module through a Plaster template. Module will now have a debug version and a compiled version that need to be built with Invoke-Build. See the Debug folder for additional informations on how to debug. + + - Open-SeUrl removed in favor of Set-SeUrl + - Send-SeKeys won't return an exception if you send $null or empty strings. + - Stop-SeDriver won't throw exceptions anymore when celled multiple times on a driver already closed. + +# 3.0.0 - 3/31/2020 + +## Changed + +- Fixed issue with importing module in PSv5.1 - https://github.com/adamdriscoll/selenium-powershell/issues/69 +- Updated Chrome drivers + +# 3.0.0-beta2 - 1/29/2020 + +## Added + +- Added Get-SeElementCssValue + +# 3.0.0-beta1 - 1/29/2020 + +## Added + +# General +## Start a Browser Driver for the browser of your choice (Chrome/Firefox/Edge/InternetExplorer) +```powershell +#Either: store the driver in your own variable +$Driver = Start-SeChrome + +#OR save it to $global:SeDriver +Start-SeChrome -AsDefaultDriver # alias Chrome +Start-SeFirefox -AsDefaultDriver # alias Firefox +Start-SeEdge -AsDefaultDriver # alias MsEdge +Start-SeNewEdge -AsDefaultDriver # alias CrEdge / NewEdge +Start-SeInternetExplorer -AsDefaultDriver # alias IE / InternetExplorer + +#OR use a shortcut which takes a browser name and sets it as the default. +SeOpen -In Chrome +``` +in the last case, -in can come an environment variable, to run the same script _n_ times with _n_ different browsers + +## Navigate to a page +```powershell +#Use a saved driver and the original function name +Enter-SeUrl https://www.poshud.com -Driver $Driver + +#Use the default driver and the new funtion name +Open-SeUrl https://www.poshud.com #alias SeNavigate + +#or Start the driver and navigate in one +Start-SeChrome -AsDefaultDriver -StartURL https://www.poshud.com + +#or using SeOpen +SeOpen -URL https://www.poshud.com -In Chrome +``` + +## Find an Element on the page +```powershell +#Using the saved driver and the old syntax +$Element = Find-SeElement -Driver $Driver -ClassName 'center-align' + +#Using the default driver and the new syntax +$Element = Get-SeElement -By ClassName 'center-align' #alias SeElement + +#xpath is selected by default - you can specify a timeout to wait for the element to appear. +$xpath = '/html/body/div[1]/div/main/div/div[2]/div[3]/div[1]/div/div/div[2]/a' +$Element = Get-SeElement $xpath -Timeout 10 + +#In a Pester Test you can check the element is present with +SeElement $xpath | should not beNullOrEmpty +#or +SeShouldHave $xpath +``` +_SeElement_ and _Find-SeElement_ are aliases for Get-SeElement. + +## Click on an Element/Button +```powershell +#send to a saved element with old syntax +Invoke-SeClick -Element $Element + +#Pipe an element into the command using new syntax +Get-SeElement $Xpath | Send-SeClick -SleepSeconds 2 #alias SeClick + +#in a Pester Test you can get the element, click and confirm a element was found +SeElement $xPath | SeClick -sleep 2 -passthru | should not beNullOrEmpty +``` +_Invove-SeClick_ and _Send-SeClick_ are almost interchangable, _SeClick_ is an alias for the latter + +## Send Keystrokes + +```powershell +#using a saved element +$Element = Find-SeElement -Driver $Driver -Id "txtEmail" +Send-SeKeys -Element $Element -Keys "adam@poshtools.com" + +#or using the pipeline +seElement -by ID "txtEmail" | Send-SeKeys -Keys "adam@poshtools.com" + +#in a Pester Test you can get the element, sendkeys and confirm a element was found +seElement -by ID "txtEmail" | SeType "adam@poshtools.com" -passthru | should not beNullOrEmpty +``` +_setype_ is a wrapper for _Send-SeKeys_ to be more Pester-friendly + +# using pester +### Navigating to a page (SeNavigate) + +```powershell + Enter-SeUrl -Url "https://www.powershellgallery.com/" -driver $Global:SeDriver + #Enter-SeUrl has an alias of SeNavigate, and will assume the driver is $Global:SeDriver, and take URL by position giving + SeNavigate https://www.powershellgallery.com/ +``` +### Checking the page url and title (SeShouldHave) + +```powershell + #knowing about the driver we could use it with a standard pester command + $Global:SeDriver.Url | should be "https://www.powershellgallery.com/" + + #Or we could use SeShouldHave. The full, explicit form looks like this + SeShouldHave -URL -Operator eq -Value "https://www.powershellgallery.com/" + #which can be shorted by passing Operator and Value parameters by position; + #Operator will tab-complete contains, match, notlike etc and will transform other names; match and notmatch are regular expressions + SeShouldHave -URL equalTo "https://www.powershellgallery.com/" + SeShouldHave -Title match "PowerShell\s+Gallery" +``` +The primary job of _SeShouldHave_ is to work like pesters _should_ and succeed silently or fail the test by throwing an error. + +### Finding and using an element: (SeElement) +```powershell + #we can shorten the command :Get-SeElement -By XPath -Selection '//*[@id="search"]' + #first with an alias and then -by Xpath is assumed and Selection can be passed in the first position to become + # SeElement '//*[@id="search"]' | SeType -ClearFirst "selenium{{Enter}}" + #This will not report a failure if the element was not found so + SeElement '//*[@id="search"]' | SeType -ClearFirst "selenium{{Enter}}" -PassThru | should not beNullorEmpty +``` +This is also possible with SeShouldHave.. see below + +### Checking elements: (SeShouldHave) +```powershell + $linkpath = '//*[@id="skippedToContent"]/section/div[1]/div[2]/div[2]/section[1]/div/table/tbody/tr/td[1]/div/div[2]/header/div[1]/h1/a' + #SeShouldHave can be written explictly like this + SeShouldHave -Selection $linkpath -By XPath -With Text -Operator match 'selenium' + #-by Xpath is assumed and the other parameters can be passed by position. Operators will tab complete, and convert "matching" or "matches" to match etc + SeShouldHave $linkpath Text matching 'selenium' +``` +The `-with` parameter can be 'Text', 'Displayed', 'Enabled', 'TagName', 'X', 'Y', 'Width', 'Height', 'Choice' or _the name of an attribute_, like 'href'. + If `-with` is not specified only _the presence_ of the page element is checked. + If `-PassThru` is specified, matching elements will be sent to the pipeline. (`-Passthru` can't be used when checking the page URL or tile, only with elements on the page). +```powershell + SeShouldHave $linkpath -PassThru | SeClick +``` +### Checking Multiple elements +The selection parameter can take multiple values; in the following command it is specified by position (and assumed to be one or more Xpaths) +```powershell + SeShouldHave '//*[@id="version-history"]/table/tbody[1]/tr[1]/ td[1]/a/b' , + '//*[@id="skippedToContent"]/section/div/aside/ul[2]/li[1]/a' +``` +When multiple elements are found from the selection criteria, and '-With' is specified the test will pass _any_ element passess - in other words, all elements do not need to pass. +```powershell + #The following counts 8 elements + SeNavigate 'https://www.google.com/ncr' + SeShouldHave -by TagName input -PassThru | measure + #The following command rejects 7 of these 8, without error, and passes the one with a title attribute of 'search' to another command + SeShouldHave -by TagName input -With Title eq Search -PassThru | SeType 'PowerShell-Selenium' +``` + +### Selecting frames (SeFrame) +on a page which uses frames it is necessary to specify which one containst the data +```powershell + seNavigate 'https://www.w3schools.com/js/tryit.asp?filename=tryjs_alert' + sleep -Seconds 5 #can go too fast for frames + SeFrame 1 +``` + +### Checking alerts (SeShouldHave, SeAccept, SeDismiss) +As well as checking the page URL, and page title. _SeShouldHave_ Supports -Alert and -NoAlert +```powershell + #in Frame 1 on 'https://www.w3schools.com/js/tryit.asp?filename=tryjs_alert' this will produce an alert + SeElement "/html/body/button" -Timeout 10 | SeClick -SleepSeconds 2 + #and this will check for it. + SeShouldHave -Alert match "box" + #Usually you will want to accept or dismiss the alert + SeShouldHave -Alert -PassThru | SeDismiss +``` +### Working with select/option "dropdown" controls (SeShouldHave, SeSelection) +```powershell + #This will go to a page with a dropdown box + SeNavigate 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_elem_select' + sleep -Seconds 5 #can go too fast for frames + SeFrame 1 + $dropDown = SeShouldHave -By Name "cars" -With choice contains "volvo" -PassThru +``` +In the code above, SeShouldHave finds the dropdown box which is named "Cars", and does a check to confirm one of the choices is Volvo, and assigns the result to a variable. This can be used with SeSelection (alias for Get-SeSelectionOption) to test or set options in the dropdown box. An option can be selected (and in the case of mult-select boxes, deselected) by its index, value or [partof] its display text. And the -GetSelected / -GetAllSelected options can be included in a set operation to (or used alone) to return the selected text. +```powershell + $dropdown | SeSelection -IsMultiSelect | should be $false + $dropdown | SeSelection -GetSelected | should be 'Volvo' + $dropdown | SeSelection -ListOptionText | should not contain "Ferrari" + #not the selections are case sensitive. The value in this case is all lower case, the display text has initial caps. + $dropdown | SeSelection -ByValue 'audi' -GetSelected | should be 'Audi' +``` + +DLL loading is now from the PSD1 file instead of the PSM1 file. +Now use presence of $AssembliesPath to judge "IsMacOS" -or "IsLinux" + +Send-SeKeys + -Element and -Keys parameters are both mandatory + Selenium-keys are now cached in a script-scoped variable for performance. (Get-SEKeys can be dropped) + Added -PassThru + + +Valdate-URL + Function Renamed to validateUrl (private helper function does not need to use verb-noun naming and "validate" verb upsets script analyzer) + Added the old name back as an alias (which _is_ allowed. ) + Moved functionality into a validation class which so URLs are validated before enering functions + +Checks for valid webdriver also moved to a validation class. + +Get-SeCookie & Invoke-SeScreenshot + In line with other functions, -Driver parameter is renamed -Target, with alias "Driver", and will come from $Global:SeDriver + and throws an error if no driver is passed or found from Global var + +Start-SeFirefox & Start-SeChrome + Added aliases "SeChrome" and "SeFirefox" - user can now write in a sort of DSL "SeCHROME $URL -asDefault" etc. + Made -StartUrl the first parameter and use a parameter-validation class to check it. + Now call the .Navigate method directly instead of via Enter-SeURL if -StartURL is specified + Now use parameter-sets to avoid the conflict between Minimized/Maximized/FullScreen/Headless, + Added parameter aliases so "Incognito" works with Firefox and "PrivateBrowsing" works with Chrome + Now trap a failure to return driver, and simplified the subsequent if statements + Set ImplicitWait to 10 seconds + Added Parameter -AsDefaultDriver which sets $Global:SeDriver, instead of returning the driver + Added Parameter -Quiet to run tests without web driver prattle. + Allow AzureDevops environment vars (GeckoWebDriver / ChromeWebDriver) or commandline + parameter -WebDriverDirectory to specify source of Webdriver. + Removed a possible bug with piped input, by returning the driver in the process block instead of the end block + +Start-SeInternetExplorer + Added Aliases "SeInternetExplorer" & "SeIE" and parameter -StartUrl + Plus -AsDefaultDriver which sets $Global:SeDriver, instead of returning the driver, and -Quiet to run tests + without web driver prattle. + Allow AzureDevops environment vars or commandline parameter -WebDriverDirectory to specify source of Webdriver + Set ImplicitWait to 10 seconds + +Start-SeEdge + Added Aliases "MSEdge" & "LegacyEdge", and parameters -StartUrl, -Maximized, -Minimized, FullScreen + and -PrivateBrowsing (alias Incognito) + Plus -AsDefaultDriver which sets $Global:SeDriver, instead of returning the driver, and -Quiet to run tests + without web driver prattle. + Added message if driver load errors - Webdriver is now added as a windows Feature and will be found from windows\system32, + which is on the path. Removed old driver and SHA file. + Set ImplicitWait to 10 seconds + +Stop-SeDriver + Updated to handle the default drive being in $global:SeDriver. + +Start-SeNewEdge **New Function** with alias, credge to support Chromium based edge. + Also added V79 webdriver. Specifying V80. V81 from an ENV variable (EdgeWebDriver), or via command line requires + it to be in the same directory as MSEdge.exe and -inPrivate, -headless, and -binaryLocation options don't work. + +Start-SeRemote **New Function** + Connects to remote driver by URL and requested capablites tested with testingbot.com + + Start-SeChrome Start-SeEdge Start-SeFirefox Start-SeInternetExplorer Start-SeNewEdge Start-SeRemote + AsDefaultDriver X X X X X X + Fullscreen X X X X X + Headless X X X X X + ImplicitWait X X X X X X + Maximized X X X X X + Minimized X X X X X + Incognito X As alias As alias As alias As alias + PrivateBrowsing As alias X X X X + Quiet X X X X X + StartURL X X X X X X + WebDriverDirectory X X X X + or Env var ChromeWebDriver - GeckoWebDriver IEWebDriver EdgeWebDriver + BinaryPath X X + ProfileDirectoryPath X X + DefaultDownloadPath X X X + Arguments X X + +SeOpen **New Function** + Takes -In (name of browser) and opens that browser and optional naviagates to destination in -URL + The browser is opened as with -AsDefault and other options passed in -Options. + If the browser name is omitted the function will look for $env:DefaultBrowser. + Mainly for Pester/DSL freindliness - by changing the environment variable a different browser can be used in different test runs + +Send-SeClick **New Function** (with alias SeClick) {replacement for Invoke-SeClick} + Element can be passed by position (first) + -JavaScriptClick can be abreviated -JS + Driver is ignored (element.wrapedDriver used instead) + Added -SleepSeconds and -PassThru parameters + +New-SeScreenShot: **New Function** with alias SeScreenshot. Merges functionality of Invoke-ScreenShot and SaveSeScreenShot + Can pass -Path, + -Passthru (Alias PT) + -Path & -Passthru + or -AsBase64 + "Target" with alias "Driver", can come from $Global:SeDriver + and throws an error if no driver passed or found from Global var + +Open-SeURL *New Function** with alias SeNavigate + Url is first on the commandline and mandatory + Driver is renamed target, with alias "Driver", and will come from $Global:SeDriver + Throws an error if no driver passed or found from Global var + Made interoperable with Enter-SEURL via aliases + Back, forward and refresh are available via switches + Commented out Enter-SeURL and changed PSD1, + +Get-SeElement **New Function** with alias seElement + New -By parameter with possible values "CssSelector", "Name", "Id", "ClassName", "LinkText", "PartialLinkText", "TagName", "XPath" + combined with a "Selection" parameter which holds the value, replaces the 8 parameters with those names and parametersets. + Wait made optional; -Wait without -Timeout sets timeout to 30 , and -Timeout 5 works without -Wait + -Element and -Driver are merged as -Target which has aliases of 'Element' and 'Driver' + Made interoperable with Find-seElement by aliases + Commented out Find-seElement and updated PSD1. + +Switch-SeFrame **New Function** with alias SeFrame + Selects a frame. + +Clear-SeAlert **New Function** with aliases SeAccept, SeDissmiss + Accepts or dismisses an alert box so execution can continue + If called using the aliases selects Accept or dismiss. + +SeType **New Function** + More DSL friendly form of Send-SeKeys - takes piped element; keys is first parameter and supports + clearing the text box, submit and passthru, to allow element to be fetched and keys typed, and then + Pester to throw if element was not found. + +Get-SeSelectionOption **New Function** alias SeSelection + For setting and checking options in a dropdown lists. + +SeShouldHave **New Function** +Drives pester tests as a single command See examples for details, but allows things like + SeShouldHave -url -match 'packages\?q=selenium' + SeShouldHave -Selection $linkpath -By XPath -With Text -Operator Like -Value "*selenium*" + which can be shortened to + seShouldHave $linkpath text -Like "*selenium*" + +Added some new examples - showing DSL style in Pester. + +Reorder PSD file for easy reading & add file list. + +Create CI directory with files for doing a build / test pass is Azure devops. diff --git a/Classes/PointTransformAttribute.ps1 b/Classes/PointTransformAttribute.ps1 new file mode 100644 index 0000000..9e03635 --- /dev/null +++ b/Classes/PointTransformAttribute.ps1 @@ -0,0 +1,27 @@ +class PointTransformAttribute : System.Management.Automation.ArgumentTransformationAttribute { + # Implement the Transform() method + [object] Transform([System.Management.Automation.EngineIntrinsics]$engineIntrinsics, [object] $inputData) { + <# + The parameter value(s) are passed in here as $inputData. We aren't accepting array input + for our function, but it's good to make these fairly versatile where possible, so that + you can reuse them easily! + #> + $outputData = switch ($inputData) { + { $_ -is [PointTransformAttribute] } { $_ } + { $_ -is [int] } { [System.Drawing.Point]::new($_, $_) } + { $_ -is [string] -and (($_ -split '[,x]').count -eq 2) } { + $sp = $_ -split '[,x]' + [System.Drawing.Point]::new($sp[0], $sp[1]) + } + default { + # If we hit something we can't convert, throw an exception + throw [System.Management.Automation.ArgumentTransformationMetadataException]::new( + "Could not convert input '$_' to a valid Point object." + ) + } + } + + return $OutputData + } + +} \ No newline at end of file diff --git a/Classes/SeDriverConditionsCompleter.ps1 b/Classes/SeDriverConditionsCompleter.ps1 new file mode 100644 index 0000000..741ea6b --- /dev/null +++ b/Classes/SeDriverConditionsCompleter.ps1 @@ -0,0 +1,31 @@ +$Script:SeDriverConditions = @( + [PSCustomObject]@{Text = 'AlertState'; ValueType = [bool]; Tooltip = "A value indicating whether or not an alert should be displayed in order to meet this condition." } + [PSCustomObject]@{Text = 'ScriptBlock'; ValueType = [ScriptBlock]; Tooltip = "A scriptblock to be evaluated." } + [PSCustomObject]@{Text = 'TitleContains'; ValueType = [String]; Tooltip = "An expectation for checking that the title of a page contains a case-sensitive substring." } + [PSCustomObject]@{Text = 'TitleIs'; ValueType = [String]; Tooltip = "An expectation for checking the title of a page." } + [PSCustomObject]@{Text = 'UrlContains'; ValueType = [String]; Tooltip = "An expectation for the URL of the current page to be a specific URL." } + [PSCustomObject]@{Text = 'UrlMatches'; ValueType = [String]; Tooltip = "An expectation for the URL of the current page to be a specific URL." } + [PSCustomObject]@{Text = 'UrlToBe'; ValueType = [String]; Tooltip = "An expectation for the URL of the current page to be a specific URL." } +) + +class SeDriverConditionsCompleter : System.Management.Automation.IArgumentCompleter { + [System.Collections.Generic.IEnumerable[System.Management.Automation.CompletionResult]] CompleteArgument( + [string] $CommandName , + [string] $ParameterName, + [string] $WordToComplete, + [System.Management.Automation.Language.CommandAst] $CommandAst, + [system.Collections.IDictionary] $FakeBoundParameters + ) { + $wildcard = ("*" + $wordToComplete + "*") + $CompletionResults = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new() + + $Script:SeDriverConditions.where( { $_.Text -like $wildcard }) | + ForEach-Object { + $Valuetype = $_.ValueType + if ($null -eq $ValueType) { $Valuetype = 'None' } + $pvalue = [System.Management.Automation.CompletionResultType]::ParameterValue + $CompletionResults.Add(([System.Management.Automation.CompletionResult]::new($_.Text, $_.Text, $pvalue, "Value: $ValueType`n$($_.Tooltip)") ) ) + } + return $CompletionResults + } +} \ No newline at end of file diff --git a/Classes/SeDriverUserAgentCompleter.ps1 b/Classes/SeDriverUserAgentCompleter.ps1 new file mode 100644 index 0000000..501285d --- /dev/null +++ b/Classes/SeDriverUserAgentCompleter.ps1 @@ -0,0 +1,26 @@ +class SeDriverUserAgentCompleter : System.Management.Automation.IArgumentCompleter { + [System.Collections.Generic.IEnumerable[System.Management.Automation.CompletionResult]] CompleteArgument( + [string] $CommandName , + [string] $ParameterName, + [string] $WordToComplete, + [System.Management.Automation.Language.CommandAst] $CommandAst, + [system.Collections.IDictionary] $FakeBoundParameters + ) { + $CompletionResults = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new() + + $pvalue = [System.Management.Automation.CompletionResultType]::ParameterValue + + [System.Collections.Generic.List[PSObject]]$Predefined = + [Microsoft.PowerShell.Commands.PSUserAgent].GetProperties() | + Select-Object Name, @{n = 'UserAgent'; e = { [Microsoft.PowerShell.Commands.PSUserAgent]::$($_.Name) } } + + $Predefined.Add([PSCustomObject]@{Name = 'Android'; UserAgent = 'Android' }) + $Predefined.Add([PSCustomObject]@{Name = 'Iphone'; UserAgent = 'Iphone' }) + + $Predefined | + ForEach-Object { + $CompletionResults.Add(([System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, $pvalue, $_.UserAgent) ) ) + } + return $CompletionResults + } +} \ No newline at end of file diff --git a/Classes/SeDriverUserAgentTransformAttribute.ps1 b/Classes/SeDriverUserAgentTransformAttribute.ps1 new file mode 100644 index 0000000..cfb0b53 --- /dev/null +++ b/Classes/SeDriverUserAgentTransformAttribute.ps1 @@ -0,0 +1,25 @@ +class SeDriverUserAgentTransformAttribute : System.Management.Automation.ArgumentTransformationAttribute { + # Implement the Transform() method + [object] Transform([System.Management.Automation.EngineIntrinsics]$engineIntrinsics, [object] $inputData) { + <# + The parameter value(s) are passed in here as $inputData. We aren't accepting array input + for our function, but it's good to make these fairly versatile where possible, so that + you can reuse them easily! + #> + $outputData = switch ($inputData) { + { $_ -is [string] } { + $output = [Microsoft.PowerShell.Commands.PSUserAgent]::$_ + if ($null -ne $output) { $output } else { $_ } + } + default { + # If we hit something we can't convert, throw an exception + throw [System.Management.Automation.ArgumentTransformationMetadataException]::new( + "Only String attributes are supported." + ) + } + } + + return $OutputData + } + +} \ No newline at end of file diff --git a/Classes/SeElementsConditionsCompleter.ps1 b/Classes/SeElementsConditionsCompleter.ps1 new file mode 100644 index 0000000..bb7374e --- /dev/null +++ b/Classes/SeElementsConditionsCompleter.ps1 @@ -0,0 +1,39 @@ +$Script:SeElementsConditions = @( + [PSCustomObject]@{Text = 'ElementExists'; ValueType = $null; By_Element = 1; Tooltip = 'An expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible.' } + [PSCustomObject]@{Text = 'ElementIsVisible'; ValueType = $null; By_Element = 1; Tooltip = 'An expectation for checking that an element is present on the DOM of a page and visible. Visibility means that the element is not only displayed but also has a height and width that is greater than 0.' } + [PSCustomObject]@{Text = 'ElementToBeSelected'; ValueType = [bool]; By_Element = 0; Tooltip = 'An expectation for checking if the given element is selected.' } + [PSCustomObject]@{Text = 'InvisibilityOfElementLocated'; ValueType = [bool]; By_Element = 1; Tooltip = 'An expectation for checking that an element is either invisible or not present on the DOM.' } + [PSCustomObject]@{Text = 'ElementToBeClickable'; ValueType = $null; By_Element = 0; Tooltip = 'An expectation for checking an element is visible and enabled such that you can click it.' } + [PSCustomObject]@{Text = 'InvisibilityOfElementWithText'; ValueType = [string]; By_Element = 1; Tooltip = 'An expectation for checking that an element with text is either invisible or not present on the DOM.' } + [PSCustomObject]@{Text = 'PresenceOfAllElementsLocatedBy'; ValueType = $null; By_Element = 1; Tooltip = 'An expectation for checking that all elements present on the web page that match the locator.' } + [PSCustomObject]@{Text = 'TextToBePresentInElement'; ValueType = [string]; By_Element = 2; Tooltip = 'An expectation for checking if the given text is present in the specified element.' } + [PSCustomObject]@{Text = 'TextToBePresentInElementValue'; ValueType = [string]; By_Element = 0; Tooltip = 'An expectation for checking if the given text is present in the specified elements value attribute.' } + [PSCustomObject]@{Text = 'StalenessOf'; ValueType = $null; By_Element = 2; Tooltip = 'Wait until an element is no longer attached to the DOM.' } +) + +class SeElementsConditionsCompleter : System.Management.Automation.IArgumentCompleter { + [System.Collections.Generic.IEnumerable[System.Management.Automation.CompletionResult]] CompleteArgument( + [string] $CommandName , + [string] $ParameterName, + [string] $WordToComplete, + [System.Management.Automation.Language.CommandAst] $CommandAst, + [system.Collections.IDictionary] $FakeBoundParameters + ) { + $wildcard = ("*" + $wordToComplete + "*") + $CompletionResults = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new() + + $pvalue = [System.Management.Automation.CompletionResultType]::ParameterValue + $SearchBy = 0 + switch ($true) { + { $fakeBoundParameters.ContainsKey('By') } { $SearchBy = 1; break } + { $fakeBoundParameters.ContainsKey('Element') } { $SearchBy = 2; break } + } + $Script:SeElementsConditions.where( { $_.Text -like $wildcard -and $_.By_Element -in @(0, $SearchBy) }) | + ForEach-Object { + $Valuetype = $_.ValueType + if ($null -eq $ValueType) { $Valuetype = 'None' } + $CompletionResults.Add(([System.Management.Automation.CompletionResult]::new($_.Text, $_.Text, $pvalue, "Value: $ValueType`n$($_.Tooltip)") ) ) + } + return $CompletionResults + } +} \ No newline at end of file diff --git a/Classes/SeMouseActionCompleter.ps1 b/Classes/SeMouseActionCompleter.ps1 new file mode 100644 index 0000000..e9abdaa --- /dev/null +++ b/Classes/SeMouseActionCompleter.ps1 @@ -0,0 +1,29 @@ +class SeMouseActionCompleter : System.Management.Automation.IArgumentCompleter { + [System.Collections.Generic.IEnumerable[System.Management.Automation.CompletionResult]] CompleteArgument( + [string] $CommandName , + [string] $ParameterName, + [string] $WordToComplete, + [System.Management.Automation.Language.CommandAst] $CommandAst, + [system.Collections.IDictionary] $FakeBoundParameters + ) { + $wildcard = ("*" + $wordToComplete + "*") + $CompletionResults = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new() + + $pvalue = [System.Management.Automation.CompletionResultType]::ParameterValue + + $Script:SeMouseAction.where( { $_.Text -like $wildcard }) | + ForEach-Object { + $Valuetype = $_.ValueType + if ($null -eq $ValueType) { $Valuetype = 'None' } + $ElementRequired = 'N/A' + switch ($_.ElementRequired) { + $true { $ElementRequired = 'Required' } + $false { $ElementRequired = 'Optional' } + } + + + $CompletionResults.Add(([System.Management.Automation.CompletionResult]::new($_.Text, $_.Text, $pvalue, "Element: $ElementRequired`nValue: $ValueType`n$($_.Tooltip)") ) ) + } + return $CompletionResults + } +} \ No newline at end of file diff --git a/Classes/SeMouseClickActionCompleter.ps1 b/Classes/SeMouseClickActionCompleter.ps1 new file mode 100644 index 0000000..c141238 --- /dev/null +++ b/Classes/SeMouseClickActionCompleter.ps1 @@ -0,0 +1,31 @@ +$Script:SeMouseClickAction = @( + New-Condition -Text 'Click' -Tooltip 'Clicks the mouse on the specified element.' + New-Condition -Text 'Click_JS' -ElementRequired $true -Tooltip 'Clicks the mouse on the specified element using Javascript.' + New-Condition -Text 'ClickAndHold' -Tooltip 'Clicks and holds the mouse button down on the specified element.' + New-Condition -Text 'ContextClick' -Tooltip 'Right-clicks the mouse on the specified element.' + New-Condition -Text 'DoubleClick' -Tooltip 'Double-clicks the mouse on the specified element.' + New-Condition -Text 'Release' -Tooltip 'Releases the mouse button at the last known mouse coordinates or specified element.' +) + +class SeMouseClickActionCompleter : System.Management.Automation.IArgumentCompleter { + [System.Collections.Generic.IEnumerable[System.Management.Automation.CompletionResult]] CompleteArgument( + [string] $CommandName , + [string] $ParameterName, + [string] $WordToComplete, + [System.Management.Automation.Language.CommandAst] $CommandAst, + [system.Collections.IDictionary] $FakeBoundParameters + ) { + $wildcard = ("*" + $wordToComplete + "*") + $CompletionResults = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new() + $pvalue = [System.Management.Automation.CompletionResultType]::ParameterValue + + + $Script:SeMouseClickAction.where( { $_.Text -like $wildcard }) | + ForEach-Object { + $Valuetype = $_.ValueType + if ($null -eq $ValueType) { $Valuetype = 'None' } + $CompletionResults.Add(([System.Management.Automation.CompletionResult]::new($_.Text, $_.Text, $pvalue, $_.Tooltip) ) ) + } + return $CompletionResults + } +} \ No newline at end of file diff --git a/Classes/SizeTransformAttribute.ps1 b/Classes/SizeTransformAttribute.ps1 new file mode 100644 index 0000000..3ee7c48 --- /dev/null +++ b/Classes/SizeTransformAttribute.ps1 @@ -0,0 +1,27 @@ +class SizeTransformAttribute : System.Management.Automation.ArgumentTransformationAttribute { + # Implement the Transform() method + [object] Transform([System.Management.Automation.EngineIntrinsics]$engineIntrinsics, [object] $inputData) { + <# + The parameter value(s) are passed in here as $inputData. We aren't accepting array input + for our function, but it's good to make these fairly versatile where possible, so that + you can reuse them easily! + #> + $outputData = switch ($inputData) { + { $_ -is [SizeTransformAttribute] } { $_ } + { $_ -is [int] } { [System.Drawing.Size]::new($_, $_) } + { $_ -is [string] -and (($_ -split '[,x]').count -eq 2) } { + $sp = $_ -split '[,x]' + [System.Drawing.Size]::new($sp[0], $sp[1]) + } + default { + # If we hit something we can't convert, throw an exception + throw [System.Management.Automation.ArgumentTransformationMetadataException]::new( + "Could not convert input '$_' to a valid Size object." + ) + } + } + + return $OutputData + } + +} \ No newline at end of file diff --git a/Classes/StringUrlTransformAttribute.ps1 b/Classes/StringUrlTransformAttribute.ps1 new file mode 100644 index 0000000..019dbc8 --- /dev/null +++ b/Classes/StringUrlTransformAttribute.ps1 @@ -0,0 +1,29 @@ +class StringUrlTransformAttribute : System.Management.Automation.ArgumentTransformationAttribute { + # Implement the Transform() method + [object] Transform([System.Management.Automation.EngineIntrinsics]$engineIntrinsics, [object] $inputData) { + <# + The parameter value(s) are passed in here as $inputData. We aren't accepting array input + for our function, but it's good to make these fairly versatile where possible, so that + you can reuse them easily! + #> + $outputData = switch ($inputData) { + { $_ -is [string] } { + if ($_ -match '://') { + $_ + } + else { + "https://$_" + } + } + default { + # If we hit something we can't convert, throw an exception + throw [System.Management.Automation.ArgumentTransformationMetadataException]::new( + "Only String attributes are supported." + ) + } + } + + return $OutputData + } + +} \ No newline at end of file diff --git a/Debug/Debug.ps1 b/Debug/Debug.ps1 new file mode 100644 index 0000000..6f92252 --- /dev/null +++ b/Debug/Debug.ps1 @@ -0,0 +1,31 @@ +import-module Platyps +import-module InvokeBuild + +# Just a line to replace $PsScriptRoot since the former does not work when debugging with F8 +$ScriptFullPath, $ScriptRoot, $ScriptName, $ScriptNameShort = @('', '', '', ''); $ScriptFullPath = if (-not [String]::IsNullOrEmpty($PSCommandPath)) { $PSCommandPath } elseif ($psEditor -ne $null) { $psEditor.GetEditorContext().CurrentFile.Path } elseif ($psise -ne $null) { $psise.CurrentFile.FullPath }; $ScriptRoot = Split-Path -Path $ScriptFullPath -Parent; $ScriptName = Split-Path -Path $ScriptFullPath -Leaf; $ScriptNameShort = ([System.IO.Path]::GetFileNameWithoutExtension($ScriptFullPath)) +$ProjectPath = Split-Path $ScriptRoot + +# Load Debug version +import-module "$ProjectPath\Selenium.psd1" -Force + +#Load Compiled version +#import-module "$ProjectPath\output\selenium\Selenium.psd1" -Force + +# CI tests +. $ProjectPath\CI\CI.ps1 -browserlist Chrome, Firefox + +# Build module +Get-Module pester | Remove-Module; Import-Module pester -RequiredVersion 4.10.1 +invoke-build -File "$ProjectPath\Selenium.build.ps1" + + +# Documentation update only +Update-MarkdownHelpModule -Path "$ProjectPath\Help" -ModulePagePath "$ProjectPath\Help\README.MD" -RefreshModulePage -Verbose + +#Tests +#Invoke-Pester -Script 'C:\Github\selenium-powershell\Examples\Combined.tests.ps1' + + + + + diff --git a/Debug/README.md b/Debug/README.md new file mode 100644 index 0000000..efacd8a --- /dev/null +++ b/Debug/README.md @@ -0,0 +1,31 @@ +# Instructions + +## Prerequisites +- InvokeBuild module +- PlatyPS module + +## How to + +### Debug + +To load the debugging version, simply load the Selenium.psd1 located at the root of this directory. + +`import-module "$ProjectPath\Selenium.psd1" -Force` + +To load the compiled version, load the psd1 located in the output directory instead. + +`import-module "$ProjectPath\output\selenium\Selenium.psd1" -Force` + +When developping, you should always load the development version of the module. Never work in the files from the **output** directory directly as these will be wiped out whenever you compile the module again. + +### Compile the module +The module is scaffolded into multiple files for convenience and compiled into a psm1 file when ready to be published. + +Alongside this, additional tasks are performed suche as basic Powershell validation, self-updating Markdown documentation, embedded help file generation, psd1 function replace based on Public folder content, etc. + +To perform these tasks and produce a compiled (but not packaged) version of the module, run the following + +`invoke-build -File "$ProjectPath\Selenium.build.ps1"` + + +See the debug.ps1 file in this directory to get started. \ No newline at end of file diff --git a/Examples/A-Simple-Google-Search.ps1 b/Examples/A-Simple-Google-Search.ps1 index 4f89044..4c94db1 100644 --- a/Examples/A-Simple-Google-Search.ps1 +++ b/Examples/A-Simple-Google-Search.ps1 @@ -1,70 +1,55 @@ -<# -.VERSION - 0.2 - -.DESCRIPTION -This is an example script that will show you how to use the Selenium driver to preform a simple google search. -Using this example script you will learn the basic usage of the Selenium powershell module. -Each comment line will explain the line that will come after it so you can follow it in a step by step fashion. -#> - # The line below will Import-Module Selenium if it fails it will display the installation command and stop the script. -try{Import-Module -Name Selenium -ErrorAction Stop}catch{Write-Host 'Importing the Selenium module failed. Please install it using the following command: Install-Module Selenium';break} +Import-Module -Name Selenium # Start the Selenium Chrome Driver -$Driver = Start-SeChrome +Start-SeDriver -Browser Chrome -StartURL 'google.com/ncr' -# Next we will check if the driver is running and if it's not running we will show a message. If the driver is running we will run the commands inside the if statment. -if($Driver){ - # Now that we verified that the driver is running we can start doing cool things with it. - # Using the Enter-SeUrl command we can tell the driver to go to any URL we want in this case we'll go to https://google.com/ncr - # I used the /ncr in the end of the URL because I want google to always stay in english and not redirect to a specific language for consistency. - Enter-SeUrl -Driver $Driver -Url 'https://www.google.com/ncr' - # After nevigating to the desired URL we can start interacting with elements on the page in this example we are going to find the search box and type something in it. - # We can find elements using different ways like the element id or the Name/ClassName/TagName and a few other ways. - # In the below code we're going to show you a few ways to solve this problem. +#Getting the Search box - <# This is the HTML code of the search box +<# This is the HTML code of the search box, found using the browser developer tools - #> +#> - # By examining the HTML code of the google seach box we can see that the search box name is q so in the below example we'll use the name q to find its element - $SearchBoxElement = Find-SeElement -Driver $Driver -Name q +#Here's a few different ways, all valid, to access that searchbox - # We can also use the class name gLFyf to find the google search box. - $SearchBoxElement = Find-SeElement -Driver $Driver -ClassName 'gLFyf' +# By examining the HTML code of the google seach box we can see that the search box name is q so in the below example we'll use the name q to find its element +#The Single parameter will write an error if there's not 1 element. +$Searchbox = Get-SeElement -By Name -value q -Single - # This line will get us all elements with the input TagName also known as - $AllInputElements = Find-SeElement -Driver $Driver -TagName input +# We can also use the class name gLFyf to find the google search box. +$Searchbox = Get-SeElement -ClassName 'gLFyf' - # The $AllInputElements contains all the input elements on the page if we want to find the specific element for the google search box we will need to loop through each input element in the $AllInputElements array and get the attibute we want in this case we're looking for the title attribute. - # And we only want to return the element that has a title equal to Search we can find this out based on the html code on the page. - $SearchBoxElement = $AllInputElements|ForEach-Object{if($_.GetAttribute('title') -eq 'Search'){return $_}} +# This line will get us all elements with the input TagName also known as +#The -All parameter (optional) also includes hidden elements. +# The -Attributes parameter will load the specified attribute in the result and make them available through an Attributes property +$AllInputElement = Get-SeElement -By TagName -Value input -All -Attributes title +$AllInputElement | select Attributes +# The $AllInputElements contains all the input elements on the page if we want to find the specific element for the google search box we will need to loop through each input element in the $AllInputElements array and get the attibute we want in this case we're looking for the title attribute. +# And we only want to return the element that has a title equal to Search we can find this out based on the html code on the page. +$Searchbox = $AllInputElement.Where( { $_.Attributes.title -eq 'Search' }, 'first')[0] - # Now for the fun part after finding the element we want to send keyboard input to it. this will allow us to automate the search process - # We can get the list of all special keyboard keys like enter/backspace etc using the Get-SeKeys command +# Now for the fun part after finding the element we want to send keyboard input to it. this will allow us to automate the search process +# We can get the list of all special keyboard keys like enter/backspace etc using the Get-SeKeys command - # Now that we can see all the keys we can send send some keys to the SearchBoxElement - Send-SeKeys -Element $SearchBoxElement -Keys 'Powershell-Selenium' +# Now that we can see all the keys we can send send some keys to the SearchBoxElement +Invoke-SeKeys -Element $Searchbox -Keys 'Powershell-Selenium' - # You can send special key strokes to the SearchBoxElement, you should use the Selenium Keys enum. For example, if we wanted to send an enter key stroke, you could do it like this - Send-SeKeys -Element $SearchBoxElement -Keys ([OpenQA.Selenium.Keys]::Enter) +# You can send special key strokes to the SearchBoxElement, you should use the Selenium Keys enum. For example, if we wanted to send an enter key stroke, you could do it like this +# To view special keys, use Get-SeKeys +Invoke-SeKeys -Element $Searchbox -Keys ([OpenQA.Selenium.Keys]::Enter) - # When working with dynamic websites, it's often necessary to wait awhile for elements to appear on the page. By default, Selenium won't wait and you'll receive $null from Find-SeElement because the element isn�t there yet. There are a couple ways to work around this. - # The first is to use the Find-SeElement cmdlet with the -Wait switch to wait for the existence of an element in the document. - # When using the Find-SeElement with the -Wait please take into account that only 1 element can be returned unlike the without the -Wait switch where multiple elements can be returned. +# When working with dynamic websites, it's often necessary to wait awhile for elements to appear on the page. By default, Selenium won't wait and you'll receive $null from Find-SeElement because the element isn�t there yet. There are a couple ways to work around this. +# The first is to use the Find-SeElement cmdlet with the -Wait switch to wait for the existence of an element in the document. +# When using the Find-SeElement with the -Wait please take into account that only 1 element can be returned unlike the without the -Wait switch where multiple elements can be returned. - # This command will wait for the img elements for 10 seconds and then return it to you or time out if the element wasn't found on. - $LogoImageElement = Find-SeElement -Driver $Driver -Wait -Timeout 10 -Id 'logo' +# This command will wait for the img elements for 10 seconds and then return it to you or time out if the element wasn't found on. +#Note, the value parameter is provided positionally. +$LogoImageElement = Get-SeElement -Timeout 10 -By Id 'logo' - # Once we have the image element we can simulate a mouse click on it using the Invoke-SeClick command. - Invoke-SeClick -Driver $Driver -Element $LogoImageElement +# Once we have the image element we can simulate a mouse click on it using the Invoke-SeClick command. +Invoke-SeClick -Element $LogoImageElement - # Once we are done with the web driver and we finished with all our testing/automation we can release the driver by running the Stop-SeDriver command. - Stop-SeDriver -Driver $Driver -} -# if the driver is not running we will enter the script block in the else section and display a message -else{ - Write-Host "The selenium driver was not running." -ForegroundColor Yellow -} \ No newline at end of file +# Once we are done with the web driver and we finished with all our testing/automation we can release the driver by running the Stop-SeDriver command. +Stop-SeDriver \ No newline at end of file diff --git a/Examples/Combined.tests.ps1 b/Examples/Combined.tests.ps1 new file mode 100644 index 0000000..f5dc2d1 --- /dev/null +++ b/Examples/Combined.tests.ps1 @@ -0,0 +1,254 @@ +. "$(Join-Path -Path $PSScriptRoot -ChildPath '_TestDependencies.ps1' )" + +$Global:TestCaseSettings = Get-TestCasesSettings +$Global:BrowserOptHash = $Global:TestCaseSettings."$Global:DefaultBrowser".DefaultOptions +$Env:BrowserOptText = Build-StringFromHash $Global:BrowserOptHash +$Env:BrowserID = "$Global:DefaultBrowser on $([System.Environment]::OSVersion.Platform)" +Describe "Testing the tailspin toys demo site at $env:SITE_URL" { + BeforeAll { + . "$(Join-Path -Path $PSScriptRoot -ChildPath '_TestDependencies.ps1' )" + + $Global:TestCaseSettings = Get-TestCasesSettings + $Global:BrowserOptHash = $Global:TestCaseSettings."$Global:DefaultBrowser".DefaultOptions + $Env:BrowserOptText = Build-StringFromHash $Global:BrowserOptHash + #Relying on environment variable to pick the browser. Capture ID for use in logs by requesting verbose and redirecting it. + try { Start-SeDriver -Browser $Global:DefaultBrowser -StartURL $env:SITE_URL @Global:BrowserOptHash -Verbose 4>&1 -ErrorAction Stop } catch { throw $_ } + $Env:BrowserID = "$Global:DefaultBrowser on $([System.Environment]::OSVersion.Platform)" + + } + Context "in $($Env:BrowserID) with settings ($Env:BrowserOptText)" { + It "produced the right modal dialog for the " -TestCases (Get-ModalTestCases) { + Param ($linkXPath, $modalXPath) + SeShouldHave $modalXPath -With displayed eq $false -Timeout 10 + SeElement $linkXPath | Invoke-SeClick -Action Click_JS -Sleep 1 + SeElement $modalXPath | SeElement -By ClassName 'close' | Invoke-SeClick -Action Click_JS -Sleep 1 + SeShouldHave 'body' -By TagName + SeShouldHave $modalXPath -With displayed eq $false + } + } + # Additional tests would be here + AfterAll { Stop-SeDriver } +} +#endregion + +#URLs we will visit in the remaining tests + +# + + +#As before rely on environment variable to pick browser. Capture ID by requesting & redirecting verbose +Describe "PsGallery Test" { + BeforeAll { + . "$(Join-Path -Path $PSScriptRoot -ChildPath '_TestDependencies.ps1' )" + $PSGalleryPage = 'https://www.powershellgallery.com/' + $Global:TestCaseSettings = Get-TestCasesSettings + $Global:BrowserOptHash = $Global:TestCaseSettings[$Global:DefaultBrowser].DefaultOptions + $Env:BrowserOptText = Build-StringFromHash $Global:BrowserOptHash + try { Start-SeDriver -Browser $Global:DefaultBrowser -StartURL $PSGalleryPage @Global:BrowserOptHash -Verbose 4>&1 -ErrorAction Stop }catch {} + $Env:BrowserID = "$Global:DefaultBrowser on $([System.Environment]::OSVersion.Platform)" + } + Context "in $Env:BrowserID with settings ($Env:BrowserOptText)" { + It 'opened the browser, saving the webdriver in a global variable ' { + Get-SeDriver -Current | Should -Not -BeNullOrEmpty + Get-SeDriver -Current | Should -BeOfType [OpenQA.Selenium.Remote.RemoteWebDriver] + } + + It 'reached the right starting page ' { + #Should have can check alerts, page title, URL or an element on the page + SeShouldHave -URL eq $PSGalleryPage + } + It 'found the "Sign in" link on the home page by partial text ' { + SeShouldHave -By PartialLinkText 'Sign in' -With href match logon + } + It 'found the search box on the home page by ID ' { + SeShouldHave -By Id search + } + It 'found the search box on the home page by Name ' { + SeShouldHave -By Name 'q' + } + It 'found the search box on the home page by css selector ' { + #can write -By <> [-selection] <> + # or [-selection] <> -By <> + SeShouldHave 'input[name=q]' -By CssSelector + } + It 'found the search box on the home page by class name ' { + SeShouldHave -By ClassName "search-box" + } + It 'found the search box on the home page by Tagname and typed in it ' { + #get element, pipe as input element for Typing, pass the element through + #so pester catches 'null or empty' if it was not found + Get-SeElement -By TagName -Value 'input' | + Invoke-SeKeys -ClearFirst -Keys "selenium{{Enter}}" -PassThru -Sleep 2 | Should -Not -BeNullorEmpty + } + It 'searched successfully ' { + $linkpath = '//*[@id="skippedToContent"]/section/div[1]/div[2]/div[2]/section[1]/div/table/tbody/tr/td[1]/div/div[2]/header/div[1]/h1/a' + SeShouldHave -URL match 'packages\?q=selenium' -Timeout 15 + #Two tests on the same element, second passes it through to click + SeShouldHave $linkpath -With href match selenium + SeShouldHave $linkpath -With Text like *selenium* -PassThru | Invoke-SeClick -Action Click_JS -Sleep 5 + } + It 'opened the search result page and found the expected content ' { + #Just to show we can test for the presence of multiple links. Each one is re-tested ... + SeShouldHave '//*[@id="version-history"]/table/tbody[1]/tr[1]/ td[1]/a/b' , + '//*[@id="skippedToContent"]/section/div/aside/ul[2]/li[1]/a' -Timeout 15 + + SeShouldHave '//*[@id="version-history"]/table/tbody[1]/tr[1]/ td[1]/a/b' -With text match "current" + + #Can test with "Get-SeElement | where-object <>" rather than "with <> <> <>" + SeElement '//*[@id="skippedToContent"]/section/div/aside/ul[2]/li[1]/a' | + Where-Object { ($_.text -like "*Project Site*") -and ($_.GetAttribute('href') -match "selenium") } | + Invoke-SeClick -PassThru | Should -Not -Benullorempty + } + It 'went to Github from the project link on the search result ' { + SeShouldHave -URL match 'github' -Timeout 30 + } + It 'navigated back to the start page and closed the browser ' { + Set-SeUrl -Back + Set-SeUrl -Back + Set-SeUrl -Back + SeShouldHave -URL eq $PSGalleryPage -Timeout 30 + Stop-SeDriver + Get-SeDriver -Current | Should -BeNullOrEmpty + } + } + AfterAll { Stop-SeDriver } +} + + +Describe "Alerts and Selection boxes tests" { + BeforeAll { + . "$(Join-Path -Path $PSScriptRoot -ChildPath '_TestDependencies.ps1' )" + $AlertTestPage = 'https://www.w3schools.com/js/tryit.asp?filename=tryjs_alert' + $SelectTestPage = 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_elem_select' + $Global:TestCaseSettings = Get-TestCasesSettings + $Global:BrowserOptHash = $Global:TestCaseSettings[$Global:DefaultBrowser].PrivateOptions + $Env:BrowserOptText = Build-StringFromHash $Global:BrowserOptHash + + if ($Env:BrowserOptText) { + $Global:NoLabel = [string]::IsNullOrEmpty($Global:TestCaseSettings[$Global:DefaultBrowser].InPrivateLabel) + $wv = $null + try { Start-SeDriver -Browser $Global:DefaultBrowser -StartURL $alertTestPage @BrowserOptHash -WarningVariable wv -ErrorAction Stop }catch {} + if ($wv) { Write-Output "##vso[task.logissue type=warning]$wv" } + } + else { + $Global:NoLabel = $true + try { Start-SeDriver -Browser $Global:DefaultBrowser -StartURL $alertTestPage -ErrorAction Stop } catch {} + + } + $Env:BrowserID = "$Global:DefaultBrowser on $([System.Environment]::OSVersion.Platform)" + } + Context "in $Env:BrowserID with settings ($Env:BrowserOptText)" { + # It 're-opended the browser and validated "InPrivate" mode by window title ' { + # $DriverProcess = Get-Process *driver | Where-Object { $_.Parent.id -eq $pid } + # $BrowserProcess = Get-Process | Where-Object { $_.Parent.id -eq $DriverProcess.id -and $_.Name -ne "conhost" } + # $BrowserProcess.MainWindowTitle | Should match $Global:TestCaseSettings[$Global:DefaultBrowser].InPrivateLabel + # } -Skip:$Global:NoLabel + It 'opened the right page ' { + SeShouldHave -URL -eq $alertTestPage + } + It 'Navigated to the child iframe' { #'triggered and dismissed an alert' + SeShouldHave -Selection "iframe" -By TagName -with id eq iframeResult + Switch-SeFrame 'iframeResult' + Get-SeElement "/html/body/button" | Should -Not -BeNullOrEmpty #Removed | Invoke-SeClick -PassThru + #Checking the text of the alert is optional. Dissmiss can pass the alert result through + #{ Wait-SeDriver -Condition AlertState -Value $false -Timeout 15 -ErrorAction Stop } | Should -Not -throw + #Clear-SeAlert -Alert $Alert -Action Dismiss -PassThru | Should -Not -BeNullOrEmpty + } + It 'reselected the parent frame ' { + Switch-SeFrame -Parent + SeShouldHave -Selection "iframe" -By TagName -with id eq iframeResult + } + It 'navigated to a new page, and found the "cars" selection box in frame 1 ' { + Set-SeUrl $SelectTestPage + SeShouldHave -Selection "iframe" -By TagName -with id eq iframeResult + Switch-SeFrame 'iframeResult' + $e = SeElement -by Name "cars" + $e | Should -Not -BeNullOrEmpty + (Get-SeSelectValue -Element $e -All).Items.Text | Should -Contain 'volvo' + } + It 'made selections from the "cars" selection box ' { + $e = SeElement -by Name "cars" + #Values are lower case Text has inital caps comparisons are case sensitve. Index is 0-based + { $e | Set-SeSelectValue -By Value -value "Audi" } | Should -Throw + { $e | Set-SeSelectValue -By Value -value "audi" } | Should -not -throw + $e | Set-SeSelectValue -By Index -value "2"; (Get-SeSelectValue -Element $e).Text | Should -Be 'Fiat' + $e | Set-SeSelectValue -By Text -value "Sa*" + } + It 'submitted the form and got the expected response ' { + Get-SeElement '/html/body/form/input' | Invoke-SeClick -Sleep 5 + Switch-SeFrame -Parent + Switch-SeFrame 'iframeResult' + SeShouldHave "/html/body/div[1]" -with text match "cars=saab" + } + It 'closed the in-private browser instance ' { + Stop-SeDriver + if ($DriverProcess.Id) { + (Get-Process -id $DriverProcess.id ).HasExited | Should -Be $true + } + if ($BrowserProcess.Id) { + (Get-Process -id $BrowserProcess.id).HasExited | Should -Be $true + } + } + } + AfterAll { Stop-SeDriver } +} + + +$Global:BrowserOptHash = $Global:TestCaseSettings[$Global:DefaultBrowser].HeadlessOptions +$Env:BrowserOptText = Build-StringFromHash $Global:BrowserOptHash +$Global:SkipTests = [String]::IsNullOrEmpty($Env:BrowserOptText) + +Describe "'Headless' mode browser test" { + BeforeAll { + . "$(Join-Path -Path $PSScriptRoot -ChildPath '_TestDependencies.ps1' )" + $Global:TestCaseSettings = Get-TestCasesSettings + + $Global:BrowserOptHash = $Global:TestCaseSettings[$Global:DefaultBrowser].HeadlessOptions + $Env:BrowserOptText = Build-StringFromHash $Global:BrowserOptHash + $Global:SkipTests = $true + if (![String]::IsNullOrEmpty($Env:BrowserOptText)) { + $Global:SkipTests = $false + try { $Env:BrowserID = Start-SeDriver -Browser $Global:DefaultBrowser -StartURL $env:SITE_URL @BrowserOptHash -ErrorAction Stop }catch {} + } + $Env:BrowserID = "$Global:DefaultBrowser on $([System.Environment]::OSVersion.Platform)" + } + Context "in $Env:BrowserID with settings ($Env:BrowserOptText)" { + It 're-opened the Browser in "Headless" mode' { + if ($PSVersionTable.PSVersion.Major -eq 5) { + $Processes = Get-CimInstance -Class Win32_Process + $DriverProcess = $Processes | Where { $_.Name -like '*driver.exe' -and $_.ParentProcessId -eq $Pid } + $BrowserProcess = $Processes | Where-Object { $_.ParentProcessId -eq $DriverProcess.ProcessId -and $_.Name -ne 'conhost.exe' } + if ($BrowserProcess -ne $null) { + (Get-process -Id $BrowserProcess.ProcessId).MainWindowHandle | Should -be 0 + } + } + else { + $DriverProcess = Get-Process *driver | Where-Object { $_.Parent.id -eq $pid } + $BrowserProcess = Get-Process | Where-Object { $_.Parent.id -eq $DriverProcess.id -and $_.Name -ne 'conhost' } + $BrowserProcess.MainWindowHandle | Select-Object -First 1 | Should -be 0 + } + } + it 'did a google Search ' { + Set-SeUrl 'https://www.google.com/ncr' + SeShouldHave -by Name q + SeShouldHave -by ClassName 'gLFyf' + SeShouldHave -By Name q -PassThru | Where Displayed -eq $true | + Select-Object -First 1 | Invoke-SeKeys -Keys 'Powershell-Selenium{{Enter}}' -PassThru | + should -Not -BeNullOrEmpty + + SeShouldHave '//*[@id="tsf"]/div[2]/div[1]/div[1]/a' -PassThru | + Invoke-SeClick -PassThru | should -Not -BeNullOrEmpty + } + It 'closed the browser a third time ' { + Stop-SeDriver + Get-SeDriver -Current | Should -BeNullOrEmpty + if ($DriverProcess.Id) { + (Get-Process -id $DriverProcess.id ).HasExited | Should -Be $true + } + if ($BrowserProcess.Id) { + (Get-Process -id $BrowserProcess.id).HasExited | Should -Be $true + } + } + } -Skip:$Global:SkipTests + AfterAll { Stop-SeDriver } +} \ No newline at end of file diff --git a/Examples/Example.side b/Examples/Example.side new file mode 100644 index 0000000..a11d238 --- /dev/null +++ b/Examples/Example.side @@ -0,0 +1,295 @@ +{ + "id": "1a83cd76-e78d-4402-b40e-5805b2403f44", + "version": "2.0", + "name": "Example", + "url": "https://automationintesting.com", + "tests": [{ + "id": "0896d7a2-81f1-4972-bbc3-4880718bc157", + "name": "Test1", + "commands": [{ + "id": "4770f8f0-e2c5-434e-847c-b79ecadebf41", + "comment": "", + "command": "open", + "target": "/selenium/testpage/", + "targets": [], + "value": "" + }, { + "id": "8068ba5f-597f-4d50-834d-b057c2cfb2ea", + "comment": "", + "command": "setWindowSize", + "target": "1936x1056", + "targets": [], + "value": "" + }, { + "id": "90423ff3-98f2-4de8-9998-32088c188647", + "comment": "", + "command": "click", + "target": "id=firstname", + "targets": [ + ["id=firstname", "id"], + ["css=#firstname", "css:finder"], + ["xpath=//input[@id='firstname']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div/div/label/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "" + }, { + "id": "fa88b63a-f245-4374-8db2-284f239c3ee0", + "comment": "", + "command": "type", + "target": "id=firstname", + "targets": [ + ["id=firstname", "id"], + ["css=#firstname", "css:finder"], + ["xpath=//input[@id='firstname']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div/div/label/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "test" + }, { + "id": "2626b60b-2f5b-473d-b342-4f5ec36501b5", + "comment": "", + "command": "click", + "target": "xpath=//form[@id='contactus']/div[2]/div/label/input", + "targets": [ + ["id=surname", "id"], + ["css=#surname", "css:finder"], + ["xpath=//input[@id='surname']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[2]/div/label/input", "xpath:idRelative"], + ["xpath=//div[2]/div/label/input", "xpath:position"] + ], + "value": "" + }, { + "id": "65b0a638-0f79-4a43-ac8a-db482d18c3cd", + "comment": "", + "command": "type", + "target": "xpath=//form[@id='contactus']/div[2]/div/label/input", + "targets": [ + ["id=surname", "id"], + ["css=#surname", "css:finder"], + ["xpath=//input[@id='surname']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[2]/div/label/input", "xpath:idRelative"], + ["xpath=//div[2]/div/label/input", "xpath:position"] + ], + "value": "test2" + }, { + "id": "e9047045-ede4-4c13-81b5-f8c036cb527c", + "comment": "", + "command": "click", + "target": "id=gender", + "targets": [ + ["id=gender", "id"], + ["css=#gender", "css:finder"], + ["xpath=//select[@id='gender']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[3]/div/label/select", "xpath:idRelative"], + ["xpath=//select", "xpath:position"] + ], + "value": "" + }, { + "id": "f9341c3c-215b-44c1-9fff-fa977a7ba599", + "comment": "", + "command": "select", + "target": "id=gender", + "targets": [], + "value": "label=Male" + }, { + "id": "39458fd5-e6ac-46c7-9e48-b24349314ef0", + "comment": "", + "command": "click", + "target": "id=red", + "targets": [ + ["id=red", "id"], + ["name=colour", "name"], + ["css=#red", "css:finder"], + ["xpath=//input[@id='red']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[4]/div/input", "xpath:idRelative"], + ["xpath=//div/input", "xpath:position"] + ], + "value": "" + }, { + "id": "a1ded097-b395-4bed-b641-7c2ab136d411", + "comment": "", + "command": "click", + "target": "css=textarea", + "targets": [ + ["css=textarea", "css:finder"], + ["xpath=//form[@id='contactus']/div[5]/div/label/textarea", "xpath:idRelative"], + ["xpath=//textarea", "xpath:position"] + ], + "value": "" + }, { + "id": "582f0b4e-2521-404e-a912-39261d867d11", + "comment": "", + "command": "type", + "target": "css=textarea", + "targets": [ + ["css=textarea", "css:finder"], + ["xpath=//form[@id='contactus']/div[5]/div/label/textarea", "xpath:idRelative"], + ["xpath=//textarea", "xpath:position"] + ], + "value": "text" + }, { + "id": "764ae979-42dd-457e-95c5-5dddad91e44d", + "comment": "", + "command": "addSelection", + "target": "id=continent", + "targets": [ + ["id=continent", "id"], + ["css=#continent", "css:finder"], + ["xpath=//select[@id='continent']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[6]/div/label/select", "xpath:idRelative"], + ["xpath=//div[6]/div/label/select", "xpath:position"] + ], + "value": "label=North America" + }, { + "id": "bb929f6f-ee4c-43ad-920b-0806aba3c37d", + "comment": "", + "command": "click", + "target": "id=checkbox1", + "targets": [ + ["id=checkbox1", "id"], + ["css=#checkbox1", "css:finder"], + ["xpath=//input[@id='checkbox1']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[4]/div[2]/input", "xpath:idRelative"], + ["xpath=//div[2]/input", "xpath:position"] + ], + "value": "" + }, { + "id": "542d6958-faab-40e9-9b4b-81f051673c23", + "comment": "", + "command": "click", + "target": "id=submitbutton", + "targets": [ + ["id=submitbutton", "id"], + ["css=#submitbutton", "css:finder"], + ["xpath=//button[@id='submitbutton']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[7]/div/button", "xpath:idRelative"], + ["xpath=//div/button", "xpath:position"], + ["xpath=//button[contains(.,'I do nothing!')]", "xpath:innerText"] + ], + "value": "" + }] + }, { + "id": "c0d8e914-0e45-4d59-be13-b902e026cb6c", + "name": "Test2", + "commands": [{ + "id": "319fa3e0-f697-4963-a879-b358fff62a77", + "comment": "", + "command": "open", + "target": "/selenium/testpage/", + "targets": [], + "value": "" + }, { + "id": "27aa1c23-21c7-45dc-8887-fe3d0e8f592b", + "comment": "", + "command": "setWindowSize", + "target": "1936x1056", + "targets": [], + "value": "" + }, { + "id": "421ace3d-1377-4423-9257-bfc703103beb", + "comment": "", + "command": "sendKeys", + "target": "id=firstname", + "targets": [], + "value": "test3" + }, { + "id": "301e2ba3-8f11-42cd-a41e-8241e158e962", + "comment": "", + "command": "sendKeys", + "target": "id=firstname", + "targets": [ + ["id=firstname", "id"], + ["css=#firstname", "css:finder"], + ["xpath=//input[@id='firstname']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div/div/label/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "${KEY_ENTER}" + }] + }, { + "id": "8b6ff854-fefb-40bc-bd48-d206878b9e64", + "name": "Test3", + "commands": [{ + "id": "a3b6e82e-a847-4ac5-ac72-a05c5150d107", + "comment": "", + "command": "open", + "target": "http://www.tagindex.net/html/frame/example_f01.html", + "targets": [], + "value": "" + }, { + "id": "785d2ca1-c20b-4b96-a03e-43119ad2ecef", + "comment": "", + "command": "setWindowSize", + "target": "1936x1056", + "targets": [], + "value": "" + }, { + "id": "150bc283-671d-4d77-b1a5-b5dd20c2eee3", + "comment": "", + "command": "selectFrame", + "target": "index=0", + "targets": [ + ["index=0"] + ], + "value": "" + }, { + "id": "50809502-afdf-4b1b-943b-40524bbd2420", + "comment": "", + "command": "click", + "target": "css=html", + "targets": [ + ["css=html", "css:finder"], + ["xpath=//html", "xpath:position"] + ], + "value": "" + }, { + "id": "e726cc31-c25f-4cf7-92fe-77d976bb2f91", + "comment": "", + "command": "selectFrame", + "target": "relative=parent", + "targets": [ + ["relative=parent"] + ], + "value": "" + }, { + "id": "71ab81f7-8c7d-413e-a7ed-f68c224b1373", + "comment": "", + "command": "selectFrame", + "target": "index=1", + "targets": [ + ["index=1"] + ], + "value": "" + }, { + "id": "6e01154b-2221-4eef-98db-5760b52063e0", + "comment": "", + "command": "doubleClick", + "target": "css=p", + "targets": [ + ["css=p", "css:finder"], + ["xpath=//div[@id='MainBox']/p", "xpath:idRelative"], + ["xpath=//p", "xpath:position"], + ["xpath=//p[contains(.,'Please return to the previous page using the browsers \"back\" button.')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "a9f64bfd-1962-4f32-aa85-85d1ae4af91a", + "comment": "", + "command": "close", + "target": "", + "targets": [], + "value": "" + }] + }], + "suites": [{ + "id": "3fb340b3-1af6-4948-ad2a-c689126d9dad", + "name": "Default Suite", + "persistSession": false, + "parallel": false, + "timeout": 300, + "tests": ["0896d7a2-81f1-4972-bbc3-4880718bc157"] + }], + "urls": ["https://automationintesting.com/"], + "plugins": [] +} \ No newline at end of file diff --git a/Examples/_TestDependencies.ps1 b/Examples/_TestDependencies.ps1 new file mode 100644 index 0000000..6425032 --- /dev/null +++ b/Examples/_TestDependencies.ps1 @@ -0,0 +1,70 @@ + +Function Get-DefaultParams() { + if ($null -eq $Global:DefaultBrowser) { $Global:DefaultBrowser = 'Firefox' } + if ($null -eq $env:SITE_URL) { $env:SITE_URL = 'http://tailspin-spacegame-web.azurewebsites.net' } + if ($null -eq $Global:HeadlessOnly) { $Global:HeadlessOnly = $False } +} +Get-DefaultParams + + +Function Get-TestCasesSettings() { + $HeadlessState = if ($Global:HeadlessOnly) { 'Headless' } else { 'Maximized' } + return @{ + 'NewEdge' = @{ + DefaultOptions = @{State = $HeadlessState } + PrivateOptions = @{ + PrivateBrowsing = $true + State = $HeadlessState + } + # InPrivateLabel = 'InPrivate' + } # broken after build 79 of web driver#> + 'Chrome' = @{ + PrivateOptions = @{ + PrivateBrowsing = $true + State = $HeadlessState + } + DefaultOptions = @{State = $HeadlessState } + HeadlessOptions = @{State = 'Headless' } + } + 'Firefox' = @{ + PrivateOptions = @{ + PrivateBrowsing = $true + State = $HeadlessState + } + DefaultOptions = @{State = $HeadlessState } + HeadlessOptions = @{State = 'Headless' } + } + 'MSEdge' = @{ + DefaultOptions = @{State = $HeadlessState } + PrivateOptions = @{PrivateBrowsing = $true } + } + 'InternetExplorer' = @{ + DefaultOptions = @{ImplicitWait = 30 } + PrivateOptions = @{ImplicitWait = 30 } + } + } +} + +function Build-StringFromHash { + param ($Hash) + $(foreach ($k in $Hash.Keys) { "$K`:$($hash[$K])" }) -join '; ' +} + + + +function Get-ModalTestCases() { + return @( + @{Name = 'Download Page' + linkXPath = '/html/body/div/div/section[2]/div[2]/a' + modalXPath = '//*[@id="pretend-modal"]/div/div' + }, + @{Name = 'Screen Image' + linkXPath = '/html/body/div/div/section[3]/div/ul/li[1]/a' + modalXPath = '/html/body/div[1]/div/div[2]' + }, + @{Name = 'Top Player' + linkXPath = '/html/body/div/div/section[4]/div/div/div[1]/div[2]/div[2]/div/a/div' + modalXPath = '//*[@id="profile-modal-1"]/div/div' + } + ) +} diff --git a/Examples/comparison.ps1 b/Examples/comparison.ps1 new file mode 100644 index 0000000..65e5b76 --- /dev/null +++ b/Examples/comparison.ps1 @@ -0,0 +1,60 @@ + +<# +public void testClass() throws Exception { + driver.get("http://www.wikipedia.org/") ; + Assert.assertequals("wikipedia", driver.getTitle()); + Assert.assertequals("English", driver.findElement(By.cssselector("strong")).getText()) + driver.findElement(By.cssSetector("strong")).click() ; + Assert.assertEquals("Wikipedia. the free encyclopedia", driver.getTitle()); +} +#> +Start-SeDriver -Browser Chrome -StartURL "https://www.wikipedia.org/" +SeShouldHave -Title eq Wikipedia +SeShouldHave 'strong' -By CssSelector -With Text eq 'English' -PassThru | Invoke-SeClick +SeShouldHave -Title eq 'Wikipedia, the free encyclopedia' + +<# +line 2 ## SeShouldHave -Title eq Wikipedia +is actutally short for ## SeShouldHave -Title -Operator 'eq' -Value Wikipedia +other values for -operator will translate to "eq", and parameters are defined so you can use -eq -contains, -match etc +so you can use ## SeShouldHave -Title equalTo Wikipedia +or ## SeShouldHave -Title -eq Wikipedia +line 3 ## SeShouldHave 'strong' -By CssSelector Text eq 'English' +This is short for ## SeShouldHave -Selection 'strong' -By CssSelector -With Text -operator "eq" -value 'English' +if the selector is an xPath the -By parameter can be omitted; but if used -By must specified explicitly +The first unnamed parameter will be treated as selection, the second as "with" , the third as operator and the fourth as value. +SeShouldhave can take a -passthru parameter allowing the original lines 3 and 4 to be merged, + +The last line 5 is similar to line 2 but the parameter value has a sppace so must be wrapped in quotes +#> + +<#https://www.guru99.com/first-webdriver-script.html had this +public static void main(String[] args) { + System.setProperty("webdriver.gecko.driver","C:\\geckodriver.exe"); + WebDriver driver = new FirefoxDriver(); + //comment the above 2 lines and uncomment below 2 lines to use Chrome + //System.setProperty("webdriver.chrome.driver","G:\\chromedriver.exe"); + //WebDriver driver = new ChromeDriver(); + + String baseUrl = "http://demo.guru99.com/test/newtours/"; + driver.get(baseUrl); + + String expectedTitle = "Welcome: Mercury Tours"; + String actualTitle = ""; + actualTitle = driver.getTitle(); + if (actualTitle.contentEquals(expectedTitle)){ + System.out.println("Test Passed!"); + } else { + System.out.println("Test Failed"); + } + + driver.close(); +} +#> + +Start-SeDriver -Browser Firefox -StartURL "http://demo.guru99.com/test/newtours/" +SeShouldHave -Title eq "Welcome: Mercury Tours" + +#Stop opened drivers +Get-SeDriver | Stop-SeDriver + diff --git a/Examples/test-seremote.ps1 b/Examples/test-seremote.ps1 new file mode 100644 index 0000000..56bfebb --- /dev/null +++ b/Examples/test-seremote.ps1 @@ -0,0 +1,134 @@ +$PSGalleryPage = 'https://www.powershellgallery.com/' +$AlertTestPage = 'https://www.w3schools.com/js/tryit.asp?filename=tryjs_alert' +$SelectTestPage = 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_elem_select' + +#other services at +#https://crossbrowsertesting.com/freetrial / https://help.crossbrowsertesting.com/selenium-testing/getting-started/c-sharp/ +#https://www.browserstack.com/automate/c-sharp + +$key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +$secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +$RemoteDriverURL = [uri]"http://$key`:$secret@hub.testingbot.com/wd/hub" +$caps = @{ + platform = 'HIGH-SIERRA' + browserName = 'safari' + version = '11' +} + +Start-SeRemote -RemoteAddress $RemoteDriverURL -DesiredCapabilities $caps -AsDefaultDriver -StartURL $PSGalleryPage +$BrowserID = $SeDriver.Capabilities.ToDictionary()["platformName", "browserName", "version"] -join " " + +Describe "All in one Test" { + Context "in $BrowserID with settings ($BrowserOptText)"{ + It 'opened the put the webdriver in a global variable ' { + $Global:SeDriver | Should -Not -BeNullOrEmpty + $Global:SeDriver | Should -BeOfType [OpenQA.Selenium.Remote.RemoteWebDriver] + } + It 'reached the right starting page ' { + #Should have can check alerts, page title, URL or an element on the page + SeShouldHave -URL eq $PSGalleryPage + } + It 'found the "Sign in" link on the home page by partial text ' { + SeShouldHave -By PartialLinkText 'Sign in' -With href match logon + } + It 'found the search box on the home page by ID ' { + SeShouldHave -By Id search + } + It 'found the search box on the home page by Name ' { + SeShouldHave -By Name 'q' + } + It 'found the search box on the home page by css selector ' { + #can write -By <> [-selection] <> + # or [-selection] <> -By <> + SeShouldHave 'input[name=q]' -By CssSelector + } + It 'found the search box on the home page by class name ' { + SeShouldHave -By ClassName "search-box" + } + It 'found the search box on the home page by Tagname and typed in it ' { + #get element, pipe as input element for Typing, pass the element through + #so pester catches 'null or empty' if it was not found + SeElement -By TagName input | + SeType -ClearFirst "selenium{{Enter}}" -PassThru -Sleep 2 | Should -Not -BeNullorEmpty + } + $linkpath = '//*[@id="skippedToContent"]/section/div[1]/div[2]/div[2]/section[1]/div/table/tbody/tr/td[1]/div/div[2]/header/div[1]/h1/a' + It 'searched successfully ' { + SeShouldHave -URL match 'packages\?q=selenium' -Timeout 15 + #Two tests on the same element, second passes it through to click + SeShouldHave $linkpath -With href match selenium + SeShouldHave $linkpath -With Text like *selenium* -PassThru | SeClick -Sleep 5 + } + It 'opened the search result page and found the expected content ' { + #Just to show we can test for the presence of multiple links. Each one is re-tested ... + SeShouldHave '//*[@id="version-history"]/table/tbody[1]/tr[1]/ td[1]/a/b' , + '//*[@id="skippedToContent"]/section/div/aside/ul[2]/li[1]/a' -Timeout 15 + + SeShouldHave '//*[@id="version-history"]/table/tbody[1]/tr[1]/ td[1]/a/b' -With text match "current" + + #Can test with "Get-SeElement | where-object <>" rather than "with <> <> <>" + SeElement '//*[@id="skippedToContent"]/section/div/aside/ul[2]/li[1]/a' | + Where-Object {($_.text -like "*Project Site*") -and ($_.GetAttribute('href') -match "selenium") } | + SeClick -PassThru | Should -Not -Benullorempty + } + It 'went to Github from the project link on the search result ' { + SeShouldHave -URL match 'github' -Timeout 30 + } + + It 'navigated back to the start page ' { + SeNavigate -Back + SeNavigate -Back + SeNavigate -Back + SeShouldHave -URL eq $PSGalleryPage -Timeout 30 + } + It 'did a google Search ' { + SeNavigate 'https://www.google.com/ncr' + SeShouldHave -by Name q + SeShouldHave -by ClassName 'gLFyf' + SeShouldHave -By TagName input -With title eq 'Search' -PassThru | + Select-Object -First 1 | + SeType -Keys 'Powershell-Selenium{{Enter}}' -PassThru | should -Not -BeNullOrEmpty + + SeShouldHave '//*[@id="tsf"]/div[2]/div[1]/div[1]/a' -PassThru | + SeClick -PassThru | should -Not -BeNullOrEmpty + } + It 'opened the the alert test-page ' { + SeNavigate $alertTestPage + SeShouldHave -URL -eq $alertTestPage + } + It 'found and clicked a button in frame 1 ' { + SeShouldHave -Selection "iframe" -By TagName -with id eq iframeResult + SeFrame 'iframeResult' + SeElement "/html/body/button" | SeClick -PassThru | Should -Not -BeNullOrEmpty + } + It 'saw and dismissed an alert ' { + #Checking the text of the alert is optional. Dissmiss can pass the alert result through + SeShouldHave -Alert match "box" -PassThru | + SeDismiss -PassThru | Should -Not -BeNullOrEmpty + } + It 'reselected the parent frame ' { + SeFrame -Parent + SeShouldHave -Selection "iframe" -By TagName -with id eq iframeResult + } + It 'navigated to a new page, and found the "cars" selection box in frame 1 ' { + SeNavigate $SelectTestPage + SeShouldHave -Selection "iframe" -By TagName -with id eq iframeResult + SeFrame 'iframeResult' + SeShouldHave -By Name "cars" -With choice contains "volvo" + } + It 'made selections from the "cars" selection box ' { + $e = SeElement -by Name "cars" + #Values are lower case Text has inital caps comparisons are case sensitve. Index is 0-based + {$e | SeSelection -ByValue "Audi"} | Should -Throw + {$e | SeSelection -ByValue "audi"} | Should -Not -Throw + $e | SeSelection -ByIndex "2" -GetSelected | Should -Be 'Fiat' + $e | SeSelection -ByPartialText "Sa" + } + It 'submitted the form and got the expected response ' { + SeElement '/html/body/form/input' | SeClick -Sleep 5 + SeFrame -Parent + SeFrame 'iframeResult' + SeShouldHave "/html/body/div[1]" -with text match "cars=saab" + } + } +} +SeClose \ No newline at end of file diff --git a/Help/Clear-SeAlert.md b/Help/Clear-SeAlert.md new file mode 100644 index 0000000..449c4b8 --- /dev/null +++ b/Help/Clear-SeAlert.md @@ -0,0 +1,91 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Clear-SeAlert + +## SYNOPSIS +Clear alert popup by dismissing or accepting it. + +## SYNTAX + +``` +Clear-SeAlert [-Action ] [-Alert ] [-PassThru] [] +``` + +## DESCRIPTION +Clear alert popup by dismissing or accepting it. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Clear-SeAlert -Action Dismiss +``` + +Dismiss an alert on the currently selected driver. + +## PARAMETERS + +### -Action +Action to be performed on the alert popup + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: +Accepted values: Accept, Dismiss + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Alert +Specify alert window. Seems to be ignored in favor of Target / Default Target. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -PassThru +Return Alert object. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Clear-SeSelectValue.md b/Help/Clear-SeSelectValue.md new file mode 100644 index 0000000..75e5f0a --- /dev/null +++ b/Help/Clear-SeSelectValue.md @@ -0,0 +1,60 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Clear-SeSelectValue + +## SYNOPSIS +Clear all selected entries of a SELECT element. + +## SYNTAX + +``` +Clear-SeSelectValue [-Element] [] +``` + +## DESCRIPTION +Clear all selected entries of a SELECT element. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Clear-SeSelectValue -Element $Select +``` + +Clear the selected value from the specified SELECT element. + +## PARAMETERS + +### -Element +Target IWebElement + +```yaml +Type: IWebElement +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/ConvertTo-SeSelenium.md b/Help/ConvertTo-SeSelenium.md new file mode 100644 index 0000000..9466af4 --- /dev/null +++ b/Help/ConvertTo-SeSelenium.md @@ -0,0 +1,57 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# ConvertTo-Selenium + +## SYNOPSIS +Convert Selenium IDE .side recording file to PowerShell commands. + +## SYNTAX + +``` +ConvertTo-Selenium [-Path] [] +``` + +## DESCRIPTION +Convert Selenium IDE .side recording file to PowerShell commands. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> {{ Add example code here }} +``` + +{{ Add example description here }} + +## PARAMETERS + +### -Path +Path to .side file. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS diff --git a/Help/Get-SeCookie.md b/Help/Get-SeCookie.md new file mode 100644 index 0000000..97ecd40 --- /dev/null +++ b/Help/Get-SeCookie.md @@ -0,0 +1,45 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Get-SeCookie + +## SYNOPSIS +List all cookies + +## SYNTAX + +``` +Get-SeCookie [] +``` + +## DESCRIPTION +List all cookies + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Get-SeCookie +``` + +List all cookies of the default webdriver + +## PARAMETERS + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Get-SeDriver.md b/Help/Get-SeDriver.md new file mode 100644 index 0000000..e7f3dfd --- /dev/null +++ b/Help/Get-SeDriver.md @@ -0,0 +1,127 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Get-SeDriver + +## SYNOPSIS +Get the list of all active drivers. + +## SYNTAX + +### All (Default) +``` +Get-SeDriver [] +``` + +### Current +``` +Get-SeDriver [-Current] [] +``` + +### ByName +``` +Get-SeDriver [[-Name] ] [] +``` + +### ByBrowser +``` +Get-SeDriver [-Browser ] [] +``` + +## DESCRIPTION +Get the list of all active drivers or drivers matching the specified criterias. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Get-SeDriver +``` + +Return the list of all active drivers. + +### Example 2 +```powershell +PS C:\> Get-SeDriver -Current +``` + +Return the currently selected browser. + +### Example 3 +```powershell +PS C:\> Get-SeDriver -Browser Chrome +``` + +Returh the list of all active "Chrome" browsers. + +### Example 3 +```powershell +PS C:\> Get-SeDriver -Name '70c91e0f112dcdbd22b84dd567560b8d' +``` + +Return the driver with the specified name. + +## PARAMETERS + +### -Browser +Filter the list of returned drivers by their Browser type (enum: [SeBrowsers]) + +```yaml +Type: Object +Parameter Sets: ByBrowser +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Current +Return the currently selected browser. Selected browser is the last one started, unless changed via Switch-SeDriver and is always the one that get used in all cmdlet that have an unspecified $Driver. + +```yaml +Type: SwitchParameter +Parameter Sets: Current +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +Filter driver returned by its name (SeFriendlyName). + +```yaml +Type: String +Parameter Sets: ByName +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Get-SeDriverTimeout.md b/Help/Get-SeDriverTimeout.md new file mode 100644 index 0000000..d39b84b --- /dev/null +++ b/Help/Get-SeDriverTimeout.md @@ -0,0 +1,68 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Get-SeDriverTimeout + +## SYNOPSIS +Get the specified driver timeout value. + +## SYNTAX + +``` +Get-SeDriverTimeout [[-TimeoutType] ] [] +``` + +## DESCRIPTION +Get the specified driver timeout value. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Get-SeDriverTimeout +``` + +Return the currently selected driver implicit wait timeout. + +### Example 2 +```powershell +PS C:\> Get-SeDriverTimeout -TimeoutType PageLoad -Driver $Driver +``` + +Return the specified driver PageLoad timeout. + +## PARAMETERS + +### -TimeoutType +Timeout type to be changed + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: +Accepted values: ImplicitWait, PageLoad, AsynchronousJavaScript + +Required: False +Position: 0 +Default value: ImplicitWait +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebDriver + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Get-SeElement.md b/Help/Get-SeElement.md new file mode 100644 index 0000000..6187e5b --- /dev/null +++ b/Help/Get-SeElement.md @@ -0,0 +1,206 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Get-SeElement + +## SYNOPSIS + +Finds all IWebElements within the current context using the given mechanism + +## SYNTAX + +### Default (Default) +``` +Get-SeElement [-By ] [-Value] [[-Timeout] ] [-All] [-Attributes ] + [-Filter ] [-Single] [] +``` + +### ByElement +``` +Get-SeElement [-By ] [-Value] [-Element] [-All] + [-Attributes ] [-Filter ] [-Single] [] +``` + +## DESCRIPTION +Finds all IWebElements within the current context using the given mechanism. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Get-SeElement -By XPath '//*[@id="home_text3"]/div[2]' -Value '//*[@id="home_text3"]/div[2]' +#Same but positionally bound +PS C:\> Get-SeElement '//*[@id="home_text3"]/div[2]' +``` + +Get the elements matching the specified XPath selector. + +### Example 2 +```powershell +PS C:\> Get-SeElement -By Name -Value 'username' -Single +``` + +Get the username field by name with the expectation only one element is to be returned. + +### Example 3 +```powershell +PS C:\> Get-SeElement -By Name -Value 'username' -Single +``` + +Get the username field by name with the expectation only one element is to be returned. + +### Example 4 +```powershell +PS C:\> Get-SeElement -By ClassName -Value homeitem -All -Attributes name, id -Timeout 2.5 +#To return all attributes instead: -Attributes * +``` + +Get the elements by classname. Include hidden items `-All` and append an `Attributes` NoteProperty to all the result containing the value for the name and id attribute. The call will also fail if no results are found after 2.5 seconds. + +### Example 5 +```powershell +PS C:\> Get-SeElement -By ClassName,PartialLinkText -Value 'homeitem','The' +``` + +Get the elements that match the selectors in a sequential manner. This call will return all links that contains the defined text (The) within elements that have a classname of "homeitem". + +## PARAMETERS + +### -All +Return matching hidden items in addition to displayed ones. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Attributes +Append a list of Attributes (case sensitive) to each element returned. Attributes will be available through a dictionary property of the same name. Is the wildcard `*` character is used, all attributes will be queried and appended. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -By +The locating mechanism to use. It is possible to use multiple locator, in which case they will be processed sequentially. + +```yaml +Type: SeBySelector[] +Parameter Sets: (All) +Aliases: +Accepted values: ClassName, CssSelector, Id, LinkText, PartialLinkText, Name, TagName, XPath + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Element +Target IWebElement. + +```yaml +Type: IWebElement +Parameter Sets: ByElement +Aliases: + +Required: True +Position: 3 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Filter +Filter the obtained output with additional conditions. This is equivalent to doing a Where-Object afterward with the benefit of going trough the Get-SeElement error management. + +```yaml +Type: ScriptBlock +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Single +Expectation that only one element will be returned. An error will be returned if that parameter is set and more than one corresponding element is found. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Timeout +Timeout (in seconds) + +```yaml +Type: Double +Parameter Sets: Default +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Value +Locator Value corresponding to the `$By` selector. There should be an equal number of values than `$By` selector provided. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Get-SeElementAttribute.md b/Help/Get-SeElementAttribute.md new file mode 100644 index 0000000..46cb79a --- /dev/null +++ b/Help/Get-SeElementAttribute.md @@ -0,0 +1,76 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Get-SeElementAttribute + +## SYNOPSIS +Get the specified attribute from the specified element. + +## SYNTAX + +``` +Get-SeElementAttribute [-Element] [-Name] [] +``` + +## DESCRIPTION +Get the specified attribute from the specified element. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> $Element = Get-SeElement -By Name -Selection 'username' +PS C:\> Get-SeElementAttribute -Element $Element -Attribute 'placeholder' +``` + +Get the placeholder attribue of the username element. + +## PARAMETERS + +### -Element +Target IWebElement + +```yaml +Type: IWebElement +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Name +{{ Fill Name Description }} + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebElement + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Get-SeElementCssValue.md b/Help/Get-SeElementCssValue.md new file mode 100644 index 0000000..fa38693 --- /dev/null +++ b/Help/Get-SeElementCssValue.md @@ -0,0 +1,75 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Get-SeElementCssValue + +## SYNOPSIS +Get CSS value for the specified name of targeted element. + +## SYNTAX + +``` +Get-SeElementCssValue [-Element] [-Name] [] +``` + +## DESCRIPTION +Get CSS value for the specified name of targeted element. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Get-SeElementCssValue -Element $Element -Name 'padding' +``` + +Get padding css value for the targeted element. + +## PARAMETERS + +### -Element +Target IWebElement + +```yaml +Type: IWebElement +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Name +Name of the CSS attribute to query + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebElement + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Get-SeFrame.md b/Help/Get-SeFrame.md new file mode 100644 index 0000000..a888024 --- /dev/null +++ b/Help/Get-SeFrame.md @@ -0,0 +1,45 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Get-SeFrame + +## SYNOPSIS +{{ Fill in the Synopsis }} + +## SYNTAX + +``` +Get-SeFrame [] +``` + +## DESCRIPTION +{{ Fill in the Description }} + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> {{ Add example code here }} +``` + +{{ Add example description here }} + +## PARAMETERS + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Get-SeHtml.md b/Help/Get-SeHtml.md new file mode 100644 index 0000000..8e948d5 --- /dev/null +++ b/Help/Get-SeHtml.md @@ -0,0 +1,84 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Get-SeHtml + +## SYNOPSIS +Get outer html of the specified element or driver. + +## SYNTAX + +``` +Get-SeHtml [[-Element] ] [-Inner] [] +``` + +## DESCRIPTION +Get outer html of the specified element or driver. +Driver is used by default if no element is specified. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> $Element = Get-SeElement -By ClassName -Value 'homeitem' +PS C:\> $Element | Get-SeHtml -Inner +``` + +Get inner html for all specified elements. + +### Example 2 +```powershell +PS C:\> Get-SeHtml +``` + +Get html of the current page. Equivalent to $Driver.PageSource + +## PARAMETERS + +### -Element +Target IWebElement. + +```yaml +Type: IWebElement +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Inner +Return inner html instead. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Get-SeInput.md b/Help/Get-SeInput.md new file mode 100644 index 0000000..2461701 --- /dev/null +++ b/Help/Get-SeInput.md @@ -0,0 +1,151 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Get-SeInput + +## SYNOPSIS +Get element with an input tagname matching the specified conditions. + +## SYNTAX + +``` +Get-SeInput [[-Type] ] [-Single] [[-Text] ] [[-Timeout] ] [-All] + [[-Attributes] ] [[-Value] ] [] +``` + +## DESCRIPTION +Get SeElement with an input Tagname + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Get-SeInput -Attributes placeholder,title -All -Single -Value 'Type to search' +``` + +Get all the input (including hidden) present in the Dom and load the attributes placeholder and title. A single value is expected and it's attribute placeholder should be equals to : "Type to search" + +## PARAMETERS + +### -All +Return matching hidden items in addition to displayed ones. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Attributes +Append a list of Attributes (case sensitive) to each element returned. Attributes will be available through a dictionary property of the same name. Is the wildcard `*` character is used, all attributes will be queried and appended. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Single +Expectation that only one element will be returned. An error will be returned if that parameter is set and more than one corresponding element is found. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Text +Text of the input to return + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Timeout +Timeout (in seconds) + +```yaml +Type: Double +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Type +Type of the input + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Value +Expected value of the first attribute present. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 4 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Get-SeKeys.md b/Help/Get-SeKeys.md new file mode 100644 index 0000000..54470b6 --- /dev/null +++ b/Help/Get-SeKeys.md @@ -0,0 +1,44 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Get-SeKeys + +## SYNOPSIS +Return a list of the available special keys + +## SYNTAX + +``` +Get-SeKeys [] +``` + +## DESCRIPTION +Return a list of the available special keys. +These keys can be used with `Send-SeKeys` by using their name in the following format `{{SpecialKeyName}}` + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Get-SeKeys +``` + +## PARAMETERS + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Get-SeSelectValue.md b/Help/Get-SeSelectValue.md new file mode 100644 index 0000000..bee385e --- /dev/null +++ b/Help/Get-SeSelectValue.md @@ -0,0 +1,75 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Get-SeSelectValue + +## SYNOPSIS +Get Select element selected value. + +## SYNTAX + +``` +Get-SeSelectValue [-Element] [-All] [] +``` + +## DESCRIPTION +Get Select element selected value. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Get-SeSelectValue -Element $Select +``` + +Get the selected value for the specified element. + +## PARAMETERS + +### -All +Get All selected values (only available when the Select element accept multiple values) + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Element +Target IWebElement. + +```yaml +Type: IWebElement +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebElement + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Get-SeUrl.md b/Help/Get-SeUrl.md new file mode 100644 index 0000000..c069208 --- /dev/null +++ b/Help/Get-SeUrl.md @@ -0,0 +1,65 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Get-SeUrl + +## SYNOPSIS +Retrieves the current URL of a target webdriver instance. + +## SYNTAX + +``` +Get-SeUrl [-Stack] [] +``` + +## DESCRIPTION +Retrieves the current URL of a target webdriver instance, or the currently +stored internal location stack. + +## EXAMPLES + +### EXAMPLE 1 +``` +Get-SeUrl +``` + +Retrieves the current URL of the default webdriver instance. + +## PARAMETERS + +### -Stack +Optionally retrieve the stored URL stack for the target or default +webdriver instance. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES +When using -Stack, the retrieved stack will not contain any of the driver's +history (Back/Forward) data. +It only handles locations added with +Push-SeUrl. + +To utilise a driver's Back/Forward functionality, instead use Set-SeUrl. + +## RELATED LINKS diff --git a/Help/Get-SeWindow.md b/Help/Get-SeWindow.md new file mode 100644 index 0000000..63ff25b --- /dev/null +++ b/Help/Get-SeWindow.md @@ -0,0 +1,45 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Get-SeWindow + +## SYNOPSIS +Gets the window handles of open browser windows + +## SYNTAX + +``` +Get-SeWindow [] +``` + +## DESCRIPTION +Gets the window handles of open browser windows + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Get-SeWindow +``` + +Gets the window handles of open browser windows. + +## PARAMETERS + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebDriver + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Invoke-SeClick.md b/Help/Invoke-SeClick.md new file mode 100644 index 0000000..4cbe3b8 --- /dev/null +++ b/Help/Invoke-SeClick.md @@ -0,0 +1,113 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Invoke-SeClick + +## SYNOPSIS +Perform a click in the browser window or specified element. + +## SYNTAX + +``` +Invoke-SeClick [[-Action] ] [[-Element] ] [-Sleep ] [-PassThru] + [] +``` + +## DESCRIPTION +Perform a click in the browser window or specified element. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Invoke-SeClick +``` + +Perform a click in the browser at the current position + +### Example 2 +```powershell +PS C:\> Invoke-SeClick -Action Click_JS -Element $Element +``` + +Perform a javascript click on the specified element. + +## PARAMETERS + +### -Action +test + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Element +Target IWebElement. + +```yaml +Type: IWebElement +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -PassThru +Return the IWebElement. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Sleep +Sleep time in second after performing the click action. + +```yaml +Type: Double +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebElement + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Invoke-SeJavascript.md b/Help/Invoke-SeJavascript.md new file mode 100644 index 0000000..eef6086 --- /dev/null +++ b/Help/Invoke-SeJavascript.md @@ -0,0 +1,75 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Invoke-SeJavascript + +## SYNOPSIS +Invoke Javascript in the specified Driver. + +## SYNTAX + +``` +Invoke-SeJavascript [[-Script] ] [[-ArgumentList] ] [] +``` + +## DESCRIPTION +Invoke Javascript in the specified Driver. arguments will be passed to the javascript as "argument[0]" (where 0 is the argument position) + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Invoke-SeJavascript -Script 'arguments[0].click()' -ArgumentList $Element +``` + +Perform a javascript click on the specified element. + +## PARAMETERS + +### -ArgumentList +Argument list to be passed down to the script. + +```yaml +Type: Object[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Script +Javascript script to be executed. Arguments passed down can be used in the scripts through `arguments[0],arguments[1]`,etc... + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebDriver + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Invoke-SeKeys.md b/Help/Invoke-SeKeys.md new file mode 100644 index 0000000..addac71 --- /dev/null +++ b/Help/Invoke-SeKeys.md @@ -0,0 +1,137 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Invoke-SeKeys + +## SYNOPSIS +Send the keys to the browser or specified element. + +## SYNTAX + +``` +Invoke-SeKeys [[-Element] ] [-Keys] [-ClearFirst] [-Sleep ] [-Submit] [-PassThru] + [] +``` + +## DESCRIPTION +The text to be typed may include special characters like arrow keys, backspaces, function keys, and so on. Valid special keys are defined in Keys. [OpenQA_Selelnium_Keys](https://www.selenium.dev/selenium/docs/api/dotnet/html/T_OpenQA_Selenium_Keys.htm) + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> $Search = Get-SeElement -By TagName -Value input -Single +PS C:\> Invoke-SeKeys -Element $Search -Keys 'Powershell-Selenium{{Enter}}' +``` + +Type the defined text and a special key - Enter - defined in the special keys. + +## PARAMETERS + +### -ClearFirst +Clear the element existing text first + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Element +Target IWebElement. + +```yaml +Type: IWebElement +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Keys +Text to be typed. Special keys (Enter, arrow down, etc...) can be typed using double brackets (eg: `{{Enter}}`). See cmdlet description for complete list of keys + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PassThru +Return the IWebElement or webdriver + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Sleep +Sleep time in second after performing the type action. + +```yaml +Type: Double +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Submit +Call submit on the specified element. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebElement + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Invoke-SeMouseAction.md b/Help/Invoke-SeMouseAction.md new file mode 100644 index 0000000..ad7d93e --- /dev/null +++ b/Help/Invoke-SeMouseAction.md @@ -0,0 +1,90 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Invoke-SeMouseAction + +## SYNOPSIS +Perform mouse move & drag actions. + +## SYNTAX + +``` +Invoke-SeMouseAction [[-Action] ] [[-Value] ] [[-Element] ] [] +``` + +## DESCRIPTION +Perform mouse move & drag actions. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Invoke-SeMouseAction -Element $SourceElement -Action DragAndDrop -Value $DestinationElement +``` + +Perform a drag&drop operation from the source element to destination element. + +## PARAMETERS + +### -Action +Action to be performed. Intellisense tooltip provide details regarding expected value. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Element +{{ Fill Element Description }} + +```yaml +Type: IWebElement +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Value +Value expected by the specified action. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/New-SeDriverOptions.md b/Help/New-SeDriverOptions.md new file mode 100644 index 0000000..4e47e91 --- /dev/null +++ b/Help/New-SeDriverOptions.md @@ -0,0 +1,301 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# New-SeDriverOptions + +## SYNOPSIS +Create a driver options object that can be used with `Start-SeDriver` + +## SYNTAX + +``` +New-SeDriverOptions [-Browser ] [[-StartURL] ] [-State ] + [-DefaultDownloadPath ] [-PrivateBrowsing] [-ImplicitWait ] [-Size ] + [-Position ] [-WebDriverPath ] [-BinaryPath ] [-Switches ] + [-Arguments ] [-ProfilePath ] [-LogLevel ] [-UserAgent ] + [-AcceptInsecureCertificates] [] +``` + +## DESCRIPTION +Create a driver options object that can be used with `Start-SeDriver` + +This allow for more flexibility than the Start-SeDriver cmdlet as you can perform additional things with the driver options before starting the driver. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> $Options = New-SeDriverOptions -Browser Chrome -Position 1920x0 -Size 1920x1080 +PS C:\> $Options.AddAdditionalCapability('useAutomationExtension', $false) +PS C:\> Start-SeDriver -Options $Options +``` + +Create a Chrome driver option object to perform additional things unsupported directly by Start-SeDriver, such as adding an additional capability, then Start a driver instance with the modified Chrome driver options object. + +## PARAMETERS + +### -AcceptInsecureCertificates +If set, Ignore SSL certificate error (Chrome,Edge,Firefox) + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Arguments +Command line arguments to be passed to the browser. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -BinaryPath +{{ Fill BinaryPath Description }} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Browser +Browser name to be started. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DefaultDownloadPath +{{ Fill DefaultDownloadPath Description }} + +```yaml +Type: FileInfo +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ImplicitWait +Maximum time that the browser will implicitely wait between operations + +```yaml +Type: Double +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -LogLevel +{{ Fill LogLevel Description }} + +```yaml +Type: LogLevel +Parameter Sets: (All) +Aliases: +Accepted values: All, Debug, Info, Warning, Severe, Off + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Position +Position of the browser to be set on or after launch. Some browser might not support position to be set prior launch and will have their position set after launch. + +```yaml +Type: Point +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PrivateBrowsing +Launch the browser in a private session + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProfilePath +{{ Fill ProfilePath Description }} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Size +Size of the browser to be set on or after launch. Some browser might not support size to be set prior launch and will have their size set after launch. + +```yaml +Type: Size +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -StartURL +Start URL to be set immediately after launch. If no protocol is specified, https will be assumed. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -State +Window state of the browser. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Switches +Special switches (additional legacy options that might appear for some browser ) + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -UserAgent +UserAgent to be set. Supported by Chrome & Firefox + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WebDriverPath +Location of the web driver to be used. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### OpenQA.Selenium.Chrome.ChromeOptions + +### OpenQA.Selenium.Edge.EdgeOptions + +### OpenQA.Selenium.Firefox.FirefoxOptions + +### OpenQA.Selenium.IE.InternetExplorerOptions + +## NOTES + +## RELATED LINKS diff --git a/Help/New-SeDriverService.md b/Help/New-SeDriverService.md new file mode 100644 index 0000000..3447c0b --- /dev/null +++ b/Help/New-SeDriverService.md @@ -0,0 +1,86 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# New-SeDriverService + +## SYNOPSIS +Create an instance of WebDriver service to be used with Start-SeDriver + +## SYNTAX + +``` +New-SeDriverService [-Browser ] [-WebDriverPath ] [] +``` + +## DESCRIPTION +Create an instance of WebDriver service to be used with Start-SeDriver + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> $Service = New-SeDriverService -Browser Chrome +PS C:\> $Service.PortServerAddress = 100 +PS C:\> $Options = New-SeDriverOptions -Browser Chrome -Position 1920x0 -Size 1920x1080 +PS C:\> Start-SeDriver -Service $Service -Options $Options +PS C:\> $Service.ProcessId +``` + +Create a new instance of Chrome driver service, set a custom port and start the driver with the modified service instance. + +## PARAMETERS + +### -Browser +Browser name + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WebDriverPath +Location of the web driver to be used. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### OpenQA.Selenium.Chrome.ChromeDriverService + +### OpenQA.Selenium.Firefox.FirefoxDriverService + +### OpenQA.Selenium.IE.InternetExplorerDriverService + +### OpenQA.Selenium.Edge.EdgeDriverService + +## NOTES + +## RELATED LINKS diff --git a/Help/New-SeScreenshot.md b/Help/New-SeScreenshot.md new file mode 100644 index 0000000..d5fd381 --- /dev/null +++ b/Help/New-SeScreenshot.md @@ -0,0 +1,101 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# New-SeScreenshot + +## SYNOPSIS +Take a screenshot of the current page + +## SYNTAX + +### Driver (Default) +``` +New-SeScreenshot [-AsBase64EncodedString] [] +``` + +### Pipeline +``` +New-SeScreenshot [-InputObject ] [-AsBase64EncodedString] [] +``` + +### Element +``` +New-SeScreenshot [-AsBase64EncodedString] [-Element ] [] +``` + +## DESCRIPTION +Take a screenshot of the current page + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> $Element | New-SeScreenshot +``` + +Take a screenshot of the specified element. + +## PARAMETERS + +### -AsBase64EncodedString +Return image as base64 string + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Element +Target IWebElement. + +```yaml +Type: IWebElement +Parameter Sets: Element +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -InputObject +Target IWebElement. + +```yaml +Type: Object +Parameter Sets: Pipeline +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/New-SeWindow.md b/Help/New-SeWindow.md new file mode 100644 index 0000000..1d2131a --- /dev/null +++ b/Help/New-SeWindow.md @@ -0,0 +1,60 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# New-SeWindow + +## SYNOPSIS +{{ Fill in the Synopsis }} + +## SYNTAX + +``` +New-SeWindow [[-Url] ] [] +``` + +## DESCRIPTION +{{ Fill in the Description }} + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> {{ Add example code here }} +``` + +{{ Add example description here }} + +## PARAMETERS + +### -Url +{{ Fill Url Description }} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebDriver + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Pop-SeUrl.md b/Help/Pop-SeUrl.md new file mode 100644 index 0000000..471e5c2 --- /dev/null +++ b/Help/Pop-SeUrl.md @@ -0,0 +1,49 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Pop-SeUrl + +## SYNOPSIS +Navigate back to the most recently pushed URL in the location stack. + +## SYNTAX + +``` +Pop-SeUrl [] +``` + +## DESCRIPTION +Retrieves the most recently pushed URL from the location stack and navigates +to that URL with the specified or default driver. + +## EXAMPLES + +### EXAMPLE 1 +``` +Pop-SeUrl +``` + +Retrieves the most recently pushed URL and navigates back to that URL. + +## PARAMETERS + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES +A separate internal location stack is maintained for each driver instance +by the module. +This stack is completely separate from the driver's internal +Back/Forward history logic. + +To utilise a driver's Back/Forward functionality, instead use Set-SeUrl. + +## RELATED LINKS diff --git a/Help/Push-SeUrl.md b/Help/Push-SeUrl.md new file mode 100644 index 0000000..d043e06 --- /dev/null +++ b/Help/Push-SeUrl.md @@ -0,0 +1,73 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Push-SeUrl + +## SYNOPSIS +Stores the current URL in the driver's location stack and optionally +navigate to a new URL. + +## SYNTAX + +``` +Push-SeUrl [[-Url] ] [] +``` + +## DESCRIPTION +The current driver URL is added to the stack, and if a URL is provided, the +driver navigates to the new URL. + +## EXAMPLES + +### EXAMPLE 1 +``` +Push-SeUrl +``` + +The current driver URL is added to the location stack. + +### EXAMPLE 2 +``` +Push-SeUrl 'https://google.com/' +``` + +The current driver URL is added to the location stack, and the driver then +navigates to the provided target URL. + +## PARAMETERS + +### -Url +The new URL to navigate to after storing the current location. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES +A separate internal location stack is maintained for each driver instance +by the module. +This stack is completely separate from the driver's internal +Back/Forward history logic. + +To utilise a driver's Back/Forward functionality, instead use Set-SeUrl. + +## RELATED LINKS diff --git a/Help/README.MD b/Help/README.MD new file mode 100644 index 0000000..bb45ddb --- /dev/null +++ b/Help/README.MD @@ -0,0 +1,138 @@ +--- +Module Name: Selenium +Module Guid: {{ Update Module Guid }} +Download Help Link: {{ Update Download Link }} +Help Version: {{ Update Help Version }} +Locale: {{ Update Locale }} +--- + +# Selenium Module +## Description +{{ Fill in the Description }} + +## Selenium Cmdlets +### [Clear-SeAlert](Clear-SeAlert.md) +Clear alert popup by dismissing or accepting it. + +### [Clear-SeSelectValue](Clear-SeSelectValue.md) +Clear all selected entries of a SELECT element. + +### [Get-SeCookie](Get-SeCookie.md) +List all cookies + +### [Get-SeDriver](Get-SeDriver.md) +Get the list of all active drivers. + +### [Get-SeDriverTimeout](Get-SeDriverTimeout.md) +Get the specified driver timeout value. + +### [Get-SeElement](Get-SeElement.md) + +Finds all IWebElements within the current context using the given mechanism + +### [Get-SeElementAttribute](Get-SeElementAttribute.md) +Get the specified attribute from the specified element. + +### [Get-SeElementCssValue](Get-SeElementCssValue.md) +Get CSS value for the specified name of targeted element. + +### [Get-SeFrame](Get-SeFrame.md) +{{ Fill in the Synopsis }} + +### [Get-SeHtml](Get-SeHtml.md) +Get outer html of the specified element or driver. + +### [Get-SeInput](Get-SeInput.md) +Get element with an input tagname matching the specified conditions. + +### [Get-SeKeys](Get-SeKeys.md) +Return a list of the available special keys + +### [Get-SeSelectValue](Get-SeSelectValue.md) +Get Select element selected value. + +### [Get-SeUrl](Get-SeUrl.md) +Retrieves the current URL of a target webdriver instance. + +### [Get-SeWindow](Get-SeWindow.md) +Gets the window handles of open browser windows + +### [Invoke-SeClick](Invoke-SeClick.md) +Perform a click in the browser window or specified element. + +### [Invoke-SeJavascript](Invoke-SeJavascript.md) +Invoke Javascript in the specified Driver. + +### [Invoke-SeKeys](Invoke-SeKeys.md) +Send the keys to the browser or specified element. + +### [Invoke-SeMouseAction](Invoke-SeMouseAction.md) +Perform mouse move & drag actions. + +### [New-SeDriverOptions](New-SeDriverOptions.md) +Create a driver options object that can be used with `Start-SeDriver` + +### [New-SeDriverService](New-SeDriverService.md) +Create an instance of WebDriver service to be used with Start-SeDriver + +### [New-SeScreenshot](New-SeScreenshot.md) +Take a screenshot of the current page + +### [New-SeWindow](New-SeWindow.md) +{{ Fill in the Synopsis }} + +### [Pop-SeUrl](Pop-SeUrl.md) +Navigate back to the most recently pushed URL in the location stack. + +### [Push-SeUrl](Push-SeUrl.md) +Stores the current URL in the driver's location stack and optionally +navigate to a new URL. + +### [Remove-SeCookie](Remove-SeCookie.md) +Delete the named cookie from the current domain + +### [Remove-SeWindow](Remove-SeWindow.md) +{{ Fill in the Synopsis }} + +### [Save-SeScreenshot](Save-SeScreenshot.md) +Save a screenshot on the disk. + +### [Set-SeCookie](Set-SeCookie.md) +Add a cookie to the current browsing context + +### [Set-SeDriverTimeout](Set-SeDriverTimeout.md) +Set the various driver timeouts default. + +### [Set-SeSelectValue](Set-SeSelectValue.md) +Set Select element selected value. + +### [Set-SeUrl](Set-SeUrl.md) +Navigates to the targeted URL with the selected or default driver. + +### [Start-SeDriver](Start-SeDriver.md) +Launch the specified browser. + +### [Start-SeRemote](Start-SeRemote.md) +Start a remote driver session. + +### [Stop-SeDriver](Stop-SeDriver.md) +Quits this driver, closing every associated window. + +### [Switch-SeDriver](Switch-SeDriver.md) +Select a driver, making it the default to be used with any ulterior calls whenever the driver parameter is not specified. + +### [Switch-SeFrame](Switch-SeFrame.md) +Instructs the driver to send future commands to a different frame + +### [Switch-SeWindow](Switch-SeWindow.md) +Instructs the driver to send future commands to a different window + +### [Update-SeDriver](Update-SeDriver.md) +{{ Fill in the Synopsis }} + +### [Wait-SeDriver](Wait-SeDriver.md) +Wait for the driver to be in the desired state. + +### [Wait-SeElement](Wait-SeElement.md) +Wait for an element condition to be met. + diff --git a/Help/Remove-SeCookie.md b/Help/Remove-SeCookie.md new file mode 100644 index 0000000..2eab7be --- /dev/null +++ b/Help/Remove-SeCookie.md @@ -0,0 +1,88 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Remove-SeCookie + +## SYNOPSIS +Delete the named cookie from the current domain + +## SYNTAX + +### All +``` +Remove-SeCookie [-All] [] +``` + +### NamedCookie +``` +Remove-SeCookie -Name [] +``` + +## DESCRIPTION +Delete the named cookie from the current domain + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Remove-SeCookie -Name 'CookieName' +``` + +Remove cookie from targeted Driver + +### Example 2 +```powershell +PS C:\> Remove-SeCookie -DeleteAllCookies +``` + +Remove all cookies from targeted Driver + +## PARAMETERS + +### -All +Clear all cookies. + +```yaml +Type: SwitchParameter +Parameter Sets: All +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +Cookie name to remove + +```yaml +Type: String +Parameter Sets: NamedCookie +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebDriver + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Remove-SeWindow.md b/Help/Remove-SeWindow.md new file mode 100644 index 0000000..2dcc6d2 --- /dev/null +++ b/Help/Remove-SeWindow.md @@ -0,0 +1,60 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Remove-SeWindow + +## SYNOPSIS +{{ Fill in the Synopsis }} + +## SYNTAX + +``` +Remove-SeWindow [[-SwitchToWindow] ] [] +``` + +## DESCRIPTION +{{ Fill in the Description }} + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> {{ Add example code here }} +``` + +{{ Add example description here }} + +## PARAMETERS + +### -SwitchToWindow +{{ Fill SwitchToWindow Description }} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebDriver + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Save-SeScreenshot.md b/Help/Save-SeScreenshot.md new file mode 100644 index 0000000..d500ff2 --- /dev/null +++ b/Help/Save-SeScreenshot.md @@ -0,0 +1,143 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Save-SeScreenshot + +## SYNOPSIS +Save a screenshot on the disk. + +## SYNTAX + +### Driver (Default) +``` +Save-SeScreenshot -Path [-ImageFormat ] [] +``` + +### Pipeline +``` +Save-SeScreenshot [-InputObject ] -Path [-ImageFormat ] + [] +``` + +### Screenshot +``` +Save-SeScreenshot -Screenshot -Path [-ImageFormat ] + [] +``` + +### Element +``` +Save-SeScreenshot -Path [-ImageFormat ] -Element + [] +``` + +## DESCRIPTION +Save the screenshot at the specified location. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> $Screenshot = New-SeScreenshot +PS C:\> Save-SeScreenshot -Screenshot $Screenshot -Path 'c:\temp\image.png' -ImageFormat Png +``` + +Create then save a screenshot to disk. + +## PARAMETERS + +### -Element +{{ Fill Element Description }} + +```yaml +Type: IWebElement +Parameter Sets: Element +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ImageFormat +Image format for the file to be saved. + +```yaml +Type: ScreenshotImageFormat +Parameter Sets: (All) +Aliases: +Accepted values: Png, Jpeg, Gif, Tiff, Bmp + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -InputObject +{{ Fill InputObject Description }} + +```yaml +Type: Object +Parameter Sets: Pipeline +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Path +Filepath where the image will be saved. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Screenshot +Screenshot object. + +```yaml +Type: Screenshot +Parameter Sets: Screenshot +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + +### OpenQA.Selenium.Screenshot + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/SeShouldHave.md b/Help/SeShouldHave.md new file mode 100644 index 0000000..3d24749 --- /dev/null +++ b/Help/SeShouldHave.md @@ -0,0 +1,252 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# SeShouldHave + +## SYNOPSIS +{{ Fill in the Synopsis }} + +## SYNTAX + +### DefaultPS (Default) +``` +SeShouldHave [-Selection] [-By ] [-PassThru] [-Timeout ] [] +``` + +### Element +``` +SeShouldHave [-Selection] [-By ] [-With] [[-Operator] ] [[-Value] ] + [-PassThru] [-Timeout ] [] +``` + +### Alert +``` +SeShouldHave [-Alert] [[-Operator] ] [[-Value] ] [-PassThru] [-Timeout ] + [] +``` + +### NoAlert +``` +SeShouldHave [-NoAlert] [-Timeout ] [] +``` + +### Title +``` +SeShouldHave [-Title] [[-Operator] ] [-Value] [-Timeout ] [] +``` + +### URL +``` +SeShouldHave [-URL] [[-Operator] ] [-Value] [-Timeout ] [] +``` + +## DESCRIPTION +{{ Fill in the Description }} + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> {{ Add example code here }} +``` + +{{ Add example description here }} + +## PARAMETERS + +### -Alert +{{ Fill Alert Description }} + +```yaml +Type: SwitchParameter +Parameter Sets: Alert +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -By +{{ Fill By Description }} + +```yaml +Type: String +Parameter Sets: DefaultPS, Element +Aliases: +Accepted values: CssSelector, Name, Id, ClassName, LinkText, PartialLinkText, TagName, XPath + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NoAlert +{{ Fill NoAlert Description }} + +```yaml +Type: SwitchParameter +Parameter Sets: NoAlert +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Operator +{{ Fill Operator Description }} + +```yaml +Type: String +Parameter Sets: Element, Alert, Title, URL +Aliases: +Accepted values: like, notlike, match, notmatch, contains, eq, ne, gt, lt + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PassThru +{{ Fill PassThru Description }} + +```yaml +Type: SwitchParameter +Parameter Sets: DefaultPS, Element, Alert +Aliases: PT + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Selection +{{ Fill Selection Description }} + +```yaml +Type: String[] +Parameter Sets: DefaultPS, Element +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Timeout +{{ Fill Timeout Description }} + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Title +{{ Fill Title Description }} + +```yaml +Type: SwitchParameter +Parameter Sets: Title +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -URL +{{ Fill URL Description }} + +```yaml +Type: SwitchParameter +Parameter Sets: URL +Aliases: URI + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Value +{{ Fill Value Description }} + +```yaml +Type: Object +Parameter Sets: Element, Alert +Aliases: contains, like, notlike, match, notmatch, eq, ne, gt, lt + +Required: False +Position: 4 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +```yaml +Type: Object +Parameter Sets: Title, URL +Aliases: contains, like, notlike, match, notmatch, eq, ne, gt, lt + +Required: True +Position: 4 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -With +{{ Fill With Description }} + +```yaml +Type: String +Parameter Sets: Element +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.String[] + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Set-SeCookie.md b/Help/Set-SeCookie.md new file mode 100644 index 0000000..ef96844 --- /dev/null +++ b/Help/Set-SeCookie.md @@ -0,0 +1,114 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Set-SeCookie + +## SYNOPSIS +Add a cookie to the current browsing context + +## SYNTAX + +``` +Set-SeCookie [[-Name] ] [[-Value] ] [[-Path] ] [[-Domain] ] + [[-ExpiryDate] ] [] +``` + +## DESCRIPTION +Add a cookie to the current browsing context + +## EXAMPLES + +## PARAMETERS + +### -Domain +The domain of the cookie + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ExpiryDate +The expiration date of the cookie + +```yaml +Type: DateTime +Parameter Sets: (All) +Aliases: + +Required: False +Position: 4 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +The name of the cookie + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Path +The path of the cookie + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Value +The value of the cookie + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Set-SeDriverTimeout.md b/Help/Set-SeDriverTimeout.md new file mode 100644 index 0000000..52966bc --- /dev/null +++ b/Help/Set-SeDriverTimeout.md @@ -0,0 +1,76 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Set-SeDriverTimeout + +## SYNOPSIS +Set the various driver timeouts default. + +## SYNTAX + +``` +Set-SeDriverTimeout [[-TimeoutType] ] [[-Timeout] ] [] +``` + +## DESCRIPTION +Set the various driver timeouts default. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Set-SeDriverTimeout -TimeoutType ImplicitWait -Timeout 0 +``` + +Set Implicit wait timeout to 0 + +## PARAMETERS + +### -Timeout +Value in seconds + +```yaml +Type: Double +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -TimeoutType +Type of timeout to change. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: +Accepted values: ImplicitWait, PageLoad, AsynchronousJavaScript + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebDriver + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Set-SeSelectValue.md b/Help/Set-SeSelectValue.md new file mode 100644 index 0000000..b839863 --- /dev/null +++ b/Help/Set-SeSelectValue.md @@ -0,0 +1,91 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Set-SeSelectValue + +## SYNOPSIS +Set Select element selected value. + +## SYNTAX + +``` +Set-SeSelectValue [-By ] [-Element] [-value ] [] +``` + +## DESCRIPTION +Set Select element selected value. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Set-SeSelectValue -By Text -value 'Hello' -Element $Element +``` + +Set targeted Select element selected value to 'Hello' (by text) + +## PARAMETERS + +### -By +Selector to be used to set the value. + +```yaml +Type: SeBySelect +Parameter Sets: (All) +Aliases: +Accepted values: Index, Text, Value + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Element +Target IWebElement. + +```yaml +Type: IWebElement +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -value +Value to which the specified element will be set. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebElement + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Set-SeUrl.md b/Help/Set-SeUrl.md new file mode 100644 index 0000000..ae37bd2 --- /dev/null +++ b/Help/Set-SeUrl.md @@ -0,0 +1,165 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Set-SeUrl + +## SYNOPSIS +Navigates to the targeted URL with the selected or default driver. + +## SYNTAX + +### default (Default) +``` +Set-SeUrl [] +``` + +### url +``` +Set-SeUrl [-Url] [] +``` + +### back +``` +Set-SeUrl [-Back] [-Depth ] [] +``` + +### forward +``` +Set-SeUrl [-Forward] [-Depth ] [] +``` + +### refresh +``` +Set-SeUrl [-Refresh] [] +``` + +## DESCRIPTION +Used for webdriver navigation commands, either to specific target URLs or +for history (Back/Forward) navigation or refreshing the current page. + +## EXAMPLES + +### EXAMPLE 1 +``` +Set-SeUrl 'https://www.google.com/' +``` + +Directs the default driver to navigate to www.google.com. + +### EXAMPLE 2 +``` +Set-SeUrl -Refresh +``` + +Reloads the current page for the default driver. + +### EXAMPLE 3 +``` +Set-SeUrl -Target $Driver -Back +``` + +Directs the targeted webdriver instance to navigate Back in its history. + +### EXAMPLE 4 +``` +Set-SeUrl -Forward +``` + +Directs the default webdriver to navigate Forward in its history. + +## PARAMETERS + +### -Url +The target URL for the webdriver to navigate to. + +```yaml +Type: String +Parameter Sets: url +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Back +Trigger the Back history navigation action in the webdriver. + +```yaml +Type: SwitchParameter +Parameter Sets: back +Aliases: + +Required: True +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Forward +Trigger the Forward history navigation action in the webdriver. + +```yaml +Type: SwitchParameter +Parameter Sets: forward +Aliases: + +Required: True +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Refresh +Refresh the current page in the webdriver. + +```yaml +Type: SwitchParameter +Parameter Sets: refresh +Aliases: + +Required: True +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Depth +Number of time the action should be performed. + +```yaml +Type: Int32 +Parameter Sets: back, forward +Aliases: + +Required: False +Position: Named +Default value: 1 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES +The Back/Forward/Refresh logic is handled by the webdriver itself. +If you +need a more granular approach to handling which locations are saved or +retrieved, use Push-SeUrl or Pop-SeUrl to utilise a separately managed +location stack. + +## RELATED LINKS diff --git a/Help/Start-SeDriver.md b/Help/Start-SeDriver.md new file mode 100644 index 0000000..ba58f08 --- /dev/null +++ b/Help/Start-SeDriver.md @@ -0,0 +1,355 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Start-SeDriver + +## SYNOPSIS +Launch the specified browser. + +## SYNTAX + +### default (Default) +``` +Start-SeDriver [[-StartURL] ] [-State ] [-DefaultDownloadPath ] + [-PrivateBrowsing] [-ImplicitWait ] [-Size ] [-Position ] [-WebDriverPath ] + [-BinaryPath ] [-Arguments ] [-ProfilePath ] [-LogLevel ] [-Name ] + [-UserAgent ] [-AcceptInsecureCertificates] [] +``` + +### DriverOptions +``` +Start-SeDriver [-Browser ] [[-StartURL] ] [-State ] + [-DefaultDownloadPath ] [-PrivateBrowsing] [-ImplicitWait ] [-Size ] + [-Position ] [-WebDriverPath ] [-BinaryPath ] [-Service ] + -Options [-Arguments ] [-ProfilePath ] [-LogLevel ] + [-Name ] [-UserAgent ] [-AcceptInsecureCertificates] [] +``` + +### Default +``` +Start-SeDriver [-Browser ] [[-StartURL] ] [-State ] + [-DefaultDownloadPath ] [-PrivateBrowsing] [-ImplicitWait ] [-Size ] + [-Position ] [-WebDriverPath ] [-BinaryPath ] [-Switches ] + [-Arguments ] [-ProfilePath ] [-LogLevel ] [-Name ] [-UserAgent ] + [-AcceptInsecureCertificates] [] +``` + +## DESCRIPTION +Launch a driver instance of the specified browser. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Start-SeDriver -Browser Chrome -Position 1920x0 -StartURL 'google.com' +``` + +Start a Chrome browser at the specified position and starting URL + +## PARAMETERS + +### -AcceptInsecureCertificates +If set, Ignore SSL certificate error (Chrome,Edge,Firefox) + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Arguments +Command line arguments to be passed to the browser. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -BinaryPath +{{ Fill BinaryPath Description }} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Browser +Browser to be started. + +```yaml +Type: Object +Parameter Sets: DriverOptions, Default +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -DefaultDownloadPath +{{ Fill DefaultDownloadPath Description }} + +```yaml +Type: FileInfo +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ImplicitWait +Maximum time that the browser will implicitely wait between operations + +```yaml +Type: Double +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -LogLevel +{{ Fill LogLevel Description }} + +```yaml +Type: LogLevel +Parameter Sets: (All) +Aliases: +Accepted values: All, Debug, Info, Warning, Severe, Off + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +Friendly name of the browser. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Options +Driver Options object + +```yaml +Type: DriverOptions +Parameter Sets: DriverOptions +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Position +Position of the browser to be set on or after launch. Some browser might not support position to be set prior launch and will have their position set after launch. + +```yaml +Type: Point +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PrivateBrowsing +Launch the browser in a private session + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProfilePath +{{ Fill ProfilePath Description }} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Service +DriverService object to be used. + +```yaml +Type: DriverService +Parameter Sets: DriverOptions +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Size +Size of the browser to be set on or after launch. Some browser might not support size to be set prior launch and will have their size set after launch. + +```yaml +Type: Size +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -StartURL +Start URL to be set immediately after launch. If no protocol is specified, https will be assumed. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -State +Window state of the browser. + +```yaml +Type: SeWindowState +Parameter Sets: (All) +Aliases: +Accepted values: Headless, Default, Minimized, Maximized, Fullscreen + +Required: False +Position: Named +Default value: Default +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Switches +Special switches (additional legacy options that might appear for some browser ) + +```yaml +Type: String[] +Parameter Sets: Default +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -UserAgent +UserAgent to be set. Supported by Chrome & Firefox + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WebDriverPath +Location of the web driver to be used. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### OpenQA.Selenium.IWebDriver + +## NOTES + +## RELATED LINKS diff --git a/Help/Start-SeRemote.md b/Help/Start-SeRemote.md new file mode 100644 index 0000000..47e63b9 --- /dev/null +++ b/Help/Start-SeRemote.md @@ -0,0 +1,145 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Start-SeRemote + +## SYNOPSIS +Start a remote driver session. + +## SYNTAX + +``` +Start-SeRemote [-RemoteAddress ] [-DesiredCapabilities ] [[-StartURL] ] + [-ImplicitWait ] [-Size ] [-Position ] [] +``` + +## DESCRIPTION +Start a remote driver session. +you can a remote testing account with testing bot at https://testingbot.com/users/sign_up + +## EXAMPLES + +### Example 1 +```powershell +#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 +``` + +## PARAMETERS + +### -DesiredCapabilities +{{ Fill DesiredCapabilities Description }} + +```yaml +Type: Hashtable +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ImplicitWait +{{ Fill ImplicitWait Description }} + +```yaml +Type: Double +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Position +{{ Fill Position Description }} + +```yaml +Type: Point +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RemoteAddress +{{ Fill RemoteAddress Description }} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Size +{{ Fill Size Description }} + +```yaml +Type: Size +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -StartURL +{{ Fill StartURL Description }} + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Stop-SeDriver.md b/Help/Stop-SeDriver.md new file mode 100644 index 0000000..bdd3f38 --- /dev/null +++ b/Help/Stop-SeDriver.md @@ -0,0 +1,68 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Stop-SeDriver + +## SYNOPSIS +Quits this driver, closing every associated window. + +## SYNTAX + +``` +Stop-SeDriver [[-Driver] ] [] +``` + +## DESCRIPTION +Quits this driver, closing every associated window. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Stop-SeDriver -Target $Driver +``` + +Stop the specified driver + +### Example 1 +```powershell +PS C:\> Start-SeChrome -AsDefaultDriver +PS C:\> Stop-SeDriver +``` + +Stop the default driver, which was defined using the `-AsDefaultDriver` switch. + +## PARAMETERS + +### -Driver +Target WebDriver + +```yaml +Type: IWebDriver +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebDriver + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Switch-SeDriver.md b/Help/Switch-SeDriver.md new file mode 100644 index 0000000..dfb9a59 --- /dev/null +++ b/Help/Switch-SeDriver.md @@ -0,0 +1,89 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Switch-SeDriver + +## SYNOPSIS +Select a driver, making it the default to be used with any ulterior calls whenever the driver parameter is not specified. + +## SYNTAX + +### ByName (Default) +``` +Switch-SeDriver [-Name] [] +``` + +### ByDriver +``` +Switch-SeDriver [-Driver] [] +``` + +## DESCRIPTION +Select a driver, making it the default to be used with any ulterior calls whenever the driver parameter is not specified. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> $Driver = Start-SeDriver -Browser Chrome +# Chrome is the only and default driver +PS C:\> Get-SeDriver -Current +PS C:\> Start-SeDriver -Browser Firefox +# Firefox is now the default browser +PS C:\> Get-SeDriver -Current +PS C:\> Switch-SeDriver -Driver $Driver +# Chrome is the default browser again +PS C:\> Get-SeDriver -Current +``` + +This examples show the default browser changing from Chrome to Firefox when the second instance is launched, then set back to Chrome through Switch-SeDriver + +## PARAMETERS + +### -Driver +Target WebDriver + +```yaml +Type: IWebDriver +Parameter Sets: ByDriver +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Name +SeFriendlyName of the browser to select. + +```yaml +Type: String +Parameter Sets: ByName +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Switch-SeFrame.md b/Help/Switch-SeFrame.md new file mode 100644 index 0000000..8946ca1 --- /dev/null +++ b/Help/Switch-SeFrame.md @@ -0,0 +1,96 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Switch-SeFrame + +## SYNOPSIS +Instructs the driver to send future commands to a different frame + +## SYNTAX + +### Frame +``` +Switch-SeFrame [-Frame] [] +``` + +### Parent +``` +Switch-SeFrame [-Parent] [] +``` + +### Root +``` +Switch-SeFrame [-Root] [] +``` + +## DESCRIPTION +Instructs the driver to send future commands to a different frame + +## EXAMPLES + +### Example 1 + +## PARAMETERS + +### -Frame +{{ Fill Frame Description }} + +```yaml +Type: Object +Parameter Sets: Frame +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Parent +{{ Fill Parent Description }} + +```yaml +Type: SwitchParameter +Parameter Sets: Parent +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Root +{{ Fill Root Description }} + +```yaml +Type: SwitchParameter +Parameter Sets: Root +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Switch-SeWindow.md b/Help/Switch-SeWindow.md new file mode 100644 index 0000000..14b5a16 --- /dev/null +++ b/Help/Switch-SeWindow.md @@ -0,0 +1,53 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Switch-SeWindow + +## SYNOPSIS +Instructs the driver to send future commands to a different window + +## SYNTAX + +``` +Switch-SeWindow [-Window] [] +``` + +## DESCRIPTION +Instructs the driver to send future commands to a different window + +## EXAMPLES + +## PARAMETERS + +### -Window +{{ Fill Window Description }} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### OpenQA.Selenium.IWebDriver + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Update-SeDriver.md b/Help/Update-SeDriver.md new file mode 100644 index 0000000..42eaeee --- /dev/null +++ b/Help/Update-SeDriver.md @@ -0,0 +1,91 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Update-SeDriver + +## SYNOPSIS +{{ Fill in the Synopsis }} + +## SYNTAX + +``` +Update-SeDriver [[-Browser] ] [[-OS] ] [[-Path] ] [] +``` + +## DESCRIPTION +{{ Fill in the Description }} + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> {{ Add example code here }} +``` + +{{ Add example description here }} + +## PARAMETERS + +### -Browser +{{ Fill Browser Description }} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -OS +{{ Fill OS Description }} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: +Accepted values: Linux, Mac, Windows + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Path +{{ Fill Path Description }} + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Wait-SeDriver.md b/Help/Wait-SeDriver.md new file mode 100644 index 0000000..bf7ec25 --- /dev/null +++ b/Help/Wait-SeDriver.md @@ -0,0 +1,90 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Wait-SeDriver + +## SYNOPSIS +Wait for the driver to be in the desired state. + +## SYNTAX + +``` +Wait-SeDriver [-Condition] [-Value] [[-Timeout] ] [] +``` + +## DESCRIPTION +Wait for the driver to be in the desired state. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Wait-SeDriver -Condition UrlContains 'next-' -Timeout 5.5 +``` + +Wait 5.5 seconds for the driver URL to contains text "next-" + +## PARAMETERS + +### -Condition +Condition that is expected to be met. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Timeout +Time delimiter in second for which the operation should succeed. + +```yaml +Type: Double +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Value +Condition value expected to be met. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Help/Wait-SeElement.md b/Help/Wait-SeElement.md new file mode 100644 index 0000000..26caa2f --- /dev/null +++ b/Help/Wait-SeElement.md @@ -0,0 +1,144 @@ +--- +external help file: Selenium-help.xml +Module Name: Selenium +online version: +schema: 2.0.0 +--- + +# Wait-SeElement + +## SYNOPSIS +Wait for an element condition to be met. + +## SYNTAX + +### Element (Default) +``` +Wait-SeElement -Element [-Condition ] [-ConditionValue ] [-Timeout ] + [] +``` + +### Locator +``` +Wait-SeElement [[-By] ] [-Value] [-Condition ] [-ConditionValue ] + [-Timeout ] [] +``` + +## DESCRIPTION +Wait for an element condition to be met. + +## EXAMPLES + +### Example 1 +```powershell +PS C:\> Wait-SeElement -Element $Element -Condition StalenessOf +``` + +Wait for the specified element to not exist anymore in the DOM for 3 seconds (default timeout) + +## PARAMETERS + +### -By +Locator element. + +```yaml +Type: SeBySelector +Parameter Sets: Locator +Aliases: +Accepted values: ClassName, CssSelector, Id, LinkText, PartialLinkText, Name, TagName, XPath + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Condition +Condition expected to be met. Some condition are only available with locator or element. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ConditionValue +Value of the expected condition to be met. + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Element +Element that need to meet the condition. + +```yaml +Type: IWebElement +Parameter Sets: Element +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Timeout +Time delimiter in second for which the operation should succeed. + +```yaml +Type: Double +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Value +Value of the locator corresponding to the element that should match the Condition / ConditionValue. + +```yaml +Type: String +Parameter Sets: Locator +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.Object + +## OUTPUTS + +### System.Object +## NOTES + +## RELATED LINKS diff --git a/Internal/Disable-SeDriverImplicitTimeout.ps1 b/Internal/Disable-SeDriverImplicitTimeout.ps1 new file mode 100644 index 0000000..bd9afba --- /dev/null +++ b/Internal/Disable-SeDriverImplicitTimeout.ps1 @@ -0,0 +1,27 @@ +<# +.SYNOPSIS + Disable Implicitt wait on the specidifed driver +.DESCRIPTION + This cmdlet is used alongside the corresponding Enable cmdlet to temporarily disable + Implicit wait whenever explicit wait are used. +.EXAMPLE + PS C:\> $ImpTimeout = Disable-SeDriverImplicitTimeout -Driver $Driver + Disable implicit wait on the specified driver and return the old timespan. +.INPUTS + Inputs (if any) +.OUTPUTS + Implicit wait Timespan obtained before setting it to 0 +.NOTES + These cmdlet are used because mixing ImplicitWait and ExplicitWait can have unintended consequences. + Thus, implicit wait should always temporarily be disabled when using explicit wait statements. +#> +function Disable-SeDriverImplicitTimeout { + param( + [Parameter(ValueFromPipeline = $true)] + [OpenQA.Selenium.IWebDriver]$Driver + ) + $Output = $Driver.Manage().Timeouts().ImplicitWait + $Driver.Manage().Timeouts().ImplicitWait = 0 + return $Output +} + diff --git a/Internal/Enable-SeDriverImplicitTimeout .ps1 b/Internal/Enable-SeDriverImplicitTimeout .ps1 new file mode 100644 index 0000000..6f203a9 --- /dev/null +++ b/Internal/Enable-SeDriverImplicitTimeout .ps1 @@ -0,0 +1,24 @@ +<# +.SYNOPSIS + Enable ImplicitWait on the specified driver. +.DESCRIPTION + Enable ImplicitWait on the specified driver. See the corresponding Disable cmdlet for more information. +.EXAMPLE + PS C:\> Enable-SeDriverImplicitTimeout -Driver $Driver -Timeout $ImpTimeout + Explanation of what the example does +.INPUTS + Inputs (if any) +.OUTPUTS + Output (if any) +.NOTES + General notes +#> +function Enable-SeDriverImplicitTimeout { + param( + [Parameter(ValueFromPipeline = $true)] + [OpenQA.Selenium.IWebDriver]$Driver, + [timespan]$Timeout + ) + $Driver.Manage().Timeouts().ImplicitWait = $Timeout +} + diff --git a/Internal/Get-DriverProcessId.ps1 b/Internal/Get-DriverProcessId.ps1 new file mode 100644 index 0000000..49d6b51 --- /dev/null +++ b/Internal/Get-DriverProcessId.ps1 @@ -0,0 +1,18 @@ +function Get-DriverProcessId { + [CmdletBinding()] + param ( + $ServiceProcessId + ) + + $IsWindowsPowershell = $PSVersionTable.PSVersion.Major -lt 6 + + if ($IsWindowsPowershell) { + $Processes = Get-CimInstance -Class Win32_Process -Filter "ParentProcessId=$ServiceProcessId" + $BrowserProcess = $Processes | Where-Object { $_.Name -ne 'conhost.exe' } | Select-Object -First 1 -ExpandProperty ProcessId + } + else { + $BrowserProcess = (Get-Process).Where( { { $_.Parent.id -eq $ServiceProcessId -and $_.Name -ne 'conhost' } }, 'first').Id + } + return $BrowserProcess + +} \ No newline at end of file diff --git a/Internal/Get-OptionsSwitchValue.ps1 b/Internal/Get-OptionsSwitchValue.ps1 new file mode 100644 index 0000000..8be3b9d --- /dev/null +++ b/Internal/Get-OptionsSwitchValue.ps1 @@ -0,0 +1,5 @@ + +Function Get-OptionsSwitchValue($Switches, $Name) { + if ($null -eq $Switches -or -not $Switches.Contains($Name)) { Return $false } + return $True +} \ No newline at end of file diff --git a/Internal/Get-SeElementsConditionsValueType.ps1 b/Internal/Get-SeElementsConditionsValueType.ps1 new file mode 100644 index 0000000..3047752 --- /dev/null +++ b/Internal/Get-SeElementsConditionsValueType.ps1 @@ -0,0 +1,3 @@ +Function Get-SeElementsConditionsValueType($Text) { + return $Script:SeElementsConditions.Where( { $_.Text -eq $Text }, 'first')[0].ValueType +} \ No newline at end of file diff --git a/Internal/Get-WildcardsIndices.ps1 b/Internal/Get-WildcardsIndices.ps1 new file mode 100644 index 0000000..7ca5edb --- /dev/null +++ b/Internal/Get-WildcardsIndices.ps1 @@ -0,0 +1,16 @@ +Function Get-WildcardsIndices($Value) { + + $Escape = 0 + $Index = -1 + $Value.ToCharArray() | ForEach-Object { + $Index += 1 + $IsWildCard = $false + switch ($_) { + '`' { $Escape += 1; break } + '*' { $IsWildCard = $Escape % 2 -eq 0; $Escape = 0 } + Default { $Escape = 0 } + } + if ($IsWildCard) { return $Index } + + } +} \ No newline at end of file diff --git a/Internal/Init-SeDriver.ps1 b/Internal/Init-SeDriver.ps1 new file mode 100644 index 0000000..d1b15f4 --- /dev/null +++ b/Internal/Init-SeDriver.ps1 @@ -0,0 +1,23 @@ +function Init-SeDriver { + [CmdletBinding()] + param ($Element) + + IF ($null -NE $Element) { + $Driver = ($Element | Select-Object -First 1).WrappedDriver + } + $Driver = Get-SeDriver -Current -ErrorAction Stop + + if ($null -ne $Driver) { + return $Driver + } + else { + Throw [System.ArgumentNullException]::new("An available Driver could not be found.") + } + + + + + +} + + diff --git a/Internal/Start-SeChromeDriver.ps1 b/Internal/Start-SeChromeDriver.ps1 new file mode 100644 index 0000000..9daa6a5 --- /dev/null +++ b/Internal/Start-SeChromeDriver.ps1 @@ -0,0 +1,129 @@ +function Start-SeChromeDriver { + [cmdletbinding(DefaultParameterSetName = 'default')] + param( + [string]$StartURL, + [SeWindowState]$State, + [System.IO.FileInfo]$DefaultDownloadPath, + [switch]$PrivateBrowsing, + [Double]$ImplicitWait, + [System.Drawing.Size]$Size, + [System.Drawing.Point]$Position, + $WebDriverPath = $env:ChromeWebDriver, + $BinaryPath, + [OpenQA.Selenium.DriverService]$service, + [OpenQA.Selenium.DriverOptions]$Options, + [String[]]$Switches, + [OpenQA.Selenium.LogLevel]$LogLevel, + $UserAgent, + [Switch]$AcceptInsecureCertificates + + + + # [System.IO.FileInfo]$ProfilePath, + # $BinaryPath, + + # "user-data-dir=$ProfilePath" + + + + ) + + process { + #Additional Switches + $EnablePDFViewer = Get-OptionsSwitchValue -Switches $Switches -Name 'EnablePDFViewer' + $DisableAutomationExtension = Get-OptionsSwitchValue -Switches $Switches -Name 'DisableAutomationExtension' + + #region Process Additional Switches + if ($EnablePDFViewer) { $Options.AddUserProfilePreference('plugins', @{'always_open_pdf_externally' = $true; }) } + + if ($DisableAutomationExtension) { + $Options.AddAdditionalCapability('useAutomationExtension', $false) + $Options.AddExcludedArgument('enable-automation') + } + + #endregion + + if ($DefaultDownloadPath) { + Write-Verbose "Setting Default Download directory: $DefaultDownloadPath" + $Options.AddUserProfilePreference('download', @{'default_directory' = $($DefaultDownloadPath.FullName); 'prompt_for_download' = $false; }) + } + + if ($UserAgent) { + Write-Verbose "Setting User Agent: $UserAgent" + $Options.AddArgument("--user-agent=$UserAgent") + } + + if ($AcceptInsecureCertificates) { + Write-Verbose "AcceptInsecureCertificates capability set to: $($AcceptInsecureCertificates.IsPresent)" + $Options.AddAdditionalCapability([OpenQA.Selenium.Remote.CapabilityType]::AcceptInsecureCertificates, $true, $true) + } + + if ($ProfilePath) { + Write-Verbose "Setting Profile directory: $ProfilePath" + $Options.AddArgument("user-data-dir=$ProfilePath") + } + + if ($BinaryPath) { + Write-Verbose "Setting Chrome Binary directory: $BinaryPath" + $Options.BinaryLocation = "$BinaryPath" + } + + if ($PSBoundParameters.ContainsKey('LogLevel')) { + Write-Warning "LogLevel parameter is not implemented for $($Options.SeParams.Browser)" + } + + + + switch ($State) { + { $_ -eq [SeWindowState]::Headless } { $Options.AddArguments('headless') } + # { $_ -eq [SeWindowState]::Minimized } {} # No switches... Managed after launch + { $_ -eq [SeWindowState]::Maximized } { $Options.AddArguments('start-maximized') } + { $_ -eq [SeWindowState]::Fullscreen } { $Options.AddArguments('start-fullscreen') } + } + + if ($PrivateBrowsing) { + $Options.AddArguments('Incognito') + } + # $Location = @('--window-position=1921,0', '--window-size=1919,1080') + if ($PSBoundParameters.ContainsKey('Size')) { + $Options.AddArguments("--window-size=$($Size.Width),$($Size.Height)") + } + if ($PSBoundParameters.ContainsKey('Position')) { + $Options.AddArguments("--window-position=$($Position.X),$($Position.Y)") + } + + + + if (-not $PSBoundParameters.ContainsKey('Service')) { + $ServiceParams = @{} + if ($WebDriverPath) { $ServiceParams.Add('WebDriverPath', $WebDriverPath) } + $service = New-SeDriverService -Browser Chrome @ServiceParams + } + + + + $Driver = [OpenQA.Selenium.Chrome.ChromeDriver]::new($service, $Options) + if (-not $Driver) { Write-Warning "Web driver was not created"; return } + Add-Member -InputObject $Driver -MemberType NoteProperty -Name 'SeServiceProcessId' -Value $Service.ProcessID + #region post creation options + $Driver.Manage().Timeouts().ImplicitWait = [TimeSpan]::FromMilliseconds($ImplicitWait * 1000) + + if ($State -eq '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 + + + return $Driver + } +} + diff --git a/Internal/Start-SeEdgeDriver.ps1 b/Internal/Start-SeEdgeDriver.ps1 new file mode 100644 index 0000000..1f25ab5 --- /dev/null +++ b/Internal/Start-SeEdgeDriver.ps1 @@ -0,0 +1,118 @@ +function Start-SeEdgeDriver { + param( + [ValidateURIAttribute()] + [Parameter(Position = 1)] + [string]$StartURL, + [SeWindowState]$State, + [System.IO.FileInfo]$DefaultDownloadPath, + [switch]$PrivateBrowsing, + [Double]$ImplicitWait, + [System.Drawing.Size]$Size, + [System.Drawing.Point]$Position, + $WebDriverPath, + $BinaryPath, + [OpenQA.Selenium.DriverService]$service, + [OpenQA.Selenium.DriverOptions]$Options, + [String[]]$Switches, + [OpenQA.Selenium.LogLevel]$LogLevel, + [Switch]$AcceptInsecureCertificates + + ) + + if ($AcceptInsecureCertificates) { + Write-Verbose "AcceptInsecureCertificates capability set to: $($AcceptInsecureCertificates.IsPresent)" + $Options.AddAdditionalCapability([OpenQA.Selenium.Remote.CapabilityType]::AcceptInsecureCertificates, $true, $true) + } + + #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 + } + + if ($WebDriverPath -and -not (Test-Path -Path (Join-Path -Path $WebDriverPath -ChildPath 'msedgedriver.exe'))) { + throw "Could not find msedgedriver.exe in $WebDriverPath"; return + } + elseif ($WebDriverPath -and (Test-Path (Join-Path -Path $WebDriverPath -ChildPath 'msedge.exe'))) { + Write-Verbose -Message "Using browser from $WebDriverPath" + $Options.BinaryLocation = Join-Path -Path $WebDriverPath -ChildPath 'msedge.exe' + } + elseif ($BinaryPath) { + $Options.BinaryLocation = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($BinaryPath) + Write-Verbose -Message "Will request $($Options.BinaryLocation) as the browser" + } + + if ($PSBoundParameters.ContainsKey('LogLevel')) { + Write-Warning "LogLevel parameter is not implemented for $($Options.SeParams.Browser)" + } + + if (-not $WebDriverPath -and $binaryDir -and (Test-Path (Join-Path -Path $binaryDir -ChildPath 'msedgedriver.exe'))) { + $WebDriverPath = $binaryDir + } + # No linux or mac driver to test for yet + if (-not $WebDriverPath -and (Test-Path (Join-Path -Path "$PSScriptRoot\Assemblies\" -ChildPath 'msedgedriver.exe'))) { + $WebDriverPath = "$PSScriptRoot\Assemblies\" + Write-Verbose -Message "Using Web driver from the default location" + } + + if (-not $PSBoundParameters.ContainsKey('Service')) { + $ServiceParams = @{} + if ($WebDriverPath) { $ServiceParams.Add('WebDriverPath', $WebDriverPath) } + $service = New-SeDriverService -Browser Edge @ServiceParams + } + + #The command line args may now be --inprivate --headless but msedge driver V81 does not pass them + if ($PrivateBrowsing) { $options.AddArguments('InPrivate') } + if ($State -eq [SeWindowState]::Headless) { $options.AddArguments('headless') } + if ($ProfilePath) { + $ProfilePath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($ProfilePath) + Write-Verbose "Setting Profile directory: $ProfilePath" + $options.AddArgument("user-data-dir=$ProfilePath") + } + 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 { + Add-Member -InputObject $Driver -MemberType NoteProperty -Name 'SeServiceProcessId' -Value $Service.ProcessID + $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) + + $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." + } + } + + if ($PSBoundParameters.ContainsKey('Size')) { $Driver.Manage().Window.Size = $Size } + if ($PSBoundParameters.ContainsKey('Position')) { $Driver.Manage().Window.Position = $Position } + + $Driver.Manage().Timeouts().ImplicitWait = [TimeSpan]::FromMilliseconds($ImplicitWait * 1000) + if ($StartURL) { $Driver.Navigate().GoToUrl($StartURL) } + + + switch ($State) { + { $_ -eq [SeWindowState]::Minimized } { $Driver.Manage().Window.Minimize(); } + { $_ -eq [SeWindowState]::Maximized } { $Driver.Manage().Window.Maximize() } + { $_ -eq [SeWindowState]::Fullscreen } { $Driver.Manage().Window.FullScreen() } + } + + + #endregion + + return $Driver +} \ No newline at end of file diff --git a/Internal/Start-SeFirefoxDriver.ps1 b/Internal/Start-SeFirefoxDriver.ps1 new file mode 100644 index 0000000..29efb52 --- /dev/null +++ b/Internal/Start-SeFirefoxDriver.ps1 @@ -0,0 +1,80 @@ +function Start-SeFirefoxDriver { + [cmdletbinding(DefaultParameterSetName = 'default')] + param( + [string]$StartURL, + [SeWindowState]$State, + [System.IO.FileInfo]$DefaultDownloadPath, + [switch]$PrivateBrowsing, + [Double]$ImplicitWait, + [System.Drawing.Size]$Size, + [System.Drawing.Point]$Position, + $WebDriverPath = $env:GeckoWebDriver, + $BinaryPath, + [OpenQA.Selenium.DriverService]$service, + [OpenQA.Selenium.DriverOptions]$Options, + [String[]]$Switches, + [OpenQA.Selenium.LogLevel]$LogLevel, + [String]$UserAgent, + [Switch]$AcceptInsecureCertificates + + ) + process { + + if ($State -eq [SeWindowState]::Headless) { + $Options.AddArguments('-headless') + } + + if ($DefaultDownloadPath) { + Write-Verbose "Setting Default Download directory: $DefaultDownloadPath" + $Options.setPreference("browser.download.folderList", 2); + $Options.SetPreference("browser.download.dir", "$DefaultDownloadPath"); + } + + if ($UserAgent) { + Write-Verbose "Setting User Agent: $UserAgent" + $Options.SetPreference("general.useragent.override", $UserAgent) + } + + if ($AcceptInsecureCertificates) { + Write-Verbose "AcceptInsecureCertificates capability set to: $($AcceptInsecureCertificates.IsPresent)" + $Options.AddAdditionalCapability([OpenQA.Selenium.Remote.CapabilityType]::AcceptInsecureCertificates,$true,$true) + } + + if ($PrivateBrowsing) { + $Options.SetPreference("browser.privatebrowsing.autostart", $true) + } + + if ($PSBoundParameters.ContainsKey('LogLevel')) { + Write-Verbose "Setting Firefox LogLevel to $LogLevel" + $Options.LogLevel = $LogLevel + } + + if (-not $PSBoundParameters.ContainsKey('Service')) { + $ServiceParams = @{} + if ($WebDriverPath) { $ServiceParams.Add('WebDriverPath', $WebDriverPath) } + $service = New-SeDriverService -Browser Firefox @ServiceParams + } + + + $Driver = [OpenQA.Selenium.Firefox.FirefoxDriver]::new($service, $Options) + if (-not $Driver) { Write-Warning "Web driver was not created"; return } + Add-Member -InputObject $Driver -MemberType NoteProperty -Name 'SeServiceProcessId' -Value $Service.ProcessID + #region post creation options + $Driver.Manage().Timeouts().ImplicitWait = [TimeSpan]::FromMilliseconds($ImplicitWait * 1000) + + if ($PSBoundParameters.ContainsKey('Size')) { $Driver.Manage().Window.Size = $Size } + if ($PSBoundParameters.ContainsKey('Position')) { $Driver.Manage().Window.Position = $Position } + + # [SeWindowState] + switch ($State) { + { $_ -eq [SeWindowState]::Minimized } { $Driver.Manage().Window.Minimize(); break } + { $_ -eq [SeWindowState]::Maximized } { $Driver.Manage().Window.Maximize() ; break } + { $_ -eq [SeWindowState]::Fullscreen } { $Driver.Manage().Window.FullScreen() ; break } + } + + if ($StartURL) { $Driver.Navigate().GoToUrl($StartURL) } + #endregion + + Return $Driver + } +} diff --git a/Internal/Start-SeInternetExplorerDriver.ps1 b/Internal/Start-SeInternetExplorerDriver.ps1 new file mode 100644 index 0000000..e1be142 --- /dev/null +++ b/Internal/Start-SeInternetExplorerDriver.ps1 @@ -0,0 +1,59 @@ +function Start-SeInternetExplorerDriver { + param( + [string]$StartURL, + [SeWindowState]$State, + [System.IO.FileInfo]$DefaultDownloadPath, + [switch]$PrivateBrowsing, + [Double]$ImplicitWait, + [System.Drawing.Size]$Size, + [System.Drawing.Point]$Position, + $WebDriverPath, + $BinaryPath, + [OpenQA.Selenium.DriverService]$service, + [OpenQA.Selenium.DriverOptions]$Options, + [String[]]$Switches, + [OpenQA.Selenium.LogLevel]$LogLevel + ) + + + #region IE set-up options + if ($state -eq [SeWindowState]::Headless -or $PrivateBrowsing) { Write-Warning 'The Internet explorer driver does not support headless or Inprivate operation; these switches are ignored' } + + $IgnoreProtectedModeSettings = Get-OptionsSwitchValue -Switches $Switches -Name 'IgnoreProtectedModeSettings' + if ($IgnoreProtectedModeSettings) { + $Options.IntroduceInstabilityByIgnoringProtectedModeSettings = $true + } + + if ($StartURL) { $Options.InitialBrowserUrl = $StartURL } + + if (-not $PSBoundParameters.ContainsKey('Service')) { + $ServiceParams = @{} + if ($WebDriverPath) { $ServiceParams.Add('WebDriverPath', $WebDriverPath) } + $service = New-SeDriverService -Browser InternetExplorer @ServiceParams + } + + #endregion + + $Driver = [OpenQA.Selenium.IE.InternetExplorerDriver]::new($service, $Options) + if (-not $Driver) { Write-Warning "Web driver was not created"; return } + Add-Member -InputObject $Driver -MemberType NoteProperty -Name 'SeServiceProcessId' -Value $Service.ProcessID + if ($PSBoundParameters.ContainsKey('LogLevel')) { + Write-Warning "LogLevel parameter is not implemented for $($Options.SeParams.Browser)" + } + + #region post creation options + if ($PSBoundParameters.ContainsKey('Size')) { $Driver.Manage().Window.Size = $Size } + if ($PSBoundParameters.ContainsKey('Position')) { $Driver.Manage().Window.Position = $Position } + $Driver.Manage().Timeouts().ImplicitWait = [TimeSpan]::FromMilliseconds($ImplicitWait * 1000) + + + switch ($State) { + { $_ -eq [SeWindowState]::Minimized } { $Driver.Manage().Window.Minimize(); } + { $_ -eq [SeWindowState]::Maximized } { $Driver.Manage().Window.Maximize() } + { $_ -eq [SeWindowState]::Fullscreen } { $Driver.Manage().Window.FullScreen() } + } + + #endregion + + return $Driver +} \ No newline at end of file diff --git a/Internal/Start-SeMSEdgeDriver.ps1 b/Internal/Start-SeMSEdgeDriver.ps1 new file mode 100644 index 0000000..4354c6a --- /dev/null +++ b/Internal/Start-SeMSEdgeDriver.ps1 @@ -0,0 +1,61 @@ +function Start-SeMSEdgeDriver { + param( + [ValidateURIAttribute()] + [Parameter(Position = 1)] + [string]$StartURL, + [SeWindowState]$State, + [System.IO.FileInfo]$DefaultDownloadPath, + [switch]$PrivateBrowsing, + [Double]$ImplicitWait, + [System.Drawing.Size]$Size, + [System.Drawing.Point]$Position, + $WebDriverPath, + $BinaryPath, + [OpenQA.Selenium.DriverService]$service, + [OpenQA.Selenium.DriverOptions]$Options, + [String[]]$Switches, + [OpenQA.Selenium.LogLevel]$LogLevel + ) + #region Edge set-up options + if ($state -eq [SeWindowState]::Headless) { Write-Warning 'Pre-Chromium Edge does not support headless operation; the Headless switch is ignored' } + + if (-not $PSBoundParameters.ContainsKey('Service')) { + $ServiceParams = @{} + #if ($WebDriverPath) { $ServiceParams.Add('WebDriverPath', $WebDriverPath) } + $service = New-SeDriverService -Browser MSEdge @ServiceParams -ErrorAction Stop + } + + if ($PrivateBrowsing) { $options.UseInPrivateBrowsing = $true } + if ($StartURL) { $options.StartPage = $StartURL } + #endregion + + if ($PSBoundParameters.ContainsKey('LogLevel')) { + Write-Warning "LogLevel parameter is not implemented for $($Options.SeParams.Browser)" + } + + 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 } + Add-Member -InputObject $Driver -MemberType NoteProperty -Name 'SeServiceProcessId' -Value $Service.ProcessID + #region post creation options + if ($PSBoundParameters.ContainsKey('Size')) { $Driver.Manage().Window.Size = $Size } + if ($PSBoundParameters.ContainsKey('Position')) { $Driver.Manage().Window.Position = $Position } + $Driver.Manage().Timeouts().ImplicitWait = [TimeSpan]::FromMilliseconds($ImplicitWait * 1000) + + switch ($State) { + { $_ -eq [SeWindowState]::Minimized } { $Driver.Manage().Window.Minimize() } + { $_ -eq [SeWindowState]::Maximized } { $Driver.Manage().Window.Maximize() } + { $_ -eq [SeWindowState]::Fullscreen } { $Driver.Manage().Window.FullScreen() } + } + + #endregion + + Return $Driver +} \ No newline at end of file diff --git a/Internal/Test-SeDriverAcceptInsecureCertificates.ps1 b/Internal/Test-SeDriverAcceptInsecureCertificates.ps1 new file mode 100644 index 0000000..e7afa8c --- /dev/null +++ b/Internal/Test-SeDriverAcceptInsecureCertificates.ps1 @@ -0,0 +1,18 @@ +function Test-SeDriverAcceptInsecureCertificates { + [CmdletBinding()] + param ( + $Browser, [ref]$AcceptInsecureCertificates, + $Boundparameters + ) + + $SupportedBrowsers = @('Chrome','Edge','Firefox') + if ($Browser -in $SupportedBrowsers) { + return + } + else { + Throw ([System.NotImplementedException]::new(@" +AcceptInsecureCertificates parameter is only supported by the following browser: $($SupportedBrowsers -join ',') +Selected browser: $Browser +"@)) + } +} \ No newline at end of file diff --git a/Internal/Test-SeDriverConditionsValueValidation.ps1 b/Internal/Test-SeDriverConditionsValueValidation.ps1 new file mode 100644 index 0000000..716be5a --- /dev/null +++ b/Internal/Test-SeDriverConditionsValueValidation.ps1 @@ -0,0 +1,21 @@ +function Test-SeDriverConditionsValueValidation { + [CmdletBinding()] + param ( + $Condition, $Value + ) + + if ($PSBoundParameters.ContainsKey('Condition')) { + $ConditionValueType = $Script:SeDriverConditions.Where( { $_.Text -eq $Condition }, 'first')[0].ValueType + + if ($null -eq $ConditionValueType) { + Throw "The condition $Condition do not accept value" + } + elseif ($Value -isnot $ConditionValueType) { + Throw "The condition $Condition accept only value of type $ConditionValueType. The value provided was of type $($Value.GetType())" + } + else { + return + } + } + +} \ No newline at end of file diff --git a/Internal/Test-SeDriverUserAgent.ps1 b/Internal/Test-SeDriverUserAgent.ps1 new file mode 100644 index 0000000..faab23e --- /dev/null +++ b/Internal/Test-SeDriverUserAgent.ps1 @@ -0,0 +1,18 @@ +function Test-SeDriverUserAgent { + [CmdletBinding()] + param ( + $Browser, [ref]$UserAgent, + $Boundparameters + ) + + $SupportedBrowsers = @('Chrome', 'Firefox') + if ($Browser -in $SupportedBrowsers) { + return + } + else { + Throw ([System.NotImplementedException]::new(@" +UserAgent parameter is only supported by the following browser: $($SupportedBrowsers -join ',') +Selected browser: $Browser +"@)) + } +} \ No newline at end of file diff --git a/Internal/Test-SeElementConditionsValueValidation.ps1 b/Internal/Test-SeElementConditionsValueValidation.ps1 new file mode 100644 index 0000000..798d589 --- /dev/null +++ b/Internal/Test-SeElementConditionsValueValidation.ps1 @@ -0,0 +1,41 @@ +function Test-SeElementConditionsValueValidation { + Param( + $Element, + $By, + $Condition, + $ConditionValue, + $ParameterSetName + ) + # 0: All; + # 1: By + # 2: Element + + $ConditionDetails = $Script:SeElementsConditions.Where( { $_.Text -eq $Condition }, 'first')[0] + + switch ($ParameterSetName) { + 'Locator' { + if ($ConditionDetails.By_Element -eq 2) { + Throw "The condition $Condition can only be used with an element (`$Element)" + } + } + 'Element' { + if ($ConditionDetails.By_Element -eq 1) { + Throw "The condition $Condition can only be used with a locator (`$By & `$Value)" + } + } + } + + + + if ($null -ne $ConditionValue) { + if ($null -eq $ConditionDetails.ValueType) { + Throw "The condition $Condition do not accept value" + } + elseif ($ConditionValue -isnot $ConditionDetails.ValueType) { + Throw "The condition $Condition accept only value of type $($ConditionDetails.ValueType). The value provided was of type $($ConditionValue.GetType())" + } + else { + return + } + } +} \ No newline at end of file diff --git a/Internal/Test-SeMouseActionValueValidation.ps1 b/Internal/Test-SeMouseActionValueValidation.ps1 new file mode 100644 index 0000000..501b7a4 --- /dev/null +++ b/Internal/Test-SeMouseActionValueValidation.ps1 @@ -0,0 +1,20 @@ +function Test-SeMouseActionValueValidation { + [CmdletBinding()] + Param( + $Action, + $ConditionValue + ) + + $ConditionValueType = $Script:SeMouseAction.Where( { $_.Text -eq $Action }, 'first')[0].ValueType + if ($null -eq $ConditionValueType) { + Throw "The condition $Condition do not accept value" + } + elseif ($ConditionValue -isnot $ConditionValueType) { + if ($ConditionValueType.FullName -eq 'System.Drawing.Point' -and $ConditionValue -is [String] -and ($ConditionValue -split '[,x]').Count -eq 2) { return $True } + Throw "The condition $Condition accept only value of type $ConditionValueType. The value provided was of type $($ConditionValue.GetType())" + } + else { + return $true + } + +} \ No newline at end of file diff --git a/Internal/init.ps1 b/Internal/init.ps1 new file mode 100644 index 0000000..818fa5a --- /dev/null +++ b/Internal/init.ps1 @@ -0,0 +1,113 @@ +using namespace System.Collections.Generic + + +if (!$PSCommandPath.EndsWith('init.ps1')) { + $MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = { + Get-SeDriver | Stop-SeDriver + } + +} + + +Function New-Condition { + Param([Parameter(Mandatory = $true)]$Text, [Type]$ValueType, $Tooltip, [Switch]$OptionalValue, $ElementRequired = $true ) + return [PSCustomObject]@{ + Text = $Text + ValueType = $ValueType + Tooltip = $Tooltip + ElementRequired = $ElementRequired + } +} + +$Script:SeMouseAction = @( + New-Condition -Text 'DragAndDrop' -ValueType ([OpenQA.Selenium.IWebElement]) -Tooltip 'Performs a drag-and-drop operation from one element to another.' + New-Condition -Text 'DragAndDropToOffset' -ValueType ([System.Drawing.Point]) -Tooltip 'Performs a drag-and-drop operation on one element to a specified offset.' + New-Condition -Text 'MoveByOffset' -ValueType ([System.Drawing.Point]) -ElementRequired $null -Tooltip 'Moves the mouse to the specified offset of the last known mouse coordinates.' + New-Condition -Text 'MoveToElement' -ValueType ([System.Drawing.Point]) -OptionalValue -Tooltip 'Moves the mouse to the specified element with offset of the top-left corner of the specified element.' + New-Condition -Text 'Release' -ValueType $null -Tooltip 'Releases the mouse button at the last known mouse coordinates or specified element.' +) + +$Script:SeKeys = [OpenQA.Selenium.Keys] | Get-Member -MemberType Property -Static | + Select-Object -Property Name, @{N = "ObjectString"; E = { "[OpenQA.Selenium.Keys]::$($_.Name)" } } + +[Dictionary[object, Stack[string]]] $Script:SeLocationMap = [Dictionary[object, Stack[string]]]::new() + +#region Set path to assemblies on Linux and MacOS and Grant Execution permissions on them + +$ScriptRoot = $PSScriptRoot +# This will happens only if we are debugging +if ($ScriptRoot.EndsWith('Internal')){ + $ScriptRoot = Split-Path -Path $ScriptRoot +} + +if ($IsLinux) { + $AssembliesPath = "$ScriptRoot/assemblies/linux" +} +elseif ($IsMacOS) { + $AssembliesPath = "$ScriptRoot/assemblies/macos" +} else { + $AssembliesPath = "$ScriptRoot\assemblies" +} + +# Grant Execution permission to assemblies on Linux and MacOS +if ($IsLinux -or $IsMacOS) { + # 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 + } + } +} + +$Script:SeDriversAdditionalBrowserSwitches = @{ + Chrome = @('DisableAutomationExtension', 'EnablePDFViewer') + Edge = @() + Firefox = @('SuppressLogging') + InternetExplorer = @('IgnoreProtectedModeSettings') + MsEdge = @() +} + +# List of suggested command line arguments for each browser +$Script:SeDriversBrowserArguments = @{ + Chrome = @("--user-agent=Android") + Edge = @() + Firefox = @() + InternetExplorer = @() + MsEdge = @() +} + +$Script:SeDrivers = [System.Collections.Generic.List[PSObject]]::new() +$Script:SeDriversCurrent = $null + + +$AdditionalOptionsSwitchesCompletion = { + param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) + + if ($fakeBoundParameters.ContainsKey('Browser')) { + $Browser = $fakeBoundParameters.Item('Browser') + + $Output = $Script:SeDriversAdditionalBrowserSwitches."$Browser" + $Output | % { [System.Management.Automation.CompletionResult]::new($_) } + + + } +} + + +$SeDriversBrowserArgumentsCompletion = { + param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) + + if ($fakeBoundParameters.ContainsKey('Browser')) { + $Browser = $fakeBoundParameters.Item('Browser') + $Output = $Script:SeDriversBrowserArguments."$Browser" | Where { $_ -like "*$wordToComplete*" } + $ptext = [System.Management.Automation.CompletionResultType]::ParameterValue + $Output | % { [System.Management.Automation.CompletionResult]::new("'$_'", $_, $ptext, $_) } + } +} + +Register-ArgumentCompleter -CommandName Start-SeDriver, New-SeDriverOptions -ParameterName Switches -ScriptBlock $AdditionalOptionsSwitchesCompletion +Register-ArgumentCompleter -CommandName Start-SeDriver, New-SeDriverOptions -ParameterName Arguments -ScriptBlock $SeDriversBrowserArgumentsCompletion diff --git a/LICENSE b/LICENSE index cfcccfe..a95272b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Adam Driscoll +Copyright (c) 2020 Adam Driscoll Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Output/Selenium/ChangeLog.md b/Output/Selenium/ChangeLog.md new file mode 100644 index 0000000..2fb00b4 --- /dev/null +++ b/Output/Selenium/ChangeLog.md @@ -0,0 +1,436 @@ + +# 4.0.0-preview3 (Planned) +## Added / Modified +- Get-SeElementAttribute now return a hashtable instead of a pscustom object when multiple attributes are queried + + + +## Fixes +- Get-SeElement now make use of Get-SeElementAttribute internally to query attributes. +- Get-SeElement error when using filter / attribute +- Update-SeDriver default path typo (#206) +- New-SeScreenshot documentation update (#200) +- Casing issue with Types.ps1xml filename (#203) + +# 4.0.0-preview2 (Prerelease) +## Added / Modified +- Get-SeElement -Filter; Add a new parameter to do additional filtering before returning. This is equivalent to doing a Where afterward but with the Get-SeElement error management logic applied before returning. (#192) +- AcceptInsecureCertificates switch added to Start-SeDriver / New-SeDriverOptions (Supported by: Chrome, Firefox, Edge) (#189) +- Chrome web drivers assemblies updated to latest version + +## Fixes +- Starting Edge browser broken (#188,#195) +- custom driver options, when specified, are not used (#191,#193) +- Processes management internal logic error (#190) +- Get-SeInput not working properly with -Single switch (#186) +- Screenshots fail when attempting to screenshot the page (#187) + +# 4.0.0-preview1 (Prerelease) +Note: V4 have an enormous amount of breakchanges. Most of the cmdlet have been rewriten in a way or another. +Important changes includes, but are not limited to: +- Removing all aliases and duplicate functions +- Removal of -AsDefaultDriver and $Driver parameter in favor of an internal implementation which make the last driver started the active driver. Should you need to switch between 1 or more driver, this can be accomplished through the Switch-SeDriver cmdlet. + + +## Added +- Convert-toSeSelenium to convert IDE projects to Selenium-Powershell script +- Update-SeDriver to download the latest driver (Support only Chrome currently) +- Support for UserAgent in Start-SeDriver (#91) +- New view for IwebDriver (#111). IWebDriver will now display as a table in the console by default instead of a list. +- Get-SeElement - New view. Elements will now be returned in a table view to show the essential only. This make it significantly easier to deal with elements in the console interactively (#115) +- Get-SeElement - Bychained support. The cmdlet will now drilldown when multiple by / value are provided to allow for instance the selection of links in a div containing a specific classname. This is an alternative for those less savy with Xpath (#116) +- Get-SeHtml - Allow the retrieval of the html of an element (or driver is no element is provided). Essentially a wrapper around $Element.GetAttribute('xxHTML') (xx: Inner /Outer) (#118) +- New-SeDriverService - Allow the creation of a driver service to be used later on with Start-SeDriver. Only useful if you need to do change to the service parameters native object before starting the driver (#119) +- Invoke-SeMouseAction - Support for interactions (#122) +- Wait-SeDriver / Wait-SeElement expliciti wait support (#125) +- Get-SeElement -Attributes. Allow getting specific attributes (or all using *) to the elements to be returned. Attributes will be available in an Attributes string dictionary attached to each elements. (#133) +- Position / Size parameter for Start-SeDriver. Allow starting the driver at a specified position and size. If no command line available (or not implemented), the driver will start with the default settings and the be moved. (#134) +- Get-SeElement -Single switch added. Define the expectaction that only one element should be returned (#144) +- Get/Set-SeDriverTimeout - Allow changing driver timeouts easily (#150) +- Invoke-SeJavascript - A wrapper around $Driver.ExecuteScript (#151) +- Get-SeFrame, wrapper around Get-SeElement to show iframe along with their name / id in a convenient view (#159) +- New-SeWindow / Remove-SeWindow cmdlet added to complement the existing Get/Switch (#170) +- Get-SeInput (#178) - A wrapper around Get-SeElement to get input element. + + + +## Changed +- AsDefaultDriver implementation changed. Instead, Start-SeDriver automatically make the started driver the default. (#93) +- Driver parameter was removed on most cmdleet. It is now expected to use the Switch-SeDriver cmdlet to change the active driver if multiple are open. +- Start-SeChrome and other have been removed in favor of Start-SeDriver -Browser Chrome (#100) +- #98 Removed duplicate functions that performed the same thing or overlapped significantly +- Removed all the aliases everywhere on all the parameter / functions in favor of a more rigid way of writing things (#99) +- Standardize parameters. Some parameters had different names to mean the same thing (#100) +- Revamp Get-SeSelectionOption. The cmdlet have been separated in 3 cmdlet Get/Clear/Set -SeSelectValue. The get cmdlet will also now return the Text & Value of the selected element instead of the text only. (#112) +- Set-SeUrl now have a -Depth parameter to navigate forward or back x times (#124) +- Get-SeElement now returns visible elements by default. To view hidden elements, the All switch parameter need to be used (#126) +- Start-SeDriver -Quiet parameter removal. Quiet is now the default. This remove the extra Selenium verbose and resolves an issue with Driver not being usable in jobs. (#127) +- Get-SeElement now write an error if no element are returned. (#135) +- cmdlet that expect urls will now accept urls without protocol defined. Assumptions in these cases is that the url is https thus google.ca will be treated as https://www.google.ca (#153) +- Get-SeElementAttribute - Accept multiple values and wildcard to load all attributes (#161) +- Get-SeElement - support for multiple classname (#160) +- Get-SeElementCssValue - support for multiple values / wildcard character (#162) +- Sleep / Timeout parameters type changed from int to double (Still seconds, but provide more granularity) +- Invoke-SeScreenshot - support for Element screenshot. You can now easily produce a screenshot of a specific element instead of the whole page. (#168) + + + +## Bugfixes +- Get-SeElement no longer support splatting (#82) +- Getck driver abysmal performance (#113). Gecko service need to be configured to use localhost ::1. Otherwise, it take significantly more time to do everything with it (#113) +- Get-SeElement with Timeout return only the first element instead of the collection (#139) +- Implcit-Wait - Default reduced to 0.3 seconds instead of 10 seconds. One of the problem of implicit wait is that some operation will wait 100% of the defined implicit wait before performing an action. (#146) +- Implicit / Explicit wait management. Some cmdlet (old an new) uses explicit wait. Explicit wait and Implicit wait should not be mixed together. Therefore, when an explicit wait is used, implicit wait (if present) get temporary disabled(#149) + + +# 3.1.0 - Unreleased + +## Added +- Added -IgnoreProtectedModeSettings to Start-SeInternetExplorer - https://github.com/adamdriscoll/selenium-powershell/issues/79 - Thanks, @MysticRyuujin! + +- Added Markdown documentation (See Help subfolder) for all the cmdlets (PlatyPS is used behind the scene to maintain it) +- Added MAML embedded help that can be accessed through `Get-Help`(eg: `Get-Help Start-SeChrome -Examples`) +- Added Get-SeUrl / Pop-SeUrl / Push-SeUrl / Set-SeUrl (Thanks @vexx32) + +## Changed + - Converted monolythic module into a scaffolded module through a Plaster template. Module will now have a debug version and a compiled version that need to be built with Invoke-Build. See the Debug folder for additional informations on how to debug. + + - Open-SeUrl removed in favor of Set-SeUrl + - Send-SeKeys won't return an exception if you send $null or empty strings. + - Stop-SeDriver won't throw exceptions anymore when celled multiple times on a driver already closed. + +# 3.0.0 - 3/31/2020 + +## Changed + +- Fixed issue with importing module in PSv5.1 - https://github.com/adamdriscoll/selenium-powershell/issues/69 +- Updated Chrome drivers + +# 3.0.0-beta2 - 1/29/2020 + +## Added + +- Added Get-SeElementCssValue + +# 3.0.0-beta1 - 1/29/2020 + +## Added + +# General +## Start a Browser Driver for the browser of your choice (Chrome/Firefox/Edge/InternetExplorer) +```powershell +#Either: store the driver in your own variable +$Driver = Start-SeChrome + +#OR save it to $global:SeDriver +Start-SeChrome -AsDefaultDriver # alias Chrome +Start-SeFirefox -AsDefaultDriver # alias Firefox +Start-SeEdge -AsDefaultDriver # alias MsEdge +Start-SeNewEdge -AsDefaultDriver # alias CrEdge / NewEdge +Start-SeInternetExplorer -AsDefaultDriver # alias IE / InternetExplorer + +#OR use a shortcut which takes a browser name and sets it as the default. +SeOpen -In Chrome +``` +in the last case, -in can come an environment variable, to run the same script _n_ times with _n_ different browsers + +## Navigate to a page +```powershell +#Use a saved driver and the original function name +Enter-SeUrl https://www.poshud.com -Driver $Driver + +#Use the default driver and the new funtion name +Open-SeUrl https://www.poshud.com #alias SeNavigate + +#or Start the driver and navigate in one +Start-SeChrome -AsDefaultDriver -StartURL https://www.poshud.com + +#or using SeOpen +SeOpen -URL https://www.poshud.com -In Chrome +``` + +## Find an Element on the page +```powershell +#Using the saved driver and the old syntax +$Element = Find-SeElement -Driver $Driver -ClassName 'center-align' + +#Using the default driver and the new syntax +$Element = Get-SeElement -By ClassName 'center-align' #alias SeElement + +#xpath is selected by default - you can specify a timeout to wait for the element to appear. +$xpath = '/html/body/div[1]/div/main/div/div[2]/div[3]/div[1]/div/div/div[2]/a' +$Element = Get-SeElement $xpath -Timeout 10 + +#In a Pester Test you can check the element is present with +SeElement $xpath | should not beNullOrEmpty +#or +SeShouldHave $xpath +``` +_SeElement_ and _Find-SeElement_ are aliases for Get-SeElement. + +## Click on an Element/Button +```powershell +#send to a saved element with old syntax +Invoke-SeClick -Element $Element + +#Pipe an element into the command using new syntax +Get-SeElement $Xpath | Send-SeClick -SleepSeconds 2 #alias SeClick + +#in a Pester Test you can get the element, click and confirm a element was found +SeElement $xPath | SeClick -sleep 2 -passthru | should not beNullOrEmpty +``` +_Invove-SeClick_ and _Send-SeClick_ are almost interchangable, _SeClick_ is an alias for the latter + +## Send Keystrokes + +```powershell +#using a saved element +$Element = Find-SeElement -Driver $Driver -Id "txtEmail" +Send-SeKeys -Element $Element -Keys "adam@poshtools.com" + +#or using the pipeline +seElement -by ID "txtEmail" | Send-SeKeys -Keys "adam@poshtools.com" + +#in a Pester Test you can get the element, sendkeys and confirm a element was found +seElement -by ID "txtEmail" | SeType "adam@poshtools.com" -passthru | should not beNullOrEmpty +``` +_setype_ is a wrapper for _Send-SeKeys_ to be more Pester-friendly + +# using pester +### Navigating to a page (SeNavigate) + +```powershell + Enter-SeUrl -Url "https://www.powershellgallery.com/" -driver $Global:SeDriver + #Enter-SeUrl has an alias of SeNavigate, and will assume the driver is $Global:SeDriver, and take URL by position giving + SeNavigate https://www.powershellgallery.com/ +``` +### Checking the page url and title (SeShouldHave) + +```powershell + #knowing about the driver we could use it with a standard pester command + $Global:SeDriver.Url | should be "https://www.powershellgallery.com/" + + #Or we could use SeShouldHave. The full, explicit form looks like this + SeShouldHave -URL -Operator eq -Value "https://www.powershellgallery.com/" + #which can be shorted by passing Operator and Value parameters by position; + #Operator will tab-complete contains, match, notlike etc and will transform other names; match and notmatch are regular expressions + SeShouldHave -URL equalTo "https://www.powershellgallery.com/" + SeShouldHave -Title match "PowerShell\s+Gallery" +``` +The primary job of _SeShouldHave_ is to work like pesters _should_ and succeed silently or fail the test by throwing an error. + +### Finding and using an element: (SeElement) +```powershell + #we can shorten the command :Get-SeElement -By XPath -Selection '//*[@id="search"]' + #first with an alias and then -by Xpath is assumed and Selection can be passed in the first position to become + # SeElement '//*[@id="search"]' | SeType -ClearFirst "selenium{{Enter}}" + #This will not report a failure if the element was not found so + SeElement '//*[@id="search"]' | SeType -ClearFirst "selenium{{Enter}}" -PassThru | should not beNullorEmpty +``` +This is also possible with SeShouldHave.. see below + +### Checking elements: (SeShouldHave) +```powershell + $linkpath = '//*[@id="skippedToContent"]/section/div[1]/div[2]/div[2]/section[1]/div/table/tbody/tr/td[1]/div/div[2]/header/div[1]/h1/a' + #SeShouldHave can be written explictly like this + SeShouldHave -Selection $linkpath -By XPath -With Text -Operator match 'selenium' + #-by Xpath is assumed and the other parameters can be passed by position. Operators will tab complete, and convert "matching" or "matches" to match etc + SeShouldHave $linkpath Text matching 'selenium' +``` +The `-with` parameter can be 'Text', 'Displayed', 'Enabled', 'TagName', 'X', 'Y', 'Width', 'Height', 'Choice' or _the name of an attribute_, like 'href'. + If `-with` is not specified only _the presence_ of the page element is checked. + If `-PassThru` is specified, matching elements will be sent to the pipeline. (`-Passthru` can't be used when checking the page URL or tile, only with elements on the page). +```powershell + SeShouldHave $linkpath -PassThru | SeClick +``` +### Checking Multiple elements +The selection parameter can take multiple values; in the following command it is specified by position (and assumed to be one or more Xpaths) +```powershell + SeShouldHave '//*[@id="version-history"]/table/tbody[1]/tr[1]/ td[1]/a/b' , + '//*[@id="skippedToContent"]/section/div/aside/ul[2]/li[1]/a' +``` +When multiple elements are found from the selection criteria, and '-With' is specified the test will pass _any_ element passess - in other words, all elements do not need to pass. +```powershell + #The following counts 8 elements + SeNavigate 'https://www.google.com/ncr' + SeShouldHave -by TagName input -PassThru | measure + #The following command rejects 7 of these 8, without error, and passes the one with a title attribute of 'search' to another command + SeShouldHave -by TagName input -With Title eq Search -PassThru | SeType 'PowerShell-Selenium' +``` + +### Selecting frames (SeFrame) +on a page which uses frames it is necessary to specify which one containst the data +```powershell + seNavigate 'https://www.w3schools.com/js/tryit.asp?filename=tryjs_alert' + sleep -Seconds 5 #can go too fast for frames + SeFrame 1 +``` + +### Checking alerts (SeShouldHave, SeAccept, SeDismiss) +As well as checking the page URL, and page title. _SeShouldHave_ Supports -Alert and -NoAlert +```powershell + #in Frame 1 on 'https://www.w3schools.com/js/tryit.asp?filename=tryjs_alert' this will produce an alert + SeElement "/html/body/button" -Timeout 10 | SeClick -SleepSeconds 2 + #and this will check for it. + SeShouldHave -Alert match "box" + #Usually you will want to accept or dismiss the alert + SeShouldHave -Alert -PassThru | SeDismiss +``` +### Working with select/option "dropdown" controls (SeShouldHave, SeSelection) +```powershell + #This will go to a page with a dropdown box + SeNavigate 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_elem_select' + sleep -Seconds 5 #can go too fast for frames + SeFrame 1 + $dropDown = SeShouldHave -By Name "cars" -With choice contains "volvo" -PassThru +``` +In the code above, SeShouldHave finds the dropdown box which is named "Cars", and does a check to confirm one of the choices is Volvo, and assigns the result to a variable. This can be used with SeSelection (alias for Get-SeSelectionOption) to test or set options in the dropdown box. An option can be selected (and in the case of mult-select boxes, deselected) by its index, value or [partof] its display text. And the -GetSelected / -GetAllSelected options can be included in a set operation to (or used alone) to return the selected text. +```powershell + $dropdown | SeSelection -IsMultiSelect | should be $false + $dropdown | SeSelection -GetSelected | should be 'Volvo' + $dropdown | SeSelection -ListOptionText | should not contain "Ferrari" + #not the selections are case sensitive. The value in this case is all lower case, the display text has initial caps. + $dropdown | SeSelection -ByValue 'audi' -GetSelected | should be 'Audi' +``` + +DLL loading is now from the PSD1 file instead of the PSM1 file. +Now use presence of $AssembliesPath to judge "IsMacOS" -or "IsLinux" + +Send-SeKeys + -Element and -Keys parameters are both mandatory + Selenium-keys are now cached in a script-scoped variable for performance. (Get-SEKeys can be dropped) + Added -PassThru + + +Valdate-URL + Function Renamed to validateUrl (private helper function does not need to use verb-noun naming and "validate" verb upsets script analyzer) + Added the old name back as an alias (which _is_ allowed. ) + Moved functionality into a validation class which so URLs are validated before enering functions + +Checks for valid webdriver also moved to a validation class. + +Get-SeCookie & Invoke-SeScreenshot + In line with other functions, -Driver parameter is renamed -Target, with alias "Driver", and will come from $Global:SeDriver + and throws an error if no driver is passed or found from Global var + +Start-SeFirefox & Start-SeChrome + Added aliases "SeChrome" and "SeFirefox" - user can now write in a sort of DSL "SeCHROME $URL -asDefault" etc. + Made -StartUrl the first parameter and use a parameter-validation class to check it. + Now call the .Navigate method directly instead of via Enter-SeURL if -StartURL is specified + Now use parameter-sets to avoid the conflict between Minimized/Maximized/FullScreen/Headless, + Added parameter aliases so "Incognito" works with Firefox and "PrivateBrowsing" works with Chrome + Now trap a failure to return driver, and simplified the subsequent if statements + Set ImplicitWait to 10 seconds + Added Parameter -AsDefaultDriver which sets $Global:SeDriver, instead of returning the driver + Added Parameter -Quiet to run tests without web driver prattle. + Allow AzureDevops environment vars (GeckoWebDriver / ChromeWebDriver) or commandline + parameter -WebDriverDirectory to specify source of Webdriver. + Removed a possible bug with piped input, by returning the driver in the process block instead of the end block + +Start-SeInternetExplorer + Added Aliases "SeInternetExplorer" & "SeIE" and parameter -StartUrl + Plus -AsDefaultDriver which sets $Global:SeDriver, instead of returning the driver, and -Quiet to run tests + without web driver prattle. + Allow AzureDevops environment vars or commandline parameter -WebDriverDirectory to specify source of Webdriver + Set ImplicitWait to 10 seconds + +Start-SeEdge + Added Aliases "MSEdge" & "LegacyEdge", and parameters -StartUrl, -Maximized, -Minimized, FullScreen + and -PrivateBrowsing (alias Incognito) + Plus -AsDefaultDriver which sets $Global:SeDriver, instead of returning the driver, and -Quiet to run tests + without web driver prattle. + Added message if driver load errors - Webdriver is now added as a windows Feature and will be found from windows\system32, + which is on the path. Removed old driver and SHA file. + Set ImplicitWait to 10 seconds + +Stop-SeDriver + Updated to handle the default drive being in $global:SeDriver. + +Start-SeNewEdge **New Function** with alias, credge to support Chromium based edge. + Also added V79 webdriver. Specifying V80. V81 from an ENV variable (EdgeWebDriver), or via command line requires + it to be in the same directory as MSEdge.exe and -inPrivate, -headless, and -binaryLocation options don't work. + +Start-SeRemote **New Function** + Connects to remote driver by URL and requested capablites tested with testingbot.com + + Start-SeChrome Start-SeEdge Start-SeFirefox Start-SeInternetExplorer Start-SeNewEdge Start-SeRemote + AsDefaultDriver X X X X X X + Fullscreen X X X X X + Headless X X X X X + ImplicitWait X X X X X X + Maximized X X X X X + Minimized X X X X X + Incognito X As alias As alias As alias As alias + PrivateBrowsing As alias X X X X + Quiet X X X X X + StartURL X X X X X X + WebDriverDirectory X X X X + or Env var ChromeWebDriver - GeckoWebDriver IEWebDriver EdgeWebDriver + BinaryPath X X + ProfileDirectoryPath X X + DefaultDownloadPath X X X + Arguments X X + +SeOpen **New Function** + Takes -In (name of browser) and opens that browser and optional naviagates to destination in -URL + The browser is opened as with -AsDefault and other options passed in -Options. + If the browser name is omitted the function will look for $env:DefaultBrowser. + Mainly for Pester/DSL freindliness - by changing the environment variable a different browser can be used in different test runs + +Send-SeClick **New Function** (with alias SeClick) {replacement for Invoke-SeClick} + Element can be passed by position (first) + -JavaScriptClick can be abreviated -JS + Driver is ignored (element.wrapedDriver used instead) + Added -SleepSeconds and -PassThru parameters + +New-SeScreenShot: **New Function** with alias SeScreenshot. Merges functionality of Invoke-ScreenShot and SaveSeScreenShot + Can pass -Path, + -Passthru (Alias PT) + -Path & -Passthru + or -AsBase64 + "Target" with alias "Driver", can come from $Global:SeDriver + and throws an error if no driver passed or found from Global var + +Open-SeURL *New Function** with alias SeNavigate + Url is first on the commandline and mandatory + Driver is renamed target, with alias "Driver", and will come from $Global:SeDriver + Throws an error if no driver passed or found from Global var + Made interoperable with Enter-SEURL via aliases + Back, forward and refresh are available via switches + Commented out Enter-SeURL and changed PSD1, + +Get-SeElement **New Function** with alias seElement + New -By parameter with possible values "CssSelector", "Name", "Id", "ClassName", "LinkText", "PartialLinkText", "TagName", "XPath" + combined with a "Selection" parameter which holds the value, replaces the 8 parameters with those names and parametersets. + Wait made optional; -Wait without -Timeout sets timeout to 30 , and -Timeout 5 works without -Wait + -Element and -Driver are merged as -Target which has aliases of 'Element' and 'Driver' + Made interoperable with Find-seElement by aliases + Commented out Find-seElement and updated PSD1. + +Switch-SeFrame **New Function** with alias SeFrame + Selects a frame. + +Clear-SeAlert **New Function** with aliases SeAccept, SeDissmiss + Accepts or dismisses an alert box so execution can continue + If called using the aliases selects Accept or dismiss. + +SeType **New Function** + More DSL friendly form of Send-SeKeys - takes piped element; keys is first parameter and supports + clearing the text box, submit and passthru, to allow element to be fetched and keys typed, and then + Pester to throw if element was not found. + +Get-SeSelectionOption **New Function** alias SeSelection + For setting and checking options in a dropdown lists. + +SeShouldHave **New Function** +Drives pester tests as a single command See examples for details, but allows things like + SeShouldHave -url -match 'packages\?q=selenium' + SeShouldHave -Selection $linkpath -By XPath -With Text -Operator Like -Value "*selenium*" + which can be shortened to + seShouldHave $linkpath text -Like "*selenium*" + +Added some new examples - showing DSL style in Pester. + +Reorder PSD file for easy reading & add file list. + +Create CI directory with files for doing a build / test pass is Azure devops. diff --git a/Output/Selenium/Examples/A-Simple-Google-Search.ps1 b/Output/Selenium/Examples/A-Simple-Google-Search.ps1 new file mode 100644 index 0000000..4c94db1 --- /dev/null +++ b/Output/Selenium/Examples/A-Simple-Google-Search.ps1 @@ -0,0 +1,55 @@ +# The line below will Import-Module Selenium if it fails it will display the installation command and stop the script. +Import-Module -Name Selenium + +# Start the Selenium Chrome Driver +Start-SeDriver -Browser Chrome -StartURL 'google.com/ncr' + + + +#Getting the Search box + +<# This is the HTML code of the search box, found using the browser developer tools + +#> + +#Here's a few different ways, all valid, to access that searchbox + +# By examining the HTML code of the google seach box we can see that the search box name is q so in the below example we'll use the name q to find its element +#The Single parameter will write an error if there's not 1 element. +$Searchbox = Get-SeElement -By Name -value q -Single + +# We can also use the class name gLFyf to find the google search box. +$Searchbox = Get-SeElement -ClassName 'gLFyf' + +# This line will get us all elements with the input TagName also known as +#The -All parameter (optional) also includes hidden elements. +# The -Attributes parameter will load the specified attribute in the result and make them available through an Attributes property +$AllInputElement = Get-SeElement -By TagName -Value input -All -Attributes title +$AllInputElement | select Attributes +# The $AllInputElements contains all the input elements on the page if we want to find the specific element for the google search box we will need to loop through each input element in the $AllInputElements array and get the attibute we want in this case we're looking for the title attribute. +# And we only want to return the element that has a title equal to Search we can find this out based on the html code on the page. +$Searchbox = $AllInputElement.Where( { $_.Attributes.title -eq 'Search' }, 'first')[0] + +# Now for the fun part after finding the element we want to send keyboard input to it. this will allow us to automate the search process +# We can get the list of all special keyboard keys like enter/backspace etc using the Get-SeKeys command + +# Now that we can see all the keys we can send send some keys to the SearchBoxElement +Invoke-SeKeys -Element $Searchbox -Keys 'Powershell-Selenium' + +# You can send special key strokes to the SearchBoxElement, you should use the Selenium Keys enum. For example, if we wanted to send an enter key stroke, you could do it like this +# To view special keys, use Get-SeKeys +Invoke-SeKeys -Element $Searchbox -Keys ([OpenQA.Selenium.Keys]::Enter) + +# When working with dynamic websites, it's often necessary to wait awhile for elements to appear on the page. By default, Selenium won't wait and you'll receive $null from Find-SeElement because the element isn�t there yet. There are a couple ways to work around this. +# The first is to use the Find-SeElement cmdlet with the -Wait switch to wait for the existence of an element in the document. +# When using the Find-SeElement with the -Wait please take into account that only 1 element can be returned unlike the without the -Wait switch where multiple elements can be returned. + +# This command will wait for the img elements for 10 seconds and then return it to you or time out if the element wasn't found on. +#Note, the value parameter is provided positionally. +$LogoImageElement = Get-SeElement -Timeout 10 -By Id 'logo' + +# Once we have the image element we can simulate a mouse click on it using the Invoke-SeClick command. +Invoke-SeClick -Element $LogoImageElement + +# Once we are done with the web driver and we finished with all our testing/automation we can release the driver by running the Stop-SeDriver command. +Stop-SeDriver \ No newline at end of file diff --git a/Output/Selenium/Examples/Combined.tests.ps1 b/Output/Selenium/Examples/Combined.tests.ps1 new file mode 100644 index 0000000..a3abd51 --- /dev/null +++ b/Output/Selenium/Examples/Combined.tests.ps1 @@ -0,0 +1,254 @@ +. "$(Join-Path -Path $PSScriptRoot -ChildPath '_TestDependencies.ps1' )" + +$Global:TestCaseSettings = Get-TestCasesSettings +$Global:BrowserOptHash = $Global:TestCaseSettings."$Global:DefaultBrowser".DefaultOptions +$Env:BrowserOptText = Build-StringFromHash $Global:BrowserOptHash +$Env:BrowserID = "$Global:DefaultBrowser on $([System.Environment]::OSVersion.Platform)" +Describe "Testing the tailspin toys demo site at $env:SITE_URL" { + BeforeAll { + . "$(Join-Path -Path $PSScriptRoot -ChildPath '_TestDependencies.ps1' )" + + $Global:TestCaseSettings = Get-TestCasesSettings + $Global:BrowserOptHash = $Global:TestCaseSettings."$Global:DefaultBrowser".DefaultOptions + $Env:BrowserOptText = Build-StringFromHash $Global:BrowserOptHash + #Relying on environment variable to pick the browser. Capture ID for use in logs by requesting verbose and redirecting it. + try { Start-SeDriver -Browser $Global:DefaultBrowser -StartURL $env:SITE_URL @Global:BrowserOptHash -Verbose 4>&1 -ErrorAction Stop } catch { throw $_ } + $Env:BrowserID = "$Global:DefaultBrowser on $([System.Environment]::OSVersion.Platform)" + + } + Context "in $($Env:BrowserID) with settings ($Env:BrowserOptText)" { + It "produced the right modal dialog for the " -TestCases (Get-ModalTestCases) { + Param ($linkXPath, $modalXPath) + SeShouldHave $modalXPath -With displayed eq $false -Timeout 10 + SeElement $linkXPath | Invoke-SeClick -Action Click_JS -Sleep 1 + SeElement $modalXPath | SeElement -By ClassName 'close' | Invoke-SeClick -Action Click_JS -Sleep 1 + SeShouldHave 'body' -By TagName + SeShouldHave $modalXPath -With displayed eq $false + } + } + # Additional tests would be here + AfterAll { Stop-SeDriver } +} +#endregion + +#URLs we will visit in the remaining tests + +# + + +#As before rely on environment variable to pick browser. Capture ID by requesting & redirecting verbose +Describe "PsGallery Test" { + BeforeAll { + . "$(Join-Path -Path $PSScriptRoot -ChildPath '_TestDependencies.ps1' )" + $PSGalleryPage = 'https://www.powershellgallery.com/' + $Global:TestCaseSettings = Get-TestCasesSettings + $Global:BrowserOptHash = $Global:TestCaseSettings[$Global:DefaultBrowser].DefaultOptions + $Env:BrowserOptText = Build-StringFromHash $Global:BrowserOptHash + try { Start-SeDriver -Browser $Global:DefaultBrowser -StartURL $PSGalleryPage @Global:BrowserOptHash -Verbose 4>&1 -ErrorAction Stop }catch {} + $Env:BrowserID = "$Global:DefaultBrowser on $([System.Environment]::OSVersion.Platform)" + } + Context "in $Env:BrowserID with settings ($Env:BrowserOptText)" { + It 'opened the browser, saving the webdriver in a global variable ' { + Get-SeDriver -Current | Should -Not -BeNullOrEmpty + Get-SeDriver -Current | Should -BeOfType [OpenQA.Selenium.Remote.RemoteWebDriver] + } + + It 'reached the right starting page ' { + #Should have can check alerts, page title, URL or an element on the page + SeShouldHave -URL eq $PSGalleryPage + } + It 'found the "Sign in" link on the home page by partial text ' { + SeShouldHave -By PartialLinkText 'Sign in' -With href match logon + } + It 'found the search box on the home page by ID ' { + SeShouldHave -By Id search + } + It 'found the search box on the home page by Name ' { + SeShouldHave -By Name 'q' + } + It 'found the search box on the home page by css selector ' { + #can write -By <> [-selection] <> + # or [-selection] <> -By <> + SeShouldHave 'input[name=q]' -By CssSelector + } + It 'found the search box on the home page by class name ' { + SeShouldHave -By ClassName "search-box" + } + It 'found the search box on the home page by Tagname and typed in it ' { + #get element, pipe as input element for Typing, pass the element through + #so pester catches 'null or empty' if it was not found + Get-SeElement -By TagName -Value 'input' | + Invoke-SeKeys -ClearFirst -Keys "selenium{{Enter}}" -PassThru -Sleep 2 | Should -Not -BeNullorEmpty + } + It 'searched successfully ' { + $linkpath = '//*[@id="skippedToContent"]/section/div[1]/div[2]/div[2]/section[1]/div/table/tbody/tr/td[1]/div/div[2]/header/div[1]/h1/a' + SeShouldHave -URL match 'packages\?q=selenium' -Timeout 15 + #Two tests on the same element, second passes it through to click + SeShouldHave $linkpath -With href match selenium + SeShouldHave $linkpath -With Text like *selenium* -PassThru | Invoke-SeClick -Action Click_JS -Sleep 5 + } + It 'opened the search result page and found the expected content ' { + #Just to show we can test for the presence of multiple links. Each one is re-tested ... + SeShouldHave '//*[@id="version-history"]/table/tbody[1]/tr[1]/ td[1]/a/b' , + '//*[@id="skippedToContent"]/section/div/aside/ul[2]/li[1]/a' -Timeout 15 + + SeShouldHave '//*[@id="version-history"]/table/tbody[1]/tr[1]/ td[1]/a/b' -With text match "current" + + #Can test with "Get-SeElement | where-object <>" rather than "with <> <> <>" + SeElement '//*[@id="skippedToContent"]/section/div/aside/ul[2]/li[1]/a' | + Where-Object { ($_.text -like "*Project Site*") -and ($_.GetAttribute('href') -match "selenium") } | + Invoke-SeClick -PassThru | Should -Not -Benullorempty + } + It 'went to Github from the project link on the search result ' { + SeShouldHave -URL match 'github' -Timeout 30 + } + It 'navigated back to the start page and closed the browser ' { + Set-SeUrl -Back + Set-SeUrl -Back + Set-SeUrl -Back + SeShouldHave -URL eq $PSGalleryPage -Timeout 30 + Stop-SeDriver + Get-SeDriver -Current | Should -BeNullOrEmpty + } + } + AfterAll { Stop-SeDriver } +} + + +Describe "Alerts and Selection boxes tests" { + BeforeAll { + . "$(Join-Path -Path $PSScriptRoot -ChildPath '_TestDependencies.ps1' )" + $AlertTestPage = 'https://www.w3schools.com/js/tryit.asp?filename=tryjs_alert' + $SelectTestPage = 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_elem_select' + $Global:TestCaseSettings = Get-TestCasesSettings + $Global:BrowserOptHash = $Global:TestCaseSettings[$Global:DefaultBrowser].PrivateOptions + $Env:BrowserOptText = Build-StringFromHash $Global:BrowserOptHash + + if ($Env:BrowserOptText) { + $Global:NoLabel = [string]::IsNullOrEmpty($Global:TestCaseSettings[$Global:DefaultBrowser].InPrivateLabel) + $wv = $null + try { Start-SeDriver -Browser $Global:DefaultBrowser -StartURL $alertTestPage @BrowserOptHash -WarningVariable wv -ErrorAction Stop }catch {} + if ($wv) { Write-Output "##vso[task.logissue type=warning]$wv" } + } + else { + $Global:NoLabel = $true + try { Start-SeDriver -Browser $Global:DefaultBrowser -StartURL $alertTestPage -ErrorAction Stop } catch {} + + } + $Env:BrowserID = "$Global:DefaultBrowser on $([System.Environment]::OSVersion.Platform)" + } + Context "in $Env:BrowserID with settings ($Env:BrowserOptText)" { + # It 're-opended the browser and validated "InPrivate" mode by window title ' { + # $DriverProcess = Get-Process *driver | Where-Object { $_.Parent.id -eq $pid } + # $BrowserProcess = Get-Process | Where-Object { $_.Parent.id -eq $DriverProcess.id -and $_.Name -ne "conhost" } + # $BrowserProcess.MainWindowTitle | Should match $Global:TestCaseSettings[$Global:DefaultBrowser].InPrivateLabel + # } -Skip:$Global:NoLabel + It 'opened the right page ' { + SeShouldHave -URL -eq $alertTestPage + } + It 'Navigated to the child iframe' { #'triggered and dismissed an alert' + SeShouldHave -Selection "iframe" -By TagName -with id eq iframeResult + Switch-SeFrame 'iframeResult' + Get-SeElement "/html/body/button" | Should -Not -BeNullOrEmpty #Removed | Invoke-SeClick -PassThru + #Checking the text of the alert is optional. Dissmiss can pass the alert result through + #{ Wait-SeDriver -Condition AlertState -Value $false -Timeout 15 -ErrorAction Stop } | Should -Not -throw + #Clear-SeAlert -Alert $Alert -Action Dismiss -PassThru | Should -Not -BeNullOrEmpty + } + It 'reselected the parent frame ' { + Switch-SeFrame -Parent + SeShouldHave -Selection "iframe" -By TagName -with id eq iframeResult + } + It 'navigated to a new page, and found the "cars" selection box in frame 1 ' { + Set-SeUrl $SelectTestPage + SeShouldHave -Selection "iframe" -By TagName -with id eq iframeResult + Switch-SeFrame 'iframeResult' + $e = SeElement -by Name "cars" + $e | Should -Not -BeNullOrEmpty + (Get-SeSelectValue -Element $e -All).Items.Text | Should -Contain 'volvo' + } + It 'made selections from the "cars" selection box ' { + $e = SeElement -by Name "cars" + #Values are lower case Text has inital caps comparisons are case sensitve. Index is 0-based + { $e | Set-SeSelectValue -By Value -value "Audi" } | Should -Throw + { $e | Set-SeSelectValue -By Value -value "audi" } | Should -not -throw + $e | Set-SeSelectValue -By Index -value "2"; (Get-SeSelectValue -Element $e).Text | Should -Be 'Fiat' + $e | Set-SeSelectValue -By Text -value "Sa*" + } + It 'submitted the form and got the expected response ' { + Get-SeElement '/html/body/form/input' | Invoke-SeClick -Sleep 5 + Switch-SeFrame -Parent + Switch-SeFrame 'iframeResult' + SeShouldHave "/html/body/div[1]" -with text match "cars=saab" + } + It 'closed the in-private browser instance ' { + Stop-SeDriver + if ($DriverProcess.Id) { + (Get-Process -id $DriverProcess.id ).HasExited | Should -Be $true + } + if ($BrowserProcess.Id) { + (Get-Process -id $BrowserProcess.id).HasExited | Should -Be $true + } + } + } + AfterAll { Stop-SeDriver } +} + + +$Global:BrowserOptHash = $Global:TestCaseSettings[$Global:DefaultBrowser].HeadlessOptions +$Env:BrowserOptText = Build-StringFromHash $Global:BrowserOptHash +$Global:SkipTests = [String]::IsNullOrEmpty($Env:BrowserOptText) + +Describe "'Headless' mode browser test" { + BeforeAll { + . "$(Join-Path -Path $PSScriptRoot -ChildPath '_TestDependencies.ps1' )" + $Global:TestCaseSettings = Get-TestCasesSettings + + $Global:BrowserOptHash = $Global:TestCaseSettings[$Global:DefaultBrowser].HeadlessOptions + $Env:BrowserOptText = Build-StringFromHash $Global:BrowserOptHash + $Global:SkipTests = $true + if (![String]::IsNullOrEmpty($Env:BrowserOptText)) { + $Global:SkipTests = $false + try { $Env:BrowserID = Start-SeDriver -Browser $Global:DefaultBrowser -StartURL $env:SITE_URL @BrowserOptHash -ErrorAction Stop }catch {} + } + $Env:BrowserID = "$Global:DefaultBrowser on $([System.Environment]::OSVersion.Platform)" + } + Context "in $Env:BrowserID with settings ($Env:BrowserOptText)" { + It 're-opened the Browser in "Headless" mode' { + if ($PSVersionTable.PSVersion.Major -eq 5) { + $Processes = Get-CimInstance -Class Win32_Process + $DriverProcess = $Processes | Where { $_.Name -like '*driver.exe' -and $_.ParentProcessId -eq $Pid } + $BrowserProcess = $Processes | Where-Object { $_.ParentProcessId -eq $DriverProcess.ProcessId -and $_.Name -ne 'conhost.exe' } + if ($BrowserProcess -ne $null) { + (Get-process -Id $BrowserProcess.ProcessId).MainWindowHandle | Should -be 0 + } + } + else { + $DriverProcess = Get-Process *driver | Where-Object { $_.Parent.id -eq $pid } + $BrowserProcess = Get-Process | Where-Object { $_.Parent.id -eq $DriverProcess.id -and $_.Name -ne 'conhost' } + $BrowserProcess.MainWindowHandle | Select-Object -First 1 | Should -be 0 + } + } + it 'did a google Search ' { + Set-SeUrl 'https://www.google.com/ncr' + SeShouldHave -by Name q + SeShouldHave -by ClassName 'gLFyf' + SeShouldHave -By Name q -PassThru | Where Displayed -eq $true | + Select-Object -First 1 | Invoke-SeKeys -Keys 'Powershell-Selenium{{Enter}}' -PassThru | + should -Not -BeNullOrEmpty + + SeShouldHave '//*[@id="tsf"]/div[2]/div[1]/div[1]/a' -PassThru | + Invoke-SeClick -PassThru | should -Not -BeNullOrEmpty + } + It 'closed the browser a third time ' { + Stop-SeDriver + Get-SeDriver -Current | Should -BeNullOrEmpty + if ($DriverProcess.Id) { + (Get-Process -id $DriverProcess.id ).HasExited | Should -Be $true + } + if ($BrowserProcess.Id) { + (Get-Process -id $BrowserProcess.id).HasExited | Should -Be $true + } + } + } -Skip:$Global:SkipTests + AfterAll { Stop-SeDriver } +} \ No newline at end of file diff --git a/Output/Selenium/Examples/Example.side b/Output/Selenium/Examples/Example.side new file mode 100644 index 0000000..a11d238 --- /dev/null +++ b/Output/Selenium/Examples/Example.side @@ -0,0 +1,295 @@ +{ + "id": "1a83cd76-e78d-4402-b40e-5805b2403f44", + "version": "2.0", + "name": "Example", + "url": "https://automationintesting.com", + "tests": [{ + "id": "0896d7a2-81f1-4972-bbc3-4880718bc157", + "name": "Test1", + "commands": [{ + "id": "4770f8f0-e2c5-434e-847c-b79ecadebf41", + "comment": "", + "command": "open", + "target": "/selenium/testpage/", + "targets": [], + "value": "" + }, { + "id": "8068ba5f-597f-4d50-834d-b057c2cfb2ea", + "comment": "", + "command": "setWindowSize", + "target": "1936x1056", + "targets": [], + "value": "" + }, { + "id": "90423ff3-98f2-4de8-9998-32088c188647", + "comment": "", + "command": "click", + "target": "id=firstname", + "targets": [ + ["id=firstname", "id"], + ["css=#firstname", "css:finder"], + ["xpath=//input[@id='firstname']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div/div/label/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "" + }, { + "id": "fa88b63a-f245-4374-8db2-284f239c3ee0", + "comment": "", + "command": "type", + "target": "id=firstname", + "targets": [ + ["id=firstname", "id"], + ["css=#firstname", "css:finder"], + ["xpath=//input[@id='firstname']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div/div/label/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "test" + }, { + "id": "2626b60b-2f5b-473d-b342-4f5ec36501b5", + "comment": "", + "command": "click", + "target": "xpath=//form[@id='contactus']/div[2]/div/label/input", + "targets": [ + ["id=surname", "id"], + ["css=#surname", "css:finder"], + ["xpath=//input[@id='surname']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[2]/div/label/input", "xpath:idRelative"], + ["xpath=//div[2]/div/label/input", "xpath:position"] + ], + "value": "" + }, { + "id": "65b0a638-0f79-4a43-ac8a-db482d18c3cd", + "comment": "", + "command": "type", + "target": "xpath=//form[@id='contactus']/div[2]/div/label/input", + "targets": [ + ["id=surname", "id"], + ["css=#surname", "css:finder"], + ["xpath=//input[@id='surname']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[2]/div/label/input", "xpath:idRelative"], + ["xpath=//div[2]/div/label/input", "xpath:position"] + ], + "value": "test2" + }, { + "id": "e9047045-ede4-4c13-81b5-f8c036cb527c", + "comment": "", + "command": "click", + "target": "id=gender", + "targets": [ + ["id=gender", "id"], + ["css=#gender", "css:finder"], + ["xpath=//select[@id='gender']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[3]/div/label/select", "xpath:idRelative"], + ["xpath=//select", "xpath:position"] + ], + "value": "" + }, { + "id": "f9341c3c-215b-44c1-9fff-fa977a7ba599", + "comment": "", + "command": "select", + "target": "id=gender", + "targets": [], + "value": "label=Male" + }, { + "id": "39458fd5-e6ac-46c7-9e48-b24349314ef0", + "comment": "", + "command": "click", + "target": "id=red", + "targets": [ + ["id=red", "id"], + ["name=colour", "name"], + ["css=#red", "css:finder"], + ["xpath=//input[@id='red']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[4]/div/input", "xpath:idRelative"], + ["xpath=//div/input", "xpath:position"] + ], + "value": "" + }, { + "id": "a1ded097-b395-4bed-b641-7c2ab136d411", + "comment": "", + "command": "click", + "target": "css=textarea", + "targets": [ + ["css=textarea", "css:finder"], + ["xpath=//form[@id='contactus']/div[5]/div/label/textarea", "xpath:idRelative"], + ["xpath=//textarea", "xpath:position"] + ], + "value": "" + }, { + "id": "582f0b4e-2521-404e-a912-39261d867d11", + "comment": "", + "command": "type", + "target": "css=textarea", + "targets": [ + ["css=textarea", "css:finder"], + ["xpath=//form[@id='contactus']/div[5]/div/label/textarea", "xpath:idRelative"], + ["xpath=//textarea", "xpath:position"] + ], + "value": "text" + }, { + "id": "764ae979-42dd-457e-95c5-5dddad91e44d", + "comment": "", + "command": "addSelection", + "target": "id=continent", + "targets": [ + ["id=continent", "id"], + ["css=#continent", "css:finder"], + ["xpath=//select[@id='continent']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[6]/div/label/select", "xpath:idRelative"], + ["xpath=//div[6]/div/label/select", "xpath:position"] + ], + "value": "label=North America" + }, { + "id": "bb929f6f-ee4c-43ad-920b-0806aba3c37d", + "comment": "", + "command": "click", + "target": "id=checkbox1", + "targets": [ + ["id=checkbox1", "id"], + ["css=#checkbox1", "css:finder"], + ["xpath=//input[@id='checkbox1']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[4]/div[2]/input", "xpath:idRelative"], + ["xpath=//div[2]/input", "xpath:position"] + ], + "value": "" + }, { + "id": "542d6958-faab-40e9-9b4b-81f051673c23", + "comment": "", + "command": "click", + "target": "id=submitbutton", + "targets": [ + ["id=submitbutton", "id"], + ["css=#submitbutton", "css:finder"], + ["xpath=//button[@id='submitbutton']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div[7]/div/button", "xpath:idRelative"], + ["xpath=//div/button", "xpath:position"], + ["xpath=//button[contains(.,'I do nothing!')]", "xpath:innerText"] + ], + "value": "" + }] + }, { + "id": "c0d8e914-0e45-4d59-be13-b902e026cb6c", + "name": "Test2", + "commands": [{ + "id": "319fa3e0-f697-4963-a879-b358fff62a77", + "comment": "", + "command": "open", + "target": "/selenium/testpage/", + "targets": [], + "value": "" + }, { + "id": "27aa1c23-21c7-45dc-8887-fe3d0e8f592b", + "comment": "", + "command": "setWindowSize", + "target": "1936x1056", + "targets": [], + "value": "" + }, { + "id": "421ace3d-1377-4423-9257-bfc703103beb", + "comment": "", + "command": "sendKeys", + "target": "id=firstname", + "targets": [], + "value": "test3" + }, { + "id": "301e2ba3-8f11-42cd-a41e-8241e158e962", + "comment": "", + "command": "sendKeys", + "target": "id=firstname", + "targets": [ + ["id=firstname", "id"], + ["css=#firstname", "css:finder"], + ["xpath=//input[@id='firstname']", "xpath:attributes"], + ["xpath=//form[@id='contactus']/div/div/label/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "${KEY_ENTER}" + }] + }, { + "id": "8b6ff854-fefb-40bc-bd48-d206878b9e64", + "name": "Test3", + "commands": [{ + "id": "a3b6e82e-a847-4ac5-ac72-a05c5150d107", + "comment": "", + "command": "open", + "target": "http://www.tagindex.net/html/frame/example_f01.html", + "targets": [], + "value": "" + }, { + "id": "785d2ca1-c20b-4b96-a03e-43119ad2ecef", + "comment": "", + "command": "setWindowSize", + "target": "1936x1056", + "targets": [], + "value": "" + }, { + "id": "150bc283-671d-4d77-b1a5-b5dd20c2eee3", + "comment": "", + "command": "selectFrame", + "target": "index=0", + "targets": [ + ["index=0"] + ], + "value": "" + }, { + "id": "50809502-afdf-4b1b-943b-40524bbd2420", + "comment": "", + "command": "click", + "target": "css=html", + "targets": [ + ["css=html", "css:finder"], + ["xpath=//html", "xpath:position"] + ], + "value": "" + }, { + "id": "e726cc31-c25f-4cf7-92fe-77d976bb2f91", + "comment": "", + "command": "selectFrame", + "target": "relative=parent", + "targets": [ + ["relative=parent"] + ], + "value": "" + }, { + "id": "71ab81f7-8c7d-413e-a7ed-f68c224b1373", + "comment": "", + "command": "selectFrame", + "target": "index=1", + "targets": [ + ["index=1"] + ], + "value": "" + }, { + "id": "6e01154b-2221-4eef-98db-5760b52063e0", + "comment": "", + "command": "doubleClick", + "target": "css=p", + "targets": [ + ["css=p", "css:finder"], + ["xpath=//div[@id='MainBox']/p", "xpath:idRelative"], + ["xpath=//p", "xpath:position"], + ["xpath=//p[contains(.,'Please return to the previous page using the browsers \"back\" button.')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "a9f64bfd-1962-4f32-aa85-85d1ae4af91a", + "comment": "", + "command": "close", + "target": "", + "targets": [], + "value": "" + }] + }], + "suites": [{ + "id": "3fb340b3-1af6-4948-ad2a-c689126d9dad", + "name": "Default Suite", + "persistSession": false, + "parallel": false, + "timeout": 300, + "tests": ["0896d7a2-81f1-4972-bbc3-4880718bc157"] + }], + "urls": ["https://automationintesting.com/"], + "plugins": [] +} \ No newline at end of file diff --git a/Output/Selenium/Examples/_TestDependencies.ps1 b/Output/Selenium/Examples/_TestDependencies.ps1 new file mode 100644 index 0000000..6425032 --- /dev/null +++ b/Output/Selenium/Examples/_TestDependencies.ps1 @@ -0,0 +1,70 @@ + +Function Get-DefaultParams() { + if ($null -eq $Global:DefaultBrowser) { $Global:DefaultBrowser = 'Firefox' } + if ($null -eq $env:SITE_URL) { $env:SITE_URL = 'http://tailspin-spacegame-web.azurewebsites.net' } + if ($null -eq $Global:HeadlessOnly) { $Global:HeadlessOnly = $False } +} +Get-DefaultParams + + +Function Get-TestCasesSettings() { + $HeadlessState = if ($Global:HeadlessOnly) { 'Headless' } else { 'Maximized' } + return @{ + 'NewEdge' = @{ + DefaultOptions = @{State = $HeadlessState } + PrivateOptions = @{ + PrivateBrowsing = $true + State = $HeadlessState + } + # InPrivateLabel = 'InPrivate' + } # broken after build 79 of web driver#> + 'Chrome' = @{ + PrivateOptions = @{ + PrivateBrowsing = $true + State = $HeadlessState + } + DefaultOptions = @{State = $HeadlessState } + HeadlessOptions = @{State = 'Headless' } + } + 'Firefox' = @{ + PrivateOptions = @{ + PrivateBrowsing = $true + State = $HeadlessState + } + DefaultOptions = @{State = $HeadlessState } + HeadlessOptions = @{State = 'Headless' } + } + 'MSEdge' = @{ + DefaultOptions = @{State = $HeadlessState } + PrivateOptions = @{PrivateBrowsing = $true } + } + 'InternetExplorer' = @{ + DefaultOptions = @{ImplicitWait = 30 } + PrivateOptions = @{ImplicitWait = 30 } + } + } +} + +function Build-StringFromHash { + param ($Hash) + $(foreach ($k in $Hash.Keys) { "$K`:$($hash[$K])" }) -join '; ' +} + + + +function Get-ModalTestCases() { + return @( + @{Name = 'Download Page' + linkXPath = '/html/body/div/div/section[2]/div[2]/a' + modalXPath = '//*[@id="pretend-modal"]/div/div' + }, + @{Name = 'Screen Image' + linkXPath = '/html/body/div/div/section[3]/div/ul/li[1]/a' + modalXPath = '/html/body/div[1]/div/div[2]' + }, + @{Name = 'Top Player' + linkXPath = '/html/body/div/div/section[4]/div/div/div[1]/div[2]/div[2]/div/a/div' + modalXPath = '//*[@id="profile-modal-1"]/div/div' + } + ) +} diff --git a/Output/Selenium/Examples/comparison.ps1 b/Output/Selenium/Examples/comparison.ps1 new file mode 100644 index 0000000..0e9f913 --- /dev/null +++ b/Output/Selenium/Examples/comparison.ps1 @@ -0,0 +1,60 @@ + +<# +public void testClass() throws Exception { + driver.get("http://www.wikipedia.org/") ; + Assert.assertequals("wikipedia", driver.getTitle()); + Assert.assertequals("English", driver.findElement(By.cssselector("strong")).getText()) + driver.findElement(By.cssSetector("strong")).click() ; + Assert.assertEquals("Wikipedia. the free encyclopedia", driver.getTitle()); +} +#> +Start-SeDriver -Browser Chrome -StartURL "https://www.wikipedia.org/" +SeShouldHave -Title eq Wikipedia +SeShouldHave 'strong' -By CssSelector -With Text eq 'English' -PassThru | Invoke-SeClick +SeShouldHave -Title eq 'Wikipedia, the free encyclopedia' + +<# +line 2 ## SeShouldHave -Title eq Wikipedia +is actutally short for ## SeShouldHave -Title -Operator 'eq' -Value Wikipedia +other values for -operator will translate to "eq", and parameters are defined so you can use -eq -contains, -match etc +so you can use ## SeShouldHave -Title equalTo Wikipedia +or ## SeShouldHave -Title -eq Wikipedia +line 3 ## SeShouldHave 'strong' -By CssSelector Text eq 'English' +This is short for ## SeShouldHave -Selection 'strong' -By CssSelector -With Text -operator "eq" -value 'English' +if the selector is an xPath the -By parameter can be omitted; but if used -By must specified explicitly +The first unnamed parameter will be treated as selection, the second as "with" , the third as operator and the fourth as value. +SeShouldhave can take a -passthru parameter allowing the original lines 3 and 4 to be merged, + +The last line 5 is similar to line 2 but the parameter value has a sppace so must be wrapped in quotes +#> + +<#https://www.guru99.com/first-webdriver-script.html had this +public static void main(String[] args) { + System.setProperty("webdriver.gecko.driver","C:\\geckodriver.exe"); + WebDriver driver = new FirefoxDriver(); + //comment the above 2 lines and uncomment below 2 lines to use Chrome + //System.setProperty("webdriver.chrome.driver","G:\\chromedriver.exe"); + //WebDriver driver = new ChromeDriver(); + + String baseUrl = "http://demo.guru99.com/test/newtours/"; + driver.get(baseUrl); + + String expectedTitle = "Welcome: Mercury Tours"; + String actualTitle = ""; + actualTitle = driver.getTitle(); + if (actualTitle.contentEquals(expectedTitle)){ + System.out.println("Test Passed!"); + } else { + System.out.println("Test Failed"); + } + + driver.close(); +} +#> + +Start-SeDriver -Browser Firefox -StartURL "http://demo.guru99.com/test/newtours/" +SeShouldHave -Title eq "Welcome: Mercury Tours" + +#Stop opened drivers +Get-SeDriver | Stop-SeDriver + diff --git a/Output/Selenium/Examples/test-seremote.ps1 b/Output/Selenium/Examples/test-seremote.ps1 new file mode 100644 index 0000000..e5b1bfe --- /dev/null +++ b/Output/Selenium/Examples/test-seremote.ps1 @@ -0,0 +1,134 @@ +$PSGalleryPage = 'https://www.powershellgallery.com/' +$AlertTestPage = 'https://www.w3schools.com/js/tryit.asp?filename=tryjs_alert' +$SelectTestPage = 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_elem_select' + +#other services at +#https://crossbrowsertesting.com/freetrial / https://help.crossbrowsertesting.com/selenium-testing/getting-started/c-sharp/ +#https://www.browserstack.com/automate/c-sharp + +$key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +$secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +$RemoteDriverURL = [uri]"http://$key`:$secret@hub.testingbot.com/wd/hub" +$caps = @{ + platform = 'HIGH-SIERRA' + browserName = 'safari' + version = '11' +} + +Start-SeRemote -RemoteAddress $RemoteDriverURL -DesiredCapabilities $caps -AsDefaultDriver -StartURL $PSGalleryPage +$BrowserID = $SeDriver.Capabilities.ToDictionary()["platformName", "browserName", "version"] -join " " + +Describe "All in one Test" { + Context "in $BrowserID with settings ($BrowserOptText)"{ + It 'opened the put the webdriver in a global variable ' { + $Global:SeDriver | Should -Not -BeNullOrEmpty + $Global:SeDriver | Should -BeOfType [OpenQA.Selenium.Remote.RemoteWebDriver] + } + It 'reached the right starting page ' { + #Should have can check alerts, page title, URL or an element on the page + SeShouldHave -URL eq $PSGalleryPage + } + It 'found the "Sign in" link on the home page by partial text ' { + SeShouldHave -By PartialLinkText 'Sign in' -With href match logon + } + It 'found the search box on the home page by ID ' { + SeShouldHave -By Id search + } + It 'found the search box on the home page by Name ' { + SeShouldHave -By Name 'q' + } + It 'found the search box on the home page by css selector ' { + #can write -By <> [-selection] <> + # or [-selection] <> -By <> + SeShouldHave 'input[name=q]' -By CssSelector + } + It 'found the search box on the home page by class name ' { + SeShouldHave -By ClassName "search-box" + } + It 'found the search box on the home page by Tagname and typed in it ' { + #get element, pipe as input element for Typing, pass the element through + #so pester catches 'null or empty' if it was not found + SeElement -By TagName input | + SeType -ClearFirst "selenium{{Enter}}" -PassThru -Sleep 2 | Should -Not -BeNullorEmpty + } + $linkpath = '//*[@id="skippedToContent"]/section/div[1]/div[2]/div[2]/section[1]/div/table/tbody/tr/td[1]/div/div[2]/header/div[1]/h1/a' + It 'searched successfully ' { + SeShouldHave -URL match 'packages\?q=selenium' -Timeout 15 + #Two tests on the same element, second passes it through to click + SeShouldHave $linkpath -With href match selenium + SeShouldHave $linkpath -With Text like *selenium* -PassThru | SeClick -Sleep 5 + } + It 'opened the search result page and found the expected content ' { + #Just to show we can test for the presence of multiple links. Each one is re-tested ... + SeShouldHave '//*[@id="version-history"]/table/tbody[1]/tr[1]/ td[1]/a/b' , + '//*[@id="skippedToContent"]/section/div/aside/ul[2]/li[1]/a' -Timeout 15 + + SeShouldHave '//*[@id="version-history"]/table/tbody[1]/tr[1]/ td[1]/a/b' -With text match "current" + + #Can test with "Get-SeElement | where-object <>" rather than "with <> <> <>" + SeElement '//*[@id="skippedToContent"]/section/div/aside/ul[2]/li[1]/a' | + Where-Object {($_.text -like "*Project Site*") -and ($_.GetAttribute('href') -match "selenium") } | + SeClick -PassThru | Should -Not -Benullorempty + } + It 'went to Github from the project link on the search result ' { + SeShouldHave -URL match 'github' -Timeout 30 + } + + It 'navigated back to the start page ' { + SeNavigate -Back + SeNavigate -Back + SeNavigate -Back + SeShouldHave -URL eq $PSGalleryPage -Timeout 30 + } + It 'did a google Search ' { + SeNavigate 'https://www.google.com/ncr' + SeShouldHave -by Name q + SeShouldHave -by ClassName 'gLFyf' + SeShouldHave -By TagName input -With title eq 'Search' -PassThru | + Select-Object -First 1 | + SeType -Keys 'Powershell-Selenium{{Enter}}' -PassThru | should -Not -BeNullOrEmpty + + SeShouldHave '//*[@id="tsf"]/div[2]/div[1]/div[1]/a' -PassThru | + SeClick -PassThru | should -Not -BeNullOrEmpty + } + It 'opened the the alert test-page ' { + SeNavigate $alertTestPage + SeShouldHave -URL -eq $alertTestPage + } + It 'found and clicked a button in frame 1 ' { + SeShouldHave -Selection "iframe" -By TagName -with id eq iframeResult + SeFrame 'iframeResult' + SeElement "/html/body/button" | SeClick -PassThru | Should -Not -BeNullOrEmpty + } + It 'saw and dismissed an alert ' { + #Checking the text of the alert is optional. Dissmiss can pass the alert result through + SeShouldHave -Alert match "box" -PassThru | + SeDismiss -PassThru | Should -Not -BeNullOrEmpty + } + It 'reselected the parent frame ' { + SeFrame -Parent + SeShouldHave -Selection "iframe" -By TagName -with id eq iframeResult + } + It 'navigated to a new page, and found the "cars" selection box in frame 1 ' { + SeNavigate $SelectTestPage + SeShouldHave -Selection "iframe" -By TagName -with id eq iframeResult + SeFrame 'iframeResult' + SeShouldHave -By Name "cars" -With choice contains "volvo" + } + It 'made selections from the "cars" selection box ' { + $e = SeElement -by Name "cars" + #Values are lower case Text has inital caps comparisons are case sensitve. Index is 0-based + {$e | SeSelection -ByValue "Audi"} | Should -Throw + {$e | SeSelection -ByValue "audi"} | Should -Not -Throw + $e | SeSelection -ByIndex "2" -GetSelected | Should -Be 'Fiat' + $e | SeSelection -ByPartialText "Sa" + } + It 'submitted the form and got the expected response ' { + SeElement '/html/body/form/input' | SeClick -Sleep 5 + SeFrame -Parent + SeFrame 'iframeResult' + SeShouldHave "/html/body/div[1]" -with text match "cars=saab" + } + } +} +SeClose \ No newline at end of file diff --git a/Output/Selenium/README.md b/Output/Selenium/README.md new file mode 100644 index 0000000..f47d20d --- /dev/null +++ b/Output/Selenium/README.md @@ -0,0 +1,123 @@ +# Selenium PowerShell Module + +The Selenium PowerShell module allows you to automate browser interaction using the [Selenium API](https://selenium.dev/). You can navigate to pages, find elements, click buttons, enter text and even take screenshots. + +# Looking for Maintainers + +I haven't been able to able to keep up with the issues on this repo. If you are interested in becoming a maintainer, please let me know. - [Adam](https://github.com/adamdriscoll) + +# About + +- Wraps the C# WebDriver for Selenium +- Easily execute web-based tests +- Works well with Pester + +[![Build Status](https://adamrdriscoll.visualstudio.com/Selenium/_apis/build/status/adamdriscoll.selenium-powershell?branchName=master)](https://adamrdriscoll.visualstudio.com/Selenium/_build/latest?definitionId=25&branchName=master) + +# Installation +`Note: Firefox's Latest Gecko Driver on Windows requires Microsoft Visual Studio Redistributables for the binary to run get them `[Here](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) + + +```powershell +Install-Module Selenium +``` + +OR + +``` +Import-Module "{FullPath}\selenium-powershell\Selenium.psd1" +``` + +# Usage +`Note: in order to use a specific driver you will need to have the brower of the driver installed on your system. +For example if you use Start-SeChrome you will need to have either a Chrome or Chromium browser installed +` + +## Start a Browser Driver +```powershell +# Start a driver for a browser of your choise (Chrome/Firefox/Edge/InternetExplorer) +# To start a Firefox Driver +$Driver = Start-SeFirefox + +# To start a Chrome Driver +$Driver = Start-SeChrome + +# To start an Edge Driver +$Driver = Start-SeEdge +``` + +## Navigate to a URL + +```powershell +$Driver = Start-SeFirefox +Enter-SeUrl https://www.poshud.com -Driver $Driver +``` + +## Find an Element + +```powershell +$Driver = Start-SeFirefox +Enter-SeUrl https://www.poshud.com -Driver $Driver +$Element = Find-SeElement -Driver $Driver -Id "myControl" +``` + +## Click on an Element/Button + +```powershell +$Driver = Start-SeFirefox +Enter-SeUrl https://www.poshud.com -Driver $Driver +$Element = Find-SeElement -Driver $Driver -Id "btnSend" +Invoke-SeClick -Element $Element +``` + +## Send Keystrokes + +```powershell +$Driver = Start-SeFirefox +Enter-SeUrl https://www.poshud.com -Driver $Driver +$Element = Find-SeElement -Driver $Driver -Id "txtEmail" +Send-SeKeys -Element $Element -Keys "adam@poshtools.com" +``` + +## Run Chrome with options + +```powershell +# Run Chrome in Headless mode +$Driver = Start-SeChrome -Headless + +# Run Chrome in incognito mode +$Driver = Start-SeChrome -Incognito + +# Run Chrome with alternative download folder +$Driver = Start-SeChrome -DefaultDownloadPath C:\Temp + +# Run Chrome and go to a URL in one command +$Driver = Start-SeChrome -StartURL 'https://www.google.com/ncr' + +# Run Chrome with multiple Arguments +$Driver = Start-SeChrome -Arguments @('Incognito','start-maximized') + +# Run Chrome with an existing profile. +# The default profile paths are as follows: +# Windows: C:\Users\\AppData\Local\Google\Chrome\User Data +# Linux: /home//.config/google-chrome +# MacOS: /Users//Library/Application Support/Google/Chrome +$Driver = Start-SeChrome -ProfileDirectoryPath '/home//.config/google-chrome' + +``` + +## Find and Wait for an element +```powershell +$Driver = Start-SeChrome +Enter-SeUrl 'https://www.google.com/ncr' -Driver $Driver + +# Please note that with the -Wait parameter only one element can be returned at a time. +Find-SeElement -Driver $d -Wait -Timeout 10 -Css input[name='q'] +Find-SeElement -Driver $d -Wait -Timeout 10 -Name q +``` + +# Maintainers + +- [Adam Driscoll](https://github.com/adamdriscoll) +- [Avri Chen-Roth](https://github.com/the-mentor) +- [Francis Mercier](https://github.com/itfranck) diff --git a/Output/Selenium/Selenium-Binary-Updater.ps1 b/Output/Selenium/Selenium-Binary-Updater.ps1 new file mode 100644 index 0000000..5fbb229 --- /dev/null +++ b/Output/Selenium/Selenium-Binary-Updater.ps1 @@ -0,0 +1,50 @@ +param( + [Parameter(Mandatory=$true)][ValidateSet('Chrome','Firefox','Edge')]$Browser +) + +$TempDir = [System.IO.Path]::GetTempPath() + +switch ($Browser){ + 'Chrome'{ + $LatestChromeStableRelease = Invoke-WebRequest 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE' | Select-Object -ExpandProperty Content + $ChromeBuilds = @('chromedriver_linux64','chromedriver_mac64','chromedriver_win32') + + foreach ($Build in $ChromeBuilds){ + switch($Build){ + 'chromedriver_linux64'{ + $AssembliesDir = "$PSScriptRoot/assemblies/linux" + $BinaryFileName = 'chromedriver' + } + 'chromedriver_mac64'{ + $AssembliesDir = "$PSScriptRoot/assemblies/macos" + $BinaryFileName = 'chromedriver' + } + 'chromedriver_win32'{ + $AssembliesDir = "$PSScriptRoot/assemblies" + $BinaryFileName = 'chromedriver.exe' + } + default{throw 'Incorrect Build Type'} + } + + $BuildFileName = "$Build.zip" + Write-Verbose "Downloading: $BuildFileName" + Invoke-WebRequest -OutFile "$($TempDir + $BuildFileName)" "https://chromedriver.storage.googleapis.com/$LatestChromeStableRelease/$BuildFileName" + + # Expand the ZIP Archive to the correct Assemblies Dir + Write-Verbose "Explanding: $($TempDir + $BuildFileName) to $AssembliesDir" + Expand-Archive -Path "$($TempDir + $BuildFileName)" -DestinationPath $AssembliesDir -Force + + # Generate Hash Files + Write-Verbose "Generating SHA256 Hash File: $AssembliesDir/$BinaryFileName.sha256" + Get-FileHash -Path "$AssembliesDir/$BinaryFileName" -Algorithm SHA256 | Select-Object -ExpandProperty Hash | Set-Content -Path "$AssembliesDir/$BinaryFileName.sha256" -Force + + } + } + 'Firefox'{ + Write-Host 'Not Supported Yet' + + } + 'Edge'{ + Write-Host 'Not Supported Yet' + } +} \ No newline at end of file diff --git a/Output/Selenium/Selenium.psd1 b/Output/Selenium/Selenium.psd1 new file mode 100644 index 0000000..27607e9 --- /dev/null +++ b/Output/Selenium/Selenium.psd1 @@ -0,0 +1,92 @@ +# +# Module manifest for module 'Selenium' +# +# Generated by: Adam Driscoll +# +# Generated on: 8/31/2018 +# +# Modified James O'Neill 30 Nov 2019 + +@{ + ModuleVersion = '4.0.0' + GUID = 'a3bdb8c3-c150-48a8-b56d-cd4d43f46a26' + Author = 'Adam Driscoll' + CompanyName = 'Unknown' + Copyright = '(c) 2020 Adam Driscoll. All rights reserved.' + Description = 'Web automation using the Selenium Web Driver' + ScriptsToProcess = @('SeleniumClasses.ps1') + RootModule = 'Selenium.psm1' + RequiredAssemblies = @('./assemblies/WebDriver.dll', './assemblies/WebDriver.Support.dll') + FunctionsToExport = @('Clear-SeAlert', 'Clear-SeSelectValue', 'ConvertTo-SeSelenium', 'Get-SeCookie', 'Get-SeDriver', 'Get-SeDriverTimeout', 'Get-SeElement', 'Get-SeElementAttribute', 'Get-SeElementCssValue', 'Get-SeFrame', 'Get-SeHtml', 'Get-SeInput', 'Get-SeKeys', 'Get-SeSelectValue', 'Get-SeUrl', 'Get-SeWindow', 'Invoke-SeClick', 'Invoke-SeJavascript', 'Invoke-SeKeys', 'Invoke-seMouseAction', 'New-SeDriverOptions', 'New-SeDriverService', 'New-SeScreenshot', 'New-SeWindow', 'Pop-SeUrl', 'Push-SeUrl', 'Remove-SeCookie', 'Remove-SeWindow', 'Save-SeScreenshot', 'SeShouldHave', 'Set-SeCookie', 'Set-SeDriverTimeout', 'Set-SeSelectValue', 'Set-SeUrl', 'Start-SeDriver', 'Start-SeRemote', 'Stop-SeDriver', 'Switch-SeDriver', 'Switch-SeFrame', 'Switch-SeWindow', 'Update-SeDriver', 'Wait-SeDriver', 'Wait-SeElement') + AliasesToExport = @() + CmdletsToExport = @() + VariablesToExport = @() + DscResourcesToExport = @() + FileList = @('.\assemblies', + '.\Examples', + '.\ChangeLog.md', + '.\README.md', + '.\Selenium.psm1' + '.\Selenium.tests.ps1' + '.\Selenium-Binary-Updater.ps1') + + PrivateData = @{ + PSData = @{ + Tags = @('selenium', 'automation', 'web') + LicenseUri = 'https://github.com/adamdriscoll/selenium-powershell/blob/master/LICENSE' + ProjectUri = 'https://github.com/adamdriscoll/selenium-powershell' + ReleaseNotes = 'Updating WebDrivers for Selenium' + + # A URL to an icon representing this module. + # IconUri = '' + Prerelease = 'preview3' + } # End of PSData hashtable + + } # End of PrivateData hashtable + + # Supported PSEditions + # CompatiblePSEditions = @() + + # Minimum version of the Windows PowerShell engine required by this module + # PowerShellVersion = '' + + # Name of the Windows PowerShell host required by this module + # PowerShellHostName = '' + + # Minimum version of the Windows PowerShell host required by this module + # PowerShellHostVersion = '' + + # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # DotNetFrameworkVersion = '' + + # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # CLRVersion = '' + + # Processor architecture (None, X86, Amd64) required by this module + # ProcessorArchitecture = '' + + # Modules that must be imported into the global environment prior to importing this module + # RequiredModules = @() + + #Type files (.ps1xml) to be loaded when importing this module + TypesToProcess = @('types/Selenium.types.ps1xml') + + # Format files (.ps1xml) to be loaded when importing this module + FormatsToProcess = @('formats/Selenium.format.ps1xml') + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() + + # List of all modules packaged with this module + # ModuleList = @() + + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + + # HelpInfo URI of this module + # HelpInfoURI = '' + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' + +} diff --git a/Output/Selenium/Selenium.psm1 b/Output/Selenium/Selenium.psm1 new file mode 100644 index 0000000..6c563b7 Binary files /dev/null and b/Output/Selenium/Selenium.psm1 differ diff --git a/Output/Selenium/Selenium.tests.ps1 b/Output/Selenium/Selenium.tests.ps1 new file mode 100644 index 0000000..3d181eb --- /dev/null +++ b/Output/Selenium/Selenium.tests.ps1 @@ -0,0 +1,224 @@ +Import-Module (Join-Path $PSScriptRoot "Selenium.psd1") -Force + +Describe "Verify the Binaries SHA256 Hash" { + It "Check WebDriver.dll Hash"{ + # VirusTotal Scan URL = https://www.virustotal.com/gui/file/0ee619b1786cf5971c0f9c6ee1859497aecba93a4953cf92fea998e8eefadf3c/detection + $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\WebDriver.dll).Hash + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\WebDriver.dll.sha256) + } + + It "Check WebDriver.Support.dll Hash" { + # VirusTotal Scan URL = https://www.virustotal.com/gui/file/b59ba7d0cffe43e722b13ad737cf596f030788b86b5b557cb479f0b6957cce8a/detection + $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\WebDriver.Support.dll).Hash + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\WebDriver.Support.dll.sha256) + } + + It "Check ChromeDriver.exe Hash" { + # VirusTotal Scan URL = https://www.virustotal.com/gui/file/c5c852d8f0890eb8c0b77fed623a3c36f50434552e9623e47fadf1e445f2f772/detection + $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\chromedriver.exe).Hash + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\chromedriver.exe.sha256) + } + + It "Check ChromeDriver Linux Hash" { + # VirusTotal Scan URL = https://www.virustotal.com/gui/file/ed50bce67a54727b7bf323d588d62be699233a75300d24c92409499a9329b2e6/detection + $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\linux\chromedriver).Hash + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\linux\chromedriver.sha256) + } + + It "Check ChromeDriver MacOS Hash" { + # VirusTotal Scan URL = https://www.virustotal.com/gui/file/6bb2996ebdeea6b2d10e6a9397ff53c394ebbaa8388087f134a4bc10f532863c/detection + $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\macos\chromedriver).Hash + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\macos\chromedriver.sha256) + } + + It "Check GeckoDriver.exe Hash" { + # VirusTotal Scan URL = https://www.virustotal.com/gui/file/255c9d3571c86841213f49b26d176a6ad440be8c720e3c2d9226076adf4f603d/detection + $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\geckodriver.exe).Hash + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\geckodriver.exe.sha256) + } + + It "Check GeckoDriver Linux Hash" { + # VirusTotal Scan URL = https://www.virustotal.com/gui/file/6590e3b9d9bf292c8df50b6df5bcf8a5191d999f9e48f68aa2055eb5746b2c05/detection + $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\linux\geckodriver).Hash + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\linux\geckodriver.sha256) + } + + It "Check GeckoDriver MacOS Hash" { + # VirusTotal Scan URL = https://www.virustotal.com/gui/file/d62c2178377addeb1bb860426b2c9b10b68d2eeabf0c521529a4a6a7b1e208c4/detection + $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\macos\geckodriver).Hash + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\macos\geckodriver.sha256) + } + + It "Check IEDriverServer.exe Hash" { + # VirusTotal Scan URL = https://www.virustotal.com/gui/file/a1e26b0e8cb5f8db1cd784bac71bbf540485d81e697293b0b4586e25a31a8187/detection - this driver seems to have 2 false positives and is marked as clean in the comments + $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\IEDriverServer.exe).Hash + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\IEDriverServer.exe.sha256) + } + + It "Check MicrosoftWebDriver.exe Hash" { + # VirusTotal Scan URL = https://www.virustotal.com/gui/file/6e8182697ea5189491b5519d8496a3392e43741b7c0515130f2f8205881d208e/detection + $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\MicrosoftWebDriver.exe).Hash + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\MicrosoftWebDriver.exe.sha256) + } +} + +Describe "Start-SeChrome" { + Context "Should Start Chrome Driver" { + $Driver = Start-SeChrome + Stop-SeDriver $Driver + } +} + +Describe "Start-SeChrome with Options" { + Context "Should Start Chrome Driver with different startup options" { + It "Start Chrome with StartURL" { + $Driver = Start-SeChrome -StartURL 'https://github.com/adamdriscoll/selenium-powershell' + Stop-SeDriver $Driver + } + + It "Start Chrome in Headless mode" { + $Driver = Start-SeChrome -Headless + Stop-SeDriver $Driver + } + + It "Start Chrome Minimize" { + $Driver = Start-SeChrome -Minimize + Stop-SeDriver $Driver + } + + It "Start Chrome Maximized" { + $Driver = Start-SeChrome -Maximized + Stop-SeDriver $Driver + } + + It "Start Chrome Incognito" { + $Driver = Start-SeChrome -Incognito + Stop-SeDriver $Driver + } + + It "Start Chrome Fullscreen" { + $Driver = Start-SeChrome -Fullscreen + Stop-SeDriver $Driver + } + + It "Start Chrome Maximized and Incognito" { + $Driver = Start-SeChrome -Maximized -Incognito + Stop-SeDriver $Driver + } + + It "Start Chrome with Multiple arguments" { + $Driver = Start-SeChrome -Arguments @('Incognito','start-maximized') + Stop-SeDriver $Driver + } + } +} + +Describe "Start-SeFirefox"{ + Context "Should Start Firefox Driver" { + $Driver = Start-SeFirefox + Stop-SeDriver $Driver + } +} + +Describe "Start-SeFirefox with Options" { + Context "Should Start Firefox Driver with different startup options" { + It "Start Firefox with StartURL" { + $Driver = Start-SeFirefox -StartURL 'https://github.com/adamdriscoll/selenium-powershell' + Stop-SeDriver $Driver + } + + It "Start Firefox in Headless mode" { + $Driver = Start-SeFirefox -Headless + Stop-SeDriver $Driver + } + + It "Start Firefox Minimize" { + $Driver = Start-SeFirefox -Minimize + Stop-SeDriver $Driver + } + + It "Start Firefox Maximized" { + $Driver = Start-SeFirefox -Maximized + Stop-SeDriver $Driver + } + + It "Start Firefox PrivateBrowsing (Incognito)" { + $Driver = Start-SeFirefox -PrivateBrowsing + Stop-SeDriver $Driver + } + + It "Start Firefox Fullscreen" { + $Driver = Start-SeFirefox -Fullscreen + Stop-SeDriver $Driver + } + + It "Start Firefox Maximized and PrivateBrowsing (Incognito)" { + $Driver = Start-SeFirefox -Maximized -PrivateBrowsing + Stop-SeDriver $Driver + } + + It "Start Firefox with Multiple arguments" { + $Driver = Start-SeFirefox -Arguments @('-headless','-private') + Stop-SeDriver $Driver + } + } +} + +Describe "Start-SeEdge" { + Context "Should Start Edge Driver" { + if(!$IsLinux -and !$IsMacOS){ + $Driver = Start-SeEdge + Stop-SeDriver $Driver + } + } +} + +Describe "Start-SeInternetExplorer" { + Context "Should Start InternetExplorer Driver" { + if(!$IsLinux -and !$IsMacOS){ + $Driver = Start-SeInternetExplorer + Stop-SeDriver $Driver + } + } +} + +Describe "Get-SeCookie" { + $Driver = Start-SeFirefox + Context "Should get cookies from google" { + Enter-SeUrl -Driver $Driver -Url "http://www.google.com" + + Get-SeCookie $Driver + } + Stop-SeDriver $Driver +} + +Describe "Send-SeKeys" { + $Driver = Start-SeFirefox + Enter-SeUrl -Driver $Driver -Url "http://www.google.com/ncr" + Context "Find-SeElement" { + It "By Css" { + $SearchInput = Find-SeElement -Driver $Driver -Css "input[name='q']" + Send-SeKeys -Element $SearchInput -Keys "test" + } + } + Stop-SeDriver $Driver +} + +Describe "Find-SeElement Firefox" { + $Driver = Start-SeFirefox + Enter-SeUrl -Driver $Driver -Url "http://www.google.com/ncr" + Context "Find-SeElement" { + It "By Css" { + $SearchInput = Find-SeElement -Driver $Driver -Css "input[name='q']" + } + } + + Context "Find-SeElement -Wait" { + It "By Name"{ + $SearchInput = Find-SeElement -Driver $Driver -Wait -Name q -Timeout 60 + } + } + + Stop-SeDriver $Driver +} + diff --git a/Output/Selenium/SeleniumClasses.ps1 b/Output/Selenium/SeleniumClasses.ps1 new file mode 100644 index 0000000..9031fff --- /dev/null +++ b/Output/Selenium/SeleniumClasses.ps1 @@ -0,0 +1,144 @@ +using namespace system.Collections +using namespace System.Collections.Generic +using namespace System.Management.Automation +using namespace System.Management.Automation.Language + +if ('ValidateURIAttribute' -as [type]) { + class ValidateURIAttribute : System.Management.Automation.ValidateArgumentsAttribute { + [void] Validate([object] $arguments , [System.Management.Automation.EngineIntrinsics]$EngineIntrinsics) { + $Out = $null + if ([uri]::TryCreate($arguments, [System.UriKind]::Absolute, [ref]$Out)) { return } + else { throw [System.Management.Automation.ValidationMetadataException]::new('Incorrect StartURL please make sure the URL starts with http:// or https://') } + return + } + } + class ValidateURI : ValidateURIAttribute {} +} + + +if ('ValidateIsWebDriverAttribute' -as [type]) { + class ValidateIsWebDriverAttribute : System.Management.Automation.ValidateArgumentsAttribute { + [void] Validate([object] $arguments , [System.Management.Automation.EngineIntrinsics]$EngineIntrinsics) { + if ($arguments -isnot [OpenQA.Selenium.Remote.RemoteWebDriver]) { + throw [System.Management.Automation.ValidationMetadataException]::new('Target was not a valid web driver') + } + return + } + } + class ValidateIsWebDriver : ValidateIsWebDriverAttribute {} +} + + + +if ('OperatorTransformAttribute' -as [type]) { + #Allow operator to use containing, matching, matches, equals etc. + class OperatorTransformAttribute : System.Management.Automation.ArgumentTransformationAttribute { + [object] Transform([System.Management.Automation.EngineIntrinsics]$EngineIntrinsics, [object] $InputData) { + if ($inputData -match '^(contains|like|notlike|match|notmatch|eq|ne|gt|lt)$') { + return $InputData + } + switch -regex ($InputData) { + "^contain" { return 'contains' ; break } + "^match" { return 'match' ; break } + "^n\w*match" { return 'notmatch' ; break } + "^eq" { return 'eq' ; break } + "^n\w*eq" { return 'ne' ; break } + "^n\w*like" { return 'like' ; break } + } + return $InputData + } + } + + class OperatorTransform : OperatorTransformAttribute {} +} + +$dll1Path = Join-path -path (Join-path -path $PSScriptRoot -ChildPath 'assemblies') -ChildPath 'WebDriver.dll' +$dll2Path = Join-path -path (Join-path -path $PSScriptRoot -ChildPath 'assemblies') -ChildPath 'WebDriver.Support.dll' + +Add-type @" +using OpenQA.Selenium; +using OpenQA.Selenium.Support.UI; +using System.Collections.Generic; +namespace SeleniumSelection { + public class Option { + public static bool IsMultiSelect(IWebElement element) { + var selection = new SelectElement(element); + return selection.IsMultiple; + } + public static IList GetOptions(IWebElement element) { + var selection = new SelectElement(element); + return selection.Options; + } + public static void SelectByValue(IWebElement element, string value) { + var selection = new SelectElement(element); + selection.SelectByValue(value); + } + public static void DeselectByValue(IWebElement element, string value) { + var selection = new SelectElement(element); + selection.DeselectByValue(value); + } + public static void SelectByText(IWebElement element, string text, bool partialMatch = false) { + var selection = new SelectElement(element); + selection.SelectByText(text,partialMatch); + } + public static void DeselectByText(IWebElement element, string text) { + var selection = new SelectElement(element); + selection.DeselectByText(text); + } + public static void SelectByIndex(IWebElement element, int index) { + var selection = new SelectElement(element); + selection.SelectByIndex(index); + } + public static void DeselectByIndex(IWebElement element, int index) { + var selection = new SelectElement(element); + selection.DeselectByIndex(index); + } + public static void DeselectAll(IWebElement element) { + var selection = new SelectElement(element); + selection.DeselectAll(); + } + public static IWebElement GetSelectedOption(IWebElement element) { + var selection = new SelectElement(element); + return selection.SelectedOption; + } + public static IList GetAllSelectedOptions(IWebElement element) { + var selection = new SelectElement(element); + return selection.AllSelectedOptions; + } + } +} +"@ -ReferencedAssemblies $dll1Path, $dll2Path, mscorlib + + +enum SeBrowsers { + Chrome + Edge + Firefox + InternetExplorer + MSEdge +} + +enum SeWindowState { + Headless + Default + Minimized + Maximized + Fullscreen +} + +enum SeBySelector { + ClassName + CssSelector + Id + LinkText + PartialLinkText + Name + TagName + XPath +} + +enum SeBySelect { + Index + Text + Value +} \ No newline at end of file diff --git a/Output/Selenium/assemblies/IEDriverServer.exe b/Output/Selenium/assemblies/IEDriverServer.exe new file mode 100644 index 0000000..d5d6ada Binary files /dev/null and b/Output/Selenium/assemblies/IEDriverServer.exe differ diff --git a/Output/Selenium/assemblies/IEDriverServer.exe.sha256 b/Output/Selenium/assemblies/IEDriverServer.exe.sha256 new file mode 100644 index 0000000..7a01c45 --- /dev/null +++ b/Output/Selenium/assemblies/IEDriverServer.exe.sha256 @@ -0,0 +1 @@ +51053574E3BA3AB5D9F47E13EC0E9961AD6C9C9978DC851BE71C0F86A272C74B diff --git a/Output/Selenium/assemblies/WebDriver.Support.dll b/Output/Selenium/assemblies/WebDriver.Support.dll new file mode 100644 index 0000000..0f85686 Binary files /dev/null and b/Output/Selenium/assemblies/WebDriver.Support.dll differ diff --git a/Output/Selenium/assemblies/WebDriver.Support.dll.sha256 b/Output/Selenium/assemblies/WebDriver.Support.dll.sha256 new file mode 100644 index 0000000..917d916 --- /dev/null +++ b/Output/Selenium/assemblies/WebDriver.Support.dll.sha256 @@ -0,0 +1 @@ +B59BA7D0CFFE43E722B13AD737CF596F030788B86B5B557CB479F0B6957CCE8A diff --git a/Output/Selenium/assemblies/WebDriver.dll b/Output/Selenium/assemblies/WebDriver.dll new file mode 100644 index 0000000..41d471f Binary files /dev/null and b/Output/Selenium/assemblies/WebDriver.dll differ diff --git a/Output/Selenium/assemblies/WebDriver.dll.sha256 b/Output/Selenium/assemblies/WebDriver.dll.sha256 new file mode 100644 index 0000000..189a3f9 --- /dev/null +++ b/Output/Selenium/assemblies/WebDriver.dll.sha256 @@ -0,0 +1 @@ +0EE619B1786CF5971C0F9C6EE1859497AECBA93A4953CF92FEA998E8EEFADF3C diff --git a/Output/Selenium/assemblies/chromedriver.exe b/Output/Selenium/assemblies/chromedriver.exe new file mode 100644 index 0000000..14e61bc Binary files /dev/null and b/Output/Selenium/assemblies/chromedriver.exe differ diff --git a/Output/Selenium/assemblies/chromedriver.exe.sha256 b/Output/Selenium/assemblies/chromedriver.exe.sha256 new file mode 100644 index 0000000..e9f7251 --- /dev/null +++ b/Output/Selenium/assemblies/chromedriver.exe.sha256 @@ -0,0 +1 @@ +C6131A3106A8956702459673BDCC7F37BDD8989A141D2CBE15DC0157F0D53C74 diff --git a/Output/Selenium/assemblies/geckodriver.exe b/Output/Selenium/assemblies/geckodriver.exe new file mode 100644 index 0000000..4ce451b Binary files /dev/null and b/Output/Selenium/assemblies/geckodriver.exe differ diff --git a/Output/Selenium/assemblies/geckodriver.exe.sha256 b/Output/Selenium/assemblies/geckodriver.exe.sha256 new file mode 100644 index 0000000..e43d884 --- /dev/null +++ b/Output/Selenium/assemblies/geckodriver.exe.sha256 @@ -0,0 +1 @@ +FAED02EC5B0D6246856843D10EE020CB5121B8261AC939BE761130F21A73D3EE diff --git a/Output/Selenium/assemblies/linux/chromedriver b/Output/Selenium/assemblies/linux/chromedriver new file mode 100644 index 0000000..68b4075 Binary files /dev/null and b/Output/Selenium/assemblies/linux/chromedriver differ diff --git a/Output/Selenium/assemblies/linux/chromedriver.sha256 b/Output/Selenium/assemblies/linux/chromedriver.sha256 new file mode 100644 index 0000000..4eb67e6 --- /dev/null +++ b/Output/Selenium/assemblies/linux/chromedriver.sha256 @@ -0,0 +1 @@ +01112975217552167F101D7B549D31A12B3C45ABE411892F92228BF8CB2F0058 diff --git a/Output/Selenium/assemblies/linux/geckodriver b/Output/Selenium/assemblies/linux/geckodriver new file mode 100644 index 0000000..bf9538e Binary files /dev/null and b/Output/Selenium/assemblies/linux/geckodriver differ diff --git a/Output/Selenium/assemblies/linux/geckodriver.sha256 b/Output/Selenium/assemblies/linux/geckodriver.sha256 new file mode 100644 index 0000000..930beaa --- /dev/null +++ b/Output/Selenium/assemblies/linux/geckodriver.sha256 @@ -0,0 +1 @@ +0B2C9B9791925DCEA2981CBDFAB8274FB4668BF65D6A57C2257E8B57757C394A diff --git a/Output/Selenium/assemblies/macos/chromedriver b/Output/Selenium/assemblies/macos/chromedriver new file mode 100644 index 0000000..f4bfcc6 Binary files /dev/null and b/Output/Selenium/assemblies/macos/chromedriver differ diff --git a/Output/Selenium/assemblies/macos/chromedriver.sha256 b/Output/Selenium/assemblies/macos/chromedriver.sha256 new file mode 100644 index 0000000..27ca9d8 --- /dev/null +++ b/Output/Selenium/assemblies/macos/chromedriver.sha256 @@ -0,0 +1 @@ +1DA3E0CBF79A92CF06B08812A39991A37B5C5458DEC2A7B4FFF34F6D87126281 diff --git a/Output/Selenium/assemblies/macos/geckodriver b/Output/Selenium/assemblies/macos/geckodriver new file mode 100644 index 0000000..4a2671f Binary files /dev/null and b/Output/Selenium/assemblies/macos/geckodriver differ diff --git a/Output/Selenium/assemblies/macos/geckodriver.sha256 b/Output/Selenium/assemblies/macos/geckodriver.sha256 new file mode 100644 index 0000000..ac73b7f --- /dev/null +++ b/Output/Selenium/assemblies/macos/geckodriver.sha256 @@ -0,0 +1 @@ +AA2FCE6B96183C9D8FD0AA125F87557FCCEC60301CF7ADD1578B0DA59355AD8B diff --git a/Output/Selenium/assemblies/msedgedriver.exe b/Output/Selenium/assemblies/msedgedriver.exe new file mode 100644 index 0000000..74d70ba Binary files /dev/null and b/Output/Selenium/assemblies/msedgedriver.exe differ diff --git a/Output/Selenium/assemblies/msedgedriver.exe.sha256 b/Output/Selenium/assemblies/msedgedriver.exe.sha256 new file mode 100644 index 0000000..1d5e296 --- /dev/null +++ b/Output/Selenium/assemblies/msedgedriver.exe.sha256 @@ -0,0 +1 @@ +A6EB02FF3EF75079A647F20BD0B6B563648BC4C8563443229C65671AB0BBB6CD diff --git a/Output/Selenium/en-US/Selenium-help.xml b/Output/Selenium/en-US/Selenium-help.xml new file mode 100644 index 0000000..36f73b6 --- /dev/null +++ b/Output/Selenium/en-US/Selenium-help.xml @@ -0,0 +1,6221 @@ + + + + + Clear-SeAlert + Clear + SeAlert + + Clear alert popup by dismissing or accepting it. + + + + Clear alert popup by dismissing or accepting it. + + + + Clear-SeAlert + + Action + + Action to be performed on the alert popup + + + Accept + Dismiss + + Object + + Object + + + None + + + Alert + + Specify alert window. Seems to be ignored in favor of Target / Default Target. + + Object + + Object + + + None + + + PassThru + + Return Alert object. + + + SwitchParameter + + + False + + + + + + Action + + Action to be performed on the alert popup + + Object + + Object + + + None + + + Alert + + Specify alert window. Seems to be ignored in favor of Target / Default Target. + + Object + + Object + + + None + + + PassThru + + Return Alert object. + + SwitchParameter + + SwitchParameter + + + False + + + + + + System.Object + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Clear-SeAlert -Action Dismiss + + Dismiss an alert on the currently selected driver. + + + + + + + + Clear-SeSelectValue + Clear + SeSelectValue + + Clear all selected entries of a SELECT element. + + + + Clear all selected entries of a SELECT element. + + + + Clear-SeSelectValue + + Element + + Target IWebElement + + IWebElement + + IWebElement + + + None + + + + + + Element + + Target IWebElement + + IWebElement + + IWebElement + + + None + + + + + + None + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Clear-SeSelectValue -Element $Select + + Clear the selected value from the specified SELECT element. + + + + + + + + ConvertTo-Selenium + ConvertTo + Selenium + + Convert Selenium IDE .side recording file to PowerShell commands. + + + + Convert Selenium IDE .side recording file to PowerShell commands. + + + + ConvertTo-Selenium + + Path + + Path to .side file. + + String + + String + + + None + + + + + + Path + + Path to .side file. + + String + + String + + + None + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> {{ Add example code here }} + + {{ Add example description here }} + + + + + + + + Get-SeCookie + Get + SeCookie + + List all cookies + + + + List all cookies + + + + Get-SeCookie + + + + + + + System.Object + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Get-SeCookie + + List all cookies of the default webdriver + + + + + + + + Get-SeDriver + Get + SeDriver + + Get the list of all active drivers. + + + + Get the list of all active drivers or drivers matching the specified criterias. + + + + Get-SeDriver + + Browser + + Filter the list of returned drivers by their Browser type (enum: [SeBrowsers]) + + Object + + Object + + + None + + + + Get-SeDriver + + Current + + Return the currently selected browser. Selected browser is the last one started, unless changed via Switch-SeDriver and is always the one that get used in all cmdlet that have an unspecified $Driver. + + + SwitchParameter + + + False + + + + Get-SeDriver + + Name + + Filter driver returned by its name (SeFriendlyName). + + String + + String + + + None + + + + + + Browser + + Filter the list of returned drivers by their Browser type (enum: [SeBrowsers]) + + Object + + Object + + + None + + + Current + + Return the currently selected browser. Selected browser is the last one started, unless changed via Switch-SeDriver and is always the one that get used in all cmdlet that have an unspecified $Driver. + + SwitchParameter + + SwitchParameter + + + False + + + Name + + Filter driver returned by its name (SeFriendlyName). + + String + + String + + + None + + + + + + None + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Get-SeDriver + + Return the list of all active drivers. + + + + -------------------------- Example 2 -------------------------- + PS C:\> Get-SeDriver -Current + + Return the currently selected browser. + + + + -------------------------- Example 3 -------------------------- + PS C:\> Get-SeDriver -Browser Chrome + + Returh the list of all active "Chrome" browsers. + + + + -------------------------- Example 3 -------------------------- + PS C:\> Get-SeDriver -Name '70c91e0f112dcdbd22b84dd567560b8d' + + Return the driver with the specified name. + + + + + + + + Get-SeDriverTimeout + Get + SeDriverTimeout + + Get the specified driver timeout value. + + + + Get the specified driver timeout value. + + + + Get-SeDriverTimeout + + TimeoutType + + Timeout type to be changed + + + ImplicitWait + PageLoad + AsynchronousJavaScript + + Object + + Object + + + ImplicitWait + + + + + + TimeoutType + + Timeout type to be changed + + Object + + Object + + + ImplicitWait + + + + + + OpenQA.Selenium.IWebDriver + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Get-SeDriverTimeout + + Return the currently selected driver implicit wait timeout. + + + + -------------------------- Example 2 -------------------------- + PS C:\> Get-SeDriverTimeout -TimeoutType PageLoad -Driver $Driver + + Return the specified driver PageLoad timeout. + + + + + + + + Get-SeElement + Get + SeElement + + Finds all IWebElements within the current context using the given mechanism + + + + Finds all IWebElements within the current context using the given mechanism. + + + + Get-SeElement + + Value + + Locator Value corresponding to the `$By` selector. There should be an equal number of values than `$By` selector provided. + + String[] + + String[] + + + None + + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + All + + Return matching hidden items in addition to displayed ones. + + + SwitchParameter + + + False + + + Attributes + + Append a list of Attributes (case sensitive) to each element returned. Attributes will be available through a dictionary property of the same name. Is the wildcard `*` character is used, all attributes will be queried and appended. + + String[] + + String[] + + + None + + + By + + The locating mechanism to use. It is possible to use multiple locator, in which case they will be processed sequentially. + + + ClassName + CssSelector + Id + LinkText + PartialLinkText + Name + TagName + XPath + + SeBySelector[] + + SeBySelector[] + + + None + + + Filter + + Filter the obtained output with additional conditions. This is equivalent to doing a Where-Object afterward with the benefit of going trough the Get-SeElement error management. + + ScriptBlock + + ScriptBlock + + + None + + + Single + + Expectation that only one element will be returned. An error will be returned if that parameter is set and more than one corresponding element is found. + + + SwitchParameter + + + False + + + + Get-SeElement + + Value + + Locator Value corresponding to the `$By` selector. There should be an equal number of values than `$By` selector provided. + + String[] + + String[] + + + None + + + Timeout + + Timeout (in seconds) + + Double + + Double + + + None + + + All + + Return matching hidden items in addition to displayed ones. + + + SwitchParameter + + + False + + + Attributes + + Append a list of Attributes (case sensitive) to each element returned. Attributes will be available through a dictionary property of the same name. Is the wildcard `*` character is used, all attributes will be queried and appended. + + String[] + + String[] + + + None + + + By + + The locating mechanism to use. It is possible to use multiple locator, in which case they will be processed sequentially. + + + ClassName + CssSelector + Id + LinkText + PartialLinkText + Name + TagName + XPath + + SeBySelector[] + + SeBySelector[] + + + None + + + Filter + + Filter the obtained output with additional conditions. This is equivalent to doing a Where-Object afterward with the benefit of going trough the Get-SeElement error management. + + ScriptBlock + + ScriptBlock + + + None + + + Single + + Expectation that only one element will be returned. An error will be returned if that parameter is set and more than one corresponding element is found. + + + SwitchParameter + + + False + + + + + + All + + Return matching hidden items in addition to displayed ones. + + SwitchParameter + + SwitchParameter + + + False + + + Attributes + + Append a list of Attributes (case sensitive) to each element returned. Attributes will be available through a dictionary property of the same name. Is the wildcard `*` character is used, all attributes will be queried and appended. + + String[] + + String[] + + + None + + + By + + The locating mechanism to use. It is possible to use multiple locator, in which case they will be processed sequentially. + + SeBySelector[] + + SeBySelector[] + + + None + + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + Filter + + Filter the obtained output with additional conditions. This is equivalent to doing a Where-Object afterward with the benefit of going trough the Get-SeElement error management. + + ScriptBlock + + ScriptBlock + + + None + + + Single + + Expectation that only one element will be returned. An error will be returned if that parameter is set and more than one corresponding element is found. + + SwitchParameter + + SwitchParameter + + + False + + + Timeout + + Timeout (in seconds) + + Double + + Double + + + None + + + Value + + Locator Value corresponding to the `$By` selector. There should be an equal number of values than `$By` selector provided. + + String[] + + String[] + + + None + + + + + + System.Object + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Get-SeElement -By XPath '//*[@id="home_text3"]/div[2]' -Value '//*[@id="home_text3"]/div[2]' +#Same but positionally bound +PS C:\> Get-SeElement '//*[@id="home_text3"]/div[2]' + + Get the elements matching the specified XPath selector. + + + + -------------------------- Example 2 -------------------------- + PS C:\> Get-SeElement -By Name -Value 'username' -Single + + Get the username field by name with the expectation only one element is to be returned. + + + + -------------------------- Example 3 -------------------------- + PS C:\> Get-SeElement -By Name -Value 'username' -Single + + Get the username field by name with the expectation only one element is to be returned. + + + + -------------------------- Example 4 -------------------------- + PS C:\> Get-SeElement -By ClassName -Value homeitem -All -Attributes name, id -Timeout 2.5 +#To return all attributes instead: -Attributes * + + Get the elements by classname. Include hidden items `-All` and append an `Attributes` NoteProperty to all the result containing the value for the name and id attribute. The call will also fail if no results are found after 2.5 seconds. + + + + -------------------------- Example 5 -------------------------- + PS C:\> Get-SeElement -By ClassName,PartialLinkText -Value 'homeitem','The' + + Get the elements that match the selectors in a sequential manner. This call will return all links that contains the defined text (The) within elements that have a classname of "homeitem". + + + + + + + + Get-SeElementAttribute + Get + SeElementAttribute + + Get the specified attribute from the specified element. + + + + Get the specified attribute from the specified element. + + + + Get-SeElementAttribute + + Element + + Target IWebElement + + IWebElement + + IWebElement + + + None + + + Name + + {{ Fill Name Description }} + + String[] + + String[] + + + None + + + + + + Element + + Target IWebElement + + IWebElement + + IWebElement + + + None + + + Name + + {{ Fill Name Description }} + + String[] + + String[] + + + None + + + + + + OpenQA.Selenium.IWebElement + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> $Element = Get-SeElement -By Name -Selection 'username' +PS C:\> Get-SeElementAttribute -Element $Element -Attribute 'placeholder' + + Get the placeholder attribue of the username element. + + + + + + + + Get-SeElementCssValue + Get + SeElementCssValue + + Get CSS value for the specified name of targeted element. + + + + Get CSS value for the specified name of targeted element. + + + + Get-SeElementCssValue + + Element + + Target IWebElement + + IWebElement + + IWebElement + + + None + + + Name + + Name of the CSS attribute to query + + String[] + + String[] + + + None + + + + + + Element + + Target IWebElement + + IWebElement + + IWebElement + + + None + + + Name + + Name of the CSS attribute to query + + String[] + + String[] + + + None + + + + + + OpenQA.Selenium.IWebElement + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Get-SeElementCssValue -Element $Element -Name 'padding' + + Get padding css value for the targeted element. + + + + + + + + Get-SeFrame + Get + SeFrame + + {{ Fill in the Synopsis }} + + + + {{ Fill in the Description }} + + + + Get-SeFrame + + + + + + + None + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> {{ Add example code here }} + + {{ Add example description here }} + + + + + + + + Get-SeHtml + Get + SeHtml + + Get outer html of the specified element or driver. + + + + Get outer html of the specified element or driver. Driver is used by default if no element is specified. + + + + Get-SeHtml + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + Inner + + Return inner html instead. + + + SwitchParameter + + + False + + + + + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + Inner + + Return inner html instead. + + SwitchParameter + + SwitchParameter + + + False + + + + + + None + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> $Element = Get-SeElement -By ClassName -Value 'homeitem' +PS C:\> $Element | Get-SeHtml -Inner + + Get inner html for all specified elements. + + + + -------------------------- Example 2 -------------------------- + PS C:\> Get-SeHtml + + Get html of the current page. Equivalent to $Driver.PageSource + + + + + + + + Get-SeInput + Get + SeInput + + Get element with an input tagname matching the specified conditions. + + + + Get SeElement with an input Tagname + + + + Get-SeInput + + Type + + Type of the input + + String + + String + + + None + + + Text + + Text of the input to return + + String + + String + + + None + + + Timeout + + Timeout (in seconds) + + Double + + Double + + + None + + + Attributes + + Append a list of Attributes (case sensitive) to each element returned. Attributes will be available through a dictionary property of the same name. Is the wildcard `*` character is used, all attributes will be queried and appended. + + String[] + + String[] + + + None + + + Value + + Expected value of the first attribute present. + + String + + String + + + None + + + All + + Return matching hidden items in addition to displayed ones. + + + SwitchParameter + + + False + + + Single + + Expectation that only one element will be returned. An error will be returned if that parameter is set and more than one corresponding element is found. + + + SwitchParameter + + + False + + + + + + All + + Return matching hidden items in addition to displayed ones. + + SwitchParameter + + SwitchParameter + + + False + + + Attributes + + Append a list of Attributes (case sensitive) to each element returned. Attributes will be available through a dictionary property of the same name. Is the wildcard `*` character is used, all attributes will be queried and appended. + + String[] + + String[] + + + None + + + Single + + Expectation that only one element will be returned. An error will be returned if that parameter is set and more than one corresponding element is found. + + SwitchParameter + + SwitchParameter + + + False + + + Text + + Text of the input to return + + String + + String + + + None + + + Timeout + + Timeout (in seconds) + + Double + + Double + + + None + + + Type + + Type of the input + + String + + String + + + None + + + Value + + Expected value of the first attribute present. + + String + + String + + + None + + + + + + None + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Get-SeInput -Attributes placeholder,title -All -Single -Value 'Type to search' + + Get all the input (including hidden) present in the Dom and load the attributes placeholder and title. A single value is expected and it's attribute placeholder should be equals to : "Type to search" + + + + + + + + Get-SeKeys + Get + SeKeys + + Return a list of the available special keys + + + + Return a list of the available special keys. These keys can be used with `Send-SeKeys` by using their name in the following format `{{SpecialKeyName}}` + + + + Get-SeKeys + + + + + + + None + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Get-SeKeys + + + + + + + + + + Get-SeSelectValue + Get + SeSelectValue + + Get Select element selected value. + + + + Get Select element selected value. + + + + Get-SeSelectValue + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + All + + Get All selected values (only available when the Select element accept multiple values) + + + SwitchParameter + + + False + + + + + + All + + Get All selected values (only available when the Select element accept multiple values) + + SwitchParameter + + SwitchParameter + + + False + + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + + + + OpenQA.Selenium.IWebElement + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Get-SeSelectValue -Element $Select + + Get the selected value for the specified element. + + + + + + + + Get-SeUrl + Get + SeUrl + + Retrieves the current URL of a target webdriver instance. + + + + Retrieves the current URL of a target webdriver instance, or the currently stored internal location stack. + + + + Get-SeUrl + + Stack + + Optionally retrieve the stored URL stack for the target or default webdriver instance. + + + SwitchParameter + + + False + + + + + + Stack + + Optionally retrieve the stored URL stack for the target or default webdriver instance. + + SwitchParameter + + SwitchParameter + + + False + + + + + + + When using -Stack, the retrieved stack will not contain any of the driver's history (Back/Forward) data. It only handles locations added with Push-SeUrl. + To utilise a driver's Back/Forward functionality, instead use Set-SeUrl. + + + + + -------------------------- EXAMPLE 1 -------------------------- + Get-SeUrl + + Retrieves the current URL of the default webdriver instance. + + + + + + + + Get-SeWindow + Get + SeWindow + + Gets the window handles of open browser windows + + + + Gets the window handles of open browser windows + + + + Get-SeWindow + + + + + + + OpenQA.Selenium.IWebDriver + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Get-SeWindow + + Gets the window handles of open browser windows. + + + + + + + + Invoke-SeClick + Invoke + SeClick + + Perform a click in the browser window or specified element. + + + + Perform a click in the browser window or specified element. + + + + Invoke-SeClick + + Action + + test + + Object + + Object + + + None + + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + PassThru + + Return the IWebElement. + + + SwitchParameter + + + False + + + Sleep + + Sleep time in second after performing the click action. + + Double + + Double + + + None + + + + + + Action + + test + + Object + + Object + + + None + + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + PassThru + + Return the IWebElement. + + SwitchParameter + + SwitchParameter + + + False + + + Sleep + + Sleep time in second after performing the click action. + + Double + + Double + + + None + + + + + + OpenQA.Selenium.IWebElement + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Invoke-SeClick + + Perform a click in the browser at the current position + + + + -------------------------- Example 2 -------------------------- + PS C:\> Invoke-SeClick -Action Click_JS -Element $Element + + Perform a javascript click on the specified element. + + + + + + + + Invoke-SeJavascript + Invoke + SeJavascript + + Invoke Javascript in the specified Driver. + + + + Invoke Javascript in the specified Driver. arguments will be passed to the javascript as "argument[0]" (where 0 is the argument position) + + + + Invoke-SeJavascript + + Script + + Javascript script to be executed. Arguments passed down can be used in the scripts through `arguments[0],arguments[1]`,etc... + + + String + + String + + + None + + + ArgumentList + + Argument list to be passed down to the script. + + Object[] + + Object[] + + + None + + + + + + ArgumentList + + Argument list to be passed down to the script. + + Object[] + + Object[] + + + None + + + Script + + Javascript script to be executed. Arguments passed down can be used in the scripts through `arguments[0],arguments[1]`,etc... + + + String + + String + + + None + + + + + + OpenQA.Selenium.IWebDriver + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Invoke-SeJavascript -Script 'arguments[0].click()' -ArgumentList $Element + + Perform a javascript click on the specified element. + + + + + + + + Invoke-SeKeys + Invoke + SeKeys + + Send the keys to the browser or specified element. + + + + The text to be typed may include special characters like arrow keys, backspaces, function keys, and so on. Valid special keys are defined in Keys. OpenQA_Selelnium_Keys (https://www.selenium.dev/selenium/docs/api/dotnet/html/T_OpenQA_Selenium_Keys.htm) + + + + Invoke-SeKeys + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + Keys + + Text to be typed. Special keys (Enter, arrow down, etc...) can be typed using double brackets (eg: `{{Enter}}`). See cmdlet description for complete list of keys + + String + + String + + + None + + + ClearFirst + + Clear the element existing text first + + + SwitchParameter + + + False + + + PassThru + + Return the IWebElement or webdriver + + + SwitchParameter + + + False + + + Sleep + + Sleep time in second after performing the type action. + + Double + + Double + + + None + + + Submit + + Call submit on the specified element. + + + SwitchParameter + + + False + + + + + + ClearFirst + + Clear the element existing text first + + SwitchParameter + + SwitchParameter + + + False + + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + Keys + + Text to be typed. Special keys (Enter, arrow down, etc...) can be typed using double brackets (eg: `{{Enter}}`). See cmdlet description for complete list of keys + + String + + String + + + None + + + PassThru + + Return the IWebElement or webdriver + + SwitchParameter + + SwitchParameter + + + False + + + Sleep + + Sleep time in second after performing the type action. + + Double + + Double + + + None + + + Submit + + Call submit on the specified element. + + SwitchParameter + + SwitchParameter + + + False + + + + + + OpenQA.Selenium.IWebElement + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> $Search = Get-SeElement -By TagName -Value input -Single +PS C:\> Invoke-SeKeys -Element $Search -Keys 'Powershell-Selenium{{Enter}}' + + Type the defined text and a special key - Enter - defined in the special keys. + + + + + + + + Invoke-SeMouseAction + Invoke + SeMouseAction + + Perform mouse move & drag actions. + + + + Perform mouse move & drag actions. + + + + Invoke-SeMouseAction + + Action + + Action to be performed. Intellisense tooltip provide details regarding expected value. + + Object + + Object + + + None + + + Value + + Value expected by the specified action. + + Object + + Object + + + None + + + Element + + {{ Fill Element Description }} + + IWebElement + + IWebElement + + + None + + + + + + Action + + Action to be performed. Intellisense tooltip provide details regarding expected value. + + Object + + Object + + + None + + + Element + + {{ Fill Element Description }} + + IWebElement + + IWebElement + + + None + + + Value + + Value expected by the specified action. + + Object + + Object + + + None + + + + + + None + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Invoke-SeMouseAction -Element $SourceElement -Action DragAndDrop -Value $DestinationElement + + Perform a drag&drop operation from the source element to destination element. + + + + + + + + New-SeDriverOptions + New + SeDriverOptions + + Create a driver options object that can be used with `Start-SeDriver` + + + + Create a driver options object that can be used with `Start-SeDriver` + This allow for more flexibility than the Start-SeDriver cmdlet as you can perform additional things with the driver options before starting the driver. + + + + New-SeDriverOptions + + StartURL + + Start URL to be set immediately after launch. If no protocol is specified, https will be assumed. + + String + + String + + + None + + + AcceptInsecureCertificates + + If set, Ignore SSL certificate error (Chrome,Edge,Firefox) + + + SwitchParameter + + + False + + + Arguments + + Command line arguments to be passed to the browser. + + String[] + + String[] + + + None + + + BinaryPath + + {{ Fill BinaryPath Description }} + + Object + + Object + + + None + + + Browser + + Browser name to be started. + + Object + + Object + + + None + + + DefaultDownloadPath + + {{ Fill DefaultDownloadPath Description }} + + FileInfo + + FileInfo + + + None + + + ImplicitWait + + Maximum time that the browser will implicitely wait between operations + + Double + + Double + + + None + + + LogLevel + + {{ Fill LogLevel Description }} + + + All + Debug + Info + Warning + Severe + Off + + LogLevel + + LogLevel + + + None + + + Position + + Position of the browser to be set on or after launch. Some browser might not support position to be set prior launch and will have their position set after launch. + + Point + + Point + + + None + + + PrivateBrowsing + + Launch the browser in a private session + + + SwitchParameter + + + False + + + ProfilePath + + {{ Fill ProfilePath Description }} + + Object + + Object + + + None + + + Size + + Size of the browser to be set on or after launch. Some browser might not support size to be set prior launch and will have their size set after launch. + + Size + + Size + + + None + + + State + + Window state of the browser. + + Object + + Object + + + None + + + Switches + + Special switches (additional legacy options that might appear for some browser ) + + String[] + + String[] + + + None + + + UserAgent + + UserAgent to be set. Supported by Chrome & Firefox + + String + + String + + + None + + + WebDriverPath + + Location of the web driver to be used. + + Object + + Object + + + None + + + + + + AcceptInsecureCertificates + + If set, Ignore SSL certificate error (Chrome,Edge,Firefox) + + SwitchParameter + + SwitchParameter + + + False + + + Arguments + + Command line arguments to be passed to the browser. + + String[] + + String[] + + + None + + + BinaryPath + + {{ Fill BinaryPath Description }} + + Object + + Object + + + None + + + Browser + + Browser name to be started. + + Object + + Object + + + None + + + DefaultDownloadPath + + {{ Fill DefaultDownloadPath Description }} + + FileInfo + + FileInfo + + + None + + + ImplicitWait + + Maximum time that the browser will implicitely wait between operations + + Double + + Double + + + None + + + LogLevel + + {{ Fill LogLevel Description }} + + LogLevel + + LogLevel + + + None + + + Position + + Position of the browser to be set on or after launch. Some browser might not support position to be set prior launch and will have their position set after launch. + + Point + + Point + + + None + + + PrivateBrowsing + + Launch the browser in a private session + + SwitchParameter + + SwitchParameter + + + False + + + ProfilePath + + {{ Fill ProfilePath Description }} + + Object + + Object + + + None + + + Size + + Size of the browser to be set on or after launch. Some browser might not support size to be set prior launch and will have their size set after launch. + + Size + + Size + + + None + + + StartURL + + Start URL to be set immediately after launch. If no protocol is specified, https will be assumed. + + String + + String + + + None + + + State + + Window state of the browser. + + Object + + Object + + + None + + + Switches + + Special switches (additional legacy options that might appear for some browser ) + + String[] + + String[] + + + None + + + UserAgent + + UserAgent to be set. Supported by Chrome & Firefox + + String + + String + + + None + + + WebDriverPath + + Location of the web driver to be used. + + Object + + Object + + + None + + + + + + None + + + + + + + + + + OpenQA.Selenium.Chrome.ChromeOptions + + + + + + + + OpenQA.Selenium.Edge.EdgeOptions + + + + + + + + OpenQA.Selenium.Firefox.FirefoxOptions + + + + + + + + OpenQA.Selenium.IE.InternetExplorerOptions + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> $Options = New-SeDriverOptions -Browser Chrome -Position 1920x0 -Size 1920x1080 +PS C:\> $Options.AddAdditionalCapability('useAutomationExtension', $false) +PS C:\> Start-SeDriver -Options $Options + + Create a Chrome driver option object to perform additional things unsupported directly by Start-SeDriver, such as adding an additional capability, then Start a driver instance with the modified Chrome driver options object. + + + + + + + + New-SeDriverService + New + SeDriverService + + Create an instance of WebDriver service to be used with Start-SeDriver + + + + Create an instance of WebDriver service to be used with Start-SeDriver + + + + New-SeDriverService + + Browser + + Browser name + + Object + + Object + + + None + + + WebDriverPath + + Location of the web driver to be used. + + Object + + Object + + + None + + + + + + Browser + + Browser name + + Object + + Object + + + None + + + WebDriverPath + + Location of the web driver to be used. + + Object + + Object + + + None + + + + + + None + + + + + + + + + + OpenQA.Selenium.Chrome.ChromeDriverService + + + + + + + + OpenQA.Selenium.Firefox.FirefoxDriverService + + + + + + + + OpenQA.Selenium.IE.InternetExplorerDriverService + + + + + + + + OpenQA.Selenium.Edge.EdgeDriverService + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> $Service = New-SeDriverService -Browser Chrome +PS C:\> $Service.PortServerAddress = 100 +PS C:\> $Options = New-SeDriverOptions -Browser Chrome -Position 1920x0 -Size 1920x1080 +PS C:\> Start-SeDriver -Service $Service -Options $Options +PS C:\> $Service.ProcessId + + Create a new instance of Chrome driver service, set a custom port and start the driver with the modified service instance. + + + + + + + + New-SeScreenshot + New + SeScreenshot + + Take a screenshot of the current page + + + + Take a screenshot of the current page + + + + New-SeScreenshot + + AsBase64EncodedString + + Return image as base64 string + + + SwitchParameter + + + False + + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + + New-SeScreenshot + + AsBase64EncodedString + + Return image as base64 string + + + SwitchParameter + + + False + + + InputObject + + Target IWebElement. + + Object + + Object + + + None + + + + + + AsBase64EncodedString + + Return image as base64 string + + SwitchParameter + + SwitchParameter + + + False + + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + InputObject + + Target IWebElement. + + Object + + Object + + + None + + + + + + System.Object + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> $Element | New-SeScreenshot + + Take a screenshot of the specified element. + + + + + + + + New-SeWindow + New + SeWindow + + {{ Fill in the Synopsis }} + + + + {{ Fill in the Description }} + + + + New-SeWindow + + Url + + {{ Fill Url Description }} + + Object + + Object + + + None + + + + + + Url + + {{ Fill Url Description }} + + Object + + Object + + + None + + + + + + OpenQA.Selenium.IWebDriver + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> {{ Add example code here }} + + {{ Add example description here }} + + + + + + + + Pop-SeUrl + Pop + SeUrl + + Navigate back to the most recently pushed URL in the location stack. + + + + Retrieves the most recently pushed URL from the location stack and navigates to that URL with the specified or default driver. + + + + Pop-SeUrl + + + + + + + + A separate internal location stack is maintained for each driver instance by the module. This stack is completely separate from the driver's internal Back/Forward history logic. + To utilise a driver's Back/Forward functionality, instead use Set-SeUrl. + + + + + -------------------------- EXAMPLE 1 -------------------------- + Pop-SeUrl + + Retrieves the most recently pushed URL and navigates back to that URL. + + + + + + + + Push-SeUrl + Push + SeUrl + + Stores the current URL in the driver's location stack and optionally navigate to a new URL. + + + + The current driver URL is added to the stack, and if a URL is provided, the driver navigates to the new URL. + + + + Push-SeUrl + + Url + + The new URL to navigate to after storing the current location. + + String + + String + + + None + + + + + + Url + + The new URL to navigate to after storing the current location. + + String + + String + + + None + + + + + + + A separate internal location stack is maintained for each driver instance by the module. This stack is completely separate from the driver's internal Back/Forward history logic. + To utilise a driver's Back/Forward functionality, instead use Set-SeUrl. + + + + + -------------------------- EXAMPLE 1 -------------------------- + Push-SeUrl + + The current driver URL is added to the location stack. + + + + -------------------------- EXAMPLE 2 -------------------------- + Push-SeUrl 'https://google.com/' + + The current driver URL is added to the location stack, and the driver then navigates to the provided target URL. + + + + + + + + Remove-SeCookie + Remove + SeCookie + + Delete the named cookie from the current domain + + + + Delete the named cookie from the current domain + + + + Remove-SeCookie + + All + + Clear all cookies. + + + SwitchParameter + + + False + + + + Remove-SeCookie + + Name + + Cookie name to remove + + String + + String + + + None + + + + + + All + + Clear all cookies. + + SwitchParameter + + SwitchParameter + + + False + + + Name + + Cookie name to remove + + String + + String + + + None + + + + + + OpenQA.Selenium.IWebDriver + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Remove-SeCookie -Name 'CookieName' + + Remove cookie from targeted Driver + + + + -------------------------- Example 2 -------------------------- + PS C:\> Remove-SeCookie -DeleteAllCookies + + Remove all cookies from targeted Driver + + + + + + + + Remove-SeWindow + Remove + SeWindow + + {{ Fill in the Synopsis }} + + + + {{ Fill in the Description }} + + + + Remove-SeWindow + + SwitchToWindow + + {{ Fill SwitchToWindow Description }} + + String + + String + + + None + + + + + + SwitchToWindow + + {{ Fill SwitchToWindow Description }} + + String + + String + + + None + + + + + + OpenQA.Selenium.IWebDriver + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> {{ Add example code here }} + + {{ Add example description here }} + + + + + + + + Save-SeScreenshot + Save + SeScreenshot + + Save a screenshot on the disk. + + + + Save the screenshot at the specified location. + + + + Save-SeScreenshot + + Element + + {{ Fill Element Description }} + + IWebElement + + IWebElement + + + None + + + ImageFormat + + Image format for the file to be saved. + + + Png + Jpeg + Gif + Tiff + Bmp + + ScreenshotImageFormat + + ScreenshotImageFormat + + + None + + + Path + + Filepath where the image will be saved. + + String + + String + + + None + + + + Save-SeScreenshot + + ImageFormat + + Image format for the file to be saved. + + + Png + Jpeg + Gif + Tiff + Bmp + + ScreenshotImageFormat + + ScreenshotImageFormat + + + None + + + InputObject + + {{ Fill InputObject Description }} + + Object + + Object + + + None + + + Path + + Filepath where the image will be saved. + + String + + String + + + None + + + + Save-SeScreenshot + + ImageFormat + + Image format for the file to be saved. + + + Png + Jpeg + Gif + Tiff + Bmp + + ScreenshotImageFormat + + ScreenshotImageFormat + + + None + + + Path + + Filepath where the image will be saved. + + String + + String + + + None + + + Screenshot + + Screenshot object. + + Screenshot + + Screenshot + + + None + + + + + + Element + + {{ Fill Element Description }} + + IWebElement + + IWebElement + + + None + + + ImageFormat + + Image format for the file to be saved. + + ScreenshotImageFormat + + ScreenshotImageFormat + + + None + + + InputObject + + {{ Fill InputObject Description }} + + Object + + Object + + + None + + + Path + + Filepath where the image will be saved. + + String + + String + + + None + + + Screenshot + + Screenshot object. + + Screenshot + + Screenshot + + + None + + + + + + System.Object + + + + + + + + OpenQA.Selenium.Screenshot + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> $Screenshot = New-SeScreenshot +PS C:\> Save-SeScreenshot -Screenshot $Screenshot -Path 'c:\temp\image.png' -ImageFormat Png + + Create then save a screenshot to disk. + + + + + + + + Set-SeCookie + Set + SeCookie + + Add a cookie to the current browsing context + + + + Add a cookie to the current browsing context + + + + Set-SeCookie + + Name + + The name of the cookie + + String + + String + + + None + + + Value + + The value of the cookie + + String + + String + + + None + + + Path + + The path of the cookie + + String + + String + + + None + + + Domain + + The domain of the cookie + + String + + String + + + None + + + ExpiryDate + + The expiration date of the cookie + + DateTime + + DateTime + + + None + + + + + + Domain + + The domain of the cookie + + String + + String + + + None + + + ExpiryDate + + The expiration date of the cookie + + DateTime + + DateTime + + + None + + + Name + + The name of the cookie + + String + + String + + + None + + + Path + + The path of the cookie + + String + + String + + + None + + + Value + + The value of the cookie + + String + + String + + + None + + + + + + System.Object + + + + + + + + + + System.Object + + + + + + + + + + + + + + + + + Set-SeDriverTimeout + Set + SeDriverTimeout + + Set the various driver timeouts default. + + + + Set the various driver timeouts default. + + + + Set-SeDriverTimeout + + TimeoutType + + Type of timeout to change. + + + ImplicitWait + PageLoad + AsynchronousJavaScript + + Object + + Object + + + None + + + Timeout + + Value in seconds + + Double + + Double + + + None + + + + + + Timeout + + Value in seconds + + Double + + Double + + + None + + + TimeoutType + + Type of timeout to change. + + Object + + Object + + + None + + + + + + OpenQA.Selenium.IWebDriver + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Set-SeDriverTimeout -TimeoutType ImplicitWait -Timeout 0 + + Set Implicit wait timeout to 0 + + + + + + + + Set-SeSelectValue + Set + SeSelectValue + + Set Select element selected value. + + + + Set Select element selected value. + + + + Set-SeSelectValue + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + By + + Selector to be used to set the value. + + + Index + Text + Value + + SeBySelect + + SeBySelect + + + None + + + value + + Value to which the specified element will be set. + + Object + + Object + + + None + + + + + + By + + Selector to be used to set the value. + + SeBySelect + + SeBySelect + + + None + + + Element + + Target IWebElement. + + IWebElement + + IWebElement + + + None + + + value + + Value to which the specified element will be set. + + Object + + Object + + + None + + + + + + OpenQA.Selenium.IWebElement + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Set-SeSelectValue -By Text -value 'Hello' -Element $Element + + Set targeted Select element selected value to 'Hello' (by text) + + + + + + + + Set-SeUrl + Set + SeUrl + + Navigates to the targeted URL with the selected or default driver. + + + + Used for webdriver navigation commands, either to specific target URLs or for history (Back/Forward) navigation or refreshing the current page. + + + + Set-SeUrl + + Url + + The target URL for the webdriver to navigate to. + + String + + String + + + None + + + + Set-SeUrl + + Back + + Trigger the Back history navigation action in the webdriver. + + + SwitchParameter + + + False + + + Depth + + Number of time the action should be performed. + + Int32 + + Int32 + + + 1 + + + + Set-SeUrl + + Forward + + Trigger the Forward history navigation action in the webdriver. + + + SwitchParameter + + + False + + + Depth + + Number of time the action should be performed. + + Int32 + + Int32 + + + 1 + + + + Set-SeUrl + + Refresh + + Refresh the current page in the webdriver. + + + SwitchParameter + + + False + + + + + + Url + + The target URL for the webdriver to navigate to. + + String + + String + + + None + + + Back + + Trigger the Back history navigation action in the webdriver. + + SwitchParameter + + SwitchParameter + + + False + + + Forward + + Trigger the Forward history navigation action in the webdriver. + + SwitchParameter + + SwitchParameter + + + False + + + Refresh + + Refresh the current page in the webdriver. + + SwitchParameter + + SwitchParameter + + + False + + + Depth + + Number of time the action should be performed. + + Int32 + + Int32 + + + 1 + + + + + + + The Back/Forward/Refresh logic is handled by the webdriver itself. If you need a more granular approach to handling which locations are saved or retrieved, use Push-SeUrl or Pop-SeUrl to utilise a separately managed location stack. + + + + + -------------------------- EXAMPLE 1 -------------------------- + Set-SeUrl 'https://www.google.com/' + + Directs the default driver to navigate to www.google.com. + + + + -------------------------- EXAMPLE 2 -------------------------- + Set-SeUrl -Refresh + + Reloads the current page for the default driver. + + + + -------------------------- EXAMPLE 3 -------------------------- + Set-SeUrl -Target $Driver -Back + + Directs the targeted webdriver instance to navigate Back in its history. + + + + -------------------------- EXAMPLE 4 -------------------------- + Set-SeUrl -Forward + + Directs the default webdriver to navigate Forward in its history. + + + + + + + + Start-SeDriver + Start + SeDriver + + Launch the specified browser. + + + + Launch a driver instance of the specified browser. + + + + Start-SeDriver + + StartURL + + Start URL to be set immediately after launch. If no protocol is specified, https will be assumed. + + String + + String + + + None + + + AcceptInsecureCertificates + + If set, Ignore SSL certificate error (Chrome,Edge,Firefox) + + + SwitchParameter + + + False + + + Arguments + + Command line arguments to be passed to the browser. + + String[] + + String[] + + + None + + + BinaryPath + + {{ Fill BinaryPath Description }} + + Object + + Object + + + None + + + Browser + + Browser to be started. + + Object + + Object + + + None + + + DefaultDownloadPath + + {{ Fill DefaultDownloadPath Description }} + + FileInfo + + FileInfo + + + None + + + ImplicitWait + + Maximum time that the browser will implicitely wait between operations + + Double + + Double + + + None + + + LogLevel + + {{ Fill LogLevel Description }} + + + All + Debug + Info + Warning + Severe + Off + + LogLevel + + LogLevel + + + None + + + Name + + Friendly name of the browser. + + Object + + Object + + + None + + + Options + + Driver Options object + + DriverOptions + + DriverOptions + + + None + + + Position + + Position of the browser to be set on or after launch. Some browser might not support position to be set prior launch and will have their position set after launch. + + Point + + Point + + + None + + + PrivateBrowsing + + Launch the browser in a private session + + + SwitchParameter + + + False + + + ProfilePath + + {{ Fill ProfilePath Description }} + + Object + + Object + + + None + + + Service + + DriverService object to be used. + + DriverService + + DriverService + + + None + + + Size + + Size of the browser to be set on or after launch. Some browser might not support size to be set prior launch and will have their size set after launch. + + Size + + Size + + + None + + + State + + Window state of the browser. + + + Headless + Default + Minimized + Maximized + Fullscreen + + SeWindowState + + SeWindowState + + + Default + + + UserAgent + + UserAgent to be set. Supported by Chrome & Firefox + + String + + String + + + None + + + WebDriverPath + + Location of the web driver to be used. + + Object + + Object + + + None + + + + Start-SeDriver + + StartURL + + Start URL to be set immediately after launch. If no protocol is specified, https will be assumed. + + String + + String + + + None + + + AcceptInsecureCertificates + + If set, Ignore SSL certificate error (Chrome,Edge,Firefox) + + + SwitchParameter + + + False + + + Arguments + + Command line arguments to be passed to the browser. + + String[] + + String[] + + + None + + + BinaryPath + + {{ Fill BinaryPath Description }} + + Object + + Object + + + None + + + Browser + + Browser to be started. + + Object + + Object + + + None + + + DefaultDownloadPath + + {{ Fill DefaultDownloadPath Description }} + + FileInfo + + FileInfo + + + None + + + ImplicitWait + + Maximum time that the browser will implicitely wait between operations + + Double + + Double + + + None + + + LogLevel + + {{ Fill LogLevel Description }} + + + All + Debug + Info + Warning + Severe + Off + + LogLevel + + LogLevel + + + None + + + Name + + Friendly name of the browser. + + Object + + Object + + + None + + + Position + + Position of the browser to be set on or after launch. Some browser might not support position to be set prior launch and will have their position set after launch. + + Point + + Point + + + None + + + PrivateBrowsing + + Launch the browser in a private session + + + SwitchParameter + + + False + + + ProfilePath + + {{ Fill ProfilePath Description }} + + Object + + Object + + + None + + + Size + + Size of the browser to be set on or after launch. Some browser might not support size to be set prior launch and will have their size set after launch. + + Size + + Size + + + None + + + State + + Window state of the browser. + + + Headless + Default + Minimized + Maximized + Fullscreen + + SeWindowState + + SeWindowState + + + Default + + + Switches + + Special switches (additional legacy options that might appear for some browser ) + + String[] + + String[] + + + None + + + UserAgent + + UserAgent to be set. Supported by Chrome & Firefox + + String + + String + + + None + + + WebDriverPath + + Location of the web driver to be used. + + Object + + Object + + + None + + + + + + AcceptInsecureCertificates + + If set, Ignore SSL certificate error (Chrome,Edge,Firefox) + + SwitchParameter + + SwitchParameter + + + False + + + Arguments + + Command line arguments to be passed to the browser. + + String[] + + String[] + + + None + + + BinaryPath + + {{ Fill BinaryPath Description }} + + Object + + Object + + + None + + + Browser + + Browser to be started. + + Object + + Object + + + None + + + DefaultDownloadPath + + {{ Fill DefaultDownloadPath Description }} + + FileInfo + + FileInfo + + + None + + + ImplicitWait + + Maximum time that the browser will implicitely wait between operations + + Double + + Double + + + None + + + LogLevel + + {{ Fill LogLevel Description }} + + LogLevel + + LogLevel + + + None + + + Name + + Friendly name of the browser. + + Object + + Object + + + None + + + Options + + Driver Options object + + DriverOptions + + DriverOptions + + + None + + + Position + + Position of the browser to be set on or after launch. Some browser might not support position to be set prior launch and will have their position set after launch. + + Point + + Point + + + None + + + PrivateBrowsing + + Launch the browser in a private session + + SwitchParameter + + SwitchParameter + + + False + + + ProfilePath + + {{ Fill ProfilePath Description }} + + Object + + Object + + + None + + + Service + + DriverService object to be used. + + DriverService + + DriverService + + + None + + + Size + + Size of the browser to be set on or after launch. Some browser might not support size to be set prior launch and will have their size set after launch. + + Size + + Size + + + None + + + StartURL + + Start URL to be set immediately after launch. If no protocol is specified, https will be assumed. + + String + + String + + + None + + + State + + Window state of the browser. + + SeWindowState + + SeWindowState + + + Default + + + Switches + + Special switches (additional legacy options that might appear for some browser ) + + String[] + + String[] + + + None + + + UserAgent + + UserAgent to be set. Supported by Chrome & Firefox + + String + + String + + + None + + + WebDriverPath + + Location of the web driver to be used. + + Object + + Object + + + None + + + + + + None + + + + + + + + + + OpenQA.Selenium.IWebDriver + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Start-SeDriver -Browser Chrome -Position 1920x0 -StartURL 'google.com' + + Start a Chrome browser at the specified position and starting URL + + + + + + + + Start-SeRemote + Start + SeRemote + + Start a remote driver session. + + + + Start a remote driver session. you can a remote testing account with testing bot at https://testingbot.com/users/sign_up + + + + Start-SeRemote + + StartURL + + {{ Fill StartURL Description }} + + String + + String + + + None + + + DesiredCapabilities + + {{ Fill DesiredCapabilities Description }} + + Hashtable + + Hashtable + + + None + + + ImplicitWait + + {{ Fill ImplicitWait Description }} + + Double + + Double + + + None + + + Position + + {{ Fill Position Description }} + + Point + + Point + + + None + + + RemoteAddress + + {{ Fill RemoteAddress Description }} + + String + + String + + + None + + + Size + + {{ Fill Size Description }} + + Size + + Size + + + None + + + + + + DesiredCapabilities + + {{ Fill DesiredCapabilities Description }} + + Hashtable + + Hashtable + + + None + + + ImplicitWait + + {{ Fill ImplicitWait Description }} + + Double + + Double + + + None + + + Position + + {{ Fill Position Description }} + + Point + + Point + + + None + + + RemoteAddress + + {{ Fill RemoteAddress Description }} + + String + + String + + + None + + + Size + + {{ Fill Size Description }} + + Size + + Size + + + None + + + StartURL + + {{ Fill StartURL Description }} + + String + + String + + + None + + + + + + None + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + #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 + + + + + + + + + + Stop-SeDriver + Stop + SeDriver + + Quits this driver, closing every associated window. + + + + Quits this driver, closing every associated window. + + + + Stop-SeDriver + + Driver + + Target WebDriver + + IWebDriver + + IWebDriver + + + None + + + + + + Driver + + Target WebDriver + + IWebDriver + + IWebDriver + + + None + + + + + + OpenQA.Selenium.IWebDriver + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Stop-SeDriver -Target $Driver + + Stop the specified driver + + + + -------------------------- Example 1 -------------------------- + PS C:\> Start-SeChrome -AsDefaultDriver +PS C:\> Stop-SeDriver + + Stop the default driver, which was defined using the `-AsDefaultDriver` switch. + + + + + + + + Switch-SeDriver + Switch + SeDriver + + Select a driver, making it the default to be used with any ulterior calls whenever the driver parameter is not specified. + + + + Select a driver, making it the default to be used with any ulterior calls whenever the driver parameter is not specified. + + + + Switch-SeDriver + + Driver + + Target WebDriver + + IWebDriver + + IWebDriver + + + None + + + + Switch-SeDriver + + Name + + SeFriendlyName of the browser to select. + + String + + String + + + None + + + + + + Driver + + Target WebDriver + + IWebDriver + + IWebDriver + + + None + + + Name + + SeFriendlyName of the browser to select. + + String + + String + + + None + + + + + + None + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> $Driver = Start-SeDriver -Browser Chrome +# Chrome is the only and default driver +PS C:\> Get-SeDriver -Current +PS C:\> Start-SeDriver -Browser Firefox +# Firefox is now the default browser +PS C:\> Get-SeDriver -Current +PS C:\> Switch-SeDriver -Driver $Driver +# Chrome is the default browser again +PS C:\> Get-SeDriver -Current + + This examples show the default browser changing from Chrome to Firefox when the second instance is launched, then set back to Chrome through Switch-SeDriver + + + + + + + + Switch-SeFrame + Switch + SeFrame + + Instructs the driver to send future commands to a different frame + + + + Instructs the driver to send future commands to a different frame + + + + Switch-SeFrame + + Frame + + {{ Fill Frame Description }} + + Object + + Object + + + None + + + + Switch-SeFrame + + Parent + + {{ Fill Parent Description }} + + + SwitchParameter + + + False + + + + Switch-SeFrame + + Root + + {{ Fill Root Description }} + + + SwitchParameter + + + False + + + + + + Frame + + {{ Fill Frame Description }} + + Object + + Object + + + None + + + Parent + + {{ Fill Parent Description }} + + SwitchParameter + + SwitchParameter + + + False + + + Root + + {{ Fill Root Description }} + + SwitchParameter + + SwitchParameter + + + False + + + + + + System.Object + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + + + + + + + + + + + Switch-SeWindow + Switch + SeWindow + + Instructs the driver to send future commands to a different window + + + + Instructs the driver to send future commands to a different window + + + + Switch-SeWindow + + Window + + {{ Fill Window Description }} + + Object + + Object + + + None + + + + + + Window + + {{ Fill Window Description }} + + Object + + Object + + + None + + + + + + OpenQA.Selenium.IWebDriver + + + + + + + + + + System.Object + + + + + + + + + + + + + + + + + Update-SeDriver + Update + SeDriver + + {{ Fill in the Synopsis }} + + + + {{ Fill in the Description }} + + + + Update-SeDriver + + Browser + + {{ Fill Browser Description }} + + Object + + Object + + + None + + + OS + + {{ Fill OS Description }} + + + Linux + Mac + Windows + + Object + + Object + + + None + + + Path + + {{ Fill Path Description }} + + Object + + Object + + + None + + + + + + Browser + + {{ Fill Browser Description }} + + Object + + Object + + + None + + + OS + + {{ Fill OS Description }} + + Object + + Object + + + None + + + Path + + {{ Fill Path Description }} + + Object + + Object + + + None + + + + + + None + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> {{ Add example code here }} + + {{ Add example description here }} + + + + + + + + Wait-SeDriver + Wait + SeDriver + + Wait for the driver to be in the desired state. + + + + Wait for the driver to be in the desired state. + + + + Wait-SeDriver + + Condition + + Condition that is expected to be met. + + Object + + Object + + + None + + + Value + + Condition value expected to be met. + + Object + + Object + + + None + + + Timeout + + Time delimiter in second for which the operation should succeed. + + Double + + Double + + + None + + + + + + Condition + + Condition that is expected to be met. + + Object + + Object + + + None + + + Timeout + + Time delimiter in second for which the operation should succeed. + + Double + + Double + + + None + + + Value + + Condition value expected to be met. + + Object + + Object + + + None + + + + + + System.Object + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Wait-SeDriver -Condition UrlContains 'next-' -Timeout 5.5 + + Wait 5.5 seconds for the driver URL to contains text "next-" + + + + + + + + Wait-SeElement + Wait + SeElement + + Wait for an element condition to be met. + + + + Wait for an element condition to be met. + + + + Wait-SeElement + + By + + Locator element. + + + ClassName + CssSelector + Id + LinkText + PartialLinkText + Name + TagName + XPath + + SeBySelector + + SeBySelector + + + None + + + Value + + Value of the locator corresponding to the element that should match the Condition / ConditionValue. + + String + + String + + + None + + + Condition + + Condition expected to be met. Some condition are only available with locator or element. + + Object + + Object + + + None + + + ConditionValue + + Value of the expected condition to be met. + + Object + + Object + + + None + + + Timeout + + Time delimiter in second for which the operation should succeed. + + Double + + Double + + + None + + + + Wait-SeElement + + Condition + + Condition expected to be met. Some condition are only available with locator or element. + + Object + + Object + + + None + + + ConditionValue + + Value of the expected condition to be met. + + Object + + Object + + + None + + + Element + + Element that need to meet the condition. + + IWebElement + + IWebElement + + + None + + + Timeout + + Time delimiter in second for which the operation should succeed. + + Double + + Double + + + None + + + + + + By + + Locator element. + + SeBySelector + + SeBySelector + + + None + + + Condition + + Condition expected to be met. Some condition are only available with locator or element. + + Object + + Object + + + None + + + ConditionValue + + Value of the expected condition to be met. + + Object + + Object + + + None + + + Element + + Element that need to meet the condition. + + IWebElement + + IWebElement + + + None + + + Timeout + + Time delimiter in second for which the operation should succeed. + + Double + + Double + + + None + + + Value + + Value of the locator corresponding to the element that should match the Condition / ConditionValue. + + String + + String + + + None + + + + + + System.Object + + + + + + + + + + System.Object + + + + + + + + + + + + + + -------------------------- Example 1 -------------------------- + PS C:\> Wait-SeElement -Element $Element -Condition StalenessOf + + Wait for the specified element to not exist anymore in the DOM for 3 seconds (default timeout) + + + + + + \ No newline at end of file diff --git a/Output/Selenium/formats/Selenium.format.ps1xml b/Output/Selenium/formats/Selenium.format.ps1xml new file mode 100644 index 0000000..4521c8d --- /dev/null +++ b/Output/Selenium/formats/Selenium.format.ps1xml @@ -0,0 +1,215 @@ + + + + + + OpenQA.Selenium.Remote.RemoteWebElement + + OpenQA.Selenium.Remote.RemoteWebElement + + + + + left + 7 + + + left + 7 + + + left + 9 + + + Left + 80 + + + + + + + Tagname + + + Enabled + + + Displayed + + + Text + + + + + + + + OpenQA.Selenium.Remote.RemoteWebElement + + OpenQA.Selenium.Remote.RemoteWebElement + + + + + + + Tagname + + + Text + + + Enabled + + + Selected + + + Location + + + Size + + + Displayed + + + + + + + + selenium-powershell/SeFrame + + selenium-powershell/SeFrame + + + + + + + + + + + + + + + + + + + TagName + + + Enabled + + + $_.Attributes.name + + + $_.Attributes.id + + + + + + + + selenium-powershell/SeInput + + selenium-powershell/SeInput + + + + + + + + + + + + + + + + + + + + + + + + + + Tagname + + + $_.Attributes.type + + + Enabled + + + Displayed + + + Text + + + $_.Attributes.placeholder + + + $_.Attributes.value + + + + + + + + SeSelectValueInfo + + selenium-powershell/SeSelectValueInfo + + + + + + + IsMultiSelect + + + + + + + ($_.Items.Count -ne 0) + + + + $output = [System.Text.StringBuilder]::new(); + $TextMax = ($_.Items.Text | Measure-Object -Maximum).Maximum.length + $ValueMax = ($_.Items.Value | Measure-Object -Maximum).Maximum.length + [void]($Output.AppendFormat("Index {0} {1} Selected`n", 'Text'.PadRight($TextMax, ' '), 'Value'.PadRight($ValueMax, ' '))) + [void]($Output.AppendFormat("----- {0} {1} --------`n", '----'.PadRight($TextMax, ' '), '-----'.PadRight($ValueMax, ' '))) + foreach ($I in $_.Items) { + $IsSelected = if ($I.Selected) {" *"} else {''} + [Void]($output.AppendFormat("{0} {1} {2} {3}`n", "$($I.Index)".PadLeft(5, ' '), "$($I.Text)".PadRight($TextMax, ' '), "$($I.Value)".PadRight($ValueMax, ' '), $IsSelected)) + }; + $output.ToString().Trim("`n"); + + + + + + + + + diff --git a/Output/Selenium/types/Selenium.types.ps1xml b/Output/Selenium/types/Selenium.types.ps1xml new file mode 100644 index 0000000..a70253c --- /dev/null +++ b/Output/Selenium/types/Selenium.types.ps1xml @@ -0,0 +1,54 @@ + + + + + OpenQA.Selenium.Remote.RemoteWebElement + + + PSStandardMembers + + + DefaultDisplayPropertySet + + Tagname + Enabled + Displayed + Text + + + + + + + + OpenQA.Selenium.Remote.RemoteWebDriver + + + PSStandardMembers + + + DefaultDisplayPropertySet + + SeFriendlyName + SeBrowser + SeTitle + SeUrl + + + + + + SeUrl + + if ($null -ne $this.SessionId) { $this.Url } + + + + SeTitle + + if ($null -ne $this.SessionId) { $this.Title } + + + + + diff --git a/Public/Clear-SeAlert.ps1 b/Public/Clear-SeAlert.ps1 new file mode 100644 index 0000000..986b4be --- /dev/null +++ b/Public/Clear-SeAlert.ps1 @@ -0,0 +1,36 @@ +function Clear-SeAlert { + [CmdletBinding()] + param ( + [ValidateSet('Accept', 'Dismiss')] + $Action = 'Dismiss', + [parameter(ParameterSetName = 'Alert', ValueFromPipeline = $true)] + $Alert, + [switch]$PassThru + ) + Begin { + $Driver = Init-SeDriver -ErrorAction Stop + $ImpTimeout = 0 + } + Process { + if ($Driver) { + try { + $ImpTimeout = Disable-SeDriverImplicitTimeout -Driver $Driver + $WebDriverWait = [OpenQA.Selenium.Support.UI.WebDriverWait]::new($Driver, (New-TimeSpan -Seconds 10)) + $Condition = [OpenQA.Selenium.Support.UI.ExpectedConditions]::AlertIsPresent() + $WebDriverWait.Until($Condition) + $Alert = $Driver.SwitchTo().alert() + } + catch { + Write-Warning 'No alert was displayed' + return + } + Finally { + Enable-SeDriverImplicitTimeout -Driver $Driver -Timeout $ImpTimeout + } + } + if ($Alert) { $alert.$action() } + if ($PassThru) { $Alert } + } + End {} +} + diff --git a/Public/Clear-SeSelectValue.ps1 b/Public/Clear-SeSelectValue.ps1 new file mode 100644 index 0000000..3b57096 --- /dev/null +++ b/Public/Clear-SeSelectValue.ps1 @@ -0,0 +1,10 @@ +function Clear-SeSelectValue { + [Cmdletbinding()] + param ( + [Parameter(Mandatory = $true)] + [OpenQA.Selenium.IWebElement]$Element + ) + [SeleniumSelection.Option]::DeselectAll($Element) + +} + diff --git a/Public/ConvertTo-SeSelenium.ps1 b/Public/ConvertTo-SeSelenium.ps1 new file mode 100644 index 0000000..346db40 --- /dev/null +++ b/Public/ConvertTo-SeSelenium.ps1 @@ -0,0 +1,107 @@ +function ConvertTo-Selenium { + [CmdletBinding()] + param ( + # Path to .side file. + [Parameter(Mandatory)] + [String]$Path + ) + + $ByMap = @{ + id = 'Id' + css = 'CssSelector' + xpath = 'XPath' + linkText = 'LinkText' + label = 'Text' + index = 'Index' + } + function Get-Replace { + <# + .SYNOPSIS + Helper function to convert ScriptBlocks to strings. + + Parameter set 1: + Replace -From [String] with -To [String]. + -QuotesTo adds quotes around -To. + -SplitTo take only the value part from "label=value" of -To. + + Parameter set 2: + -By "label=value" replaces input "-By $By" with "-By -value ''". + * $ByMap is used to map the labels. + #> + [CmdletBinding()] + param ( + [String]$From, + [String]$To, + [String]$By, + [Parameter(ValueFromPipeline)] + $InputObject, + [switch]$QuotesTo, + [switch]$SplitTo + ) + process { + $String = $InputObject.ToString().Trim() + if ($From) { + if ($QuotesTo) { + $To = '"' + $To + '"' + } + if ($SplitTo) { + $To = $To.Split('=', 2)[1] + } + $String = $String.Replace($From, $To) + } + if ($By) { + $String = $String.Replace('-By $By', ('-By {0} -value {1}' -f $ByMap[$By.Split('=', 2)[0]], ('"' + $By.Split('=', 2)[1] + '"'))) + } + $String + } + } + + $ActionMap = @{ + click = { Invoke-SeClick } + doubleClick = { Invoke-SeClick -Action DoubleClick } + sendKeys = { Invoke-SeKeys -Keys $Keys } + type = { Invoke-SeKeys -Keys $Keys } + select = { Set-SeSelectValue -By $By } + } + + $Recording = Get-Content -Path $Path | ConvertFrom-Json + $BaseUrl = [Uri]$Recording.url + $PsCode = $( + '# Project: ' + $Recording.name + foreach ($Test in $Recording.tests) { + '# Test: ' + $Test.name + foreach ($Command in $Test.commands) { + switch ($Command) { + { $_.comment } { '# Description: ' + $_.comment } + { $_.command -eq 'open' } { + $Url = if ([Uri]::IsWellFormedUriString($_.target, [System.UriKind]::Relative)) { + [Uri]::new($BaseUrl, $_.target) + } + else { + $_.target + } + { Set-SeUrl -Url $Url } | Get-Replace -From '$Url' -To $Url -QuotesTo + Break + } + { $_.command -eq 'close' } { { Stop-SeDriver } ; Break } + { $_.command -in $ActionMap.Keys } { + $Action = $ActionMap[$_.command] | Get-Replace -From '$Keys' -To ($_.value.Replace('${KEY_ENTER}', '{{Enter}}')) -QuotesTo -By $_.value + { Get-SeElement -By $By | _Action_ } | Get-Replace -From '_Action_' -To $Action -By $_.target + Break + } + { $_.command -eq 'selectFrame' } { + if ($_.target -eq 'relative=parent') { + { Switch-SeFrame -Parent } + } + else { + { Switch-SeFrame -Frame $Index } | Get-Replace -From '$Index' -To $_.target -SplitTo + } + Break + } + Default { '# Unsupported command. Command: "{0}", Target: "{1}", Value: "{2}", Comment: "{3}".' -f $_.command, $_.target, $_.value, $_.comment } + } + } + } + ) | Get-Replace + [ScriptBlock]::Create($PsCode -join [Environment]::NewLine) +} \ No newline at end of file diff --git a/Public/Get-SeCookie.ps1 b/Public/Get-SeCookie.ps1 new file mode 100644 index 0000000..3fd6497 --- /dev/null +++ b/Public/Get-SeCookie.ps1 @@ -0,0 +1,6 @@ +function Get-SeCookie { + [CmdletBinding()] + param() + $Driver = Init-SeDriver -ErrorAction Stop + $Driver.Manage().Cookies.AllCookies.GetEnumerator() +} \ No newline at end of file diff --git a/Public/Get-SeDriver.ps1 b/Public/Get-SeDriver.ps1 new file mode 100644 index 0000000..794db60 --- /dev/null +++ b/Public/Get-SeDriver.ps1 @@ -0,0 +1,50 @@ + +function Get-SeDriver { + [cmdletbinding(DefaultParameterSetName = 'All')] + param( + [parameter(ParameterSetName = 'Current', Mandatory = $false)] + [Switch]$Current, + [parameter(Position = 0, ParameterSetName = 'ByName', Mandatory = $false)] + [String]$Name, + [parameter(ParameterSetName = 'ByBrowser', Mandatory = $false)] + [ArgumentCompleter( { [Enum]::GetNames([SeBrowsers]) })] + [ValidateScript( { $_ -in [Enum]::GetNames([SeBrowsers]) })] + $Browser + + + + ) + + $Output = $null + switch ($PSCmdlet.ParameterSetName) { + 'All' { $Output = $Script:SeDrivers; break } + 'Current' { $Output = $Script:SeDriversCurrent; break } + 'ByName' { $Output = $Script:SeDrivers.Where( { $_.SeFriendlyName -eq $Name }, 'first' ); break } + 'ByBrowser' { $Output = $Script:SeDrivers.Where( { $_.SeBrowser -like "$Browser*" }); break } + } + + if ($null -eq $Output) { return } + + $DriversToClose = [System.Collections.Generic.List[PSObject]]::new() + Foreach ($drv in $Output) { + $Processes = (Get-Process -Id $Drv.SeProcessId, $Drv.SeServiceProcessId -ErrorAction SilentlyContinue ) + if ($Processes.count -eq 2) { Continue } + + if ($Processes.count -eq 0) { + Write-Warning -Message "The driver $($Drv.SeFriendlyName) $($Drv.SeBrowser) processes are not running anymore and have been removed automatically from the list of available drivers." + } + else { + $ProcessType = if ($Processes.id -eq $Drv.SeServiceProcessId) { "driver service" } else { "browser" } + Write-Warning -Message "The driver $($Drv.SeFriendlyName) $($Drv.SeBrowser) $ProcessType is not running anymore and will be removed from the active driver list." + } + $DriversToClose.Add($Drv) + } + + if ($DriversToClose.Count -gt 0) { + foreach ($drv in $DriversToClose) { + $Output = $Output.Where( { $_.SeServiceProcessId -ne $drv.SeServiceProcessId }) + Stop-SeDriver -Driver $drv + } + } + return $Output +} \ No newline at end of file diff --git a/Public/Get-SeDriverTimeout.ps1 b/Public/Get-SeDriverTimeout.ps1 new file mode 100644 index 0000000..1f51a0d --- /dev/null +++ b/Public/Get-SeDriverTimeout.ps1 @@ -0,0 +1,16 @@ +function Get-SeDriverTimeout { + [CmdletBinding()] + param( + [Parameter(Position = 0)] + [ValidateSet('ImplicitWait', 'PageLoad', 'AsynchronousJavaScript')] + $TimeoutType = 'ImplicitWait' + ) + begin { + $Driver = Init-SeDriver -ErrorAction Stop + } + Process { + return $Driver.Manage().Timeouts().$TimeoutType + } + End {} +} + diff --git a/Public/Get-SeElement.ps1 b/Public/Get-SeElement.ps1 new file mode 100644 index 0000000..24415ef --- /dev/null +++ b/Public/Get-SeElement.ps1 @@ -0,0 +1,136 @@ +#TODO Positional binding $Element = Get-SeElement Tagname 'Select' +function Get-SeElement { + [Cmdletbinding(DefaultParameterSetName = 'Default')] + param( + #Specifies whether the selction text is to select by name, ID, Xpath etc + [ArgumentCompleter( { [Enum]::GetNames([SeBySelector]) })] + [ValidateScript( { $_ -in [Enum]::GetNames([SeBySelector]) })] + [SeBySelector[]]$By = [SeBySelector]::XPath, + [Parameter(Position = 1, Mandatory = $true)] + [string[]]$Value, + #Specifies a time out + [Parameter(Position = 2, ParameterSetName = 'Default')] + [Double]$Timeout = 0, + [Parameter(Position = 3, ValueFromPipeline = $true, Mandatory = $true, ParameterSetName = 'ByElement')] + [OpenQA.Selenium.IWebElement] + $Element, + [Switch]$All, + [ValidateNotNullOrEmpty()] + [String[]]$Attributes, + [scriptblock]$Filter, + [Switch]$Single + ) + Begin { + $Driver = Init-SeDriver -ErrorAction Stop + $ShowAll = $PSBoundParameters.ContainsKey('All') -and $PSBoundParameters.Item('All') -eq $true + if ($By.Count -ne $Value.Count) { + Throw [System.InvalidOperationException]::new("An equal number of `$By element ($($By.Count)) and `$Value ($($Value.Count)) must be provided.") + } + Filter DisplayedFilter([Switch]$All) { + if ($All) { $_ } else { if ($_.Displayed) { $_ } } + } + $Output = $null + $ByCondition = $null + + + + if ($by.Count -gt 1) { + $ByChainedArgs = for ($i = 0; $i -lt $by.Count; $i++) { + $cby = $by[$i] + $CValue = $value[$i] + if ($cby -eq ([SeBySelector]::ClassName)) { + $spl = $CValue.Split(' ', [StringSplitOptions]::RemoveEmptyEntries) + if ($spl.count -gt 1) { + $Cby = [SeBySelector]::CssSelector + $CValue = ".$($spl -join '.')" + } + } + [OpenQA.Selenium.By]::$cby($CValue) + } + $ByCondition = [OpenQA.Selenium.Support.PageObjects.ByChained]::new($ByChainedArgs) + } + else { + if ($By[0] -eq ([SeBySelector]::ClassName)) { + $spl = $Value.Split(' ', [StringSplitOptions]::RemoveEmptyEntries) + if ($spl.Count -gt 1) { + $by = [SeBySelector]::CssSelector + $Value = ".$($spl -join '.')" + } + } + $ByCondition = [OpenQA.Selenium.By]::$By($Value) + } + + $ImpTimeout = -1 + if ($By.Count -gt 1 -or $PSBoundParameters.ContainsKey('Timeout')) { + $ImpTimeout = Disable-SeDriverImplicitTimeout -Driver $Driver + } + #Id Should always be considered as Single + if ($By.Contains('Id') -and !$PSBoundParameters.ContainsKey('Single')) { + $PSBoundParameters.Add('Single', $true) + } + } + process { + + + switch ($PSCmdlet.ParameterSetName) { + 'Default' { + if ($Timeout) { + $WebDriverWait = [OpenQA.Selenium.Support.UI.WebDriverWait]::new($Driver, ([timespan]::FromMilliseconds($Timeout * 1000))) + $Condition = [OpenQA.Selenium.Support.UI.ExpectedConditions]::PresenceOfAllElementsLocatedBy($ByCondition) + $Output = $WebDriverWait.Until($Condition) | DisplayedFilter -All:$ShowAll + } + else { + $Output = $Driver.FindElements($ByCondition) | DisplayedFilter -All:$ShowAll + } + } + 'ByElement' { + Write-Verbose "Searching an Element - Timeout ignored" + $Output = $Element.FindElements($ByCondition) | DisplayedFilter -All:$ShowAll + } + } + + + $GetAllAttributes = $PSBoundParameters.ContainsKey('Attributes') -and $Attributes.Count -eq 1 -and $Attributes[0] -eq '*' + $MyAttributes = [System.Collections.Generic.List[String]]::new() + if ( $null -ne $Attributes) { $MyAttributes = [System.Collections.Generic.List[String]]$Attributes } + + if (!$GetAllAttributes -and $Filter) { + $AdditionalAttributes = [regex]::Matches($Filter, '\$_\.Attributes.(\w+)', [System.Text.RegularExpressions.RegexOptions]::IgnoreCase) | % { $_.Groups[1].value } + $AdditionalAttributes | ForEach-Object {if (!$MyAttributes.Contains($_)) { $MyAttributes.Add($_) }} + } + + if ($MyAttributes.Count -gt 0) { + Foreach ($Item in $Output) { + $htAttributes = Get-SeElementAttribute -Element $Item -Name $MyAttributes + if ($htAttributes -is [String]) {$htAttributes = @{$MyAttributes[0] = $htAttributes }} + Add-Member -InputObject $Item -Name 'Attributes' -Value $htAttributes -MemberType NoteProperty + } + } + + # Apply filter here + $AndFilterstr = "" + if ($Filter) { + $AndFilterstr = " and the applied filter" + $Output = $Output | Where-Object $Filter + } + + + if ($null -eq $Output) { + $Message = "no such element: Unable to locate element by: $($By -join ',') with value $($Value -join ',')$AndFilterstr" + Write-Error -Exception ([System.Management.Automation.ItemNotFoundException]::new($Message)) + return + } + elseif ($PSBoundParameters.ContainsKey('Single') -and $Single -eq $true -and $Output.count -gt 1) { + $Message = "A single element was expected but $($Output.count) elements were found using the locator $($By -join ',') with value $($Value -join ',')$AndFilterstr." + Write-Error -Exception ([System.InvalidOperationException]::new($Message)) + return + } + else { + return $Output + } + } + End { + if ($ImpTimeout -ne -1) { Enable-SeDriverImplicitTimeout -Driver $Driver -Timeout $ImpTimeout } + + } +} \ No newline at end of file diff --git a/Public/Get-SeElementAttribute.ps1 b/Public/Get-SeElementAttribute.ps1 new file mode 100644 index 0000000..800b92e --- /dev/null +++ b/Public/Get-SeElementAttribute.ps1 @@ -0,0 +1,44 @@ +function Get-SeElementAttribute { + [CmdletBinding()] + param( + [Parameter(ValueFromPipeline = $true, Mandatory = $true)] + [OpenQA.Selenium.IWebElement]$Element, + [Parameter(Mandatory = $true)] + [string[]]$Name + ) + Begin { + $Script = 'var items = {}; for (index = 0; index < arguments[0].attributes.length; ++index) { items[arguments[0].attributes[index].name] = arguments[0].attributes[index].value }; return items;' + } + process { + $AllAttributes = $Name.Count -eq 1 -and $Name[0] -eq '*' + $ManyAttributes = $Name.Count -gt 1 + + if ($AllAttributes) { + $AllAttributes = $Element.WrappedDriver.ExecuteScript($Script, $Element) + $Output = @{} + + Foreach ($Att in $AllAttributes.Keys) { + $value = $Element.GetAttribute($Att) + if ($value -ne "") { + $Output.$Att = $value + } + } + $Output + } + elseif ($ManyAttributes) { + $Output = @{} + Foreach ($Att in $Name) { + $value = $Element.GetAttribute($Att) + if ($value -ne "") { + $Output.$Att = $value + } + } + $Output + } + else { + $Element.GetAttribute($Name) + } + + + } +} \ No newline at end of file diff --git a/Public/Get-SeElementCssValue.ps1 b/Public/Get-SeElementCssValue.ps1 new file mode 100644 index 0000000..3c47e96 --- /dev/null +++ b/Public/Get-SeElementCssValue.ps1 @@ -0,0 +1,53 @@ +function Get-SeElementCssValue { + [CmdletBinding()] + param( + [Parameter(ValueFromPipeline = $true, Mandatory = $true)] + [OpenQA.Selenium.IWebElement]$Element, + [Parameter(Mandatory = $true)] + [string[]]$Name + ) + Begin { + $ScriptAllValues = @' + var items = {}; +var o = getComputedStyle(arguments[0]); +for(var i = 0; i < o.length; i++){ + items[o[i]] = o.getPropertyValue(o[i]) +} +return items; +'@ + } + Process { + $AllValues = $Name.Count -eq 1 -and $Name[0] -eq '*' + $ManyValues = $Name.Count -gt 1 + + + if ($AllValues) { + + $AllCSSNames = $Element.WrappedDriver.ExecuteScript($ScriptAllValues, $Element) + $Output = @{} + + Foreach ($Att in $AllCSSNames.Keys) { + $value = $Element.GetCssValue($Att) + if ($value -ne "") { + $Output.$Att = $value + } + } + [PSCustomObject]$Output + } + elseif ($ManyValues) { + $Output = @{} + Foreach ($Item in $Name) { + $Value = $Element.GetCssValue($Item) + if ($Value -ne "") { + $Output.$Item = $Value + } + } + [PSCustomObject]$Output + } + else { + $Element.GetCssValue($Name) + } + + + } +} diff --git a/Public/Get-SeFrame.ps1 b/Public/Get-SeFrame.ps1 new file mode 100644 index 0000000..de164f7 --- /dev/null +++ b/Public/Get-SeFrame.ps1 @@ -0,0 +1,14 @@ +function Get-SeFrame { + [cmdletbinding()] + param() + + $Driver = Init-SeDriver -ErrorAction Stop + + Get-SeElement -By TagName -Value iframe -Attributes name, id -ErrorAction SilentlyContinue | + ForEach-Object { + $_.Psobject.TypeNames.Insert(0, 'selenium-powershell/SeFrame') + $_ + } + +} + diff --git a/Public/Get-SeHtml.ps1 b/Public/Get-SeHtml.ps1 new file mode 100644 index 0000000..bf282f6 --- /dev/null +++ b/Public/Get-SeHtml.ps1 @@ -0,0 +1,22 @@ +function Get-SeHtml { + [CmdletBinding()] + param( + [Parameter(ValueFromPipeline = $true)] + [OpenQA.Selenium.IWebElement]$Element, + [switch]$Inner + ) + Begin { + $Driver = Init-SeDriver -ErrorAction Stop + } + Process { + if ($PSBoundParameters.ContainsKey('Element')) { + if ($Inner) { return $Element.GetAttribute('innerHTML') } + return $Element.GetAttribute('outerHTML') + } + else { + $Driver.PageSource + } + + } +} + diff --git a/Public/Get-SeInput.ps1 b/Public/Get-SeInput.ps1 new file mode 100644 index 0000000..1a861ea --- /dev/null +++ b/Public/Get-SeInput.ps1 @@ -0,0 +1,54 @@ +function Get-SeInput { + [CmdletBinding()] + param( + [ArgumentCompleter( { @('button', 'checkbox', 'color', 'date', 'datetime-local', 'email', 'file', 'hidden', 'image', 'month', 'number', 'password', 'radio', 'range', 'reset', 'search', 'submit', 'tel', 'text', 'time', 'url', 'week') })] + [String]$Type, + [Switch]$Single, + [String]$Text, + [Double]$Timeout, + [Switch]$All, + [String[]]$Attributes, + [String]$Value + + + ) + Begin { + $Driver = Init-SeDriver -ErrorAction Stop + } + Process { + $MyAttributes = @{Attributes = [System.Collections.Generic.List[String]]::new()} + $SelectedAttribute = "" + $LoadAllAttributes = $false + + if ($PSBoundParameters.Remove('Attributes')) { + $MyAttributes = @{Attributes = [System.Collections.Generic.List[String]]$Attributes } + $LoadAllAttributes = $Attributes.Count -eq 1 -and $Attributes[0] -eq '*' + if ($Attributes[0] -ne '*') { $SelectedAttribute = $MyAttributes.Attributes[0] } + } + + if (!$LoadAllAttributes){ + if ($PSBoundParameters.Remove('Type')) { + if (-not $MyAttributes.Attributes.Contains('type')) { $MyAttributes.Attributes.add('type') } + } + if (-not $MyAttributes.Attributes.Contains('placeholder')) { $MyAttributes.Attributes.add('placeholder') } + if (-not $MyAttributes.Attributes.Contains('value')) { $MyAttributes.Attributes.add('value') } + } + + + [void]($PSBoundParameters.Remove('Value')) + + $Filter = [scriptblock]::Create(@" + if ("" -ne "$Type") { if (`$_.Attributes.type -ne "$type") { return } } + if ("" -ne "$Text") { if (`$_.Text -ne "$Text" ) { return } } + if ("" -ne "$Value" -and "" -ne "$SelectedAttribute") { if (`$_.Attributes."$SelectedAttribute" -ne "$Value" ) { return } } + `$_ +"@) + + Get-SeElement -By TagName -Value input @PSBoundParameters @MyAttributes -Filter $Filter | ForEach-Object { + $_.Psobject.TypeNames.Insert(0, 'selenium-powershell/SeInput') + $_ + } + + } +} + diff --git a/Public/Get-SeKeys.ps1 b/Public/Get-SeKeys.ps1 new file mode 100644 index 0000000..7506e41 --- /dev/null +++ b/Public/Get-SeKeys.ps1 @@ -0,0 +1,5 @@ +function Get-SeKeys { + [OpenQA.Selenium.Keys] | + Get-Member -MemberType Property -Static | + Select-Object -Property Name, @{N = "ObjectString"; E = { "[OpenQA.Selenium.Keys]::$($_.Name)" } } +} \ No newline at end of file diff --git a/Public/Get-SeSelectValue.ps1 b/Public/Get-SeSelectValue.ps1 new file mode 100644 index 0000000..3b3849e --- /dev/null +++ b/Public/Get-SeSelectValue.ps1 @@ -0,0 +1,51 @@ +function Get-SeSelectValue { + [CmdletBinding()] + [cmdletbinding(DefaultParameterSetName = 'default')] + param ( + [Parameter( ValueFromPipeline = $true, Mandatory = $true, Position = 1)] + [OpenQA.Selenium.IWebElement]$Element, + [Switch]$All + ) + try { + $IsMultiSelectResult = [SeleniumSelection.Option]::IsMultiSelect($Element) + + + $SelectStatement = if ($IsMultiSelectResult) { 'GetAllSelectedOptions' } else { 'GetSelectedOption' } + $Selected = [SeleniumSelection.Option]::$SelectStatement($Element) + $Items = @(foreach ($item in $Selected) { + [PSCustomObject]@{ + Text = $Item.text + Value = Get-SeElementAttribute -Element $Item -Name value + } + }) + + if (-not $All) { + return $Items + } + else { + + $Index = 0 + $Options = Get-SeElement -Element $Element -By Tagname -Value option -Attributes value + $Values = foreach ($Opt in $Options) { + [PSCustomObject]@{ + Index = $Index + Text = $Opt.text + Value = $opt.Attributes.value + Selected = $Null -ne $Items.Value -and $Items.Value.Contains($opt.Attributes.value) + } + $Index += 1 + } + return [PSCustomObject]@{ + PSTypeName = 'selenium-powershell/SeSelectValueInfo' + IsMultiSelect = [SeleniumSelection.Option]::IsMultiSelect($Element) + Items = $Values + } + } + + + + } + catch { + throw "An error occured checking the selection box, the message was:`r`n $($_.exception.message)" + } +} \ No newline at end of file diff --git a/Public/Get-SeUrl.ps1 b/Public/Get-SeUrl.ps1 new file mode 100644 index 0000000..7da597a --- /dev/null +++ b/Public/Get-SeUrl.ps1 @@ -0,0 +1,40 @@ +function Get-SeUrl { + <# + .SYNOPSIS + Retrieves the current URL of a target webdriver instance. + + .DESCRIPTION + Retrieves the current URL of a target webdriver instance, or the currently + stored internal location stack. + + .EXAMPLE + Get-SeUrl + + Retrieves the current URL of the default webdriver instance. + + .NOTES + When using -Stack, the retrieved stack will not contain any of the driver's + history (Back/Forward) data. It only handles locations added with + Push-SeUrl. + + To utilise a driver's Back/Forward functionality, instead use Set-SeUrl. + #> + [CmdletBinding()] + param( + # Optionally retrieve the stored URL stack for the target or default + # webdriver instance. + [Parameter()] + [switch] + $Stack + ) + $Driver = Init-SeDriver -ErrorAction Stop + + if ($Stack) { + if ($Script:SeLocationMap[$Driver].Count -gt 0) { + $Script:SeLocationMap[$Driver].ToArray() + } + } + else { + $Driver.Url + } +} diff --git a/Public/Get-SeWindow.ps1 b/Public/Get-SeWindow.ps1 new file mode 100644 index 0000000..cb65154 --- /dev/null +++ b/Public/Get-SeWindow.ps1 @@ -0,0 +1,10 @@ +function Get-SeWindow { + [CmdletBinding()] + param() + begin { + $Driver = Init-SeDriver -ErrorAction Stop + } + process { + $Driver.WindowHandles + } +} \ No newline at end of file diff --git a/Public/Invoke-SeClick.ps1 b/Public/Invoke-SeClick.ps1 new file mode 100644 index 0000000..23cc6a3 --- /dev/null +++ b/Public/Invoke-SeClick.ps1 @@ -0,0 +1,54 @@ +function Invoke-SeClick { + [CmdletBinding()] + param( + [parameter(Position = 0, HelpMessage = 'test')] + [ArgumentCompleter([SeMouseClickActionCompleter])] + [ValidateScript( { $_ -in $Script:SeMouseClickAction.Text })] + $Action = 'Click', + [Parameter( ValueFromPipeline = $true, Position = 1)] + [ValidateNotNull()] + [OpenQA.Selenium.IWebElement]$Element, + [Double]$Sleep = 0 , + [switch]$PassThru + ) + + begin { + $Driver = Init-SeDriver -ErrorAction Stop + $HasElement = $PSBoundParameters.ContainsKey('Element') -or $PSCmdlet.MyInvocation.ExpectingInput + if ($Action -eq 'Click_JS' -and -not $HasElement) { + Write-Error 'Click_JS can only be performed if an $Element is specified' + return $null + } + } + Process { + Write-Verbose "Performing $Action" + switch ($Action) { + 'Click_Js' { + try { $Driver.ExecuteScript("arguments[0].click()", $Element) } + catch { $PSCmdlet.ThrowTerminatingError($_) } + } + Default { + $Interaction = [OpenQA.Selenium.Interactions.Actions]::new($Driver) + if ($PSBoundParameters.ContainsKey('Element')) { + Write-Verbose "On Element: $($Element.Tagname)" + if ($Action -eq 'Click') { + $Element.Click() #Mitigating IE driver issue with statement below. + } + else { + try { $Interaction.$Action($Element).Perform() } + catch { $PSCmdlet.ThrowTerminatingError($_) } + } + } + else { + Write-Verbose "On Driver currently located at: $($Driver.Url)" + try { $Interaction.$Action().Perform() } + catch { $PSCmdlet.ThrowTerminatingError($_) } + } + } + } + + if ($Sleep -gt 0) { Start-Sleep -Milliseconds ($Sleep * 1000) } + if ($PassThru) { if ($HasElement) { return $Element } else { return $Driver } } + + } +} \ No newline at end of file diff --git a/Public/Invoke-SeJavascript.ps1 b/Public/Invoke-SeJavascript.ps1 new file mode 100644 index 0000000..89b3e76 --- /dev/null +++ b/Public/Invoke-SeJavascript.ps1 @@ -0,0 +1,21 @@ +function Invoke-SeJavascript { + [CmdletBinding()] + param( + [Parameter(ValueFromPipeline = $true, Position = 0)] + [String]$Script, + [Parameter(Position = 1)] + [Object[]]$ArgumentList + ) + begin { + $Driver = Init-SeDriver -ErrorAction Stop + } + Process { + #Fix #165 + $MYargumentList = Foreach ($item in $ArgumentList) { + $Item -as $Item.GetType() + } + $Driver.ExecuteScript($Script, $MyArgumentList) + } + End {} +} + diff --git a/Public/Invoke-SeKeys.ps1 b/Public/Invoke-SeKeys.ps1 new file mode 100644 index 0000000..dcd0e01 --- /dev/null +++ b/Public/Invoke-SeKeys.ps1 @@ -0,0 +1,84 @@ +$Script:ModifierKeys = @( + 'Control', + 'LeftControl' + 'Alt', + 'LeftAlt' + 'Shift', + 'LeftShift' +) +function Invoke-SeKeys { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param( + [Parameter( Position = 0, ValueFromPipeline = $true)] + [ValidateNotNull()] + [OpenQA.Selenium.IWebElement]$Element , + [Parameter(Mandatory = $true, Position = 1)] + [AllowEmptyString()] + [string]$Keys, + [switch]$ClearFirst, + [Double]$Sleep = 0 , + [switch]$Submit, + [switch]$PassThru + ) + begin { + $Driver = Init-SeDriver -ErrorAction Stop + + $Regexstr = '(?{{(?.*?)}})' + $MyMatches = [Regex]::Matches($Keys, $Regexstr) + #Treat modifier keys as key down . + $Sequence = [System.Collections.Generic.List[String]]::new() + $UseSequence = $Keys.StartsWith('{{') + + Foreach ($m in $MyMatches) { + $key = $m.Groups.Item('value').value + $Found = $Script:SeKeys.Name.Contains($value) + if ($null -ne $Found) { + if ($UseSequence -and $Key -in $Script:ModifierKeys) { + $Sequence.Add([OpenQA.Selenium.Keys]::$key) + $Keys = $Keys -replace "{{$key}}", '' + } + else { + $Keys = $Keys -replace "{{$key}}", [OpenQA.Selenium.Keys]::$key + } + + } + } + $UseSequence = $UseSequence -and $Sequence.Count -gt 0 + + } + process { + $Action = [OpenQA.Selenium.Interactions.Actions]::new($Driver) + + switch ($PSBoundParameters.ContainsKey('Element')) { + $true { + if ($ClearFirst) { $Element.Clear() } + + if ($UseSequence) { + Foreach ($k in $Sequence) { $Action.KeyDown($Element, $k) } + $Action.SendKeys($Element, $Keys) + Foreach ($k in $Sequence) { $Action.KeyUp($Element, $k) } + $Action.Build().Perform() + } + else { + $Action.SendKeys($Element, $Keys).Perform() + } + + if ($Submit) { $Element.Submit() } + } + $false { + if ($UseSequence) { + Foreach ($k in $Sequence) { $Action.KeyDown($k) } + $Action.SendKeys($Keys) + Foreach ($k in $Sequence) { $Action.KeyUp($k) } + $Action.Build().Perform() + } + else { + $Action.SendKeys($Keys).Perform() + } + } + } + + if ($Sleep) { Start-Sleep -Milliseconds ($Sleep * 1000) } + if ($PassThru) { $Element } + } +} \ No newline at end of file diff --git a/Public/Invoke-seMouseAction.ps1 b/Public/Invoke-seMouseAction.ps1 new file mode 100644 index 0000000..f42d2ff --- /dev/null +++ b/Public/Invoke-seMouseAction.ps1 @@ -0,0 +1,59 @@ +function Invoke-SeMouseAction { + [CmdletBinding()] + param ( + [ArgumentCompleter([SeMouseActionCompleter])] + [ValidateScript( { $_ -in $Script:SeMouseAction.Text })] + $Action, + $Value, + [Parameter(ValueFromPipeline = $true)] + [OpenQA.Selenium.IWebElement]$Element + ) + $Driver = Init-SeDriver -ErrorAction Stop + Test-SeMouseActionValueValidation -Action $Action -ConditionValue $Value -ErrorAction Stop + + + $Value2 = $null + if ($Action -in @('DragAndDropToOffset', 'MoveByOffset', 'MoveToElement') -and $Value -is [String]) { + $Value2 = $Value -split '[,x]' + } + + + $Interaction = [OpenQA.Selenium.Interactions.Actions]::new($Driver) + + $HasElement = $PSBoundParameters.ContainsKey('Element') + $HasValue = $PSBoundParameters.ContainsKey('Value') + + if ($HasElement) { + if ($HasValue) { + if ($null -ne $value2) { + try { $Interaction.$Action($Element, $Value2[0], $value2[1]).Perform() }catch { $PSCmdlet.ThrowTerminatingError($_) } + } + else { + try { $Interaction.$Action($Element, $Value).Perform() }catch { $PSCmdlet.ThrowTerminatingError($_) } + } + } + else { + try { $Interaction.$Action($Element).Perform() }catch { $PSCmdlet.ThrowTerminatingError($_) } + } + } + else { + if ($HasValue) { + if ($null -ne $value2) { + try { $Interaction.$Action($Value2[0], $Value2[1]).Perform() }catch { $PSCmdlet.ThrowTerminatingError($_) } + } + else { + try { $Interaction.$Action($Value).Perform() }catch { $PSCmdlet.ThrowTerminatingError($_) } + } + + + } + else { + try { $Interaction.$Action().Perform() }catch { $PSCmdlet.ThrowTerminatingError($_) } + } + } + + + + + +} \ No newline at end of file diff --git a/Public/New-SeDriverOptions.ps1 b/Public/New-SeDriverOptions.ps1 new file mode 100644 index 0000000..fb6c417 --- /dev/null +++ b/Public/New-SeDriverOptions.ps1 @@ -0,0 +1,59 @@ +function New-SeDriverOptions { + [cmdletbinding()] + [OutputType( + [OpenQA.Selenium.Chrome.ChromeOptions], + [OpenQA.Selenium.Edge.EdgeOptions], + [OpenQA.Selenium.Firefox.FirefoxOptions], + [OpenQA.Selenium.IE.InternetExplorerOptions] + )] + param( + [ArgumentCompleter( { [Enum]::GetNames([SeBrowsers]) })] + [ValidateScript( { $_ -in [Enum]::GetNames([SeBrowsers]) })] + [Parameter(ParameterSetName = 'Default')] + $Browser, + [StringUrlTransformAttribute()] + [ValidateURIAttribute()] + [Parameter(Position = 1)] + [string]$StartURL, + [ArgumentCompleter( { [Enum]::GetNames([SeWindowState]) })] + [ValidateScript( { $_ -in [Enum]::GetNames([SeWindowState]) })] + $State, + [System.IO.FileInfo]$DefaultDownloadPath, + [switch]$PrivateBrowsing, + [Double]$ImplicitWait = 0.3, + [System.Drawing.Size][SizeTransformAttribute()]$Size, + [System.Drawing.Point][PointTransformAttribute()]$Position, + $WebDriverPath, + $BinaryPath, + [String[]]$Switches, + [String[]]$Arguments, + $ProfilePath, + [OpenQA.Selenium.LogLevel]$LogLevel, + [SeDriverUserAgentTransformAttribute()] + [ValidateNotNull()] + [ArgumentCompleter( [SeDriverUserAgentCompleter])] + [String]$UserAgent, + [Switch]$AcceptInsecureCertificates + ) + if ($PSBoundParameters.ContainsKey('UserAgent')) { Test-SeDriverUserAgent -Browser $Browser -ErrorAction Stop } + if ($PSBoundParameters.ContainsKey('AcceptInsecureCertificates')) { Test-SeDriverAcceptInsecureCertificates -Browser $Browser -ErrorAction Stop } + + # [Enum]::GetNames([sebrowsers]) + $output = $null + switch ($Browser) { + Chrome { $Output = [OpenQA.Selenium.Chrome.ChromeOptions]::new() } + Edge { $Output = New-Object -TypeName OpenQA.Selenium.Chrome.ChromeOptions -Property @{ browserName = '' } } + Firefox { $Output = [OpenQA.Selenium.Firefox.FirefoxOptions]::new() } + InternetExplorer { + $Output = [OpenQA.Selenium.IE.InternetExplorerOptions]::new() + $Output.IgnoreZoomLevel = $true + } + MSEdge { $Output = [OpenQA.Selenium.Edge.EdgeOptions]::new() } + } + + #Add members to be treated by Internal Start cmdlet since Start-SeDriver won't allow their use with Options parameter set. + Add-Member -InputObject $output -MemberType NoteProperty -Name 'SeParams' -Value $PSBoundParameters + + + return $output +} \ No newline at end of file diff --git a/Public/New-SeDriverService.ps1 b/Public/New-SeDriverService.ps1 new file mode 100644 index 0000000..695700a --- /dev/null +++ b/Public/New-SeDriverService.ps1 @@ -0,0 +1,52 @@ +function New-SeDriverService { + [cmdletbinding()] + [OutputType( + [OpenQA.Selenium.Chrome.ChromeDriverService], + [OpenQA.Selenium.Firefox.FirefoxDriverService], + [OpenQA.Selenium.IE.InternetExplorerDriverService], + [OpenQA.Selenium.Edge.EdgeDriverService] + )] + param( + [ArgumentCompleter( { [Enum]::GetNames([SeBrowsers]) })] + [ValidateScript( { $_ -in [Enum]::GetNames([SeBrowsers]) })] + [Parameter(ParameterSetName = 'Default')] + $Browser, + $WebDriverPath + ) + + #$AssembliesPath defined in init.ps1 + $service = $null + $ServicePath = $null + + if ($WebDriverPath) { $ServicePath = $WebDriverPath } elseif ($AssembliesPath) { $ServicePath = $AssembliesPath } + + switch ($Browser) { + + Chrome { + if ($ServicePath) { $service = [OpenQA.Selenium.Chrome.ChromeDriverService]::CreateDefaultService($ServicePath) } + else { $service = [OpenQA.Selenium.Chrome.ChromeDriverService]::CreateDefaultService() } + } + Edge { + $service = [OpenQA.Selenium.Chrome.ChromeDriverService]::CreateDefaultService($ServicePath, 'msedgedriver.exe') + } + Firefox { + if ($ServicePath) { $service = [OpenQA.Selenium.Firefox.FirefoxDriverService]::CreateDefaultService($ServicePath) } + else { $service = [OpenQA.Selenium.Firefox.FirefoxDriverService]::CreateDefaultService() } + $service.Host = '::1' + } + InternetExplorer { + if ($WebDriverPath) { $Service = [OpenQA.Selenium.IE.InternetExplorerDriverService]::CreateDefaultService($WebDriverPath) } + else { $Service = [OpenQA.Selenium.IE.InternetExplorerDriverService]::CreateDefaultService() } + + } + MSEdge { + $service = [OpenQA.Selenium.Edge.EdgeDriverService]::CreateDefaultService() + } + } + + #Set to $true by default; removing it will cause problems in jobs and create a second source of Verbose in the console. + $Service.HideCommandPromptWindow = $true + + return $service +} + diff --git a/Public/New-SeScreenshot.ps1 b/Public/New-SeScreenshot.ps1 new file mode 100644 index 0000000..8879b1c --- /dev/null +++ b/Public/New-SeScreenshot.ps1 @@ -0,0 +1,43 @@ +function New-SeScreenshot { + + [cmdletbinding(DefaultParameterSetName = 'Driver')] + param( + [Parameter(DontShow, ValueFromPipeline = $true, ParameterSetName = 'Pipeline')] + [ValidateScript( { + $Types = @([OpenQA.Selenium.IWebDriver], [OpenQA.Selenium.IWebElement]) + $Found = $false + Foreach ($t in $Types) { if ($_ -is $t) { $Found = $true; break } } + if ($found) { return $true } else { Throw "Input must be of one of the following types $($Types -join ',')" } + })] + $InputObject, + [Switch]$AsBase64EncodedString, + [Parameter(ParameterSetName = 'Element')] + [ValidateNotNull()] + [OpenQA.Selenium.IWebElement]$Element + ) + Begin { + $Driver = Init-SeDriver -ErrorAction Stop + } + Process { + switch ($PSCmdlet.ParameterSetName) { + 'Pipeline' { + switch ($InputObject) { + { $_ -is [OpenQA.Selenium.IWebElement] } { $Screenshot = $InputObject.GetScreenshot() } + { $_ -is [OpenQA.Selenium.IWebDriver] } { $Screenshot = [OpenQA.Selenium.Support.Extensions.WebDriverExtensions]::TakeScreenshot($InputObject) } + } + } + 'Element' { $Screenshot = $Element.GetScreenshot() } + 'Driver' { $Screenshot = [OpenQA.Selenium.Support.Extensions.WebDriverExtensions]::TakeScreenshot($Driver) } + } + + if ($AsBase64EncodedString) { + return $Screenshot.AsBase64EncodedString + } + else { + return $Screenshot + } + } + End {} + + +} \ No newline at end of file diff --git a/Public/New-SeWindow.ps1 b/Public/New-SeWindow.ps1 new file mode 100644 index 0000000..5b41b9b --- /dev/null +++ b/Public/New-SeWindow.ps1 @@ -0,0 +1,19 @@ +function New-SeWindow { + [CmdletBinding()] + param( + [ValidateURIAttribute()] + [StringUrlTransformAttribute()] + $Url + ) + begin { + $Driver = Init-SeDriver -ErrorAction Stop + } + process { + $Windows = Get-SeWindow + $Driver.ExecuteScript('window.open()') + $WindowsNewSet = Get-SeWindow + $NewWindowHandle = (Compare-Object -ReferenceObject $Windows -DifferenceObject $WindowsNewSet).Inputobject + Switch-SeWindow -Window $NewWindowHandle + if ($PSBoundParameters.ContainsKey('Url')) { Set-SeUrl -Url $Url } + } +} \ No newline at end of file diff --git a/Public/Pop-SeUrl.ps1 b/Public/Pop-SeUrl.ps1 new file mode 100644 index 0000000..69cdbe5 --- /dev/null +++ b/Public/Pop-SeUrl.ps1 @@ -0,0 +1,32 @@ +function Pop-SeUrl { + <# + .SYNOPSIS + Navigate back to the most recently pushed URL in the location stack. + + .DESCRIPTION + Retrieves the most recently pushed URL from the location stack and navigates + to that URL with the specified or default driver. + + .EXAMPLE + Pop-SeUrl + + Retrieves the most recently pushed URL and navigates back to that URL. + + .NOTES + A separate internal location stack is maintained for each driver instance + by the module. This stack is completely separate from the driver's internal + Back/Forward history logic. + + To utilise a driver's Back/Forward functionality, instead use Set-SeUrl. + #> + [CmdletBinding()] + param() + begin { + $Driver = Init-SeDriver -ErrorAction Stop + } + process { + if ($Script:SeLocationMap[$Driver].Count -gt 0) { + Set-SeUrl -Url $Script:SeLocationMap[$Driver].Pop() -Driver $Driver + } + } +} diff --git a/Public/Push-SeUrl.ps1 b/Public/Push-SeUrl.ps1 new file mode 100644 index 0000000..c771811 --- /dev/null +++ b/Public/Push-SeUrl.ps1 @@ -0,0 +1,49 @@ +function Push-SeUrl { + <# + .SYNOPSIS + Stores the current URL in the driver's location stack and optionally + navigate to a new URL. + + .DESCRIPTION + The current driver URL is added to the stack, and if a URL is provided, the + driver navigates to the new URL. + + .EXAMPLE + Push-SeUrl + + The current driver URL is added to the location stack. + + .EXAMPLE + Push-SeUrl 'https://google.com/' + + The current driver URL is added to the location stack, and the driver then + navigates to the provided target URL. + + .NOTES + A separate internal location stack is maintained for each driver instance + by the module. This stack is completely separate from the driver's internal + Back/Forward history logic. + + To utilise a driver's Back/Forward functionality, instead use Set-SeUrl. + #> + [CmdletBinding()] + param( + # The new URL to navigate to after storing the current location. + [Parameter(Position = 0, ParameterSetName = 'url')] + [ValidateURIAttribute()] + [string] + $Url + ) + $Driver = Init-SeDriver -ErrorAction Stop + if (-not $Script:SeLocationMap.ContainsKey($Driver)) { + $script:SeLocationMap[$Driver] = [System.Collections.Generic.Stack[string]]@() + } + + # Push the current location to the stack + $script:SeLocationMap[$Driver].Push($Driver.Url) + + if ($Url) { + # Change the driver current URL to provided URL + Set-SeUrl -Url $Url -Driver $Driver + } +} diff --git a/Public/Remove-SeCookie.ps1 b/Public/Remove-SeCookie.ps1 new file mode 100644 index 0000000..8e4305f --- /dev/null +++ b/Public/Remove-SeCookie.ps1 @@ -0,0 +1,17 @@ +function Remove-SeCookie { + [CmdletBinding()] + param( + [Parameter(Mandatory = $true, ParameterSetName = 'All')] + [switch]$All, + + [Parameter(Mandatory = $true, ParameterSetName = 'NamedCookie')] + [string]$Name + ) + $Driver = Init-SeDriver -ErrorAction Stop + if ($All) { + $Driver.Manage().Cookies.DeleteAllCookies() + } + else { + $Driver.Manage().Cookies.DeleteCookieNamed($Name) + } +} \ No newline at end of file diff --git a/Public/Remove-SeWindow.ps1 b/Public/Remove-SeWindow.ps1 new file mode 100644 index 0000000..a0312eb --- /dev/null +++ b/Public/Remove-SeWindow.ps1 @@ -0,0 +1,31 @@ +function Remove-SeWindow { + [CmdletBinding()] + param( + [String]$SwitchToWindow + ) + begin { + $Driver = Init-SeDriver -ErrorAction Stop + } + process { + try { + $Windows = @(Get-SeWindow) + if ($Windows.Count -eq 1) { Write-Warning -Message 'The driver has only one window left. Operation aborted. Use Stop-Driver instead.' } + + $Driver.Close() + if ($PSBoundParameters.ContainsKey('SwitchTo')) { + Switch-SeWindow -Window $SwitchToWindow + } + else { + $Windows = @(Get-SeWindow) + if ($Windows.count -gt 0) { + Switch-SeWindow -Window $Windows[0] + } + } + } + catch { + Write-Error $_ + } + + + } +} \ No newline at end of file diff --git a/Public/Save-SeScreenshot.ps1 b/Public/Save-SeScreenshot.ps1 new file mode 100644 index 0000000..6078468 --- /dev/null +++ b/Public/Save-SeScreenshot.ps1 @@ -0,0 +1,43 @@ +function Save-SeScreenshot { + [CmdletBinding(DefaultParameterSetName = 'Driver')] + param( + [Parameter(DontShow, ValueFromPipeline = $true, ParameterSetName = 'Pipeline')] + [ValidateScript( { + $Types = @([OpenQA.Selenium.IWebDriver], [OpenQA.Selenium.IWebElement], [OpenQA.Selenium.Screenshot]) + $Found = $false + Foreach ($t in $Types) { if ($_ -is $t) { $Found = $true; break } } + if ($found) { return $true } else { Throw "Input must be of one of the following types $($Types -join ',')" } + })] + $InputObject, + [Parameter( Mandatory = $true, ParameterSetName = 'Screenshot')] + [OpenQA.Selenium.Screenshot]$Screenshot, + [Parameter(Mandatory = $true)] + [string]$Path, + [OpenQA.Selenium.ScreenshotImageFormat]$ImageFormat = [OpenQA.Selenium.ScreenshotImageFormat]::Png, + [Parameter(Mandatory = $true, ParameterSetName = 'Element')] + [ValidateNotNull()] + [OpenQA.Selenium.IWebElement]$Element + ) + + begin { + if ($PSCmdlet.ParameterSetName -eq 'Driver') { + $Driver = Init-SeDriver -ErrorAction Stop + } + } + process { + + switch ($PSCmdlet.ParameterSetName) { + 'Pipeline' { + switch ($InputObject) { + { $_ -is [OpenQA.Selenium.IWebElement] } { $Screenshot = $InputObject.GetScreenshot() } + { $_ -is [OpenQA.Selenium.IWebDriver] } { $Screenshot = [OpenQA.Selenium.Support.Extensions.WebDriverExtensions]::TakeScreenshot($InputObject) } + { $_ -is [OpenQA.Selenium.Screenshot] } { $Screenshot = $InputObject } + } + } + 'Driver' { $Screenshot = New-SeScreenshot } + 'Element' { $Screenshot = New-SeScreenshot -Element $Element } + } + + $Screenshot.SaveAsFile($Path, $ImageFormat) + } +} diff --git a/Public/SeShouldHave.ps1 b/Public/SeShouldHave.ps1 new file mode 100644 index 0000000..24989c5 --- /dev/null +++ b/Public/SeShouldHave.ps1 @@ -0,0 +1,190 @@ +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)] + [ArgumentCompleter( { [Enum]::GetNames([SeBySelector]) })] + [ValidateScript( { $_ -in [Enum]::GetNames([SeBySelector]) })] + [string]$By = [SeBySelector]::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)] + [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')] + [switch]$PassThru, + + [Double]$Timeout = 0 + ) + begin { + $endTime = [datetime]::now.AddMilliseconds($Timeout * 1000) + $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 = [System.Collections.Generic.List[PSObject]]::new() + } + process { + $Driver = (Get-SeDriver -Current) + #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 $Driver.Url -operator $Operator -value $Value + Start-Sleep -Milliseconds 500 + } + until ($Success -or [datetime]::now -gt $endTime) + if (-not $Success) { + throw (expandErr "PageURL was $($Driver.Url). The comparison '-$operator $value' failed.") + } + } + elseif ($Title) { + do { + $Success = applyTest -testitems $Driver.Title -operator $Operator -value $Value + Start-Sleep -Milliseconds 500 + } + until ($Success -or [datetime]::now -gt $endTime) + if (-not $Success) { + throw (expandErr "Page title was $($Driver.Title). The comparison '-$operator $value' failed.") + } + } + elseif ($Alert -or $NoAlert) { + do { + try { + $a = $Driver.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; Value = $s } + if ($Timeout) { $GSEParams['Timeout'] = $Timeout } + try { $e = Get-SeElement @GSEParams -All } + 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.add($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-SeSelectValue -Element $e -All).Items.Text } + 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'.") + } + } + } + } +} \ No newline at end of file diff --git a/Public/Set-SeCookie.ps1 b/Public/Set-SeCookie.ps1 new file mode 100644 index 0000000..da06c3f --- /dev/null +++ b/Public/Set-SeCookie.ps1 @@ -0,0 +1,46 @@ +function Set-SeCookie { + [cmdletbinding()] + param( + [string]$Name, + [string]$Value, + [string]$Path, + [string]$Domain, + [DateTime]$ExpiryDate + ) + begin { + $Driver = Init-SeDriver -ErrorAction Stop + } + + 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 ($Driver.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) + Initializes a new instance of the Cookie class with a specific name, value, path and expiration date. + Cookie(String, String, String, String, Nullable) + Initializes a new instance of the Cookie class with a specific name, value, domain, path and expiration date." + } + + $Driver.Manage().Cookies.AddCookie($cookie) + } +} \ No newline at end of file diff --git a/Public/Set-SeDriverTimeout.ps1 b/Public/Set-SeDriverTimeout.ps1 new file mode 100644 index 0000000..9c4bec6 --- /dev/null +++ b/Public/Set-SeDriverTimeout.ps1 @@ -0,0 +1,18 @@ +function Set-SeDriverTimeout { + [CmdletBinding()] + param( + [Parameter(Position = 0)] + [ValidateSet('ImplicitWait', 'PageLoad', 'AsynchronousJavaScript')] + $TimeoutType = 'ImplicitWait', + [Parameter(Position = 1)] + [Double]$Timeout = 0 + ) + begin { + $Driver = Init-SeDriver -ErrorAction Stop + } + Process { + $Driver.Manage().Timeouts().$TimeoutType = [timespan]::FromMilliseconds($Timeout * 1000) + } + End {} +} + diff --git a/Public/Set-SeSelectValue.ps1 b/Public/Set-SeSelectValue.ps1 new file mode 100644 index 0000000..e623173 --- /dev/null +++ b/Public/Set-SeSelectValue.ps1 @@ -0,0 +1,46 @@ +function Set-SeSelectValue { + [CmdletBinding()] + param ( + [ArgumentCompleter( { [Enum]::GetNames([SeBySelect]) })] + [ValidateScript( { $_ -in [Enum]::GetNames([SeBySelect]) })] + [SeBySelect]$By = [SeBySelect]::Text, + [Parameter( ValueFromPipeline = $true, Position = 1, Mandatory = $true)] + [OpenQA.Selenium.IWebElement]$Element, + [Object]$value + + ) + try { + $IsMultiSelect = [SeleniumSelection.Option]::IsMultiSelect($Element) + + if (-not $IsMultiSelect -and $Value.Count -gt 1) { + Write-Error 'This select control do not accept multiple values' + return $null + } + + #byindex can be 0, but ByText and ByValue can't be empty strings + switch ($By) { + { $_ -eq [SeBySelect]::Text } { + $HaveWildcards = $null -ne (Get-WildcardsIndices -Value $value) + + if ($HaveWildcards) { + $ValuesToSelect = Get-SeSelectValue -Element $Element -All + $ValuesToSelect = $ValuesToSelect.Items | Where-Object { $_.Text -like $Value } + if (! $IsMultiSelect) { $ValuesToSelect = $ValuesToSelect | Select -first 1 } + Foreach ($v in $ValuesToSelect) { + [SeleniumSelection.Option]::SelectByText($Element, $v.Text, $false) + } + } + else { + [SeleniumSelection.Option]::SelectByText($Element, $value, $false) + } + + } + + { $_ -eq [SeBySelect]::Value } { [SeleniumSelection.Option]::SelectByValue($Element, $value) } + { $_ -eq [SeBySelect]::Index } { [SeleniumSelection.Option]::SelectByIndex($Element, $value) } + } + } + catch { + throw "An error occured checking the selection box, the message was:`r`n $($_.exception.message)" + } +} \ No newline at end of file diff --git a/Public/Set-SeUrl.ps1 b/Public/Set-SeUrl.ps1 new file mode 100644 index 0000000..17df3d2 --- /dev/null +++ b/Public/Set-SeUrl.ps1 @@ -0,0 +1,72 @@ +function Set-SeUrl { + <# + .SYNOPSIS + Navigates to the targeted URL with the selected or default driver. + + .DESCRIPTION + Used for webdriver navigation commands, either to specific target URLs or + for history (Back/Forward) navigation or refreshing the current page. + + .EXAMPLE + Set-SeUrl 'https://www.google.com/' + + Directs the default driver to navigate to www.google.com. + + .EXAMPLE + Set-SeUrl -Refresh + + Reloads the current page for the default driver. + + .EXAMPLE + Set-SeUrl -Target $Driver -Back + + Directs the targeted webdriver instance to navigate Back in its history. + + .EXAMPLE + Set-SeUrl -Forward + + Directs the default webdriver to navigate Forward in its history. + + .NOTES + The Back/Forward/Refresh logic is handled by the webdriver itself. If you + need a more granular approach to handling which locations are saved or + retrieved, use Push-SeUrl or Pop-SeUrl to utilise a separately managed + location stack. + #> + [CmdletBinding(DefaultParameterSetName = 'default')] + param( + # The target URL for the webdriver to navigate to. + [Parameter(Mandatory = $true, position = 0, ParameterSetName = 'url')] + [StringUrlTransformAttribute()] + [ValidateURIAttribute()] + [string]$Url, + + # Trigger the Back history navigation action in the webdriver. + [Parameter(Mandatory = $true, ParameterSetName = 'back')] + [switch]$Back, + + # Trigger the Forward history navigation action in the webdriver. + [Parameter(Mandatory = $true, ParameterSetName = 'forward')] + [switch]$Forward, + + # Refresh the current page in the webdriver. + [Parameter(Mandatory = $true, ParameterSetName = 'refresh')] + [switch]$Refresh, + + [Parameter(ParameterSetName = 'back')] + [Parameter(ParameterSetName = 'forward', Position = 1)] + [ValidateScript( { $_ -ge 1 })] + [Int]$Depth = 1 + ) + $Driver = Init-SeDriver -ErrorAction Stop + for ($i = 0; $i -lt $Depth; $i++) { + switch ($PSCmdlet.ParameterSetName) { + 'url' { $Driver.Navigate().GoToUrl($Url); break } + 'back' { $Driver.Navigate().Back(); break } + 'forward' { $Driver.Navigate().Forward(); break } + 'refresh' { $Driver.Navigate().Refresh(); break } + default { throw 'Unexpected ParameterSet' } + } + } + +} diff --git a/Public/Start-SeDriver.ps1 b/Public/Start-SeDriver.ps1 new file mode 100644 index 0000000..960e615 --- /dev/null +++ b/Public/Start-SeDriver.ps1 @@ -0,0 +1,137 @@ + +function Start-SeDriver { + [cmdletbinding(DefaultParameterSetName = 'default')] + [OutputType([OpenQA.Selenium.IWebDriver])] + param( + #Common to all browsers + [ArgumentCompleter( { [Enum]::GetNames([SeBrowsers]) })] + [ValidateScript( { $_ -in [Enum]::GetNames([SeBrowsers]) })] + [Parameter(ParameterSetName = 'Default')] + [Parameter(ParameterSetName = 'DriverOptions')] + $Browser, + [StringUrlTransformAttribute()] + [ValidateURIAttribute()] + [Parameter(Position = 1)] + [string]$StartURL, + [ArgumentCompleter( { [Enum]::GetNames([SeWindowState]) })] + [ValidateScript( { $_ -in [Enum]::GetNames([SeWindowState]) })] + [SeWindowState] $State = [SeWindowState]::Default, + [System.IO.FileInfo]$DefaultDownloadPath, + [switch]$PrivateBrowsing, + [Double]$ImplicitWait = 0.2, + [System.Drawing.Size][SizeTransformAttribute()]$Size, + [System.Drawing.Point][PointTransformAttribute()]$Position, + $WebDriverPath, + $BinaryPath, + [Parameter(ParameterSetName = 'DriverOptions', Mandatory = $false)] + [OpenQA.Selenium.DriverService]$Service, + [Parameter(ParameterSetName = 'DriverOptions', Mandatory = $true)] + [OpenQA.Selenium.DriverOptions]$Options, + [Parameter(ParameterSetName = 'Default')] + [String[]]$Switches, + [String[]]$Arguments, + $ProfilePath, + [OpenQA.Selenium.LogLevel]$LogLevel, + [ValidateNotNullOrEmpty()] + $Name, + [SeDriverUserAgentTransformAttribute()] + [ValidateNotNull()] + [ArgumentCompleter( [SeDriverUserAgentCompleter])] + [String]$UserAgent, + [Switch]$AcceptInsecureCertificates + # See ParametersToRemove to view parameters that should not be passed to browsers internal implementations. + ) + Begin { + if ($PSBoundParameters.ContainsKey('UserAgent')) { Test-SeDriverUserAgent -Browser $Browser -ErrorAction Stop } + if ($PSBoundParameters.ContainsKey('AcceptInsecureCertificates')) { Test-SeDriverAcceptInsecureCertificates -Browser $Browser -ErrorAction Stop } + } + process { + #Params with default value that need to be pased down to Start-SeXXDriver + $OptionalParams = @('ImplicitWait', 'State') + Foreach ($key in $OptionalParams) { + if (!$PSBoundParameters.ContainsKey($Key)) { + $PSBoundParameters.Add($key, (Get-Variable -Name $key -ValueOnly)) + } + } + # Exclusive parameters to Start-SeDriver we don't want to pass down to anything else. + # Still available through the variable directly within this cmdlet + $ParametersToRemove = @('Arguments', 'Browser', 'Name', 'PassThru') + $SelectedBrowser = $Browser + switch ($PSCmdlet.ParameterSetName) { + 'Default' { + $Options = New-SeDriverOptions -Browser $Browser + $PSBoundParameters.Add('Options', $Options) + + } + 'DriverOptions' { + if ($PSBoundParameters.ContainsKey('Service')) { + $MyService = $PSBoundParameters.Item('Service') + foreach ($Key in $MyService.SeParams.Keys) { + if (! $PSBoundParameters.ContainsKey($Key)) { + $PSBoundParameters.Add($Key, $MyService.SeParams.Item($Key)) + } + } + } + + $Options = $PSBoundParameters.Item('Options') + $SelectedBrowser = $Options.SeParams.Browser + + # Start-SeDrivers params overrides whatever is in the options. + # Any options parameter not specified by Start-SeDriver get added to the psboundparameters + foreach ($Key in $Options.SeParams.Keys) { + if (! $PSBoundParameters.ContainsKey($Key)) { + $PSBoundParameters.Add($Key, $Options.SeParams.Item($Key)) + } + } + + } + } + + if ($PSBoundParameters.ContainsKey('Arguments')) { + foreach ($Argument in $Arguments) { + $Options.AddArguments($Argument) + } + } + + + $FriendlyName = $null + if ($PSBoundParameters.ContainsKey('Name')) { + $FriendlyName = $Name + + $AlreadyExist = $Script:SeDrivers.Where( { $_.SeFriendlyName -eq $FriendlyName }, 'first').Count -gt 0 + if ($AlreadyExist) { + throw "A driver with the name $FriendlyName is already in the active list of started driver." + } + } + + + #Remove params exclusive to this cmdlet before going further. + $ParametersToRemove | ForEach-Object { if ($PSBoundParameters.ContainsKey("$_")) { [void]($PSBoundParameters.Remove("$_")) } } + + switch ($SelectedBrowser) { + 'Chrome' { $Driver = Start-SeChromeDriver @PSBoundParameters; break } + 'Edge' { $Driver = Start-SeEdgeDriver @PSBoundParameters; break } + 'Firefox' { $Driver = Start-SeFirefoxDriver @PSBoundParameters; break } + 'InternetExplorer' { $Driver = Start-SeInternetExplorerDriver @PSBoundParameters; break } + 'MSEdge' { $Driver = Start-SeMSEdgeDriver @PSBoundParameters; break } + } + if ($null -ne $Driver) { + if ($null -eq $FriendlyName) { $FriendlyName = $Driver.SessionId } + Write-Verbose -Message "Opened $($Driver.Capabilities.browsername) $($Driver.Capabilities.ToDictionary().browserVersion)" + + #Se prefix used to avoid clash with anything from Selenium in the future + #SessionId scriptproperty validation to avoid perfomance cost of checking closed session. + $Headless = if ($state -eq [SeWindowState]::Headless) { " (headless)" } else { "" } + $mp = @{InputObject = $Driver ; MemberType = 'NoteProperty' } + Add-Member @mp -Name 'SeBrowser' -Value "$SelectedBrowser$($Headless)" + Add-Member @mp -Name 'SeFriendlyName' -Value "$FriendlyName" + Add-Member @mp -Name 'SeSelectedElements' -Value $null + Add-Member -InputObject $Driver -MemberType NoteProperty -Name 'SeProcessId' -Value (Get-DriverProcessId -ServiceProcessId $Driver.SeServiceProcessId) + + $Script:SeDrivers.Add($Driver) + Return Switch-SeDriver -Name $FriendlyName + } + + } +} + diff --git a/Public/Start-SeRemote.ps1 b/Public/Start-SeRemote.ps1 new file mode 100644 index 0000000..9b24d44 --- /dev/null +++ b/Public/Start-SeRemote.ps1 @@ -0,0 +1,29 @@ +function Start-SeRemote { + [cmdletbinding(DefaultParameterSetName = 'default')] + param( + [string]$RemoteAddress, + [hashtable]$DesiredCapabilities, + [ValidateURIAttribute()] + [Parameter(Position = 0)] + [string]$StartURL, + [Double]$ImplicitWait = 0.3, + [System.Drawing.Size][SizeTransformAttribute()]$Size, + [System.Drawing.Point][PointTransformAttribute()]$Position + ) + + $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 } + + if ($PSBoundParameters.ContainsKey('Size')) { $Driver.Manage().Window.Size = $Size } + if ($PSBoundParameters.ContainsKey('Position')) { $Driver.Manage().Window.Position = $Position } + $Driver.Manage().Timeouts().ImplicitWait = [TimeSpan]::FromMilliseconds($ImplicitWait * 1000) + if ($StartURL) { $Driver.Navigate().GotoUrl($StartURL) } + + return $Driver +} \ No newline at end of file diff --git a/Public/Stop-SeDriver.ps1 b/Public/Stop-SeDriver.ps1 new file mode 100644 index 0000000..60ea567 --- /dev/null +++ b/Public/Stop-SeDriver.ps1 @@ -0,0 +1,43 @@ +function Stop-SeDriver { + [CmdletBinding()] + param( + [Parameter(Mandatory = $false, ValueFromPipeline = $true)] + [OpenQA.Selenium.IWebDriver] + $Driver + ) + Begin { + $ElementsToRemove = [System.Collections.Generic.List[PSObject]]::new() + } + Process { + if (! $PSBoundParameters.ContainsKey('Driver')) { + $Driver = Get-SeDriver -Current + } + + + if ($null -ne $Driver) { + $Processes = (Get-Process -Id $Driver.SeProcessId, $Driver.SeServiceProcessId -ErrorAction SilentlyContinue ) + + switch ($Processes.Count) { + 2 { + Write-Verbose -Message "Closing $BrowserName $($Driver.SeFriendlyName )..." + $Driver.Close() + $Driver.Dispose() + break + } + 1 { Stop-Process -Id $Processes.Id -ErrorAction SilentlyContinue } + } + $ElementsToRemove.Add($Driver) + } + + } + End { + $ElementsToRemove | ForEach-Object { [void]($script:SeDrivers.Remove($_)) } + if ($script:SeDriversCurrent -notin $script:SeDrivers) { + $script:SeDriversCurrent = $null + } + + } + + + +} \ No newline at end of file diff --git a/Public/Switch-SeDriver.ps1 b/Public/Switch-SeDriver.ps1 new file mode 100644 index 0000000..7215e69 --- /dev/null +++ b/Public/Switch-SeDriver.ps1 @@ -0,0 +1,32 @@ +function Switch-SeDriver { + [cmdletbinding(DefaultParameterSetName = 'ByName')] + param( + [parameter(Position = 0, ParameterSetName = 'ByDriver', Mandatory = $True)] + [OpenQA.Selenium.IWebDriver]$Driver, + [parameter(Position = 0, ParameterSetName = 'ByName', Mandatory = $True)] + [String]$Name + ) + + # Remove Selected visual indicator + if ($null -ne $Script:SeDriversCurrent) { + $Script:SeDriversCurrent.SeBrowser = $Script:SeDriversCurrent.SeBrowser -replace ' \*$', '' + } + + switch ($PSCmdlet.ParameterSetName) { + 'ByDriver' { $Script:SeDriversCurrent = $Driver } + 'ByName' { + $Driver = Get-SeDriver -Name $Name + if ($null -eq $Driver) { + $PSCmdlet.ThrowTerminatingError("Driver with Name: $Name not found ") + } + else { + $Script:SeDriversCurrent = $Driver + } + } + } + + $Driver.SeBrowser = "$($Driver.SeBrowser) *" + + return $Driver +} + diff --git a/Public/Switch-SeFrame.ps1 b/Public/Switch-SeFrame.ps1 new file mode 100644 index 0000000..6215abe --- /dev/null +++ b/Public/Switch-SeFrame.ps1 @@ -0,0 +1,19 @@ +function Switch-SeFrame { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, ParameterSetName = 'Frame', Position = 0)] + $Frame, + + [Parameter(Mandatory = $true, ParameterSetName = 'Parent')] + [switch]$Parent, + + [Parameter(Mandatory = $true, ParameterSetName = 'Root')] + [switch]$Root + ) + $Driver = Init-SeDriver -ErrorAction Stop + #TODO Frame validation... Do not try to switch if element does not exist ? + #TODO Review ... Maybe Parent / Root should be a unique parameter : -Level Parent/Root ) + if ($PSBoundParameters.ContainsKey('Frame')) { [void]$Driver.SwitchTo().Frame($Frame) } + elseif ($Parent) { [void]$Driver.SwitchTo().ParentFrame() } + elseif ($Root) { [void]$Driver.SwitchTo().defaultContent() } +} \ No newline at end of file diff --git a/Public/Switch-SeWindow.ps1 b/Public/Switch-SeWindow.ps1 new file mode 100644 index 0000000..0ae60fd --- /dev/null +++ b/Public/Switch-SeWindow.ps1 @@ -0,0 +1,12 @@ +function Switch-SeWindow { + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)]$Window + ) + begin { + $Driver = Init-SeDriver -ErrorAction Stop + } + process { + $Driver.SwitchTo().Window($Window) | Out-Null + } +} \ No newline at end of file diff --git a/Public/Update-SeDriver.ps1 b/Public/Update-SeDriver.ps1 new file mode 100644 index 0000000..f6b5ab5 --- /dev/null +++ b/Public/Update-SeDriver.ps1 @@ -0,0 +1,62 @@ +function Update-SeDriver { + [CmdletBinding()] + param ( + [ArgumentCompleter( { [Enum]::GetNames([SeBrowsers]) })] + [ValidateScript( { $_ -in [Enum]::GetNames([SeBrowsers]) })] + $Browser, + [ValidateSet('Linux', 'Mac', 'Windows')] + $OS, + [ValidateScript( { (Test-Path -Path $_) -and ((Get-Item -Path $_) -is [System.IO.DirectoryInfo]) })] + $Path + ) + + if (! $PSBoundParameters.ContainsKey('OS')) { + if ($IsMacOS) { $OS = 'Mac' } elseif ($IsLinux) { $OS = 'Linux' } else { $OS = 'Windows' } + } + + if (! $PSBoundParameters.ContainsKey('Path')) { + $Path = $PSScriptRoot + if ($Path.EndsWith('Public')) { $Path = Split-Path -Path $Path } #Debugging + switch ($OS) { + 'Linux' { $AssembliesDir = Join-Path -Path $Path -ChildPath '/assemblies/linux' } + 'Mac' { $AssembliesDir = Join-Path -Path $Path -ChildPath '/assemblies/macos' } + 'Windows' { $AssembliesDir = Join-Path -Path $Path -ChildPath '/assemblies' } + } + + } + + $TempDir = [System.IO.Path]::GetTempPath() + + switch ($Browser) { + 'Chrome' { + $LatestChromeStableRelease = Invoke-WebRequest 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE' | Select-Object -ExpandProperty Content + $ChromeBuilds = @{ + Linux = 'chromedriver_linux64' + Mac = 'chromedriver_mac64' + Windows = 'chromedriver_win32' + } + + $Build = $ChromeBuilds.$OS + + + $BuildFileName = "$Build.zip" + Write-Verbose "Downloading: $BuildFileName" + Invoke-WebRequest -OutFile "$($TempDir + $BuildFileName)" "https://chromedriver.storage.googleapis.com/$LatestChromeStableRelease/$BuildFileName" + + # Expand the ZIP Archive to the correct Assemblies Dir + Write-Verbose "Explanding: $($TempDir + $BuildFileName) to $AssembliesDir" + Expand-Archive -Path "$($TempDir + $BuildFileName)" -DestinationPath $AssembliesDir -Force + + } + 'Firefox' { + Write-Warning 'Not Supported Yet' + + } + 'Edge' { + Write-Warning 'Not Supported Yet' + } + Default { + Write-Warning 'Not Supported Yet' + } + } +} diff --git a/Public/Wait-SeDriver.ps1 b/Public/Wait-SeDriver.ps1 new file mode 100644 index 0000000..7c957b8 --- /dev/null +++ b/Public/Wait-SeDriver.ps1 @@ -0,0 +1,42 @@ +function Wait-SeDriver { + [Cmdletbinding()] + param( + [ArgumentCompleter([SeDriverConditionsCompleter])] + [ValidateScript( { $_ -in $Script:SeDriverConditions.Text })] + [Parameter(Position = 0, Mandatory = $true)] + $Condition, + [Parameter(Position = 1, Mandatory = $true)] + [ValidateNotNull()] + $Value, + #Specifies a time out + [Parameter(Position = 2)] + [Double]$Timeout = 3 + ) + Begin { + $Driver = Init-SeDriver -ErrorAction Stop + $ImpTimeout = -1 + Test-SeDriverConditionsValueValidation -Condition $Condition -Value $Value -Erroraction Stop + } + process { + $ImpTimeout = Disable-SeDriverImplicitTimeout -Driver $Driver + if ($Condition -eq 'ScriptBlock') { + $SeCondition = [System.Func[OpenQA.Selenium.IWebDriver, Bool]]$Value + } + else { + $SeCondition = [OpenQA.Selenium.Support.UI.ExpectedConditions]::$Condition($Value) + } + $WebDriverWait = [OpenQA.Selenium.Support.UI.WebDriverWait]::new($Driver, ([timespan]::FromMilliseconds($Timeout * 1000))) + + try { + [void]($WebDriverWait.Until($SeCondition)) + return $true + } + catch { + Write-Error $_ + return $false + } + Finally { + Enable-SeDriverImplicitTimeout -Driver $Driver -Timeout $ImpTimeout + } + } +} \ No newline at end of file diff --git a/Public/Wait-SeElement.ps1 b/Public/Wait-SeElement.ps1 new file mode 100644 index 0000000..21d331b --- /dev/null +++ b/Public/Wait-SeElement.ps1 @@ -0,0 +1,68 @@ +function Wait-SeElement { + [Cmdletbinding(DefaultParameterSetName = 'Element')] + param( + [ArgumentCompleter( { [Enum]::GetNames([SeBySelector]) })] + [ValidateScript( { $_ -in [Enum]::GetNames([SeBySelector]) })] + [Parameter(ParameterSetName = 'Locator', Position = 0)] + [SeBySelector]$By = [SeBySelector]::XPath, + [Parameter(Position = 1, Mandatory = $true, ParameterSetName = 'Locator')] + [string]$Value, + + [Parameter(ParameterSetName = 'Element', Mandatory = $true)] + [OpenQA.Selenium.IWebElement]$Element, + [ArgumentCompleter([SeElementsConditionsCompleter])] + [ValidateScript( { $_ -in $Script:SeElementsConditions.Text })] + $Condition, + [ValidateNotNull()] + $ConditionValue, + #Specifies a time out + [Double]$Timeout = 3 + + ) + begin { + $Driver = Init-SeDriver -ErrorAction Stop + Test-SeElementConditionsValueValidation -By $By -Element $Element -Condition $Condition -ConditionValue $ConditionValue -ParameterSetName $PSCmdlet.ParameterSetName @Stop + $ImpTimeout = -1 + + $ExpectedValueType = Get-SeElementsConditionsValueType -text $Condition + + } + process { + $ImpTimeout = Disable-SeDriverImplicitTimeout -Driver $Driver + + $WebDriverWait = [OpenQA.Selenium.Support.UI.WebDriverWait]::new($Driver, ([timespan]::FromMilliseconds($Timeout * 1000))) + $NoExtraArg = $null -eq $ExpectedValueType + + if ($PSBoundParameters.ContainsKey('Element')) { + if ($NoExtraArg) { + $SeCondition = [OpenQA.Selenium.Support.UI.ExpectedConditions]::$Condition($Element) + } + else { + $SeCondition = [OpenQA.Selenium.Support.UI.ExpectedConditions]::$Condition($Element, $ConditionValue) + } + } + else { + if ($NoExtraArg) { + $SeCondition = [OpenQA.Selenium.Support.UI.ExpectedConditions]::$Condition([OpenQA.Selenium.By]::$By($Value)) + } + else { + $SeCondition = [OpenQA.Selenium.Support.UI.ExpectedConditions]::$Condition([OpenQA.Selenium.By]::$By($Value), $ConditionValue) + } + } + + try { + [void]($WebDriverWait.Until($SeCondition)) + return $true + } + catch { + Write-Error $_ + return $false + } + Finally { + Enable-SeDriverImplicitTimeout -Driver $Driver -Timeout $ImpTimeout + } + } +} + + + diff --git a/README.md b/README.md index 7d4659e..81d7c59 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,19 @@ # Selenium PowerShell Module +The Selenium PowerShell module allows you to automate browser interaction using the [Selenium API](https://selenium.dev/). You can navigate to pages, find elements, click buttons, enter text and even take screenshots. + +# Looking for Maintainers + +I haven't been able to able to keep up with the issues on this repo. If you are interested in becoming a maintainer, please let me know. - [Adam](https://github.com/adamdriscoll) + +# About + - Wraps the C# WebDriver for Selenium - Easily execute web-based tests - Works well with Pester +[![Build Status](https://adamrdriscoll.visualstudio.com/Selenium/_apis/build/status/adamdriscoll.selenium-powershell?branchName=master)](https://adamrdriscoll.visualstudio.com/Selenium/_build/latest?definitionId=25&branchName=master) + # Installation `Note: Firefox's Latest Gecko Driver on Windows requires Microsoft Visual Studio Redistributables for the binary to run get them `[Here](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) @@ -15,7 +25,7 @@ Install-Module Selenium OR ``` -Import-Module "{FullPath}\selenium-powershell\Selenium.psm1" +Import-Module "{FullPath}\selenium-powershell\Selenium.psd1" ``` # Usage @@ -109,4 +119,5 @@ Find-SeElement -Driver $d -Wait -Timeout 10 -Name q # Maintainers - [Adam Driscoll](https://github.com/adamdriscoll) -- [Avri Chen-Roth](https://github.com/the-mentor) \ No newline at end of file +- [Avri Chen-Roth](https://github.com/the-mentor) +- [Francis Mercier](https://github.com/itfranck) diff --git a/Selenium.EzFormat.ps1 b/Selenium.EzFormat.ps1 new file mode 100644 index 0000000..442e3c8 --- /dev/null +++ b/Selenium.EzFormat.ps1 @@ -0,0 +1,71 @@ +#requires -Module EZOut +# Install-Module EZOut or https://github.com/StartAutomating/EZOut +$myFile = $MyInvocation.MyCommand.ScriptBlock.File +$myModuleName = $($myFile | Split-Path -Leaf) -replace '\.ezformat\.ps1', '' -replace '\.ezout\.ps1', '' +$myRoot = $myFile | Split-Path +Push-Location $myRoot +$Type = @{TypeName = 'OpenQA.Selenium.Remote.RemoteWebElement' } +$Typed = @{TypeName = 'OpenQA.Selenium.Remote.RemoteWebDriver' } +$formatting = @( + Write-FormatView @type -Property Tagname, Enabled, Displayed, Text -Width 7, 7, 9, 80 -AlignProperty @{Text = 'Left' } + Write-FormatView @type -AsList -Property Tagname, Text, Enabled, Selected, Location, Size, Displayed + + Write-FormatView -TypeName 'selenium-powershell/SeFrame' -Property 'TagName', 'Enabled', 'Name', 'Id' -VirtualProperty @{ + Name = { $_.Attributes.name } + Id = { $_.Attributes.id } + } + + Write-FormatView -TypeName 'selenium-powershell/SeInput' -Property 'Tagname','Type*','Enabled','Displayed','Text','Placeholder*','Value*' -VirtualProperty @{ + 'Type*' = {$_.Attributes.type} + 'Placeholder*' = {$_.Attributes.placeholder} + 'Value*' = {$_.Attributes.value} + } + + + # Add your own Write-FormatView here, + # or put them in a Formatting or Views directory + foreach ($potentialDirectory in 'Formatting', 'Views') { + Join-Path $myRoot $potentialDirectory | + Get-ChildItem -ea ignore | + Import-FormatView -FilePath { $_.Fullname } + } +) + +$destinationRoot = $myRoot + +if ($formatting) { + $myFormatFile = Join-Path $destinationRoot "formats/$myModuleName.format.ps1xml" + $formatting | Out-FormatData -Module $MyModuleName | Set-Content $myFormatFile -Encoding UTF8 +} + +$types = @( + Write-TypeView @Type -DefaultDisplay 'Tagname', 'Enabled', 'Displayed', 'Text' + Write-TypeView @Typed -ScriptProperty @{ + SeTitle = { if ($null -ne $this.SessionId) { $this.Title } } + SeUrl = { if ($null -ne $this.SessionId) { $this.Url } } + } -DefaultDisplay 'SeFriendlyName', 'SeBrowser', 'SeTitle', 'SeUrl' + + # Add your own Write-T + #TypeView statements here + # or declare them in the 'Types' directory + Join-Path $myRoot Types | + Get-Item -ea ignore | + Import-TypeView + +) + +if ($types) { + $myTypesFile = Join-Path $destinationRoot "types/$myModuleName.types.ps1xml" + $types | Out-TypeData | Set-Content $myTypesFile -Encoding UTF8 +} +Pop-Location + +$Content = Get-Content -Path $myFormatFile | Select -SkipLast 2 + +$SeSelectViewPath = Join-Path -Path $PSScriptRoot -ChildPath 'views/SeSelectValueInfo.ps1xml' +$EndOfFile = @' + + + +'@ +($Content | Out-String) + (Get-Content -Path $SeSelectViewPath -raw) + $EndOfFile | Out-File -Encoding utf8 $myFormatFile diff --git a/Selenium.build.ps1 b/Selenium.build.ps1 new file mode 100644 index 0000000..4945b4a --- /dev/null +++ b/Selenium.build.ps1 @@ -0,0 +1,144 @@ +task . Clean, Build, Tests, UpdateHelp, ExportHelp, Stats +task Tests ImportCompipledModule, Pester +task CreateManifest CopyPSD, UpdatPublicFunctionsToExport, CopyAdditionalFiles +task Build Compile, CreateManifest +task Stats WriteStats + +$script:ModuleName = 'Selenium' # Split-Path -Path $PSScriptRoot -Leaf +$script:ModuleRoot = $PSScriptRoot +$script:OutPutFolder = "$PSScriptRoot\Output" +$script:ModuleOutPutFolder = "$PSScriptRoot\Output\$script:ModuleName" +$script:ImportFolders = @('Public', 'Internal', 'Classes') +$script:PsmPath = Join-Path -Path $PSScriptRoot -ChildPath "Output\$($script:ModuleName)\$($script:ModuleName).psm1" +$script:PsdPath = Join-Path -Path $PSScriptRoot -ChildPath "Output\$($script:ModuleName)\$($script:ModuleName).psd1" +$script:HelpPath = Join-Path -Path $PSScriptRoot -ChildPath "Output\$($script:ModuleName)\en-US" + +$script:PublicFolder = 'Public' +$script:DSCResourceFolder = 'DSCResources' + + +task "Clean" { + if (-not(Test-Path $script:OutPutFolder)) { + New-Item -ItemType Directory -Path $script:OutPutFolder > $null + } + + Remove-Item -Path "$($script:OutPutFolder)\*" -Force -Recurse +} + +$compileParams = @{ + Inputs = { + foreach ($folder in $script:ImportFolders) { + Get-ChildItem -Path $folder -Recurse -File -Filter '*.ps1' + } + } + + Output = { + $script:PsmPath + } +} + +task Compile @compileParams { + if (Test-Path -Path $script:PsmPath) { + Remove-Item -Path $script:PsmPath -Recurse -Force + } + New-Item -Path $script:PsmPath -Force > $null + $currentFolder = Join-Path -Path $script:ModuleRoot -ChildPath 'Internal' + Get-Content -Path "$CurrentFolder\init.ps1" >> $script:PsmPath + foreach ($folder in $script:ImportFolders) { + $currentFolder = Join-Path -Path $script:ModuleRoot -ChildPath $folder + Write-Verbose -Message "Checking folder [$currentFolder]" + + if (Test-Path -Path $currentFolder) { + $files = Get-ChildItem -Path $currentFolder -File -Filter '*.ps1' + foreach ($file in $files) { + if ($file.Name -eq 'init.ps1' -and $folder -eq 'Internal') { continue } + Write-Verbose -Message "Adding $($file.FullName)" + Get-Content -Path $file.FullName >> $script:PsmPath + } + } + } + +} + +task CopyPSD { + New-Item -Path (Split-Path $script:PsdPath) -ItemType Directory -ErrorAction 0 + $copy = @{ + Path = "$($script:ModuleName).psd1" + Destination = $script:PsdPath + Force = $true + Verbose = $true + } + Copy-Item @copy +} + +task CopyAdditionalFiles { + + $CopyContainer = @{ + Container = $true + Recurse = $true + } + + $CopyFile = { Param($Name) Copy-Item -Path "$script:ModuleRoot\$Name" -Destination "$script:ModuleOutPutFolder\$Name" -Force -Verbose } + $CopyFolder = { Param($Name) Copy-Item -Path "$script:ModuleRoot\$Name" -Destination "$script:ModuleOutPutFolder" -Force -Verbose -Container -Recurse } + + & $CopyFolder 'assemblies' + & $CopyFolder 'types' + & $CopyFolder 'formats' + & $CopyFolder 'Examples' + + & $CopyFile 'SeleniumClasses.ps1' + & $CopyFile 'Selenium-Binary-Updater.ps1' + + & $CopyFile 'ChangeLog.md' + & $CopyFile 'README.md' + & $CopyFile 'Selenium.tests.ps1' + +} + +task UpdatPublicFunctionsToExport -if (Test-Path -Path $script:PublicFolder) { + $publicFunctions = (Get-ChildItem -Path $script:PublicFolder | + Select-Object -ExpandProperty BaseName) -join "', '" + + $publicFunctions = "FunctionsToExport = @('{0}')" -f $publicFunctions + + (Get-Content -Path $script:PsdPath) -replace "FunctionsToExport\s*?= '\*'", $publicFunctions | + Set-Content -Path $script:PsdPath +} + + + +task ImportCompipledModule -if (Test-Path -Path $script:PsmPath) { + Get-Module -Name $script:ModuleName | + Remove-Module -Force + Import-Module -Name $script:PsdPath -Force +} + +task Pester { + $resultFile = "{0}\testResults{1}.xml" -f $script:OutPutFolder, (Get-date -Format 'yyyyMMdd_hhmmss') + $testFolder = Join-Path -Path $PSScriptRoot -ChildPath 'Tests\*' + Invoke-Pester -Path $testFolder -OutputFile $resultFile -OutputFormat NUnitxml +} + + +task WriteStats { + $folders = Get-ChildItem -Directory | + Where-Object { $PSItem.Name -ne 'Output' } + + $stats = foreach ($folder in $folders) { + $files = Get-ChildItem "$($folder.FullName)\*" -File + if ($files) { + Get-Content -Path $files | + Measure-Object -Word -Line -Character | + Select-Object -Property @{N = "FolderName"; E = { $folder.Name } }, Words, Lines, Characters + } + } + $stats | ConvertTo-Json > "$script:OutPutFolder\stats.json" +} + +task UpdateHelp -if (Test-Path -Path "$Script:ModuleRoot\Help") { + Update-MarkdownHelpModule -Path "$Script:ModuleRoot\Help" -ModulePagePath "$Script:ModuleRoot\Help\README.MD" -RefreshModulePage +} + +task ExportHelp -if (Test-Path -Path "$script:ModuleRoot\Help") { + New-ExternalHelp -Path "$script:ModuleRoot\Help" -OutputPath $script:HelpPath +} \ No newline at end of file diff --git a/Selenium.psd1 b/Selenium.psd1 index 391fbac..dcaa88a 100644 --- a/Selenium.psd1 +++ b/Selenium.psd1 @@ -5,139 +5,88 @@ # # Generated on: 8/31/2018 # +# Modified James O'Neill 30 Nov 2019 @{ - -# Script module or binary module file associated with this manifest. -RootModule = '.\Selenium.psm1' - -# Version number of this module. -ModuleVersion = '2.3.1' - -# Supported PSEditions -# CompatiblePSEditions = @() - -# ID used to uniquely identify this module -GUID = 'a3bdb8c3-c150-48a8-b56d-cd4d43f46a26' - -# Author of this module -Author = 'Adam Driscoll' - -# Company or vendor of this module -CompanyName = 'Unknown' - -# Copyright statement for this module -Copyright = '(c) 2019 Adam Driscoll. All rights reserved.' - -# Description of the functionality provided by this module -Description = 'Web automation using the Selenium Web Driver' - -# Minimum version of the Windows PowerShell engine required by this module -# PowerShellVersion = '' - -# Name of the Windows PowerShell host required by this module -# PowerShellHostName = '' - -# Minimum version of the Windows PowerShell host required by this module -# PowerShellHostVersion = '' - -# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. -# DotNetFrameworkVersion = '' - -# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. -# CLRVersion = '' - -# Processor architecture (None, X86, Amd64) required by this module -# ProcessorArchitecture = '' - -# Modules that must be imported into the global environment prior to importing this module -# RequiredModules = @() - -# Assemblies that must be loaded prior to importing this module -# RequiredAssemblies = @() - -# Script files (.ps1) that are run in the caller's environment prior to importing this module. -# ScriptsToProcess = @() - -# Type files (.ps1xml) to be loaded when importing this module -# TypesToProcess = @() - -# Format files (.ps1xml) to be loaded when importing this module -# FormatsToProcess = @() - -# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess -# NestedModules = @() - -# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = @( - "Enter-SeUrl", - "Find-SeElement", - "Get-SeCookie", - "Get-SeElementAttribute", - "Invoke-SeClick", - "Invoke-SeScreenshot", - "Remove-SeCookie", - "Save-SeScreenshot", - "Get-SeKeys", - "Send-SeKeys", - "Set-SeCookie", - "Start-SeChrome", - "Start-SeFirefox", - "Start-SeInternetExplorer", - "Start-SeEdge", - "Stop-SeDriver", - "Get-SeWindow", - "Switch-SeWindow" -) - -# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. -CmdletsToExport = '*' - -# Variables to export from this module -VariablesToExport = '*' - -# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. -AliasesToExport = '*' - -# DSC resources to export from this module -# DscResourcesToExport = @() - -# List of all modules packaged with this module -# ModuleList = @() - -# List of all files packaged with this module -# FileList = @() - -# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. -PrivateData = @{ - - PSData = @{ - - # Tags applied to this module. These help with module discovery in online galleries. - Tags = @('selenium', 'automation', 'web') - - # A URL to the license for this module. - LicenseUri = 'https://github.com/adamdriscoll/selenium-powershell/blob/master/LICENSE' - - # A URL to the main website for this project. - ProjectUri = 'https://github.com/adamdriscoll/selenium-powershell' - - # A URL to an icon representing this module. - # IconUri = '' - - # ReleaseNotes of this module - ReleaseNotes = 'Updating WebDrivers for Selenium' - - #Prerelease = 'beta1' - - } # End of PSData hashtable - -} # End of PrivateData hashtable - -# HelpInfo URI of this module -# HelpInfoURI = '' - -# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. -# DefaultCommandPrefix = '' + ModuleVersion = '4.0.0' + GUID = 'a3bdb8c3-c150-48a8-b56d-cd4d43f46a26' + Author = 'Adam Driscoll' + CompanyName = 'Unknown' + Copyright = '(c) 2020 Adam Driscoll. All rights reserved.' + Description = 'Web automation using the Selenium Web Driver' + ScriptsToProcess = @('SeleniumClasses.ps1') + RootModule = 'Selenium.psm1' + RequiredAssemblies = @('./assemblies/WebDriver.dll', './assemblies/WebDriver.Support.dll') + FunctionsToExport = '*' + AliasesToExport = @() + CmdletsToExport = @() + VariablesToExport = @() + DscResourcesToExport = @() + FileList = @('.\assemblies', + '.\Examples', + '.\ChangeLog.md', + '.\README.md', + '.\Selenium.psm1' + '.\Selenium.tests.ps1' + '.\Selenium-Binary-Updater.ps1') + + PrivateData = @{ + PSData = @{ + Tags = @('selenium', 'automation', 'web') + LicenseUri = 'https://github.com/adamdriscoll/selenium-powershell/blob/master/LICENSE' + ProjectUri = 'https://github.com/adamdriscoll/selenium-powershell' + ReleaseNotes = 'Updating WebDrivers for Selenium' + + # A URL to an icon representing this module. + # IconUri = '' + Prerelease = 'preview3' + } # End of PSData hashtable + + } # End of PrivateData hashtable + + # Supported PSEditions + # CompatiblePSEditions = @() + + # Minimum version of the Windows PowerShell engine required by this module + # PowerShellVersion = '' + + # Name of the Windows PowerShell host required by this module + # PowerShellHostName = '' + + # Minimum version of the Windows PowerShell host required by this module + # PowerShellHostVersion = '' + + # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # DotNetFrameworkVersion = '' + + # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # CLRVersion = '' + + # Processor architecture (None, X86, Amd64) required by this module + # ProcessorArchitecture = '' + + # Modules that must be imported into the global environment prior to importing this module + # RequiredModules = @() + + #Type files (.ps1xml) to be loaded when importing this module + TypesToProcess = @('types/Selenium.types.ps1xml') + + # Format files (.ps1xml) to be loaded when importing this module + FormatsToProcess = @('formats/Selenium.format.ps1xml') + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() + + # List of all modules packaged with this module + # ModuleList = @() + + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + + # HelpInfo URI of this module + # HelpInfoURI = '' + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' } diff --git a/Selenium.psm1 b/Selenium.psm1 index bcd73f3..4292929 100644 --- a/Selenium.psm1 +++ b/Selenium.psm1 @@ -1,548 +1,22 @@ -[System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\assemblies\WebDriver.dll") -[System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\assemblies\WebDriver.Support.dll") - -if($IsLinux){ - $AssembliesPath = "$PSScriptRoot/assemblies/linux" -} -elseif($IsMacOS){ - $AssembliesPath = "$PSScriptRoot/assemblies/macos" -} - -# Grant Execution permission to assemblies on Linux and MacOS -if($IsLinux -or $IsMacOS){ - # Check if powershell is NOT running as root - $AssemblieFiles = Get-ChildItem -Path $AssembliesPath |Where-Object{$_.Name -eq 'chromedriver' -or $_.Name -eq 'geckodriver'} - foreach($AssemblieFile in $AssemblieFiles){ - if($IsLinux){ - $FileMod = stat -c "%a" $AssemblieFile.fullname - } - elseif($IsMacOS){ - $FileMod = /usr/bin/stat -f "%A" $AssemblieFile.fullname - } - - if($FileMod[2] -ne '5' -and $FileMod[2] -ne '7' ){ - Write-Host "Granting $($AssemblieFile.fullname) Execution Permissions ..." - chmod +x $AssemblieFile.fullname - } - } -} - -function Validate-URL{ - param( - [Parameter(Mandatory=$true)]$URL - ) - $Out = $null - [uri]::TryCreate($URL,[System.UriKind]::Absolute, [ref]$Out) -} - -function Start-SeChrome { - Param( - [Parameter(Mandatory = $false)] - [array]$Arguments, - [switch]$HideVersionHint, - [string]$StartURL, - [System.IO.FileInfo]$DefaultDownloadPath, - [System.IO.FileInfo]$ProfileDirectoryPath, - [bool]$DisableBuiltInPDFViewer=$true, - [switch]$Headless, - [switch]$Incognito, - [switch]$Maximized, - [switch]$Minimized, - [switch]$Fullscreen, - [System.IO.FileInfo]$ChromeBinaryPath - ) - - BEGIN{ - if($Maximized -ne $false -and $Minimized -ne $false){ - throw 'Maximized and Minimized may not be specified together.' - } - elseif($Maximized -ne $false -and $Fullscreen -ne $false){ - throw 'Maximized and Fullscreen may not be specified together.' - } - elseif($Minimized -ne $false -and $Fullscreen -ne $false){ - throw 'Minimized and Fullscreen may not be specified together.' - } - - if($StartURL){ - if(!(Validate-URL -URL $StartURL)){ - throw 'Incorrect StartURL please make sure the URL starts with http:// or https://' - } - } - } - PROCESS{ - $Chrome_Options = New-Object -TypeName "OpenQA.Selenium.Chrome.ChromeOptions" +$functionFolders = @('Classes', 'Public', 'Internal') +. (Join-Path -Path $PSScriptRoot -ChildPath 'Internal/init.ps1') +ForEach ($folder in $functionFolders) { + $folderPath = Join-Path -Path $PSScriptRoot -ChildPath $folder - 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($ChromeBinaryPath){ - Write-Verbose "Setting Chrome Binary directory: $ChromeBinaryPath" - $Chrome_Options.BinaryLocation ="$ChromeBinaryPath" - } - - - if($DisableBuiltInPDFViewer){ - $Chrome_Options.AddUserProfilePreference('plugins', @{'always_open_pdf_externally' = $true;}) - } + If (Test-Path -Path $folderPath) { - 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($Arguments){ - foreach ($Argument in $Arguments){ - $Chrome_Options.AddArguments($Argument) - } - } - - if(!$HideVersionHint){ - Write-Verbose "Download the right chromedriver from 'http://chromedriver.chromium.org/downloads'" - } - - if($IsLinux -or $IsMacOS){ - $Driver = New-Object -TypeName "OpenQA.Selenium.Chrome.ChromeDriver" -ArgumentList $AssembliesPath,$Chrome_Options + Write-Verbose -Message "Importing from $folder" + $functions = Get-ChildItem -Path $folderPath -Filter '*.ps1' + ForEach ($function in $functions) { + Write-Verbose -Message " Importing $($function.BaseName)" + . $($function.FullName) } - else{ - $Driver = New-Object -TypeName "OpenQA.Selenium.Chrome.ChromeDriver" -ArgumentList $Chrome_Options - } - - if($Minimized -and $Driver){ - $driver.Manage().Window.Minimize(); - } - - if($Headless -and $DefaultDownloadPath -and $Driver){ - $HeadlessDownloadParams = New-Object 'system.collections.generic.dictionary[[System.String],[System.Object]]]' - $HeadlessDownloadParams.Add('behavior', 'allow') - $HeadlessDownloadParams.Add('downloadPath', $DefaultDownloadPath.FullName) - $Driver.ExecuteChromeCommand('Page.setDownloadBehavior', $HeadlessDownloadParams) - } - - if($StartURL -and $Driver){ - Enter-SeUrl -Driver $Driver -Url $StartURL - } - } - END{ - return $Driver - } + } } -function Start-SeInternetExplorer { - $InternetExplorer_Options = New-Object -TypeName "OpenQA.Selenium.IE.InternetExplorerOptions" - $InternetExplorer_Options.IgnoreZoomLevel = $true - New-Object -TypeName "OpenQA.Selenium.IE.InternetExplorerDriver" -ArgumentList $InternetExplorer_Options +$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = { + Get-SeDriver | Stop-SeDriver } -function Start-SeEdge { - New-Object -TypeName "OpenQA.Selenium.Edge.EdgeDriver" -} - -function Start-SeFirefox { - param( - [array]$Arguments, - [string]$StartURL, - [System.IO.FileInfo]$DefaultDownloadPath, - [switch]$Headless, - [switch]$PrivateBrowsing, - [switch]$Maximized, - [switch]$Minimized, - [switch]$Fullscreen, - [switch]$SuppressLogging - ) - - BEGIN{ - if($Maximized -ne $false -and $Minimized -ne $false){ - throw 'Maximized and Minimized may not be specified together.' - } - elseif($Maximized -ne $false -and $Fullscreen -ne $false){ - throw 'Maximized and Fullscreen may not be specified together.' - } - elseif($Minimized -ne $false -and $Fullscreen -ne $false){ - throw 'Minimized and Fullscreen may not be specified together.' - } - - if($StartURL){ - if(!(Validate-URL -URL $StartURL)){ - throw 'Incorrect StartURL please make sure the URL starts with http:// or https://' - } - } - } - PROCESS{ - $Firefox_Options = New-Object -TypeName "OpenQA.Selenium.Firefox.FirefoxOptions" - - 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($IsLinux -or $IsMacOS){ - $Driver = New-Object -TypeName "OpenQA.Selenium.Firefox.FirefoxDriver" -ArgumentList $AssembliesPath,$Firefox_Options - } - else{ - $Driver = New-Object -TypeName "OpenQA.Selenium.Firefox.FirefoxDriver" -ArgumentList $Firefox_Options - } - - if($Driver){ - $Driver.Manage().Timeouts().ImplicitWait = [TimeSpan]::FromSeconds(10) - } - - if($Minimized -and $Driver){ - $Driver.Manage().Window.Minimize() - } - - if($Maximized -and $Driver){ - $Driver.Manage().Window.Maximize() - } - - if($Fullscreen -and $Driver){ - $Driver.Manage().Window.FullScreen() - } - - if($StartURL -and $Driver){ - Enter-SeUrl -Driver $Driver -Url $StartURL - } - } - END{ - return $Driver - } -} - -function Stop-SeDriver { - param($Driver) - - $Driver.Dispose() -} - -function Enter-SeUrl { - param($Driver, $Url) - - $Driver.Navigate().GoToUrl($Url) -} - -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 ($Driver -ne $null -and $Element -ne $null) { - throw "Driver and Element may not be specified together." - } - elseif ($Driver -ne $Null) { - $Target = $Driver - } - elseif ($Element -ne $Null) { - $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 Invoke-SeClick { - param( - [Parameter(Mandatory = $true, ValueFromPipeline = $true)] - [OpenQA.Selenium.IWebElement]$Element, - [Parameter()] - [Switch]$JavaScriptClick, - [Parameter()] - $Driver - ) - - if ($JavaScriptClick) { - $Driver.ExecuteScript("arguments[0].click()", $Element) - } - else { - $Element.Click() - } - -} - -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([OpenQA.Selenium.IWebElement]$Element, [string]$Keys) - - foreach ($Key in @(Get-SeKeys).Name) { - $Keys = $Keys -replace "{{$Key}}", [OpenQA.Selenium.Keys]::$Key - } - - $Element.SendKeys($Keys) -} - -function Get-SeCookie { - param($Driver) - - $Driver.Manage().Cookies.AllCookies.GetEnumerator() -} - -function Remove-SeCookie { - param( - $Driver, - [switch]$DeleteAllCookies, - [string]$Name - ) - - if($DeleteAllCookies){ - $Driver.Manage().Cookies.DeleteAllCookies() - } - else{ - $Driver.Manage().Cookies.DeleteCookieNamed($Name) - } -} - -function Set-SeCookie { - param( - [ValidateNotNull()]$Driver, - [string]$Name, - [string]$Value, - [string]$Path, - [string]$Domain, - $ExpiryDate - ) - - <# 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) - Initializes a new instance of the Cookie class with a specific name, value, path and expiration date. - Cookie(String, String, String, String, Nullable) - Initializes a new instance of the Cookie class with a specific name, value, domain, path and expiration date. - #> - Begin{ - if($ExpiryDate -ne $null -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 = New-Object -TypeName OpenQA.Selenium.Cookie -ArgumentList $Name,$Value - } - Elseif($Name -and $Value -and $Path -and (!$Domain -and !$ExpiryDate)){ - $cookie = New-Object -TypeName OpenQA.Selenium.Cookie -ArgumentList $Name,$Value,$Path - } - Elseif($Name -and $Value -and $Path -and $ExpiryDate -and !$Domain){ - $cookie = New-Object -TypeName OpenQA.Selenium.Cookie -ArgumentList $Name,$Value,$Path,$ExpiryDate - } - Elseif($Name -and $Value -and $Path -and $Domain -and (!$ExpiryDate -or $ExpiryDate)){ - if($Driver.Url -match $Domain){ - $cookie = New-Object -TypeName OpenQA.Selenium.Cookie -ArgumentList $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) - Initializes a new instance of the Cookie class with a specific name, value, path and expiration date. - Cookie(String, String, String, String, Nullable) - Initializes a new instance of the Cookie class with a specific name, value, domain, path and expiration date." - } - - $Driver.Manage().Cookies.AddCookie($cookie) - } -} - -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($Driver, [Switch]$AsBase64EncodedString) - - $Screenshot = [OpenQA.Selenium.Support.Extensions.WebDriverExtensions]::TakeScreenshot($Driver) - 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 Get-SeWindow { - param( - [Parameter(Mandatory = $true)][OpenQA.Selenium.IWebDriver]$Driver - ) - - Process { - $Driver.WindowHandles - } -} - -function Switch-SeWindow { - param( - [Parameter(Mandatory = $true)][OpenQA.Selenium.IWebDriver]$Driver, - [Parameter(Mandatory = $true)]$Window - ) - - Process { - $Driver.SwitchTo().Window($Window)|Out-Null - } -} +$publicFunctions = (Get-ChildItem -Path "$PSScriptRoot\Public" -Filter '*.ps1').BaseName +Export-ModuleMember -Function $publicFunctions diff --git a/Selenium.tests.ps1 b/Selenium.tests.ps1 index ed5c9db..3d181eb 100644 --- a/Selenium.tests.ps1 +++ b/Selenium.tests.ps1 @@ -4,67 +4,67 @@ Describe "Verify the Binaries SHA256 Hash" { It "Check WebDriver.dll Hash"{ # VirusTotal Scan URL = https://www.virustotal.com/gui/file/0ee619b1786cf5971c0f9c6ee1859497aecba93a4953cf92fea998e8eefadf3c/detection $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\WebDriver.dll).Hash - $Hash |Should Be (Get-Content -Path $PSScriptRoot\assemblies\WebDriver.dll.sha256) + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\WebDriver.dll.sha256) } It "Check WebDriver.Support.dll Hash" { # VirusTotal Scan URL = https://www.virustotal.com/gui/file/b59ba7d0cffe43e722b13ad737cf596f030788b86b5b557cb479f0b6957cce8a/detection $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\WebDriver.Support.dll).Hash - $Hash |Should Be (Get-Content -Path $PSScriptRoot\assemblies\WebDriver.Support.dll.sha256) + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\WebDriver.Support.dll.sha256) } It "Check ChromeDriver.exe Hash" { # VirusTotal Scan URL = https://www.virustotal.com/gui/file/c5c852d8f0890eb8c0b77fed623a3c36f50434552e9623e47fadf1e445f2f772/detection $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\chromedriver.exe).Hash - $Hash |Should Be (Get-Content -Path $PSScriptRoot\assemblies\chromedriver.exe.sha256) + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\chromedriver.exe.sha256) } - + It "Check ChromeDriver Linux Hash" { # VirusTotal Scan URL = https://www.virustotal.com/gui/file/ed50bce67a54727b7bf323d588d62be699233a75300d24c92409499a9329b2e6/detection $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\linux\chromedriver).Hash - $Hash |Should Be (Get-Content -Path $PSScriptRoot\assemblies\linux\chromedriver.sha256) + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\linux\chromedriver.sha256) } It "Check ChromeDriver MacOS Hash" { # VirusTotal Scan URL = https://www.virustotal.com/gui/file/6bb2996ebdeea6b2d10e6a9397ff53c394ebbaa8388087f134a4bc10f532863c/detection $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\macos\chromedriver).Hash - $Hash |Should Be (Get-Content -Path $PSScriptRoot\assemblies\macos\chromedriver.sha256) + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\macos\chromedriver.sha256) } It "Check GeckoDriver.exe Hash" { # VirusTotal Scan URL = https://www.virustotal.com/gui/file/255c9d3571c86841213f49b26d176a6ad440be8c720e3c2d9226076adf4f603d/detection $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\geckodriver.exe).Hash - $Hash |Should Be (Get-Content -Path $PSScriptRoot\assemblies\geckodriver.exe.sha256) + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\geckodriver.exe.sha256) } It "Check GeckoDriver Linux Hash" { # VirusTotal Scan URL = https://www.virustotal.com/gui/file/6590e3b9d9bf292c8df50b6df5bcf8a5191d999f9e48f68aa2055eb5746b2c05/detection $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\linux\geckodriver).Hash - $Hash |Should Be (Get-Content -Path $PSScriptRoot\assemblies\linux\geckodriver.sha256) + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\linux\geckodriver.sha256) } It "Check GeckoDriver MacOS Hash" { # VirusTotal Scan URL = https://www.virustotal.com/gui/file/d62c2178377addeb1bb860426b2c9b10b68d2eeabf0c521529a4a6a7b1e208c4/detection $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\macos\geckodriver).Hash - $Hash |Should Be (Get-Content -Path $PSScriptRoot\assemblies\macos\geckodriver.sha256) + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\macos\geckodriver.sha256) } It "Check IEDriverServer.exe Hash" { # VirusTotal Scan URL = https://www.virustotal.com/gui/file/a1e26b0e8cb5f8db1cd784bac71bbf540485d81e697293b0b4586e25a31a8187/detection - this driver seems to have 2 false positives and is marked as clean in the comments $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\IEDriverServer.exe).Hash - $Hash |Should Be (Get-Content -Path $PSScriptRoot\assemblies\IEDriverServer.exe.sha256) + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\IEDriverServer.exe.sha256) } It "Check MicrosoftWebDriver.exe Hash" { # VirusTotal Scan URL = https://www.virustotal.com/gui/file/6e8182697ea5189491b5519d8496a3392e43741b7c0515130f2f8205881d208e/detection $Hash = (Get-FileHash -Algorithm SHA256 -Path $PSScriptRoot\assemblies\MicrosoftWebDriver.exe).Hash - $Hash |Should Be (Get-Content -Path $PSScriptRoot\assemblies\MicrosoftWebDriver.exe.sha256) + $Hash | Should -Be (Get-Content -Path $PSScriptRoot\assemblies\MicrosoftWebDriver.exe.sha256) } } Describe "Start-SeChrome" { Context "Should Start Chrome Driver" { - $Driver = Start-SeChrome + $Driver = Start-SeChrome Stop-SeDriver $Driver } } @@ -95,7 +95,7 @@ Describe "Start-SeChrome with Options" { $Driver = Start-SeChrome -Incognito Stop-SeDriver $Driver } - + It "Start Chrome Fullscreen" { $Driver = Start-SeChrome -Fullscreen Stop-SeDriver $Driver @@ -115,7 +115,7 @@ Describe "Start-SeChrome with Options" { Describe "Start-SeFirefox"{ Context "Should Start Firefox Driver" { - $Driver = Start-SeFirefox + $Driver = Start-SeFirefox Stop-SeDriver $Driver } } @@ -146,7 +146,7 @@ Describe "Start-SeFirefox with Options" { $Driver = Start-SeFirefox -PrivateBrowsing Stop-SeDriver $Driver } - + It "Start Firefox Fullscreen" { $Driver = Start-SeFirefox -Fullscreen Stop-SeDriver $Driver @@ -167,7 +167,7 @@ Describe "Start-SeFirefox with Options" { Describe "Start-SeEdge" { Context "Should Start Edge Driver" { if(!$IsLinux -and !$IsMacOS){ - $Driver = Start-SeEdge + $Driver = Start-SeEdge Stop-SeDriver $Driver } } @@ -176,7 +176,7 @@ Describe "Start-SeEdge" { Describe "Start-SeInternetExplorer" { Context "Should Start InternetExplorer Driver" { if(!$IsLinux -and !$IsMacOS){ - $Driver = Start-SeInternetExplorer + $Driver = Start-SeInternetExplorer Stop-SeDriver $Driver } } @@ -212,7 +212,7 @@ Describe "Find-SeElement Firefox" { $SearchInput = Find-SeElement -Driver $Driver -Css "input[name='q']" } } - + Context "Find-SeElement -Wait" { It "By Name"{ $SearchInput = Find-SeElement -Driver $Driver -Wait -Name q -Timeout 60 diff --git a/SeleniumClasses.ps1 b/SeleniumClasses.ps1 new file mode 100644 index 0000000..baac8df --- /dev/null +++ b/SeleniumClasses.ps1 @@ -0,0 +1,144 @@ +using namespace system.Collections +using namespace System.Collections.Generic +using namespace System.Management.Automation +using namespace System.Management.Automation.Language + +if ('ValidateURIAttribute' -as [type]) { + class ValidateURIAttribute : System.Management.Automation.ValidateArgumentsAttribute { + [void] Validate([object] $arguments , [System.Management.Automation.EngineIntrinsics]$EngineIntrinsics) { + $Out = $null + if ([uri]::TryCreate($arguments, [System.UriKind]::Absolute, [ref]$Out)) { return } + else { throw [System.Management.Automation.ValidationMetadataException]::new('Incorrect StartURL please make sure the URL starts with http:// or https://') } + return + } + } + class ValidateURI : ValidateURIAttribute {} +} + + +if ('ValidateIsWebDriverAttribute' -as [type]) { + class ValidateIsWebDriverAttribute : System.Management.Automation.ValidateArgumentsAttribute { + [void] Validate([object] $arguments , [System.Management.Automation.EngineIntrinsics]$EngineIntrinsics) { + if ($arguments -isnot [OpenQA.Selenium.Remote.RemoteWebDriver]) { + throw [System.Management.Automation.ValidationMetadataException]::new('Target was not a valid web driver') + } + return + } + } + class ValidateIsWebDriver : ValidateIsWebDriverAttribute {} +} + + + +if ('OperatorTransformAttribute' -as [type]) { + #Allow operator to use containing, matching, matches, equals etc. + class OperatorTransformAttribute : System.Management.Automation.ArgumentTransformationAttribute { + [object] Transform([System.Management.Automation.EngineIntrinsics]$EngineIntrinsics, [object] $InputData) { + if ($inputData -match '^(contains|like|notlike|match|notmatch|eq|ne|gt|lt)$') { + return $InputData + } + switch -regex ($InputData) { + "^contain" { return 'contains' ; break } + "^match" { return 'match' ; break } + "^n\w*match" { return 'notmatch' ; break } + "^eq" { return 'eq' ; break } + "^n\w*eq" { return 'ne' ; break } + "^n\w*like" { return 'like' ; break } + } + return $InputData + } + } + + class OperatorTransform : OperatorTransformAttribute {} +} + +$dll1Path = Join-path -path (Join-path -path $PSScriptRoot -ChildPath 'assemblies') -ChildPath 'WebDriver.dll' +$dll2Path = Join-path -path (Join-path -path $PSScriptRoot -ChildPath 'assemblies') -ChildPath 'WebDriver.Support.dll' + +Add-type @" +using OpenQA.Selenium; +using OpenQA.Selenium.Support.UI; +using System.Collections.Generic; +namespace SeleniumSelection { + public class Option { + public static bool IsMultiSelect(IWebElement element) { + var selection = new SelectElement(element); + return selection.IsMultiple; + } + public static IList GetOptions(IWebElement element) { + var selection = new SelectElement(element); + return selection.Options; + } + public static void SelectByValue(IWebElement element, string value) { + var selection = new SelectElement(element); + selection.SelectByValue(value); + } + public static void DeselectByValue(IWebElement element, string value) { + var selection = new SelectElement(element); + selection.DeselectByValue(value); + } + public static void SelectByText(IWebElement element, string text, bool partialMatch = false) { + var selection = new SelectElement(element); + selection.SelectByText(text,partialMatch); + } + public static void DeselectByText(IWebElement element, string text) { + var selection = new SelectElement(element); + selection.DeselectByText(text); + } + public static void SelectByIndex(IWebElement element, int index) { + var selection = new SelectElement(element); + selection.SelectByIndex(index); + } + public static void DeselectByIndex(IWebElement element, int index) { + var selection = new SelectElement(element); + selection.DeselectByIndex(index); + } + public static void DeselectAll(IWebElement element) { + var selection = new SelectElement(element); + selection.DeselectAll(); + } + public static IWebElement GetSelectedOption(IWebElement element) { + var selection = new SelectElement(element); + return selection.SelectedOption; + } + public static IList GetAllSelectedOptions(IWebElement element) { + var selection = new SelectElement(element); + return selection.AllSelectedOptions; + } + } +} +"@ -ReferencedAssemblies $dll1Path, $dll2Path, mscorlib + + +enum SeBrowsers { + Chrome + Edge + Firefox + InternetExplorer + MSEdge +} + +enum SeWindowState { + Headless + Default + Minimized + Maximized + Fullscreen +} + +enum SeBySelector { + ClassName + CssSelector + Id + LinkText + PartialLinkText + Name + TagName + XPath +} + +enum SeBySelect { + Index + Text + Value +} \ No newline at end of file diff --git a/Tests/selenium-powershell.tests.ps1 b/Tests/selenium-powershell.tests.ps1 new file mode 100644 index 0000000..c19b6c2 --- /dev/null +++ b/Tests/selenium-powershell.tests.ps1 @@ -0,0 +1,20 @@ +$moduleRoot = Resolve-Path "$PSScriptRoot\.." +$moduleName = Split-Path $moduleRoot -Leaf + +Describe "General project validation: $moduleName" { + + $scripts = Get-ChildItem $moduleRoot -Include *.ps1, *.psm1, *.psd1 -Recurse + + # TestCases are splatted to the script so we need hashtables + $testCase = $scripts | Foreach-Object {@{file = $_}} + It "Script should be valid powershell" -TestCases $testCase { + param($file) + + $file.fullname | Should Exist + + $contents = Get-Content -Path $file.fullname -ErrorAction Stop + $errors = $null + $null = [System.Management.Automation.PSParser]::Tokenize($contents, [ref]$errors) + $errors.Count | Should Be 0 + } +} \ No newline at end of file diff --git a/Views/SeSelectValueInfo.ps1xml b/Views/SeSelectValueInfo.ps1xml new file mode 100644 index 0000000..cb1b20d --- /dev/null +++ b/Views/SeSelectValueInfo.ps1xml @@ -0,0 +1,38 @@ + + SeSelectValueInfo + + selenium-powershell/SeSelectValueInfo + + + + + + + IsMultiSelect + + + + + + + ($_.Items.Count -ne 0) + + + + $output = [System.Text.StringBuilder]::new(); + $TextMax = ($_.Items.Text | Measure-Object -Maximum).Maximum.length + $ValueMax = ($_.Items.Value | Measure-Object -Maximum).Maximum.length + [void]($Output.AppendFormat("Index {0} {1} Selected`n", 'Text'.PadRight($TextMax, ' '), 'Value'.PadRight($ValueMax, ' '))) + [void]($Output.AppendFormat("----- {0} {1} --------`n", '----'.PadRight($TextMax, ' '), '-----'.PadRight($ValueMax, ' '))) + foreach ($I in $_.Items) { + $IsSelected = if ($I.Selected) {" *"} else {''} + [Void]($output.AppendFormat("{0} {1} {2} {3}`n", "$($I.Index)".PadLeft(5, ' '), "$($I.Text)".PadRight($TextMax, ' '), "$($I.Value)".PadRight($ValueMax, ' '), $IsSelected)) + }; + $output.ToString().Trim("`n"); + + + + + + + \ No newline at end of file diff --git a/assemblies/IEDriverServer.exe b/assemblies/IEDriverServer.exe index d4890e2..d5d6ada 100644 Binary files a/assemblies/IEDriverServer.exe and b/assemblies/IEDriverServer.exe differ diff --git a/assemblies/IEDriverServer.exe.sha256 b/assemblies/IEDriverServer.exe.sha256 index 9573b7c..7a01c45 100644 --- a/assemblies/IEDriverServer.exe.sha256 +++ b/assemblies/IEDriverServer.exe.sha256 @@ -1 +1 @@ -A1E26B0E8CB5F8DB1CD784BAC71BBF540485D81E697293B0B4586E25A31A8187 +51053574E3BA3AB5D9F47E13EC0E9961AD6C9C9978DC851BE71C0F86A272C74B diff --git a/assemblies/MicrosoftWebDriver.exe b/assemblies/MicrosoftWebDriver.exe deleted file mode 100644 index 56d386b..0000000 Binary files a/assemblies/MicrosoftWebDriver.exe and /dev/null differ diff --git a/assemblies/MicrosoftWebDriver.exe.sha256 b/assemblies/MicrosoftWebDriver.exe.sha256 deleted file mode 100644 index 5bd6923..0000000 --- a/assemblies/MicrosoftWebDriver.exe.sha256 +++ /dev/null @@ -1 +0,0 @@ -6E8182697EA5189491B5519D8496A3392E43741B7C0515130F2F8205881D208E diff --git a/assemblies/chromedriver.exe b/assemblies/chromedriver.exe index ec9ce29..14e61bc 100644 Binary files a/assemblies/chromedriver.exe and b/assemblies/chromedriver.exe differ diff --git a/assemblies/chromedriver.exe.sha256 b/assemblies/chromedriver.exe.sha256 index d3080b3..e9f7251 100644 --- a/assemblies/chromedriver.exe.sha256 +++ b/assemblies/chromedriver.exe.sha256 @@ -1 +1 @@ -C5C852D8F0890EB8C0B77FED623A3C36F50434552E9623E47FADF1E445F2F772 +C6131A3106A8956702459673BDCC7F37BDD8989A141D2CBE15DC0157F0D53C74 diff --git a/assemblies/geckodriver.exe b/assemblies/geckodriver.exe index 9fae8e0..4ce451b 100644 Binary files a/assemblies/geckodriver.exe and b/assemblies/geckodriver.exe differ diff --git a/assemblies/geckodriver.exe.sha256 b/assemblies/geckodriver.exe.sha256 index 2b051b9..e43d884 100644 --- a/assemblies/geckodriver.exe.sha256 +++ b/assemblies/geckodriver.exe.sha256 @@ -1 +1 @@ -255C9D3571C86841213F49B26D176A6AD440BE8C720E3C2D9226076ADF4F603D +FAED02EC5B0D6246856843D10EE020CB5121B8261AC939BE761130F21A73D3EE diff --git a/assemblies/linux/chromedriver b/assemblies/linux/chromedriver index eeecd35..68b4075 100755 Binary files a/assemblies/linux/chromedriver and b/assemblies/linux/chromedriver differ diff --git a/assemblies/linux/chromedriver.sha256 b/assemblies/linux/chromedriver.sha256 index b4b34aa..4eb67e6 100644 --- a/assemblies/linux/chromedriver.sha256 +++ b/assemblies/linux/chromedriver.sha256 @@ -1 +1 @@ -ED50BCE67A54727B7BF323D588D62BE699233A75300D24C92409499A9329B2E6 +01112975217552167F101D7B549D31A12B3C45ABE411892F92228BF8CB2F0058 diff --git a/assemblies/linux/geckodriver b/assemblies/linux/geckodriver index ff08a41..bf9538e 100755 Binary files a/assemblies/linux/geckodriver and b/assemblies/linux/geckodriver differ diff --git a/assemblies/linux/geckodriver.sha256 b/assemblies/linux/geckodriver.sha256 index 6d92a3d..930beaa 100644 --- a/assemblies/linux/geckodriver.sha256 +++ b/assemblies/linux/geckodriver.sha256 @@ -1 +1 @@ -6590E3B9D9BF292C8DF50B6DF5BCF8A5191D999F9E48F68AA2055EB5746B2C05 +0B2C9B9791925DCEA2981CBDFAB8274FB4668BF65D6A57C2257E8B57757C394A diff --git a/assemblies/macos/chromedriver b/assemblies/macos/chromedriver index 4ff3bcc..f4bfcc6 100644 Binary files a/assemblies/macos/chromedriver and b/assemblies/macos/chromedriver differ diff --git a/assemblies/macos/chromedriver.sha256 b/assemblies/macos/chromedriver.sha256 index 00e419c..27ca9d8 100644 --- a/assemblies/macos/chromedriver.sha256 +++ b/assemblies/macos/chromedriver.sha256 @@ -1 +1 @@ -6BB2996EBDEEA6B2D10E6A9397FF53C394EBBAA8388087F134A4BC10F532863C +1DA3E0CBF79A92CF06B08812A39991A37B5C5458DEC2A7B4FFF34F6D87126281 diff --git a/assemblies/macos/geckodriver b/assemblies/macos/geckodriver index 83a86e1..4a2671f 100755 Binary files a/assemblies/macos/geckodriver and b/assemblies/macos/geckodriver differ diff --git a/assemblies/macos/geckodriver.sha256 b/assemblies/macos/geckodriver.sha256 index 449827d..ac73b7f 100644 --- a/assemblies/macos/geckodriver.sha256 +++ b/assemblies/macos/geckodriver.sha256 @@ -1 +1 @@ -D62C2178377ADDEB1BB860426B2C9B10B68D2EEABF0C521529A4A6A7B1E208C4 +AA2FCE6B96183C9D8FD0AA125F87557FCCEC60301CF7ADD1578B0DA59355AD8B diff --git a/assemblies/msedgedriver.exe b/assemblies/msedgedriver.exe new file mode 100644 index 0000000..74d70ba Binary files /dev/null and b/assemblies/msedgedriver.exe differ diff --git a/assemblies/msedgedriver.exe.sha256 b/assemblies/msedgedriver.exe.sha256 new file mode 100644 index 0000000..96c8978 --- /dev/null +++ b/assemblies/msedgedriver.exe.sha256 @@ -0,0 +1 @@ +A6EB02FF3EF75079A647F20BD0B6B563648BC4C8563443229C65671AB0BBB6CD diff --git a/formats/Selenium.format.ps1xml b/formats/Selenium.format.ps1xml new file mode 100644 index 0000000..4521c8d --- /dev/null +++ b/formats/Selenium.format.ps1xml @@ -0,0 +1,215 @@ + + + + + + OpenQA.Selenium.Remote.RemoteWebElement + + OpenQA.Selenium.Remote.RemoteWebElement + + + + + left + 7 + + + left + 7 + + + left + 9 + + + Left + 80 + + + + + + + Tagname + + + Enabled + + + Displayed + + + Text + + + + + + + + OpenQA.Selenium.Remote.RemoteWebElement + + OpenQA.Selenium.Remote.RemoteWebElement + + + + + + + Tagname + + + Text + + + Enabled + + + Selected + + + Location + + + Size + + + Displayed + + + + + + + + selenium-powershell/SeFrame + + selenium-powershell/SeFrame + + + + + + + + + + + + + + + + + + + TagName + + + Enabled + + + $_.Attributes.name + + + $_.Attributes.id + + + + + + + + selenium-powershell/SeInput + + selenium-powershell/SeInput + + + + + + + + + + + + + + + + + + + + + + + + + + Tagname + + + $_.Attributes.type + + + Enabled + + + Displayed + + + Text + + + $_.Attributes.placeholder + + + $_.Attributes.value + + + + + + + + SeSelectValueInfo + + selenium-powershell/SeSelectValueInfo + + + + + + + IsMultiSelect + + + + + + + ($_.Items.Count -ne 0) + + + + $output = [System.Text.StringBuilder]::new(); + $TextMax = ($_.Items.Text | Measure-Object -Maximum).Maximum.length + $ValueMax = ($_.Items.Value | Measure-Object -Maximum).Maximum.length + [void]($Output.AppendFormat("Index {0} {1} Selected`n", 'Text'.PadRight($TextMax, ' '), 'Value'.PadRight($ValueMax, ' '))) + [void]($Output.AppendFormat("----- {0} {1} --------`n", '----'.PadRight($TextMax, ' '), '-----'.PadRight($ValueMax, ' '))) + foreach ($I in $_.Items) { + $IsSelected = if ($I.Selected) {" *"} else {''} + [Void]($output.AppendFormat("{0} {1} {2} {3}`n", "$($I.Index)".PadLeft(5, ' '), "$($I.Text)".PadRight($TextMax, ' '), "$($I.Value)".PadRight($ValueMax, ' '), $IsSelected)) + }; + $output.ToString().Trim("`n"); + + + + + + + + + diff --git a/types/Selenium.Types.ps1xml b/types/Selenium.Types.ps1xml new file mode 100644 index 0000000..a70253c --- /dev/null +++ b/types/Selenium.Types.ps1xml @@ -0,0 +1,54 @@ + + + + + OpenQA.Selenium.Remote.RemoteWebElement + + + PSStandardMembers + + + DefaultDisplayPropertySet + + Tagname + Enabled + Displayed + Text + + + + + + + + OpenQA.Selenium.Remote.RemoteWebDriver + + + PSStandardMembers + + + DefaultDisplayPropertySet + + SeFriendlyName + SeBrowser + SeTitle + SeUrl + + + + + + SeUrl + + if ($null -ne $this.SessionId) { $this.Url } + + + + SeTitle + + if ($null -ne $this.SessionId) { $this.Title } + + + + +