Skip to content

Commit a96b97c

Browse files
authored
Update to Appium 8.0.1, Selenium 4.36.0 +semver:breaking (#59)
* Update to Appium 8.0.1, Selenium 4.36.0 +semver:breaking Update copyright and license year Use npm appium@latest (3.1.0) and appium-doctor@latest package in ADO pipelines, install windows-driver --force before running appium-doctor remove deprecated request npm package installation from the pipeline * Use NodeJS v.20 * Use NodeJS v.22 * SonarCloud: use scannerMode: 'dotnet' * Fix sonar maintainability bug Use windows-2022 agent as winAppDriver only supports Windows 10 * npm install -g request@2.34.0 appium driver doctor windows * fix Chrome tests * Fix sonar issues and stabilize Chrome tests * update waiting for Got it button * Chrome: scroll More button * Stabilize chrome window interactions
1 parent fe3d14c commit a96b97c

File tree

7 files changed

+85
-66
lines changed

7 files changed

+85
-66
lines changed

Aquality.WinAppDriver/src/Aquality.WinAppDriver/Aquality.WinAppDriver.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<RepositoryType>git</RepositoryType>
1515
<PackageTags>windows application winappdriver automation</PackageTags>
1616
<PackageLicenseFile>LICENSE</PackageLicenseFile>
17-
<Copyright>Copyright 2024 Aquality Automation</Copyright>
17+
<Copyright>Copyright 2025 Aquality Automation</Copyright>
1818
<IsPackable>true</IsPackable>
1919
</PropertyGroup>
2020

Aquality.WinAppDriver/src/Aquality.WinAppDriver/Configurations/DriverSettings.cs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,7 @@ public virtual AppiumOptions AppiumOptions
6363
}
6464
else
6565
{
66-
if (exception.Message.StartsWith("There is already an option"))
67-
{
68-
SetKnownProperty(options, capability, exception);
69-
}
70-
else
71-
{
72-
throw;
73-
}
66+
throw;
7467
}
7568
}
7669
});
@@ -86,25 +79,30 @@ public virtual string ApplicationPath
8679
{
8780
get
8881
{
82+
Capabilities.TryGetValue(AppCapabilityKey, out var defaultValue);
8983
var appValue = settingsFile.GetValueOrDefault(ApplicationPathJPath,
90-
defaultValue: (Capabilities.ContainsKey(AppCapabilityKey) ? Capabilities[AppCapabilityKey] : null)?.ToString());
91-
return appValue?.StartsWith(".") == true ? Path.GetFullPath(appValue) : appValue;
84+
defaultValue: defaultValue?.ToString());
85+
if (appValue?.FirstOrDefault() == '.')
86+
{
87+
appValue = Path.GetFullPath(appValue);
88+
}
89+
return appValue;
9290
}
9391
}
9492

9593
private void SetKnownProperty(DriverOptions options, KeyValuePair<string, object> capability, ArgumentException exception)
9694
{
97-
if (KnownCapabilitySetters.ContainsKey(capability.Key))
95+
if (KnownCapabilitySetters.TryGetValue(capability.Key, out var setter))
9896
{
99-
KnownCapabilitySetters[capability.Key](options, capability.Value);
97+
setter(options, capability.Value);
10098
}
10199
else
102100
{
103101
SetOptionByPropertyName(options, capability, exception);
104102
}
105103
}
106104

107-
private void SetOptionByPropertyName(DriverOptions options, KeyValuePair<string, object> option, Exception exception)
105+
private static void SetOptionByPropertyName(DriverOptions options, KeyValuePair<string, object> option, Exception exception)
108106
{
109107
var optionProperty = options
110108
.GetType()
@@ -118,14 +116,14 @@ private void SetOptionByPropertyName(DriverOptions options, KeyValuePair<string,
118116
optionProperty.SetValue(options, valueToSet);
119117
}
120118

121-
private object ParseEnumValue(Type propertyType, object optionValue)
119+
private static object ParseEnumValue(Type propertyType, object optionValue)
122120
{
123121
return optionValue is string
124122
? Enum.Parse(propertyType, optionValue.ToString(), ignoreCase: true)
125123
: Enum.ToObject(propertyType, Convert.ChangeType(optionValue, Enum.GetUnderlyingType(propertyType)));
126124
}
127125

128-
private bool IsEnumValue(Type propertyType, object optionValue)
126+
private static bool IsEnumValue(Type propertyType, object optionValue)
129127
{
130128
var valueAsString = optionValue.ToString();
131129
if (!propertyType.IsEnum || string.IsNullOrEmpty(valueAsString))
@@ -140,18 +138,18 @@ private bool IsEnumValue(Type propertyType, object optionValue)
140138
&& propertyType.IsEnumDefined(Convert.ChangeType(optionValue, Enum.GetUnderlyingType(propertyType))));
141139
}
142140

