Skip to content

Commit 18c5348

Browse files
committed
Merged PR 620052: Add test methods for launching application with arguments and creating a session from top level window scenarios
Add test methods for launching application with arguments scenarios Add test methods for creating a session from existing top level window scenarios Add test methods for starting a classic windows application in given directory Update the window switching test methods to cover the new restriction on the API Reorder and rename Session and Window test methods for better clarity and organization Add GetOrphanedWindowHandle helper function in Utility class for no such window scenarios Fix Appium test where switching to other session's window is now prohibited Replace browser URLs with Edge specific about URLs to increase reliability and reduce test duration Create a common helper method in Utility class to check window handle validity Update Edge app session base by removing unproductive test scenarios Related work items: #10018205, #12391049
2 parents ace61e7 + ff792be commit 18c5348

13 files changed

+591
-421
lines changed

Tests/Appium/AppLaunch.cs

+3-5
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,12 @@ public void LaunchClassicApp()
3535

3636
var originalTitle = session.Title;
3737
var originalLaunchedWindowHandle = session.CurrentWindowHandle;
38-
session.LaunchApp();
38+
session.Close();
39+
Assert.IsNotNull(session.SessionId);
3940

41+
session.LaunchApp();
4042
Assert.AreEqual(originalTitle, session.Title);
4143
Assert.AreNotEqual(originalLaunchedWindowHandle, session.CurrentWindowHandle);
42-
43-
session.Close();
44-
session.SwitchTo().Window(originalLaunchedWindowHandle);
45-
session.Close();
4644
session.Quit();
4745
}
4846

Tests/W3CWebDriver/AppSessionBase/AlarmClockBase.cs

