Skip to content

Commit 8005715

Browse files
authored
Merge pull request #95 from FlaUI/fix-test-duration
Fix test duration
2 parents c7229cd + e620d85 commit 8005715

File tree

4 files changed

+85
-59
lines changed

4 files changed

+85
-59
lines changed

src/FlaUI.WebDriver.UITests/SessionTests.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,6 @@ public void NewSession_AppTopLevelWindowZero_ReturnsError()
164164
Assert.That(newSession, Throws.TypeOf<WebDriverArgumentException>().With.Message.EqualTo("Capability appium:appTopLevelWindow '0x0' should not be zero"));
165165
}
166166

167-
[Explicit("Sometimes multiple processes are left open")]
168167
[TestCase("FlaUI WPF Test App")]
169168
[TestCase("FlaUI WPF .*")]
170169
public void NewSession_AppTopLevelWindowTitleMatch_IsSupported(string match)
@@ -191,7 +190,7 @@ public void EndSession_AppTopLevelWindowTitleMatch_DoesNotKillApp()
191190
Assert.That(testAppProcess.Process.HasExited, Is.False);
192191
}
193192

194-
[Test, Explicit("Sometimes multiple processes are left open")]
193+
[Test]
195194
public void NewSession_AppTopLevelWindowTitleMatchMultipleMatching_ReturnsError()
196195
{
197196
using var testAppProcess = new TestAppProcess();
@@ -338,7 +337,7 @@ public void NewCommandTimeout_NotExpired_DoesNotEndSession()
338337
Assert.That(() => driver.Title, Throws.Nothing);
339338
}
340339

