Skip to content
Merged
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
40 changes: 0 additions & 40 deletions .appveyor.yml

This file was deleted.

101 changes: 101 additions & 0 deletions .github/workflows/dotnetCi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: .NET CI

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]

jobs:

# Summary:
#
# * Installs and configures the environment
# * Runs all .NET and JS tests
# * In Debug configuration (.NET tests)
# * WebDriver-based tests use a locally-running Chrome browser ONLY
# * Packages test results as build artifacts
# * Builds & packs the solution in Release configuration
# * Uploads the Release config packages as build artifacts

build_test_and_pack:
name: Build, test & package
runs-on: ubuntu-24.04
timeout-minutes: 30

env:
VersionSuffix: ci.${{ github.run_number }}
Configuration: Debug
DotnetVersion: 8.0.x
DISPLAY: :99

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

# Install build dependencies

- name: Add .NET global tools location to PATH
run: echo "$HOME/.dotnet/tools" >> "$GITHUB_PATH"
- name: Install .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DotnetVersion }}
- name: Install DocFX
run: dotnet tool install --global docfx
# See https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md
- name: Disable AppArmor restrictions so Chrome may run
run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns
- name: Start an Xvfb display so Chrome may run
run: Xvfb -ac $DISPLAY -screen 0 1280x1024x16 &

# Environment setup pre-build

- name: Restore .NET packages
run: dotnet restore

# Build and test the solution

- name: Build the solution
run: dotnet build -c ${{ env.Configuration }}
- name: Run .NET tests
id: dotnet_tests
run: dotnet test
continue-on-error: true

# Post-test tasks (artifacts, overall status)

- name: Gracefully stop Xvfb
run: killall Xvfb
continue-on-error: true
- name: Upload .NET test results artifacts
uses: actions/upload-artifact@v4
with:
name: NUnit test results
path: Tests/*.Tests/**/TestResults.xml
- name: Fail the build if any test failures
if: steps.dotnet_tests.outcome == 'failure'
run: |
echo "Failing the build due to test failures"
exit 1

# Build the apps in release mode and publish artifacts

- name: Clean the solution ahead of building in release config
run: dotnet clean
- name: Build, in release configuration
run: dotnet pack -p:VersionSuffix=$VersionSuffix -o packages
- name: Upload build result artifacts
uses: actions/upload-artifact@v4
with:
name: Build results (NuGet)
path: packages/*.nupkg
- name: Build docs website
run: docfx CSF.Extensions.WebDriver.Docs/docfx.json
- name: Upload docs website artifact
uses: actions/upload-artifact@v4
with:
name: Docs website
path: docs/**/*
8 changes: 7 additions & 1 deletion CSF.Extensions.WebDriver.Docs/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ Do not forget that you may provide configuration from multiple sources; for exam

[`GetDefaultWebDriver()`]: xref:CSF.Extensions.WebDriver.IGetsWebDriver.GetDefaultWebDriver(System.Action{OpenQA.Selenium.DriverOptions})

### Configuration reference

The available configuration options/syntax is documented in the classes [`WebDriverCreationOptionsCollection`] and [`WebDriverCreationOptions`].

[`WebDriverCreationOptionsCollection`]: xref:CSF.Extensions.WebDriver.Factories.WebDriverCreationOptionsCollection
[`WebDriverCreationOptions`]: xref:CSF.Extensions.WebDriver.Factories.WebDriverCreationOptions

## 3. Inject and use the services

Use dependency injection to inject an [`IGetsWebDriver`].
Expand All @@ -82,4 +89,3 @@ This service offers the same functionality except that the consumer is responsib

[`IGetsWebDriver`]: xref:CSF.Extensions.WebDriver.IGetsWebDriver
[`ICreatesWebDriverFromOptions`]: xref:CSF.Extensions.WebDriver.Factories.ICreatesWebDriverFromOptions
[`WebDriverCreationOptions`]: xref:CSF.Extensions.WebDriver.Factories.WebDriverCreationOptions
6 changes: 3 additions & 3 deletions CSF.Extensions.WebDriver.Docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ This is broadly organised into three features:
* A mechanism to ['mark WebDrivers up' with information about their quirks] which affect that browser/WebDriver/version combination

[Selenium WebDriver]: https://www.selenium.dev/documentation/webdriver/
[universal WebDriver factory]: Docs/index.md
[reliably identify WebDriver instances]: Docs/DriverIdentification.md
['mark WebDrivers up' with information about their quirks]: Docs/Quirks.md
[universal WebDriver factory]: docs/index.md
[reliably identify WebDriver instances]: docs/DriverIdentification.md
['mark WebDrivers up' with information about their quirks]: docs/Quirks.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,15 @@
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<!-- Floating version should keep ChromeDriver up to date with the browser on the OS. See #47 for more info. -->
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="*" Condition="'$(CI_LINUX)' != 'true'" />
<!-- AppVeyor Linux builds use a fixed Chrome version, this driver version must match it; note that
this might change over time (an will need to be manually kept in-sync) as they upgrade their CI images -->
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="127.0.6533.9900" Condition="'$(CI_LINUX)' == 'true'" />
<PackageReference Include="Selenium.WebDriver" Version="4.15.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CSF.Extensions.WebDriver\CSF.Extensions.WebDriver.csproj" />
</ItemGroup>