+1-22
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public class AlarmClockBase
3030
public static void Setup(TestContext context)
3131
{
3232
// Launch Alarm Clock if it is not yet launched
33-
if (session == null || touchScreen == null || !CurrentWindowIsAlive())
33+
if (session == null || touchScreen == null || !Utility.CurrentWindowIsAlive(session))
3434
{
3535
TearDown();
3636
session = Utility.CreateNewSession(CommonTestSettings.AlarmClockAppId);
@@ -82,27 +82,6 @@ protected void AddAlarmEntry(string alarmName)
8282
session.FindElementByAccessibilityId("AlarmSaveButton").Click();
8383
}
8484

85-
private static bool CurrentWindowIsAlive()
86-
{
87-
bool windowIsAlive = false;
88-
89-
if (session != null)
90-
{
91-
try
92-
{
93-
windowIsAlive = !String.IsNullOrEmpty(session.CurrentWindowHandle) && session.CurrentWindowHandle != "0";
94-
windowIsAlive = true;
95-
}
96-
catch
97-
{
98-
session.Quit();
99-
session = null;
100-
}
101-
}
102-
103-
return windowIsAlive;
104-
}
105-
10685
protected void DeletePreviouslyCreatedAlarmEntry(string alarmName)
10786
{
10887
while (true)

Tests/W3CWebDriver/AppSessionBase/CalculatorBase.cs

+10-1
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,30 @@
1616

1717
using Microsoft.VisualStudio.TestTools.UnitTesting;
1818
using OpenQA.Selenium.Appium.Windows;
19+
using OpenQA.Selenium.Remote;
1920

2021
namespace W3CWebDriver
2122
{
2223
public class CalculatorBase
2324
{
2425
protected static WindowsDriver<WindowsElement> session;
26+
protected static RemoteTouchScreen touchScreen;
2527
private static WindowsElement header;
2628

2729
public static void Setup(TestContext context)
2830
{
2931
// Launch Calculator if it is not yet launched
30-
if (session == null)
32+
if (session == null || touchScreen == null)
3133
{
3234
session = Utility.CreateNewSession(CommonTestSettings.CalculatorAppId);
3335
Assert.IsNotNull(session);
3436
Assert.IsNotNull(session.SessionId);
3537
header = session.FindElementByAccessibilityId("Header");
3638
Assert.IsNotNull(header);
39+
40+
// Initialize touch screen object
41+
touchScreen = new RemoteTouchScreen(session);
42+
Assert.IsNotNull(touchScreen);
3743
}
3844

3945
// Set focus on the calculator window
@@ -55,6 +61,9 @@ public static void TearDown()
5561
{
5662
header = null;
5763

64+
// Cleanup RemoteTouchScreen object if initialized
65+
touchScreen = null;
66+
5867
// Close the application and delete the session
5968
if (session != null)
6069
{

Tests/W3CWebDriver/AppSessionBase/CommonTestSettings.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,13 @@ public class CommonTestSettings
2525
public const string EdgeAppId = "Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge";
2626
public const string ExplorerAppId = @"C:\Windows\System32\explorer.exe";
2727
public const string NotepadAppId = @"C:\Windows\System32\notepad.exe";
28-
public const string MicrosoftUrl = "www.microsoft.com";
29-
public const string GitHubUrl = "https://github.com/Microsoft/WinAppDriver";
28+
29+
public const string EdgeAboutBlankURL = "about:blank";
30+
public const string EdgeAboutFlagsURL = "about:flags";
31+
public const string EdgeAboutTabsURL = "about:tabs";
32+
33+
public const string TestFileName = "TestFile.txt";
34+
public const string TestFolderLocation = "%TEMP%";
3035
}
3136

3237
public class ErrorStrings

Tests/W3CWebDriver/AppSessionBase/EdgeBase.cs

+28-104
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,22 @@ public class EdgeBase
3535

3636
public static void Setup(TestContext context)
3737
{
38-
// Cleanup leftover objects from previous test if exists
39-
TearDown();
40-
41-
// Launch the Edge browser app
42-
session = Utility.CreateNewSession(CommonTestSettings.EdgeAppId);
43-
session.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5));
44-
Assert.IsNotNull(session);
45-
Assert.IsNotNull(session.SessionId);
46-
47-
// Initialize touch screen object
48-
touchScreen = new RemoteTouchScreen(session);
49-
Assert.IsNotNull(touchScreen);
38+
// Launch Edge browser app if it is not yet launched
39+
if (session == null || touchScreen == null || !Utility.CurrentWindowIsAlive(session))
40+
{
41+
// Cleanup leftover objects from previous test if exists
42+
TearDown();
43+
44+
// Launch the Edge browser app
45+
session = Utility.CreateNewSession(CommonTestSettings.EdgeAppId);
46+
session.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5));
47+
Assert.IsNotNull(session);
48+
Assert.IsNotNull(session.SessionId);
49+
50+
// Initialize touch screen object
51+
touchScreen = new RemoteTouchScreen(session);
52+
Assert.IsNotNull(touchScreen);
53+
}
5054

5155
// Track the Microsoft Edge starting page title to be used to initialize all test cases
5256
System.Threading.Thread.Sleep(3000); // Sleep for 3 seconds
@@ -100,108 +104,28 @@ public void TestInit()
100104
}
101105
}
102106

103-
protected RemoteWebElement GetOrphanedElement(WindowsDriver<WindowsElement> remoteSession)
104-
{
105-
RemoteWebElement orphanedElement = null;
106-
107-
// Track existing opened Edge window(s) and only manipulate newly opened windows
108-
var previouslyOpenedEdgeWindows = remoteSession.WindowHandles;
109-
var originalActiveWindowHandle = remoteSession.CurrentWindowHandle;
110-
111-
// Open a new window
112-
// The menu item names have changed between Windows 10 and the anniversary update
113-
// account for both combinations.
114-
try
115-
{
116-
remoteSession.FindElementByAccessibilityId("m_actionsMenuButton").Click();
117-
remoteSession.FindElementByAccessibilityId("m_newWindow").Click();
118-
}
119-
catch (System.InvalidOperationException)
120-
{
121-
remoteSession.FindElementByAccessibilityId("ActionsMenuButton").Click();
122-
remoteSession.FindElementByAccessibilityId("ActionsMenuNewWindow").Click();
123-
}
124-
125-
System.Threading.Thread.Sleep(3000); // Sleep for 3 second
126-
var multipleWindowHandles = remoteSession.WindowHandles;
127-
Assert.IsTrue(multipleWindowHandles.Count == previouslyOpenedEdgeWindows.Count + 1);
128-
129-
// Ensure we get the newly opened window by removing other previously known windows from the list
130-
List<String> newlyOpenedEdgeWindows = new List<String>(multipleWindowHandles);
131-
foreach (var previouslyOpenedEdgeWindow in previouslyOpenedEdgeWindows)
132-
{
133-
newlyOpenedEdgeWindows.Remove(previouslyOpenedEdgeWindow);
134-
}
135-
Assert.IsTrue(newlyOpenedEdgeWindows.Count == 1);
136-
137-
// Switch to new window and use the address edit box as orphaned element
138-
remoteSession.SwitchTo().Window(newlyOpenedEdgeWindows[0]);
139-
System.Threading.Thread.Sleep(1000); // Sleep for 1 second
140-
Assert.AreEqual(newlyOpenedEdgeWindows[0], remoteSession.CurrentWindowHandle);
141-
orphanedElement = remoteSession.FindElementByAccessibilityId("addressEditBox");
142-
Assert.IsNotNull(orphanedElement);
143-
144-
// Close the newly opened window and return to previously active window
145-
remoteSession.Close();
146-
remoteSession.SwitchTo().Window(originalActiveWindowHandle);
147-
System.Threading.Thread.Sleep(1000); // Sleep for 1 second
148-
149-
return orphanedElement;
150-
}
151-
152-
protected static RemoteWebElement GetStaleElement(WindowsDriver<WindowsElement> remoteSession)
107+
protected static RemoteWebElement GetStaleElement()
153108
{
154109
RemoteWebElement staleElement = null;
155110

156-
remoteSession.FindElementByAccessibilityId("addressEditBox").SendKeys(CommonTestSettings.MicrosoftUrl + OpenQA.Selenium.Keys.Enter);
157-
System.Threading.Thread.Sleep(3000); // Sleep for 3 seconds
158-
var originalTitle = remoteSession.Title;
111+
session.FindElementByAccessibilityId("addressEditBox").SendKeys(CommonTestSettings.EdgeAboutTabsURL + OpenQA.Selenium.Keys.Enter);
112+
System.Threading.Thread.Sleep(2000); // Sleep for 2 seconds
113+
var originalTitle = session.Title;
159114
Assert.AreNotEqual(string.Empty, originalTitle);
160115

161-
// Navigate to GitHub page
162-
remoteSession.FindElementByAccessibilityId("addressEditBox").SendKeys(CommonTestSettings.GitHubUrl + OpenQA.Selenium.Keys.Enter);
163-
System.Threading.Thread.Sleep(3000); // Sleep for 3 seconds
164-
Assert.AreNotEqual(originalTitle, remoteSession.Title);
116+
// Navigate to Edge about:flags page
117+
session.FindElementByAccessibilityId("addressEditBox").SendKeys(CommonTestSettings.EdgeAboutFlagsURL + OpenQA.Selenium.Keys.Enter);
118+
System.Threading.Thread.Sleep(2000); // Sleep for 2 seconds
119+
Assert.AreNotEqual(originalTitle, session.Title);
165120

166-
// Save a reference to Homepage web link on the GitHub page and navigate back to home
167-
staleElement = remoteSession.FindElementByName("Homepage");
121+
// Save a reference to Reset all flags button on the page and navigate back to home
122+
staleElement = session.FindElementByAccessibilityId("ResetAllFlags");
168123
Assert.IsNotNull(staleElement);
169-
remoteSession.Navigate().Back();
170-
System.Threading.Thread.Sleep(2000);
124+
session.Navigate().Back();
125+
System.Threading.Thread.Sleep(1000);
171126
Assert.AreEqual(originalTitle, session.Title);
172127

173128
return staleElement;
174129
}
175-
176-
protected HttpWebResponse SendTouchPost(String touchType, JObject requestObject)
177-
{
178-
var request = WebRequest.Create(CommonTestSettings.WindowsApplicationDriverUrl + "/session/" + session.SessionId + "/touch/" + touchType);
179-
request.Method = "POST";
180-
request.ContentType = "application/json";
181-
182-
String postData = requestObject.ToString();
183-
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
184-
request.ContentLength = byteArray.Length;
185-
Stream dataStream = request.GetRequestStream();
186-
dataStream.Write(byteArray, 0, byteArray.Length);
187-
dataStream.Close();
188-
return request.GetResponse() as HttpWebResponse;
189-
}
190-
191-
public void ErrorTouchInvalidElement(string touchType)
192-
{
193-
JObject enterRequestObject = new JObject();
194-
enterRequestObject["element"] = "InvalidElementId";
195-
HttpWebResponse response = SendTouchPost(touchType, enterRequestObject);
196-
Assert.Fail("Exception should have been thrown because there is no such element");
197-
}
198-
199-
public void ErrorTouchInvalidArguments(string touchType)
200-
{
201-
JObject enterRequestObject = new JObject();
202-
HttpWebResponse response = SendTouchPost(touchType, enterRequestObject);
203-
session.Close();
204-
Assert.Fail("Exception should have been thrown because there are insufficient arguments");
205-
}
206130
}
207131
}

