Skip to content

Commit 28cee06

Browse files
authored
Merge pull request #895 from licanhua/addjs
Provide JavaScript examples: WinAppDriver + selenium-webdriver and WinAppDriver + WebDriverIO
2 parents c33c66b + ef7d2e6 commit 28cee06

32 files changed

+9728
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ obj/
5555
# except build/, which is used as an MSBuild target.
5656
!**/packages/build/
5757

58+
# except Javascript examples
59+
!Samples/JavaScript/packages
60+
5861
# Visual Studio 2015/2017 cache/options directory
5962
.vs/
6063

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "Xaml-Controls-Gallery"]
2+
path = Xaml-Controls-Gallery
3+
url = https://github.com/microsoft/Xaml-Controls-Gallery.git
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
trigger: none # will disable CI builds entirely
2+
3+
pr:
4+
- master
5+
6+
pool:
7+
vmImage: 'windows-2019'
8+
9+
steps:
10+
- checkout: self
11+
clean: true
12+
lfs: false
13+
submodules: true
14+
persistCredentials: false
15+
16+
- template: templates/buildTestApp.yml
17+
18+
- template: templates/deployTestApp.yml
19+
20+
- task: PowerShell@2
21+
displayName: 'Remove WebDriverIO Workaround'
22+
inputs:
23+
targetType: 'inline'
24+
script: '((Get-Content -path Samples/JavaScript/packages/webdriverio/package.json -Raw) -replace ".*webdriver.git.*","") | Set-Content -Path Samples/JavaScript/packages/webdriverio/package.json'
25+
26+
- task: CmdLine@2
27+
displayName: yarn install
28+
inputs:
29+
script: yarn install
30+
workingDirectory: Samples/JavaScript/
31+
32+
- task: PowerShell@2
33+
displayName: 'Patch WebDriverIO'
34+
inputs:
35+
targetType: 'inline'
36+
script: '((Get-Content -path Samples/JavaScript/node_modules/webdriver/build/utils.js -Raw) -replace "if \(!body .*","if (!body) {") | Set-Content -Path Samples/JavaScript/node_modules/webdriver/build/utils.js'
37+
38+
39+
- task: WinAppDriver.winappdriver-pipelines-task.winappdriver-pipelines-task.Windows Application Driver@0
40+
displayName: 'Start - WinAppDriver'
41+
inputs:
42+
WADArguments: 127.0.0.1 4723/wd/hub
43+
AgentResolution: 1080p
44+
45+
- task: PowerShell@2
46+
displayName: 'Start the App'
47+
inputs:
48+
targetType: 'inline'
49+
script: 'start shell:AppsFolder\Microsoft.XAMLControlsGallery_8wekyb3d8bbwe!App'
50+
51+
# Wait for app to launch. A workaround to avoid WinAppDriver error: Failed to locate opened application window with appId
52+
- task: PowerShell@2
53+
displayName: Wait for app to launch
54+
inputs:
55+
targetType: inline # filePath | inline
56+
script: |
57+
Start-Sleep -Seconds 30
58+
59+
- task: PowerShell@2
60+
displayName: 'Check TestApp'
61+
inputs:
62+
targetType: 'inline'
63+
script: 'if ((Get-Process AppUIBasics) -eq $Null) { echo "TestApp is not running"; exit 1}'
64+
65+
- task: CmdLine@2
66+
displayName: Run WebDriverIO test
67+
inputs:
68+
script: yarn run test
69+
workingDirectory: Samples/JavaScript/packages/webdriverio
70+
condition: succeededOrFailed()
71+
72+
- task: WinAppDriver.winappdriver-pipelines-task.winappdriver-pipelines-task.Windows Application Driver@0
73+
displayName: 'Stop - WinAppDriver'
74+
inputs:
75+
OperationType: Stop
76+
condition: succeededOrFailed()
77+
78+
- task: WinAppDriver.winappdriver-pipelines-task.winappdriver-pipelines-task.Windows Application Driver@0
79+
displayName: 'Start - WinAppDriver'
80+
inputs:
81+
WADArguments: 127.0.0.1 4723/wd/hub
82+
AgentResolution: 1080p
83+
condition: succeededOrFailed()
84+
85+
- task: CmdLine@2
86+
displayName: yarn install
87+
inputs:
88+
script: yarn install
89+
workingDirectory: Samples/JavaScript/packages/selenium-webdriver
90+
condition: succeededOrFailed()
91+
92+
- task: CmdLine@2
93+
displayName: Run selenium-webdriver test
94+
inputs:
95+
script: yarn run jest
96+
workingDirectory: Samples/JavaScript/packages/selenium-webdriver
97+
condition: succeededOrFailed()
98+
99+
- task: WinAppDriver.winappdriver-pipelines-task.winappdriver-pipelines-task.Windows Application Driver@0
100+
displayName: 'Stop - WinAppDriver'
101+
inputs:
102+
OperationType: Stop
103+
condition: succeededOrFailed()
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
steps:
2+
- task: NuGetToolInstaller@0
3+
displayName: 'Use NuGet 4.4.1'
4+
inputs:
5+
versionSpec: 4.4.1
6+
7+
- task: NuGetCommand@2
8+
displayName: 'NuGet restore'
9+
inputs:
10+
restoreSolution: Xaml-Controls-Gallery/XamlControlsGallery/XamlControlsGallery.sln
11+
- task: VSBuild@1
12+
displayName: 'Build solution XamlControlsGallery/XamlControlsGallery.sln'
13+
inputs:
14+
solution: Xaml-Controls-Gallery/XamlControlsGallery/XamlControlsGallery.sln
15+
msbuildArgs: '/p:Configuration=Deploy /p:AppxPackageDir="$(Build.ArtifactStagingDirectory)\\" /p:UapAppxPackageBuildMode=CI/p:AppxBundlePlatforms="x86" /p:AppxBundle=Always'
16+
platform: x86
17+
configuration: Release
18+
- task: CopyFiles@2
19+
displayName: 'Copy Files to: $(build.artifactstagingdirectory)'
20+
inputs:
21+
SourceFolder: '$(system.defaultworkingdirectory)'
22+
Contents: '**\bin\$(BuildConfiguration)\**'
23+
TargetFolder: '$(build.artifactstagingdirectory)'
24+
condition: succeededOrFailed()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
steps:
2+
- task: PowerShell@1
3+
displayName: 'Install Xaml Controls Cert'
4+
inputs:
5+
scriptType: inlineScript
6+
arguments: '-NonInteractive -Verb RunAs'
7+
inlineScript: |
8+
$file = ( Get-ChildItem -Path $(Build.ArtifactStagingDirectory)\XamlControlsGallery_$(PackageManifest)_Test\XamlControlsGallery_$(PackageManifest)_x86.cer )
9+
$file | Import-Certificate -CertStoreLocation cert:\LocalMachine\Root
10+
11+
- task: PowerShell@1
12+
displayName: 'Install XAML Appx Packages'
13+
inputs:
14+
scriptName: '$(Build.ArtifactStagingDirectory)\XamlControlsGallery_$(PackageManifest)_Test\Add-AppDevPackage.ps1'
15+
arguments: '-NonInteractive -Force:$true -Verb RunAs'

