diff --git a/SeleniumManager.ConsoleApp/Program.cs b/SeleniumManager.ConsoleApp/Program.cs
index cffcfcd..a0ae0ae 100644
--- a/SeleniumManager.ConsoleApp/Program.cs
+++ b/SeleniumManager.ConsoleApp/Program.cs
@@ -10,7 +10,7 @@ static void Main(string[] args)
{
string jarName = "selenium-server-4.9.1.jar"; // Name of your JAR file
string jarPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), jarName); // Path to your JAR file
- string arguments = $" -jar {jarPath} standalone ";//--driver-implementation \"Chrome\"";
+ string arguments = $@" -jar {jarPath} standalone ";// --config D:\dev\C#\SeleniumManager\SeleniumManager.ConsoleApp\myconfig.toml";//--driver-implementation \"Chrome\"";
ProcessStartInfo psi = new ProcessStartInfo("java", arguments);
psi.CreateNoWindow = false; // Hide the console window
psi.UseShellExecute = false; // Do not use the operating system shell to start the process
diff --git a/SeleniumManager.Core/ConfigManager.cs b/SeleniumManager.Core/ConfigManager.cs
index 988f31c..239b991 100644
--- a/SeleniumManager.Core/ConfigManager.cs
+++ b/SeleniumManager.Core/ConfigManager.cs
@@ -12,8 +12,18 @@ namespace SeleniumManager.Core
{
public class ConfigManager
{
+ #region Declaration
+
public readonly ConfigurationSettings configSettings;
+ #endregion
+
+ #region Public Functions
+
+ ///
+ /// This function sets the config required for the Selenium Manager
+ ///
+ ///
public ConfigManager(string? configFilePath = null)
{
if (string.IsNullOrEmpty(configFilePath))
@@ -28,6 +38,10 @@ public ConfigManager(string? configFilePath = null)
}
}
+ #endregion
+
+ #region Private Functions
+
private ConfigurationSettings LoadConfigSettingsFromResource(string resourceName)
{
Assembly assembly = Assembly.GetExecutingAssembly();
@@ -68,5 +82,8 @@ private ConfigurationSettings LoadConfigSettingsFromFile(string configFilePath)
return LoadConfigSettingsFromResource("SeleniumManager.Core.Configuration.config.json");
}
}
+
+ #endregion
+
}
}
diff --git a/SeleniumManager.Core/DataContract/Options.cs b/SeleniumManager.Core/DataContract/Options.cs
index 9a50358..d1692a4 100644
--- a/SeleniumManager.Core/DataContract/Options.cs
+++ b/SeleniumManager.Core/DataContract/Options.cs
@@ -20,6 +20,7 @@ public class Options
public EdgeOptions edgeOptions { get; set; } = GetEdgeOptions();
public InternetExplorerOptions internetExplorerOptions { get; set; } = GetInternetExplorerOptions();
public SafariOptions safariOptions { get; set; } = GetSafariOptions();
+ public ChromeOptions operaOptions { get; set; } = GetChromeOptions();
public static ChromeOptions GetChromeOptions()
{
@@ -39,8 +40,8 @@ public static FirefoxOptions GetFirefoxOptions()
#if !DEBUG
firefoxOptions.AddArgument("headless");
#endif
- firefoxOptions.AddArgument("disable-gpu");
- firefoxOptions.AddArgument("no-sandbox");
+ //firefoxOptions.AddArgument("disable-gpu");
+ //firefoxOptions.AddArgument("no-sandbox");
firefoxOptions.AddArgument("--blink-settings=imagesEnabled=false");
return firefoxOptions;
}
diff --git a/SeleniumManager.Core/Enum/AdjustType.cs b/SeleniumManager.Core/Enum/AdjustType.cs
new file mode 100644
index 0000000..1e1b586
--- /dev/null
+++ b/SeleniumManager.Core/Enum/AdjustType.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SeleniumManager.Core.Enum
+{
+ ///
+ /// Tells the selenium manager to Create or destroy a instance
+ ///
+ public enum AdjustType
+ {
+ Create = 1,
+ Destroy = 2
+ }
+}
diff --git a/SeleniumManager.Core/Enum/WebDriverType.cs b/SeleniumManager.Core/Enum/WebDriverType.cs
new file mode 100644
index 0000000..65d0758
--- /dev/null
+++ b/SeleniumManager.Core/Enum/WebDriverType.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SeleniumManager.Core.Enum
+{
+ public enum WebDriverType
+ {
+ None = 0,
+ [Description("Chrome")]
+ Chrome = 1,
+ [Description("Microsoft Edge")]
+ Microsoft_Edge = 2,
+ [Description("Firefox")]
+ Firefox = 3,
+ [Description("Safari")]
+ Safari = 4,
+ [Description("InternetExplorer")]
+ InternetExplorer = 5,
+ [Description("Opera")]
+ Opera = 6,
+ [Description("Custom")]
+ Custom = 7,
+ }
+}
diff --git a/SeleniumManager.Core/Interface/ISeleniumManager.cs b/SeleniumManager.Core/Interface/ISeleniumManager.cs
index 2f3f77d..4dc029a 100644
--- a/SeleniumManager.Core/Interface/ISeleniumManager.cs
+++ b/SeleniumManager.Core/Interface/ISeleniumManager.cs
@@ -1,4 +1,5 @@
using OpenQA.Selenium;
+using SeleniumManager.Core.Enum;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -9,6 +10,122 @@ namespace SeleniumManager.Core.Interface
{
public interface ISeleniumManager
{
+ #region Properties
+ ///
+ /// Gets Max Session available
+ ///
+ int MaxSessions { get; }
+
+ ///
+ /// Gets Free Session available
+ ///
+ int FreeSessions { get; }
+
+ ///
+ /// Gets total count of session available
+ ///
+ int TotalSessions { get; }
+
+ ///
+ /// Gets Total count of available sessions
+ ///
+ int AvailableSessions { get; }
+
+ ///
+ /// Gets Total count of concurrent sessions which are in use
+ ///
+ int ConcurrentSessions { get; }
+
+ ///
+ /// Gets When Last Hartbeat was taken.
+ ///
+ /// the string represents browser's name and long represents the count
+ DateTime LastSessionDetails { get; }
+
+ ///
+ /// This dictionary has list of browsers with max count of instance available
+ ///
+ /// the string represents browser's name and long represents the count
+ Dictionary MaxStereotypes { get; }
+
+ ///
+ /// This dictionary has list of browsers with available instances.
+ ///
+ /// the string represents browser's name and long represents the count
+ Dictionary AvailableStereotypes { get; }
+
+ ///
+ /// This dictionary has list of browsers with parallel count of instance running
+ ///
+ /// the string represents browser's name and long represents the count
+ Dictionary ConcurrentStereotypes { get; }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// This function will try to execute next in line of queue
+ ///
+ ///
+ void TryExecuteNext();
+
+ ///
+ /// This function returns complete data of the status available from grid
+ /// the endpoint is mostly example.com/status
+ ///
+ /// task of dynamic
+ Task GetHeartBeat();
+
+ ///
+ /// This function returns number of available instance in a Task
+ ///
+ /// Task of int
+ Task GetAvailableInstances();
+
+ ///
+ ///
+ /// This overridable function returns the webdriver from the given browser name.
+ /// By default it will try to get best available browser from the configured statistics.
+ ///
+ ///
+ /// Name of the browser
+ /// IWebDriver
+ ///
+ IWebDriver CreateDriverInstance(string? browserName);
+
+ ///
+ /// This Function Enqueues an function
+ /// in which has the first parameter supports IWebDriver
+ ///
+ /// Action
+ ///
+ /// manager = new SeleniumManager();
+ /// manager.EnqueueAction(SomeFunction);
+ /// string SomeFunction(IWebDriver driver) { }
+ ///
+ /// TaskCompletionSource string
+ ///
Task EnqueueAction(Func action);
+
+ ///
+ /// This function checks if the browser is available or not.
+ ///
+ /// Name of the browser
+ ///
+ ///
+ string GetAvailableDriverName(string? browserName);
+
+ ///
+ /// This Function override Enqueues an function
+ /// in which has the first parameter supports IWebDriver and the other is the brousername you want
+ ///
+ ///
+ /// Name of the brouser for example check WebDriverType enum
+ ///
+ ///
+ Task EnqueueAction(Func action, string browserName);
+ #endregion
+
}
}
diff --git a/SeleniumManager.Core/SeleniumManager.Core.csproj b/SeleniumManager.Core/SeleniumManager.Core.csproj
index 133f9fe..65c7fc4 100644
--- a/SeleniumManager.Core/SeleniumManager.Core.csproj
+++ b/SeleniumManager.Core/SeleniumManager.Core.csproj
@@ -14,16 +14,17 @@
This include managing Queues, Parallel Tests, etc.
MIT License
True
- 0.0.0.3
- 0.0.0.3-alpha
+ 0.0.0.4
+ 0.0.0.4-alpha
+ True
- 1701;1702;8618
+ 1701;1702;8618;1591
- 1701;1702;8618
+ 1701;1702;8618;1591
@@ -50,7 +51,7 @@ This include managing Queues, Parallel Tests, etc.
-
+
diff --git a/SeleniumManager.Core/SeleniumManager.cs b/SeleniumManager.Core/SeleniumManager.cs
index 8819550..a404c83 100644
--- a/SeleniumManager.Core/SeleniumManager.cs
+++ b/SeleniumManager.Core/SeleniumManager.cs
@@ -1,10 +1,7 @@
-using Newtonsoft.Json.Linq;
-using OpenQA.Selenium;
-using OpenQA.Selenium.Chrome;
-using OpenQA.Selenium.Edge;
-using OpenQA.Selenium.Firefox;
+using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using SeleniumManager.Core.DataContract;
+using SeleniumManager.Core.Enum;
using SeleniumManager.Core.Interface;
using SeleniumManager.Core.Utils;
using System;
@@ -12,8 +9,10 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
+using System.Reflection;
using System.Text;
using System.Threading.Tasks;
+using static SeleniumManager.Core.SeleniumManager;
namespace SeleniumManager.Core
{
@@ -21,12 +20,15 @@ public class SeleniumManager: ISeleniumManager
{
#region Declerations
+ #region Private Properties
private readonly SemaphoreSlim _semaphore;
private readonly SemaphoreSlim _availableStereotypesSemaphore = new SemaphoreSlim(1, 1);
- private readonly ConcurrentQueue> _queue;
+ private readonly ConcurrentQueue _queue;
private readonly ConfigurationSettings _configSettings;
private readonly HttpClient httpClient;
+ #endregion
+ #region Public Properties
public int MaxSessions { get; private set; } = 0;
public int FreeSessions { get; private set; } = 0;
public int ConcurrentSessions { get; private set; } = 0;
@@ -36,11 +38,9 @@ public class SeleniumManager: ISeleniumManager
public Dictionary ConcurrentStereotypes { get; private set; } = new();
public Dictionary AvailableStereotypes { get; private set; } = new();
public DateTime LastSessionDetails { get; private set; }
- enum AdjustType
- {
- Create = 1,
- Destroy = 2
- }
+ public delegate void ActionWithBrowser(IWebDriver driver, string? browserName);
+ #endregion
+
#endregion
#region Constructor
@@ -49,7 +49,7 @@ public SeleniumManager(ConfigManager configManager)
_configSettings = configManager.configSettings;
httpClient = new HttpClient();
_semaphore = new SemaphoreSlim(GetAvailableInstances().Result,1000);
- _queue = new ConcurrentQueue>();
+ _queue = new ConcurrentQueue();
}
#endregion
@@ -60,7 +60,7 @@ public virtual Task EnqueueAction(Func action)
{
var tcs = new TaskCompletionSource();
- _queue.Enqueue(driver =>
+ _queue.Enqueue((driver,n) =>
{
try
{
@@ -86,21 +86,60 @@ public virtual Task EnqueueAction(Func action)
TryExecuteNext();
return tcs.Task;
}
+
+ public virtual Task EnqueueAction(Func action, string browserName)
+ {
+ var tcs = new TaskCompletionSource();
+
+ _queue.Enqueue((driver,bn) =>
+ {
+ try
+ {
+ bn = browserName;
+
+ // Execute the action and get the result
+ var result = action(driver);
+
+ // Set the result as the task completion result
+ tcs.SetResult(result);
+ }
+ catch (Exception ex)
+ {
+ // Set the exception as the task completion exception
+ tcs.SetException(ex);
+ throw new Exception("Error Occoured inside Action", ex);
+ }
+ finally
+ {
+ // Dispose the driver if not already done
+ driver?.Dispose();
+ }
+ });
+
+ TryExecuteNext();
+ return tcs.Task;
+ }
+
public async void TryExecuteNext()
{
await _semaphore.WaitAsync(); // Acquire the semaphore
if (_queue.TryDequeue(out var action))
{
- string browserName = "";
+ string? browserName = null;
+ if (action.Target != null)
+ {
+ FieldInfo browserNameField = action.Target.GetType().GetField("browserName");
+ browserName = (string?)browserNameField?.GetValue(action.Target);
+ }
// TODO: make it like get the driver first and then process the action
try
{
// for now only using chrome for testing
- IWebDriver _driver = CreateDriverInstance();
+ IWebDriver _driver = CreateDriverInstance(browserName);
ICapabilities capabilities = ((RemoteWebDriver)_driver).Capabilities;
browserName = capabilities.GetCapability("browserName").ToString();
- action(_driver);
+ action(_driver, browserName);
// Release driver
_driver.Dispose();
@@ -129,8 +168,11 @@ public async void TryExecuteNext()
}
}
}
+
public virtual async Task GetAvailableInstances()
{
+ LastSessionDetails = DateTime.Now;
+
var nodeStatus = await GetStatus();
if (nodeStatus == null) return 0;
@@ -149,6 +191,7 @@ public virtual async Task GetAvailableInstances()
return nodeStatus;
}
+
public virtual IWebDriver CreateDriverInstance(string? browserName = null)
{
IWebDriver driver;
@@ -156,27 +199,41 @@ public virtual IWebDriver CreateDriverInstance(string? browserName = null)
switch (browserName.ToLower())
{
case "firefox":
+ case "geko":
driver = new RemoteWebDriver(new Uri(_configSettings.GridHost.ToString()), _configSettings.Options.firefoxOptions);
-
break;
+
case "chrome":
driver = new RemoteWebDriver(new Uri(_configSettings.GridHost.ToString()), _configSettings.Options.chromeOptions);
break;
+
case "microsoftedge":
driver = new RemoteWebDriver(new Uri(_configSettings.GridHost.ToString()), _configSettings.Options.edgeOptions);
break;
+
case "safari":
driver = new RemoteWebDriver(new Uri(_configSettings.GridHost.ToString()), _configSettings.Options.safariOptions);
break;
+
+ // Not Tested
case "ie":
+ case "internetexplorer":
+ case "internet explorer":
driver = new RemoteWebDriver(new Uri(_configSettings.GridHost.ToString()), _configSettings.Options.internetExplorerOptions);
break;
+
+ // Not Tested
+ case "opera":
+ driver = new RemoteWebDriver(new Uri(_configSettings.GridHost.ToString()), _configSettings.Options.operaOptions);
+ break;
+
default:
throw new ArgumentException("Browser not supported yet!");
}
return driver;
}
+
public string GetAvailableDriverName(string? browserName)
{
// check if last session was gotten in last 1 min get from config default 1 min
@@ -256,7 +313,6 @@ private void getSessions(dynamic nodeStatus)
_availableStereotypesSemaphore.Release();
ConcurrentSessions = TotalSessions - FreeSessions;
AvailableSessions = MaxSessions - ConcurrentSessions;
- LastSessionDetails = DateTime.Now;
}
private void ResetValues()
@@ -298,7 +354,7 @@ private async Task FindBestAvailableBrowser()
}
// If no available browser is found, return the browser with the highest instances count
- return statistics.OrderByDescending(x => x.Value).FirstOrDefault().Key ?? "Chrome";
+ return statistics.OrderByDescending(x => x.Value).FirstOrDefault().Key ?? WebDriverType.Chrome.GetDescription();
}
private void AdjustInstance(string key,AdjustType type)
diff --git a/SeleniumManager.Core/Utils/WebDriverTypeExtensions.cs b/SeleniumManager.Core/Utils/WebDriverTypeExtensions.cs
new file mode 100644
index 0000000..618e030
--- /dev/null
+++ b/SeleniumManager.Core/Utils/WebDriverTypeExtensions.cs
@@ -0,0 +1,46 @@
+using SeleniumManager.Core.Enum;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+
+public static class WebDriverTypeExtensions
+{
+ private static readonly Dictionary customDescriptions = new Dictionary();
+
+ public static string GetDescription(this WebDriverType value)
+ {
+ if (customDescriptions.TryGetValue(value, out string customDescription))
+ {
+ return customDescription;
+ }
+
+ Type enumType = value.GetType();
+ string name = Enum.GetName(enumType, value);
+
+ if (name != null)
+ {
+ FieldInfo field = enumType.GetField(name);
+ if (field != null)
+ {
+ DescriptionAttribute attr = field.GetCustomAttribute();
+ if (attr != null)
+ {
+ return attr.Description;
+ }
+ }
+ }
+
+ return value.ToString();
+ }
+
+ public static void SetCustomDescription(WebDriverType type, string description)
+ {
+ customDescriptions[type] = description;
+ }
+}
+
diff --git a/SeleniumManager.Tests/BrowsingTest.cs b/SeleniumManager.Tests/BrowsingTest.cs
index 3bdca2a..c92ff79 100644
--- a/SeleniumManager.Tests/BrowsingTest.cs
+++ b/SeleniumManager.Tests/BrowsingTest.cs
@@ -31,6 +31,16 @@ public async Task TestBrouse()
}
+ [TestMethod]
+ public async Task TestBrouseChrome()
+ {
+ var data = await _seleniumManager.EnqueueAction(BrouseWebsite, "chrome");
+
+ // Start processing the actions
+ _seleniumManager.TryExecuteNext();
+
+ }
+
[TestMethod]
public async Task ParallelTestBrouse()
{
diff --git a/SeleniumManager.Tests/SeleniumManager.Tests.csproj b/SeleniumManager.Tests/SeleniumManager.Tests.csproj
index fb51eb8..9ac9041 100644
--- a/SeleniumManager.Tests/SeleniumManager.Tests.csproj
+++ b/SeleniumManager.Tests/SeleniumManager.Tests.csproj
@@ -1,4 +1,4 @@
-
+
net7.0
@@ -14,6 +14,7 @@
+