Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/playwright module #1288

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
129 changes: 65 additions & 64 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,67 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="BouncyCastle.Cryptography" Version="2.3.1"/>
<PackageVersion Include="Docker.DotNet.X509" Version="3.125.15"/>
<PackageVersion Include="Docker.DotNet" Version="3.125.15"/>
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0"/>
<PackageVersion Include="Microsoft.Bcl.HashCode" Version="1.1.1"/>
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.4"/>
<PackageVersion Include="ReflectionMagic" Version="5.0.1"/>
<PackageVersion Include="SharpZipLib" Version="1.4.2"/>
<PackageVersion Include="SSH.NET" Version="2023.0.0"/>
<PackageVersion Include="System.Text.Json" Version="6.0.10"/>
<!-- Unit and integration test dependencies: -->
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1"/>
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Testing" Version="8.9.1"/>
<PackageVersion Include="coverlet.collector" Version="6.0.2"/>
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2"/>
<PackageVersion Include="xunit" Version="2.9.0"/>
<!-- Third-party client dependencies to connect and interact with the containers: -->
<PackageVersion Include="Apache.NMS.ActiveMQ" Version="2.1.0"/>
<PackageVersion Include="ArangoDBNetStandard" Version="2.0.1"/>
<PackageVersion Include="AWSSDK.CloudWatchLogs" Version="3.7.104.14"/>
<PackageVersion Include="AWSSDK.DynamoDBv2" Version="3.7.101.42"/>
<PackageVersion Include="AWSSDK.S3" Version="3.7.103.3"/>
<PackageVersion Include="AWSSDK.SimpleNotificationService" Version="3.7.101.7"/>
<PackageVersion Include="AWSSDK.SQS" Version="3.7.100.71"/>
<PackageVersion Include="Azure.Data.Tables" Version="12.8.0"/>
<PackageVersion Include="Azure.Storage.Blobs" Version="12.17.0"/>
<PackageVersion Include="Azure.Storage.Queues" Version="12.15.0"/>
<PackageVersion Include="ClickHouse.Client" Version="6.7.1"/>
<PackageVersion Include="Confluent.Kafka" Version="2.0.2"/>
<PackageVersion Include="Consul" Version="1.6.10.9"/>
<PackageVersion Include="CouchbaseNetClient" Version="3.4.3"/>
<PackageVersion Include="DotPulsar" Version="3.3.2"/>
<PackageVersion Include="Elastic.Clients.Elasticsearch" Version="8.0.5"/>
<PackageVersion Include="EventStore.Client.Grpc.Streams" Version="22.0.0"/>
<PackageVersion Include="FirebirdSql.Data.FirebirdClient" Version="10.0.0"/>
<PackageVersion Include="Google.Cloud.BigQuery.V2" Version="3.4.0"/>
<PackageVersion Include="Google.Cloud.Bigtable.Admin.V2" Version="3.7.0"/>
<PackageVersion Include="Google.Cloud.Firestore" Version="3.1.0"/>
<PackageVersion Include="Google.Cloud.PubSub.V1" Version="3.5.0"/>
<PackageVersion Include="Google.Cloud.Storage.V1" Version="4.6.0"/>
<PackageVersion Include="InfluxDB.Client" Version="4.12.0"/>
<PackageVersion Include="JanusGraph.Net" Version="1.0.0"/>
<PackageVersion Include="Keycloak.Net.Core" Version="1.0.20"/>
<PackageVersion Include="KubernetesClient" Version="10.1.4"/>
<PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.32.1"/>
<PackageVersion Include="Microsoft.Azure.Kusto.Data" Version="11.3.3"/>
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.1.3"/>
<PackageVersion Include="Milvus.Client" Version="2.2.2-preview.6"/>
<PackageVersion Include="MongoDB.Driver" Version="2.19.0"/>
<PackageVersion Include="MyCouch" Version="7.6.0"/>
<PackageVersion Include="MySqlConnector" Version="2.2.5"/>
<PackageVersion Include="NATS.Client" Version="1.0.8"/>
<PackageVersion Include="Neo4j.Driver" Version="5.5.0"/>
<PackageVersion Include="Npgsql" Version="6.0.11"/>
<PackageVersion Include="Oracle.ManagedDataAccess.Core" Version="3.21.90"/>
<PackageVersion Include="RabbitMQ.Client" Version="6.4.0"/>
<PackageVersion Include="RavenDB.Client" Version="5.4.100"/>
<PackageVersion Include="Selenium.WebDriver" Version="4.8.1"/>
<PackageVersion Include="StackExchange.Redis" Version="2.6.90"/>
</ItemGroup>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="BouncyCastle.Cryptography" Version="2.3.1" />
<PackageVersion Include="Docker.DotNet.X509" Version="3.125.15" />
<PackageVersion Include="Docker.DotNet" Version="3.125.15" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
<PackageVersion Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.4" />
<PackageVersion Include="Microsoft.Playwright" Version="1.48.0" />
<PackageVersion Include="ReflectionMagic" Version="5.0.1" />
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
<PackageVersion Include="SSH.NET" Version="2023.0.0" />
<PackageVersion Include="System.Text.Json" Version="6.0.10" />
<!-- Unit and integration test dependencies: -->
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Testing" Version="8.9.1" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageVersion Include="xunit" Version="2.9.0" />
<!-- Third-party client dependencies to connect and interact with the containers: -->
<PackageVersion Include="Apache.NMS.ActiveMQ" Version="2.1.0" />
<PackageVersion Include="ArangoDBNetStandard" Version="2.0.1" />
<PackageVersion Include="AWSSDK.CloudWatchLogs" Version="3.7.104.14" />
<PackageVersion Include="AWSSDK.DynamoDBv2" Version="3.7.101.42" />
<PackageVersion Include="AWSSDK.S3" Version="3.7.103.3" />
<PackageVersion Include="AWSSDK.SimpleNotificationService" Version="3.7.101.7" />
<PackageVersion Include="AWSSDK.SQS" Version="3.7.100.71" />
<PackageVersion Include="Azure.Data.Tables" Version="12.8.0" />
<PackageVersion Include="Azure.Storage.Blobs" Version="12.17.0" />
<PackageVersion Include="Azure.Storage.Queues" Version="12.15.0" />
<PackageVersion Include="ClickHouse.Client" Version="6.7.1" />
<PackageVersion Include="Confluent.Kafka" Version="2.0.2" />
<PackageVersion Include="Consul" Version="1.6.10.9" />
<PackageVersion Include="CouchbaseNetClient" Version="3.4.3" />
<PackageVersion Include="DotPulsar" Version="3.3.2" />
<PackageVersion Include="Elastic.Clients.Elasticsearch" Version="8.0.5" />
<PackageVersion Include="EventStore.Client.Grpc.Streams" Version="22.0.0" />
<PackageVersion Include="FirebirdSql.Data.FirebirdClient" Version="10.0.0" />
<PackageVersion Include="Google.Cloud.BigQuery.V2" Version="3.4.0" />
<PackageVersion Include="Google.Cloud.Bigtable.Admin.V2" Version="3.7.0" />
<PackageVersion Include="Google.Cloud.Firestore" Version="3.1.0" />
<PackageVersion Include="Google.Cloud.PubSub.V1" Version="3.5.0" />
<PackageVersion Include="Google.Cloud.Storage.V1" Version="4.6.0" />
<PackageVersion Include="InfluxDB.Client" Version="4.12.0" />
<PackageVersion Include="JanusGraph.Net" Version="1.0.0" />
<PackageVersion Include="Keycloak.Net.Core" Version="1.0.20" />
<PackageVersion Include="KubernetesClient" Version="10.1.4" />
<PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.32.1" />
<PackageVersion Include="Microsoft.Azure.Kusto.Data" Version="11.3.3" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.1.3" />
<PackageVersion Include="Milvus.Client" Version="2.2.2-preview.6" />
<PackageVersion Include="MongoDB.Driver" Version="2.19.0" />
<PackageVersion Include="MyCouch" Version="7.6.0" />
<PackageVersion Include="MySqlConnector" Version="2.2.5" />
<PackageVersion Include="NATS.Client" Version="1.0.8" />
<PackageVersion Include="Neo4j.Driver" Version="5.5.0" />
<PackageVersion Include="Npgsql" Version="6.0.11" />
<PackageVersion Include="Oracle.ManagedDataAccess.Core" Version="3.21.90" />
<PackageVersion Include="RabbitMQ.Client" Version="6.4.0" />
<PackageVersion Include="RavenDB.Client" Version="5.4.100" />
<PackageVersion Include="Selenium.WebDriver" Version="4.8.1" />
<PackageVersion Include="StackExchange.Redis" Version="2.6.90" />
</ItemGroup>
</Project>
14 changes: 14 additions & 0 deletions Testcontainers.sln
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Tests", "tes
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.WebDriver.Tests", "tests\Testcontainers.WebDriver.Tests\Testcontainers.WebDriver.Tests.csproj", "{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Playwright", "src\Testcontainers.Playwright\Testcontainers.Playwright.csproj", "{275ADBA5-498E-45FA-AD3F-0E5EE7996D99}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Playwright.Tests", "tests\Testcontainers.Playwright.Tests\Testcontainers.Playwright.Tests.csproj", "{A56D182C-8347-4CBE-9FC8-F2C98648F134}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -568,6 +572,14 @@ Global
{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Release|Any CPU.Build.0 = Release|Any CPU
{275ADBA5-498E-45FA-AD3F-0E5EE7996D99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{275ADBA5-498E-45FA-AD3F-0E5EE7996D99}.Debug|Any CPU.Build.0 = Debug|Any CPU
{275ADBA5-498E-45FA-AD3F-0E5EE7996D99}.Release|Any CPU.ActiveCfg = Release|Any CPU
{275ADBA5-498E-45FA-AD3F-0E5EE7996D99}.Release|Any CPU.Build.0 = Release|Any CPU
{A56D182C-8347-4CBE-9FC8-F2C98648F134}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A56D182C-8347-4CBE-9FC8-F2C98648F134}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A56D182C-8347-4CBE-9FC8-F2C98648F134}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A56D182C-8347-4CBE-9FC8-F2C98648F134}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{5365F780-0E6C-41F0-B1B9-7DC34368F80C} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
Expand Down Expand Up @@ -661,5 +673,7 @@ Global
{9E8E6AA5-65D1-498F-BEAB-BA34723A0050} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{27CDB869-A150-4593-958F-6F26E5391E7C} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{275ADBA5-498E-45FA-AD3F-0E5EE7996D99} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{A56D182C-8347-4CBE-9FC8-F2C98648F134} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
EndGlobalSection
EndGlobal
52 changes: 52 additions & 0 deletions src/Testcontainers.Playwright/PlaywrightBrowser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
namespace Testcontainers.Playwright;

