Added Calculator Standard Mode UI Tests (#501)
- Added the CalculatorUIFramework to handle the WinAppDriver logic. - Added Standard Mode smoke tests and BVTs to the CalculatorUITests project. - Removed old UI tests that did not use the CalculatorUIFramework
This commit is contained in:
parent
e9551e3774
commit
2517854836
208
NOTICE.txt
208
NOTICE.txt
@ -37,3 +37,211 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
Appium DotNet Driver
|
||||
|
||||
Copyright 2014-2015 Appium Contributors
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
@ -15,6 +15,10 @@ jobs:
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- powershell: Set-DisplayResolution -Width 1920 -Height 1080 -Force
|
||||
displayName: Set resolution to 1920x1080
|
||||
continueOnError: true
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download AppxBundle and CalculatorUITests
|
||||
inputs:
|
||||
@ -35,11 +39,6 @@ jobs:
|
||||
filePath: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/Calculator/AppPackages/Calculator_$(Build.BuildNumber)_Test/Add-AppDevPackage.ps1
|
||||
arguments: -Force
|
||||
|
||||
- task: WinAppDriver.winappdriver-pipelines-task.winappdriver-pipelines-task.Windows Application Driver@0
|
||||
displayName: 'WinAppDriver - Start'
|
||||
inputs:
|
||||
AgentResolution: 1080p
|
||||
|
||||
- task: VSTest@2
|
||||
displayName: Run CalculatorUITests
|
||||
inputs:
|
||||
@ -47,9 +46,4 @@ jobs:
|
||||
vsTestVersion: 16.0
|
||||
runSettingsFile: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/publish/CalculatorUITests.runsettings
|
||||
platform: ${{ parameters.platform }}
|
||||
configuration: Release
|
||||
|
||||
- task: WinAppDriver.winappdriver-pipelines-task.winappdriver-pipelines-task.Windows Application Driver@0
|
||||
displayName: 'WinAppDriver - Stop'
|
||||
inputs:
|
||||
OperationType: Stop
|
||||
configuration: Release
|
@ -17,7 +17,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcViewModel", "CalcViewMo
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalculatorUnitTests", "CalculatorUnitTests\CalculatorUnitTests.vcxproj", "{D3BAED2C-4B07-4E1D-8807-9D6499450349}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CalculatorUITests", "CalculatorUITests\CalculatorUITests.csproj", "{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CalculatorUITests", "CalculatorUITests\CalculatorUITests.csproj", "{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CalculatorUITestFramework", "CalculatorUITestFramework\CalculatorUITestFramework.csproj", "{96454213-94AF-457D-9DF9-B14F80E7770F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@ -119,6 +121,22 @@ Global
|
||||
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B2C5ADFF-D6B5-48C1-BB8C-571BFD583D7F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{96454213-94AF-457D-9DF9-B14F80E7770F}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Appium.WebDriver" Version="4.0.0.6-beta" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
55
src/CalculatorUITestFramework/HistoryPanel.cs
Normal file
55
src/CalculatorUITestFramework/HistoryPanel.cs
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace CalculatorUITestFramework
|
||||
{
|
||||
public class HistoryPanel
|
||||
{
|
||||
private WindowsDriver<WindowsElement> session => WinAppDriver.Instance.CalculatorSession;
|
||||
public WindowsElement HistoryLabel => this.session.TryFindElementByAccessibilityId("HistoryLabel");
|
||||
public WindowsElement HistoryListView => this.session.TryFindElementByAccessibilityId("HistoryListView");
|
||||
public WindowsElement ClearHistoryButton => this.session.TryFindElementByAccessibilityId("ClearHistory");
|
||||
public WindowsElement HistoryEmptyLabel => this.session.TryFindElementByAccessibilityId("HistoryEmpty");
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets all of the history items listed in the History Pane.
|
||||
/// </summary>
|
||||
/// <returns>A readonly collection of history items.</returns>
|
||||
public ReadOnlyCollection<AppiumWebElement> GetAllHistoryListViewItems()
|
||||
{
|
||||
this.HistoryLabel.Click();
|
||||
this.HistoryListView.WaitForDisplayed();
|
||||
return this.HistoryListView.FindElementsByClassName("ListViewItem");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the History Pane and clicks the delete button if it is visible.
|
||||
/// </summary>
|
||||
public void ClearHistory()
|
||||
{
|
||||
this.HistoryLabel.Click();
|
||||
|
||||
try
|
||||
{
|
||||
this.ClearHistoryButton.Click();
|
||||
}
|
||||
catch(WebDriverException ex)
|
||||
{
|
||||
if (ex.Message.Contains("element could not be located"))
|
||||
{
|
||||
Assert.IsNotNull(this.HistoryEmptyLabel);
|
||||
return;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
42
src/CalculatorUITestFramework/MemoryPanel.cs
Normal file
42
src/CalculatorUITestFramework/MemoryPanel.cs
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace CalculatorUITestFramework
|
||||
{
|
||||
public class MemoryPanel
|
||||
{
|
||||
private WindowsDriver<WindowsElement> session => WinAppDriver.Instance.CalculatorSession;
|
||||
public WindowsElement MemoryClear => this.session.TryFindElementByAccessibilityId("ClearMemoryButton");
|
||||
public WindowsElement MemRecall => this.session.TryFindElementByAccessibilityId("MemRecall");
|
||||
public WindowsElement MemPlus => this.session.TryFindElementByAccessibilityId("MemPlus");
|
||||
public WindowsElement MemMinus => this.session.TryFindElementByAccessibilityId("MemMinus");
|
||||
public WindowsElement MemButton => this.session.TryFindElementByAccessibilityId("memButton");
|
||||
public WindowsElement MemoryPane => this.session.TryFindElementByAccessibilityId("MemoryPanel");
|
||||
public WindowsElement MemoryLabel => this.session.TryFindElementByAccessibilityId("MemoryLabel");
|
||||
public WindowsElement MemoryListView => this.session.TryFindElementByAccessibilityId("MemoryListView");
|
||||
public WindowsElement MemoryPaneEmptyLabel => this.session.TryFindElementByAccessibilityId("MemoryPaneEmpty");
|
||||
|
||||
/// <summary>
|
||||
/// Opens the Memory Pane by clicking the Memory pivot label.
|
||||
/// </summary>
|
||||
public void OpenMemoryPanel()
|
||||
{
|
||||
this.MemoryLabel.Click();
|
||||
this.MemoryPane.WaitForDisplayed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all of the memory items listed in the Memory Pane.
|
||||
/// </summary>
|
||||
/// <returns>A readonly collection of memory items.</returns>
|
||||
public ReadOnlyCollection<AppiumWebElement> GetAllMemoryListViewItems()
|
||||
{
|
||||
OpenMemoryPanel();
|
||||
return this.MemoryListView.FindElementsByClassName("ListViewItem");
|
||||
}
|
||||
}
|
||||
}
|
105
src/CalculatorUITestFramework/NavigationMenu.cs
Normal file
105
src/CalculatorUITestFramework/NavigationMenu.cs
Normal file
@ -0,0 +1,105 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using System;
|
||||
|
||||
namespace CalculatorUITestFramework
|
||||
{
|
||||
public enum CalculatorMode
|
||||
{
|
||||
StandardCalculator,
|
||||
ScientificCalculator,
|
||||
ProgrammerCalculator,
|
||||
DateCalculator,
|
||||
Currency,
|
||||
Volume,
|
||||
Length,
|
||||
Weight,
|
||||
Temperature,
|
||||
Energy,
|
||||
Area,
|
||||
Speed,
|
||||
Time,
|
||||
Power,
|
||||
Data,
|
||||
Pressure,
|
||||
Angle
|
||||
}
|
||||
public class NavigationMenu
|
||||
{
|
||||
private WindowsDriver<WindowsElement> session => WinAppDriver.Instance.CalculatorSession;
|
||||
|
||||
public WindowsElement NavigationMenuButton => this.session.TryFindElementByAccessibilityId("TogglePaneButton");
|
||||
public WindowsElement NavigationMenuPane => this.session.TryFindElementByClassName("SplitViewPane");
|
||||
|
||||
/// <summary>
|
||||
/// Changes the mode using the navigation menu in the UI
|
||||
/// </summary>
|
||||
/// <param name="mode">The mode to be changed to</param>
|
||||
public void ChangeCalculatorMode(CalculatorMode mode)
|
||||
{
|
||||
string modeAccessibilityId;
|
||||
switch (mode)
|
||||
{
|
||||
case CalculatorMode.StandardCalculator:
|
||||
modeAccessibilityId = "Standard";
|
||||
break;
|
||||
case CalculatorMode.ScientificCalculator:
|
||||
modeAccessibilityId = "Scientific";
|
||||
break;
|
||||
case CalculatorMode.ProgrammerCalculator:
|
||||
modeAccessibilityId = "Programmer";
|
||||
break;
|
||||
case CalculatorMode.DateCalculator:
|
||||
modeAccessibilityId = "Date";
|
||||
break;
|
||||
case CalculatorMode.Currency:
|
||||
modeAccessibilityId = "Currency";
|
||||
break;
|
||||
case CalculatorMode.Volume:
|
||||
modeAccessibilityId = "Volume";
|
||||
break;
|
||||
case CalculatorMode.Length:
|
||||
modeAccessibilityId = "Length";
|
||||
break;
|
||||
case CalculatorMode.Weight:
|
||||
modeAccessibilityId = "Weight";
|
||||
break;
|
||||
case CalculatorMode.Temperature:
|
||||
modeAccessibilityId = "Temperature";
|
||||
break;
|
||||
case CalculatorMode.Energy:
|
||||
modeAccessibilityId = "Energy";
|
||||
break;
|
||||
case CalculatorMode.Area:
|
||||
modeAccessibilityId = "Area";
|
||||
break;
|
||||
case CalculatorMode.Speed:
|
||||
modeAccessibilityId = "Speed";
|
||||
break;
|
||||
case CalculatorMode.Time:
|
||||
modeAccessibilityId = "Time";
|
||||
break;
|
||||
case CalculatorMode.Power:
|
||||
modeAccessibilityId = "Power";
|
||||
break;
|
||||
case CalculatorMode.Data:
|
||||
modeAccessibilityId = "Data";
|
||||
break;
|
||||
case CalculatorMode.Pressure:
|
||||
modeAccessibilityId = "Pressure";
|
||||
break;
|
||||
case CalculatorMode.Angle:
|
||||
modeAccessibilityId = "Angle";
|
||||
break;
|
||||
default:
|
||||
throw (new ArgumentException("The mode is not valid"));
|
||||
}
|
||||
|
||||
this.NavigationMenuButton.Click();
|
||||
this.NavigationMenuPane.WaitForDisplayed();
|
||||
this.session.TryFindElementByAccessibilityId(modeAccessibilityId).Click();
|
||||
}
|
||||
}
|
||||
}
|
82
src/CalculatorUITestFramework/NumberPad.cs
Normal file
82
src/CalculatorUITestFramework/NumberPad.cs
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using System;
|
||||
|
||||
namespace CalculatorUITestFramework
|
||||
{
|
||||
public class NumberPad
|
||||
{
|
||||
private WindowsDriver<WindowsElement> session => WinAppDriver.Instance.CalculatorSession;
|
||||
public WindowsElement Num0Button => this.session.TryFindElementByAccessibilityId("num0Button");
|
||||
public WindowsElement Num1Button => this.session.TryFindElementByAccessibilityId("num1Button");
|
||||
public WindowsElement Num2Button => this.session.TryFindElementByAccessibilityId("num2Button");
|
||||
public WindowsElement Num3Button => this.session.TryFindElementByAccessibilityId("num3Button");
|
||||
public WindowsElement Num4Button => this.session.TryFindElementByAccessibilityId("num4Button");
|
||||
public WindowsElement Num5Button => this.session.TryFindElementByAccessibilityId("num5Button");
|
||||
public WindowsElement Num6Button => this.session.TryFindElementByAccessibilityId("num6Button");
|
||||
public WindowsElement Num7Button => this.session.TryFindElementByAccessibilityId("num7Button");
|
||||
public WindowsElement Num8Button => this.session.TryFindElementByAccessibilityId("num8Button");
|
||||
public WindowsElement Num9Button => this.session.TryFindElementByAccessibilityId("num9Button");
|
||||
public WindowsElement DecimalButton => this.session.TryFindElementByAccessibilityId("decimalSeparatorButton");
|
||||
public WindowsElement NegateButton => this.session.TryFindElementByAccessibilityId("negateButton");
|
||||
|
||||
/// <summary>
|
||||
/// Translates a number into the Calculator button clicks.
|
||||
/// </summary>
|
||||
/// <param name="number">Number to be entered into the calculator.</param>
|
||||
public void Input(double number)
|
||||
{
|
||||
string numberStr = number.ToString();
|
||||
if (numberStr.StartsWith("-"))
|
||||
{
|
||||
numberStr = numberStr.Substring(1) + "-";
|
||||
}
|
||||
foreach (char digit in numberStr)
|
||||
{
|
||||
switch (digit)
|
||||
{
|
||||
case '0':
|
||||
this.Num0Button.Click();
|
||||
break;
|
||||
case '1':
|
||||
this.Num1Button.Click();
|
||||
break;
|
||||
case '2':
|
||||
this.Num2Button.Click();
|
||||
break;
|
||||
case '3':
|
||||
this.Num3Button.Click();
|
||||
break;
|
||||
case '4':
|
||||
this.Num4Button.Click();
|
||||
break;
|
||||
case '5':
|
||||
this.Num5Button.Click();
|
||||
break;
|
||||
case '6':
|
||||
this.Num6Button.Click();
|
||||
break;
|
||||
case '7':
|
||||
this.Num7Button.Click();
|
||||
break;
|
||||
case '8':
|
||||
this.Num8Button.Click();
|
||||
break;
|
||||
case '9':
|
||||
this.Num9Button.Click();
|
||||
break;
|
||||
case '.':
|
||||
this.DecimalButton.Click();
|
||||
break;
|
||||
case '-':
|
||||
this.NegateButton.Click();
|
||||
break;
|
||||
default:
|
||||
throw (new ArgumentException(String.Format("{0} is not valid", digit)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
49
src/CalculatorUITestFramework/StandardCalculatorPage.cs
Normal file
49
src/CalculatorUITestFramework/StandardCalculatorPage.cs
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
|
||||
namespace CalculatorUITestFramework
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains the UI automation objects and helper methods available when the Calculator is in Standard Mode.
|
||||
/// </summary>
|
||||
public class StandardCalculatorPage
|
||||
{
|
||||
private WindowsDriver<WindowsElement> session => WinAppDriver.Instance.CalculatorSession;
|
||||
public StandardOperatorsPanel StandardOperators = new StandardOperatorsPanel();
|
||||
public MemoryPanel MemoryPanel = new MemoryPanel();
|
||||
public HistoryPanel HistoryPanel = new HistoryPanel();
|
||||
public NavigationMenu NavigationMenu = new NavigationMenu();
|
||||
public WindowsElement Header => this.session.TryFindElementByAccessibilityId("Header");
|
||||
|
||||
public WindowsElement CalculatorResult => this.session.TryFindElementByAccessibilityId("CalculatorResults");
|
||||
|
||||
public void NavigateToStandardCalculator()
|
||||
{
|
||||
// Ensure that calculator is in standard mode
|
||||
this.NavigationMenu.ChangeCalculatorMode(CalculatorMode.StandardCalculator);
|
||||
Assert.IsNotNull(CalculatorResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear the Calculator display, Memory Panel and optionally the History Panel
|
||||
/// </summary>
|
||||
public void ClearAll()
|
||||
{
|
||||
this.StandardOperators.ClearButton.Click();
|
||||
this.MemoryPanel.MemoryClear.Click();
|
||||
this.HistoryPanel.ClearHistory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the text from the display control and removes the narrator text that is not displayed in the UI.
|
||||
/// </summary>
|
||||
/// <returns>The string shown in the UI.</returns>
|
||||
public string GetCalculatorResultText()
|
||||
{
|
||||
return this.CalculatorResult.Text.Replace("Display is", string.Empty).Trim();
|
||||
}
|
||||
}
|
||||
}
|
31
src/CalculatorUITestFramework/StandardOperatorsPanel.cs
Normal file
31
src/CalculatorUITestFramework/StandardOperatorsPanel.cs
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CalculatorUITestFramework
|
||||
{
|
||||
/// <summary>
|
||||
/// UI elements and helper methods to perform common mathematical standard operations.
|
||||
/// </summary>
|
||||
public class StandardOperatorsPanel
|
||||
{
|
||||
private WindowsDriver<WindowsElement> session => WinAppDriver.Instance.CalculatorSession;
|
||||
public NumberPad NumberPad = new NumberPad();
|
||||
|
||||
public WindowsElement PercentButton => this.session.TryFindElementByAccessibilityId("percentButton");
|
||||
public WindowsElement SquareRootButton => this.session.TryFindElementByAccessibilityId("squareRootButton");
|
||||
public WindowsElement XPower2Button => this.session.TryFindElementByAccessibilityId("xpower2Button");
|
||||
public WindowsElement XPower3Button => this.session.TryFindElementByAccessibilityId("xpower3Button");
|
||||
public WindowsElement InvertButton => this.session.TryFindElementByAccessibilityId("invertButton");
|
||||
public WindowsElement DivideButton => this.session.TryFindElementByAccessibilityId("divideButton");
|
||||
public WindowsElement MultiplyButton => this.session.TryFindElementByAccessibilityId("multiplyButton");
|
||||
public WindowsElement MinusButton => this.session.TryFindElementByAccessibilityId("minusButton");
|
||||
public WindowsElement PlusButton => this.session.TryFindElementByAccessibilityId("plusButton");
|
||||
public WindowsElement EqualButton => this.session.TryFindElementByAccessibilityId("equalButton");
|
||||
public WindowsElement ClearEntryButton => this.session.TryFindElementByAccessibilityId("clearEntryButton");
|
||||
public WindowsElement ClearButton => this.session.TryFindElementByAccessibilityId("clearButton");
|
||||
public WindowsElement BackSpaceButton => this.session.TryFindElementByAccessibilityId("backSpaceButton");
|
||||
}
|
||||
}
|
84
src/CalculatorUITestFramework/WinAppDriver.cs
Normal file
84
src/CalculatorUITestFramework/WinAppDriver.cs
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace CalculatorUITestFramework
|
||||
{
|
||||
public sealed class WinAppDriver
|
||||
{
|
||||
private WindowsDriverLocalService windowsDriverService = null;
|
||||
private const string calculatorAppId = "Microsoft.WindowsCalculator.Dev_8wekyb3d8bbwe!App";
|
||||
private static WinAppDriver instance = null;
|
||||
public static WinAppDriver Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new WinAppDriver();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public WindowsDriver<WindowsElement> CalculatorSession { get; private set; }
|
||||
|
||||
|
||||
private WinAppDriver()
|
||||
{
|
||||
}
|
||||
|
||||
public void SetupCalculatorSession(TestContext context)
|
||||
{
|
||||
this.windowsDriverService = new WindowsDriverServiceBuilder().Build();
|
||||
|
||||
this.windowsDriverService.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
|
||||
{
|
||||
var outputData = e.Data?.Replace("\0", string.Empty);
|
||||
if (!String.IsNullOrEmpty(outputData))
|
||||
{
|
||||
Console.WriteLine(outputData);
|
||||
}
|
||||
});
|
||||
|
||||
this.windowsDriverService.Start();
|
||||
|
||||
// Launch Calculator application if it is not yet launched
|
||||
if (this.CalculatorSession == null)
|
||||
{
|
||||
// Create a new WinAppDriver session to bring up an instance of the Calculator application
|
||||
// Note: Multiple calculator windows (instances) share the same process Id
|
||||
var options = new AppiumOptions();
|
||||
options.AddAdditionalCapability("app", calculatorAppId);
|
||||
options.AddAdditionalCapability("deviceName", "WindowsPC");
|
||||
this.CalculatorSession = new WindowsDriver<WindowsElement>(this.windowsDriverService.ServiceUrl, options);
|
||||
this.CalculatorSession.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
|
||||
Assert.IsNotNull(this.CalculatorSession);
|
||||
}
|
||||
}
|
||||
|
||||
public void TearDownCalculatorSession()
|
||||
{
|
||||
// Close the application and delete the session
|
||||
if (this.CalculatorSession != null)
|
||||
{
|
||||
this.CalculatorSession.Quit();
|
||||
this.CalculatorSession = null;
|
||||
}
|
||||
|
||||
if (this.windowsDriverService != null)
|
||||
{
|
||||
this.windowsDriverService.Dispose();
|
||||
this.windowsDriverService = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
72
src/CalculatorUITestFramework/WindowsDriverExtensions.cs
Normal file
72
src/CalculatorUITestFramework/WindowsDriverExtensions.cs
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
|
||||
namespace CalculatorUITestFramework
|
||||
{
|
||||
public static class WindowsDriverExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Wraps the WindowsDriver.FindElementByAccessibilityId and adds retry logic for when the element cannot be found due to WinAppDriver losing the window.
|
||||
/// If FindElementByAccessibilityId fails for a different reason rethrow the error.
|
||||
/// </summary>
|
||||
public static WindowsElement TryFindElementByAccessibilityId(this WindowsDriver<WindowsElement> driver, string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
return driver.FindElementByAccessibilityId(id);
|
||||
}
|
||||
catch (WebDriverException ex)
|
||||
{
|
||||
if (ex.Message.Contains("Currently selected window has been closed"))
|
||||
{
|
||||
driver.SwitchToCurrentWindowHandle();
|
||||
return driver.FindElementByAccessibilityId(id);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps the WindowsDriver.FindElementByClassName and adds retry logic for when the element cannot be found due to WinAppDriver losing the window.
|
||||
/// If FindElementByAccessibilityId fails for a different reason rethrow the error.
|
||||
/// </summary>
|
||||
public static WindowsElement TryFindElementByClassName(this WindowsDriver<WindowsElement> driver, string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return driver.FindElementByClassName(name);
|
||||
}
|
||||
catch (WebDriverException ex)
|
||||
{
|
||||
if (ex.Message.Contains("Currently selected window has been closed"))
|
||||
{
|
||||
driver.SwitchToCurrentWindowHandle();
|
||||
return driver.FindElementByClassName(name);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the window handles for the current CalculatorSession and switches to the first one.
|
||||
/// </summary>
|
||||
public static void SwitchToCurrentWindowHandle(this WindowsDriver<WindowsElement> driver)
|
||||
{
|
||||
// Identify the current window handle. You can check through inspect.exe which window this is.
|
||||
var currentWindowHandle = driver.CurrentWindowHandle;
|
||||
// Return all window handles associated with this process/application.
|
||||
// At this point hopefully you have one to pick from. Otherwise you can
|
||||
// simply iterate through them to identify the one you want.
|
||||
var allWindowHandles = driver.WindowHandles;
|
||||
// Assuming you only have only one window entry in allWindowHandles and it is in fact the correct one,
|
||||
// switch the session to that window as follows. You can repeat this logic with any top window with the same
|
||||
// process id (any entry of allWindowHandles)
|
||||
driver.SwitchTo().Window(allWindowHandles[0]);
|
||||
}
|
||||
}
|
||||
}
|
191
src/CalculatorUITestFramework/WindowsDriverLocalService.cs
Normal file
191
src/CalculatorUITestFramework/WindowsDriverLocalService.cs
Normal file
@ -0,0 +1,191 @@
|
||||
//Licensed under the Apache License, Version 2.0 (the "License");
|
||||
//you may not use this file except in compliance with the License.
|
||||
//See the NOTICE file distributed with this work for additional
|
||||
//information regarding copyright ownership.
|
||||
//You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing, software
|
||||
//distributed under the License is distributed on an "AS IS" BASIS,
|
||||
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//See the License for the specific language governing permissions and
|
||||
//limitations under the License.
|
||||
|
||||
//Portions Copyright(c) Microsoft Corporation
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace CalculatorUITestFramework
|
||||
{
|
||||
public class WindowsDriverLocalService : IDisposable
|
||||
{
|
||||
private FileInfo FileName;
|
||||
private string Arguments;
|
||||
private IPAddress IP;
|
||||
private int Port;
|
||||
private TimeSpan InitializationTimeout;
|
||||
private Process Service;
|
||||
|
||||
public event DataReceivedEventHandler OutputDataReceived;
|
||||
|
||||
internal WindowsDriverLocalService(
|
||||
FileInfo fileName,
|
||||
string arguments,
|
||||
IPAddress ip,
|
||||
int port,
|
||||
TimeSpan initializationTimeout)
|
||||
{
|
||||
this.FileName = fileName;
|
||||
this.Arguments = arguments;
|
||||
this.IP = ip;
|
||||
this.Port = port;
|
||||
this.InitializationTimeout = initializationTimeout;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public void Start()
|
||||
{
|
||||
if (this.IsRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.Service = new Process();
|
||||
this.Service.StartInfo.FileName = FileName.FullName;
|
||||
this.Service.StartInfo.Arguments = Arguments;
|
||||
this.Service.StartInfo.UseShellExecute = false;
|
||||
this.Service.StartInfo.CreateNoWindow = true;
|
||||
|
||||
this.Service.StartInfo.RedirectStandardOutput = true;
|
||||
this.Service.OutputDataReceived += (sender, e) => OutputDataReceived?.Invoke(this, e);
|
||||
|
||||
bool isLaunched = false;
|
||||
string msgTxt =
|
||||
$"The local WinAppDriver server has not been started: {this.FileName.FullName} Arguments: {this.Arguments}. " +
|
||||
"\n";
|
||||
|
||||
try
|
||||
{
|
||||
Service.Start();
|
||||
|
||||
Service.BeginOutputReadLine();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DestroyProcess();
|
||||
throw new Exception(msgTxt, e);
|
||||
}
|
||||
|
||||
isLaunched = Ping();
|
||||
if (!isLaunched)
|
||||
{
|
||||
DestroyProcess();
|
||||
throw new Exception(
|
||||
msgTxt +
|
||||
$"Time {InitializationTimeout.TotalMilliseconds} ms for the service starting has been expired!");
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsRunning
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.Service == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var pid = this.Service.Id;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Ping();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DestroyProcess();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public Uri ServiceUrl
|
||||
{
|
||||
// Note: append /wd/hub to the URL if you're directing the test at Appium
|
||||
get { return new Uri($"http://{this.IP.ToString()}:{Convert.ToString(this.Port)}"); }
|
||||
}
|
||||
|
||||
private void DestroyProcess()
|
||||
{
|
||||
if (this.Service == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.Service.Kill();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Service.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private bool Ping()
|
||||
{
|
||||
bool pinged = false;
|
||||
|
||||
Uri status;
|
||||
|
||||
Uri service = this.ServiceUrl;
|
||||
if (service.IsLoopback)
|
||||
{
|
||||
status = new Uri("http://localhost:" + Convert.ToString(this.Port) + "/status");
|
||||
}
|
||||
else
|
||||
{
|
||||
status = new Uri(service.ToString() + "/status");
|
||||
}
|
||||
|
||||
DateTime endTime = DateTime.Now.Add(this.InitializationTimeout);
|
||||
while (!pinged & DateTime.Now < endTime)
|
||||
{
|
||||
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(status);
|
||||
HttpWebResponse response = null;
|
||||
try
|
||||
{
|
||||
using (response = (HttpWebResponse)request.GetResponse())
|
||||
{
|
||||
pinged = true;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
pinged = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (response != null)
|
||||
{
|
||||
response.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
return pinged;
|
||||
}
|
||||
}
|
||||
}
|
103
src/CalculatorUITestFramework/WindowsDriverServiceBuilder.cs
Normal file
103
src/CalculatorUITestFramework/WindowsDriverServiceBuilder.cs
Normal file
@ -0,0 +1,103 @@
|
||||
//Licensed under the Apache License, Version 2.0 (the "License");
|
||||
//you may not use this file except in compliance with the License.
|
||||
//See the NOTICE file distributed with this work for additional
|
||||
//information regarding copyright ownership.
|
||||
//You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing, software
|
||||
//distributed under the License is distributed on an "AS IS" BASIS,
|
||||
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//See the License for the specific language governing permissions and
|
||||
//limitations under the License.
|
||||
|
||||
//Portions Copyright(c) Microsoft Corporation
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace CalculatorUITestFramework
|
||||
{
|
||||
public class WindowsDriverServiceBuilder
|
||||
{
|
||||
private string IpAddress = "127.0.0.1";
|
||||
private int Port = 4723;
|
||||
private TimeSpan StartUpTimeout = new TimeSpan(0, 2, 0);
|
||||
private FileInfo FileInfo;
|
||||
|
||||
public WindowsDriverLocalService Build()
|
||||
{
|
||||
if (this.FileInfo == null)
|
||||
{
|
||||
this.FileInfo = new FileInfo(@"c:\Program Files (x86)\Windows Application Driver\winappdriver.exe");
|
||||
}
|
||||
return new WindowsDriverLocalService(this.FileInfo, string.Empty, IPAddress.Parse(this.IpAddress), this.Port, this.StartUpTimeout);
|
||||
}
|
||||
|
||||
public WindowsDriverServiceBuilder WithFileInfo(FileInfo fileInfo)
|
||||
{
|
||||
if (fileInfo == null)
|
||||
{
|
||||
throw new ArgumentNullException("FileInfo should not be NULL");
|
||||
}
|
||||
this.FileInfo = fileInfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WindowsDriverServiceBuilder WithStartUpTimeOut(TimeSpan startUpTimeout)
|
||||
{
|
||||
if (startUpTimeout == null)
|
||||
{
|
||||
throw new ArgumentNullException("A startup timeout should not be NULL");
|
||||
}
|
||||
this.StartUpTimeout = startUpTimeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WindowsDriverServiceBuilder WithIPAddress(string ipAddress)
|
||||
{
|
||||
this.IpAddress = ipAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WindowsDriverServiceBuilder UsingPort(int port)
|
||||
{
|
||||
if (port < 0)
|
||||
{
|
||||
throw new ArgumentException("The port parameter should not be negative");
|
||||
}
|
||||
|
||||
if (port == 0)
|
||||
{
|
||||
return UsingAnyFreePort();
|
||||
}
|
||||
|
||||
this.Port = port;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WindowsDriverServiceBuilder UsingAnyFreePort()
|
||||
{
|
||||
Socket sock = null;
|
||||
|
||||
try
|
||||
{
|
||||
sock = new Socket(AddressFamily.InterNetwork,
|
||||
SocketType.Stream, ProtocolType.Tcp);
|
||||
sock.Bind(new IPEndPoint(IPAddress.Any, 0));
|
||||
this.Port = ((IPEndPoint)sock.LocalEndPoint).Port;
|
||||
return this;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (sock != null)
|
||||
{
|
||||
sock.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
39
src/CalculatorUITestFramework/WindowsElementExtensions.cs
Normal file
39
src/CalculatorUITestFramework/WindowsElementExtensions.cs
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting.Logging;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
namespace CalculatorUITestFramework
|
||||
{
|
||||
public static class WindowsElementExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits for an element to be displayed until the timeout is reached.
|
||||
/// </summary>
|
||||
/// <param name="element">WindowsElement in the Calculator application.</param>
|
||||
/// <param name="timeout">Timeout in ms.</param>
|
||||
public static void WaitForDisplayed(this WindowsElement element, int timeout = 2000)
|
||||
{
|
||||
Stopwatch timer = new Stopwatch();
|
||||
timer.Reset();
|
||||
timer.Start();
|
||||
while (timer.ElapsedMilliseconds < timeout)
|
||||
{
|
||||
if (element.Displayed)
|
||||
{
|
||||
timer.Stop();
|
||||
return;
|
||||
}
|
||||
Logger.LogMessage("Waiting for 10ms in WaitForDisplayed");
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
timer.Stop();
|
||||
Assert.Fail(String.Format("{0} was not displayed in {1} ms", element, timeout));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using System;
|
||||
|
||||
namespace CalculatorUITests
|
||||
{
|
||||
public class CalculatorSession
|
||||
{
|
||||
// Note: append /wd/hub to the URL if you're directing the test at Appium
|
||||
private const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
|
||||
private const string CalculatorAppId = "Microsoft.WindowsCalculator.Dev_8wekyb3d8bbwe!App";
|
||||
protected static WindowsDriver<WindowsElement> session;
|
||||
|
||||
public static void Setup(TestContext context)
|
||||
{
|
||||
// Launch Calculator application if it is not yet launched
|
||||
if (session == null)
|
||||
{
|
||||
// Create a new session to bring up an instance of the Calculator application
|
||||
// Note: Multiple calculator windows (instances) share the same process Id
|
||||
var options = new AppiumOptions();
|
||||
options.AddAdditionalCapability("app", CalculatorAppId);
|
||||
options.AddAdditionalCapability("deviceName", "WindowsPC");
|
||||
session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), options);
|
||||
session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(180);
|
||||
Assert.IsNotNull(session);
|
||||
}
|
||||
}
|
||||
|
||||
public static void TearDown()
|
||||
{
|
||||
// Close the application and delete the session
|
||||
if (session != null)
|
||||
{
|
||||
session.Quit();
|
||||
session = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
@ -13,6 +13,10 @@
|
||||
<PackageReference Include="Appium.WebDriver" Version="4.0.0.6-beta" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CalculatorUITestFramework\CalculatorUITestFramework.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="CalculatorUITests.runsettings">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
|
@ -1,112 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using System.Threading;
|
||||
using System;
|
||||
|
||||
namespace CalculatorUITests
|
||||
{
|
||||
[TestClass]
|
||||
public class StandardModeTests : CalculatorSession
|
||||
{
|
||||
private static WindowsElement header;
|
||||
private static WindowsElement calculatorResult;
|
||||
|
||||
[TestMethod]
|
||||
public void Addition()
|
||||
{
|
||||
// Find the buttons by their names and click them in sequence to perform 1 + 7 = 8
|
||||
session.FindElementByName("One").Click();
|
||||
session.FindElementByName("Plus").Click();
|
||||
session.FindElementByName("Seven").Click();
|
||||
session.FindElementByName("Equals").Click();
|
||||
Assert.AreEqual("8", GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Division()
|
||||
{
|
||||
// Find the buttons by their accessibility ids and click them in sequence to perform 88 / 11 = 8
|
||||
session.FindElementByAccessibilityId("num8Button").Click();
|
||||
session.FindElementByAccessibilityId("num8Button").Click();
|
||||
session.FindElementByAccessibilityId("divideButton").Click();
|
||||
session.FindElementByAccessibilityId("num1Button").Click();
|
||||
session.FindElementByAccessibilityId("num1Button").Click();
|
||||
session.FindElementByAccessibilityId("equalButton").Click();
|
||||
Assert.AreEqual("8", GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Multiplication()
|
||||
{
|
||||
session.FindElementByAccessibilityId("num9Button").Click();
|
||||
session.FindElementByAccessibilityId("multiplyButton").Click();
|
||||
session.FindElementByAccessibilityId("num9Button").Click();
|
||||
session.FindElementByAccessibilityId("equalButton").Click();
|
||||
Assert.AreEqual("81", GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Subtraction()
|
||||
{
|
||||
// Find the buttons by their accessibility ids using XPath and click them in sequence to perform 9 - 1 = 8
|
||||
session.FindElementByAccessibilityId("num9Button").Click();
|
||||
session.FindElementByAccessibilityId("minusButton").Click();
|
||||
session.FindElementByAccessibilityId("num1Button").Click();
|
||||
session.FindElementByAccessibilityId("equalButton").Click();
|
||||
Assert.AreEqual("8", GetCalculatorResultText());
|
||||
}
|
||||
|
||||
|
||||
[ClassInitialize]
|
||||
public static void ClassInitialize(TestContext context)
|
||||
{
|
||||
// Create session to launch a Calculator window
|
||||
Setup(context);
|
||||
// Identify calculator mode by locating the header
|
||||
try
|
||||
{
|
||||
header = session.FindElementByAccessibilityId("Header");
|
||||
}
|
||||
catch
|
||||
{
|
||||
header = session.FindElementByAccessibilityId("ContentPresenter");
|
||||
}
|
||||
|
||||
// Ensure that calculator is in standard mode
|
||||
if (!header.Text.Equals("Standard", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
session.FindElementByAccessibilityId("TogglePaneButton").Click();
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
var splitViewPane = session.FindElementByClassName("SplitViewPane");
|
||||
splitViewPane.FindElementByName("Standard Calculator").Click();
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
Assert.IsTrue(header.Text.Equals("Standard", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
// Locate the calculatorResult element
|
||||
calculatorResult = session.FindElementByAccessibilityId("CalculatorResults");
|
||||
Assert.IsNotNull(calculatorResult);
|
||||
}
|
||||
|
||||
[ClassCleanup]
|
||||
public static void ClassCleanup()
|
||||
{
|
||||
TearDown();
|
||||
}
|
||||
|
||||
[TestInitialize]
|
||||
public void Clear()
|
||||
{
|
||||
session.FindElementByName("Clear").Click();
|
||||
Assert.AreEqual("0", GetCalculatorResultText());
|
||||
}
|
||||
|
||||
private string GetCalculatorResultText()
|
||||
{
|
||||
return calculatorResult.Text.Replace("Display is", string.Empty).Trim();
|
||||
}
|
||||
}
|
||||
}
|
323
src/CalculatorUITests/StandardModeFunctionalTests.cs
Normal file
323
src/CalculatorUITests/StandardModeFunctionalTests.cs
Normal file
@ -0,0 +1,323 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using CalculatorUITestFramework;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CalculatorUITests
|
||||
{
|
||||
[TestClass]
|
||||
public class StandardModeFunctionalTests
|
||||
{
|
||||
private static StandardCalculatorPage page = new StandardCalculatorPage();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the WinAppDriver web driver session.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
[ClassInitialize]
|
||||
public static void ClassInitialize(TestContext context)
|
||||
{
|
||||
// Create session to launch a Calculator window
|
||||
WinAppDriver.Instance.SetupCalculatorSession(context);
|
||||
|
||||
// Ensure that calculator is in standard mode
|
||||
page.NavigateToStandardCalculator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the app and WinAppDriver web driver session.
|
||||
/// </summary>
|
||||
[ClassCleanup]
|
||||
public static void ClassCleanup()
|
||||
{
|
||||
// Tear down Calculator session.
|
||||
WinAppDriver.Instance.TearDownCalculatorSession();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures the calculator is in a cleared state
|
||||
/// </summary>
|
||||
[TestInitialize]
|
||||
public void TestInit()
|
||||
{
|
||||
if ("0" != page.GetCalculatorResultText())
|
||||
{
|
||||
page.ClearAll();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void TestCleanup()
|
||||
{
|
||||
page.ClearAll();
|
||||
}
|
||||
|
||||
#region Smoke Tests
|
||||
[TestMethod]
|
||||
public void SmokeTest_Add()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(3.5);
|
||||
page.StandardOperators.PlusButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(0.25);
|
||||
page.StandardOperators.EqualButton.Click();
|
||||
Assert.AreEqual("3.75", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SmokeTest_Add_KeyboardInput()
|
||||
{
|
||||
page.Header.SendKeys("3+3=");
|
||||
Assert.AreEqual("6", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SmokeTest_Subtract()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(4.3);
|
||||
page.StandardOperators.MinusButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(2.6);
|
||||
page.StandardOperators.EqualButton.Click();
|
||||
Assert.AreEqual("1.7", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SmokeTest_History()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(-3);
|
||||
page.StandardOperators.PlusButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(-2.6);
|
||||
page.StandardOperators.EqualButton.Click();
|
||||
|
||||
page.StandardOperators.NumberPad.Input(2);
|
||||
page.StandardOperators.MinusButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(3);
|
||||
page.StandardOperators.EqualButton.Click();
|
||||
|
||||
page.StandardOperators.NumberPad.Input(1);
|
||||
page.StandardOperators.MultiplyButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(3);
|
||||
page.StandardOperators.EqualButton.Click();
|
||||
|
||||
var historyItems = page.HistoryPanel.GetAllHistoryListViewItems();
|
||||
Assert.IsTrue(historyItems[0].Text.Equals("1 × 3 = 3", StringComparison.InvariantCultureIgnoreCase));
|
||||
Assert.IsTrue(historyItems[1].Text.Equals("2 Minus ( 3 = Minus (1", StringComparison.InvariantCultureIgnoreCase));
|
||||
Assert.IsTrue(historyItems[2].Text.Equals("-3 + -2.6 = Minus (5.6", StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SmokeTest_Memory()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(3);
|
||||
page.StandardOperators.PlusButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(0);
|
||||
page.StandardOperators.EqualButton.Click();
|
||||
page.MemoryPanel.MemButton.Click();
|
||||
|
||||
page.StandardOperators.NumberPad.Input(2);
|
||||
page.StandardOperators.DivideButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(3);
|
||||
page.StandardOperators.EqualButton.Click();
|
||||
page.MemoryPanel.MemButton.Click();
|
||||
|
||||
page.StandardOperators.NumberPad.Input(7);
|
||||
page.StandardOperators.MultiplyButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(9);
|
||||
page.StandardOperators.EqualButton.Click();
|
||||
page.MemoryPanel.MemButton.Click();
|
||||
|
||||
var memoryItems = page.MemoryPanel.GetAllMemoryListViewItems();
|
||||
|
||||
Assert.IsTrue(memoryItems[0].Text.Equals("63", StringComparison.InvariantCultureIgnoreCase));
|
||||
Assert.IsTrue(memoryItems[1].Text.Equals("0.6666666666666667", StringComparison.InvariantCultureIgnoreCase));
|
||||
Assert.IsTrue(memoryItems[2].Text.Equals("3", StringComparison.InvariantCultureIgnoreCase));
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Basic Arthimetic Tests
|
||||
[TestMethod]
|
||||
public void Operator_Reciprocal()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(4);
|
||||
page.StandardOperators.InvertButton.Click();
|
||||
Assert.AreEqual("0.25", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Operator_Squared()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(-15.5);
|
||||
page.StandardOperators.XPower2Button.Click();
|
||||
Assert.AreEqual("240.25", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Operator_SquareRoot()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(144);
|
||||
page.StandardOperators.SquareRootButton.Click();
|
||||
Assert.AreEqual("12", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Operator_Cubed()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(-3);
|
||||
page.StandardOperators.XPower3Button.Click();
|
||||
Assert.AreEqual("-27", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Operator_Percent()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(600);
|
||||
page.StandardOperators.MultiplyButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(15);
|
||||
page.StandardOperators.PercentButton.Click();
|
||||
page.StandardOperators.EqualButton.Click();
|
||||
Assert.AreEqual("90", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Operator_Delete()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(-12345);
|
||||
page.StandardOperators.BackSpaceButton.Click();
|
||||
Assert.AreEqual("-1,234", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Operator_ClearAll()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(12345);
|
||||
page.StandardOperators.PlusButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(6789);
|
||||
page.StandardOperators.ClearButton.Click();
|
||||
Assert.AreEqual("0", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Operator_ClearEntry()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(-12345);
|
||||
page.StandardOperators.MinusButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(5678);
|
||||
page.StandardOperators.ClearEntryButton.Click();
|
||||
Assert.AreEqual("0", page.GetCalculatorResultText());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Keyboard Input Tests
|
||||
[TestMethod]
|
||||
public void KeyboardInput_Subtract()
|
||||
{
|
||||
page.Header.SendKeys("70090-890987=");
|
||||
Assert.AreEqual("-820,897", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void KeyboardInput_Multiply()
|
||||
{
|
||||
page.Header.SendKeys("-15*3=");
|
||||
Assert.AreEqual("-45", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void KeyboardInput_Divide()
|
||||
{
|
||||
page.Header.SendKeys("26/13=");
|
||||
Assert.AreEqual("2", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void KeyboardInput_SquareRoot()
|
||||
{
|
||||
page.Header.SendKeys("100@");
|
||||
Assert.AreEqual("10", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void KeyboardInput_Cubed()
|
||||
{
|
||||
page.Header.SendKeys("3#");
|
||||
Assert.AreEqual("27", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void KeyboardInput_Percent()
|
||||
{
|
||||
page.Header.SendKeys("34+7%=");
|
||||
Assert.AreEqual("36.38", page.GetCalculatorResultText());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Memory Tests
|
||||
[TestMethod]
|
||||
public void Memory_AddTest()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(12);
|
||||
page.StandardOperators.DivideButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(3);
|
||||
page.StandardOperators.EqualButton.Click();
|
||||
|
||||
page.MemoryPanel.MemButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(15);
|
||||
page.MemoryPanel.MemPlus.Click();
|
||||
var memoryItems = page.MemoryPanel.GetAllMemoryListViewItems();
|
||||
Assert.IsTrue(memoryItems[0].Text.Equals("19", StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Memory_SubtractTest()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(12);
|
||||
page.StandardOperators.DivideButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(3);
|
||||
page.StandardOperators.EqualButton.Click();
|
||||
|
||||
page.MemoryPanel.MemButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(3.3);
|
||||
page.MemoryPanel.MemMinus.Click();
|
||||
var memoryItems = page.MemoryPanel.GetAllMemoryListViewItems();
|
||||
Assert.IsTrue(memoryItems[0].Text.Equals("0.7", StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Memory_RecallTest()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(12);
|
||||
page.StandardOperators.DivideButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(3);
|
||||
page.StandardOperators.EqualButton.Click();
|
||||
|
||||
page.MemoryPanel.MemButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(3.3);
|
||||
page.MemoryPanel.MemRecall.Click();
|
||||
var memoryItems = page.MemoryPanel.GetAllMemoryListViewItems();
|
||||
Assert.IsTrue(memoryItems[0].Text.Equals("4", StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Memory_ClearTest()
|
||||
{
|
||||
page.StandardOperators.NumberPad.Input(12);
|
||||
page.StandardOperators.DivideButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(3);
|
||||
page.StandardOperators.EqualButton.Click();
|
||||
|
||||
page.MemoryPanel.MemButton.Click();
|
||||
page.StandardOperators.NumberPad.Input(3.3);
|
||||
page.MemoryPanel.MemoryClear.Click();
|
||||
page.MemoryPanel.OpenMemoryPanel();
|
||||
Assert.IsNotNull(page.MemoryPanel.MemoryPaneEmptyLabel);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user