341-
[Test, Explicit(("Sometimes multiple processes are left open"))]
340+
[Test]
342341
public void NewCommandTimeout_SessionWithAppTopLevelWindowTitleMatch_ClosesSessionButDoesNotCloseApp()
343342
{
344343
using var testAppProcess = new TestAppProcess();

src/FlaUI.WebDriver/Controllers/SessionController.cs

Lines changed: 68 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using FlaUI.Core;
12
using FlaUI.WebDriver.Models;
23
using Microsoft.AspNetCore.Mvc;
34
using System.Diagnostics;
@@ -29,8 +30,6 @@ public async Task<ActionResult> CreateNewSession([FromBody] CreateSessionRequest
2930
.Where(capabilities => TryMatchCapabilities(capabilities, out matchedCapabilities, out _))
3031
.Select(capabillities => matchedCapabilities!);
3132

32-
Core.Application? app;
33-
var isAppOwnedBySession = false;
3433
var capabilities = matchingCapabilities.FirstOrDefault();
3534
if (capabilities == null)
3635
{
@@ -43,69 +42,87 @@ public async Task<ActionResult> CreateNewSession([FromBody] CreateSessionRequest
4342
Message = string.Join("; ", mismatchIndications)
4443
});
4544
}
45+
46+
var timeoutsConfiguration = new TimeoutsConfiguration();
47+
if (capabilities.TryGetCapability<TimeoutsConfiguration>("timeouts", out var timeoutsConfigurationFromCapabilities))
48+
{
49+
timeoutsConfiguration = timeoutsConfigurationFromCapabilities!;
50+
}
51+
var newCommandTimeout = TimeSpan.FromSeconds(60);
52+
if (capabilities.TryGetNumberCapability("appium:newCommandTimeout", out var newCommandTimeoutFromCapabilities))
53+
{
54+
newCommandTimeout = TimeSpan.FromSeconds(newCommandTimeoutFromCapabilities);
55+
}
56+
57+
Application? app = GetApp(capabilities, out bool isAppOwnedBySession);
58+
Session session;
59+
try
60+
{
61+
session = new Session(app, isAppOwnedBySession, timeoutsConfiguration, newCommandTimeout);
62+
}
63+
catch (Exception)
64+
{
65+
app?.Dispose();
66+
throw;
67+
}
68+
69+
_sessionRepository.Add(session);
70+
_logger.LogInformation("Created session with ID {SessionId} and capabilities {Capabilities}", session.SessionId, capabilities);
71+
return await Task.FromResult(WebDriverResult.Success(new CreateSessionResponse()
72+
{
73+
SessionId = session.SessionId,
74+
Capabilities = capabilities.Capabilities
75+
}));
76+
}
77+
78+
private static Application? GetApp(MergedCapabilities capabilities, out bool isAppOwnedBySession)
79+
{
4680
if (capabilities.TryGetStringCapability("appium:app", out var appPath))
4781
{
4882
if (appPath == "Root")
4983
{
50-
app = null;
84+
isAppOwnedBySession = false;
85+
return null;
5186
}
52-
else
87+
88+
capabilities.TryGetStringCapability("appium:appArguments", out var appArguments);
89+
try
5390
{
54-
capabilities.TryGetStringCapability("appium:appArguments", out var appArguments);
55-
try
91+
if (appPath.EndsWith("!App"))
5692
{
57-
if (appPath.EndsWith("!App"))
58-
{
59-
app = Core.Application.LaunchStoreApp(appPath, appArguments);
60-
}
61-
else
62-
{
63-
var processStartInfo = new ProcessStartInfo(appPath, appArguments ?? "");
64-
if(capabilities.TryGetStringCapability("appium:appWorkingDir", out var appWorkingDir))
65-
{
66-
processStartInfo.WorkingDirectory = appWorkingDir;
67-
}
68-
app = Core.Application.Launch(processStartInfo);
69-
}
93+
isAppOwnedBySession = true;
94+
return Application.LaunchStoreApp(appPath, appArguments);
7095
}
71-
catch(Exception e)
96+
97+
var processStartInfo = new ProcessStartInfo(appPath, appArguments ?? "");
98+
if (capabilities.TryGetStringCapability("appium:appWorkingDir", out var appWorkingDir))
7299
{
73-
throw WebDriverResponseException.InvalidArgument($"Starting app '{appPath}' with arguments '{appArguments}' threw an exception: {e.Message}");
100+
processStartInfo.WorkingDirectory = appWorkingDir;
74101
}
102+
isAppOwnedBySession = true;
103+
return Application.Launch(processStartInfo);
104+
}
105+
catch (Exception e)
106+
{
107+
throw WebDriverResponseException.InvalidArgument($"Starting app '{appPath}' with arguments '{appArguments}' threw an exception: {e.Message}");
75108
}
76-
77-
isAppOwnedBySession = true;
78109
}
79-
else if (capabilities.TryGetStringCapability("appium:appTopLevelWindow", out var appTopLevelWindowString))
110+
111+
if (capabilities.TryGetStringCapability("appium:appTopLevelWindow", out var appTopLevelWindowString))
80112
{
113+
isAppOwnedBySession = false;
81114
Process process = GetProcessByMainWindowHandle(appTopLevelWindowString);
82-
app = Core.Application.Attach(process);
115+
return Application.Attach(process);
83116
}
84-
else if (capabilities.TryGetStringCapability("appium:appTopLevelWindowTitleMatch", out var appTopLevelWindowTitleMatch))
117+
118+
if (capabilities.TryGetStringCapability("appium:appTopLevelWindowTitleMatch", out var appTopLevelWindowTitleMatch))
85119
{
120+
isAppOwnedBySession = false;
86121
Process? process = GetProcessByMainWindowTitle(appTopLevelWindowTitleMatch);
87-
app = Core.Application.Attach(process);
88-
}
89-
else
90-
{
91-
throw WebDriverResponseException.InvalidArgument("One of appium:app, appium:appTopLevelWindow or appium:appTopLevelWindowTitleMatch must be passed as a capability");
92-
}
93-
var session = new Session(app, isAppOwnedBySession);
94-
if(capabilities.TryGetNumberCapability("appium:newCommandTimeout", out var newCommandTimeout))
95-
{
96-
session.NewCommandTimeout = TimeSpan.FromSeconds(newCommandTimeout);
122+
return Application.Attach(process);
97123
}
98-
if (capabilities.TryGetCapability<TimeoutsConfiguration>("timeouts", out var timeoutsConfiguration))
99-
{
100-
session.TimeoutsConfiguration = timeoutsConfiguration!;
101-
}
102-
_sessionRepository.Add(session);
103-
_logger.LogInformation("Created session with ID {SessionId} and capabilities {Capabilities}", session.SessionId, capabilities);
104-
return await Task.FromResult(WebDriverResult.Success(new CreateSessionResponse()
105-
{
106-
SessionId = session.SessionId,
107-
Capabilities = capabilities.Capabilities
108-
}));
124+
125+
throw WebDriverResponseException.InvalidArgument("One of appium:app, appium:appTopLevelWindow or appium:appTopLevelWindowTitleMatch must be passed as a capability");
109126
}
110127