/// <summary>
/// Playwright browser configuration.
/// </summary>
[PublicAPI]
public readonly struct PlaywrightBrowser
{
/// <summary>
/// Gets the Playwright standalone Chrome configuration.
/// </summary>
public static readonly PlaywrightBrowser Chrome = new PlaywrightBrowser("jacoblincool/playwright:chrome-server");

/// <summary>
/// Gets the Playwright standalone Chromium configuration.
/// </summary>
public static readonly PlaywrightBrowser Chromium = new PlaywrightBrowser("jacoblincool/playwright:chromium-server");

/// <summary>
/// Gets the Playwright standalone Firefox configuration.
/// </summary>
public static readonly PlaywrightBrowser Firefox = new PlaywrightBrowser("jacoblincool/playwright:firefox-server");

/// <summary>
/// Gets the Playwright standalone Edge configuration.
/// </summary>
public static readonly PlaywrightBrowser Edge = new PlaywrightBrowser("jacoblincool/playwright:msedge-server");


/// <summary>
/// Initializes a new instance of the <see cref="PlaywrightBrowser" /> struct.
/// </summary>
/// <param name="image">The Playwright standalone Docker image.</param>
public PlaywrightBrowser(string image)
: this(new DockerImage(image))
{
}

/// <summary>
/// Initializes a new instance of the <see cref="PlaywrightBrowser" /> struct.
/// </summary>
/// <param name="image">The Playwright standalone Docker image.</param>
public PlaywrightBrowser(IImage image)
{
Image = image;
}
/// <summary>
/// Gets the Playwright standalone Docker image.
/// </summary>
[NotNull]
public IImage Image { get; }
}
98 changes: 98 additions & 0 deletions src/Testcontainers.Playwright/PlaywrightBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
namespace Testcontainers.Playwright;

