Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
c75901c
Move assets to nuget directory
nvborisenko Jul 12, 2025
34d5be5
Fix dotnet build
nvborisenko Jul 12, 2025
4754394
Import shared targets
nvborisenko Jul 12, 2025
33c2234
Import targets
nvborisenko Jul 12, 2025
a0cd824
Fix dotnet build
nvborisenko Jul 12, 2025
abc0858
Support buildMultiTargeting
nvborisenko Jul 12, 2025
8a747d1
Update Selenium.WebDriver.csproj
nvborisenko Jul 13, 2025
050c3dd
Pack as native dependency
nvborisenko Jul 13, 2025
715d7b6
dotnet pack
nvborisenko Jul 13, 2025
47b2065
Update Selenium.WebDriver.csproj
nvborisenko Jul 13, 2025
3106d3c
Now it is possible to reference csproj witout any custom targets
nvborisenko Jul 13, 2025
b3f29e5
Clean test project
nvborisenko Jul 13, 2025
088e107
Green tests
nvborisenko Jul 13, 2025
da351d4
Amazing improvement
nvborisenko Jul 13, 2025
8636b15
Throw if not supported
nvborisenko Jul 13, 2025
86ef405
Remove old targets
nvborisenko Jul 14, 2025
e5a0648
Remove unnecessary buildMultiTargeting
nvborisenko Jul 14, 2025
2189a3d
Custom targets for netstandard2.0 only
nvborisenko Jul 14, 2025
8819990
Legacy packages.config support
nvborisenko Jul 14, 2025
2fd1c83
Fix bazel part
nvborisenko Jul 14, 2025
2b32f0f
Add other assets for legacy projects
nvborisenko Jul 14, 2025
e68ab2a
Throw fast if provided incorrectly
nvborisenko Jul 14, 2025
7b86af1
Probing couple of potential SM paths
nvborisenko Jul 14, 2025
f980107
Single file and AOT
nvborisenko Jul 14, 2025
b63491e
Remove temporary fallback
nvborisenko Jul 14, 2025
70009e2
Finally
nvborisenko Jul 14, 2025
5c40a80
Update SeleniumManager.cs
nvborisenko Jul 14, 2025
7ec66a3
Distinct and format error
nvborisenko Jul 14, 2025
5354d1c
Fix bazel, we like it
nvborisenko Jul 14, 2025
10c068d
Fix NullRef
nvborisenko Jul 14, 2025
b856428
More explanations
nvborisenko Jul 15, 2025
a4be9be
More explanations
nvborisenko Jul 15, 2025
8f7a81f
Format script?
nvborisenko Jul 15, 2025
40cf289
Use Path.PathSeparator
nvborisenko Jul 15, 2025
6d64cd2
Use linq to probe file existance
nvborisenko Jul 15, 2025
d4b3da8
Clearer bazel assets target names
nvborisenko Jul 15, 2025
e129016
Merge branch 'trunk' into dotnet-sm-native
nvborisenko Jul 16, 2025
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
26 changes: 13 additions & 13 deletions dotnet/src/webdriver/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -162,21 +162,21 @@ csharp_library(
)

copy_file(
name = "readme",
src = "//dotnet/src/webdriver/assets:README.md",
name = "assets-nuget-readme",
src = "//dotnet/src/webdriver/assets:nuget/README.md",
out = "README.md",
)

copy_file(
name = "props",
src = "//dotnet/src/webdriver/assets:Selenium.WebDriver.targets",
name = "assets-nuget-build-netstandard20-targets",
src = "//dotnet/src/webdriver/assets:nuget/build/netstandard2.0/Selenium.WebDriver.targets",
out = "Selenium.WebDriver.targets",
)

copy_file(
name = "transitive-props",
src = "//dotnet/src/webdriver/assets:Selenium.WebDriver.targets",
out = "transitive.Selenium.WebDriver.targets",
name = "assets-nuget-buildtransitive-netstandard20-targets",
src = "//dotnet/src/webdriver/assets:nuget/buildTransitive/netstandard2.0/Selenium.WebDriver.targets",
out = "transitiveSelenium.WebDriver.targets",
)

