├── .gitattributes
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── README_RU.md
├── scripts
├── ci-release.ps1
├── ci.ps1
├── prepare-release.ps1
└── setup.ps1
└── src
├── .nuget
├── NuGet.Config
└── NuGet.targets
├── Settings.StyleCop
├── TestApps.Tests
├── WindowsFormsTestApplication.Tests
│ ├── BaseForMainWindowTest.cs
│ ├── BaseTest.cs
│ ├── CommandTests
│ │ ├── ClearElementTests.cs
│ │ ├── ClickElementTests.cs
│ │ ├── CloseTests.cs
│ │ ├── FindTests.cs
│ │ ├── GetActiveElementTests.cs
│ │ ├── GetElementAttributeTests.cs
│ │ ├── GetElementSizeTests.cs
│ │ ├── GetElementTextTests.cs
│ │ ├── IsElementDisplayedTests.cs
│ │ ├── IsElementEnabledTests.cs
│ │ ├── IsElementSelectedTests.cs
│ │ ├── MouseClickTests.cs
│ │ ├── MouseDoubleClickTests.cs
│ │ ├── QuitTests.cs
│ │ ├── SendKeysToActiveElementTests.cs
│ │ ├── SendKeysToElementTests.cs
│ │ └── TakeScreenshotTests.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── WindowsFormsTestApplication.Tests.csproj
│ ├── WindowsFormsTestApplication.exe
│ └── packages.config
└── WpfTestApplication.Tests
│ ├── ActionChainsTests.cs
│ ├── BaseForMainWindowTest.cs
│ ├── BaseTest.cs
│ ├── CommandTests
│ ├── ClearElementTests.cs
│ ├── ClickElementTests.cs
│ ├── CloseTests.cs
│ ├── FindTests.cs
│ ├── GetActiveElementTests.cs
│ ├── GetElementAttributeTests.cs
│ ├── GetElementSizeTests.cs
│ ├── GetElementTextTests.cs
│ ├── IsElementDisplayedTests.cs
│ ├── IsElementEnabledTests.cs
│ ├── IsElementSelectedTests.cs
│ ├── MouseClickTests.cs
│ ├── MouseDoubleClickTests.cs
│ ├── MouseMoveToTests.cs
│ ├── QuitTests.cs
│ └── TakeScreenshotTests.cs
│ ├── Properties
│ └── AssemblyInfo.cs
│ ├── TestHelper.cs
│ ├── TestWebDriver.cs
│ ├── WiniumCommandTests
│ ├── ComboBoxCommandsTests.cs
│ ├── DataGridCommandsTests.cs
│ └── MenuCommandsTests.cs
│ ├── WpfTestApplication.Tests.csproj
│ ├── WpfTestApplication.exe
│ └── packages.config
├── Winium.Desktop.Driver
├── App.config
├── Automator
│ ├── Automator.cs
│ └── Capabilities.cs
├── CommandExecutorDispatchTable.cs
├── CommandExecutors
│ ├── ClearElementExecutor.cs
│ ├── ClickElementExecutor.cs
│ ├── CloseExecutor.cs
│ ├── CollapseComboBoxExecutor.cs
│ ├── CommandExecutorBase.cs
│ ├── ElementEqualsExecutor.cs
│ ├── ExecuteScriptExecutor.cs
│ ├── ExpandComboBoxExecutor.cs
│ ├── FindChildElementExecutor.cs
│ ├── FindChildElementsExecutor.cs
│ ├── FindComboBoxSelectedItemExecutor.cs
│ ├── FindDataGridCellExecutor.cs
│ ├── FindElementExecutor.cs
│ ├── FindElementsExecutor.cs
│ ├── FindMenuItemExecutor.cs
│ ├── GetActiveElementExecutor.cs
│ ├── GetCurrentWindowHandleExecutor.cs
│ ├── GetDataGridColumnCountExecutor.cs
│ ├── GetDataGridRowCountExecutor.cs
│ ├── GetElementAttributeExecutor.cs
│ ├── GetElementSizeExecutor.cs
│ ├── GetElementTextExecutor.cs
│ ├── GetOrientationExecutor.cs
│ ├── GetWindowHandlesExecutor.cs
│ ├── ImplicitlyWaitExecutor.cs
│ ├── IsComboBoxExpandedExecutor.cs
│ ├── IsElementDisplayedExecutor.cs
│ ├── IsElementEnabledExecutor.cs
│ ├── IsElementSelectedExecutor.cs
│ ├── MouseClickExecutor.cs
│ ├── MouseDoubleClickExecutor.cs
│ ├── MouseMoveToExecutor.cs
│ ├── NewSessionExecutor.cs
│ ├── NotImplementedExecutor.cs
│ ├── QuitExecutor.cs
│ ├── ScreenshotExecutor.cs
│ ├── ScrollToComboBoxItemExecutor.cs
│ ├── ScrollToDataGridCellExecutor.cs
│ ├── ScrollToListBoxItemExecutor.cs
│ ├── SelectDataGridCellExecutor.cs
│ ├── SelectMenuItemExecutor.cs
│ ├── SendKeysToActiveElementExecutor.cs
│ ├── SendKeysToElementExecutor.cs
│ ├── SetOrientationExecutor.cs
│ ├── StatusExecutor.cs
│ ├── SubmitElementExecutor.cs
│ └── SwitchToWindowExecutor.cs
├── CommandHelpers
│ ├── BuildInfo.cs
│ └── OSInfo.cs
├── CommandLineOptions.cs
├── ElementsRegistry.cs
├── Extensions
│ ├── AutomationPropertyHelper.cs
│ └── ByHelper.cs
├── HttpRequest.cs
├── Input
│ ├── KeyEvent.cs
│ ├── KeyboardModifiers.cs
│ └── WiniumKeyboard.cs
├── Listener.cs
├── Logger.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── Requester.cs
├── UriDispatchTables.cs
├── Winium.Desktop.Driver.csproj
└── packages.config
├── Winium.StoreApps.Common
├── Command.cs
├── CommandInfo.cs
├── CommandResponse.cs
├── DriverCommand.cs
├── Exceptions
│ ├── AutomationException.cs
│ └── InnerDriverRequestException.cs
├── HttpResponseHelper.cs
├── JsonErrorCodes.cs
├── JsonWireClasses.cs
├── Properties
│ └── AssemblyInfo.cs
├── ResponseStatus.cs
├── Winium.StoreApps.Common.csproj
└── packages.config
├── Winium.sln
└── Winium.sln.DotSettings
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 |
11 | [Dd]ebug/
12 | [Rr]elease/
13 | x64/
14 | !build/
15 | /*/build
16 | [Bb]in/
17 | [Oo]bj/
18 |
19 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
20 | !packages/*/build/
21 |
22 | # MSTest test Results
23 | [Tt]est[Rr]esult*/
24 | [Bb]uild[Ll]og.*
25 |
26 | *_i.c
27 | *_p.c
28 | *.ilk
29 | *.meta
30 | *.obj
31 | *.pch
32 | *.pdb
33 | *.pgc
34 | *.pgd
35 | *.rsp
36 | *.sbr
37 | *.tlb
38 | *.tli
39 | *.tlh
40 | *.tmp
41 | *.tmp_proj
42 | *.log
43 | *.vspscc
44 | *.vssscc
45 | .builds
46 | *.pidb
47 | *.svclog
48 | *.scc
49 |
50 | # Visual C++ cache files
51 | ipch/
52 | *.aps
53 | *.ncb
54 | *.opensdf
55 | *.sdf
56 | *.cachefile
57 |
58 | # Visual Studio profiler
59 | *.psess
60 | *.vsp
61 | *.vspx
62 |
63 | # TFS 2012 Local Workspace
64 | $tf/
65 |
66 | # Guidance Automation Toolkit
67 | *.gpState
68 |
69 | # ReSharper is a .NET coding add-in
70 | _ReSharper*/
71 | *.[Rr]e[Ss]harper
72 | *.DotSettings.user
73 |
74 | # TeamCity is a build add-in
75 | _TeamCity*
76 |
77 | # DotCover is a Code Coverage Tool
78 | *.dotCover
79 |
80 | # NCrunch
81 | *.ncrunch*
82 | _NCrunch_*
83 | .*crunch*.local.xml
84 |
85 | # Installshield output folder
86 | [Ee]xpress/
87 |
88 | # DocProject is a documentation generator add-in
89 | DocProject/buildhelp/
90 | DocProject/Help/*.HxT
91 | DocProject/Help/*.HxC
92 | DocProject/Help/*.hhc
93 | DocProject/Help/*.hhk
94 | DocProject/Help/*.hhp
95 | DocProject/Help/Html2
96 | DocProject/Help/html
97 |
98 | # Click-Once directory
99 | publish/
100 |
101 | # Publish Web Output
102 | *.Publish.xml
103 |
104 | # NuGet Packages Directory
105 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
106 | packages/
107 |
108 | # Windows Azure Build Output
109 | csx
110 | *.build.csdef
111 |
112 | # Windows Store app package directory
113 | AppPackages/
114 |
115 | # Others
116 | sql/
117 | *.Cache
118 | ClientBin/
119 | [Ss]tyle[Cc]op.*
120 | ~$*
121 | *~
122 | *.dbmdl
123 | *.dbproj.schemaview
124 | *.[Pp]ublish.xml
125 | *.pfx
126 | *.publishsettings
127 |
128 | # RIA/Silverlight projects
129 | Generated_Code/
130 |
131 | # Backup & report files from converting an old project file to a newer
132 | # Visual Studio version. Backup files are not needed, because we have git ;-)
133 | _UpgradeReport_Files/
134 | Backup*/
135 | UpgradeLog*.XML
136 | UpgradeLog*.htm
137 |
138 | # SQL Server files
139 | App_Data/*.mdf
140 | App_Data/*.ldf
141 |
142 | # Business Intelligence projects
143 | *.rdl.data
144 | *.bim.layout
145 | *.bim_*.settings
146 |
147 | # Microsoft Fakes
148 | FakesAssemblies/
149 |
150 | # =========================
151 | # Windows detritus
152 | # =========================
153 |
154 | # Windows image file caches
155 | Thumbs.db
156 | ehthumbs.db
157 |
158 | # Folder config file
159 | Desktop.ini
160 |
161 | # Recycle Bin used on file shares
162 | $RECYCLE.BIN/
163 |
164 | # Mac crap
165 | .DS_Store
166 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 |
7 |
8 |
## v1.6.0
9 |
10 | - Add new script command for click to element center (by bounding rectangle). Thanks @kdavydenko
11 | - Add `GetOrientation` and `SetOrientation` command. Thanks @jonstoneman
12 | - Fix listener crashing on empty incoming request (python bindings >2.53.3)
13 | - Fix get attribute response format
14 |
15 |
16 | ## v1.5.0
17 |
18 | - Add `SwitchToWindow` command
19 | - Fix XPath attribute value if this ControlType
20 |
21 |
22 | ## v1.4.0
23 |
24 | - Add `XPath` strategy for locating elements
25 | - Add `GetCurrentWindowHandle` command
26 | - Add `GetWindowHandles` command
27 | - Add `--silent` option to a driver CLI (suppresses output)
28 | - Fix logger timestamp format
29 |
30 |
31 | ## v1.3.0
32 |
33 | - Fix error response format
34 | - Add `args` capability for launching application with arguments
35 | - Set default elements search timeout to 10 seconds (fixed in [Winium.Cruciatus 2.7.0](https://github.com/2gis/Winium.Cruciatus/releases/tag/v2.7.0))
36 | - Single file Driver distribution
37 | - Add extended driver commands (see [Winium.Elements](https://github.com/2gis/Winium.Elements/releases) for bindings). Extended commands simplify usage of following elements:
38 | - ComboBox (collapse, expand, is expanded, find selected item, scroll to item)
39 | - DataGrid (row count, column count, find cell, scroll to cell, select cell)
40 | - ListBox (scroll to item)
41 | - Menu (find item, select item)
42 |
43 |
44 | ## v1.2.0
45 |
46 | New features:
47 | - Support Action Chains from bindings
48 | - Add new script command for setting value to element using ValuePattern
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | English description | Описание на русском
3 |
4 |
5 | # Winium for Desktop
6 | [](http://opensource-ci.2gis.ru/job/Winium.Desktop/)
7 | [](https://github.com/2gis/Winium.Desktop/releases/)
8 | [](LICENSE)
9 |
10 |
11 |
12 |
13 |
14 | Winium.Desktop is an open source test automation tool for automated testing of Windows application based on WinForms and WPF platforms.
15 |
16 | ## Supported Platforms
17 | - WinForms
18 | - WPF
19 |
20 | For Windows Phone 8.1 test automation tool see [Windows Phone Driver](https://github.com/2gis/Winium.StoreApps).
21 | For Windows Phone 8 Silverlight test automation tool see [Windows Phone Driver](https://github.com/2gis/winphonedriver).
22 |
23 | ## Why Winium?
24 | You have Selenium WebDriver for testing of web apps, Appium for testing of iOS and Android apps. And now you have Selenium-based tools for testing of Windows apps too. What are some of the benefits? As said by Appium:
25 | > - You can write tests with your favorite dev tools using any WebDriver-compatible language such as Java, Objective-C, JavaScript with Node.js (in promise, callback or generator flavors), PHP, Python, Ruby, C#, Clojure, or Perl with the Selenium WebDriver API and language-specific client libraries.
26 | > - You can use any testing framework.
27 |
28 | ## Requirements
29 | * Microsoft .NET Framework 4.5.1
30 |
31 | ## Quick Start
32 | 1. Write your tests using you favorite language. In your tests use `app` [desired capability](https://github.com/2gis/Winium.Desktop/wiki/Capabilities) to set path to tested app's exe file. Here is python example:
33 | ```python
34 | # put it in setUp
35 | self.driver = webdriver.Remote(command_executor='http://localhost:9999',
36 | desired_capabilities={'app': 'C:\\testApp.exe',
37 | 'args': '-port 345'})
38 | # put it in test method body
39 | win = self.driver.find_element_by_id('WpfTestApplicationMainWindow')
40 | win.find_element_by_id('SetTextButton').click()
41 | assert 'CARAMBA' == self.driver.find_element_by_id('MyTextBox').text
42 | ```
43 |
44 | 2. Start `Winium.Desktop.Driver.exe` ([download release from github](https://github.com/2gis/Winium.Desktop/releases) or build it yourself)
45 |
46 | 3. Run your tests and watch the magic happening
47 |
48 | ## How it works
49 | **Winium.Desktop.Driver** implements Selenium Remote WebDriver and listens for JsonWireProtocol commands. It is responsible for automation of app under test using [Winium.Cruciatus](https://github.com/2gis/Winium.Cruciatus).
50 |
51 | ## Contributing
52 |
53 | Contributions are welcome!
54 |
55 | 1. Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug.
56 | 2. Fork the repository to start making your changes to the master branch (or branch off of it).
57 | 3. We recommend to write a test which shows that the bug was fixed or that the feature works as expected.
58 | 4. Send a pull request and bug the maintainer until it gets merged and published. :smiley:
59 |
60 | ## Contact
61 |
62 | Have some questions? Found a bug? Create [new issue](https://github.com/2gis/Winium.Desktop/issues/new) or contact us at g.golovin@2gis.ru
63 |
64 | ## License
65 |
66 | Winium is released under the MPL 2.0 license. See [LICENSE](LICENSE) for details.
67 |
--------------------------------------------------------------------------------
/README_RU.md:
--------------------------------------------------------------------------------
1 | # Winium для Desktop
2 | [](http://opensource-ci.2gis.ru/job/Winium.Desktop/)
3 | [](https://github.com/2gis/Winium.Desktop/releases/)
4 | [](LICENSE)
5 |
6 |
7 |
8 |
9 |
10 | Winium.Desktop это open-source инструмент для автоматизации тестирования Windows приложений построенных на WinFroms и WPF платформах.
11 |
12 | ## Поддерживаемые платформы
13 | - WinForms
14 | - WPF
15 |
16 | Для автоматизации Windows Phone 8.1 есть [Windows StoreApps Driver](https://github.com/2gis/Winium.StoreApps).
17 | Для автоматизации Windows Phone 8 Silverlight есть [Windows Phone Driver](https://github.com/2gis/winphonedriver).
18 |
19 | ## Почему Winium?
20 | Уже есть Selenium WebDriver для тестирования веб приложений, Appium для тестирования iOS и Android приложений. А теперь появился Selenium-based инструмент для тестирования Windows приложений. Какие он дает преимущества? Цитируя Appium:
21 | > - You can write tests with your favorite dev tools using any WebDriver-compatible language such as Java, Objective-C, JavaScript with Node.js (in promise, callback or generator flavors), PHP, Python, Ruby, C#, Clojure, or Perl with the Selenium WebDriver API and language-specific client libraries.
22 | > - You can use any testing framework.
23 |
24 | А по-русски можно?
25 | - Пишите тесты, используя ваши любимые инструменты, любой WebDriver-совместимый язык программирования, например, Java, Objective-C, JavaScript with Node.js, PHP, Python, Ruby, C#, Clojure...
26 | - Используйте любой тестовый фреймворк.
27 |
28 | ## Требования
29 | * Microsoft .NET Framework 4.5.1
30 |
31 | ## Быстрый старт
32 | 1. Пишите тесты на удобном языке. В тесте используйте `app` [desired capability](https://github.com/2gis/Winium.Desktop/wiki/Capabilities) для задания исполняемого файла приложения. Это пример на python:
33 | ```python
34 | # put it in setUp
35 | self.driver = webdriver.Remote(command_executor='http://localhost:9999',
36 | desired_capabilities={'app': 'C:\\testApp.exe',
37 | 'args': '-port 345'})
38 | # put it in test method body
39 | win = self.driver.find_element_by_id('WpfTestApplicationMainWindow')
40 | win.find_element_by_id('SetTextButton').click()
41 | assert 'CARAMBA' == self.driver.find_element_by_id('MyTextBox').text
42 | ```
43 |
44 | 2. Запустите `Winium.Desktop.Driver.exe` ([загрузить последнюю версию с github](https://github.com/2gis/Winium.Desktop/releases) или соберите проект у себя)
45 |
46 | 3. Запустите тесты и балдейте от происходящей магии
47 |
48 | ## Как это работает
49 | **Winium.Desktop.Driver** реализует Selenium Remote WebDriver и слушает команды в JsonWireProtocol. Для автоматизации действий над приложением используется фреймворк [Winium.Cruciatus](https://github.com/2gis/Winium.Cruciatus).
50 |
51 | ## Вклад в развитие
52 |
53 | Мы открыты для сотрудничества!
54 |
55 | 1. Проверьте нет ли уже открытого issue или заведите новый issue для обсуждения новой фичи или бага.
56 | 2. Форкните репозиторий и начните делать свои изменения в ветке мастер или новой ветке
57 | 3. Мы советуем написать тест, который покажет, что баг был починен или что новая фича работает как ожидается.
58 | 4. Создайте pull-request и тыкайте в мэнтейнера до тех пор, пока он не примет и не сольет ваши изменения. :smiley:
59 |
60 | ## Контакты
61 |
62 | Есть вопросы? Нашли ошибку? Создавайте [новое issue](https://github.com/2gis/Winium.Desktop/issues/new) или пишите g.golovin@2gis.ru
63 |
64 | ## Лицензия
65 |
66 | Winium выпущен под MPL 2.0 лицензией. [Подробности](LICENSE).
67 |
--------------------------------------------------------------------------------
/scripts/ci-release.ps1:
--------------------------------------------------------------------------------
1 | Set-StrictMode -Version Latest
2 | $ErrorActionPreference = 'Stop'
3 | #------------------------------
4 |
5 | Import-Module '.\setup.ps1' -Args (,('git', 'versioning', 'changelog', 'msbuild', 'nunit', 'github'))
6 |
7 | $version = $env:release_version
8 | $description = $env:release_description
9 |
10 | # Git checkout master
11 | Invoke-Git ('checkout', 'master') -Verbose
12 |
13 | # Update AssembyInfo
14 | Update-AssemblyInfo $assemblyInfoPath $version -Verbose
15 |
16 | # Update CHANGELOG.md
17 | Update-Changelog $changelogPath $version $description -Verbose
18 |
19 | # Build
20 | Invoke-MSBuild $solution $msbuildProperties -Verbose
21 |
22 | # Test
23 | Start-Process $driverMerged -RedirectStandardError $errorLog -RedirectStandardOutput $outputLog
24 | Invoke-NUnit $testFiles -Verbose
25 | & taskkill ('/im', 'Winium.Desktop.Driver.exe', '/f')
26 |
27 | # Prepare release artifacts
28 | New-Item -ItemType directory -Path $releaseDir | Out-Null
29 | Add-Type -assembly "system.io.compression.filesystem"
30 | $driverMergedPath = Split-Path $driverMerged
31 | [IO.Compression.ZipFile]::CreateFromDirectory($driverMergedPath, "$releaseDir/Winium.Desktop.Driver.zip")
32 |
33 | # Git add changes
34 | Invoke-Git ('add', $assemblyInfoPath) -Verbose
35 | Invoke-Git ('add', $changelogPath) -Verbose
36 |
37 | # Git commit and push
38 | Invoke-GitCommit "Version $version" -Verbose
39 | Invoke-Git ('push', 'origin', 'master') -Verbose
40 |
41 | # Git tag and push
42 | $buildUrl = $env:BUILD_URL
43 | Invoke-GitTag "Version '$version'. Build url '$buildUrl'." "v$version" -Verbose
44 | Invoke-Git ('push', 'origin', 'master', "v$version") -Verbose
45 |
46 | # Create github release
47 | Invoke-CreateGitHubRelease '2gis' $githubProjectName $version $description $releaseDir -Verbose
48 |
--------------------------------------------------------------------------------
/scripts/ci.ps1:
--------------------------------------------------------------------------------
1 | Set-StrictMode -Version Latest
2 | $ErrorActionPreference = 'Stop'
3 | #------------------------------
4 |
5 | Import-Module '.\setup.ps1' -Args (,('msbuild', 'nunit'))
6 |
7 | # Build
8 | Invoke-MSBuild $solution $msbuildProperties -Verbose
9 |
10 | # Test
11 | Start-Process $driverMerged -RedirectStandardError $errorLog -RedirectStandardOutput $outputLog
12 | Invoke-NUnit $testFiles -Verbose
13 | & taskkill ('/im', 'Winium.Desktop.Driver.exe', '/f')
14 |
15 | # Artifacts
16 | New-Item -ItemType directory -Path $artifactsDir | Out-Null
17 | Copy-Item -Path ($errorLog, $outputLog) -Destination $artifactsDir
18 |
--------------------------------------------------------------------------------
/scripts/prepare-release.ps1:
--------------------------------------------------------------------------------
1 | Set-StrictMode -Version Latest
2 | $ErrorActionPreference = 'Stop'
3 | #------------------------------
4 |
5 | Import-Module '.\setup.ps1' -Args (,('msbuild', 'nunit'))
6 |
7 | if (Test-Path $releaseDir)
8 | {
9 | Remove-Item $releaseDir -Force -Recurse
10 | }
11 |
12 | New-Item -ItemType directory -Path $releaseDir | Out-Null
13 |
14 | Write-Output "Update CHANGELOG.md"
15 | Write-Output "Update version in Assemblies"
16 |
17 | Pause
18 |
19 | # Build
20 | Invoke-MSBuild $solution $msbuildProperties -Verbose
21 |
22 | # Test
23 | Start-Process $driverMerged -RedirectStandardError $errorLog -RedirectStandardOutput $outputLog
24 | Invoke-NUnit $testFiles -Verbose
25 | & taskkill ('/im', 'Winium.Desktop.Driver.exe', '/f')
26 |
27 | # Pack driver
28 | Add-Type -assembly "system.io.compression.filesystem"
29 | $driverMergedPath = Split-Path $driverMerged
30 | [IO.Compression.ZipFile]::CreateFromDirectory($driverMergedPath, "$releaseDir/Winium.Desktop.Driver.zip")
31 |
32 | Write-Output "Add and push tag using git tag -a -m 'Version *.*.*' v*.*.*"
33 | Write-Output "Upload and attach $releaseDir\* files to release"
34 |
--------------------------------------------------------------------------------
/scripts/setup.ps1:
--------------------------------------------------------------------------------
1 | Param(
2 | [string[]]$modules
3 | )
4 |
5 | Set-StrictMode -Version Latest
6 | $ErrorActionPreference = 'Stop'
7 | #------------------------------
8 |
9 | $configuration = 'Release'
10 | $solution = Join-Path $PSScriptRoot '..\src\Winium.sln'
11 | $testFiles = ,"..\src\TestApps.Tests\WindowsFormsTestApplication.Tests\bin\$configuration\WindowsFormsTestApplication.Tests.dll"
12 | $testFiles += "..\src\TestApps.Tests\WpfTestApplication.Tests\bin\$configuration\WpfTestApplication.Tests.dll"
13 | $releaseDir = Join-Path $PSScriptRoot '..\Release'
14 | $artifactsDir = Join-Path $PSScriptRoot '..\Artifacts'
15 | $driverMerged = "..\src\Winium.Desktop.Driver\bin\$configuration\Merge\Winium.Desktop.Driver.exe"
16 | $errorLog = 'error.log'
17 | $outputLog = 'output.log'
18 | $assemblyInfoPath = Join-Path $PSScriptRoot '..\src\Winium.Desktop.Driver\Properties\AssemblyInfo.cs'
19 | $changelogPath = Join-Path $PSScriptRoot '..\CHANGELOG.md'
20 | $githubProjectName = 'Winium.Desktop'
21 |
22 | $msbuildProperties = @{
23 | 'Configuration' = $configuration
24 | }
25 |
26 | $modulesUrl = 'https://raw.githubusercontent.com/skyline-gleb/dev-help/v0.2.1/psm'
27 |
28 | if (!(Get-Module -ListAvailable -Name PsGet))
29 | {
30 | (new-object Net.WebClient).DownloadString("http://psget.net/GetPsGet.ps1") | iex
31 | }
32 |
33 | foreach ($module in $modules)
34 | {
35 | Install-Module -ModuleUrl "$modulesUrl/$module.psm1" -Update
36 | }
37 |
--------------------------------------------------------------------------------
/src/.nuget/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/BaseForMainWindowTest.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class BaseForMainWindowTest : BaseTest
12 | {
13 | #region Public Properties
14 |
15 | public IWebElement MainWindow { get; set; }
16 |
17 | #endregion
18 |
19 | #region Public Methods and Operators
20 |
21 | [SetUp]
22 | public void FindMainWindow()
23 | {
24 | this.MainWindow = this.Driver.FindElement(By.XPath("/*[@AutomationId='Form1']"));
25 | }
26 |
27 | #endregion
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/BaseTest.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests
2 | {
3 | #region using
4 |
5 | using System;
6 | using System.IO;
7 |
8 | using NUnit.Framework;
9 |
10 | using OpenQA.Selenium.Remote;
11 |
12 | #endregion
13 |
14 | public class BaseTest
15 | {
16 | #region Public Properties
17 |
18 | public RemoteWebDriver Driver { get; set; }
19 |
20 | #endregion
21 |
22 | #region Public Methods and Operators
23 |
24 | [SetUp]
25 | public void SetUp()
26 | {
27 | var dc = new DesiredCapabilities();
28 | dc.SetCapability("app", Path.Combine(Environment.CurrentDirectory, "WindowsFormsTestApplication.exe"));
29 | dc.SetCapability("launchDelay", 2);
30 | this.Driver = new RemoteWebDriver(new Uri("http://localhost:9999"), dc);
31 | }
32 |
33 | [TearDown]
34 | public void TearDown()
35 | {
36 | this.Driver.Close();
37 | }
38 |
39 | #endregion
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/ClearElementTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class ClearElementTests : BaseForMainWindowTest
12 | {
13 |
14 | #region Public Methods and Operators
15 |
16 | [Test]
17 | public void ClearTextBox()
18 | {
19 | var textBox = this.MainWindow.FindElement(By.Id("TextBox1"));
20 | textBox.Clear();
21 |
22 | Assert.AreEqual(string.Empty, textBox.Text);
23 | }
24 |
25 | #endregion
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/ClickElementTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | [TestFixture]
12 | public class ClickElementTests : BaseForMainWindowTest
13 | {
14 | #region Public Methods and Operators
15 |
16 | [Test]
17 | public void ClickButtonWhichSetsText()
18 | {
19 | this.MainWindow.FindElement(By.Id("SetTextButton")).Click();
20 |
21 | Assert.AreEqual("CARAMBA", this.MainWindow.FindElement(By.Id("TextBox1")).Text);
22 | }
23 |
24 | #endregion
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/CloseTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using System.Diagnostics;
6 |
7 | using NUnit.Framework;
8 |
9 | #endregion
10 |
11 | [TestFixture]
12 | public class CloseTests
13 | {
14 | #region Fields
15 |
16 | private Process appProcess;
17 |
18 | private BaseForMainWindowTest baseForMainWindowTest;
19 |
20 | #endregion
21 |
22 | #region Public Methods and Operators
23 |
24 | [Test]
25 | public void CloseApplication()
26 | {
27 | this.baseForMainWindowTest.TearDown();
28 |
29 | Assert.IsTrue(this.appProcess.HasExited);
30 | }
31 |
32 | [Test, Ignore("Application not have needed elements")]
33 | public void CloseApplicationWithOpenedDialogWindow()
34 | {
35 | // TODO: Extend WindowsFormsTestApplication
36 | }
37 |
38 | [SetUp]
39 | public void SetUp()
40 | {
41 | this.baseForMainWindowTest = new BaseForMainWindowTest();
42 | this.baseForMainWindowTest.SetUp();
43 |
44 | this.appProcess = Process.GetProcessesByName("WindowsFormsTestApplication")[0];
45 | }
46 |
47 | #endregion
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/FindTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | [TestFixture]
12 | public class FindTests : BaseTest
13 | {
14 | #region Public Properties
15 |
16 | public IWebElement MainWindow
17 | {
18 | get
19 | {
20 | var mainWindowStrategy = By.XPath("/*[@AutomationId='Form1']");
21 | return this.Driver.FindElement(mainWindowStrategy);
22 | }
23 | }
24 |
25 | #endregion
26 |
27 | #region Public Methods and Operators
28 |
29 | [Test]
30 | public void FindChildElementById()
31 | {
32 | var child = this.MainWindow.FindElement(By.Id("TextBox1"));
33 | Assert.NotNull(child);
34 | }
35 |
36 | [Test]
37 | public void FindChildElementByName()
38 | {
39 | var child = this.MainWindow.FindElement(By.Name("TextBox1"));
40 | Assert.NotNull(child);
41 | }
42 |
43 | [Test]
44 | public void FindElementById()
45 | {
46 | var element = this.Driver.FindElement(By.Id("TextBox1"));
47 | Assert.NotNull(element);
48 | }
49 |
50 | [Test]
51 | public void FindElementByName()
52 | {
53 | var element = this.Driver.FindElement(By.Name("TextBox1"));
54 | Assert.NotNull(element);
55 | }
56 |
57 | [Test]
58 | public void FindElements()
59 | {
60 | var comboBox = this.MainWindow.FindElement(By.Id("TextComboBox"));
61 | var elements = comboBox.FindElements(By.Id(string.Empty));
62 | Assert.AreEqual(6, elements.Count);
63 | }
64 |
65 | [Test]
66 | public void FindNoElements()
67 | {
68 | var elements = this.MainWindow.FindElements(By.Id("UnexistId"));
69 | Assert.AreEqual(0, elements.Count);
70 | }
71 |
72 | #endregion
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/GetActiveElementTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class GetActiveElementTests : BaseForMainWindowTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | public void GetActiveElement()
17 | {
18 | var textBox = this.MainWindow.FindElement(By.Id("TextBox1"));
19 | textBox.Click();
20 |
21 | var textBoxToo = this.Driver.SwitchTo().ActiveElement();
22 |
23 | Assert.IsTrue(textBox.Equals(textBoxToo));
24 | }
25 |
26 | #endregion
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/GetElementAttributeTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class GetElementAttributeTests : BaseForMainWindowTest
12 | {
13 | #region Fields
14 |
15 | private IWebElement textBox;
16 |
17 | #endregion
18 |
19 | #region Public Methods and Operators
20 |
21 | [SetUp]
22 | public void FindBaseElement()
23 | {
24 | this.textBox = this.MainWindow.FindElement(By.Id("TextBox1"));
25 | }
26 |
27 | [Test]
28 | public void GetNotSupportedAttribute()
29 | {
30 | var value = this.textBox.GetAttribute("InvalidAttributeName");
31 |
32 | Assert.AreEqual(null, value);
33 | }
34 |
35 | [Test]
36 | public void GetSupportedAttributeByFullPropertyName()
37 | {
38 | var value = this.textBox.GetAttribute("NameProperty");
39 |
40 | Assert.AreEqual("TextBox1", value);
41 | }
42 |
43 | [Test]
44 | public void GetSupportedAttributeByShortPropertyName()
45 | {
46 | var value = this.textBox.GetAttribute("Name");
47 |
48 | Assert.AreEqual("TextBox1", value);
49 | }
50 |
51 | #endregion
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/GetElementSizeTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class GetElementSizeTests : BaseTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [TestCase("TextBox1", 200, 20)]
16 | [TestCase("TextListBox", 200, 95)]
17 | public void GetSizeOfElement(string elementId, int width, int height)
18 | {
19 | var mainWindowStrategy = By.XPath("/*[@AutomationId='Form1']");
20 | var element = this.Driver.FindElement(mainWindowStrategy).FindElement(By.Id(elementId));
21 |
22 | var size = element.Size;
23 |
24 | Assert.AreEqual(width, size.Width);
25 | Assert.AreEqual(height, size.Height);
26 | }
27 |
28 | #endregion
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/GetElementTextTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class GetElementTextTests : BaseForMainWindowTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | public void GetTextBoxText()
17 | {
18 | var textBox = this.MainWindow.FindElement(By.Id("TextBox1"));
19 | Assert.AreEqual("TextBox1", textBox.Text);
20 | }
21 |
22 | #endregion
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/IsElementDisplayedTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class IsElementDisplayedTests : BaseForMainWindowTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | public void IsDisplaydVisibleElement()
17 | {
18 | var element = this.MainWindow.FindElement(By.Id("TextBox1"));
19 |
20 | Assert.IsTrue(element.Displayed);
21 | }
22 |
23 | #endregion
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/IsElementEnabledTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class IsElementEnabledTests : BaseForMainWindowTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | public void IsDisabledElement()
17 | {
18 | var list = this.MainWindow.FindElement(By.Id("TextListBox"));
19 |
20 | var disabledCheckBox = this.MainWindow.FindElement(By.Id("CheckBox1"));
21 | disabledCheckBox.Click();
22 |
23 | Assert.IsFalse(list.Enabled);
24 | }
25 |
26 | [Test]
27 | public void IsEnabledElement()
28 | {
29 | var list = this.MainWindow.FindElement(By.Id("TextListBox"));
30 |
31 | Assert.IsTrue(list.Enabled);
32 | }
33 |
34 | #endregion
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/IsElementSelectedTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class IsElementSelectedTests : BaseForMainWindowTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | public void IsSelectedCheckBox()
17 | {
18 | var checkbox = this.MainWindow.FindElement(By.Id("CheckBox1"));
19 |
20 | Assert.IsTrue(checkbox.Selected);
21 | }
22 |
23 | [Test]
24 | public void IsSelectedListItem()
25 | {
26 | var list = this.MainWindow.FindElement(By.Id("TextListBox"));
27 | var listItem = list.FindElement(By.Name("May"));
28 |
29 | listItem.Click();
30 |
31 | Assert.IsTrue(listItem.Selected);
32 | }
33 |
34 | [Test]
35 | public void IsSelectedTab()
36 | {
37 | var tab = this.MainWindow.FindElement(By.Name("TabItem1"));
38 |
39 | Assert.IsTrue(tab.Selected);
40 | }
41 |
42 | [Test]
43 | public void IsUnselectedCheckBox()
44 | {
45 | var checkbox = this.MainWindow.FindElement(By.Id("CheckBox1"));
46 |
47 | checkbox.Click();
48 |
49 | Assert.IsFalse(checkbox.Selected);
50 | }
51 |
52 | [Test]
53 | public void IsUnselectedListItem()
54 | {
55 | var list = this.MainWindow.FindElement(By.Id("TextListBox"));
56 | var listItem = list.FindElement(By.Name("May"));
57 |
58 | Assert.IsFalse(listItem.Selected);
59 | }
60 |
61 | [Test]
62 | public void IsUnselectedTab()
63 | {
64 | var tab = this.MainWindow.FindElement(By.Name("TabItem2"));
65 |
66 | Assert.IsFalse(tab.Selected);
67 | }
68 |
69 | #endregion
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/MouseClickTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 | using OpenQA.Selenium.Interactions;
9 |
10 | #endregion
11 |
12 | public class MouseClickTests : BaseForMainWindowTest
13 | {
14 | #region Fields
15 |
16 | private Actions action;
17 |
18 | private IWebElement button;
19 |
20 | private IWebElement textBox;
21 |
22 | #endregion
23 |
24 | #region Public Methods and Operators
25 |
26 | [Test]
27 | public void ClickToButton()
28 | {
29 | this.action.MoveToElement(this.button, 1, 1);
30 | this.action.Click();
31 | this.action.Perform();
32 |
33 | Assert.AreEqual("CARAMBA", this.textBox.Text);
34 | }
35 |
36 | [SetUp]
37 | public void SetUpForFindElementsAndCreateActionsClass()
38 | {
39 | this.textBox = this.MainWindow.FindElement(By.Id("TextBox1"));
40 | this.button = this.MainWindow.FindElement(By.Id("SetTextButton"));
41 |
42 | this.action = new Actions(this.Driver);
43 | }
44 |
45 | #endregion
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/MouseDoubleClickTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | #endregion
8 |
9 | public class MouseDoubleClickTests : BaseTest
10 | {
11 | #region Public Methods and Operators
12 |
13 | [Test]
14 | [Ignore("Application not have needed elements")]
15 | public void ClickToButton()
16 | {
17 | // TODO: Extend WindowsFormsTestApplication
18 | }
19 |
20 | #endregion
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/QuitTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using System.Diagnostics;
6 |
7 | using NUnit.Framework;
8 |
9 | #endregion
10 |
11 | [TestFixture]
12 | public class QuitTests
13 | {
14 | #region Fields
15 |
16 | private Process appProcess;
17 |
18 | private BaseForMainWindowTest baseForMainWindowTest;
19 |
20 | #endregion
21 |
22 | #region Public Methods and Operators
23 |
24 | [Test]
25 | public void CloseApplication()
26 | {
27 | this.baseForMainWindowTest.Driver.Quit();
28 |
29 | Assert.IsTrue(this.appProcess.HasExited);
30 | }
31 |
32 | [Test, Ignore("Application not have needed elements")]
33 | public void CloseApplicationWithOpenedDialogWindow()
34 | {
35 | // TODO: Extend WindowsFormsTestApplication
36 | }
37 |
38 | [SetUp]
39 | public void SetUp()
40 | {
41 | this.baseForMainWindowTest = new BaseForMainWindowTest();
42 | this.baseForMainWindowTest.SetUp();
43 |
44 | this.appProcess = Process.GetProcessesByName("WindowsFormsTestApplication")[0];
45 | }
46 |
47 | #endregion
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/SendKeysToActiveElementTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class SendKeysToActiveElementTests : BaseForMainWindowTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | public void SendKeysToActiveElement()
17 | {
18 | var textbox = this.MainWindow.FindElement(By.Id("TextBox1"));
19 | textbox.Click();
20 |
21 | this.Driver.Keyboard.SendKeys("test");
22 |
23 | Assert.AreEqual("TextBox1test", textbox.Text);
24 | }
25 |
26 | #endregion
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/SendKeysToElementTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class SendKeysToElementTests : BaseForMainWindowTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | public void SendEmptyKeysToElement()
17 | {
18 | var textBox = this.MainWindow.FindElement(By.Id("TextBox1"));
19 | textBox.SendKeys(string.Empty);
20 |
21 | Assert.AreEqual(string.Empty, textBox.Text);
22 | }
23 |
24 | [Test]
25 | public void SendKeysToElement()
26 | {
27 | const string NewText = "new test text";
28 |
29 | var textBox = this.MainWindow.FindElement(By.Id("TextBox1"));
30 | textBox.SendKeys(NewText);
31 |
32 | Assert.AreEqual(NewText, textBox.Text);
33 | }
34 |
35 | #endregion
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/CommandTests/TakeScreenshotTests.cs:
--------------------------------------------------------------------------------
1 | namespace WindowsFormsTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | #endregion
8 |
9 | public class TakeScreenshotTests : BaseTest
10 | {
11 | #region Public Methods and Operators
12 |
13 | [Test]
14 | public void IsSelectedListItem()
15 | {
16 | var screenshot = this.Driver.GetScreenshot().ToString();
17 | Assert.That(screenshot.Length, Is.GreaterThan(0));
18 | }
19 |
20 | #endregion
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | #region using
2 |
3 | using System.Reflection;
4 | using System.Runtime.InteropServices;
5 |
6 | #endregion
7 |
8 | // General Information about an assembly is controlled through the following
9 | // set of attributes. Change these attribute values to modify the information
10 | // associated with an assembly.
11 | [assembly: AssemblyTitle("WindowsFormsTestApplication.Tests")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("WindowsFormsTestApplication.Tests")]
16 | [assembly: AssemblyCopyright("Copyright © 2015")]
17 | [assembly: AssemblyTrademark("")]
18 | [assembly: AssemblyCulture("")]
19 |
20 | // Setting ComVisible to false makes the types in this assembly not visible
21 | // to COM components. If you need to access a type in this assembly from
22 | // COM, set the ComVisible attribute to true on that type.
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 | [assembly: Guid("a12835c0-d656-4420-b3e8-271218eea250")]
27 |
28 | // Version information for an assembly consists of the following four values:
29 | // Major Version
30 | // Minor Version
31 | // Build Number
32 | // Revision
33 | // You can specify all the values or you can default the Build and Revision Numbers
34 | // by using the '*' as shown below:
35 | // [assembly: AssemblyVersion("1.0.*")]
36 | [assembly: AssemblyVersion("1.0.0.0")]
37 | [assembly: AssemblyFileVersion("1.0.0.0")]
38 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/WindowsFormsTestApplication.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {DC69009A-39E7-4F02-B721-3CC99B4EA637}
8 | Library
9 | Properties
10 | WindowsFormsTestApplication.Tests
11 | WindowsFormsTestApplication.Tests
12 | v4.5
13 | 512
14 | ..\
15 | true
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 | ..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll
37 | True
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | ..\..\packages\Selenium.WebDriver.2.53.1\lib\net40\WebDriver.dll
46 | True
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | Always
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
85 |
86 |
87 |
88 |
95 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/WindowsFormsTestApplication.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2gis/Winium.Desktop/bc4999ecc5c452839058a71054c685db8854f5c9/src/TestApps.Tests/WindowsFormsTestApplication.Tests/WindowsFormsTestApplication.exe
--------------------------------------------------------------------------------
/src/TestApps.Tests/WindowsFormsTestApplication.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/ActionChainsTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests
2 | {
3 | #region using
4 |
5 | using System.Linq;
6 |
7 | using NUnit.Framework;
8 |
9 | using OpenQA.Selenium;
10 | using OpenQA.Selenium.Interactions;
11 |
12 | #endregion
13 |
14 | [TestFixture]
15 | public class ActionChainsTests : BaseForMainWindowTest
16 | {
17 | #region Public Methods and Operators
18 |
19 | [Test]
20 | public void KeyUpAndKeyDown()
21 | {
22 | var list = this.MainWindow.FindElement(By.Id("TextListBox"));
23 | var items = list.FindElements(By.ClassName("ListBoxItem"));
24 | var first = items.First();
25 | var random = items.ElementAt(3);
26 | var actions = new Actions(this.Driver);
27 |
28 | actions.Click(first).KeyDown(Keys.Shift).Click(random).KeyUp(Keys.Shift).Perform();
29 |
30 | var selectedItemsCount = list.FindElements(By.ClassName("ListBoxItem")).Count(item => item.Selected);
31 |
32 | Assert.AreEqual(4, selectedItemsCount);
33 | }
34 |
35 | #endregion
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/BaseForMainWindowTest.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 | using OpenQA.Selenium.Remote;
9 |
10 | #endregion
11 |
12 | public class BaseForMainWindowTest : BaseTest
13 | {
14 | #region Public Properties
15 |
16 | public IWebElement MainWindow { get; set; }
17 |
18 | #endregion
19 |
20 | #region Public Methods and Operators
21 |
22 | [SetUp]
23 | public void FindMainWindow()
24 | {
25 | this.MainWindow = this.Driver.FindElement(By.XPath("/*[@AutomationId='WpfTestApplicationMainWindow']"));
26 | }
27 |
28 | #endregion
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/BaseTest.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests
2 | {
3 | #region using
4 |
5 | using System;
6 | using System.IO;
7 |
8 | using NUnit.Framework;
9 |
10 | using OpenQA.Selenium;
11 | using OpenQA.Selenium.Remote;
12 |
13 | #endregion
14 |
15 | public class BaseTest
16 | where TDriver : class, IWebDriver
17 | {
18 | #region Public Properties
19 |
20 | public TDriver Driver { get; set; }
21 |
22 | #endregion
23 |
24 | #region Public Methods and Operators
25 |
26 | [SetUp]
27 | public void SetUp()
28 | {
29 | var dc = new DesiredCapabilities();
30 | dc.SetCapability("app", Path.Combine(Environment.CurrentDirectory, "WpfTestApplication.exe"));
31 | dc.SetCapability("launchDelay", 2);
32 | this.Driver = Activator.CreateInstance(typeof(TDriver), new Uri("http://localhost:9999"), dc) as TDriver;
33 | }
34 |
35 | [TearDown]
36 | public void TearDown()
37 | {
38 | this.Driver.Close();
39 | }
40 |
41 | #endregion
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/ClearElementTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class ClearElementTests : BaseForMainWindowTest
12 | {
13 |
14 | #region Public Methods and Operators
15 |
16 | [Test]
17 | public void ClearTextBox()
18 | {
19 | var textBox = this.MainWindow.FindElement(By.Id("TextBox1"));
20 | textBox.Clear();
21 |
22 | Assert.AreEqual(string.Empty, textBox.Text);
23 | }
24 |
25 | #endregion
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/ClickElementTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | [TestFixture]
12 | public class ClickElementTests : BaseForMainWindowTest
13 | {
14 | #region Public Methods and Operators
15 |
16 | [Test]
17 | public void ClickButtonWhichSetsText()
18 | {
19 | this.MainWindow.FindElement(By.Id("SetTextButton")).Click();
20 |
21 | Assert.AreEqual("CARAMBA", this.MainWindow.FindElement(By.Id("TextBox1")).Text);
22 | }
23 |
24 | [Test]
25 | public void ClickByTwoElementsWithPressedControl()
26 | {
27 | var list = this.MainWindow.FindElement(By.Id("TextListBox"));
28 |
29 | var listItem1 = list.FindElement(By.Name("March"));
30 | var listItem2 = list.FindElement(By.Name("January"));
31 | var listItem3 = list.FindElement(By.Name("February"));
32 |
33 | this.Driver.ExecuteScript("input: ctrl_click", listItem1);
34 | this.Driver.ExecuteScript("input: ctrl_click", listItem2);
35 |
36 | Assert.IsTrue(listItem1.Selected);
37 | Assert.IsTrue(listItem2.Selected);
38 | Assert.IsFalse(listItem3.Selected);
39 | }
40 |
41 | [Test]
42 | public void ClickByElementBoundingRecatngleCenter()
43 | {
44 | var list = this.MainWindow.FindElement(By.Id("TextListBox"));
45 |
46 | var listItem1 = list.FindElement(By.Name("March"));
47 |
48 | this.Driver.ExecuteScript("input: brc_click", listItem1);
49 |
50 | Assert.IsTrue(listItem1.Selected);
51 | }
52 |
53 | #endregion
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/CloseTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using System.Diagnostics;
6 |
7 | using NUnit.Framework;
8 |
9 | using OpenQA.Selenium;
10 |
11 | #endregion
12 |
13 | [TestFixture]
14 | public class CloseTests
15 | {
16 | #region Fields
17 |
18 | private Process appProcess;
19 |
20 | private BaseForMainWindowTest baseForMainWindowTest;
21 |
22 | #endregion
23 |
24 | #region Public Methods and Operators
25 |
26 | [Test]
27 | public void CloseApplication()
28 | {
29 | this.baseForMainWindowTest.TearDown();
30 |
31 | Assert.IsTrue(this.appProcess.HasExited);
32 | }
33 |
34 | [Test]
35 | public void CloseApplicationWithOpenedDialogWindow()
36 | {
37 | this.baseForMainWindowTest.FindMainWindow();
38 | var tabItem3 = this.baseForMainWindowTest.MainWindow.FindElement(By.Id("TabItem3"));
39 | tabItem3.Click();
40 | tabItem3.FindElement(By.Id("OpenFileDialogButton")).Click();
41 |
42 | this.baseForMainWindowTest.TearDown();
43 |
44 | Assert.IsTrue(this.appProcess.HasExited);
45 | }
46 |
47 | [SetUp]
48 | public void SetUp()
49 | {
50 | this.baseForMainWindowTest = new BaseForMainWindowTest();
51 | this.baseForMainWindowTest.SetUp();
52 |
53 | this.appProcess = Process.GetProcessesByName("WpfTestApplication")[0];
54 | }
55 |
56 | #endregion
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/FindTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 | using OpenQA.Selenium.Remote;
9 |
10 | #endregion
11 |
12 | [TestFixture]
13 | public class FindTests : BaseTest
14 | {
15 | #region Public Properties
16 |
17 | public IWebElement MainWindow
18 | {
19 | get
20 | {
21 | var mainWindowStrategy = By.XPath("/*[@AutomationId='WpfTestApplicationMainWindow']");
22 | return this.Driver.FindElement(mainWindowStrategy);
23 | }
24 | }
25 |
26 | #endregion
27 |
28 | #region Public Methods and Operators
29 |
30 | [Test]
31 | public void FindChildElementByClassName()
32 | {
33 | var child = this.MainWindow.FindElement(By.ClassName("TextBox"));
34 | Assert.NotNull(child);
35 | }
36 |
37 | [Test]
38 | public void FindChildElementById()
39 | {
40 | var child = this.MainWindow.FindElement(By.Id("TextBox1"));
41 | Assert.NotNull(child);
42 | }
43 |
44 | [Test]
45 | public void FindChildElementByName()
46 | {
47 | var child = this.MainWindow.FindElement(By.Name("IsEnabledTextListBox"));
48 | Assert.NotNull(child);
49 | }
50 |
51 | [Test]
52 | public void FindElementByClassName()
53 | {
54 | var element = this.Driver.FindElement(By.ClassName("Window"));
55 | Assert.NotNull(element);
56 | }
57 |
58 | [Test]
59 | public void FindElementById()
60 | {
61 | var element = this.MainWindow;
62 | Assert.NotNull(element);
63 | }
64 |
65 | [Test]
66 | public void FindElementByName()
67 | {
68 | var element = this.Driver.FindElement(By.Name("MainWindow"));
69 | Assert.NotNull(element);
70 | }
71 |
72 | [Test]
73 | public void FindElements()
74 | {
75 | var comboBox = this.MainWindow.FindElement(By.Id("TextComboBox"));
76 | comboBox.Click();
77 |
78 | var elements = comboBox.FindElements(By.ClassName("ListBoxItem"));
79 | Assert.AreEqual(6, elements.Count);
80 | }
81 |
82 | [Test]
83 | public void FindNoElements()
84 | {
85 | var elements = this.MainWindow.FindElements(By.Id("UnexistId"));
86 | Assert.AreEqual(0, elements.Count);
87 | }
88 |
89 | #endregion
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/GetActiveElementTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class GetActiveElementTests : BaseForMainWindowTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | public void GetActiveElement()
17 | {
18 | var textBox = this.MainWindow.FindElement(By.Id("TextBox1"));
19 | textBox.Click();
20 |
21 | var textBoxToo = this.Driver.SwitchTo().ActiveElement();
22 |
23 | Assert.IsTrue(textBox.Equals(textBoxToo));
24 | }
25 |
26 | #endregion
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/GetElementAttributeTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class GetElementAttributeTests : BaseForMainWindowTest
12 | {
13 | #region Fields
14 |
15 | private IWebElement textBox;
16 |
17 | #endregion
18 |
19 | #region Public Methods and Operators
20 |
21 | [SetUp]
22 | public void FindBaseElement()
23 | {
24 | this.textBox = this.MainWindow.FindElement(By.Id("TextBox1"));
25 | }
26 |
27 | [Test]
28 | public void GetNotSupportedAttribute()
29 | {
30 | var value = this.textBox.GetAttribute("InvalidAttributeName");
31 |
32 | Assert.AreEqual(null, value);
33 | }
34 |
35 | [Test]
36 | public void GetSupportedAttributeByFullPropertyName()
37 | {
38 | var value = this.textBox.GetAttribute("ClassNameProperty");
39 |
40 | Assert.AreEqual("TextBox", value);
41 | }
42 |
43 | [Test]
44 | public void GetSupportedAttributeByShortPropertyName()
45 | {
46 | var value = this.textBox.GetAttribute("ClassName");
47 |
48 | Assert.AreEqual("TextBox", value);
49 | }
50 |
51 | #endregion
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/GetElementSizeTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 | using OpenQA.Selenium.Remote;
9 |
10 | #endregion
11 |
12 | public class GetElementSizeTests : BaseTest
13 | {
14 | #region Public Methods and Operators
15 |
16 | [TestCase("TextBox1", 200, 23)]
17 | [TestCase("TextListBox", 200, 100)]
18 | public void GetSizeOfElement(string elementId, int width, int height)
19 | {
20 | var mainWindowStrategy = By.XPath("/*[@AutomationId='WpfTestApplicationMainWindow']");
21 | var element = this.Driver.FindElement(mainWindowStrategy).FindElement(By.Id(elementId));
22 |
23 | var size = element.Size;
24 |
25 | Assert.AreEqual(width, size.Width);
26 | Assert.AreEqual(height, size.Height);
27 | }
28 |
29 | #endregion
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/GetElementTextTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class GetElementTextTests : BaseForMainWindowTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | public void GetTextBoxText()
17 | {
18 | var textBox = this.MainWindow.FindElement(By.Id("TextBox1"));
19 | Assert.AreEqual("TextBox1", textBox.Text);
20 | }
21 |
22 | #endregion
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/IsElementDisplayedTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class IsElementDisplayedTests : BaseForMainWindowTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | public void IsDisplaydVisibleElement()
17 | {
18 | var element = this.MainWindow.FindElement(By.Id("TextBox1"));
19 |
20 | Assert.IsTrue(element.Displayed);
21 | }
22 |
23 | #endregion
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/IsElementEnabledTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class IsElementEnabledTests : BaseForMainWindowTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | public void IsDisabledElement()
17 | {
18 | var list = this.MainWindow.FindElement(By.Id("TextListBox"));
19 |
20 | var disabledCheckBox = this.MainWindow.FindElement(By.Id("CheckBox1"));
21 | disabledCheckBox.Click();
22 |
23 | Assert.IsFalse(list.Enabled);
24 | }
25 |
26 | [Test]
27 | public void IsEnabledElement()
28 | {
29 | var list = this.MainWindow.FindElement(By.Id("TextListBox"));
30 |
31 | Assert.IsTrue(list.Enabled);
32 | }
33 |
34 | #endregion
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/IsElementSelectedTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public class IsElementSelectedTests : BaseForMainWindowTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | public void IsSelectedCheckBox()
17 | {
18 | var checkbox = this.MainWindow.FindElement(By.Id("CheckBox1"));
19 |
20 | Assert.IsTrue(checkbox.Selected);
21 | }
22 |
23 | [Test]
24 | public void IsSelectedListItem()
25 | {
26 | var list = this.MainWindow.FindElement(By.Id("TextListBox"));
27 | var listItem = list.FindElement(By.Name("May"));
28 |
29 | listItem.Click();
30 |
31 | Assert.IsTrue(listItem.Selected);
32 | }
33 |
34 | [Test]
35 | public void IsSelectedTab()
36 | {
37 | var tab = this.MainWindow.FindElement(By.Name("TabItem1"));
38 |
39 | Assert.IsTrue(tab.Selected);
40 | }
41 |
42 | [Test]
43 | public void IsUnselectedCheckBox()
44 | {
45 | var checkbox = this.MainWindow.FindElement(By.Id("CheckBox1"));
46 |
47 | checkbox.Click();
48 |
49 | Assert.IsFalse(checkbox.Selected);
50 | }
51 |
52 | [Test]
53 | public void IsUnselectedListItem()
54 | {
55 | var list = this.MainWindow.FindElement(By.Id("TextListBox"));
56 | var listItem = list.FindElement(By.Name("May"));
57 |
58 | Assert.IsFalse(listItem.Selected);
59 | }
60 |
61 | [Test]
62 | public void IsUnselectedTab()
63 | {
64 | var tab = this.MainWindow.FindElement(By.Name("TabItem2"));
65 |
66 | Assert.IsFalse(tab.Selected);
67 | }
68 |
69 | #endregion
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/MouseClickTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 | using OpenQA.Selenium.Interactions;
9 |
10 | #endregion
11 |
12 | public class MouseClickTests : BaseForMainWindowTest
13 | {
14 | #region Fields
15 |
16 | private Actions action;
17 |
18 | private IWebElement button;
19 |
20 | private IWebElement textBox;
21 |
22 | #endregion
23 |
24 | #region Public Methods and Operators
25 |
26 | [Test]
27 | public void ClickToButton()
28 | {
29 | this.action.MoveToElement(this.button, 1, 1);
30 | this.action.Click();
31 | this.action.Perform();
32 |
33 | Assert.AreEqual("CARAMBA", this.textBox.Text);
34 | }
35 |
36 | [SetUp]
37 | public void SetUpForFindElementsAndCreateActionsClass()
38 | {
39 | this.textBox = this.MainWindow.FindElement(By.Id("TextBox1"));
40 | this.button = this.MainWindow.FindElement(By.Id("SetTextButton"));
41 |
42 | this.action = new Actions(this.Driver);
43 | }
44 |
45 | #endregion
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/MouseDoubleClickTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium.Remote;
8 |
9 | #endregion
10 |
11 | public class MouseDoubleClickTests : BaseTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | [Ignore("Application not have needed elements")]
17 | public void ClickToButton()
18 | {
19 | // TODO: Extend WpfTestApplication
20 | }
21 |
22 | #endregion
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/MouseMoveToTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using System.Windows;
6 | using System.Windows.Forms;
7 |
8 | using NUnit.Framework;
9 |
10 | using OpenQA.Selenium;
11 | using OpenQA.Selenium.Interactions;
12 |
13 | using Point = System.Drawing.Point;
14 |
15 | #endregion
16 |
17 | public class MouseMoveToTests : BaseForMainWindowTest
18 | {
19 | #region Constants
20 |
21 | private const int StartCrdValue = 10;
22 |
23 | #endregion
24 |
25 | #region Fields
26 |
27 | private Actions action;
28 |
29 | private IWebElement textBox;
30 |
31 | #endregion
32 |
33 | #region Public Methods and Operators
34 |
35 | [Test]
36 | public void MoveByOffset()
37 | {
38 | const int Offset = 50;
39 |
40 | this.action.MoveByOffset(Offset, Offset);
41 | this.action.Perform();
42 | var newPoint = Cursor.Position;
43 |
44 | Assert.That(StartCrdValue + Offset, Is.EqualTo(newPoint.X).Within(1));
45 | Assert.That(StartCrdValue + Offset, Is.EqualTo(newPoint.Y).Within(1));
46 | }
47 |
48 | [Test]
49 | public void MoveToElementWithOffset()
50 | {
51 | const int Offset = 50;
52 | var rect = Rect.Parse(this.textBox.GetAttribute("BoundingRectangle"));
53 |
54 | this.action.MoveToElement(this.textBox, Offset, Offset);
55 | this.action.Perform();
56 | var newPoint = Cursor.Position;
57 |
58 | Assert.That(rect.TopLeft.X + Offset, Is.EqualTo(newPoint.X).Within(1));
59 | Assert.That(rect.TopLeft.Y + Offset, Is.EqualTo(newPoint.Y).Within(1));
60 | }
61 |
62 | [Test]
63 | public void MoveToElementWithoutOffset()
64 | {
65 | var rect = Rect.Parse(this.textBox.GetAttribute("BoundingRectangle"));
66 |
67 | this.action.MoveToElement(this.textBox);
68 | this.action.Perform();
69 | var newPoint = Cursor.Position;
70 |
71 | Assert.That(rect.TopLeft.X + (rect.Width / 2), Is.EqualTo(newPoint.X).Within(1));
72 | Assert.That(rect.TopLeft.Y + (rect.Height / 2), Is.EqualTo(newPoint.Y).Within(1));
73 | }
74 |
75 | [SetUp]
76 | public void SetUpForFindElementAndCreateActionsClass()
77 | {
78 | this.textBox = this.MainWindow.FindElement(By.Id("TextBox1"));
79 | this.action = new Actions(this.Driver);
80 | Cursor.Position = new Point(StartCrdValue, StartCrdValue);
81 | }
82 |
83 | #endregion
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/QuitTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using System.Diagnostics;
6 |
7 | using NUnit.Framework;
8 |
9 | using OpenQA.Selenium;
10 |
11 | #endregion
12 |
13 | [TestFixture]
14 | public class QuitTests
15 | {
16 | #region Fields
17 |
18 | private Process appProcess;
19 |
20 | private BaseForMainWindowTest baseForMainWindowTest;
21 |
22 | #endregion
23 |
24 | #region Public Methods and Operators
25 |
26 | [Test]
27 | public void CloseApplication()
28 | {
29 | this.baseForMainWindowTest.Driver.Quit();
30 |
31 | Assert.IsTrue(this.appProcess.HasExited);
32 | }
33 |
34 | [Test]
35 | public void CloseApplicationWithOpenedDialogWindow()
36 | {
37 | this.baseForMainWindowTest.FindMainWindow();
38 | var tabItem3 = this.baseForMainWindowTest.MainWindow.FindElement(By.Id("TabItem3"));
39 | tabItem3.Click();
40 | tabItem3.FindElement(By.Id("OpenFileDialogButton")).Click();
41 |
42 | this.baseForMainWindowTest.Driver.Quit();
43 |
44 | Assert.IsTrue(this.appProcess.HasExited);
45 | }
46 |
47 | [SetUp]
48 | public void SetUp()
49 | {
50 | this.baseForMainWindowTest = new BaseForMainWindowTest();
51 | this.baseForMainWindowTest.SetUp();
52 |
53 | this.appProcess = Process.GetProcessesByName("WpfTestApplication")[0];
54 | }
55 |
56 | #endregion
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/CommandTests/TakeScreenshotTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.CommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium.Remote;
8 |
9 | #endregion
10 |
11 | public class TakeScreenshotTests : BaseTest
12 | {
13 | #region Public Methods and Operators
14 |
15 | [Test]
16 | public void TakeScreenshotAfterStartApplication()
17 | {
18 | var screenshot = this.Driver.GetScreenshot().ToString();
19 | Assert.That(screenshot.Length, Is.GreaterThan(0));
20 | }
21 |
22 | #endregion
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | #region using
2 |
3 | using System.Reflection;
4 | using System.Runtime.InteropServices;
5 |
6 | #endregion
7 |
8 | // General Information about an assembly is controlled through the following
9 | // set of attributes. Change these attribute values to modify the information
10 | // associated with an assembly.
11 | [assembly: AssemblyTitle("WpfTestApplication.Tests")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("WpfTestApplication.Tests")]
16 | [assembly: AssemblyCopyright("Copyright © 2015")]
17 | [assembly: AssemblyTrademark("")]
18 | [assembly: AssemblyCulture("")]
19 |
20 | // Setting ComVisible to false makes the types in this assembly not visible
21 | // to COM components. If you need to access a type in this assembly from
22 | // COM, set the ComVisible attribute to true on that type.
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 | [assembly: Guid("3b3aeff8-1b5e-4949-b663-650884293f80")]
27 |
28 | // Version information for an assembly consists of the following four values:
29 | // Major Version
30 | // Minor Version
31 | // Build Number
32 | // Revision
33 | // You can specify all the values or you can default the Build and Revision Numbers
34 | // by using the '*' as shown below:
35 | // [assembly: AssemblyVersion("1.0.*")]
36 | [assembly: AssemblyVersion("1.0.0.0")]
37 | [assembly: AssemblyFileVersion("1.0.0.0")]
38 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/TestHelper.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests
2 | {
3 | #region using
4 |
5 | using System.Reflection;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | public static class TestHelper
12 | {
13 | #region Public Methods and Operators
14 |
15 | public static string GetElementId(IWebElement element)
16 | {
17 | return
18 | element.GetType()
19 | .GetProperty("Id", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty)
20 | .GetValue(element, null)
21 | .ToString();
22 | }
23 |
24 | #endregion
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/WiniumCommandTests/ComboBoxCommandsTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.WiniumCommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | [Ignore]
12 | public class ComboBoxCommandsTests : BaseTest
13 | {
14 | #region Public Properties
15 |
16 | public IWebElement ComboBoxElement { get; set; }
17 |
18 | #endregion
19 |
20 | #region Public Methods and Operators
21 |
22 | [Test]
23 | public void CollapseComboBox()
24 | {
25 | this.ComboBoxElement.Click();
26 |
27 | this.Driver.CollapseComboBox(this.ComboBoxElement);
28 |
29 | Assert.IsFalse(this.ComboBoxElement.FindElement(By.Name("Month")).Displayed);
30 | }
31 |
32 | [Test]
33 | public void ExpandComboBox()
34 | {
35 | this.Driver.ExpandComboBox(this.ComboBoxElement);
36 |
37 | Assert.IsTrue(this.ComboBoxElement.FindElement(By.Name("Month")).Displayed);
38 | }
39 |
40 | [Test]
41 | public void ExpectNotSurchElementExceptionIfNoItemsSelected()
42 | {
43 | Assert.Throws(() => this.Driver.FindComboBoxSelctedItem(this.ComboBoxElement));
44 | }
45 |
46 | [Test]
47 | public void FindSelectedItem()
48 | {
49 | this.ComboBoxElement.Click();
50 |
51 | var item = this.ComboBoxElement.FindElement(By.Name("Month"));
52 |
53 | item.Click();
54 |
55 | Assert.IsTrue(this.Driver.FindComboBoxSelctedItem(this.ComboBoxElement).Equals(item));
56 | }
57 |
58 | [Test]
59 | public void IsComboBoxExpanded()
60 | {
61 | this.ComboBoxElement.Click();
62 |
63 | Assert.IsTrue(this.Driver.IsComboBoxExpanded(this.ComboBoxElement));
64 | }
65 |
66 | [SetUp]
67 | public new void SetUp()
68 | {
69 | var mainWindow = this.Driver.FindElement(By.XPath("/*[@AutomationId='WpfTestApplicationMainWindow']"));
70 | this.ComboBoxElement = mainWindow.FindElement(By.Id("TextComboBox"));
71 | }
72 |
73 | #endregion
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/WiniumCommandTests/DataGridCommandsTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.WiniumCommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | [Ignore]
12 | public class DataGridCommandsTests : BaseTest
13 | {
14 | #region Public Properties
15 |
16 | public IWebElement DataGridElement { get; set; }
17 |
18 | #endregion
19 |
20 | #region Public Methods and Operators
21 |
22 | [Test]
23 | public void ExpectNotSurchElementExceptionIfCellUnavailableForSelection()
24 | {
25 | Assert.Throws(() => this.Driver.SelectDataGridCell(this.DataGridElement, 14, 1));
26 | }
27 |
28 | [Test]
29 | public void ExpectNotSurchElementExceptionIfDataGridCellNotExist()
30 | {
31 | Assert.Throws(() => this.Driver.FindDataGridCell(this.DataGridElement, 99, 9));
32 | }
33 |
34 | [Test]
35 | public void ExpectNotSurchElementExceptionIfDataGridCellUnavailable()
36 | {
37 | Assert.Throws(() => this.Driver.FindDataGridCell(this.DataGridElement, 14, 1));
38 | }
39 |
40 | [Test]
41 | public void FindDataGridCell()
42 | {
43 | var dataGridCell = this.Driver.FindDataGridCell(this.DataGridElement, 0, 1);
44 |
45 | Assert.AreEqual("one", dataGridCell.Text);
46 | }
47 |
48 | [Test]
49 | public void GetDataGridColumnCount()
50 | {
51 | var columnCount = this.Driver.GetDataGridColumnCount(this.DataGridElement);
52 |
53 | Assert.AreEqual(2, columnCount);
54 | }
55 |
56 | [Test]
57 | public void GetDataGridRowCount()
58 | {
59 | var rowCount = this.Driver.GetDataGridRowCount(this.DataGridElement);
60 |
61 | Assert.AreEqual(15, rowCount);
62 | }
63 |
64 | [Test]
65 | public void ScrollToDataGridCell()
66 | {
67 | this.Driver.ScrollToDataGridCell(this.DataGridElement, 14, 1);
68 |
69 | var dataGridCell = this.Driver.FindDataGridCell(this.DataGridElement, 14, 1);
70 |
71 | Assert.IsTrue(dataGridCell.Displayed);
72 | }
73 |
74 | [Test]
75 | public void SelectDataGridCell()
76 | {
77 | this.Driver.SelectDataGridCell(this.DataGridElement, 1, 1);
78 | var dataGridCell = this.Driver.FindDataGridCell(this.DataGridElement, 1, 1);
79 |
80 | var dataGridCellToo = this.Driver.SwitchTo().ActiveElement();
81 |
82 | Assert.IsTrue(dataGridCell.Equals(dataGridCellToo));
83 | }
84 |
85 | [SetUp]
86 | public new void SetUp()
87 | {
88 | var mainWindow = this.Driver.FindElement(By.XPath("/*[@AutomationId='WpfTestApplicationMainWindow']"));
89 | var tab = mainWindow.FindElement(By.Name("TabItem4"));
90 | tab.Click();
91 |
92 | this.DataGridElement = tab.FindElement(By.Id("DataGrid"));
93 | }
94 |
95 | #endregion
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/WiniumCommandTests/MenuCommandsTests.cs:
--------------------------------------------------------------------------------
1 | namespace WpfTestApplication.Tests.WiniumCommandTests
2 | {
3 | #region using
4 |
5 | using NUnit.Framework;
6 |
7 | using OpenQA.Selenium;
8 |
9 | #endregion
10 |
11 | [Ignore]
12 | public class MenuCommandsTests : BaseTest
13 | {
14 | #region Public Properties
15 |
16 | public IWebElement MenuElement { get; set; }
17 |
18 | #endregion
19 |
20 | #region Public Methods and Operators
21 |
22 | [Test]
23 | public void ExpectNotSurchElementExceptionIfGetNotExistMenuItem()
24 | {
25 | Assert.Throws(
26 | () => this.Driver.FindMenuItem(this.MenuElement, "Level1$NotExistItem"));
27 | }
28 |
29 | [Test]
30 | public void ExpectNotSurchElementExceptionIfSelectNotExistMenuItem()
31 | {
32 | Assert.Throws(
33 | () => this.Driver.SelectMenuItem(this.MenuElement, "Level1$NotExistItem"));
34 | }
35 |
36 | [Test]
37 | public void FindMenuItem()
38 | {
39 | var menuItem = this.Driver.FindMenuItem(this.MenuElement, "Level1$MultiLevel2$Level3");
40 | Assert.NotNull(menuItem);
41 | }
42 |
43 | [SetUp]
44 | public new void SetUp()
45 | {
46 | var mainWindow = this.Driver.FindElement(By.XPath("/*[@AutomationId='WpfTestApplicationMainWindow']"));
47 | this.MenuElement = mainWindow.FindElement(By.Id("SimpleMenu"));
48 | }
49 |
50 | #endregion
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/WpfTestApplication.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {8B4DB0CD-0853-43A4-8E45-EB7080C1DCD7}
8 | Library
9 | Properties
10 | WpfTestApplication.Tests
11 | WpfTestApplication.Tests
12 | v4.5
13 | 512
14 | ..\
15 | true
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 | ..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll
37 | True
38 |
39 |
40 |
41 |
42 |
43 |
44 | ..\..\packages\Selenium.WebDriver.2.53.1\lib\net40\WebDriver.dll
45 | True
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | Always
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
89 |
90 |
91 |
92 |
99 |
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/WpfTestApplication.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/2gis/Winium.Desktop/bc4999ecc5c452839058a71054c685db8854f5c9/src/TestApps.Tests/WpfTestApplication.Tests/WpfTestApplication.exe
--------------------------------------------------------------------------------
/src/TestApps.Tests/WpfTestApplication.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/Automator/Automator.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.Automator
2 | {
3 | #region using
4 |
5 | using System.Collections.Generic;
6 |
7 | using Winium.Cruciatus;
8 | using Winium.Desktop.Driver.Input;
9 |
10 | #endregion
11 |
12 | internal class Automator
13 | {
14 | #region Static Fields
15 |
16 | private static readonly object LockObject = new object();
17 |
18 | private static volatile Automator instance;
19 |
20 | #endregion
21 |
22 | #region Constructors and Destructors
23 |
24 | public Automator(string session)
25 | {
26 | this.Session = session;
27 | this.ElementsRegistry = new ElementsRegistry();
28 | }
29 |
30 | #endregion
31 |
32 | #region Public Properties
33 |
34 | public Capabilities ActualCapabilities { get; set; }
35 |
36 | public Application Application { get; set; }
37 |
38 | public ElementsRegistry ElementsRegistry { get; private set; }
39 |
40 | public string Session { get; private set; }
41 |
42 | public WiniumKeyboard WiniumKeyboard { get; set; }
43 |
44 | #endregion
45 |
46 | #region Public Methods and Operators
47 |
48 | public static T GetValue(IReadOnlyDictionary parameters, string key) where T : class
49 | {
50 | object valueObject;
51 | parameters.TryGetValue(key, out valueObject);
52 |
53 | return valueObject as T;
54 | }
55 |
56 | public static Automator InstanceForSession(string sessionId)
57 | {
58 | if (instance == null)
59 | {
60 | lock (LockObject)
61 | {
62 | if (instance == null)
63 | {
64 | if (sessionId == null)
65 | {
66 | sessionId = "AwesomeSession";
67 | }
68 |
69 | // TODO: Add actual support for sessions. Temporary return single Automator for any season
70 | instance = new Automator(sessionId);
71 | }
72 | }
73 | }
74 |
75 | return instance;
76 | }
77 |
78 | #endregion
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/Automator/Capabilities.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.Automator
2 | {
3 | #region using
4 |
5 | using Newtonsoft.Json;
6 | using Newtonsoft.Json.Serialization;
7 |
8 | using Winium.Cruciatus.Settings;
9 |
10 | #endregion
11 |
12 | internal class Capabilities
13 | {
14 | #region Constructors and Destructors
15 |
16 | internal Capabilities()
17 | {
18 | this.App = string.Empty;
19 | this.Arguments = string.Empty;
20 | this.LaunchDelay = 0;
21 | this.DebugConnectToRunningApp = false;
22 | this.InnerPort = 9998;
23 | this.KeyboardSimulator = KeyboardSimulatorType.BasedOnInputSimulatorLib;
24 | }
25 |
26 | #endregion
27 |
28 | #region Public Properties
29 |
30 | [JsonProperty("app")]
31 | public string App { get; set; }
32 |
33 | [JsonProperty("args")]
34 | public string Arguments { get; set; }
35 |
36 | [JsonProperty("debugConnectToRunningApp")]
37 | public bool DebugConnectToRunningApp { get; set; }
38 |
39 | [JsonProperty("innerPort")]
40 | public int InnerPort { get; set; }
41 |
42 | [JsonProperty("keyboardSimulator")]
43 | public KeyboardSimulatorType KeyboardSimulator { get; set; }
44 |
45 | [JsonProperty("launchDelay")]
46 | public int LaunchDelay { get; set; }
47 |
48 | #endregion
49 |
50 | #region Public Methods and Operators
51 |
52 | public static Capabilities CapabilitiesFromJsonString(string jsonString)
53 | {
54 | var capabilities = JsonConvert.DeserializeObject(
55 | jsonString,
56 | new JsonSerializerSettings
57 | {
58 | Error =
59 | delegate(object sender, ErrorEventArgs args)
60 | {
61 | args.ErrorContext.Handled = true;
62 | }
63 | });
64 |
65 | return capabilities;
66 | }
67 |
68 | public string CapabilitiesToJsonString()
69 | {
70 | return JsonConvert.SerializeObject(this);
71 | }
72 |
73 | #endregion
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutorDispatchTable.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver
2 | {
3 | #region using
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Reflection;
9 |
10 | using Winium.Desktop.Driver.CommandExecutors;
11 | using Winium.StoreApps.Common;
12 |
13 | #endregion
14 |
15 | internal class CommandExecutorDispatchTable
16 | {
17 | #region Fields
18 |
19 | private Dictionary commandExecutorsRepository;
20 |
21 | #endregion
22 |
23 | #region Constructors and Destructors
24 |
25 | public CommandExecutorDispatchTable()
26 | {
27 | this.ConstructDispatcherTable();
28 | }
29 |
30 | #endregion
31 |
32 | #region Public Methods and Operators
33 |
34 | public CommandExecutorBase GetExecutor(string commandName)
35 | {
36 | Type executorType;
37 | if (this.commandExecutorsRepository.TryGetValue(commandName, out executorType))
38 | {
39 | }
40 | else
41 | {
42 | executorType = typeof(NotImplementedExecutor);
43 | }
44 |
45 | return (CommandExecutorBase)Activator.CreateInstance(executorType);
46 | }
47 |
48 | #endregion
49 |
50 | #region Methods
51 |
52 | private void ConstructDispatcherTable()
53 | {
54 | this.commandExecutorsRepository = new Dictionary();
55 |
56 | // TODO: bad const
57 | const string ExecutorsNamespace = "Winium.Desktop.Driver.CommandExecutors";
58 |
59 | var q =
60 | (from t in Assembly.GetExecutingAssembly().GetTypes()
61 | where t.IsClass && t.Namespace == ExecutorsNamespace
62 | select t).ToArray();
63 |
64 | var fields = typeof(DriverCommand).GetFields(BindingFlags.Public | BindingFlags.Static);
65 | foreach (var field in fields)
66 | {
67 | var localField = field;
68 | var executor = q.FirstOrDefault(x => x.Name.Equals(localField.Name + "Executor"));
69 | if (executor != null)
70 | {
71 | this.commandExecutorsRepository.Add(localField.GetValue(null).ToString(), executor);
72 | }
73 | }
74 | }
75 |
76 | #endregion
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/ClearElementExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | internal class ClearElementExecutor : CommandExecutorBase
4 | {
5 | #region Methods
6 |
7 | protected override string DoImpl()
8 | {
9 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
10 |
11 | var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey);
12 | element.SetText(null);
13 |
14 | return this.JsonResponse();
15 | }
16 |
17 | #endregion
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/ClickElementExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | internal class ClickElementExecutor : CommandExecutorBase
4 | {
5 | #region Methods
6 |
7 | protected override string DoImpl()
8 | {
9 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
10 | this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey).Click();
11 |
12 | return this.JsonResponse();
13 | }
14 |
15 | #endregion
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/CloseExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | internal class CloseExecutor : CommandExecutorBase
4 | {
5 | #region Methods
6 |
7 | protected override string DoImpl()
8 | {
9 | if (!this.Automator.ActualCapabilities.DebugConnectToRunningApp)
10 | {
11 | if (!this.Automator.Application.Close())
12 | {
13 | this.Automator.Application.Kill();
14 | }
15 |
16 | this.Automator.ElementsRegistry.Clear();
17 | }
18 |
19 | return this.JsonResponse();
20 | }
21 |
22 | #endregion
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/CollapseComboBoxExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Core;
6 | using Winium.Cruciatus.Extensions;
7 | using Winium.StoreApps.Common;
8 |
9 | #endregion
10 |
11 | internal class CollapseComboBoxExecutor : CommandExecutorBase
12 | {
13 | #region Methods
14 |
15 | protected override string DoImpl()
16 | {
17 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
18 |
19 | this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey).ToComboBox().Collapse();
20 |
21 | return this.JsonResponse();
22 | }
23 |
24 | #endregion
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/CommandExecutorBase.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System;
6 | using System.Net;
7 |
8 | using Newtonsoft.Json;
9 |
10 | using Winium.Desktop.Driver.Automator;
11 | using Winium.StoreApps.Common;
12 | using Winium.StoreApps.Common.Exceptions;
13 |
14 | #endregion
15 |
16 | internal abstract class CommandExecutorBase
17 | {
18 | #region Public Properties
19 |
20 | public Command ExecutedCommand { get; set; }
21 |
22 | #endregion
23 |
24 | #region Properties
25 |
26 | protected Automator Automator { get; set; }
27 |
28 | #endregion
29 |
30 | #region Public Methods and Operators
31 |
32 | public CommandResponse Do()
33 | {
34 | if (this.ExecutedCommand == null)
35 | {
36 | throw new NullReferenceException("ExecutedCommand property must be set before calling Do");
37 | }
38 |
39 | try
40 | {
41 | var session = this.ExecutedCommand.SessionId;
42 | this.Automator = Automator.InstanceForSession(session);
43 | return CommandResponse.Create(HttpStatusCode.OK, this.DoImpl());
44 | }
45 | catch (AutomationException exception)
46 | {
47 | return CommandResponse.Create(HttpStatusCode.OK, this.JsonResponse(exception.Status, exception));
48 | }
49 | catch (NotImplementedException exception)
50 | {
51 | return CommandResponse.Create(
52 | HttpStatusCode.NotImplemented,
53 | this.JsonResponse(ResponseStatus.UnknownCommand, exception));
54 | }
55 | catch (Exception exception)
56 | {
57 | return CommandResponse.Create(
58 | HttpStatusCode.OK,
59 | this.JsonResponse(ResponseStatus.UnknownError, exception));
60 | }
61 | }
62 |
63 | #endregion
64 |
65 | #region Methods
66 |
67 | protected abstract string DoImpl();
68 |
69 | ///
70 | /// The JsonResponse with SUCCESS status and NULL value.
71 | ///
72 | protected string JsonResponse()
73 | {
74 | return this.JsonResponse(ResponseStatus.Success, null);
75 | }
76 |
77 | protected string JsonResponse(ResponseStatus status, object value)
78 | {
79 | return JsonConvert.SerializeObject(
80 | new JsonResponse(this.Automator.Session, status, value),
81 | Formatting.Indented);
82 | }
83 |
84 | #endregion
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/ElementEqualsExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.StoreApps.Common;
6 |
7 | #endregion
8 |
9 | internal class ElementEqualsExecutor : CommandExecutorBase
10 | {
11 | #region Methods
12 |
13 | protected override string DoImpl()
14 | {
15 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
16 | var otherRegisteredKey = this.ExecutedCommand.Parameters["other"].ToString();
17 |
18 | return this.JsonResponse(ResponseStatus.Success, registeredKey == otherRegisteredKey);
19 | }
20 |
21 | #endregion
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/ExecuteScriptExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Windows.Automation;
8 |
9 | using Newtonsoft.Json.Linq;
10 |
11 | using Winium.Cruciatus.Core;
12 | using Winium.Cruciatus.Elements;
13 | using Winium.Cruciatus.Extensions;
14 | using Winium.StoreApps.Common;
15 | using Winium.StoreApps.Common.Exceptions;
16 |
17 | #endregion
18 |
19 | internal class ExecuteScriptExecutor : CommandExecutorBase
20 | {
21 | #region Constants
22 |
23 | internal const string HelpArgumentsErrorMsg = "Arguments error. See {0} for more information.";
24 |
25 | internal const string HelpUnknownScriptMsg = "Unknown script command '{0} {1}'. See {2} for supported commands.";
26 |
27 | internal const string HelpUrlAutomationScript =
28 | "https://github.com/2gis/Winium.Desktop/wiki/Command-Execute-Script#use-ui-automation-patterns-on-element";
29 |
30 | internal const string HelpUrlInputScript =
31 | "https://github.com/2gis/Winium.Desktop/wiki/Command-Execute-Script#simulate-input";
32 |
33 | internal const string HelpUrlScript = "https://github.com/2gis/Winium.Desktop/wiki/Command-Execute-Script";
34 |
35 | #endregion
36 |
37 | #region Methods
38 |
39 | protected override string DoImpl()
40 | {
41 | var script = this.ExecutedCommand.Parameters["script"].ToString();
42 |
43 | var prefix = string.Empty;
44 | string command;
45 |
46 | var index = script.IndexOf(':');
47 | if (index == -1)
48 | {
49 | command = script;
50 | }
51 | else
52 | {
53 | prefix = script.Substring(0, index);
54 | command = script.Substring(++index).Trim();
55 | }
56 |
57 | switch (prefix)
58 | {
59 | case "input":
60 | this.ExecuteInputScript(command);
61 | break;
62 | case "automation":
63 | this.ExecuteAutomationScript(command);
64 | break;
65 | default:
66 | var msg = string.Format(HelpUnknownScriptMsg, prefix, command, HelpUrlScript);
67 | throw new AutomationException(msg, ResponseStatus.JavaScriptError);
68 | }
69 |
70 | return this.JsonResponse();
71 | }
72 |
73 | private void ExecuteAutomationScript(string command)
74 | {
75 | var args = (JArray)this.ExecutedCommand.Parameters["args"];
76 | var elementId = args[0]["ELEMENT"].ToString();
77 |
78 | var element = this.Automator.ElementsRegistry.GetRegisteredElement(elementId);
79 |
80 | switch (command)
81 | {
82 | case "ValuePattern.SetValue":
83 | this.ValuePatternSetValue(element, args);
84 | break;
85 | default:
86 | var msg = string.Format(HelpUnknownScriptMsg, "automation:", command, HelpUrlAutomationScript);
87 | throw new AutomationException(msg, ResponseStatus.JavaScriptError);
88 | }
89 | }
90 |
91 | private void ExecuteInputScript(string command)
92 | {
93 | var args = (JArray)this.ExecutedCommand.Parameters["args"];
94 | var elementId = args[0]["ELEMENT"].ToString();
95 |
96 | var element = this.Automator.ElementsRegistry.GetRegisteredElement(elementId);
97 |
98 | switch (command)
99 | {
100 | case "ctrl_click":
101 | element.ClickWithPressedCtrl();
102 | return;
103 | case "brc_click":
104 | element.Click(MouseButton.Left, ClickStrategies.BoundingRectangleCenter);
105 | return;
106 | default:
107 | var msg = string.Format(HelpUnknownScriptMsg, "input:", command, HelpUrlInputScript);
108 | throw new AutomationException(msg, ResponseStatus.JavaScriptError);
109 | }
110 | }
111 |
112 | private void ValuePatternSetValue(CruciatusElement element, IEnumerable args)
113 | {
114 | var value = args.ElementAtOrDefault(1);
115 | if (value == null)
116 | {
117 | var msg = string.Format(HelpArgumentsErrorMsg, HelpUrlAutomationScript);
118 | throw new AutomationException(msg, ResponseStatus.JavaScriptError);
119 | }
120 |
121 | element.GetPattern(ValuePattern.Pattern).SetValue(value.ToString());
122 | }
123 |
124 | #endregion
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/ExpandComboBoxExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Core;
6 | using Winium.Cruciatus.Extensions;
7 | using Winium.StoreApps.Common;
8 |
9 | #endregion
10 |
11 | internal class ExpandComboBoxExecutor : CommandExecutorBase
12 | {
13 | #region Methods
14 |
15 | protected override string DoImpl()
16 | {
17 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
18 |
19 | this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey).ToComboBox().Expand();
20 |
21 | return this.JsonResponse();
22 | }
23 |
24 | #endregion
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/FindChildElementExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Desktop.Driver.Extensions;
6 | using Winium.StoreApps.Common;
7 | using Winium.StoreApps.Common.Exceptions;
8 |
9 | #endregion
10 |
11 | internal class FindChildElementExecutor : CommandExecutorBase
12 | {
13 | #region Methods
14 |
15 | protected override string DoImpl()
16 | {
17 | var parentKey = this.ExecutedCommand.Parameters["ID"].ToString();
18 | var searchValue = this.ExecutedCommand.Parameters["value"].ToString();
19 | var searchStrategy = this.ExecutedCommand.Parameters["using"].ToString();
20 |
21 | var parent = this.Automator.ElementsRegistry.GetRegisteredElement(parentKey);
22 | var strategy = ByHelper.GetStrategy(searchStrategy, searchValue);
23 | var element = parent.FindElement(strategy);
24 | if (element == null)
25 | {
26 | throw new AutomationException("Element cannot be found", ResponseStatus.NoSuchElement);
27 | }
28 |
29 | var registeredKey = this.Automator.ElementsRegistry.RegisterElement(element);
30 | var registeredObject = new JsonElementContent(registeredKey);
31 | return this.JsonResponse(ResponseStatus.Success, registeredObject);
32 | }
33 |
34 | #endregion
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/FindChildElementsExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System.Linq;
6 |
7 | using Winium.Desktop.Driver.Extensions;
8 | using Winium.StoreApps.Common;
9 |
10 | #endregion
11 |
12 | internal class FindChildElementsExecutor : CommandExecutorBase
13 | {
14 | #region Methods
15 |
16 | protected override string DoImpl()
17 | {
18 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
19 | var searchValue = this.ExecutedCommand.Parameters["value"].ToString();
20 | var searchStrategy = this.ExecutedCommand.Parameters["using"].ToString();
21 |
22 | var parent = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey);
23 | var strategy = ByHelper.GetStrategy(searchStrategy, searchValue);
24 | var elements = parent.FindElements(strategy);
25 |
26 | var registeredKeys = this.Automator.ElementsRegistry.RegisterElements(elements);
27 | var registeredObjects = registeredKeys.Select(e => new JsonElementContent(e));
28 | return this.JsonResponse(ResponseStatus.Success, registeredObjects);
29 | }
30 |
31 | #endregion
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/FindComboBoxSelectedItemExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Extensions;
6 | using Winium.StoreApps.Common;
7 | using Winium.StoreApps.Common.Exceptions;
8 |
9 | #endregion
10 |
11 | internal class FindComboBoxSelectedItemExecutor : CommandExecutorBase
12 | {
13 | #region Methods
14 |
15 | protected override string DoImpl()
16 | {
17 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
18 |
19 | var comboBox = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey).ToComboBox();
20 |
21 | var selectedItem = comboBox.SelectedItem();
22 | if (selectedItem == null)
23 | {
24 | throw new AutomationException("No items is selected", ResponseStatus.NoSuchElement);
25 | }
26 |
27 | var selectedItemKey = this.Automator.ElementsRegistry.RegisterElement(selectedItem);
28 | var registeredObject = new JsonElementContent(selectedItemKey);
29 |
30 | return this.JsonResponse(ResponseStatus.Success, registeredObject);
31 | }
32 |
33 | #endregion
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/FindDataGridCellExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Elements;
6 | using Winium.Cruciatus.Exceptions;
7 | using Winium.Cruciatus.Extensions;
8 | using Winium.StoreApps.Common;
9 |
10 | #endregion
11 |
12 | internal class FindDataGridCellExecutor : CommandExecutorBase
13 | {
14 | #region Methods
15 |
16 | protected override string DoImpl()
17 | {
18 | var dataGridKey = this.ExecutedCommand.Parameters["ID"].ToString();
19 | var column = int.Parse(this.ExecutedCommand.Parameters["COLUMN"].ToString());
20 | var row = int.Parse(this.ExecutedCommand.Parameters["ROW"].ToString());
21 |
22 | var dataGrid = this.Automator.ElementsRegistry.GetRegisteredElement(dataGridKey).ToDataGrid();
23 |
24 | CruciatusElement dataGridCell;
25 | try
26 | {
27 | dataGridCell = dataGrid.Item(row, column);
28 | }
29 | catch (CruciatusException exception)
30 | {
31 | return this.JsonResponse(ResponseStatus.NoSuchElement, exception);
32 | }
33 |
34 | var registeredKey = this.Automator.ElementsRegistry.RegisterElement(dataGridCell);
35 | var registeredObject = new JsonElementContent(registeredKey);
36 |
37 | return this.JsonResponse(ResponseStatus.Success, registeredObject);
38 | }
39 |
40 | #endregion
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/FindElementExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus;
6 | using Winium.Desktop.Driver.Extensions;
7 | using Winium.StoreApps.Common;
8 | using Winium.StoreApps.Common.Exceptions;
9 |
10 | #endregion
11 |
12 | internal class FindElementExecutor : CommandExecutorBase
13 | {
14 | #region Methods
15 |
16 | protected override string DoImpl()
17 | {
18 | var searchValue = this.ExecutedCommand.Parameters["value"].ToString();
19 | var searchStrategy = this.ExecutedCommand.Parameters["using"].ToString();
20 |
21 | var strategy = ByHelper.GetStrategy(searchStrategy, searchValue);
22 | var element = CruciatusFactory.Root.FindElement(strategy);
23 | if (element == null)
24 | {
25 | throw new AutomationException("Element cannot be found", ResponseStatus.NoSuchElement);
26 | }
27 |
28 | var registeredKey = this.Automator.ElementsRegistry.RegisterElement(element);
29 | var registeredObject = new JsonElementContent(registeredKey);
30 | return this.JsonResponse(ResponseStatus.Success, registeredObject);
31 | }
32 |
33 | #endregion
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/FindElementsExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System.Linq;
6 |
7 | using Winium.Cruciatus;
8 | using Winium.Desktop.Driver.Extensions;
9 | using Winium.StoreApps.Common;
10 |
11 | #endregion
12 |
13 | internal class FindElementsExecutor : CommandExecutorBase
14 | {
15 | #region Methods
16 |
17 | protected override string DoImpl()
18 | {
19 | var searchValue = this.ExecutedCommand.Parameters["value"].ToString();
20 | var searchStrategy = this.ExecutedCommand.Parameters["using"].ToString();
21 |
22 | var strategy = ByHelper.GetStrategy(searchStrategy, searchValue);
23 | var elements = CruciatusFactory.Root.FindElements(strategy);
24 |
25 | var registeredKeys = this.Automator.ElementsRegistry.RegisterElements(elements);
26 | var registeredObjects = registeredKeys.Select(e => new JsonElementContent(e));
27 | return this.JsonResponse(ResponseStatus.Success, registeredObjects);
28 | }
29 |
30 | #endregion
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/FindMenuItemExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Extensions;
6 | using Winium.StoreApps.Common;
7 | using Winium.StoreApps.Common.Exceptions;
8 |
9 | #endregion
10 |
11 | internal class FindMenuItemExecutor : CommandExecutorBase
12 | {
13 | #region Methods
14 |
15 | protected override string DoImpl()
16 | {
17 | var dataGridKey = this.ExecutedCommand.Parameters["ID"].ToString();
18 | var headersPath = this.ExecutedCommand.Parameters["PATH"].ToString();
19 |
20 | var munu = this.Automator.ElementsRegistry.GetRegisteredElement(dataGridKey).ToMenu();
21 |
22 | var element = munu.GetItem(headersPath);
23 | if (element == null)
24 | {
25 | throw new AutomationException("No menu item was found", ResponseStatus.NoSuchElement);
26 | }
27 |
28 | var elementKey = this.Automator.ElementsRegistry.RegisterElement(element);
29 |
30 | return this.JsonResponse(ResponseStatus.Success, new JsonElementContent(elementKey));
31 | }
32 |
33 | #endregion
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/GetActiveElementExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus;
6 | using Winium.StoreApps.Common;
7 |
8 | #endregion
9 |
10 | internal class GetActiveElementExecutor : CommandExecutorBase
11 | {
12 | #region Methods
13 |
14 | protected override string DoImpl()
15 | {
16 | var registeredKey = this.Automator.ElementsRegistry.RegisterElement(CruciatusFactory.FocusedElement);
17 | var registeredObject = new JsonElementContent(registeredKey);
18 | return this.JsonResponse(ResponseStatus.Success, registeredObject);
19 | }
20 |
21 | #endregion
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/GetCurrentWindowHandleExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System.Globalization;
6 | using System.Windows.Automation;
7 |
8 | using Winium.StoreApps.Common;
9 |
10 | #endregion
11 |
12 | internal class GetCurrentWindowHandleExecutor : CommandExecutorBase
13 | {
14 | #region Methods
15 |
16 | protected override string DoImpl()
17 | {
18 | var node = AutomationElement.FocusedElement;
19 | var rootElement = AutomationElement.RootElement;
20 | var treeWalker = TreeWalker.ControlViewWalker;
21 | while (node != rootElement && !node.Current.ControlType.Equals(ControlType.Window))
22 | {
23 | node = treeWalker.GetParent(node);
24 | }
25 |
26 | var result = (node == rootElement)
27 | ? string.Empty
28 | : node.Current.NativeWindowHandle.ToString(CultureInfo.InvariantCulture);
29 | return this.JsonResponse(ResponseStatus.Success, result);
30 | }
31 |
32 | #endregion
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/GetDataGridColumnCountExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Extensions;
6 | using Winium.StoreApps.Common;
7 |
8 | #endregion
9 |
10 | internal class GetDataGridColumnCountExecutor : CommandExecutorBase
11 | {
12 | #region Methods
13 |
14 | protected override string DoImpl()
15 | {
16 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
17 |
18 | var dataGrid = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey).ToDataGrid();
19 |
20 | return this.JsonResponse(ResponseStatus.Success, dataGrid.ColumnCount);
21 | }
22 |
23 | #endregion
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/GetDataGridRowCountExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Extensions;
6 | using Winium.StoreApps.Common;
7 |
8 | #endregion
9 |
10 | internal class GetDataGridRowCountExecutor : CommandExecutorBase
11 | {
12 | #region Methods
13 |
14 | protected override string DoImpl()
15 | {
16 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
17 |
18 | var dataGrid = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey).ToDataGrid();
19 |
20 | return this.JsonResponse(ResponseStatus.Success, dataGrid.RowCount);
21 | }
22 |
23 | #endregion
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/GetElementAttributeExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System;
6 | using System.Windows.Automation;
7 |
8 | using Winium.Cruciatus.Extensions;
9 | using Winium.Desktop.Driver.Extensions;
10 | using Winium.StoreApps.Common;
11 |
12 | #endregion
13 |
14 | internal class GetElementAttributeExecutor : CommandExecutorBase
15 | {
16 | #region Methods
17 |
18 | protected override string DoImpl()
19 | {
20 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
21 | var propertyName = this.ExecutedCommand.Parameters["NAME"].ToString();
22 |
23 | var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey);
24 |
25 | try
26 | {
27 | var property = AutomationPropertyHelper.GetAutomationProperty(propertyName);
28 | var propertyObject = element.GetAutomationPropertyValue(property);
29 |
30 | return this.JsonResponse(ResponseStatus.Success, PrepareValueToSerialize(propertyObject));
31 | }
32 | catch (Exception)
33 | {
34 | return this.JsonResponse();
35 | }
36 | }
37 |
38 | /* Known types:
39 | * string, bool, int - should be as plain text
40 | * System.Windows.Automation.ControlType - should be used `ProgrammaticName` property
41 | * System.Window.Rect, System.Window.Point - overrides `ToString()` method, can serialize
42 | */
43 | private static object PrepareValueToSerialize(object obj)
44 | {
45 | if (obj == null)
46 | {
47 | return null;
48 | }
49 |
50 | if (obj.GetType().IsPrimitive)
51 | {
52 | return obj.ToString();
53 | }
54 |
55 | var controlType = obj as ControlType;
56 | if (controlType != null)
57 | {
58 | return controlType.ProgrammaticName;
59 | }
60 |
61 | return obj;
62 | }
63 |
64 | #endregion
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/GetElementSizeExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System.Collections.Generic;
6 |
7 | using Winium.StoreApps.Common;
8 |
9 | #endregion
10 |
11 | internal class GetElementSizeExecutor : CommandExecutorBase
12 | {
13 | #region Methods
14 |
15 | protected override string DoImpl()
16 | {
17 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
18 |
19 | var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey);
20 |
21 | var boundingRect = element.Properties.BoundingRectangle;
22 |
23 | var response = new Dictionary
24 | {
25 | { "width", boundingRect.Width },
26 | { "height", boundingRect.Height }
27 | };
28 | return this.JsonResponse(ResponseStatus.Success, response);
29 | }
30 |
31 | #endregion
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/GetElementTextExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.StoreApps.Common;
6 |
7 | #endregion
8 |
9 | internal class GetElementTextExecutor : CommandExecutorBase
10 | {
11 | #region Methods
12 |
13 | protected override string DoImpl()
14 | {
15 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
16 |
17 | var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey);
18 |
19 | return this.JsonResponse(ResponseStatus.Success, element.Text());
20 | }
21 |
22 | #endregion
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/GetOrientationExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Core;
6 | using Winium.StoreApps.Common;
7 |
8 | #endregion
9 |
10 | internal class GetOrientationExecutor : CommandExecutorBase
11 | {
12 | #region Methods
13 |
14 | protected override string DoImpl()
15 | {
16 | var orientation = RotationManager.GetCurrentOrientation();
17 |
18 | return this.JsonResponse(ResponseStatus.Success, orientation.ToString());
19 | }
20 |
21 | #endregion
22 | }
23 | }
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/GetWindowHandlesExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System.Linq;
6 | using System.Windows.Automation;
7 |
8 | using Winium.Cruciatus;
9 | using Winium.Cruciatus.Core;
10 | using Winium.Cruciatus.Extensions;
11 | using Winium.StoreApps.Common;
12 |
13 | #endregion
14 |
15 | internal class GetWindowHandlesExecutor : CommandExecutorBase
16 | {
17 | #region Methods
18 |
19 | protected override string DoImpl()
20 | {
21 | var typeProperty = AutomationElement.ControlTypeProperty;
22 | var windows = CruciatusFactory.Root.FindElements(By.AutomationProperty(typeProperty, ControlType.Window));
23 |
24 | var handleProperty = AutomationElement.NativeWindowHandleProperty;
25 | var handles = windows.Select(element => element.GetAutomationPropertyValue(handleProperty));
26 |
27 | return this.JsonResponse(ResponseStatus.Success, handles);
28 | }
29 |
30 | #endregion
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/ImplicitlyWaitExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System;
6 |
7 | using Winium.Cruciatus;
8 | using Winium.StoreApps.Common;
9 |
10 | #endregion
11 |
12 | internal class ImplicitlyWaitExecutor : CommandExecutorBase
13 | {
14 | #region Methods
15 |
16 | protected override string DoImpl()
17 | {
18 | var timeout = this.ExecutedCommand.Parameters["ms"];
19 |
20 | CruciatusFactory.Settings.SearchTimeout = Convert.ToInt32(timeout);
21 |
22 | return this.JsonResponse();
23 | }
24 |
25 | #endregion
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/IsComboBoxExpandedExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Extensions;
6 | using Winium.StoreApps.Common;
7 |
8 | #endregion
9 |
10 | internal class IsComboBoxExpandedExecutor : CommandExecutorBase
11 | {
12 | #region Methods
13 |
14 | protected override string DoImpl()
15 | {
16 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
17 |
18 | var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey);
19 |
20 | return this.JsonResponse(ResponseStatus.Success, element.ToComboBox().IsExpanded);
21 | }
22 |
23 | #endregion
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/IsElementDisplayedExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.StoreApps.Common;
6 |
7 | #endregion
8 |
9 | internal class IsElementDisplayedExecutor : CommandExecutorBase
10 | {
11 | #region Methods
12 |
13 | protected override string DoImpl()
14 | {
15 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
16 |
17 | var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey);
18 |
19 | return this.JsonResponse(ResponseStatus.Success, !element.Properties.IsOffscreen);
20 | }
21 |
22 | #endregion
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/IsElementEnabledExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.StoreApps.Common;
6 |
7 | #endregion
8 |
9 | internal class IsElementEnabledExecutor : CommandExecutorBase
10 | {
11 | #region Methods
12 |
13 | protected override string DoImpl()
14 | {
15 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
16 |
17 | var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey);
18 |
19 | return this.JsonResponse(ResponseStatus.Success, element.Properties.IsEnabled);
20 | }
21 |
22 | #endregion
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/IsElementSelectedExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System.Windows.Automation;
6 |
7 | using Winium.Cruciatus.Exceptions;
8 | using Winium.Cruciatus.Extensions;
9 | using Winium.StoreApps.Common;
10 |
11 | #endregion
12 |
13 | internal class IsElementSelectedExecutor : CommandExecutorBase
14 | {
15 | #region Methods
16 |
17 | protected override string DoImpl()
18 | {
19 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
20 |
21 | var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey);
22 |
23 | bool isSelected;
24 |
25 | try
26 | {
27 | var selectionItemProperty = SelectionItemPattern.IsSelectedProperty;
28 | isSelected = element.GetAutomationPropertyValue(selectionItemProperty);
29 | }
30 | catch (CruciatusException)
31 | {
32 | var toggleStateProperty = TogglePattern.ToggleStateProperty;
33 | var toggleState = element.GetAutomationPropertyValue(toggleStateProperty);
34 |
35 | isSelected = toggleState == ToggleState.On;
36 | }
37 |
38 | return this.JsonResponse(ResponseStatus.Success, isSelected);
39 | }
40 |
41 | #endregion
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/MouseClickExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System;
6 |
7 | using Winium.Cruciatus;
8 | using Winium.Cruciatus.Core;
9 | using Winium.StoreApps.Common;
10 |
11 | #endregion
12 |
13 | internal class MouseClickExecutor : CommandExecutorBase
14 | {
15 | #region Methods
16 |
17 | protected override string DoImpl()
18 | {
19 | var buttonId = Convert.ToInt32(this.ExecutedCommand.Parameters["button"]);
20 |
21 | switch ((MouseButton)buttonId)
22 | {
23 | case MouseButton.Left:
24 | CruciatusFactory.Mouse.LeftButtonClick();
25 | break;
26 |
27 | case MouseButton.Right:
28 | CruciatusFactory.Mouse.RightButtonClick();
29 | break;
30 |
31 | default:
32 | return this.JsonResponse(ResponseStatus.UnknownCommand, "Mouse button behavior is not implemented");
33 | }
34 |
35 | return this.JsonResponse();
36 | }
37 |
38 | #endregion
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/MouseDoubleClickExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus;
6 | using Winium.Cruciatus.Core;
7 |
8 | #endregion
9 |
10 | internal class MouseDoubleClickExecutor : CommandExecutorBase
11 | {
12 | #region Methods
13 |
14 | protected override string DoImpl()
15 | {
16 | CruciatusFactory.Mouse.DoubleClick(MouseButton.Left);
17 | return this.JsonResponse();
18 | }
19 |
20 | #endregion
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/MouseMoveToExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System;
6 |
7 | using Winium.Cruciatus;
8 | using Winium.StoreApps.Common;
9 |
10 | #endregion
11 |
12 | internal class MouseMoveToExecutor : CommandExecutorBase
13 | {
14 | #region Methods
15 |
16 | protected override string DoImpl()
17 | {
18 | var haveElement = this.ExecutedCommand.Parameters.ContainsKey("element");
19 | var haveOffset = this.ExecutedCommand.Parameters.ContainsKey("xoffset")
20 | && this.ExecutedCommand.Parameters.ContainsKey("yoffset");
21 |
22 | if (!(haveElement || haveOffset))
23 | {
24 | // TODO: in the future '400 : invalid argument' will be used
25 | return this.JsonResponse(ResponseStatus.UnknownError, "WRONG PARAMETERS");
26 | }
27 |
28 | var resultPoint = CruciatusFactory.Mouse.CurrentCursorPos;
29 | if (haveElement)
30 | {
31 | var registeredKey = this.ExecutedCommand.Parameters["element"].ToString();
32 | var element = this.Automator.ElementsRegistry.GetRegisteredElementOrNull(registeredKey);
33 | if (element != null)
34 | {
35 | var rect = element.Properties.BoundingRectangle;
36 | resultPoint.X = rect.TopLeft.X;
37 | resultPoint.Y = rect.TopLeft.Y;
38 | if (!haveOffset)
39 | {
40 | resultPoint.X += rect.Width / 2;
41 | resultPoint.Y += rect.Height / 2;
42 | }
43 | }
44 | }
45 |
46 | if (haveOffset)
47 | {
48 | resultPoint.X += Convert.ToInt32(this.ExecutedCommand.Parameters["xoffset"]);
49 | resultPoint.Y += Convert.ToInt32(this.ExecutedCommand.Parameters["yoffset"]);
50 | }
51 |
52 | CruciatusFactory.Mouse.SetCursorPos(resultPoint.X, resultPoint.Y);
53 |
54 | return this.JsonResponse();
55 | }
56 |
57 | #endregion
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/NewSessionExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System.Threading;
6 |
7 | using Newtonsoft.Json;
8 |
9 | using Winium.Cruciatus;
10 | using Winium.Cruciatus.Settings;
11 | using Winium.Desktop.Driver.Automator;
12 | using Winium.Desktop.Driver.Input;
13 | using Winium.StoreApps.Common;
14 |
15 | #endregion
16 |
17 | internal class NewSessionExecutor : CommandExecutorBase
18 | {
19 | #region Methods
20 |
21 | protected override string DoImpl()
22 | {
23 | // It is easier to reparse desired capabilities as JSON instead of re-mapping keys to attributes and calling type conversions,
24 | // so we will take possible one time performance hit by serializing Dictionary and deserializing it as Capabilities object
25 | var serializedCapability =
26 | JsonConvert.SerializeObject(this.ExecutedCommand.Parameters["desiredCapabilities"]);
27 | this.Automator.ActualCapabilities = Capabilities.CapabilitiesFromJsonString(serializedCapability);
28 |
29 | this.InitializeApplication(this.Automator.ActualCapabilities.DebugConnectToRunningApp);
30 | this.InitializeKeyboardEmulator(this.Automator.ActualCapabilities.KeyboardSimulator);
31 |
32 | // Gives sometime to load visuals (needed only in case of slow emulation)
33 | Thread.Sleep(this.Automator.ActualCapabilities.LaunchDelay);
34 |
35 | return this.JsonResponse(ResponseStatus.Success, this.Automator.ActualCapabilities);
36 | }
37 |
38 | private void InitializeApplication(bool debugDoNotDeploy = false)
39 | {
40 | var appPath = this.Automator.ActualCapabilities.App;
41 | var appArguments = this.Automator.ActualCapabilities.Arguments;
42 |
43 | this.Automator.Application = new Application(appPath);
44 | if (!debugDoNotDeploy)
45 | {
46 | this.Automator.Application.Start(appArguments);
47 | }
48 | }
49 |
50 | private void InitializeKeyboardEmulator(KeyboardSimulatorType keyboardSimulatorType)
51 | {
52 | this.Automator.WiniumKeyboard = new WiniumKeyboard(keyboardSimulatorType);
53 |
54 | Logger.Debug("Current keyboard simulator: {0}", keyboardSimulatorType);
55 | }
56 |
57 | #endregion
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/NotImplementedExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System;
6 |
7 | #endregion
8 |
9 | internal class NotImplementedExecutor : CommandExecutorBase
10 | {
11 | #region Methods
12 |
13 | protected override string DoImpl()
14 | {
15 | var msg = string.Format("'{0}' is not valid or implemented command.", this.ExecutedCommand.Name);
16 | throw new NotImplementedException(msg);
17 | }
18 |
19 | #endregion
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/QuitExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | internal class QuitExecutor : CommandExecutorBase
4 | {
5 | #region Methods
6 |
7 | protected override string DoImpl()
8 | {
9 | if (!this.Automator.ActualCapabilities.DebugConnectToRunningApp)
10 | {
11 | if (!this.Automator.Application.Close())
12 | {
13 | this.Automator.Application.Kill();
14 | }
15 |
16 | this.Automator.ElementsRegistry.Clear();
17 | }
18 |
19 | return this.JsonResponse();
20 | }
21 |
22 | #endregion
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/ScreenshotExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus;
6 | using Winium.StoreApps.Common;
7 |
8 | #endregion
9 |
10 | internal class ScreenshotExecutor : CommandExecutorBase
11 | {
12 | #region Methods
13 |
14 | protected override string DoImpl()
15 | {
16 | var screenshot = CruciatusFactory.Screenshoter.GetScreenshot();
17 | var screenshotSource = screenshot.AsBase64String();
18 |
19 | return this.JsonResponse(ResponseStatus.Success, screenshotSource);
20 | }
21 |
22 | #endregion
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/ScrollToComboBoxItemExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Elements;
6 | using Winium.Cruciatus.Exceptions;
7 | using Winium.Cruciatus.Extensions;
8 | using Winium.Desktop.Driver.Extensions;
9 | using Winium.StoreApps.Common;
10 |
11 | #endregion
12 |
13 | internal class ScrollToComboBoxItemExecutor : CommandExecutorBase
14 | {
15 | #region Methods
16 |
17 | protected override string DoImpl()
18 | {
19 | var dataGridKey = this.ExecutedCommand.Parameters["ID"].ToString();
20 | var searchStrategy = this.ExecutedCommand.Parameters["using"].ToString();
21 | var searchValue = this.ExecutedCommand.Parameters["value"].ToString();
22 |
23 | var strategy = ByHelper.GetStrategy(searchStrategy, searchValue);
24 |
25 | var comboBox = this.Automator.ElementsRegistry.GetRegisteredElement(dataGridKey).ToComboBox();
26 |
27 | CruciatusElement element;
28 | try
29 | {
30 | element = comboBox.ScrollTo(strategy);
31 | }
32 | catch (CruciatusException exception)
33 | {
34 | return this.JsonResponse(ResponseStatus.NoSuchElement, exception);
35 | }
36 |
37 | var elementKey = this.Automator.ElementsRegistry.RegisterElement(element);
38 |
39 | return this.JsonResponse(ResponseStatus.Success, new JsonElementContent(elementKey));
40 | }
41 |
42 | #endregion
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/ScrollToDataGridCellExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Exceptions;
6 | using Winium.Cruciatus.Extensions;
7 | using Winium.StoreApps.Common;
8 |
9 | #endregion
10 |
11 | internal class ScrollToDataGridCellExecutor : CommandExecutorBase
12 | {
13 | #region Methods
14 |
15 | protected override string DoImpl()
16 | {
17 | var dataGridKey = this.ExecutedCommand.Parameters["ID"].ToString();
18 | var column = int.Parse(this.ExecutedCommand.Parameters["COLUMN"].ToString());
19 | var row = int.Parse(this.ExecutedCommand.Parameters["ROW"].ToString());
20 |
21 | var dataGrid = this.Automator.ElementsRegistry.GetRegisteredElement(dataGridKey).ToDataGrid();
22 |
23 | try
24 | {
25 | dataGrid.ScrollTo(row, column);
26 | }
27 | catch (CruciatusException exception)
28 | {
29 | return this.JsonResponse(ResponseStatus.NoSuchElement, exception);
30 | }
31 |
32 | return this.JsonResponse();
33 | }
34 |
35 | #endregion
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/ScrollToListBoxItemExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Elements;
6 | using Winium.Cruciatus.Exceptions;
7 | using Winium.Cruciatus.Extensions;
8 | using Winium.Desktop.Driver.Extensions;
9 | using Winium.StoreApps.Common;
10 |
11 | #endregion
12 |
13 | internal class ScrollToListBoxItemExecutor : CommandExecutorBase
14 | {
15 | #region Methods
16 |
17 | protected override string DoImpl()
18 | {
19 | var dataGridKey = this.ExecutedCommand.Parameters["ID"].ToString();
20 | var searchStrategy = this.ExecutedCommand.Parameters["using"].ToString();
21 | var searchValue = this.ExecutedCommand.Parameters["value"].ToString();
22 |
23 | var strategy = ByHelper.GetStrategy(searchStrategy, searchValue);
24 |
25 | var listBox = this.Automator.ElementsRegistry.GetRegisteredElement(dataGridKey).ToListBox();
26 |
27 | CruciatusElement element;
28 | try
29 | {
30 | element = listBox.ScrollTo(strategy);
31 | }
32 | catch (CruciatusException exception)
33 | {
34 | return this.JsonResponse(ResponseStatus.NoSuchElement, exception);
35 | }
36 |
37 | var elementKey = this.Automator.ElementsRegistry.RegisterElement(element);
38 |
39 | return this.JsonResponse(ResponseStatus.Success, new JsonElementContent(elementKey));
40 | }
41 |
42 | #endregion
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/SelectDataGridCellExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Exceptions;
6 | using Winium.Cruciatus.Extensions;
7 | using Winium.StoreApps.Common;
8 |
9 | #endregion
10 |
11 | internal class SelectDataGridCellExecutor : CommandExecutorBase
12 | {
13 | #region Methods
14 |
15 | protected override string DoImpl()
16 | {
17 | var dataGridKey = this.ExecutedCommand.Parameters["ID"].ToString();
18 | var column = int.Parse(this.ExecutedCommand.Parameters["COLUMN"].ToString());
19 | var row = int.Parse(this.ExecutedCommand.Parameters["ROW"].ToString());
20 |
21 | var dataGrid = this.Automator.ElementsRegistry.GetRegisteredElement(dataGridKey).ToDataGrid();
22 |
23 | try
24 | {
25 | dataGrid.SelectCell(row, column);
26 | }
27 | catch (CruciatusException exception)
28 | {
29 | return this.JsonResponse(ResponseStatus.NoSuchElement, exception);
30 | }
31 |
32 | return this.JsonResponse();
33 | }
34 |
35 | #endregion
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/SelectMenuItemExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus.Exceptions;
6 | using Winium.Cruciatus.Extensions;
7 | using Winium.StoreApps.Common;
8 |
9 | #endregion
10 |
11 | internal class SelectMenuItemExecutor : CommandExecutorBase
12 | {
13 | #region Methods
14 |
15 | protected override string DoImpl()
16 | {
17 | var dataGridKey = this.ExecutedCommand.Parameters["ID"].ToString();
18 | var headersPath = this.ExecutedCommand.Parameters["PATH"].ToString();
19 |
20 | var menu = this.Automator.ElementsRegistry.GetRegisteredElement(dataGridKey).ToMenu();
21 |
22 | try
23 | {
24 | menu.SelectItem(headersPath);
25 | }
26 | catch (CruciatusException exception)
27 | {
28 | return this.JsonResponse(ResponseStatus.NoSuchElement, exception);
29 | }
30 |
31 | return this.JsonResponse();
32 | }
33 |
34 | #endregion
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/SendKeysToActiveElementExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System;
6 | using System.Linq;
7 |
8 | #endregion
9 |
10 | internal class SendKeysToActiveElementExecutor : CommandExecutorBase
11 | {
12 | #region Methods
13 |
14 | protected override string DoImpl()
15 | {
16 | var chars = this.ExecutedCommand.Parameters["value"].Select(x => Convert.ToChar(x.ToString()));
17 |
18 | this.Automator.WiniumKeyboard.SendKeys(chars.ToArray());
19 |
20 | return this.JsonResponse();
21 | }
22 |
23 | #endregion
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/SendKeysToElementExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | internal class SendKeysToElementExecutor : CommandExecutorBase
4 | {
5 | #region Methods
6 |
7 | protected override string DoImpl()
8 | {
9 | var registeredKey = this.ExecutedCommand.Parameters["ID"].ToString();
10 | var text = string.Join(string.Empty, this.ExecutedCommand.Parameters["value"]);
11 |
12 | var element = this.Automator.ElementsRegistry.GetRegisteredElement(registeredKey);
13 | element.SetText(text);
14 |
15 | return this.JsonResponse();
16 | }
17 |
18 | #endregion
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/SetOrientationExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System;
6 |
7 | using Winium.StoreApps.Common;
8 | using Winium.Cruciatus.Core;
9 |
10 | #endregion using
11 |
12 | internal class SetOrientationExecutor : CommandExecutorBase
13 | {
14 | #region Methods
15 |
16 | protected override string DoImpl()
17 | {
18 | if (!this.ExecutedCommand.Parameters.ContainsKey("orientation"))
19 | {
20 | // TODO: in the future '400 : invalid argument' will be used
21 | return this.JsonResponse(ResponseStatus.UnknownError, "WRONG PARAMETERS");
22 | }
23 |
24 | var orientation = (DisplayOrientation)Enum.Parse(
25 | typeof(DisplayOrientation),
26 | this.ExecutedCommand.Parameters["orientation"].ToString());
27 |
28 | var result = RotationManager.SetOrientation(orientation);
29 |
30 | string message;
31 |
32 | switch (result)
33 | {
34 | case 0:
35 | return this.JsonResponse();
36 | case 1:
37 | message = "A device restart is required";
38 | break;
39 | case -2:
40 | message = this.ExecutedCommand.Parameters["orientation"] + " not supported by device";
41 | break;
42 | default:
43 | message = "Unknown error: " + result;
44 | break;
45 | }
46 |
47 | Logger.Warn(message);
48 | return this.JsonResponse(ResponseStatus.UnknownError, message);
49 | }
50 |
51 | #endregion
52 | }
53 | }
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/StatusExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System.Collections.Generic;
6 |
7 | using Winium.Desktop.Driver.CommandHelpers;
8 | using Winium.StoreApps.Common;
9 |
10 | #endregion
11 |
12 | internal class StatusExecutor : CommandExecutorBase
13 | {
14 | #region Methods
15 |
16 | protected override string DoImpl()
17 | {
18 | var response = new Dictionary { { "build", new BuildInfo() }, { "os", new OSInfo() } };
19 | return this.JsonResponse(ResponseStatus.Success, response);
20 | }
21 |
22 | #endregion
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/SubmitElementExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using Winium.Cruciatus;
6 |
7 | #endregion
8 |
9 | internal class SubmitElementExecutor : CommandExecutorBase
10 | {
11 | #region Methods
12 |
13 | protected override string DoImpl()
14 | {
15 | CruciatusFactory.Keyboard.SendEnter();
16 | return this.JsonResponse();
17 | }
18 |
19 | #endregion
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandExecutors/SwitchToWindowExecutor.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandExecutors
2 | {
3 | #region using
4 |
5 | using System.Windows.Automation;
6 | using Winium.Cruciatus;
7 | using Winium.Cruciatus.Core;
8 | using Winium.StoreApps.Common;
9 | using Winium.StoreApps.Common.Exceptions;
10 |
11 | #endregion
12 |
13 | internal class SwitchToWindowExecutor : CommandExecutorBase
14 | {
15 | #region Methods
16 |
17 | protected override string DoImpl()
18 | {
19 | var windowHandle = int.Parse(this.ExecutedCommand.Parameters["name"].ToString());
20 |
21 | var handleProperty = AutomationElement.NativeWindowHandleProperty;
22 | var window = CruciatusFactory.Root.FindElement(By.AutomationProperty(handleProperty, windowHandle));
23 | if (window == null)
24 | {
25 | throw new AutomationException("Window cannot be found", ResponseStatus.NoSuchElement);
26 | }
27 |
28 | window.SetFocus();
29 |
30 | return this.JsonResponse();
31 | }
32 |
33 | #endregion
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandHelpers/BuildInfo.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandHelpers
2 | {
3 | #region using
4 |
5 | using System.Reflection;
6 |
7 | using Newtonsoft.Json;
8 |
9 | #endregion
10 |
11 | public class BuildInfo
12 | {
13 | #region Static Fields
14 |
15 | private static string version;
16 |
17 | #endregion
18 |
19 | #region Public Properties
20 |
21 | [JsonProperty("version")]
22 | public string Version
23 | {
24 | get
25 | {
26 | return version ?? (version = Assembly.GetExecutingAssembly().GetName().Version.ToString());
27 | }
28 | }
29 |
30 | #endregion
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandHelpers/OSInfo.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.CommandHelpers
2 | {
3 | #region using
4 |
5 | using System;
6 |
7 | using Newtonsoft.Json;
8 |
9 | #endregion
10 |
11 | // ReSharper disable once InconsistentNaming
12 | public class OSInfo
13 | {
14 | #region Static Fields
15 |
16 | private static string architecture;
17 |
18 | private static string version;
19 |
20 | #endregion
21 |
22 | #region Public Properties
23 |
24 | [JsonProperty("arch")]
25 | public string Architecture
26 | {
27 | get
28 | {
29 | return architecture ?? (architecture = Environment.Is64BitOperatingSystem ? "x64" : "x86");
30 | }
31 | }
32 |
33 | [JsonProperty("name")]
34 | public string Name
35 | {
36 | get
37 | {
38 | return "windows";
39 | }
40 | }
41 |
42 | [JsonProperty("version")]
43 | public string Version
44 | {
45 | get
46 | {
47 | return version ?? (version = Environment.OSVersion.VersionString);
48 | }
49 | }
50 |
51 | #endregion
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/CommandLineOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver
2 | {
3 | #region using
4 |
5 | using CommandLine;
6 | using CommandLine.Text;
7 |
8 | #endregion
9 |
10 | internal class CommandLineOptions
11 | {
12 | #region Public Properties
13 |
14 | [Option("log-path", Required = false,
15 | HelpText = "write server log to file instead of stdout, increases log level to INFO")]
16 | public string LogPath { get; set; }
17 |
18 | [Option("port", Required = false, HelpText = "port to listen on")]
19 | public int? Port { get; set; }
20 |
21 | [Option("url-base", Required = false, HelpText = "base URL path prefix for commands, e.g. wd/url")]
22 | public string UrlBase { get; set; }
23 |
24 | [Option("verbose", Required = false, HelpText = "log verbosely")]
25 | public bool Verbose { get; set; }
26 |
27 | [Option("silent", Required = false, HelpText = "log nothing")]
28 | public bool Silent { get; set; }
29 |
30 | #endregion
31 |
32 | #region Public Methods and Operators
33 |
34 | [HelpOption]
35 | public string GetUsage()
36 | {
37 | return HelpText.AutoBuild(this, current => HelpText.DefaultParsingErrorsHandler(this, current));
38 | }
39 |
40 | #endregion
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/ElementsRegistry.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver
2 | {
3 | #region using
4 |
5 | using System.Collections.Generic;
6 | using System.Globalization;
7 | using System.Linq;
8 | using System.Threading;
9 |
10 | using Winium.Cruciatus.Elements;
11 | using Winium.StoreApps.Common;
12 | using Winium.StoreApps.Common.Exceptions;
13 |
14 | #endregion
15 |
16 | internal class ElementsRegistry
17 | {
18 | #region Static Fields
19 |
20 | private static int safeInstanceCount;
21 |
22 | #endregion
23 |
24 | #region Fields
25 |
26 | private readonly Dictionary registeredElements;
27 |
28 | #endregion
29 |
30 | #region Constructors and Destructors
31 |
32 | public ElementsRegistry()
33 | {
34 | this.registeredElements = new Dictionary();
35 | }
36 |
37 | #endregion
38 |
39 | #region Public Methods and Operators
40 |
41 | public void Clear()
42 | {
43 | this.registeredElements.Clear();
44 | }
45 |
46 | ///
47 | /// Returns CruciatusElement registered with specified key if any exists. Throws if no element is found.
48 | ///
49 | ///
50 | /// Registered element is not found or element has been garbage collected.
51 | ///
52 | public CruciatusElement GetRegisteredElement(string registeredKey)
53 | {
54 | var element = this.GetRegisteredElementOrNull(registeredKey);
55 | if (element != null)
56 | {
57 | return element;
58 | }
59 |
60 | throw new AutomationException("Stale element reference", ResponseStatus.StaleElementReference);
61 | }
62 |
63 | public string RegisterElement(CruciatusElement element)
64 | {
65 | var registeredKey =
66 | this.registeredElements.FirstOrDefault(
67 | x => x.Value.Properties.RuntimeId == element.Properties.RuntimeId).Key;
68 |
69 | if (registeredKey == null)
70 | {
71 | Interlocked.Increment(ref safeInstanceCount);
72 |
73 | // TODO: Maybe use RuntimeId how registeredKey?
74 | registeredKey = element.GetHashCode() + "-"
75 | + safeInstanceCount.ToString(string.Empty, CultureInfo.InvariantCulture);
76 | this.registeredElements.Add(registeredKey, element);
77 | }
78 |
79 | return registeredKey;
80 | }
81 |
82 | public IEnumerable RegisterElements(IEnumerable elements)
83 | {
84 | return elements.Select(this.RegisterElement);
85 | }
86 |
87 | #endregion
88 |
89 | #region Methods
90 |
91 | internal CruciatusElement GetRegisteredElementOrNull(string registeredKey)
92 | {
93 | CruciatusElement element;
94 | this.registeredElements.TryGetValue(registeredKey, out element);
95 | return element;
96 | }
97 |
98 | #endregion
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/Extensions/AutomationPropertyHelper.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.Extensions
2 | {
3 | #region using
4 |
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Reflection;
8 | using System.Windows.Automation;
9 |
10 | using Winium.Cruciatus;
11 | using Winium.Cruciatus.Exceptions;
12 |
13 | #endregion
14 |
15 | internal static class AutomationPropertyHelper
16 | {
17 | #region Static Fields
18 |
19 | private static readonly Dictionary Properties;
20 |
21 | #endregion
22 |
23 | #region Constructors and Destructors
24 |
25 | static AutomationPropertyHelper()
26 | {
27 | Properties =
28 | typeof(AutomationElementIdentifiers).GetFields(BindingFlags.Public | BindingFlags.Static)
29 | .Where(f => f.FieldType == typeof(AutomationProperty))
30 | .ToDictionary(f => f.Name, f => (AutomationProperty)f.GetValue(null));
31 | }
32 |
33 | #endregion
34 |
35 | #region Public Methods and Operators
36 |
37 | internal static AutomationProperty GetAutomationProperty(string propertyName)
38 | {
39 | const string Suffix = "Property";
40 | var fullPropertyName = propertyName.EndsWith(Suffix) ? propertyName : propertyName + Suffix;
41 | if (Properties.ContainsKey(fullPropertyName))
42 | {
43 | return Properties[fullPropertyName];
44 | }
45 |
46 | CruciatusFactory.Logger.Error(string.Format("Property '{0}' is not UI Automation Property", propertyName));
47 | throw new CruciatusException("UNSUPPORTED PROPERTY");
48 | }
49 |
50 | #endregion
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/Extensions/ByHelper.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.Extensions
2 | {
3 | #region using
4 |
5 | using System;
6 | using System.Windows.Automation;
7 |
8 | using Winium.Cruciatus.Core;
9 |
10 | #endregion
11 |
12 | public static class ByHelper
13 | {
14 | #region Public Methods and Operators
15 |
16 | public static By GetStrategy(string strategy, string value)
17 | {
18 | switch (strategy)
19 | {
20 | case "id":
21 | return By.Uid(value);
22 | case "name":
23 | return By.Name(value);
24 | case "class name":
25 | return By.AutomationProperty(AutomationElementIdentifiers.ClassNameProperty, value);
26 | case "xpath":
27 | return By.XPath(value);
28 | default:
29 | throw new NotImplementedException(
30 | string.Format("'{0}' is not valid or implemented searching strategy.", strategy));
31 | }
32 | }
33 |
34 | #endregion
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/HttpRequest.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver
2 | {
3 | #region using
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Globalization;
8 | using System.IO;
9 | using System.Linq;
10 |
11 | #endregion
12 |
13 | public class HttpRequest
14 | {
15 | #region Public Properties
16 |
17 | public Dictionary Headers { get; set; }
18 |
19 | public string MessageBody { get; private set; }
20 |
21 | public string StartingLine { get; private set; }
22 |
23 | #endregion
24 |
25 | #region Public Methods and Operators
26 |
27 | public static HttpRequest ReadFromStreamWithoutClosing(Stream stream)
28 | {
29 | var request = new HttpRequest();
30 | var streamReader = new StreamReader(stream);
31 |
32 | request.StartingLine = streamReader.ReadLine();
33 |
34 | request.Headers = ReadHeaders(streamReader);
35 |
36 | var contentLength = GetContentLength(request.Headers);
37 | request.MessageBody = contentLength != 0 ? ReadContent(streamReader, contentLength) : string.Empty;
38 |
39 | return request;
40 | }
41 |
42 | #endregion
43 |
44 | #region Methods
45 |
46 | private static int GetContentLength(IReadOnlyDictionary headers)
47 | {
48 | var contentLength = 0;
49 | string contentLengthString;
50 | if (headers.TryGetValue("Content-Length", out contentLengthString))
51 | {
52 | contentLength = Convert.ToInt32(contentLengthString, CultureInfo.InvariantCulture);
53 | }
54 |
55 | return contentLength;
56 | }
57 |
58 | // reads the content of a request depending on its length
59 | private static string ReadContent(TextReader textReader, int contentLength)
60 | {
61 | var readBuffer = new char[contentLength];
62 | textReader.Read(readBuffer, 0, readBuffer.Length);
63 | return readBuffer.Aggregate(string.Empty, (current, ch) => current + ch);
64 | }
65 |
66 | private static Dictionary ReadHeaders(TextReader textReader)
67 | {
68 | var headers = new Dictionary();
69 | string header;
70 | while (!string.IsNullOrEmpty(header = textReader.ReadLine()))
71 | {
72 | var splitHeader = header.Split(':');
73 | headers.Add(splitHeader[0], splitHeader[1].Trim(' '));
74 | }
75 |
76 | return headers;
77 | }
78 |
79 | #endregion
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/Input/KeyEvent.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.Input
2 | {
3 | #region using
4 |
5 | using OpenQA.Selenium;
6 |
7 | #endregion
8 |
9 | internal class KeyEvent
10 | {
11 | #region Fields
12 |
13 | private readonly char character;
14 |
15 | private readonly string unicodeKey;
16 |
17 | #endregion
18 |
19 | #region Constructors and Destructors
20 |
21 | public KeyEvent(char ch)
22 | {
23 | this.character = ch;
24 | this.unicodeKey = KeyboardModifiers.GetKeyFromUnicode(this.character);
25 | }
26 |
27 | #endregion
28 |
29 | #region Public Methods and Operators
30 |
31 | public char GetCharacter()
32 | {
33 | return this.character;
34 | }
35 |
36 | public string GetKey()
37 | {
38 | return this.unicodeKey;
39 | }
40 |
41 | public bool IsModifier()
42 | {
43 | return KeyboardModifiers.IsModifier(this.unicodeKey);
44 | }
45 |
46 | public bool IsModifierRelease()
47 | {
48 | return this.GetKey() == Keys.Null;
49 | }
50 |
51 | public bool IsNewLine()
52 | {
53 | return this.GetCharacter() == '\n';
54 | }
55 |
56 | #endregion
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/Input/KeyboardModifiers.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.Input
2 | {
3 | #region using
4 |
5 | using System.Collections.Generic;
6 |
7 | using OpenQA.Selenium;
8 |
9 | using WindowsInput.Native;
10 |
11 | #endregion
12 |
13 | internal class KeyboardModifiers : List
14 | {
15 | #region Static Fields
16 |
17 | private static readonly List Modifiers = new List
18 | {
19 | Keys.Control,
20 | Keys.LeftControl,
21 | Keys.Shift,
22 | Keys.LeftShift,
23 | Keys.Alt,
24 | Keys.LeftAlt
25 | };
26 |
27 | private static readonly Dictionary ModifiersMap =
28 | new Dictionary
29 | {
30 | { Keys.Control, VirtualKeyCode.CONTROL },
31 | { Keys.Shift, VirtualKeyCode.SHIFT },
32 | { Keys.Alt, VirtualKeyCode.MENU },
33 | };
34 |
35 | #endregion
36 |
37 | #region Public Methods and Operators
38 |
39 | public static string GetKeyFromUnicode(char key)
40 | {
41 | return Modifiers.Find(modifier => modifier[0] == key);
42 | }
43 |
44 | public static VirtualKeyCode GetVirtualKeyCode(string key)
45 | {
46 | VirtualKeyCode virtualKey;
47 |
48 | if (ModifiersMap.TryGetValue(key, out virtualKey))
49 | {
50 | return virtualKey;
51 | }
52 |
53 | return default(VirtualKeyCode);
54 | }
55 |
56 | public static bool IsModifier(string key)
57 | {
58 | return Modifiers.Contains(key);
59 | }
60 |
61 | #endregion
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/Input/WiniumKeyboard.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver.Input
2 | {
3 | #region using
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 |
9 | using OpenQA.Selenium;
10 |
11 | using Winium.Cruciatus;
12 | using Winium.Cruciatus.Settings;
13 |
14 | #endregion
15 |
16 | internal class WiniumKeyboard
17 | {
18 | #region Fields
19 |
20 | private readonly KeyboardModifiers modifiers = new KeyboardModifiers();
21 |
22 | #endregion
23 |
24 | #region Constructors and Destructors
25 |
26 | public WiniumKeyboard(KeyboardSimulatorType keyboardSimulatorType)
27 | {
28 | CruciatusFactory.Settings.KeyboardSimulatorType = keyboardSimulatorType;
29 | }
30 |
31 | #endregion
32 |
33 | #region Public Methods and Operators
34 |
35 | public void KeyDown(string keyToPress)
36 | {
37 | var key = KeyboardModifiers.GetVirtualKeyCode(keyToPress);
38 | this.modifiers.Add(keyToPress);
39 | CruciatusFactory.Keyboard.KeyDown(key);
40 | }
41 |
42 | public void KeyUp(string keyToRelease)
43 | {
44 | var key = KeyboardModifiers.GetVirtualKeyCode(keyToRelease);
45 | this.modifiers.Remove(keyToRelease);
46 | CruciatusFactory.Keyboard.KeyUp(key);
47 | }
48 |
49 | public void SendKeys(char[] keysToSend)
50 | {
51 | var builder = keysToSend.Select(key => new KeyEvent(key)).ToList();
52 |
53 | this.SendKeys(builder);
54 | }
55 |
56 | #endregion
57 |
58 | #region Methods
59 |
60 | protected void ReleaseModifiers()
61 | {
62 | var tmp = this.modifiers.ToList();
63 |
64 | foreach (var modifierKey in tmp)
65 | {
66 | this.KeyUp(modifierKey);
67 | }
68 | }
69 |
70 | private void PressOrReleaseModifier(string modifier)
71 | {
72 | if (this.modifiers.Contains(modifier))
73 | {
74 | this.KeyUp(modifier);
75 | }
76 | else
77 | {
78 | this.KeyDown(modifier);
79 | }
80 | }
81 |
82 | private void SendKeys(IEnumerable events)
83 | {
84 | foreach (var keyEvent in events)
85 | {
86 | if (keyEvent.IsNewLine())
87 | {
88 | CruciatusFactory.Keyboard.SendEnter();
89 | }
90 | else if (keyEvent.IsModifierRelease())
91 | {
92 | this.ReleaseModifiers();
93 | }
94 | else if (keyEvent.IsModifier())
95 | {
96 | this.PressOrReleaseModifier(keyEvent.GetKey());
97 | }
98 | else
99 | {
100 | this.Type(keyEvent.GetCharacter());
101 | }
102 | }
103 | }
104 |
105 | private void Type(char key)
106 | {
107 | string str = Convert.ToString(key);
108 |
109 | if (this.modifiers.Contains(Keys.LeftShift) || this.modifiers.Contains(Keys.Shift))
110 | {
111 | str = str.ToUpper();
112 | }
113 |
114 | CruciatusFactory.Keyboard.SendText(str);
115 | }
116 |
117 | #endregion
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/Listener.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver
2 | {
3 | #region using
4 |
5 | using System;
6 | using System.Globalization;
7 | using System.IO;
8 | using System.Net;
9 | using System.Net.Sockets;
10 |
11 | using Winium.StoreApps.Common;
12 |
13 | #endregion
14 |
15 | public class Listener
16 | {
17 | #region Static Fields
18 |
19 | private static string urnPrefix;
20 |
21 | #endregion
22 |
23 | #region Fields
24 |
25 | private UriDispatchTables dispatcher;
26 |
27 | private CommandExecutorDispatchTable executorDispatcher;
28 |
29 | private TcpListener listener;
30 |
31 | #endregion
32 |
33 | #region Constructors and Destructors
34 |
35 | public Listener(int listenerPort)
36 | {
37 | this.Port = listenerPort;
38 | }
39 |
40 | #endregion
41 |
42 | #region Public Properties
43 |
44 | public static string UrnPrefix
45 | {
46 | get
47 | {
48 | return urnPrefix;
49 | }
50 |
51 | set
52 | {
53 | if (!string.IsNullOrEmpty(value))
54 | {
55 | // Normalize prefix
56 | urnPrefix = "/" + value.Trim('/');
57 | }
58 | }
59 | }
60 |
61 | public int Port { get; private set; }
62 |
63 | public Uri Prefix { get; private set; }
64 |
65 | #endregion
66 |
67 | #region Public Methods and Operators
68 |
69 | public void StartListening()
70 | {
71 | try
72 | {
73 | this.listener = new TcpListener(IPAddress.Any, this.Port);
74 |
75 | this.Prefix = new Uri(string.Format(CultureInfo.InvariantCulture, "http://localhost:{0}", this.Port));
76 | this.dispatcher = new UriDispatchTables(new Uri(this.Prefix, UrnPrefix));
77 | this.executorDispatcher = new CommandExecutorDispatchTable();
78 |
79 | // Start listening for client requests.
80 | this.listener.Start();
81 |
82 | // Enter the listening loop
83 | while (true)
84 | {
85 | Logger.Debug("Waiting for a connection...");
86 |
87 | // Perform a blocking call to accept requests.
88 | var client = this.listener.AcceptTcpClient();
89 |
90 | // Get a stream object for reading and writing
91 | using (var stream = client.GetStream())
92 | {
93 | var acceptedRequest = HttpRequest.ReadFromStreamWithoutClosing(stream);
94 |
95 | if (string.IsNullOrWhiteSpace(acceptedRequest.StartingLine))
96 | {
97 | Logger.Warn("ACCEPTED EMPTY REQUEST");
98 | }
99 | else
100 | {
101 | Logger.Debug("ACCEPTED REQUEST {0}", acceptedRequest.StartingLine);
102 |
103 | var response = this.HandleRequest(acceptedRequest);
104 | using (var writer = new StreamWriter(stream))
105 | {
106 | try
107 | {
108 | writer.Write(response);
109 | writer.Flush();
110 | }
111 | catch (IOException ex)
112 | {
113 | Logger.Error("Error occured while writing response: {0}", ex);
114 | }
115 | }
116 | }
117 |
118 | // Shutdown and end connection
119 | }
120 |
121 | client.Close();
122 |
123 | Logger.Debug("Client closed\n");
124 | }
125 | }
126 | catch (SocketException ex)
127 | {
128 | Logger.Error("SocketException occurred while trying to start listner: {0}", ex);
129 | throw;
130 | }
131 | catch (ArgumentException ex)
132 | {
133 | Logger.Error("ArgumentException occurred while trying to start listner: {0}", ex);
134 | throw;
135 | }
136 | finally
137 | {
138 | // Stop listening for new clients.
139 | this.listener.Stop();
140 | }
141 | }
142 |
143 | public void StopListening()
144 | {
145 | this.listener.Stop();
146 | }
147 |
148 | #endregion
149 |
150 | #region Methods
151 |
152 | private string HandleRequest(HttpRequest acceptedRequest)
153 | {
154 | var firstHeaderTokens = acceptedRequest.StartingLine.Split(' ');
155 | var method = firstHeaderTokens[0];
156 | var resourcePath = firstHeaderTokens[1];
157 |
158 | var uriToMatch = new Uri(this.Prefix, resourcePath);
159 | var matched = this.dispatcher.Match(method, uriToMatch);
160 |
161 | if (matched == null)
162 | {
163 | Logger.Warn("Unknown command recived: {0}", uriToMatch);
164 | return HttpResponseHelper.ResponseString(HttpStatusCode.NotFound, "Unknown command " + uriToMatch);
165 | }
166 |
167 | var commandName = matched.Data.ToString();
168 | var commandToExecute = new Command(commandName, acceptedRequest.MessageBody);
169 | foreach (string variableName in matched.BoundVariables.Keys)
170 | {
171 | commandToExecute.Parameters[variableName] = matched.BoundVariables[variableName];
172 | }
173 |
174 | var commandResponse = this.ProcessCommand(commandToExecute);
175 | return HttpResponseHelper.ResponseString(commandResponse.HttpStatusCode, commandResponse.Content);
176 | }
177 |
178 | private CommandResponse ProcessCommand(Command command)
179 | {
180 | Logger.Info("COMMAND {0}\r\n{1}", command.Name, command.Parameters.ToString());
181 | var executor = this.executorDispatcher.GetExecutor(command.Name);
182 | executor.ExecutedCommand = command;
183 | var respnose = executor.Do();
184 | Logger.Debug("RESPONSE:\r\n{0}", respnose);
185 |
186 | return respnose;
187 | }
188 |
189 | #endregion
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/Logger.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver
2 | {
3 | #region using
4 |
5 | using System.ComponentModel;
6 |
7 | using NLog;
8 | using NLog.Targets;
9 |
10 | #endregion
11 |
12 | internal static class Logger
13 | {
14 | #region Constants
15 |
16 | private const string LayoutFormat = "${date:format=HH\\:mm\\:ss} [${level:uppercase=true}] ${message}";
17 |
18 | #endregion
19 |
20 | #region Static Fields
21 |
22 | private static readonly NLog.Logger Log = LogManager.GetLogger("outerdriver");
23 |
24 | #endregion
25 |
26 | #region Public Methods and Operators
27 |
28 | public static void Debug([Localizable(false)] string message, params object[] args)
29 | {
30 | Log.Debug(message, args);
31 | }
32 |
33 | public static void Error([Localizable(false)] string message, params object[] args)
34 | {
35 | Log.Error(message, args);
36 | }
37 |
38 | public static void Fatal([Localizable(false)] string message, params object[] args)
39 | {
40 | Log.Fatal(message, args);
41 | }
42 |
43 | public static void Info([Localizable(false)] string message, params object[] args)
44 | {
45 | Log.Info(message, args);
46 | }
47 |
48 | public static void TargetConsole(bool verbose)
49 | {
50 | var target = new ConsoleTarget { Layout = LayoutFormat };
51 |
52 | NLog.Config.SimpleConfigurator.ConfigureForTargetLogging(target, verbose ? LogLevel.Debug : LogLevel.Fatal);
53 | LogManager.ReconfigExistingLoggers();
54 | }
55 |
56 | public static void TargetFile(string fileName, bool verbose)
57 | {
58 | var target = new FileTarget { Layout = LayoutFormat, FileName = fileName };
59 |
60 | NLog.Config.SimpleConfigurator.ConfigureForTargetLogging(target, verbose ? LogLevel.Debug : LogLevel.Info);
61 | LogManager.ReconfigExistingLoggers();
62 | }
63 |
64 | public static void TargetNull()
65 | {
66 | NLog.Config.SimpleConfigurator.ConfigureForTargetLogging(new NullTarget());
67 | LogManager.ReconfigExistingLoggers();
68 | }
69 |
70 | public static void Trace([Localizable(false)] string message, params object[] args)
71 | {
72 | Log.Trace(message, args);
73 | }
74 |
75 | public static void Warn([Localizable(false)] string message, params object[] args)
76 | {
77 | Log.Warn(message, args);
78 | }
79 |
80 | #endregion
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/Program.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver
2 | {
3 | #region using
4 |
5 | using System;
6 |
7 | #endregion
8 |
9 | internal class Program
10 | {
11 | #region Methods
12 |
13 | [STAThread]
14 | private static void Main(string[] args)
15 | {
16 | var listeningPort = 9999;
17 |
18 | var options = new CommandLineOptions();
19 | if (CommandLine.Parser.Default.ParseArguments(args, options))
20 | {
21 | if (options.Port.HasValue)
22 | {
23 | listeningPort = options.Port.Value;
24 | }
25 | }
26 |
27 | if (options.LogPath != null)
28 | {
29 | Logger.TargetFile(options.LogPath, options.Verbose);
30 | }
31 | else if (!options.Silent)
32 | {
33 | Logger.TargetConsole(options.Verbose);
34 | }
35 | else
36 | {
37 | Logger.TargetNull();
38 | }
39 |
40 | try
41 | {
42 | var listener = new Listener(listeningPort);
43 | Listener.UrnPrefix = options.UrlBase;
44 |
45 | Console.WriteLine("Starting Windows Desktop Driver on port {0}\n", listeningPort);
46 |
47 | listener.StartListening();
48 | }
49 | catch (Exception ex)
50 | {
51 | Logger.Fatal("Failed to start driver: {0}", ex);
52 | throw;
53 | }
54 | }
55 |
56 | #endregion
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | #region using
2 |
3 | using System.Reflection;
4 | using System.Runtime.InteropServices;
5 |
6 | #endregion
7 |
8 | // General Information about an assembly is controlled through the following
9 | // set of attributes. Change these attribute values to modify the information
10 | // associated with an assembly.
11 | [assembly: AssemblyTitle("Winium.Desktop.Driver")]
12 | [assembly: AssemblyDescription("Selenium Remote WebDriver implementation for test automation of Windows application based on WinFroms and WPF platforms.")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("Winium.Desktop.Driver")]
16 | [assembly: AssemblyCopyright("Copyright © 2015")]
17 | [assembly: AssemblyTrademark("")]
18 | [assembly: AssemblyCulture("")]
19 |
20 | // Setting ComVisible to false makes the types in this assembly not visible
21 | // to COM components. If you need to access a type in this assembly from
22 | // COM, set the ComVisible attribute to true on that type.
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 | [assembly: Guid("2878a69b-16cd-455a-8f46-6323e9109635")]
27 |
28 | // Version information for an assembly consists of the following four values:
29 | // Major Version
30 | // Minor Version
31 | // Build Number
32 | // Revision
33 | // You can specify all the values or you can default the Build and Revision Numbers
34 | // by using the '*' as shown below:
35 | // [assembly: AssemblyVersion("1.0.*")]
36 | [assembly: AssemblyVersion("1.2.0.0")]
37 | [assembly: AssemblyFileVersion("1.6.0.*")]
38 | [assembly: AssemblyInformationalVersion("1.6.0")]
39 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/Requester.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.Desktop.Driver
2 | {
3 | #region using
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Globalization;
8 | using System.IO;
9 | using System.Net;
10 |
11 | using Newtonsoft.Json;
12 |
13 | using Winium.StoreApps.Common;
14 | using Winium.StoreApps.Common.Exceptions;
15 |
16 | #endregion
17 |
18 | internal class Requester
19 | {
20 | #region Fields
21 |
22 | private readonly string ip;
23 |
24 | private readonly int port;
25 |
26 | #endregion
27 |
28 | #region Constructors and Destructors
29 |
30 | public Requester(string ip, int port)
31 | {
32 | this.ip = ip;
33 | this.port = port;
34 | }
35 |
36 | #endregion
37 |
38 | #region Public Methods and Operators
39 |
40 | public string ForwardCommand(Command commandToForward, bool verbose = true, int timeout = 0)
41 | {
42 | var serializedCommand = JsonConvert.SerializeObject(commandToForward);
43 |
44 | var response = this.SendRequest(serializedCommand, verbose, timeout);
45 | if (response.Key == HttpStatusCode.OK)
46 | {
47 | return response.Value;
48 | }
49 |
50 | throw new InnerDriverRequestException(response.Value, response.Key);
51 | }
52 |
53 | public KeyValuePair SendRequest(string requestContent, bool verbose, int timeout)
54 | {
55 | var result = string.Empty;
56 | StreamReader reader = null;
57 | HttpWebResponse response = null;
58 | var status = HttpStatusCode.OK;
59 | try
60 | {
61 | // create the request
62 | var uri = string.Format(CultureInfo.InvariantCulture, "http://{0}:{1}", this.ip, this.port);
63 | var request = CreateWebRequest(uri, requestContent);
64 | if (timeout != 0)
65 | {
66 | request.Timeout = timeout;
67 | }
68 |
69 | if (verbose)
70 | {
71 | Logger.Debug("Sending request to inner driver: {0}", uri);
72 | }
73 |
74 | // send the request and get the response
75 | try
76 | {
77 | response = request.GetResponse() as HttpWebResponse;
78 | }
79 | catch (WebException ex)
80 | {
81 | response = ex.Response as HttpWebResponse;
82 | }
83 |
84 | if (response != null)
85 | {
86 | status = response.StatusCode;
87 | var stream = response.GetResponseStream();
88 | if (stream == null)
89 | {
90 | throw new NullReferenceException("No response stream.");
91 | }
92 |
93 | // read and return the response
94 | reader = new StreamReader(stream);
95 | result = reader.ReadToEnd();
96 | }
97 | }
98 | catch (Exception ex)
99 | {
100 | if (verbose)
101 | {
102 | // No need to log exceptions raised when sending service commands like ping.
103 | Logger.Error("Error occurred while trying to send request to inner driver: {0}", ex);
104 | }
105 | }
106 | finally
107 | {
108 | if (response != null)
109 | {
110 | response.Close();
111 | }
112 |
113 | if (reader != null)
114 | {
115 | reader.Close();
116 | }
117 | }
118 |
119 | return new KeyValuePair(status, result);
120 | }
121 |
122 | #endregion
123 |
124 | #region Methods
125 |
126 | private static HttpWebRequest CreateWebRequest(string uri, string content)
127 | {
128 | // create request
129 | var request = (HttpWebRequest)WebRequest.Create(uri);
130 | request.ContentType = "application/json";
131 | request.Method = "POST";
132 | request.KeepAlive = false;
133 |
134 | // write request body
135 | if (!string.IsNullOrEmpty(content))
136 | {
137 | var writer = new StreamWriter(request.GetRequestStream());
138 | writer.Write(content);
139 | writer.Close();
140 | }
141 |
142 | return request;
143 | }
144 |
145 | #endregion
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/Winium.Desktop.Driver/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/Winium.StoreApps.Common/Command.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.StoreApps.Common
2 | {
3 | #region
4 |
5 | using System.Collections.Generic;
6 |
7 | using Newtonsoft.Json;
8 | using Newtonsoft.Json.Linq;
9 |
10 | #endregion
11 |
12 | public class Command
13 | {
14 | #region Fields
15 |
16 | private IDictionary commandParameters = new JObject();
17 |
18 | #endregion
19 |
20 | #region Constructors and Destructors
21 |
22 | public Command(string name, IDictionary parameters)
23 | {
24 | this.Name = name;
25 | if (parameters != null)
26 | {
27 | this.Parameters = parameters;
28 | }
29 | }
30 |
31 | public Command(string name, string jsonParameters)
32 | : this(name, string.IsNullOrEmpty(jsonParameters) ? null : JObject.Parse(jsonParameters))
33 | {
34 | }
35 |
36 | public Command(string name)
37 | {
38 | this.Name = name;
39 | }
40 |
41 | public Command()
42 | {
43 | }
44 |
45 | #endregion
46 |
47 | #region Public Properties
48 |
49 | ///
50 | /// Gets the command name
51 | ///
52 | [JsonProperty("name")]
53 | public string Name { get; set; }
54 |
55 | ///
56 | /// Gets the parameters of the command
57 | ///
58 | [JsonProperty("parameters")]
59 | public IDictionary Parameters
60 | {
61 | get
62 | {
63 | return this.commandParameters;
64 | }
65 |
66 | set
67 | {
68 | this.commandParameters = value;
69 | }
70 | }
71 |
72 | ///
73 | /// Gets the SessionID of the command
74 | ///
75 | [JsonProperty("sessionId")]
76 | public string SessionId { get; set; }
77 |
78 | #endregion
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/Winium.StoreApps.Common/CommandInfo.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.StoreApps.Common
2 | {
3 | public class CommandInfo
4 | {
5 | #region Constants
6 |
7 | public const string DeleteCommand = "DELETE";
8 |
9 | public const string GetCommand = "GET";
10 |
11 | public const string PostCommand = "POST";
12 |
13 | #endregion
14 |
15 | #region Constructors and Destructors
16 |
17 | public CommandInfo(string method, string resourcePath)
18 | {
19 | this.ResourcePath = resourcePath;
20 | this.Method = method;
21 | }
22 |
23 | #endregion
24 |
25 | #region Public Properties
26 |
27 | public string Method { get; set; }
28 |
29 | public string ResourcePath { get; set; }
30 |
31 | #endregion
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Winium.StoreApps.Common/CommandResponse.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.StoreApps.Common
2 | {
3 | #region
4 |
5 | using System.Net;
6 |
7 | #endregion
8 |
9 | public class CommandResponse
10 | {
11 | #region Public Properties
12 |
13 | public string Content { get; set; }
14 |
15 | public HttpStatusCode HttpStatusCode { get; set; }
16 |
17 | #endregion
18 |
19 | #region Public Methods and Operators
20 |
21 | public static CommandResponse Create(HttpStatusCode code, string content)
22 | {
23 | return new CommandResponse { HttpStatusCode = code, Content = content };
24 | }
25 |
26 | public override string ToString()
27 | {
28 | return string.Format("{0}: {1}", this.HttpStatusCode, this.Content);
29 | }
30 |
31 | #endregion
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Winium.StoreApps.Common/Exceptions/AutomationException.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.StoreApps.Common.Exceptions
2 | {
3 | #region
4 |
5 | using System;
6 |
7 | #endregion
8 |
9 | public class AutomationException : Exception
10 | {
11 | #region Fields
12 |
13 | private ResponseStatus responseStatus = ResponseStatus.UnknownError;
14 |
15 | #endregion
16 |
17 | #region Constructors and Destructors
18 |
19 | public AutomationException()
20 | {
21 | }
22 |
23 | public AutomationException(string message, ResponseStatus status)
24 | : base(message)
25 | {
26 | this.Status = status;
27 | }
28 |
29 | public AutomationException(string message, params object[] args)
30 | : base(string.Format(message, args))
31 | {
32 | }
33 |
34 | public AutomationException(string message, Exception innerException)
35 | : base(message, innerException)
36 | {
37 | }
38 |
39 | #endregion
40 |
41 | #region Public Properties
42 |
43 | public ResponseStatus Status
44 | {
45 | get
46 | {
47 | return this.responseStatus;
48 | }
49 |
50 | set
51 | {
52 | this.responseStatus = value;
53 | }
54 | }
55 |
56 | #endregion
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Winium.StoreApps.Common/Exceptions/InnerDriverRequestException.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.StoreApps.Common.Exceptions
2 | {
3 | #region
4 |
5 | using System;
6 | using System.Net;
7 |
8 | #endregion
9 |
10 | public class InnerDriverRequestException : Exception
11 | {
12 | #region Constructors and Destructors
13 |
14 | public InnerDriverRequestException()
15 | {
16 | }
17 |
18 | public InnerDriverRequestException(string message, HttpStatusCode statusCode)
19 | : base(message)
20 | {
21 | this.StatusCode = statusCode;
22 | }
23 |
24 | public InnerDriverRequestException(string message, params object[] args)
25 | : base(string.Format(message, args))
26 | {
27 | }
28 |
29 | public InnerDriverRequestException(string message, Exception innerException)
30 | : base(message, innerException)
31 | {
32 | }
33 |
34 | #endregion
35 |
36 | #region Public Properties
37 |
38 | public HttpStatusCode StatusCode { get; set; }
39 |
40 | #endregion
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Winium.StoreApps.Common/HttpResponseHelper.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.StoreApps.Common
2 | {
3 | #region
4 |
5 | using System.Collections.Generic;
6 | using System.Net;
7 | using System.Text;
8 |
9 | #endregion
10 |
11 | public static class HttpResponseHelper
12 | {
13 | #region Constants
14 |
15 | private const string JsonContentType = "application/json;charset=UTF-8";
16 |
17 | private const string PlainTextContentType = "text/plain";
18 |
19 | #endregion
20 |
21 | #region Static Fields
22 |
23 | private static Dictionary statusCodeDescriptors;
24 |
25 | #endregion
26 |
27 | #region Public Properties
28 |
29 | public static Dictionary StatusCodeDescriptors
30 | {
31 | get
32 | {
33 | return statusCodeDescriptors
34 | ?? (statusCodeDescriptors =
35 | new Dictionary
36 | {
37 | { HttpStatusCode.OK, "OK" },
38 | { HttpStatusCode.BadRequest, "Bad Request" },
39 | { HttpStatusCode.NotFound, "Not Found" },
40 | { HttpStatusCode.NotImplemented, "Not Implemented" }
41 | });
42 | }
43 | }
44 |
45 | #endregion
46 |
47 | #region Public Methods and Operators
48 |
49 | public static bool IsClientError(int code)
50 | {
51 | return code >= 400 && code < 500;
52 | }
53 |
54 | public static string ResponseString(HttpStatusCode statusCode, string content)
55 | {
56 | var contentType = IsClientError((int)statusCode) ? PlainTextContentType : JsonContentType;
57 |
58 | string statusDescription;
59 | StatusCodeDescriptors.TryGetValue(statusCode, out statusDescription);
60 |
61 | var responseString = new StringBuilder();
62 | responseString.AppendLine(string.Format("HTTP/1.1 {0} {1}", (int)statusCode, statusDescription));
63 | responseString.AppendLine(string.Format("Content-Type: {0}", contentType));
64 | responseString.AppendLine("Connection: close");
65 | responseString.AppendLine(string.Empty);
66 | responseString.AppendLine(content);
67 |
68 | return responseString.ToString();
69 | }
70 |
71 | #endregion
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Winium.StoreApps.Common/JsonErrorCodes.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.StoreApps.Common
2 | {
3 | #region using
4 |
5 | using System.Collections.Generic;
6 |
7 | #endregion
8 |
9 | public static class JsonErrorCodes
10 | {
11 | // TODO: in the future ResponseStatus will be removed in favor of HTTPStatus (see https://w3c.github.io/webdriver/webdriver-spec.html#handling-errors)
12 | #region Static Fields
13 |
14 | private static readonly Dictionary ErrorMap = new Dictionary();
15 |
16 | #endregion
17 |
18 | #region Constructors and Destructors
19 |
20 | static JsonErrorCodes()
21 | {
22 | ErrorMap.Add(ResponseStatus.NoSuchElement, "no such element");
23 | ErrorMap.Add(ResponseStatus.NoSuchFrame, "no such frame");
24 | ErrorMap.Add(ResponseStatus.UnknownCommand, "unknown command");
25 | ErrorMap.Add(ResponseStatus.StaleElementReference, "stale element reference");
26 | ErrorMap.Add(ResponseStatus.ElementNotVisible, "element not visible");
27 | ErrorMap.Add(ResponseStatus.InvalidElementState, "invalid element state");
28 | ErrorMap.Add(ResponseStatus.UnknownError, "unknown error");
29 | ErrorMap.Add(ResponseStatus.ElementIsNotSelectable, "element not selectable");
30 | ErrorMap.Add(ResponseStatus.JavaScriptError, "javascript error");
31 | ErrorMap.Add(ResponseStatus.Timeout, "timeout");
32 | ErrorMap.Add(ResponseStatus.NoSuchWindow, "no such window");
33 | ErrorMap.Add(ResponseStatus.InvalidCookieDomain, "invalid cookie domain");
34 | ErrorMap.Add(ResponseStatus.UnableToSetCookie, "unable to set cookie");
35 | ErrorMap.Add(ResponseStatus.UnexpectedAlertOpen, "unexpected alert open");
36 | ErrorMap.Add(ResponseStatus.NoAlertOpenError, "no such alert");
37 | ErrorMap.Add(ResponseStatus.ScriptTimeout, "script timeout");
38 | ErrorMap.Add(ResponseStatus.InvalidElementCoordinates, "invalid element coordinates");
39 | ErrorMap.Add(ResponseStatus.InvalidSelector, "invalid selector");
40 | ErrorMap.Add(ResponseStatus.SessionNotCreatedException, "session not created");
41 | ErrorMap.Add(ResponseStatus.MoveTargetOutOfBounds, "move target out of bounds");
42 |
43 | // TODO: No match in ResponseStatus
44 | /*ErrorMap.Add(400, "invalid argument");
45 | ErrorMap.Add(404, "invalid session id");
46 | ErrorMap.Add(405, "unknown method");
47 | ErrorMap.Add(500, "unsupported operation");*/
48 | }
49 |
50 | #endregion
51 |
52 | #region Public Methods and Operators
53 |
54 | public static string Parse(ResponseStatus status)
55 | {
56 | return ErrorMap.ContainsKey(status) ? ErrorMap[status] : status.ToString();
57 | }
58 |
59 | #endregion
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/Winium.StoreApps.Common/JsonWireClasses.cs:
--------------------------------------------------------------------------------
1 | //
2 | namespace Winium.StoreApps.Common
3 | {
4 | #region
5 |
6 | using System;
7 | using System.Collections.Generic;
8 |
9 | using Newtonsoft.Json;
10 |
11 | #endregion
12 |
13 | public class JsonElementContent
14 | {
15 | #region Constructors and Destructors
16 |
17 | public JsonElementContent(string element)
18 | {
19 | this.Element = element;
20 | }
21 |
22 | #endregion
23 |
24 | #region Public Properties
25 |
26 | [JsonProperty("ELEMENT")]
27 | public string Element { get; set; }
28 |
29 | #endregion
30 | }
31 |
32 | public class JsonResponse
33 | {
34 | #region Constructors and Destructors
35 |
36 | public JsonResponse(string sessionId, ResponseStatus responseCode, object value)
37 | {
38 | this.SessionId = sessionId;
39 | this.Status = responseCode;
40 |
41 | this.Value = responseCode == ResponseStatus.Success ? value : this.PrepareErrorResponse(value);
42 | }
43 |
44 | private object PrepareErrorResponse(object value)
45 | {
46 | var result = new Dictionary { { "error", JsonErrorCodes.Parse(this.Status) } };
47 |
48 | string message;
49 | var exception = value as Exception;
50 | if (exception != null)
51 | {
52 | message = exception.Message;
53 | result.Add("stacktrace", exception.StackTrace);
54 | }
55 | else
56 | {
57 | message = value.ToString();
58 | }
59 |
60 | result.Add("message", message);
61 | return result;
62 | }
63 |
64 | #endregion
65 |
66 | #region Public Properties
67 |
68 | [JsonProperty("sessionId")]
69 | public string SessionId { get; set; }
70 |
71 | [JsonProperty("status")]
72 | public ResponseStatus Status { get; set; }
73 |
74 | [JsonProperty("value")]
75 | public object Value { get; set; }
76 |
77 | #endregion
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/Winium.StoreApps.Common/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | #region
2 |
3 | using System.Reflection;
4 | using System.Resources;
5 |
6 | #endregion
7 |
8 | // General Information about an assembly is controlled through the following
9 | // set of attributes. Change these attribute values to modify the information
10 | // associated with an assembly.
11 | [assembly: AssemblyTitle("Winium.StoreApps.Common")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("Winium.StoreApps.Common")]
16 | [assembly: AssemblyCopyright("Copyright © 2015")]
17 | [assembly: AssemblyTrademark("")]
18 | [assembly: AssemblyCulture("")]
19 | [assembly: NeutralResourcesLanguage("en")]
20 |
21 | // Version information for an assembly consists of the following four values:
22 | // Major Version
23 | // Minor Version
24 | // Build Number
25 | // Revision
26 | // You can specify all the values or you can default the Build and Revision Numbers
27 | // by using the '*' as shown below:
28 | // [assembly: AssemblyVersion("1.0.*")]
29 | [assembly: AssemblyVersion("1.0.*")]
30 |
--------------------------------------------------------------------------------
/src/Winium.StoreApps.Common/ResponseStatus.cs:
--------------------------------------------------------------------------------
1 | namespace Winium.StoreApps.Common
2 | {
3 | public enum ResponseStatus
4 | {
5 | Success = 0,
6 |
7 | NoSuchDriver = 6,
8 |
9 | NoSuchElement = 7,
10 |
11 | NoSuchFrame = 8,
12 |
13 | UnknownCommand = 9,
14 |
15 | StaleElementReference = 10,
16 |
17 | ElementNotVisible = 11,
18 |
19 | InvalidElementState = 12,
20 |
21 | UnknownError = 13,
22 |
23 | ElementIsNotSelectable = 15,
24 |
25 | JavaScriptError = 17,
26 |
27 | XPathLookupError = 19,
28 |
29 | Timeout = 21,
30 |
31 | NoSuchWindow = 23,
32 |
33 | InvalidCookieDomain = 24,
34 |
35 | UnableToSetCookie = 25,
36 |
37 | UnexpectedAlertOpen = 26,
38 |
39 | NoAlertOpenError = 27,
40 |
41 | ScriptTimeout = 28,
42 |
43 | InvalidElementCoordinates = 29,
44 |
45 | ImeNotAvailable = 30,
46 |
47 | ImeEngineActivationFailed = 31,
48 |
49 | InvalidSelector = 32,
50 |
51 | SessionNotCreatedException = 33,
52 |
53 | MoveTargetOutOfBounds = 34
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Winium.StoreApps.Common/Winium.StoreApps.Common.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 12.0
6 | Debug
7 | AnyCPU
8 | {3C8D0B9C-576B-4778-97B1-6839AA944AEE}
9 | Library
10 | Properties
11 | Winium.StoreApps.Common
12 | Winium.StoreApps.Common
13 | en-US
14 | 512
15 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
16 | Profile151
17 | v4.6
18 | ..\
19 | true
20 |
21 |
22 | true
23 | full
24 | false
25 | bin\Debug\
26 | DEBUG;TRACE
27 | prompt
28 | 4
29 |
30 |
31 | pdbonly
32 | true
33 | bin\Release\
34 | TRACE
35 | prompt
36 | 4
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | ..\packages\Newtonsoft.Json.6.0.8\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
64 |
65 |
66 |
67 |
74 |
--------------------------------------------------------------------------------
/src/Winium.StoreApps.Common/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/Winium.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.31101.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Winium.Desktop.Driver", "Winium.Desktop.Driver\Winium.Desktop.Driver.csproj", "{B214C2BA-43FA-486F-AD0B-D4890C1748C0}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{56A74D50-0B52-4130-BF77-C5BD2B3441A6}"
9 | ProjectSection(SolutionItems) = preProject
10 | Settings.StyleCop = Settings.StyleCop
11 | Winium.sln.DotSettings = Winium.sln.DotSettings
12 | EndProjectSection
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Winium.StoreApps.Common", "Winium.StoreApps.Common\Winium.StoreApps.Common.csproj", "{3C8D0B9C-576B-4778-97B1-6839AA944AEE}"
15 | EndProject
16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{7F1DBF6F-6390-429F-BAD0-08D85DE19E0C}"
17 | ProjectSection(SolutionItems) = preProject
18 | .nuget\NuGet.Config = .nuget\NuGet.Config
19 | .nuget\NuGet.targets = .nuget\NuGet.targets
20 | EndProjectSection
21 | EndProject
22 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestApps.Tests", "TestApps.Tests", "{EAE7A411-86B1-4AD5-BF33-81F60CD1A8FC}"
23 | EndProject
24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsFormsTestApplication.Tests", "TestApps.Tests\WindowsFormsTestApplication.Tests\WindowsFormsTestApplication.Tests.csproj", "{DC69009A-39E7-4F02-B721-3CC99B4EA637}"
25 | EndProject
26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfTestApplication.Tests", "TestApps.Tests\WpfTestApplication.Tests\WpfTestApplication.Tests.csproj", "{8B4DB0CD-0853-43A4-8E45-EB7080C1DCD7}"
27 | EndProject
28 | Global
29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
30 | Debug|Any CPU = Debug|Any CPU
31 | Release|Any CPU = Release|Any CPU
32 | EndGlobalSection
33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
34 | {B214C2BA-43FA-486F-AD0B-D4890C1748C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {B214C2BA-43FA-486F-AD0B-D4890C1748C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {B214C2BA-43FA-486F-AD0B-D4890C1748C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {B214C2BA-43FA-486F-AD0B-D4890C1748C0}.Release|Any CPU.Build.0 = Release|Any CPU
38 | {3C8D0B9C-576B-4778-97B1-6839AA944AEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {3C8D0B9C-576B-4778-97B1-6839AA944AEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {3C8D0B9C-576B-4778-97B1-6839AA944AEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {3C8D0B9C-576B-4778-97B1-6839AA944AEE}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {DC69009A-39E7-4F02-B721-3CC99B4EA637}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {DC69009A-39E7-4F02-B721-3CC99B4EA637}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {DC69009A-39E7-4F02-B721-3CC99B4EA637}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {DC69009A-39E7-4F02-B721-3CC99B4EA637}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {8B4DB0CD-0853-43A4-8E45-EB7080C1DCD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
47 | {8B4DB0CD-0853-43A4-8E45-EB7080C1DCD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
48 | {8B4DB0CD-0853-43A4-8E45-EB7080C1DCD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
49 | {8B4DB0CD-0853-43A4-8E45-EB7080C1DCD7}.Release|Any CPU.Build.0 = Release|Any CPU
50 | EndGlobalSection
51 | GlobalSection(SolutionProperties) = preSolution
52 | HideSolutionNode = FALSE
53 | EndGlobalSection
54 | GlobalSection(NestedProjects) = preSolution
55 | {DC69009A-39E7-4F02-B721-3CC99B4EA637} = {EAE7A411-86B1-4AD5-BF33-81F60CD1A8FC}
56 | {8B4DB0CD-0853-43A4-8E45-EB7080C1DCD7} = {EAE7A411-86B1-4AD5-BF33-81F60CD1A8FC}
57 | EndGlobalSection
58 | EndGlobal
59 |
--------------------------------------------------------------------------------