<ItemGroup>
<Content Include="appsettings.WebDriverFactoryIntegrationTests.json">
<Content Include="appsettings.*.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@ public void GetKnownDriverAndOptionsTypesShouldContainAllOfTheExpectedDrivers(Se
Warn.Unless(supportedDriverNames,
Is.SupersetOf(expectedDriverNames),
"The collection of supported drivers no longer contains all of expected drivers; breaking change in Selenium?");
Assert.Pass("This isn't a true test, but if there has been a warning emitted then perhaps Selenium has introduced a change in built-in browser support.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,9 @@ static async Task<WebDriverCreationOptionsCollection> GetOptionsAsync(IGetsWebDr
{
var options = new WebDriverCreationOptionsCollection();
var config = await GetConfigurationAsync(json);
var sut = new WebDriverCreationConfigureOptions(typeProvider, config, logger ?? Mock.Of<ILogger<WebDriverCreationConfigureOptions>>());
var sut = new WebDriverCreationConfigureOptions(new WebDriverConfigurationItemParser(typeProvider, Mock.Of<ILogger<WebDriverConfigurationItemParser>>()),
config,
logger ?? Mock.Of<ILogger<WebDriverCreationConfigureOptions>>());
sut.Configure(options);
return options;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ public void GetDefaultWebDriverShouldReturnADriverProxyWithIdentification()
Assert.That(() => driver.WebDriver.GetBrowserId(), Is.Not.Null);
}

[Test]
public void DriverTypeNorOptionsTypeShouldBeMandatoryIfACustomFactoryTypeIsSpecified()
{
var services = GetServiceProvider(o => o.SelectedConfiguration = "OmittedDriverAndOptionsType");
var driverFactory = services.GetRequiredService<IGetsWebDriver>();
using var driver = driverFactory.GetDefaultWebDriver();
Assert.That(() => driver.WebDriver.GetBrowserId(), Is.Not.Null);
}

IServiceProvider GetServiceProvider(Action<WebDriverCreationOptionsCollection>? configureOptions = null)
{
var services = new ServiceCollection();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,6 @@ public class FakeWebDriver : IWebDriver

public class FakeOptions : DriverOptions
{
[Obsolete("Obsolete because base class is obsolete")]
public override void AddAdditionalCapability(string capabilityName, object capabilityValue) => throw new NotImplementedException();

public override ICapabilities ToCapabilities() => throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"__Description__": "This configuration file is used by WebDriverFactoryIntegrationTests. It describes RemoteWebDriver configs which will raise a crash errors because of unsupported URL schemes. They are useful because they prove that Selenium's functionality is being exercised.",
"__Description__": "This configuration file is used by WebDriverFactoryIntegrationTests. It describes a number of WebDriver config scenarios which will be tested.",
"WebDriverFactory": {
"DriverConfigurations": {
"DefaultFake": {
Expand All @@ -17,6 +17,9 @@
"DriverType": "RemoteWebDriver",
"OptionsType": "ChromeOptions",
"GridUrl": "nonsense://127.0.0.1/no-http-request/should-be-made"
},
"OmittedDriverAndOptionsType": {
"DriverFactoryType": "CSF.Extensions.WebDriver.Factories.WebDriverFactoryIntegrationTests+FakeWebDriverFactory, CSF.Extensions.WebDriver.Tests"
}
},
"SelectedConfiguration": "DefaultInvalid"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using Microsoft.Extensions.Configuration;

namespace CSF.Extensions.WebDriver.Factories
{
/// <summary>
/// A service which reads an <see cref="IConfigurationSection"/> which describes a creation-strategy for a WebDriver, and gets an
/// instance of <see cref="WebDriverCreationOptions"/>.
/// </summary>
public interface IParsesSingleWebDriverConfigurationSection
{
/// <summary>
/// Gets an instance of <see cref="WebDriverCreationOptions"/> from the specified <see cref="IConfigurationSection"/>.
/// </summary>
/// <remarks>
/// <para>
/// Note that if the configuration is invalid, then this method will return a <see langword="null"/> instance of
/// <see cref="WebDriverCreationOptions"/>.
/// </para>
/// </remarks>
/// <param name="configuration">The configuration section which describes the configuration of a WebDriver.</param>
/// <returns>A strongly-typed options object, or a <see langword="null"/> reference indicating an invalid configuration.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="configuration"/> is <see langword="null"/>.</exception>
WebDriverCreationOptions GetDriverConfiguration(IConfigurationSection configuration);
}
}

Loading
Loading