/// <inheritdoc cref="PlaywrightBuilder{TBuilderEntity, TContainerEntity, TConfigurationEntity}" />
/// <remarks>
/// Find further information about the Playwright image, here: https://playwright.dev/dotnet/docs/docker.
/// </remarks>
[PublicAPI]
public class PlaywrightBuilder : ContainerBuilder<PlaywrightBuilder, PlaywrightContainer, PlaywrightConfiguration>
{
private const ushort PlaywrightPort = 53333;
private const string PlaywrightEndpointPath = "/playwright";

/// <summary>
/// Initializes a new instance of the <see cref="PlaywrightBuilder" /> class.
/// </summary>
public PlaywrightBuilder() : this(new PlaywrightConfiguration())
{
DockerResourceConfiguration = Init().DockerResourceConfiguration;
}

/// <summary>
/// Initializes a new instance of the <see cref="PlaywrightBuilder" /> class.
/// </summary>
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
private PlaywrightBuilder(PlaywrightConfiguration resourceConfiguration)
: base(resourceConfiguration)
{
DockerResourceConfiguration = resourceConfiguration;
}

/// <inheritdoc />
protected override PlaywrightConfiguration DockerResourceConfiguration { get; }

public override PlaywrightContainer Build()
{
Validate();
return new PlaywrightContainer(DockerResourceConfiguration);
}

/// <inheritdoc />
protected override PlaywrightBuilder Init()
{
return base.Init()
.WithBrowser(PlaywrightBrowser.Chrome)
.WithEndpointPath(PlaywrightEndpointPath)
.WithBrowserPort(PlaywrightPort)
.WithWaitStrategy(Wait.ForUnixContainer()
.UntilMessageIsLogged($"ws://.*:{PlaywrightPort}{PlaywrightEndpointPath}"));
}

public PlaywrightBuilder WithBrowser(PlaywrightBrowser playwrightBrowser)
{
return WithImage(playwrightBrowser.Image);
}

/// <summary>
/// Sets the BROWSER WS ENDPOINT.
/// </summary>
/// <param name="endpointPath">The BROWSER WS ENDPOINT.</param>
/// <returns>A configured instance of <see cref="PlaywrightBuilder" />.</returns>
public PlaywrightBuilder WithEndpointPath(string endpointPath)
{
return Merge(DockerResourceConfiguration, new PlaywrightConfiguration(endpoint: endpointPath))
.WithEnvironment("BROWSER_WS_ENDPOINT", endpointPath);
}

/// <summary>
/// Sets the BROWSER WS PORT.
/// </summary>
/// <param name="port">The BROWSER WS PORT.</param>
/// <returns>A configured instance of <see cref="PlaywrightBuilder" />.</returns>
public PlaywrightBuilder WithBrowserPort(int port, bool assignRandomHostPort=false)
{
return Merge(DockerResourceConfiguration, new PlaywrightConfiguration(port: port))
.WithEnvironment("BROWSER_PORT", port.ToString())
.WithPortBinding(port, assignRandomHostPort);
}



/// <inheritdoc />
protected override PlaywrightBuilder Clone(IResourceConfiguration<CreateContainerParameters> resourceConfiguration)
{
return Merge(DockerResourceConfiguration, new PlaywrightConfiguration(resourceConfiguration));
}

/// <inheritdoc />
protected override PlaywrightBuilder Clone(IContainerConfiguration resourceConfiguration)
{
return Merge(DockerResourceConfiguration, new PlaywrightConfiguration(resourceConfiguration));
}

/// <inheritdoc />
protected override PlaywrightBuilder Merge(PlaywrightConfiguration oldValue, PlaywrightConfiguration newValue)
{
return new PlaywrightBuilder(new PlaywrightConfiguration(oldValue, newValue));
}
}
70 changes: 70 additions & 0 deletions src/Testcontainers.Playwright/PlaywrightConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
namespace Testcontainers.Playwright;

