2025-03-06 04:17:44 +00:00
// Copyright (c) Duende Software. All rights reserved.
2025-02-10 10:35:22 +00:00
// See LICENSE in the project root for license information.
2025-03-01 18:45:48 +00:00
using System.Reflection ;
2025-02-10 10:35:22 +00:00
using Microsoft.Playwright ;
2026-02-18 08:54:01 +00:00
using Microsoft.Playwright.Xunit.v3 ;
using Xunit.v3 ;
2025-10-15 16:57:54 +00:00
2025-08-29 20:08:52 +00:00
namespace Duende.Xunit.Playwright ;
2025-02-10 10:35:22 +00:00
2025-03-17 14:13:36 +00:00
public class Defaults
{
public static readonly PageGotoOptions PageGotoOptions = new PageGotoOptions ( )
2025-10-15 16:57:54 +00:00
{ WaitUntil = WaitUntilState . NetworkIdle } ;
2025-03-17 14:13:36 +00:00
}
2025-02-20 13:14:31 +00:00
[WithTestName]
2025-10-15 16:57:54 +00:00
public class PlaywrightTestBase < THost > : PageTest , IDisposable where THost : class
2025-02-10 10:35:22 +00:00
{
private readonly IDisposable _loggingScope ;
2026-02-18 08:54:01 +00:00
private readonly ITestOutputHelper _testOutputHelper = TestContext . Current . TestOutputHelper ! ;
2025-02-10 10:35:22 +00:00
2026-02-18 08:54:01 +00:00
public PlaywrightTestBase ( AppHostFixture < THost > fixture )
2025-02-10 10:35:22 +00:00
{
Fixture = fixture ;
2026-02-18 08:54:01 +00:00
_loggingScope = fixture . ConnectLogger ( _testOutputHelper . WriteLine ) ;
2025-02-10 10:35:22 +00:00
if ( Fixture . UsingAlreadyRunningInstance )
{
2026-02-18 08:54:01 +00:00
_testOutputHelper . WriteLine ( "Running tests against locally running instance" ) ;
2025-02-10 10:35:22 +00:00
}
else
{
#if DEBUG_NCRUNCH
// Running in NCrunch. NCrunch cannot build the aspire project, so it needs
2025-08-29 20:08:52 +00:00
// to be started manually.
2026-02-18 08:54:01 +00:00
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. " ) ;
2025-02-10 10:35:22 +00:00
#endif
}
}
2026-02-18 08:54:01 +00:00
public override async ValueTask InitializeAsync ( )
2025-02-20 13:14:31 +00:00
{
2025-10-15 16:57:54 +00:00
await base . InitializeAsync ( ) ;
2026-02-18 18:07:47 +00:00
Context . SetDefaultTimeout ( 60_000 ) ;
2025-02-20 13:14:31 +00:00
await Context . Tracing . StartAsync ( new ( )
{
Title = $"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}" ,
Screenshots = true ,
Snapshots = true ,
Sources = true
} ) ;
}
2026-02-18 08:54:01 +00:00
public override async ValueTask DisposeAsync ( )
2025-02-20 13:14:31 +00:00
{
var path = Path . GetDirectoryName ( Assembly . GetExecutingAssembly ( ) . Location ) ? ? Environment . CurrentDirectory ;
2025-08-29 20:08:52 +00:00
// if path ends with /bin/{build configuration}/{dotnetversion}, then strip that from the path.
2025-02-20 13:14:31 +00:00
var bin = Path . GetFullPath ( Path . Combine ( path , "../../" ) ) ;
if ( bin . EndsWith ( "\\bin\\" ) | | bin . EndsWith ( "/bin/" ) )
{
path = Path . GetFullPath ( Path . Combine ( path , "../../../" ) ) ;
}
2025-10-15 16:57:54 +00:00
2025-02-20 13:14:31 +00:00
await Context . Tracing . StopAsync ( new ( )
{
Path = Path . Combine (
path ,
"playwright-traces" ,
$"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}.zip"
)
} ) ;
2025-10-15 16:57:54 +00:00
await base . DisposeAsync ( ) ;
2025-02-20 13:14:31 +00:00
}
2025-10-15 16:57:54 +00:00
public override BrowserNewContextOptions ContextOptions ( ) = > new ( )
2025-02-10 10:35:22 +00:00
{
2025-04-07 06:10:10 +00:00
Locale = "en-US" ,
ColorScheme = ColorScheme . Light ,
2025-08-29 20:08:52 +00:00
// We need to ignore https errors to make this work on the build server.
2025-04-07 06:10:10 +00:00
// Even though we use dotnet dev-certs https --trust on the build agent,
2025-08-29 20:08:52 +00:00
// it still claims the certs are invalid.
2025-04-07 06:10:10 +00:00
IgnoreHTTPSErrors = true ,
} ;
2025-02-10 10:35:22 +00:00
2025-10-15 16:57:54 +00:00
public AppHostFixture < THost > Fixture { get ; }
2026-02-18 08:54:01 +00:00
public ITestOutputHelper TestOutputHelper = > _testOutputHelper ;
2025-10-15 16:57:54 +00:00
2025-02-10 10:35:22 +00:00
public void Dispose ( )
{
if ( ! Fixture . UsingAlreadyRunningInstance )
{
2026-02-18 08:54:01 +00:00
_testOutputHelper . WriteLine ( Environment . NewLine ) ;
_testOutputHelper . WriteLine ( Environment . NewLine ) ;
_testOutputHelper . WriteLine ( Environment . NewLine ) ;
_testOutputHelper . WriteLine ( "*************************************************" ) ;
_testOutputHelper . WriteLine ( "** Startup logs ***" ) ;
_testOutputHelper . WriteLine ( "*************************************************" ) ;
_testOutputHelper . WriteLine ( Fixture . StartupLogs ) ;
2025-02-10 10:35:22 +00:00
}
_loggingScope . Dispose ( ) ;
}
2025-04-07 06:10:10 +00:00
public HttpClient CreateHttpClient ( string clientName ) = > Fixture . CreateHttpClient ( clientName ) ;
2025-02-20 13:14:31 +00:00
}
2025-10-15 16:57:54 +00:00
public class WithTestNameAttribute : BeforeAfterTestAttribute
{
public static string CurrentTestName = string . Empty ;
public static string CurrentClassName = string . Empty ;
2026-02-18 08:54:01 +00:00
public override void Before ( MethodInfo methodUnderTest , IXunitTest test )
2025-10-15 16:57:54 +00:00
{
2026-02-18 08:54:01 +00:00
CurrentTestName = methodUnderTest . Name ;
CurrentClassName = methodUnderTest . DeclaringType ! . Name ;
2025-10-15 16:57:54 +00:00
}
2026-02-18 08:54:01 +00:00
public override void After ( MethodInfo methodUnderTest , IXunitTest test )
2025-10-15 16:57:54 +00:00
{
}
}