Tests/W3CWebDriver/AppSessionBase/Utility.cs

+33-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public class Utility
2424
{
2525
private static WindowsDriver<WindowsElement> orphanedSession;
2626
private static WindowsElement orphanedElement;
27+
private static string orphanedWindowHandle;
2728

2829
~Utility()
2930
{
@@ -37,6 +38,24 @@ public static WindowsDriver<WindowsElement> CreateNewSession(string appId)
3738
return new WindowsDriver<WindowsElement>(new Uri(CommonTestSettings.WindowsApplicationDriverUrl), appCapabilities);
3839
}
3940

41+
public static bool CurrentWindowIsAlive(WindowsDriver<WindowsElement> remoteSession)
42+
{
43+
bool windowIsAlive = false;
44+
45+
if (remoteSession != null)
46+
{
47+
try
48+
{
49+
windowIsAlive = !string.IsNullOrEmpty(remoteSession.CurrentWindowHandle) && remoteSession.CurrentWindowHandle != "0";
50+
windowIsAlive = true;
51+
}
52+
catch { }
53+
}
54+
55+
return windowIsAlive;
56+
}
57+
58+
4059
public static WindowsElement GetOrphanedElement()
4160
{
4261
// Re-initialize orphaned session and element if they are compromised
@@ -51,16 +70,28 @@ public static WindowsElement GetOrphanedElement()
5170
public static WindowsDriver<WindowsElement> GetOrphanedSession()
5271
{
5372
// Re-initialize orphaned session and element if they are compromised
54-
if (orphanedSession == null || orphanedElement == null)
73+
if (orphanedSession == null || orphanedElement == null || string.IsNullOrEmpty(orphanedWindowHandle))
5574
{
5675
InitializeOrphanedSession();
5776
}
5877

5978
return orphanedSession;
6079
}
6180

81+
public static string GetOrphanedWindowHandle()
82+
{
83+
// Re-initialize orphaned session and element if they are compromised
84+
if (orphanedSession == null || orphanedElement == null || string.IsNullOrEmpty(orphanedWindowHandle))
85+
{
86+
InitializeOrphanedSession();
87+
}
88+
89+
return orphanedWindowHandle;
90+
}
91+
6292
private static void CleanupOrphanedSession()
6393
{
94+
orphanedWindowHandle = null;
6495
orphanedElement = null;
6596

6697
// Cleanup after the session if exists
@@ -77,6 +108,7 @@ private static void InitializeOrphanedSession()
77108
CleanupOrphanedSession();
78109
orphanedSession = CreateNewSession(CommonTestSettings.CalculatorAppId);
79110
orphanedElement = orphanedSession.FindElementByAccessibilityId("Header");
111+
orphanedWindowHandle = orphanedSession.CurrentWindowHandle;
80112
orphanedSession.Close();
81113
}
82114
}

Tests/W3CWebDriver/Back.cs

+4-7
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,20 @@ public void NavigateBackBrowser()
3131
{
3232
session = Utility.CreateNewSession(CommonTestSettings.EdgeAppId);
3333
Assert.IsNotNull(session);
34-
System.Threading.Thread.Sleep(3000); // Sleep for 3 seconds
3534

36-
session.FindElementByAccessibilityId("addressEditBox").SendKeys(CommonTestSettings.MicrosoftUrl + OpenQA.Selenium.Keys.Enter);
37-
System.Threading.Thread.Sleep(3000); // Sleep for 3 seconds
35+
session.FindElementByAccessibilityId("addressEditBox").SendKeys(CommonTestSettings.EdgeAboutFlagsURL + OpenQA.Selenium.Keys.Enter);
36+
System.Threading.Thread.Sleep(1000); // Sleep for 1 second
3837
var originalTitle = session.Title;
3938
Assert.AreNotEqual(String.Empty, originalTitle);
4039

4140
// Navigate to different URLs
4241
var addressEditBox = session.FindElementByAccessibilityId("addressEditBox");
43-
addressEditBox.SendKeys(CommonTestSettings.GitHubUrl + OpenQA.Selenium.Keys.Enter);
44-
45-
System.Threading.Thread.Sleep(5000); // Sleep for 5 seconds
42+
addressEditBox.SendKeys(CommonTestSettings.EdgeAboutBlankURL + OpenQA.Selenium.Keys.Enter);
4643
Assert.AreNotEqual(originalTitle, session.Title);
4744

4845
// Navigate back to original URL
4946
session.Navigate().Back();
50-
System.Threading.Thread.Sleep(5000); // Sleep for 5 seconds
47+
System.Threading.Thread.Sleep(1000); // Sleep for 1 second
5148
Assert.AreEqual(originalTitle, session.Title);
5249

5350
session.Quit();

0 commit comments

Comments
 (0)