/// <inheritdoc cref="PlaywrightConfiguration" />
[PublicAPI]
public class PlaywrightConfiguration : ContainerConfiguration
{
/// <summary>
/// Initializes a new instance of the <see cref="PlaywrightConfiguration" /> class.
/// </summary>
/// <param name="endpoint">The Playwright endpoint.</param>
public PlaywrightConfiguration(string endpoint = null,
int? port = null)
{
Endpoint = endpoint;
Port = port;
}

/// <summary>
/// Initializes a new instance of the <see cref="PlaywrightConfiguration" /> class.
/// </summary>
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
public PlaywrightConfiguration(IResourceConfiguration<CreateContainerParameters> resourceConfiguration)
: base(resourceConfiguration)
{
// Passes the configuration upwards to the base implementations to create an updated immutable copy.
}

/// <summary>
/// Initializes a new instance of the <see cref="PlaywrightConfiguration" /> class.
/// </summary>
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
public PlaywrightConfiguration(IContainerConfiguration resourceConfiguration)
: base(resourceConfiguration)
{
// Passes the configuration upwards to the base implementations to create an updated immutable copy.
}

/// <summary>
/// Initializes a new instance of the <see cref="PlaywrightConfiguration" /> class.
/// </summary>
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
public PlaywrightConfiguration(PlaywrightConfiguration resourceConfiguration)
: this(new PlaywrightConfiguration(), resourceConfiguration)
{
// Passes the configuration upwards to the base implementations to create an updated immutable copy.
}

/// <summary>
/// Initializes a new instance of the <see cref="PlaywrightConfiguration" /> class.
/// </summary>
/// <param name="oldValue">The old Docker resource configuration.</param>
/// <param name="newValue">The new Docker resource configuration.</param>
public PlaywrightConfiguration(PlaywrightConfiguration oldValue, PlaywrightConfiguration newValue)
: base(oldValue, newValue)
{
Endpoint = BuildConfiguration.Combine(oldValue.Endpoint, newValue.Endpoint);
}


/// <summary>
/// Gets the Playwright endpoint.
/// </summary>
public string Endpoint { get; }


/// <summary>
/// Gets the Playwright port.
/// </summary>
public int? Port { get; }
}
Loading