Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/ElectronNET.API/API/ApiBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ protected enum SocketEventNameTypes
CamelCase,
}

private const int InvocationTimeout = 1000;
private static readonly TimeSpan InvocationTimeout = 1000.ms();

private readonly string objectName;
private readonly ConcurrentDictionary<string, Invocator> invocators;
Expand Down Expand Up @@ -120,7 +120,7 @@ protected Task<T> InvokeAsync<T>(object arg = null, [CallerMemberName] string ca
return this.InvokeAsyncWithTimeout<T>(InvocationTimeout, arg, callerName);
}

protected Task<T> InvokeAsyncWithTimeout<T>(int invocationTimeout, object arg = null, [CallerMemberName] string callerName = null)
protected Task<T> InvokeAsyncWithTimeout<T>(TimeSpan invocationTimeout, object arg = null, [CallerMemberName] string callerName = null)
{
Debug.Assert(callerName != null, nameof(callerName) + " != null");

Expand Down Expand Up @@ -245,7 +245,7 @@ internal class Invocator<T> : Invocator
private readonly Task<T> tcsTask;
private TaskCompletionSource<T> tcs;

public Invocator(ApiBase apiBase, string callerName, int timeoutMs, object arg = null)
public Invocator(ApiBase apiBase, string callerName, TimeSpan timeout, object arg = null)
{
this.tcs = new TaskCompletionSource<T>(TaskCreationOptions.RunContinuationsAsynchronously);
this.tcsTask = this.tcs.Task;
Expand Down Expand Up @@ -306,15 +306,15 @@ public Invocator(ApiBase apiBase, string callerName, int timeoutMs, object arg =
_ = apiBase.Id >= 0 ? BridgeConnector.Socket.Emit(messageName, apiBase.Id) : BridgeConnector.Socket.Emit(messageName);
}

System.Threading.Tasks.Task.Delay(timeoutMs).ContinueWith(_ =>
System.Threading.Tasks.Task.Delay(timeout).ContinueWith(_ =>
{
if (this.tcs != null)
{
lock (this)
{
if (this.tcs != null)
{
var ex = new TimeoutException($"No response after {timeoutMs:D}ms trying to retrieve value {apiBase.objectName}.{callerName}()");
var ex = new TimeoutException($"No response after {timeout:D}ms trying to retrieve value {apiBase.objectName}.{callerName}()");
this.tcs.TrySetException(ex);
this.tcs = null;
}
Expand Down
7 changes: 4 additions & 3 deletions src/ElectronNET.API/API/WebContents.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using ElectronNET.API.Entities;
using System;
using System.Threading.Tasks;
using ElectronNET.API.Entities;
using ElectronNET.Common;

// ReSharper disable InconsistentNaming

Expand Down Expand Up @@ -173,7 +174,7 @@ public bool IsDevToolsFocused()
/// Get system printers.
/// </summary>
/// <returns>printers</returns>
public Task<PrinterInfo[]> GetPrintersAsync() => this.InvokeAsyncWithTimeout<PrinterInfo[]>(5_000);
public Task<PrinterInfo[]> GetPrintersAsync() => this.InvokeAsyncWithTimeout<PrinterInfo[]>(8.seconds());

/// <summary>
/// Prints window's web page.
Expand Down Expand Up @@ -388,7 +389,7 @@ public void SetAudioMuted(bool muted)
/// Returns string - The user agent for this web page.
/// </summary>
/// <returns></returns>
public Task<string> GetUserAgentAsync() => InvokeAsync<string>();
public Task<string> GetUserAgentAsync() => InvokeAsyncWithTimeout<string>(3.seconds());

/// <summary>
/// Overrides the user agent for this web page.
Expand Down
74 changes: 74 additions & 0 deletions src/ElectronNET.API/Common/TimeSpanExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// <copyright file="TimeSpanExtensions.cs" company="Emby LLC">
// Copyright © Emby LLC. All rights reserved.
// </copyright>

namespace ElectronNET.Common
{
using System;
using System.Diagnostics.CodeAnalysis;

/// <summary>
/// The TimeSpanExtensions class.
/// </summary>
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "OK")]
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "OK")]
[SuppressMessage("ReSharper", "StyleCop.SA1300", Justification = "OK")]
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "OK")]
internal static class TimeSpanExtensions
{
public static TimeSpan ms(this int value)
{
return TimeSpan.FromMilliseconds(value);
}

public static TimeSpan ms(this long value)
{
return TimeSpan.FromMilliseconds(value);
}

public static TimeSpan seconds(this int value)
{
return TimeSpan.FromSeconds(value);
}

public static TimeSpan minutes(this int value)
{
return TimeSpan.FromMinutes(value);
}

public static TimeSpan hours(this int value)
{
return TimeSpan.FromHours(value);
}

public static TimeSpan days(this int value)
{
return TimeSpan.FromDays(value);
}

public static TimeSpan ms(this double value)
{
return TimeSpan.FromMilliseconds(value);
}

public static TimeSpan seconds(this double value)
{
return TimeSpan.FromSeconds(value);
}

public static TimeSpan minutes(this double value)
{
return TimeSpan.FromMinutes(value);
}

public static TimeSpan hours(this double value)
{
return TimeSpan.FromHours(value);
}

public static TimeSpan days(this double value)
{
return TimeSpan.FromDays(value);
}
}
}
1 change: 1 addition & 0 deletions src/ElectronNET.API/ElectronNET.API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@
<ItemGroup>
<InternalsVisibleTo Include="ElectronNET.AspNet" />
<InternalsVisibleTo Include="ElectronNET.Core.AspNet" />
<InternalsVisibleTo Include="ElectronNET.IntegrationTests" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ private async Task StartInternal(string startCmd, string args, string directoriy
{
try
{
await Task.Delay(10).ConfigureAwait(false);
await Task.Delay(10.ms()).ConfigureAwait(false);

Console.Error.WriteLine("[StartInternal]: startCmd: {0}", startCmd);
Console.Error.WriteLine("[StartInternal]: args: {0}", args);
Expand All @@ -85,7 +85,7 @@ private async Task StartInternal(string startCmd, string args, string directoriy
this.process.ProcessExited += this.Process_Exited;
this.process.Run(startCmd, args, directoriy);

await Task.Delay(500).ConfigureAwait(false);
await Task.Delay(500.ms()).ConfigureAwait(false);

Console.Error.WriteLine("[StartInternal]: after run:");

Expand Down
101 changes: 101 additions & 0 deletions src/ElectronNET.IntegrationTests/Common/IntegrationFactAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
namespace ElectronNET.IntegrationTests.Common
{
using System.Runtime.InteropServices;
using Xunit.Sdk;

/// <summary>
/// Custom fact attribute with a default timeout of 20 seconds, allowing tests to be skipped on specific environments.
/// </summary>
/// <seealso cref="Xunit.FactAttribute" />
[AttributeUsage(AttributeTargets.Method)]
[XunitTestCaseDiscoverer("Xunit.Sdk.SkippableFactDiscoverer", "Xunit.SkippableFact")]
internal sealed class IntegrationFactAttribute : FactAttribute
{
private static readonly bool IsOnWsl;

private static readonly bool IsOnCI;

static IntegrationFactAttribute()
{
IsOnWsl = DetectWsl();
IsOnCI = DetectCI();
}

/// <summary>
/// Initializes a new instance of the <see cref="IntegrationFactAttribute" /> class.
/// </summary>
public IntegrationFactAttribute()
{
this.Timeout = 20_000;
}

public bool SkipOnWsl { get; set; }

public bool SkipOnCI { get; set; }

/// <summary>
/// Marks the test so that it will not be run, and gets or sets the skip reason
/// </summary>
public override string Skip {
get
{
if (IsOnWsl && this.SkipOnWsl)
{
return "Skipping test on WSL environment.";
}

if (IsOnCI && this.SkipOnCI)
{
return "Skipping test on CI environment.";
}

return base.Skip;
}
set
{
base.Skip = value;
}
}

private static bool DetectWsl()
{
try
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return false;
}

if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WSL_DISTRO_NAME")) ||
!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WSL_INTEROP")))
{
return true;
}

return false;
}
catch
{
return false;
}
}

private static bool DetectCI()
{
try
{
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TF_BUILD")) ||
!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GITHUB_ACTIONS")))
{
return true;
}

return false;
}
catch
{
return false;
}
}
}
}
23 changes: 23 additions & 0 deletions src/ElectronNET.IntegrationTests/Common/IntegrationTestBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace ElectronNET.IntegrationTests.Common
{
using ElectronNET.API;
using ElectronNET.API.Entities;

// Base class for integration tests providing shared access to MainWindow and OS platform constants
public abstract class IntegrationTestBase
{
protected IntegrationTestBase(ElectronFixture fixture)
{
Fixture = fixture;
MainWindow = fixture.MainWindow;
}

protected ElectronFixture Fixture { get; }
protected BrowserWindow MainWindow { get; }

// Constants for SupportedOSPlatform attributes
public const string Windows = "Windows";
public const string MacOS = "macOS";
public const string Linux = "Linux";
}
}
49 changes: 0 additions & 49 deletions src/ElectronNET.IntegrationTests/Common/SkipOnWslFactAttribute.cs

This file was deleted.

3 changes: 2 additions & 1 deletion src/ElectronNET.IntegrationTests/ElectronFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace ElectronNET.IntegrationTests
using System.Reflection;
using ElectronNET.API;
using ElectronNET.API.Entities;
using ElectronNET.Common;

// Shared fixture that starts Electron runtime once
[SuppressMessage("ReSharper", "MethodHasAsyncOverload")]
Expand All @@ -26,7 +27,7 @@ public async Task InitializeAsync()
await runtimeController.Start();

Console.Error.WriteLine("[ElectronFixture] Waiting for Ready...");
await Task.WhenAny(runtimeController.WaitReadyTask, Task.Delay(TimeSpan.FromSeconds(10)));
await Task.WhenAny(runtimeController.WaitReadyTask, Task.Delay(10.seconds()));

if (!runtimeController.WaitReadyTask.IsCompleted)
{
Expand Down
Loading