mirror of
https://github.com/DuendeSoftware/products
synced 2026-05-24 09:28:24 +00:00
Migrate all test projects to xUnit v3 and Microsoft Test Platform
Major Changes: - Upgraded from xunit.core v2 to xunit.v3 (3.1.0) - Replaced Microsoft.NET.Test.Sdk with Microsoft.Testing.Platform.MSBuild (1.8.4) - Updated test projects to use <OutputType>Exe</OutputType> (required for xUnit v3) Package Updates: - Replaced Verify.Xunit with Verify.XunitV3 (31.0.0) - Replaced Meziantou.Extensions.Logging.Xunit with MartinCostello.Logging.XUnit.v3 (0.6.0) - Replaced Serilog.Sinks.XUnit with Serilog.Sinks.XUnit3 (1.1.0) - Removed Xunit.SkippableFact (xUnit v3 has built-in skipping) - Removed Microsoft.SourceLink.GitHub from test projects - Updated Serilog to 4.3.0 (required by Serilog.Sinks.XUnit3) Code Changes: - Updated IAsyncLifetime implementations (Task → ValueTask, Task.CompletedTask → default) - Removed 'using Xunit.Abstractions;' from 37 files - Replaced Skip.If() with Assert.Skip() for conditional test skipping - Replaced [SkippableFact] with [Fact] and [SkippableTheory] with [Theory] - Updated BeforeAfterTestAttribute to IBeforeAfterTestAttribute in xUnit v3 - Fixed TheoryData syntax for xUnit v3 (collection expressions) Playwright Integration: - Removed Retries folder (unused xUnit v2 extensibility code) - Replaced Microsoft.Playwright.Xunit with Microsoft.Playwright - Removed PageTest base class, implemented Playwright directly - Added IAsyncLifetime implementation with manual browser initialization
This commit is contained in:
parent
0f8bbf0611
commit
0afe76f186
59 changed files with 136 additions and 368 deletions
|
|
@ -39,7 +39,6 @@
|
|||
<PackageVersion Include="Aspire.Hosting.SqlServer" Version="9.5.0" />
|
||||
<PackageVersion Include="BenchmarkDotNet" Version="0.15.0" />
|
||||
<PackageVersion Include="BullsEye" Version="5.0.0" />
|
||||
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
|
||||
<!-- Added aspire transitive package to resolve package vulnerability -->
|
||||
<PackageVersion Include="KubernetesClient" Version="17.0.14" />
|
||||
<PackageVersion Include="Duende.AccessTokenManagement" Version="3.2.0" Condition="'$(IsBffProject)' == 'true'" />
|
||||
|
|
@ -54,7 +53,7 @@
|
|||
<PackageVersion Include="Duende.IdentityServer" Version="7.1.0" />
|
||||
<PackageVersion Include="Duende.Private.Licensing" Version="1.0.0" />
|
||||
<PackageVersion Include="IdentityModel.AspNetCore.OAuth2Introspection" Version="6.2.0" />
|
||||
<PackageVersion Include="Meziantou.Extensions.Logging.Xunit" Version="1.0.8" />
|
||||
<PackageVersion Include="MartinCostello.Logging.XUnit.v3" Version="0.6.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Certificate" Version="$(AuthenticationCertificateVersion)" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="$(FrameworkVersion)" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="$(FrameworkVersion)" />
|
||||
|
|
@ -98,10 +97,10 @@
|
|||
<PackageVersion Include="Microsoft.IdentityModel.Logging" Version="$(IdentityModelVersion)" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="$(IdentityModelVersion)" />
|
||||
<PackageVersion Include="Microsoft.Net.Http.Headers" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||
<PackageVersion Include="Microsoft.NETCore.Jit" Version="2.0.8" />
|
||||
<PackageVersion Include="Microsoft.Playwright.Xunit" Version="1.50.0" />
|
||||
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Playwright" Version="1.55.0" />
|
||||
<PackageVersion Include="Microsoft.Playwright.Xunit.v3" Version="1.55.0" />
|
||||
<PackageVersion Include="Microsoft.Testing.Platform.MSBuild" Version="1.8.4" />
|
||||
<PackageVersion Include="MinVer" Version="6.0.0" />
|
||||
<PackageVersion Include="NBomber" Version="6.0.2" />
|
||||
<PackageVersion Include="NBomber.Http" Version="6.0.2" />
|
||||
|
|
@ -117,13 +116,13 @@
|
|||
<PackageVersion Include="OpenTelemetry" Version="1.12.0" />
|
||||
<PackageVersion Include="PublicApiGenerator" Version="11.1.0" />
|
||||
<PackageVersion Include="RichardSzalay.MockHttp" Version="7.0.0" />
|
||||
<PackageVersion Include="Serilog" Version="4.2.0" />
|
||||
<PackageVersion Include="Serilog" Version="4.3.0" />
|
||||
<PackageVersion Include="Serilog.AspNetCore" Version="8.0.3" />
|
||||
<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.OpenTelemetry" Version="4.2.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.TextWriter" Version="3.0.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.XUnit" Version="3.0.19" />
|
||||
<PackageVersion Include="Serilog.Sinks.XUnit3" Version="1.1.0" />
|
||||
<PackageVersion Include="Serilog.Extensions.Logging" Version="9.0.2" />
|
||||
<PackageVersion Include="Shouldly" Version="4.2.1" />
|
||||
<PackageVersion Include="SimpleExec" Version="12.0.0" />
|
||||
|
|
@ -131,10 +130,11 @@
|
|||
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageVersion Include="System.Text.Json" Version="$(SystemTextJsonVersion)" />
|
||||
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
<PackageVersion Include="xunit.core" Version="2.9.3" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
<PackageVersion Include="Xunit.SkippableFact" Version="1.5.23" />
|
||||
<PackageVersion Include="Verify.Xunit" Version="28.9.0" />
|
||||
<PackageVersion Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageVersion Include="xunit.v3" Version="3.1.0" />
|
||||
<PackageVersion Include="xunit.v3.core" Version="3.1.0" />
|
||||
<PackageVersion Include="xunit.v3.extensibility.core" Version="3.1.0" />
|
||||
<PackageVersion Include="Verify.XunitV3" Version="31.0.0" />
|
||||
<PackageVersion Include="Vogen" Version="7.0.3" />
|
||||
<PackageVersion Include="Yarp.ReverseProxy" Version="2.1.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" VersionOverride="9.0.4" />
|
||||
<PackageReference Include="Meziantou.Extensions.Logging.Xunit" />
|
||||
<PackageReference Include="MartinCostello.Logging.XUnit.v3" />
|
||||
<PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<PackageReference Include="NSubstitute" />
|
||||
<PackageReference Include="RichardSzalay.MockHttp" />
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ using Microsoft.AspNetCore.Builder;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.AspNetCore.Authentication.JwtBearer;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.AspNetCore.TestFramework;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ using Microsoft.AspNetCore.Builder;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using RichardSzalay.MockHttp;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.AspNetCore.TestFramework;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@
|
|||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Security.Claims;
|
||||
using Meziantou.Extensions.Logging.Xunit;
|
||||
using MartinCostello.Logging.XUnit;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.AspNetCore.TestFramework;
|
||||
|
||||
|
|
@ -104,7 +103,7 @@ public class GenericHost
|
|||
private void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// This adds log messages to the output of our tests when they fail.
|
||||
// See https://www.meziantou.net/how-to-view-logs-from-ilogger-in-xunitdotnet.htm
|
||||
// See https://github.com/martincostello/xunit-logging
|
||||
services.AddLogging(options =>
|
||||
{
|
||||
// If you need different log output to understand a test failure, configure it here
|
||||
|
|
@ -113,10 +112,7 @@ public class GenericHost
|
|||
options.AddFilter("Duende.IdentityServer.License", LogLevel.Error);
|
||||
options.AddFilter("Duende.IdentityServer.Startup", LogLevel.Error);
|
||||
|
||||
options.AddProvider(new XUnitLoggerProvider(_testOutputHelper, new XUnitLoggerOptions
|
||||
{
|
||||
IncludeCategory = true,
|
||||
}));
|
||||
options.AddXUnit(_testOutputHelper);
|
||||
});
|
||||
|
||||
OnConfigureServices(services);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ using Microsoft.AspNetCore.Builder;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.IdentityModel.JsonWebTokens;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.AspNetCore.TestFramework;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
<PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<PackageReference Include="NSubstitute" />
|
||||
<PackageReference Include="PublicApiGenerator" />
|
||||
<PackageReference Include="Verify.Xunit" />
|
||||
<PackageReference Include="Verify.XunitV3" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,28 +3,16 @@
|
|||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NSubstitute" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
|
||||
<PackageReference Include="PublicApiGenerator" />
|
||||
<PackageReference Include="Verify.Xunit" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
|
||||
<PackageReference Include="Verify.XunitV3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -32,4 +20,8 @@
|
|||
<ProjectReference Include="..\Bff.Tests\Bff.Tests.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using Duende.Bff;
|
|||
using Duende.Bff.Tests.TestHosts;
|
||||
using Duende.IdentityServer.Models;
|
||||
using Duende.IdentityServer.Services;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Bff.Blazor.UnitTests;
|
||||
|
||||
|
|
@ -70,7 +69,7 @@ public class BffBlazorTests : OutputWritingTestBase
|
|||
response.StatusCode.ShouldBe(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
public override async Task InitializeAsync()
|
||||
public override async ValueTask InitializeAsync()
|
||||
{
|
||||
await IdentityServerHost.InitializeAsync();
|
||||
await ApiHost.InitializeAsync();
|
||||
|
|
@ -78,7 +77,7 @@ public class BffBlazorTests : OutputWritingTestBase
|
|||
await base.InitializeAsync();
|
||||
}
|
||||
|
||||
public override async Task DisposeAsync()
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
await ApiHost.DisposeAsync();
|
||||
await BffHost.DisposeAsync();
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
|
||||
<PackageReference Include="PublicApiGenerator" />
|
||||
<PackageReference Include="Verify.Xunit" />
|
||||
<PackageReference Include="Verify.XunitV3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Bff.EntityFramework\Bff.EntityFramework.csproj" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.TestHost" />
|
||||
<PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<PackageReference Include="PublicApiGenerator" />
|
||||
<PackageReference Include="Verify.Xunit" />
|
||||
<PackageReference Include="Verify.XunitV3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ using Duende.Bff.Tests.TestFramework;
|
|||
using Duende.Bff.Tests.TestHosts;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.Endpoints;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using System.Net.Http.Json;
|
|||
using Duende.Bff.Tests.TestFramework;
|
||||
using Duende.Bff.Tests.TestHosts;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.Endpoints;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using System.Net;
|
||||
using Duende.Bff.Tests.TestHosts;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.Endpoints.Management;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using System.Net;
|
||||
using Duende.Bff.Tests.TestHosts;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.Endpoints.Management;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using System.Net;
|
||||
using Duende.Bff.Tests.TestHosts;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.Endpoints.Management;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System.Net;
|
|||
using Duende.Bff.Tests.TestHosts;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.Endpoints.Management;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
using Duende.Bff.Tests.TestHosts;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.Endpoints.Management;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using System.Net.Http.Json;
|
|||
using System.Text.Json;
|
||||
using Duende.Bff.Tests.TestFramework;
|
||||
using Duende.Bff.Tests.TestHosts;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.Endpoints;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using System.Net;
|
||||
using Duende.Bff.Tests.TestFramework;
|
||||
using Duende.Bff.Tests.TestHosts;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.Endpoints;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using System.Net;
|
||||
using Duende.Bff.Tests.TestFramework;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using System.Text.Json;
|
||||
using Duende.Bff.Tests.TestFramework;
|
||||
using Duende.Bff.Tests.TestHosts;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.Headers;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using System.Text.Json;
|
||||
using Duende.Bff.Tests.TestFramework;
|
||||
using Duende.Bff.Tests.TestHosts;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.Headers;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using System.Text.Json;
|
||||
using Duende.Bff.Tests.TestFramework;
|
||||
using Duende.Bff.Tests.TestHosts;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.Headers;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Builder;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using Duende.Bff.Tests.TestHosts;
|
|||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Time.Testing;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
|
||||
namespace Duende.Bff.Tests.SessionManagement;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using Duende.Bff.Tests.TestHosts;
|
||||
using Duende.IdentityServer.Stores;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.SessionManagement;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using Duende.Bff.Tests.TestHosts;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.SessionManagement;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ public class GenericHost(WriteTestOutput writeOutput, string baseAddress = "http
|
|||
return _baseAddress + path;
|
||||
}
|
||||
|
||||
public async Task InitializeAsync()
|
||||
public async ValueTask InitializeAsync()
|
||||
{
|
||||
var hostBuilder = new HostBuilder()
|
||||
.ConfigureWebHost(builder =>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using Duende.IdentityServer.Models;
|
|||
using Duende.IdentityServer.Services;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.TestHosts;
|
||||
|
||||
|
|
@ -52,7 +51,7 @@ public class BffIntegrationTestBase : OutputWritingTestBase
|
|||
|
||||
public async Task Login(string sub) => await IdentityServerHost.IssueSessionCookieAsync(new Claim("sub", sub));
|
||||
|
||||
public override async Task InitializeAsync()
|
||||
public override async ValueTask InitializeAsync()
|
||||
{
|
||||
await IdentityServerHost.InitializeAsync();
|
||||
await ApiHost.InitializeAsync();
|
||||
|
|
@ -61,7 +60,7 @@ public class BffIntegrationTestBase : OutputWritingTestBase
|
|||
await base.InitializeAsync();
|
||||
}
|
||||
|
||||
public override async Task DisposeAsync()
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
await ApiHost.DisposeAsync();
|
||||
await BffHost.DisposeAsync();
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// See LICENSE in the project root for license information.
|
||||
|
||||
using System.Text;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.TestHosts;
|
||||
|
||||
|
|
@ -18,9 +17,9 @@ public class OutputWritingTestBase(ITestOutputHelper testOutputHelper) : IAsyncL
|
|||
}
|
||||
}
|
||||
|
||||
public virtual Task InitializeAsync() => Task.CompletedTask;
|
||||
public virtual ValueTask InitializeAsync() => default;
|
||||
|
||||
public virtual Task DisposeAsync()
|
||||
public virtual ValueTask DisposeAsync()
|
||||
{
|
||||
lock (_output)
|
||||
{
|
||||
|
|
@ -28,6 +27,6 @@ public class OutputWritingTestBase(ITestOutputHelper testOutputHelper) : IAsyncL
|
|||
}
|
||||
|
||||
|
||||
return Task.CompletedTask;
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using Duende.IdentityServer.Models;
|
|||
using Duende.IdentityServer.Services;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests.TestHosts;
|
||||
|
||||
|
|
@ -51,7 +50,7 @@ public class YarpBffIntegrationTestBase : OutputWritingTestBase
|
|||
|
||||
public async Task Login(string sub) => await _identityServerHost.IssueSessionCookieAsync(new Claim("sub", sub));
|
||||
|
||||
public override async Task InitializeAsync()
|
||||
public override async ValueTask InitializeAsync()
|
||||
{
|
||||
await _identityServerHost.InitializeAsync();
|
||||
await ApiHost.InitializeAsync();
|
||||
|
|
@ -60,7 +59,7 @@ public class YarpBffIntegrationTestBase : OutputWritingTestBase
|
|||
await base.InitializeAsync();
|
||||
}
|
||||
|
||||
public override async Task DisposeAsync()
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
await _identityServerHost.DisposeAsync();
|
||||
await ApiHost.DisposeAsync();
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using Hosts.ServiceDefaults;
|
||||
using Hosts.Tests.PageModels;
|
||||
using Hosts.Tests.TestInfra;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Hosts.Tests;
|
||||
|
||||
|
|
@ -20,7 +19,7 @@ public class BffBlazorWebAssemblyTests(ITestOutputHelper output, AppHostFixture
|
|||
};
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
[Fact]
|
||||
public async Task Can_login_and_load_local_api()
|
||||
{
|
||||
await Warmup();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using Hosts.ServiceDefaults;
|
||||
using Hosts.Tests.TestInfra;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Hosts.Tests;
|
||||
|
||||
|
|
@ -18,14 +17,14 @@ public class BffTests : IntegrationTestBase
|
|||
_bffClient = new BffClient(CreateHttpClient(AppHostServices.Bff));
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
[Fact]
|
||||
public async Task Can_invoke_home()
|
||||
{
|
||||
var response = await _httpClient.GetAsync("/");
|
||||
response.StatusCode.ShouldBe(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
[Fact]
|
||||
public async Task Can_initiate_login()
|
||||
{
|
||||
|
||||
|
|
@ -39,7 +38,7 @@ public class BffTests : IntegrationTestBase
|
|||
claims.Any().ShouldBeTrue();
|
||||
}
|
||||
|
||||
[SkippableTheory]
|
||||
[Theory]
|
||||
[InlineData("/local/self-contained")]
|
||||
[InlineData("/local/invokes-external-api")]
|
||||
[InlineData("/api/user-token")]
|
||||
|
|
@ -55,7 +54,7 @@ public class BffTests : IntegrationTestBase
|
|||
await _bffClient.InvokeApi(url);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
[Fact]
|
||||
public async Task Can_logout()
|
||||
{
|
||||
await _bffClient.TriggerLogin();
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using Hosts.ServiceDefaults;
|
||||
using Hosts.Tests.PageModels;
|
||||
using Hosts.Tests.TestInfra;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Hosts.Tests;
|
||||
|
||||
|
|
@ -21,7 +20,7 @@ public class BlazorPerComponentTests(ITestOutputHelper output, AppHostFixture fi
|
|||
};
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
[Fact]
|
||||
public async Task Can_load_blazor_webassembly_app()
|
||||
{
|
||||
await Warmup();
|
||||
|
|
|
|||
|
|
@ -13,30 +13,25 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<PackageReference Include="AngleSharp" />
|
||||
<PackageReference Include="Aspire.Hosting.Testing" />
|
||||
<PackageReference Include="Serilog" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" />
|
||||
<PackageReference Include="Serilog.Sinks.TextWriter" />
|
||||
<PackageReference Include="Serilog.Sinks.XUnit" />
|
||||
<PackageReference Include="Serilog.Sinks.XUnit3" />
|
||||
<PackageReference Include="Serilog.AspNetCore" />
|
||||
<PackageReference Include="Aspire.Hosting.Testing" />
|
||||
<PackageReference Include="Xunit.SkippableFact" />
|
||||
<PackageReference Include="Microsoft.Playwright.Xunit" />
|
||||
|
||||
<PackageReference Include="Microsoft.Playwright.Xunit.v3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)' != 'Debug_NCrunch'">
|
||||
|
||||
<ProjectReference Include="..\..\hosts\Hosts.AppHost\Hosts.AppHost.csproj" />
|
||||
<Using Include="Aspire.Hosting.ApplicationModel" />
|
||||
<Using Include="Aspire.Hosting.Testing" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Net" />
|
||||
<Using Include="Aspire.Hosting.ApplicationModel" />
|
||||
<Using Include="Aspire.Hosting.Testing" />
|
||||
<Using Include="Microsoft.Extensions.DependencyInjection" />
|
||||
<Using Include="System.Net" />
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@
|
|||
using System.Reflection;
|
||||
using Hosts.Tests.TestInfra;
|
||||
using Microsoft.Playwright;
|
||||
using Microsoft.Playwright.Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
using Microsoft.Playwright.Xunit.v3;
|
||||
using Xunit.v3;
|
||||
|
||||
namespace Hosts.Tests;
|
||||
|
||||
|
|
@ -31,12 +30,12 @@ public class PlaywrightTestBase : PageTest, IDisposable
|
|||
#if DEBUG_NCRUNCH
|
||||
// Running in NCrunch. NCrunch cannot build the aspire project, so it needs
|
||||
// to be started manually.
|
||||
Skip.If(true, "When running the Host.Tests using NCrunch, you must start the Hosts.AppHost project manually. IE: dotnet run -p bff/samples/Hosts.AppHost. Or start without debugging from the UI. ");
|
||||
Assert.Skip("When running the Host.Tests using NCrunch, you must start the Hosts.AppHost project manually. IE: dotnet run -p bff/samples/Hosts.AppHost. Or start without debugging from the UI. ");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task InitializeAsync()
|
||||
public async ValueTask InitializeAsync()
|
||||
{
|
||||
await base.InitializeAsync();
|
||||
Context.SetDefaultTimeout(10_000);
|
||||
|
|
@ -49,7 +48,7 @@ public class PlaywrightTestBase : PageTest, IDisposable
|
|||
});
|
||||
}
|
||||
|
||||
public override async Task DisposeAsync()
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Environment.CurrentDirectory;
|
||||
// if path ends with /bin/{build configuration}/{dotnetversion}, then strip that from the path.
|
||||
|
|
@ -106,18 +105,17 @@ public class PlaywrightTestBase : PageTest, IDisposable
|
|||
public HttpClient CreateHttpClient(string clientName) => Fixture.CreateHttpClient(clientName);
|
||||
}
|
||||
|
||||
public class WithTestNameAttribute : BeforeAfterTestAttribute
|
||||
public class WithTestNameAttribute : Attribute, IBeforeAfterTestAttribute
|
||||
{
|
||||
public static string CurrentTestName = string.Empty;
|
||||
public static string CurrentClassName = string.Empty;
|
||||
|
||||
public override void Before(MethodInfo methodInfo)
|
||||
public void Before(MethodInfo methodInfo, IXunitTest _)
|
||||
{
|
||||
CurrentTestName = methodInfo.Name;
|
||||
CurrentClassName = methodInfo.DeclaringType!.Name;
|
||||
}
|
||||
|
||||
public override void After(MethodInfo methodInfo)
|
||||
{
|
||||
}
|
||||
public void After(MethodInfo methodInfo, IXunitTest _)
|
||||
{ }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public class AppHostFixture : IAsyncLifetime
|
|||
public bool UsingAlreadyRunningInstance { get; private set; }
|
||||
public string StartupLogs => _startupLogs.ToString() ?? string.Empty;
|
||||
|
||||
public async Task InitializeAsync()
|
||||
public async ValueTask InitializeAsync()
|
||||
{
|
||||
using var startupLogWriter = ConnectLogger(s => _startupLogs.Write(s));
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ public class AppHostFixture : IAsyncLifetime
|
|||
}
|
||||
|
||||
|
||||
public async Task DisposeAsync()
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_app != null)
|
||||
{
|
||||
|
|
@ -272,7 +272,7 @@ public class AppHostFixture : IAsyncLifetime
|
|||
|
||||
return _app.GetEndpoint(clientName);
|
||||
#else
|
||||
Skip.If(true, "When running the Host.Tests using NCrunch, you must start the Hosts.AppHost project manually. IE: dotnet run -p bff/samples/Hosts.AppHost. Or start without debugging from the UI. ");
|
||||
Assert.Skip("When running the Host.Tests using NCrunch, you must start the Hosts.AppHost project manually. IE: dotnet run -p bff/samples/Hosts.AppHost. Or start without debugging from the UI. ");
|
||||
return null!;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright (c) Duende Software. All rights reserved.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Hosts.Tests.TestInfra;
|
||||
|
||||
|
|
@ -24,7 +23,7 @@ public class IntegrationTestBase : IDisposable
|
|||
#if DEBUG_NCRUNCH
|
||||
// Running in NCrunch. NCrunch cannot build the aspire project, so it needs
|
||||
// to be started manually.
|
||||
Skip.If(true, "When running the Host.Tests using NCrunch, you must start the Hosts.AppHost project manually. IE: dotnet run -p bff/samples/Hosts.AppHost. Or start without debugging from the UI. ");
|
||||
Assert.Skip("When running the Host.Tests using NCrunch, you must start the Hosts.AppHost project manually. IE: dotnet run -p bff/samples/Hosts.AppHost. Or start without debugging from the UI. ");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,11 +12,9 @@
|
|||
<PackageReference Include="Serilog" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" />
|
||||
<PackageReference Include="Serilog.Sinks.TextWriter" />
|
||||
<PackageReference Include="Serilog.Sinks.XUnit" />
|
||||
<PackageReference Include="Serilog.Sinks.XUnit3" />
|
||||
<PackageReference Include="Serilog.AspNetCore" />
|
||||
<PackageReference Include="Aspire.Hosting.Testing" />
|
||||
<PackageReference Include="Xunit.SkippableFact" />
|
||||
<PackageReference Include="Microsoft.Playwright.Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using Duende.IdentityServer.EndToEndTests.TestInfra;
|
|||
using Duende.Xunit.Playwright;
|
||||
using Projects;
|
||||
using ServiceDefaults;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.IdentityServer.EndToEndTests;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using Duende.Xunit.Playwright;
|
||||
using Projects;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.IdentityServer.EndToEndTests.TestInfra;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// See LICENSE in the project root for license information.
|
||||
|
||||
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
|
@ -50,5 +51,6 @@ public class IntegrationTest<TClass, TDbContext, TStoreOption> : IClassFixture<D
|
|||
}
|
||||
}
|
||||
|
||||
protected IntegrationTest(DatabaseProviderFixture<TDbContext> fixture) => fixture.Options = TestDatabaseProviders.ToList<DbContextOptions<TDbContext>>();
|
||||
protected IntegrationTest(DatabaseProviderFixture<TDbContext> fixture)
|
||||
=> fixture.Options = TestDatabaseProviders.Select(row => row.Data).ToList();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ public class ClientStoreTests : IntegrationTest<ClientStoreTests, ConfigurationD
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new TestTimeoutException(timeout);
|
||||
TestTimeoutException.ForTimedOutTest(timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public class DynamicProvidersTests
|
|||
await ctx.SignOutAsync();
|
||||
});
|
||||
};
|
||||
_idp1.InitializeAsync().Wait();
|
||||
_idp1.InitializeAsync().AsTask().Wait();
|
||||
|
||||
_idp2 = new GenericHost("https://idp2");
|
||||
_idp2.OnConfigureServices += services =>
|
||||
|
|
@ -133,9 +133,7 @@ public class DynamicProvidersTests
|
|||
await ctx.SignInAsync(new IdentityServerUser("2").CreatePrincipal());
|
||||
});
|
||||
};
|
||||
_idp2.InitializeAsync().Wait();
|
||||
|
||||
|
||||
_idp2.InitializeAsync().AsTask().Wait();
|
||||
|
||||
_host = new GenericHost("https://server");
|
||||
_host.OnConfigureServices += services =>
|
||||
|
|
@ -403,21 +401,15 @@ public class DynamicProvidersTests
|
|||
public override string ToString() => Name;
|
||||
}
|
||||
|
||||
private class DynamicProviderConfigurationData : TheoryData<DynamicProviderTestScenario>
|
||||
private sealed class DynamicProviderConfigurationData : TheoryData<DynamicProviderTestScenario>
|
||||
{
|
||||
public DynamicProviderConfigurationData()
|
||||
{
|
||||
Add(new("Default PathPrefix", _ => { }));
|
||||
Add(new("PathPrefix Callback",
|
||||
options => options.DynamicProviders.PathMatchingCallback = ctx =>
|
||||
{
|
||||
if (ctx.Request.Path.StartsWithSegments("/federation/idp1", StringComparison.InvariantCulture))
|
||||
{
|
||||
return Task.FromResult("idp1");
|
||||
}
|
||||
|
||||
return Task.FromResult((string)null);
|
||||
}));
|
||||
Add(new DynamicProviderTestScenario("Default PathPrefix", _ => { }));
|
||||
Add(new DynamicProviderTestScenario("PathPrefix Callback",
|
||||
options => options.DynamicProviders.PathMatchingCallback = ctx => ctx.Request.Path.StartsWithSegments("/federation/idp1", StringComparison.InvariantCulture)
|
||||
? Task.FromResult("idp1")
|
||||
: Task.FromResult((string)null)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ public class GenericHost
|
|||
return _baseAddress + path;
|
||||
}
|
||||
|
||||
public async Task InitializeAsync()
|
||||
public async ValueTask InitializeAsync()
|
||||
{
|
||||
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ public class ConfigurationIntegrationTestBase
|
|||
{
|
||||
var dbRoot = new InMemoryDatabaseRoot();
|
||||
IdentityServerHost = new IdentityServerHost(dbRoot);
|
||||
IdentityServerHost.InitializeAsync().Wait();
|
||||
IdentityServerHost.InitializeAsync().AsTask().Wait();
|
||||
|
||||
ConfigurationHost = new ConfigurationHost(dbRoot);
|
||||
ConfigurationHost.InitializeAsync().Wait();
|
||||
ConfigurationHost.InitializeAsync().AsTask().Wait();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -514,13 +514,13 @@ public class ClientConfigurationValidation
|
|||
context.ErrorMessage.ShouldBe(expectedError);
|
||||
}
|
||||
|
||||
public static TheoryData<ICollection<string>> GrantTypesWithClientCredentialsTestData =>
|
||||
[
|
||||
public static TheoryData<ICollection<string>> GrantTypesWithClientCredentialsTestData => new()
|
||||
{
|
||||
GrantTypes.ImplicitAndClientCredentials,
|
||||
GrantTypes.CodeAndClientCredentials,
|
||||
GrantTypes.HybridAndClientCredentials,
|
||||
GrantTypes.ClientCredentials,
|
||||
GrantTypes.ResourceOwnerPasswordAndClientCredentials
|
||||
];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public class AppHostFixture<THost>(IAppHostServiceRoutes routes) : IAsyncLifetim
|
|||
public bool UsingAlreadyRunningInstance { get; private set; }
|
||||
public string StartupLogs => _startupLogs.ToString() ?? string.Empty;
|
||||
|
||||
public async Task InitializeAsync()
|
||||
public async ValueTask InitializeAsync()
|
||||
{
|
||||
using var startupLogWriter = ConnectLogger(s => _startupLogs.Write(s));
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ public class AppHostFixture<THost>(IAppHostServiceRoutes routes) : IAsyncLifetim
|
|||
}
|
||||
|
||||
|
||||
public async Task DisposeAsync()
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_app != null)
|
||||
{
|
||||
|
|
@ -237,7 +237,7 @@ public class AppHostFixture<THost>(IAppHostServiceRoutes routes) : IAsyncLifetim
|
|||
|
||||
return _app.GetEndpoint(hostName);
|
||||
#else
|
||||
Skip.If(true, "When running the Host.Tests using NCrunch, you must start the Hosts.AppHost project manually. IE: dotnet run -p bff/samples/Hosts.AppHost. Or start without debugging from the UI. ");
|
||||
Assert.Skip("When running the Host.Tests using NCrunch, you must start the Hosts.AppHost project manually. IE: dotnet run -p bff/samples/Hosts.AppHost. Or start without debugging from the UI. ");
|
||||
return null!;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,13 +18,12 @@
|
|||
<PackageReference Include="Serilog" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" />
|
||||
<PackageReference Include="Serilog.Sinks.TextWriter" />
|
||||
<PackageReference Include="Serilog.Sinks.XUnit" />
|
||||
<PackageReference Include="Serilog.Sinks.XUnit3" />
|
||||
<PackageReference Include="Serilog.AspNetCore" />
|
||||
<PackageReference Include="Aspire.Hosting.Testing" />
|
||||
<PackageReference Include="Xunit.SkippableFact" />
|
||||
<PackageReference Include="Microsoft.Playwright.Xunit" />
|
||||
<PackageReference Include="Microsoft.Playwright" />
|
||||
<PackageReference Include="Shouldly" />
|
||||
<PackageReference Include="xunit.core" />
|
||||
<PackageReference Include="xunit.v3.extensibility.core" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright (c) Duende Software. All rights reserved.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Xunit.Playwright;
|
||||
|
||||
|
|
@ -23,7 +22,7 @@ public class IntegrationTestBase<THost> : IDisposable where THost : class
|
|||
#if DEBUG_NCRUNCH
|
||||
// Running in NCrunch. NCrunch cannot build the aspire project, so it needs
|
||||
// to be started manually.
|
||||
Skip.If(true, "When running the Host.Tests using NCrunch, you must start the Hosts.AppHost project manually. IE: dotnet run -p bff/samples/Hosts.AppHost. Or start without debugging from the UI. ");
|
||||
Assert.Skip("When running the Host.Tests using NCrunch, you must start the Hosts.AppHost project manually. IE: dotnet run -p bff/samples/Hosts.AppHost. Or start without debugging from the UI. ");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
using System.Reflection;
|
||||
using Microsoft.Playwright;
|
||||
using Microsoft.Playwright.Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Duende.Xunit.Playwright;
|
||||
|
|
@ -12,13 +10,20 @@ namespace Duende.Xunit.Playwright;
|
|||
public class Defaults
|
||||
{
|
||||
public static readonly PageGotoOptions PageGotoOptions = new PageGotoOptions()
|
||||
{ WaitUntil = WaitUntilState.NetworkIdle };
|
||||
{
|
||||
WaitUntil = WaitUntilState.NetworkIdle
|
||||
};
|
||||
}
|
||||
|
||||
[WithTestName]
|
||||
public class PlaywrightTestBase<THost> : PageTest, IDisposable where THost : class
|
||||
public class PlaywrightTestBase<THost> : IAsyncLifetime, IDisposable where THost : class
|
||||
{
|
||||
private readonly IDisposable _loggingScope;
|
||||
private IPlaywright? _playwright;
|
||||
private IBrowser? _browser;
|
||||
|
||||
protected IBrowserContext Context { get; private set; } = null!;
|
||||
protected IPage Page { get; private set; } = null!;
|
||||
|
||||
public PlaywrightTestBase(ITestOutputHelper output, AppHostFixture<THost> fixture)
|
||||
{
|
||||
|
|
@ -35,14 +40,22 @@ public class PlaywrightTestBase<THost> : PageTest, IDisposable where THost : cla
|
|||
#if DEBUG_NCRUNCH
|
||||
// Running in NCrunch. NCrunch cannot build the aspire project, so it needs
|
||||
// to be started manually.
|
||||
Skip.If(true, "When running the Host.Tests using NCrunch, you must start the Hosts.AppHost project manually. IE: dotnet run -p bff/samples/Hosts.AppHost. Or start without debugging from the UI. ");
|
||||
Assert.Skip("When running the Host.Tests using NCrunch, you must start the Hosts.AppHost project manually. IE: dotnet run -p bff/samples/Hosts.AppHost. Or start without debugging from the UI. ");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task InitializeAsync()
|
||||
public AppHostFixture<THost> Fixture { get; }
|
||||
|
||||
public ITestOutputHelper Output { get; }
|
||||
|
||||
public virtual async ValueTask InitializeAsync()
|
||||
{
|
||||
await base.InitializeAsync();
|
||||
_playwright = await Microsoft.Playwright.Playwright.CreateAsync();
|
||||
_browser = await _playwright.Chromium.LaunchAsync(new() { Headless = true });
|
||||
Context = await _browser.NewContextAsync(ContextOptions());
|
||||
Page = await Context.NewPageAsync();
|
||||
|
||||
Context.SetDefaultTimeout(10_000);
|
||||
await Context.Tracing.StartAsync(new()
|
||||
{
|
||||
|
|
@ -53,7 +66,7 @@ public class PlaywrightTestBase<THost> : PageTest, IDisposable where THost : cla
|
|||
});
|
||||
}
|
||||
|
||||
public override async Task DisposeAsync()
|
||||
public virtual async ValueTask DisposeAsync()
|
||||
{
|
||||
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Environment.CurrentDirectory;
|
||||
// if path ends with /bin/{build configuration}/{dotnetversion}, then strip that from the path.
|
||||
|
|
@ -63,7 +76,6 @@ public class PlaywrightTestBase<THost> : PageTest, IDisposable where THost : cla
|
|||
path = Path.GetFullPath(Path.Combine(path, "../../../"));
|
||||
}
|
||||
|
||||
|
||||
await Context.Tracing.StopAsync(new()
|
||||
{
|
||||
Path = Path.Combine(
|
||||
|
|
@ -72,10 +84,13 @@ public class PlaywrightTestBase<THost> : PageTest, IDisposable where THost : cla
|
|||
$"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}.zip"
|
||||
)
|
||||
});
|
||||
await base.DisposeAsync();
|
||||
|
||||
await Context.CloseAsync();
|
||||
await _browser!.DisposeAsync();
|
||||
_playwright!.Dispose();
|
||||
}
|
||||
|
||||
public override BrowserNewContextOptions ContextOptions() => new()
|
||||
public virtual BrowserNewContextOptions ContextOptions() => new()
|
||||
{
|
||||
Locale = "en-US",
|
||||
ColorScheme = ColorScheme.Light,
|
||||
|
|
@ -86,11 +101,6 @@ public class PlaywrightTestBase<THost> : PageTest, IDisposable where THost : cla
|
|||
IgnoreHTTPSErrors = true,
|
||||
};
|
||||
|
||||
|
||||
public AppHostFixture<THost> Fixture { get; }
|
||||
|
||||
public ITestOutputHelper Output { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!Fixture.UsingAlreadyRunningInstance)
|
||||
|
|
@ -109,19 +119,3 @@ public class PlaywrightTestBase<THost> : PageTest, IDisposable where THost : cla
|
|||
|
||||
public HttpClient CreateHttpClient(string clientName) => Fixture.CreateHttpClient(clientName);
|
||||
}
|
||||
|
||||
public class WithTestNameAttribute : BeforeAfterTestAttribute
|
||||
{
|
||||
public static string CurrentTestName = string.Empty;
|
||||
public static string CurrentClassName = string.Empty;
|
||||
|
||||
public override void Before(MethodInfo methodInfo)
|
||||
{
|
||||
CurrentTestName = methodInfo.Name;
|
||||
CurrentClassName = methodInfo.DeclaringType!.Name;
|
||||
}
|
||||
|
||||
public override void After(MethodInfo methodInfo)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (c) Duende Software. All rights reserved.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Duende.Xunit.Playwright.Retries;
|
||||
|
||||
[XunitTestCaseDiscoverer(
|
||||
typeName: "Duende.Hosts.Tests.TestInfra.Retries.RetryableTestDiscoverer",
|
||||
assemblyName: "Duende.Hosts.Tests"
|
||||
)]
|
||||
public class RetryableFact : FactAttribute
|
||||
{
|
||||
public int MaxRetries { get; set; } = 5;
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright (c) Duende Software. All rights reserved.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Duende.Xunit.Playwright.Retries;
|
||||
|
||||
public class RetryableTestCase(
|
||||
IMessageSink sink,
|
||||
TestMethodDisplay display,
|
||||
TestMethodDisplayOptions methodDisplayOptions,
|
||||
ITestMethod method
|
||||
) : XunitTestCase(sink,
|
||||
display,
|
||||
methodDisplayOptions,
|
||||
method,
|
||||
testMethodArguments: null)
|
||||
{
|
||||
public override async Task<RunSummary> RunAsync(
|
||||
IMessageSink diagnosticMessageSink,
|
||||
IMessageBus messageBus,
|
||||
object[] constructorArguments,
|
||||
ExceptionAggregator aggregator,
|
||||
CancellationTokenSource cts)
|
||||
{
|
||||
var retryCount = 0;
|
||||
var maxRetries = Method.GetCustomAttributes(typeof(RetryableFact)).FirstOrDefault()?.GetNamedArgument<int>(nameof(RetryableFact.MaxRetries)) ?? 5;
|
||||
|
||||
while (true)
|
||||
{
|
||||
retryCount++;
|
||||
|
||||
var exceptionCapturingBus = new ExceptionCapturingMessageBus(messageBus);
|
||||
var summary = await base.RunAsync(
|
||||
diagnosticMessageSink,
|
||||
exceptionCapturingBus,
|
||||
constructorArguments,
|
||||
aggregator,
|
||||
cts);
|
||||
|
||||
summary.Failed -= exceptionCapturingBus.SkippedCount;
|
||||
summary.Skipped += exceptionCapturingBus.SkippedCount;
|
||||
|
||||
if (aggregator.HasExceptions || summary.Failed == 0 || retryCount >= maxRetries)
|
||||
{
|
||||
exceptionCapturingBus.Flush();
|
||||
return summary;
|
||||
}
|
||||
|
||||
diagnosticMessageSink.OnMessage(new DiagnosticMessage(
|
||||
"Execution of retriable test '{0}' failed. Attempt {1} of {2}",
|
||||
DisplayName,
|
||||
retryCount,
|
||||
maxRetries
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
// Copyright (c) Duende Software. All rights reserved.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace Duende.Xunit.Playwright.Retries;
|
||||
|
||||
public class RetryableTestDiscoverer(IMessageSink messageSink) : IXunitTestCaseDiscoverer
|
||||
{
|
||||
public IEnumerable<IXunitTestCase> Discover(
|
||||
ITestFrameworkDiscoveryOptions discoveryOptions,
|
||||
ITestMethod testMethod,
|
||||
IAttributeInfo factAttribute)
|
||||
{
|
||||
yield return new RetryableTestCase(
|
||||
messageSink,
|
||||
discoveryOptions.MethodDisplayOrDefault(),
|
||||
discoveryOptions.MethodDisplayOptionsOrDefault(),
|
||||
testMethod
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class ExceptionCapturingMessageBus(IMessageBus inner) : IMessageBus
|
||||
{
|
||||
private readonly object _syncRoot = new();
|
||||
private readonly Queue<IMessageSinkMessage> _failedMessages = new();
|
||||
private bool _disposed = false;
|
||||
|
||||
public bool ExceptionHasOccurred { get; private set; }
|
||||
public int SkippedCount { get; private set; }
|
||||
|
||||
public bool QueueMessage(IMessageSinkMessage message)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(nameof(ExceptionCapturingMessageBus));
|
||||
}
|
||||
|
||||
var skipTest = false;
|
||||
|
||||
if (message is ITestFailed failed)
|
||||
{
|
||||
// We ignore 'skip' exceptions
|
||||
if (failed.ExceptionTypes.Contains("XUnit.SkipException", StringComparer.InvariantCultureIgnoreCase))
|
||||
{
|
||||
skipTest = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExceptionHasOccurred = true;
|
||||
}
|
||||
|
||||
if (skipTest)
|
||||
{
|
||||
SkippedCount++;
|
||||
return inner.QueueMessage(new TestSkipped(failed.Test, "Skipped"));
|
||||
}
|
||||
}
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
_failedMessages.Enqueue(message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
while (_failedMessages.Any())
|
||||
{
|
||||
inner.QueueMessage(_failedMessages.Dequeue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
Flush();
|
||||
}
|
||||
}
|
||||
22
shared/Xunit.Playwright/WithTestNameAttribute.cs
Normal file
22
shared/Xunit.Playwright/WithTestNameAttribute.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) Duende Software. All rights reserved.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using Xunit.v3;
|
||||
|
||||
namespace Duende.Xunit.Playwright;
|
||||
|
||||
public class WithTestNameAttribute : Attribute, IBeforeAfterTestAttribute
|
||||
{
|
||||
public static string CurrentTestName = string.Empty;
|
||||
public static string CurrentClassName = string.Empty;
|
||||
|
||||
public void Before(MethodInfo methodInfo, IXunitTest _)
|
||||
{
|
||||
CurrentTestName = methodInfo.Name;
|
||||
CurrentClassName = methodInfo.DeclaringType!.Name;
|
||||
}
|
||||
|
||||
public void After(MethodInfo methodInfo, IXunitTest _)
|
||||
{ }
|
||||
}
|
||||
|
|
@ -62,10 +62,6 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MinVer">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
|
|
|||
13
test.props
13
test.props
|
|
@ -6,6 +6,7 @@
|
|||
<DebugType>full</DebugType>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<OutputType>Exe</OutputType>
|
||||
<ImplicitUsings>true</ImplicitUsings>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<!-- <Nullable>enable</Nullable> -->
|
||||
|
|
@ -25,17 +26,9 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="Shouldly" />
|
||||
<PackageReference Include="xunit.core" />
|
||||
<PackageReference Include="xunit.runner.visualstudio">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.v3" />
|
||||
<PackageReference Include="xunit.v3.core" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
Loading…
Reference in a new issue