Skip to content

Commit

Permalink
Merge pull request #95 from FlaUI/fix-test-duration
Browse files Browse the repository at this point in the history
Fix test duration
  • Loading branch information
aristotelos authored Sep 28, 2024
2 parents c7229cd + e620d85 commit 8005715
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 59 deletions.
5 changes: 2 additions & 3 deletions src/FlaUI.WebDriver.UITests/SessionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ public void NewSession_AppTopLevelWindowZero_ReturnsError()
Assert.That(newSession, Throws.TypeOf<WebDriverArgumentException>().With.Message.EqualTo("Capability appium:appTopLevelWindow '0x0' should not be zero"));
}

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

[Test, Explicit("Sometimes multiple processes are left open")]
[Test]
public void NewSession_AppTopLevelWindowTitleMatchMultipleMatching_ReturnsError()
{
using var testAppProcess = new TestAppProcess();
Expand Down Expand Up @@ -338,7 +337,7 @@ public void NewCommandTimeout_NotExpired_DoesNotEndSession()
Assert.That(() => driver.Title, Throws.Nothing);
}

[Test, Explicit(("Sometimes multiple processes are left open"))]
[Test]
public void NewCommandTimeout_SessionWithAppTopLevelWindowTitleMatch_ClosesSessionButDoesNotCloseApp()
{
using var testAppProcess = new TestAppProcess();
Expand Down
119 changes: 68 additions & 51 deletions src/FlaUI.WebDriver/Controllers/SessionController.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using FlaUI.Core;
using FlaUI.WebDriver.Models;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
Expand Down Expand Up @@ -29,8 +30,6 @@ public async Task<ActionResult> CreateNewSession([FromBody] CreateSessionRequest
.Where(capabilities => TryMatchCapabilities(capabilities, out matchedCapabilities, out _))
.Select(capabillities => matchedCapabilities!);

Core.Application? app;
var isAppOwnedBySession = false;
var capabilities = matchingCapabilities.FirstOrDefault();
if (capabilities == null)
{
Expand All @@ -43,69 +42,87 @@ public async Task<ActionResult> CreateNewSession([FromBody] CreateSessionRequest
Message = string.Join("; ", mismatchIndications)
});
}

var timeoutsConfiguration = new TimeoutsConfiguration();
if (capabilities.TryGetCapability<TimeoutsConfiguration>("timeouts", out var timeoutsConfigurationFromCapabilities))
{
timeoutsConfiguration = timeoutsConfigurationFromCapabilities!;
}
var newCommandTimeout = TimeSpan.FromSeconds(60);
if (capabilities.TryGetNumberCapability("appium:newCommandTimeout", out var newCommandTimeoutFromCapabilities))
{
newCommandTimeout = TimeSpan.FromSeconds(newCommandTimeoutFromCapabilities);
}

Application? app = GetApp(capabilities, out bool isAppOwnedBySession);
Session session;
try
{
session = new Session(app, isAppOwnedBySession, timeoutsConfiguration, newCommandTimeout);
}
catch (Exception)
{
app?.Dispose();
throw;
}

_sessionRepository.Add(session);
_logger.LogInformation("Created session with ID {SessionId} and capabilities {Capabilities}", session.SessionId, capabilities);
return await Task.FromResult(WebDriverResult.Success(new CreateSessionResponse()
{
SessionId = session.SessionId,
Capabilities = capabilities.Capabilities
}));
}