143-
private bool IsValueOfIntegralNumericType(object value)
141+
private static bool IsValueOfIntegralNumericType(object value)
144142
{
145143
return value is byte || value is sbyte
146144
|| value is ushort || value is short
147145
|| value is uint || value is int
148146
|| value is ulong || value is long;
149147
}
150148

151-
private bool IsPropertyNameMatchOption(string propertyName, string optionKey)
149+
private static bool IsPropertyNameMatchOption(string propertyName, string optionKey)
152150
{
153151
return propertyName.Equals(optionKey, StringComparison.InvariantCultureIgnoreCase)
154-
|| optionKey.ToLowerInvariant().Contains(propertyName.ToLowerInvariant());
152+
|| optionKey.IndexOf(propertyName, StringComparison.InvariantCultureIgnoreCase) >= 0;
155153
}
156154
}
157155
}

Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Forms/Chrome/ChromeNavigationPanel.cs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
using Aquality.Selenium.Core.Configurations;
1+
using Aquality.Selenium.Core.Elements;
22
using Aquality.WinAppDriver.Actions;
3-
using Aquality.WinAppDriver.Applications;
43
using Aquality.WinAppDriver.Elements.Interfaces;
54
using Aquality.WinAppDriver.Forms;
65
using OpenQA.Selenium;
@@ -12,20 +11,22 @@ public class ChromeNavigationPanel : Form
1211
{
1312
private IButton NoThanksButton { get; }
1413
private IButton GotItButton { get; }
15-
private ILabel LastTextLabel { get; }
14+
private IButton MoreButton { get; }
1615
private ILabel RestorePagesLabel { get; }
1716
private IButton CloseButton { get; }
1817
private IButton DontSignInButton { get; }
1918
public ChromeNavigationPanel() : base(By.TagName("Pane"), "Chrome Navigation panel")
2019
{
21-
NoThanksButton = ElementFactory.GetButton(By.Name("No thanks"), "No thanks");
22-
GotItButton = ElementFactory.GetButton(MobileBy.AccessibilityId("ackButton"), "Got it");
23-
LastTextLabel = ElementFactory.GetLabel(MobileBy.AccessibilityId("lastTextElement"), "Last element text");
20+
NoThanksButton = ElementFactory.GetButton(MobileBy.AccessibilityId("declineButton"), "No thanks", ElementState.ExistsInAnyState);
21+
GotItButton = ElementFactory.GetButton(MobileBy.AccessibilityId("ackButton"), "Got it", ElementState.ExistsInAnyState);
22+
MoreButton = ElementFactory.GetButton(MobileBy.AccessibilityId("moreButton"), "More");
2423
RestorePagesLabel = ElementFactory.GetLabel(By.Name("Restore pages?"), "Restore pages?");
2524
CloseButton = RestorePagesLabel.FindChildElement<IButton>(By.Name("Close"), "Close");
2625
DontSignInButton = ElementFactory.GetButton(MobileBy.AccessibilityId("declineSignInButton"), "Don't sign in");
2726
}
2827

28+
public bool IsSignInPresent => DontSignInButton.State.WaitForDisplayed();
29+
2930
public void DontSignIn()
3031
{
3132
DontSignInButton.Click();
@@ -34,21 +35,39 @@ public void DontSignIn()
3435
public void ClosePopUps()
3536
{
3637
State.WaitForExist();
37-
if (!NoThanksButton.State.WaitForNotDisplayed())
38+
if (NoThanksButton.State.WaitForExist())
3839
{
3940
NoThanksButton.Click();
40-
NoThanksButton.State.WaitForNotDisplayed();
41-
if (GotItButton.State.WaitForExist())
41+
NoThanksButton.State.WaitForNotExist();
42+
}
43+
if (MoreButton.State.IsDisplayed)
44+
{
45+
MoreButton.Click();
46+
MoreButton.MouseActions.Scroll(1000, ScrollDirection.Vertical);
47+
}
48+
if (GotItButton.State.IsExist)
49+
{
50+
GotItButton.MouseActions.MoveToElement();
51+
if (GotItButton.State.IsDisplayed)
4252
{
43-
LastTextLabel.Click();
44-
KeyboardActions.SendKeys(ActionKey.Tab, times: 2);
45-
KeyboardActions.SendKeys(ActionKey.Enter);
53+
GotItButton.Click();
54+
}
55+
else
56+
{
57+
GotItButton.KeyboardActions.SendKeys(ActionKey.Enter);
4658
}
4759
}
48-
if (RestorePagesLabel.State.IsExist)
60+
ConditionalWait.WaitForTrue(() =>
4961
{
50-
CloseButton.Click();
51-
}
62+
if (RestorePagesLabel.State.IsExist)
63+
{
64+
RestorePagesLabel.Click();
65+
CloseButton.Click();
66+
}
67+
68+
return !RestorePagesLabel.State.IsExist;
69+
}, message: "Restore pages? popup must be closed to proceed");
70+
5271
}
5372

5473
public void OpenDownloads()

Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Forms/Chrome/ChromeWindow.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ public class ChromeWindow(string name) : Window(By.Name(name), name)
99
{
1010
private ILabel DocumentLabel => FindChildElement<ILabel>(By.TagName("Document"), "Document");
1111

12+
public bool HasKeyboardFocus => bool.Parse(GetAttribute("HasKeyboardFocus"));
13+
1214
public void ClickOnDocument()
1315
{
1416
DocumentLabel.Click();

Aquality.WinAppDriver/tests/Aquality.WinAppDriver.Tests/Forms/Chrome/MultipleWindowsTest.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,11 @@ public void Should_BePossibleTo_ShowAndHideWindow_ViaProcess()
3939

4040
var secondWindowProcess = secondWindow.Process;
4141
secondWindowProcess.ShowWindow(ShowCommand.Minimize);
42-
secondWindow.State.WaitForNotDisplayed();
43-
Assert.IsFalse(secondWindow.State.IsDisplayed, "Second window is not minimized");
42+
Assert.IsFalse(secondWindow.HasKeyboardFocus, "Second window is not minimized");
4443
Assert.IsTrue(firstWindow.State.IsDisplayed, "First window is not displayed");
4544
secondWindowProcess.ShowWindow(ShowCommand.ShowNormal);
4645
secondWindow.State.WaitForDisplayed();
47-
Assert.IsTrue(secondWindow.State.IsDisplayed, "Second window is not shown");
46+
Assert.IsTrue(secondWindow.HasKeyboardFocus, "Second window is not shown");
4847
}
4948

5049
private void OpenTwoWindows(out ChromeWindow firstWindow, out ChromeWindow secondWindow)
@@ -58,7 +57,7 @@ private void OpenTwoWindows(out ChromeWindow firstWindow, out ChromeWindow secon
5857
Assert.IsTrue(firstWindow.State.WaitForDisplayed(), $"{firstWindow.Name} window is not displayed");
5958

6059
var navigationPanel = new ChromeNavigationPanel();
61-
if (firstWindowName.Contains("Sign in"))
60+
if (navigationPanel.IsSignInPresent)
6261
{
6362
navigationPanel.DontSignIn();
6463
AqualityServices.Application = AqualityServices.ApplicationFactory.Application;

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@
186186
same "printed page" as the copyright notice for easier
187187
identification within third-party archives.
188188

189-
Copyright 2024 Aquality Automation
189+
Copyright 2025 Aquality Automation
190190

191191
Licensed under the Apache License, Version 2.0 (the "License");
192192
you may not use this file except in compliance with the License.

azure-pipelines.yml

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ trigger:
22
- master
33

44
pool:
5-
vmImage: 'windows-latest'
5+
vmImage: 'windows-2022'
66

77
variables:
88
buildConfiguration: 'Release'
@@ -15,32 +15,31 @@ stages:
1515
displayName: Analyse code with SonarQube
1616

1717
steps:
18-
- task: SonarCloudPrepare@2
18+
- task: SonarCloudPrepare@3
1919
displayName: 'Prepare SonarCloud analysis'
2020
inputs:
2121
SonarCloud: 'SonarCloud'
2222
organization: 'aqualityautomation'
23-
scannerMode: 'MSBuild'
23+
scannerMode: 'dotnet'
2424
projectKey: 'aquality-automation_aquality-winappdriver-dotnet'
2525
projectName: 'aquality-winappdriver-dotnet'
2626
projectVersion: '$(Build.BuildNumber)'
27-
extraProperties: |
28-
sonar.coverage.exclusions=**/**
27+
extraProperties: 'sonar.coverage.exclusions=**/**'
2928

3029
- task: DotNetCoreCLI@2
3130
displayName: 'Build solution'
3231
inputs:
3332
command: 'build'
3433
projects: Aquality.WinAppDriver/Aquality.WinAppDriver.sln
3534
arguments: -c $(buildConfiguration)
36-
37-
- task: SonarCloudAnalyze@2
38-
displayName: 'Run SonarCloud code analysis'
39-
continueOnError: true
35+
36+
- task: SonarCloudAnalyze@3
4037
inputs:
4138
jdkversion: 'JAVA_HOME_17_X64'
39+
displayName: 'Run SonarCloud code analysis'
40+
continueOnError: true
4241

43-
- task: SonarCloudPublish@2
42+
- task: SonarCloudPublish@3
4443
displayName: 'Publish SonarCloud quality gate results'
4544
inputs:
4645
pollingTimeoutSec: '300'
@@ -62,35 +61,34 @@ stages:
6261
- task: NodeTool@0
6362
displayName: 'Install Node.js'
6463
inputs:
65-
versionSpec: '16.x'
64+
versionSpec: '22.x'
6665

6766
- task: CmdLine@2
6867
displayName: 'Install Appium'
6968
inputs:
7069
script: |
7170
echo "Installing Appium"
72-
npm install -g appium@next
71+
npm install -g appium@latest
7372
appium --version
7473
echo "Appium installed"
75-
76-
- task: CmdLine@2
77-
displayName: 'Install and Run Appium doctor'
78-
inputs:
79-
script: |
80-
echo "Installing and Running Appium doctor"
81-
npm install -g request@2.34.0
82-
npm install -g appium-doctor@1.15.1
83-
appium-doctor
84-
echo "Appium doctor installed and executed"
8574
8675
- task: CmdLine@2
8776
displayName: 'Install Appium Windows Driver'
8877
inputs:
8978
script: |
9079
echo "Installing Appium Windows Driver"
91-
appium driver install --source=npm appium-windows-driver
80+
appium driver install windows
9281
appium driver list
9382
echo "Appium Windows Driver installed"
83+
84+
- task: CmdLine@2
85+
displayName: 'Run Appium doctor'
86+
inputs:
87+
script: |
88+
echo " Running Appium doctor"
89+
npm install -g request@2.34.0
90+
appium driver doctor windows
91+
echo "Appium doctor executed"
9492
9593
- task: CmdLine@2
9694
displayName: 'Start Appium server'
@@ -118,6 +116,7 @@ stages:
118116

119117
steps:
120118
- task: gitversion/setup@0
119+
displayName: 'Install GitTools'
121120
inputs:
122121
versionSpec: '5.x'
123122
- task: gitversion/execute@0
@@ -128,16 +127,18 @@ stages:
128127
- script: dotnet pack Aquality.WinAppDriver\src\Aquality.WinAppDriver\Aquality.WinAppDriver.csproj -c $(buildConfiguration) -p:Version=$(GitVersion.NuGetVersion) -o $(Build.ArtifactStagingDirectory)
129128
displayName: 'Pack to NuGet package'
130129

131-
- task: GitHubRelease@0
130+
- task: GitHubRelease@1
132131
displayName: 'Create tag on GitHub'
133132
inputs:
134133
gitHubConnection: 'github.com_aqualityautomation'
135134
repositoryName: 'aquality-automation/aquality-winappdriver-dotnet'
136135
action: 'create'
136+
target: '$(Build.SourceVersion)'
137+
tagSource: 'userSpecifiedTag'
137138
tag: 'v$(GitVersion.NuGetVersion)'
138-
title: 'v$(GitVersion.NuGetVersion)'
139-
tagSource: 'manual'
140-
isPreRelease: contains(variables['GitVersion.NuGetVersion'], '-')
139+
isDraft: contains(variables['GitVersion.NuGetVersion'], '-')
140+
changeLogCompareToRelease: 'lastFullRelease'
141+
changeLogType: 'commitBased'
141142

142143
- task: NuGetCommand@2
143144
displayName: 'Push NuGet package'

0 commit comments

Comments
 (0)