copy_file(
Expand Down Expand Up @@ -207,9 +207,9 @@ nuget_pack(
"//common/manager:selenium-manager-linux": "manager/linux/selenium-manager",
"//common/manager:selenium-manager-macos": "manager/macos/selenium-manager",
"//common/manager:selenium-manager-windows": "manager/windows/selenium-manager.exe",
":readme": "README.md",
":props": "build/Selenium.WebDriver.targets",
":transitive-props": "buildTransitive/Selenium.WebDriver.targets",
":assets-nuget-readme": "README.md",
":assets-nuget-build-netstandard20-targets": "build/netstandard2.0/Selenium.WebDriver.targets",
":assets-nuget-buildtransitive-netstandard20-targets": "buildTransitive/netstandard2.0/Selenium.WebDriver.targets",
},
id = "Selenium.WebDriver",
libs = {
Expand All @@ -233,9 +233,9 @@ nuget_pack(
"//common/manager:selenium-manager-linux": "manager/linux/selenium-manager",
"//common/manager:selenium-manager-macos": "manager/macos/selenium-manager",
"//common/manager:selenium-manager-windows": "manager/windows/selenium-manager.exe",
":readme": "README.md",
":props": "build/Selenium.WebDriver.StrongNamed.targets",
":transitive-props": "buildTransitive/Selenium.WebDriver.StrongNamed.targets",
":assets-nuget-readme": "README.md",
":assets-nuget-build-netstandard20-targets": "build/netstandard2.0/Selenium.WebDriver.StrongNamed.targets",
":assets-nuget-buildtransitive-netstandard20-targets": "buildTransitive/netstandard2.0/Selenium.WebDriver.StrongNamed.targets",
},
id = "Selenium.WebDriver.StrongNamed",
libs = {
Expand Down
10 changes: 5 additions & 5 deletions dotnet/src/webdriver/Selenium.WebDriver.StrongNamed.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@
<file src="lib/net8.0/WebDriver.StrongNamed.pdb" target="lib/net8.0/WebDriver.StrongNamed.pdb" />
<file src="lib/net8.0/WebDriver.StrongNamed.xml" target="lib/net8.0/WebDriver.StrongNamed.xml" />

<file src="build/Selenium.WebDriver.StrongNamed.targets" target="build/Selenium.WebDriver.StrongNamed.targets"/>
<file src="buildTransitive/Selenium.WebDriver.StrongNamed.targets" target="buildTransitive/Selenium.WebDriver.StrongNamed.targets"/>
<file src="build/netstandard2.0/Selenium.WebDriver.StrongNamed.targets" target="build/netstandard2.0/Selenium.WebDriver.StrongNamed.targets"/>
<file src="buildTransitive/netstandard2.0/Selenium.WebDriver.StrongNamed.targets" target="buildTransitive/netstandard2.0/Selenium.WebDriver.StrongNamed.targets"/>

<file src="manager/linux/selenium-manager" target="manager/linux/selenium-manager" />
<file src="manager/macos/selenium-manager" target="manager/macos/selenium-manager" />
<file src="manager/windows/selenium-manager.exe" target="manager/windows/selenium-manager.exe" />
<file src="manager/linux/selenium-manager" target="runtimes/linux/native/selenium-manager" />
<file src="manager/macos/selenium-manager" target="runtimes/osx/native/selenium-manager" />
<file src="manager/windows/selenium-manager.exe" target="runtimes/win/native/selenium-manager.exe" />

<file src="icon.png" />
<file src="README.md" />
Expand Down
34 changes: 17 additions & 17 deletions dotnet/src/webdriver/Selenium.WebDriver.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<PropertyGroup>
<BaseSeleniumManagerPath>$(MSBuildThisFileDirectory)..\..\..\bazel-bin\dotnet\src\webdriver\manager</BaseSeleniumManagerPath>
</PropertyGroup>

<!--TODO when AOT is ready https://github.com/SeleniumHQ/selenium/issues/14480-->
<!--<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">
<IsAotCompatible>true</IsAotCompatible>
Expand All @@ -56,29 +60,25 @@
<PackageReference Include="System.Text.Json" Version="8.0.5" />
</ItemGroup>

<PropertyGroup>
<BaseImagePath>..\..\..\bazel-bin\dotnet\src\webdriver\images</BaseImagePath>
</PropertyGroup>

<ItemGroup>
<None Include="assets\Selenium.WebDriver.targets" Pack="true" PackagePath="build\" />
<None Include="assets\Selenium.WebDriver.targets" Pack="true" PackagePath="buildTransitive\" />

<None Include="$(BaseImagePath)\selenium_logo_small.png" Pack="true" PackagePath="logo.png" Visible="false" />

<None Include="$(BaseSeleniumManagerPath)\linux\selenium-manager" Pack="true" PackagePath="manager\linux" Visible="false" />
<None Include="$(BaseSeleniumManagerPath)\macos\selenium-manager" Pack="true" PackagePath="manager\macos" Visible="false" />
<None Include="$(BaseSeleniumManagerPath)\windows\selenium-manager.exe" Pack="true" PackagePath="manager\windows" Visible="false" />
<None Include="assets\nuget\build\netstandard2.0\Selenium.WebDriver.targets" Pack="true" PackagePath="build\netstandard2.0\" />
<None Include="assets\nuget\buildTransitive\netstandard2.0\Selenium.WebDriver.targets" Pack="true" PackagePath="buildTransitive\netstandard2.0\" />
</ItemGroup>

<Target Name="GenerateSeleniumManagerBinaries" BeforeTargets="BeforeBuild">
<Exec Command="bazel build //dotnet/src/webdriver:manager-linux //dotnet/src/webdriver:manager-windows //dotnet/src/webdriver:manager-macos" WorkingDirectory="../../.." />

<PropertyGroup>
<BaseSeleniumManagerPath>..\..\..\bazel-bin\dotnet\src\webdriver\manager</BaseSeleniumManagerPath>
</PropertyGroup>
</Target>

<ItemGroup>
<None Include="$(BaseSeleniumManagerPath)\linux\selenium-manager" Pack="true" PackagePath="runtimes\linux\native\" Visible="false" CopyToOutputDirectory="PreserveNewest" Link="runtimes\linux\native\selenium-manager" />
<None Include="$(BaseSeleniumManagerPath)\macos\selenium-manager" Pack="true" PackagePath="runtimes\osx\native\" Visible="false" CopyToOutputDirectory="PreserveNewest" Link="runtimes\osx\native\selenium-manager" />
<None Include="$(BaseSeleniumManagerPath)\windows\selenium-manager.exe" Pack="true" PackagePath="runtimes\win\native\" Visible="false" CopyToOutputDirectory="PreserveNewest" Link="runtimes\win\native\selenium-manager.exe" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\..\common\images\selenium_logo_small.png" Pack="true" PackagePath="logo.png" Visible="false" />
</ItemGroup>

<Target Name="GenerateAtoms" BeforeTargets="BeforeBuild">
<Exec Command="bazel build //javascript/webdriver/atoms:get-attribute.js //javascript/atoms/fragments:is-displayed.js //javascript/atoms/fragments:find-elements.js" WorkingDirectory="../../.." />

Expand Down Expand Up @@ -114,4 +114,4 @@
</ItemGroup>
</Target>

</Project>
</Project>
10 changes: 5 additions & 5 deletions dotnet/src/webdriver/Selenium.WebDriver.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@
<file src="lib/net8.0/WebDriver.pdb" target="lib/net8.0/WebDriver.pdb" />
<file src="lib/net8.0/WebDriver.xml" target="lib/net8.0/WebDriver.xml" />

<file src="build/Selenium.WebDriver.targets" target="build/Selenium.WebDriver.targets"/>
<file src="buildTransitive/Selenium.WebDriver.targets" target="buildTransitive/Selenium.WebDriver.targets"/>
<file src="build/netstandard2.0/Selenium.WebDriver.targets" target="build/netstandard2.0/Selenium.WebDriver.targets"/>
<file src="buildTransitive/netstandard2.0/Selenium.WebDriver.targets" target="buildTransitive/netstandard2.0/Selenium.WebDriver.targets"/>

<file src="manager/linux/selenium-manager" target="manager/linux/selenium-manager" />
<file src="manager/macos/selenium-manager" target="manager/macos/selenium-manager" />
<file src="manager/windows/selenium-manager.exe" target="manager/windows/selenium-manager.exe" />
<file src="manager/linux/selenium-manager" target="runtimes/linux/native/selenium-manager" />
<file src="manager/macos/selenium-manager" target="runtimes/osx/native/selenium-manager" />
<file src="manager/windows/selenium-manager.exe" target="runtimes/win/native/selenium-manager.exe" />

<file src="icon.png" />
<file src="README.md" />
Expand Down
146 changes: 105 additions & 41 deletions dotnet/src/webdriver/SeleniumManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
Expand All @@ -41,56 +42,120 @@ public static class SeleniumManager

private static readonly ILogger _logger = Log.GetLogger(typeof(SeleniumManager));

// This logic to find Selenium Manager binary is complex and strange.
// As soon as Selenium Manager will be real native library (dll ,so, dynlib),
// we will be able to use it directly from the .NET bindings, and this logic will be removed.
private static readonly Lazy<string> _lazyBinaryFullPath = new(() =>
{
string? binaryFullPath = Environment.GetEnvironmentVariable("SE_MANAGER_PATH");
if (binaryFullPath == null)
{
SupportedPlatform? platform = null;

#if NET8_0_OR_GREATER
if (OperatingSystem.IsWindows())
{
platform = SupportedPlatform.Windows;
}
else if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD())
{
platform = SupportedPlatform.Linux;
}
else if (OperatingSystem.IsMacOS() || OperatingSystem.IsMacCatalyst())
if (binaryFullPath is not null)
{
if (!File.Exists(binaryFullPath))
{
platform = SupportedPlatform.MacOS;
throw new FileNotFoundException($"Unable to locate provided Selenium Manager binary at '{binaryFullPath}'.");
}

return binaryFullPath;
}

SupportedPlatform? platform = null;

#if NET8_0_OR_GREATER
if (OperatingSystem.IsWindows())
{
platform = SupportedPlatform.Windows;
}
else if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD())
{
platform = SupportedPlatform.Linux;
}
else if (OperatingSystem.IsMacOS() || OperatingSystem.IsMacCatalyst())
{
platform = SupportedPlatform.MacOS;
}
#else
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
platform = SupportedPlatform.Windows;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
platform = SupportedPlatform.Linux;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
platform = SupportedPlatform.MacOS;
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
platform = SupportedPlatform.Windows;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
platform = SupportedPlatform.Linux;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
platform = SupportedPlatform.MacOS;
}
#endif

var currentDirectory = AppContext.BaseDirectory;
var seleniumManagerFileName = platform switch
{
SupportedPlatform.Windows => "selenium-manager.exe",
SupportedPlatform.Linux => "selenium-manager",
SupportedPlatform.MacOS => "selenium-manager",
_ => throw new PlatformNotSupportedException(
$"Selenium Manager doesn't support your runtime platform: {RuntimeInformation.OSDescription}"),
};

var baseDirectory = AppContext.BaseDirectory;

binaryFullPath = platform switch
List<string> probingPaths = [];

if (baseDirectory is not null)
{
probingPaths.Add(Path.Combine(baseDirectory, seleniumManagerFileName));

switch (platform)
{
SupportedPlatform.Windows => Path.Combine(currentDirectory, "selenium-manager", "windows", "selenium-manager.exe"),
SupportedPlatform.Linux => Path.Combine(currentDirectory, "selenium-manager", "linux", "selenium-manager"),
SupportedPlatform.MacOS => Path.Combine(currentDirectory, "selenium-manager", "macos", "selenium-manager"),
_ => throw new PlatformNotSupportedException(
$"Selenium Manager doesn't support your runtime platform: {RuntimeInformation.OSDescription}"),
};
case SupportedPlatform.Windows:
probingPaths.Add(Path.Combine(baseDirectory, "runtimes", "win", "native", seleniumManagerFileName));
break;
case SupportedPlatform.Linux:
probingPaths.Add(Path.Combine(baseDirectory, "runtimes", "linux", "native", seleniumManagerFileName));
break;
case SupportedPlatform.MacOS:
probingPaths.Add(Path.Combine(baseDirectory, "runtimes", "osx", "native", seleniumManagerFileName));
break;
}
}

if (!File.Exists(binaryFullPath))
// Supporting .NET5+ applications deployed as bundled applications (single file or AOT).
// In this case bootstrapper extracts the native libraries into a temporary directory.
// Most interesting build properties: "IncludeNativeLibrariesForSelfExtract" and "IncludeAllContentForSelfExtract".
var nativeDllSearchDirectories = AppContext.GetData("NATIVE_DLL_SEARCH_DIRECTORIES")?.ToString();

if (nativeDllSearchDirectories is not null)
{
throw new WebDriverException($"Unable to locate or obtain Selenium Manager binary at {binaryFullPath}");
probingPaths.AddRange(nativeDllSearchDirectories.Split(new char[] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries).Select(path => Path.Combine(path, seleniumManagerFileName)));
}

// Covering the case when the application is hosted by another application, most likely
// we can find Selenium Manager in the assembly location, because "AppContext.BaseDirectory"
// might return the path of the host application.
var assemblyDirectory = Path.GetDirectoryName(typeof(SeleniumManager).Assembly.Location);

if (assemblyDirectory is not null)
{
probingPaths.Add(Path.Combine(assemblyDirectory, seleniumManagerFileName));
}

probingPaths = [.. probingPaths.Distinct()];

binaryFullPath = probingPaths.FirstOrDefault(File.Exists);

if (binaryFullPath is null)
{
var messageBuilder = new StringBuilder();
messageBuilder.AppendFormat("Selenium Manager binary '{0}' was not found in the following paths:", seleniumManagerFileName);

foreach (var probingPath in probingPaths)
{
messageBuilder.AppendLine();
messageBuilder.AppendFormat(" - {0}", probingPath);
}

throw new FileNotFoundException(messageBuilder.ToString());
}

return binaryFullPath;
Expand All @@ -113,7 +178,7 @@ public static Dictionary<string, string> BinaryPaths(string arguments)
argsBuilder.Append(" --debug");
}

var smCommandResult = RunCommand(_lazyBinaryFullPath.Value, argsBuilder.ToString());
var smCommandResult = RunCommand(argsBuilder.ToString());
Dictionary<string, string> binaryPaths = new()
{
{ BrowserPathKey, smCommandResult.BrowserPath },
Expand All @@ -132,12 +197,11 @@ public static Dictionary<string, string> BinaryPaths(string arguments)
/// <summary>
/// Executes a process with the given arguments.
/// </summary>
/// <param name="fileName">The path to the Selenium Manager.</param>
/// <param name="arguments">The switches to be used by Selenium Manager.</param>
/// <returns>
/// the standard output of the execution.
/// </returns>
private static ResultResponse RunCommand(string fileName, string arguments)
private static ResultResponse RunCommand(string arguments)
{
Process process = new Process();
process.StartInfo.FileName = _lazyBinaryFullPath.Value;
Expand Down Expand Up @@ -171,7 +235,7 @@ private static ResultResponse RunCommand(string fileName, string arguments)
{
// We do not log any warnings coming from Selenium Manager like the other bindings, as we don't have any logging in the .NET bindings

var exceptionMessageBuilder = new StringBuilder($"Selenium Manager process exited abnormally with {process.ExitCode} code: {fileName} {arguments}");
var exceptionMessageBuilder = new StringBuilder($"Selenium Manager process exited abnormally with {process.ExitCode} code: {process.StartInfo.FileName} {arguments}");

if (!string.IsNullOrWhiteSpace(errorOutputBuilder.ToString()))
{
Expand All @@ -194,7 +258,7 @@ private static ResultResponse RunCommand(string fileName, string arguments)
}
catch (Exception ex)
{
throw new WebDriverException($"Error starting process: {fileName} {arguments}", ex);
throw new WebDriverException($"Error starting process: {process.StartInfo.FileName} {arguments}", ex);
}
finally
{
Expand Down
5 changes: 3 additions & 2 deletions dotnet/src/webdriver/assets/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
exports_files([
"README.md",
"Selenium.WebDriver.targets",
"nuget/README.md",
"nuget/build/netstandard2.0/Selenium.WebDriver.targets",
"nuget/buildTransitive/netstandard2.0/Selenium.WebDriver.targets",
])
31 changes: 0 additions & 31 deletions dotnet/src/webdriver/assets/Selenium.WebDriver.targets

This file was deleted.

Loading