private static Application? GetApp(MergedCapabilities capabilities, out bool isAppOwnedBySession)
{
if (capabilities.TryGetStringCapability("appium:app", out var appPath))
{
if (appPath == "Root")
{
app = null;
isAppOwnedBySession = false;
return null;
}
else

capabilities.TryGetStringCapability("appium:appArguments", out var appArguments);
try
{
capabilities.TryGetStringCapability("appium:appArguments", out var appArguments);
try
if (appPath.EndsWith("!App"))
{
if (appPath.EndsWith("!App"))
{
app = Core.Application.LaunchStoreApp(appPath, appArguments);
}
else
{
var processStartInfo = new ProcessStartInfo(appPath, appArguments ?? "");
if(capabilities.TryGetStringCapability("appium:appWorkingDir", out var appWorkingDir))
{
processStartInfo.WorkingDirectory = appWorkingDir;
}
app = Core.Application.Launch(processStartInfo);
}
isAppOwnedBySession = true;
return Application.LaunchStoreApp(appPath, appArguments);
}
catch(Exception e)

var processStartInfo = new ProcessStartInfo(appPath, appArguments ?? "");
if (capabilities.TryGetStringCapability("appium:appWorkingDir", out var appWorkingDir))
{
throw WebDriverResponseException.InvalidArgument($"Starting app '{appPath}' with arguments '{appArguments}' threw an exception: {e.Message}");
processStartInfo.WorkingDirectory = appWorkingDir;
}
isAppOwnedBySession = true;
return Application.Launch(processStartInfo);
}
catch (Exception e)
{
throw WebDriverResponseException.InvalidArgument($"Starting app '{appPath}' with arguments '{appArguments}' threw an exception: {e.Message}");
}

isAppOwnedBySession = true;
}
else if (capabilities.TryGetStringCapability("appium:appTopLevelWindow", out var appTopLevelWindowString))

if (capabilities.TryGetStringCapability("appium:appTopLevelWindow", out var appTopLevelWindowString))
{
isAppOwnedBySession = false;
Process process = GetProcessByMainWindowHandle(appTopLevelWindowString);
app = Core.Application.Attach(process);
return Application.Attach(process);
}
else if (capabilities.TryGetStringCapability("appium:appTopLevelWindowTitleMatch", out var appTopLevelWindowTitleMatch))

if (capabilities.TryGetStringCapability("appium:appTopLevelWindowTitleMatch", out var appTopLevelWindowTitleMatch))
{
isAppOwnedBySession = false;
Process? process = GetProcessByMainWindowTitle(appTopLevelWindowTitleMatch);
app = Core.Application.Attach(process);
}
else
{
throw WebDriverResponseException.InvalidArgument("One of appium:app, appium:appTopLevelWindow or appium:appTopLevelWindowTitleMatch must be passed as a capability");
}
var session = new Session(app, isAppOwnedBySession);
if(capabilities.TryGetNumberCapability("appium:newCommandTimeout", out var newCommandTimeout))
{
session.NewCommandTimeout = TimeSpan.FromSeconds(newCommandTimeout);
return Application.Attach(process);
}
if (capabilities.TryGetCapability<TimeoutsConfiguration>("timeouts", out var timeoutsConfiguration))
{
session.TimeoutsConfiguration = timeoutsConfiguration!;
}
_sessionRepository.Add(session);
_logger.LogInformation("Created session with ID {SessionId} and capabilities {Capabilities}", session.SessionId, capabilities);
return await Task.FromResult(WebDriverResult.Success(new CreateSessionResponse()
{
SessionId = session.SessionId,
Capabilities = capabilities.Capabilities
}));

throw WebDriverResponseException.InvalidArgument("One of appium:app, appium:appTopLevelWindow or appium:appTopLevelWindowTitleMatch must be passed as a capability");
}

private string? GetMismatchIndication(MergedCapabilities capabilities)
Expand Down Expand Up @@ -163,7 +180,7 @@ private bool TryMatchCapabilities(MergedCapabilities capabilities, [MaybeNullWhe
matchedCapabilities.Copy("appium:appTopLevelWindow", capabilities);
}
else if (capabilities.Contains("appium:appTopLevelWindowTitleMatch"))
{
{
matchedCapabilities.Copy("appium:appTopLevelWindowTitleMatch", capabilities);
}
else
Expand Down Expand Up @@ -199,8 +216,8 @@ private static Process GetProcessByMainWindowTitle(string appTopLevelWindowTitle
try
{
appMainWindowTitleRegex = new Regex(appTopLevelWindowTitleMatch);
}
catch(ArgumentException e)
}
catch (ArgumentException e)
{
throw WebDriverResponseException.InvalidArgument($"Capability appium:appTopLevelWindowTitleMatch '{appTopLevelWindowTitleMatch}' is not a valid regular expression: {e.Message}");
}
Expand All @@ -209,7 +226,7 @@ private static Process GetProcessByMainWindowTitle(string appTopLevelWindowTitle
{
throw WebDriverResponseException.InvalidArgument($"Process with main window title matching '{appTopLevelWindowTitleMatch}' could not be found");
}
else if (processes.Length > 1)
if (processes.Length > 1)
{
throw WebDriverResponseException.InvalidArgument($"Found multiple ({processes.Length}) processes with main window title matching '{appTopLevelWindowTitleMatch}'");
}
Expand Down
5 changes: 3 additions & 2 deletions src/FlaUI.WebDriver/Session.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ namespace FlaUI.WebDriver
{
public class Session : IDisposable
{
public Session(Application? app, bool isAppOwnedBySession)
public Session(Application? app, bool isAppOwnedBySession, TimeoutsConfiguration timeoutsConfiguration, TimeSpan newCommandTimeout)
{
App = app;
SessionId = Guid.NewGuid().ToString();
Automation = new UIA3Automation();
InputState = new InputState();
TimeoutsConfiguration = new TimeoutsConfiguration();
TimeoutsConfiguration = timeoutsConfiguration;
IsAppOwnedBySession = isAppOwnedBySession;
NewCommandTimeout = newCommandTimeout;

if (app != null)
{
Expand Down
15 changes: 12 additions & 3 deletions src/TestApplications/WpfApplication/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Windows;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

Expand All @@ -9,6 +10,8 @@ namespace WpfApplication
/// </summary>
public partial class MainWindow
{
private Window1 _subWindow;

public MainWindow()
{
InitializeComponent();
Expand All @@ -34,6 +37,12 @@ protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
base.OnRenderSizeChanged(sizeInfo);
}

protected override void OnClosing(CancelEventArgs e)
{
_subWindow?.Close();
base.OnClosing(e);
}

private void OnShowLabel(object sender, RoutedEventArgs e)
{
MenuItem menuitem = sender as MenuItem;
Expand Down Expand Up @@ -68,8 +77,8 @@ private void OnDisableForm(object sender, RoutedEventArgs e)

private void MenuItem_Click(object sender, RoutedEventArgs e)
{
var window = new Window1();
window.Show();
_subWindow = new Window1();
_subWindow.Show();
}

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

0 comments on commit 8005715

Please sign in to comment.