111128
private string? GetMismatchIndication(MergedCapabilities capabilities)
@@ -163,7 +180,7 @@ private bool TryMatchCapabilities(MergedCapabilities capabilities, [MaybeNullWhe
163180
matchedCapabilities.Copy("appium:appTopLevelWindow", capabilities);
164181
}
165182
else if (capabilities.Contains("appium:appTopLevelWindowTitleMatch"))
166-
{
183+
{
167184
matchedCapabilities.Copy("appium:appTopLevelWindowTitleMatch", capabilities);
168185
}
169186
else
@@ -199,8 +216,8 @@ private static Process GetProcessByMainWindowTitle(string appTopLevelWindowTitle
199216
try
200217
{
201218
appMainWindowTitleRegex = new Regex(appTopLevelWindowTitleMatch);
202-
}
203-
catch(ArgumentException e)
219+
}
220+
catch (ArgumentException e)
204221
{
205222
throw WebDriverResponseException.InvalidArgument($"Capability appium:appTopLevelWindowTitleMatch '{appTopLevelWindowTitleMatch}' is not a valid regular expression: {e.Message}");
206223
}
@@ -209,7 +226,7 @@ private static Process GetProcessByMainWindowTitle(string appTopLevelWindowTitle
209226
{
210227
throw WebDriverResponseException.InvalidArgument($"Process with main window title matching '{appTopLevelWindowTitleMatch}' could not be found");
211228
}
212-
else if (processes.Length > 1)
229+
if (processes.Length > 1)
213230
{
214231
throw WebDriverResponseException.InvalidArgument($"Found multiple ({processes.Length}) processes with main window title matching '{appTopLevelWindowTitleMatch}'");
215232
}

src/FlaUI.WebDriver/Session.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ namespace FlaUI.WebDriver
88
{
99
public class Session : IDisposable
1010
{
11-
public Session(Application? app, bool isAppOwnedBySession)
11+
public Session(Application? app, bool isAppOwnedBySession, TimeoutsConfiguration timeoutsConfiguration, TimeSpan newCommandTimeout)
1212
{
1313
App = app;
1414
SessionId = Guid.NewGuid().ToString();
1515
Automation = new UIA3Automation();
1616
InputState = new InputState();
17-
TimeoutsConfiguration = new TimeoutsConfiguration();
17+
TimeoutsConfiguration = timeoutsConfiguration;
1818
IsAppOwnedBySession = isAppOwnedBySession;
19+
NewCommandTimeout = newCommandTimeout;
1920

2021
if (app != null)
2122
{

src/TestApplications/WpfApplication/MainWindow.xaml.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Windows;
1+
using System.ComponentModel;
2+
using System.Windows;
23
using System.Windows.Controls;
34
using System.Windows.Media;
45

@@ -9,6 +10,8 @@ namespace WpfApplication
910
/// </summary>
1011
public partial class MainWindow
1112
{
13+
private Window1 _subWindow;
14+
1215
public MainWindow()
1316
{
1417
InitializeComponent();
@@ -34,6 +37,12 @@ protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
3437
base.OnRenderSizeChanged(sizeInfo);
3538
}
3639

40+
protected override void OnClosing(CancelEventArgs e)
41+
{
42+
_subWindow?.Close();
43+
base.OnClosing(e);
44+
}
45+
3746
private void OnShowLabel(object sender, RoutedEventArgs e)
3847
{
3948
MenuItem menuitem = sender as MenuItem;
@@ -68,8 +77,8 @@ private void OnDisableForm(object sender, RoutedEventArgs e)
6877

6978
private void MenuItem_Click(object sender, RoutedEventArgs e)
7079
{
71-
var window = new Window1();
72-
window.Show();
80+
_subWindow = new Window1();
81+
_subWindow.Show();
7382
}
7483

7584
private void LabelWithHover_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)

0 commit comments

Comments
 (0)