Samples/JavaScript/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*/node_modules
2+
# Reports section
3+
packages/webdriverio/reports
4+
.vscode
5+
node_modules

Samples/JavaScript/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# winappdriver-js-webdriver-example
2+
There are two popular JavaScript WebDrivers which could be used for WinAppDriver testing: [selenium-webdriver](https://www.npmjs.com/package/selenium-webdriver) and [webdriverio](https://webdriver.io/).
3+
4+
This is used to demo UI automation testing with WinAppDriver which the test runner is JavaScript. It includes the examples and Azure Pipeline with selenium-webdirver and WebDriverIO.
5+
1. Jest + selenium-webdriver + WinAppDriver
6+
2. Jasmine + WebDriverIO + WinAppDriver
7+
8+
9+
[WinAppDriver](https://github.com/Microsoft/WinAppDriver) is recommended to do E2E test for Windows apps.
10+
Here I validate [Xaml-Controls-Gallery](https://github.com/Microsoft/Xaml-Controls-Gallery) application using JavaScript + WinAppDriver.
11+
12+
This test project highlights the following basic interactions to demonstrate how UI testing using Windows Application Driver work.
13+
- Azure pipeline
14+
- Finding element using 'accessibility id' and 'name'
15+
- Sending click action to an element
16+
- Retrieving element value
17+
- WinAppDriver integration with WebDriverIO and selenium-webdriver
18+
19+
I prototyped and successfully made the two webdrivers to be happy with WinAppDriver. And you can use any of them on your project.
20+
21+
## Examples
22+
I provided two examples which are using selenium-webdriver or webdriverio.
23+
24+
- [selenium-webdriver example](packages/selenium-webdriver/README.md) in packages/selenium-webdriver
25+
26+
selenium-webdriver is the offical WebDriver JavaScript binding from selenium project. Unfortunately selenium-webdriver doesn't support [Mobile JSON Wire Protocol Specification](https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol).
27+
[selenium-appium](https://www.npmjs.com/package/selenium-appium) is selenium-webdriver extension to make selenium-webdriver to drive Appium to run automation.
28+
29+
- [webdriverio example](packages/webdriverio/README.md) in packages/webdriverio
30+
31+
WinAppDriver doesn't implement w3c WebDriver completely, so currently I workaround the problem by [WebDriver](https://github.com/react-native-windows/webdriver). In your project, you have to use private webdriver in package.json lke this:
32+
```
33+
"webdriverio": "^5.10.1",
34+
"webdriver": "git+https://github.com/react-native-windows/webdriver.git",
35+
```
36+
37+
## Azure pipeline for WinAppDriver
38+
Please refer to [.ado](.ado) folder in this project.
39+
For WinAppDriver, see [WinAppDriver in CI with Azure Pipelines](https://github.com/microsoft/WinAppDriver/blob/master/Docs/CI_AzureDevOps.md)
40+
41+
## Dependencies
42+
* Install nodejs, make sure a recent version of [Node.js](https://nodejs.org) is installed.
43+
[Chocolatey](https://chocolatey.org/) is the recommended installation method. But you can also install Node directly from [NodeJs](https://nodejs.org/en/download/). To use chocolately, from an elevated Command Prompt, run:
44+
```
45+
choco install nodejs
46+
```
47+
* Install [Yarn](https://yarnpkg.com/en/docs/install) (*optional* if you use npm command directly)
48+
49+
* Install 'xaml controls Gallery'
50+
- Download and Install it from Microsoft Store.
51+
- Or build and deploy Xaml-Controls-Gallery submodule
52+
53+
* Install the most recent stable [WinAppDriver](https://github.com/Microsoft/WinAppDriver/releases) on the test device

Samples/JavaScript/lerna.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"packages": [
3+
"packages/*"
4+
],
5+
"version": "0.0.0"
6+
}

Samples/JavaScript/package.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "winappdriver-js-webdriver-example-repo",
3+
"version": "0.0.1",
4+
"private": true,
5+
"scripts": {
6+
},
7+
"repository": {
8+
"type": "git",
9+
"url": "git@github.com:Microsoft/WinAppDriver.git"
10+
},
11+
"license": "MIT",
12+
"workspaces": {
13+
"packages": [
14+
"packages/*"
15+
]
16+
},
17+
"devDependencies": {
18+
}
19+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License.
4+
*/
5+
6+
import { PageObject, By2 } from "selenium-appium";
7+
8+
class BasicInputPage extends PageObject {
9+
isPageLoaded() {
10+
return this.checkBoxButton.isDisplayed();
11+
}
12+
13+
private get checkBoxButton() { return By2.nativeName('CheckBox'); }
14+
private get buttonButton() { return By2.nativeName('Button'); }
15+
16+
gotoButtonPage() {
17+
return this.buttonButton.click();
18+
}
19+
20+
gotoCheckboxPage() {
21+
return this.checkBoxButton.click();
22+
}
23+
}
24+
25+
export default new BasicInputPage();
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License.
4+
*/
5+
6+
import { PageObject, By2 } from "selenium-appium";
7+
8+
class ButtonPage extends PageObject {
9+
isPageLoaded() {
10+
return this.button1Button.isDisplayed();
11+
}
12+
13+
private get button1Button() { return By2.nativeAccessibilityId('Button1'); }
14+
private get control1Ooutput() { return By2.nativeAccessibilityId('Control1Output');}
15+
16+
clickButton1() {
17+
return this.button1Button.click();
18+
}
19+
20+
getControl1Output() {
21+
return this.control1Ooutput.getText();
22+
}
23+
}
24+
25+
export default new ButtonPage();
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License.
4+
*/
5+
6+
import { PageObject, By2 } from "selenium-appium";
7+
8+
class CheckBoxPage extends PageObject {
9+
isPageLoaded() {
10+
return this.checkbox1Button.isDisplayed();
11+
}
12+
13+
private get checkbox1Button() { return By2.nativeName('Two-state CheckBox'); }
14+
private get control1Ooutput() { return By2.nativeAccessibilityId('Control1Output');}
15+
16+
clickCheckbox1() {
17+
return this.checkbox1Button.click();
18+
}
19+
20+
getControl1Output() {
21+
return this.control1Ooutput.getText();
22+
}
23+
}
24+
25+
export default new CheckBoxPage();
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License.
4+
*/
5+
6+
import { PageObject, By2 } from "selenium-appium";
7+
8+
class HomePage extends PageObject {
9+
isPageLoaded() {
10+
return this.basicInputButton.isDisplayed();
11+
}
12+
private get basicInputButton() { return By2.nativeName('Basic Input'); }
13+
14+
gotoBasicInputPage() {
15+
return this.basicInputButton.click();
16+
}
17+
}
18+
19+
export default new HomePage();
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
## Example with selenium-webdriver
2+
Make sure [Dependencies](../../README.md)
3+
4+
1. goto selenium-webdriver project
5+
2. start appium
6+
7+
`yarn run appium` or `npm run appium`
8+
9+
expect output
10+
```
11+
[Appium] Welcome to Appium v1.14.1
12+
[Appium] Appium REST http interface listener started on 0.0.0.0:4723
13+
```
14+
15+
3. run jest test
16+
17+
`yarn run jest` or `npm run jest`

0 commit comments

Comments
 (0)