diff --git a/src/Playwright.MSTest.v4/Playwright.MSTest.v4.csproj b/src/Playwright.MSTest.v4/Playwright.MSTest.v4.csproj
new file mode 100644
index 000000000..21573913a
--- /dev/null
+++ b/src/Playwright.MSTest.v4/Playwright.MSTest.v4.csproj
@@ -0,0 +1,50 @@
+
+
+
+ Microsoft.Playwright.MSTest.v4
+ Microsoft.Playwright.MSTest.v4
+ A set of helpers and fixtures to enable using Playwright in MSTest 4 tests.
+
+ Playwright enables reliable end-to-end testing for modern web apps. This package brings in additional helpers
+ and fixtures to enable using it within MSTest.
+
+ icon.png
+ netstandard2.0
+ true
+ true
+ Microsoft.Playwright.MSTest
+ 0.0.0
+ True
+ Microsoft.Playwright.MSTest.v4
+ ./nupkg
+ true
+ enable
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+ %(RecursiveDir)%(FileName)%(Extension)
+
+
+
diff --git a/src/Playwright.TestingHarnessTest/Playwright.TestingHarnessTest.csproj b/src/Playwright.TestingHarnessTest/Playwright.TestingHarnessTest.csproj
index b6670ab1c..2bc474ac1 100644
--- a/src/Playwright.TestingHarnessTest/Playwright.TestingHarnessTest.csproj
+++ b/src/Playwright.TestingHarnessTest/Playwright.TestingHarnessTest.csproj
@@ -18,6 +18,11 @@
+
+
+
+
+
diff --git a/src/Playwright.TestingHarnessTest/tests/baseTest.ts b/src/Playwright.TestingHarnessTest/tests/baseTest.ts
index c162b3411..55e850795 100644
--- a/src/Playwright.TestingHarnessTest/tests/baseTest.ts
+++ b/src/Playwright.TestingHarnessTest/tests/baseTest.ts
@@ -19,7 +19,7 @@ type RunResult = {
export const test = base.extend<{
proxyServer: ProxyServer;
- testMode: 'nunit' | 'mstest' | 'xunit' | 'xunit.v3';
+ testMode: 'nunit' | 'mstest' | 'mstest.v4' | 'xunit' | 'xunit.v3';
runTest: (files: Record, command: string, env?: NodeJS.ProcessEnv) => Promise;
launchServer: (options: { port: number }) => Promise;
server: SimpleServer;
diff --git a/src/Playwright.TestingHarnessTest/tests/mstest.v4/basic.spec.ts b/src/Playwright.TestingHarnessTest/tests/mstest.v4/basic.spec.ts
new file mode 100644
index 000000000..4819349f2
--- /dev/null
+++ b/src/Playwright.TestingHarnessTest/tests/mstest.v4/basic.spec.ts
@@ -0,0 +1,537 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) Microsoft Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import { test, expect } from '../baseTest';
+
+test.use({ testMode: 'mstest.v4' });
+
+test('should be able to forward DEBUG=pw:api env var', async ({ runTest }) => {
+ const result = await runTest({
+ 'ExampleTests.cs': `
+ using System;
+ using System.Threading.Tasks;
+ using Microsoft.Playwright.MSTest;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ namespace Playwright.TestingHarnessTest.MSTest;
+
+ [TestClass]
+ public class : PageTest
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ await Page.GotoAsync("about:blank");
+ await Page.SetContentAsync("");
+ try
+ {
+ await Page.Locator("button").ClickAsync(new() { Timeout = 1_000 });
+ }
+ catch
+ {
+ }
+ }
+ }`,
+ '.runsettings': `
+
+
+
+
+ pw:api
+
+
+ `,
+ }, 'dotnet test --settings=.runsettings');
+ expect(result.passed).toBe(1);
+ expect(result.failed).toBe(0);
+ expect(result.total).toBe(1);
+ expect(result.stderr).toContain("pw:api")
+ expect(result.stderr).toContain("element is not enabled")
+ expect(result.stderr).toContain("retrying click action")
+});
+
+test('should be able to set the browser via the runsettings file', async ({ runTest }) => {
+ const result = await runTest({
+ 'ExampleTests.cs': `
+ using System;
+ using System.Threading.Tasks;
+ using Microsoft.Playwright.MSTest;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ namespace Playwright.TestingHarnessTest.MSTest;
+
+ [TestClass]
+ public class : PageTest
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ await Page.GotoAsync("about:blank");
+ Console.WriteLine("BrowserName: " + BrowserName);
+ Console.WriteLine("BrowserType: " + BrowserType.Name);
+ Console.WriteLine("User-Agent: " + await Page.EvaluateAsync("() => navigator.userAgent"));
+ }
+ }`,
+ '.runsettings': `
+
+
+
+ webkit
+
+
+ `,
+ }, 'dotnet test --settings=.runsettings');
+ expect(result.passed).toBe(1);
+ expect(result.failed).toBe(0);
+ expect(result.total).toBe(1);
+ expect(result.stdout).toContain("BrowserName: webkit")
+ expect(result.stdout).toContain("BrowserType: webkit")
+ expect(/User-Agent: .*WebKit.*/.test(result.stdout)).toBeTruthy()
+});
+
+test('should prioritize browser from env over the runsettings file', async ({ runTest }) => {
+ const result = await runTest({
+ 'ExampleTests.cs': `
+ using System;
+ using System.Threading.Tasks;
+ using Microsoft.Playwright.MSTest;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ namespace Playwright.TestingHarnessTest.MSTest;
+
+ [TestClass]
+ public class : PageTest
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ await Page.GotoAsync("about:blank");
+ Console.WriteLine("BrowserName: " + BrowserName);
+ Console.WriteLine("BrowserType: " + BrowserType.Name);
+ Console.WriteLine("User-Agent: " + await Page.EvaluateAsync("() => navigator.userAgent"));
+ }
+ }`,
+ '.runsettings': `
+
+
+
+ webkit
+
+
+ `,
+ }, 'dotnet test --settings=.runsettings', {
+ BROWSER: 'firefox'
+ });
+ expect(result.passed).toBe(1);
+ expect(result.failed).toBe(0);
+ expect(result.total).toBe(1);
+ expect(result.stdout).toContain("BrowserName: firefox")
+ expect(result.stdout).toContain("BrowserType: firefox")
+ expect(/User-Agent: .*Firefox.*/.test(result.stdout)).toBeTruthy()
+});
+
+test('should be able to make the browser headed via the env', async ({ runTest }) => {
+ const result = await runTest({
+ 'ExampleTests.cs': `
+ using System;
+ using System.Threading.Tasks;
+ using Microsoft.Playwright.MSTest;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ namespace Playwright.TestingHarnessTest.MSTest;
+
+ [TestClass]
+ public class : PageTest
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ await Page.GotoAsync("about:blank");
+ Console.WriteLine("BrowserName: " + BrowserName);
+ Console.WriteLine("User-Agent: " + await Page.EvaluateAsync("() => navigator.userAgent"));
+ }
+ }`,
+ }, 'dotnet test', {
+ HEADED: '1'
+ });
+ expect(result.passed).toBe(1);
+ expect(result.failed).toBe(0);
+ expect(result.total).toBe(1);
+ expect(result.stdout).toContain("BrowserName: chromium")
+ expect(result.stdout).not.toContain("Headless")
+});
+
+test('should be able to parse BrowserName and LaunchOptions.Headless from runsettings', async ({ runTest }) => {
+ const result = await runTest({
+ 'ExampleTests.cs': `
+ using System;
+ using System.Threading.Tasks;
+ using Microsoft.Playwright.MSTest;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ namespace Playwright.TestingHarnessTest.MSTest;
+
+ [TestClass]
+ public class : PageTest
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ await Page.GotoAsync("about:blank");
+ Console.WriteLine("BrowserName: " + BrowserName);
+ Console.WriteLine("User-Agent: " + await Page.EvaluateAsync("() => navigator.userAgent"));
+ }
+ }`,
+ '.runsettings': `
+
+
+
+
+ false
+
+
+ firefox
+
+
+ `,
+ }, 'dotnet test --settings=.runsettings');
+ expect(result.passed).toBe(1);
+ expect(result.failed).toBe(0);
+ expect(result.total).toBe(1);
+ expect(result.stdout).toContain("BrowserName: firefox")
+ expect(result.stdout).not.toContain("Headless")
+});
+
+test('should be able to parse LaunchOptions.Proxy from runsettings', async ({ runTest, proxyServer, server }) => {
+ const result = await runTest({
+ 'ExampleTests.cs': `
+ using System;
+ using System.Threading.Tasks;
+ using Microsoft.Playwright.MSTest;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ namespace Playwright.TestingHarnessTest.MSTest;
+
+ [TestClass]
+ public class : PageTest
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ Console.WriteLine("User-Agent: " + await Page.EvaluateAsync("() => navigator.userAgent"));
+ await Page.GotoAsync("${server.EMPTY_PAGE}");
+ }
+ }`,
+ '.runsettings': `
+
+
+
+ chromium
+
+ false
+
+ ${proxyServer.listenAddr()}
+ user
+ pwd
+
+
+
+
+ `,
+ }, 'dotnet test --settings=.runsettings');
+ expect(result.passed).toBe(1);
+ expect(result.failed).toBe(0);
+ expect(result.total).toBe(1);
+
+ expect(result.stdout).not.toContain("Headless");
+
+ const { url, auth } = proxyServer.requests.find(r => r.url === server.EMPTY_PAGE)!;
+ expect(url).toBe(server.EMPTY_PAGE);
+ expect(auth).toBe('user:pwd');
+});
+
+test('should be able to parse LaunchOptions.Args from runsettings', async ({ runTest }) => {
+ const result = await runTest({
+ 'ExampleTests.cs': `
+ using System;
+ using System.Threading.Tasks;
+ using Microsoft.Playwright.MSTest;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ namespace Playwright.TestingHarnessTest.MSTest;
+
+ [TestClass]
+ public class : PageTest
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ Console.WriteLine("User-Agent: " + await Page.EvaluateAsync("() => navigator.userAgent"));
+ }
+ }`,
+ '.runsettings': `
+
+
+
+
+ ['--user-agent=hello']
+
+
+
+ `,
+ }, 'dotnet test --settings=.runsettings');
+ expect(result.passed).toBe(1);
+ expect(result.failed).toBe(0);
+ expect(result.total).toBe(1);
+ expect(result.stdout).toContain("User-Agent: hello")
+});
+
+test('should be able to override context options', async ({ runTest, server }) => {
+ const result = await runTest({
+ 'ExampleTests.cs': `
+ using System;
+ using System.Collections.Generic;
+ using System.Threading.Tasks;
+ using Microsoft.Playwright;
+ using Microsoft.Playwright.MSTest;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ namespace Playwright.TestingHarnessTest.MSTest;
+
+ [TestClass]
+ public class : PageTest
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ await Page.GotoAsync("about:blank");
+
+ Assert.IsFalse(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches"));
+ Assert.IsTrue(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches"));
+
+ Assert.AreEqual(1920, await Page.EvaluateAsync("() => window.innerWidth"));
+ Assert.AreEqual(1080, await Page.EvaluateAsync("() => window.innerHeight"));
+
+ Assert.AreEqual("Foobar", await Page.EvaluateAsync("() => navigator.userAgent"));
+
+ var response = await Page.GotoAsync("${server.EMPTY_PAGE}");
+ Assert.AreEqual(await response.Request.HeaderValueAsync("Kekstar"), "KekStarValue");
+ }
+
+ public override BrowserNewContextOptions ContextOptions()
+ {
+ return new BrowserNewContextOptions()
+ {
+ ColorScheme = ColorScheme.Dark,
+ UserAgent = "Foobar",
+ ViewportSize = new()
+ {
+ Width = 1920,
+ Height = 1080
+ },
+ ExtraHTTPHeaders = new Dictionary {
+ { "Kekstar", "KekStarValue" }
+ }
+ };
+ }
+ }`}, 'dotnet test');
+ expect(result.passed).toBe(1);
+ expect(result.failed).toBe(0);
+ expect(result.total).toBe(1);
+});
+
+test('should be able to override launch options', async ({ runTest }) => {
+ const result = await runTest({
+ 'ExampleTests.cs': `
+ using System;
+ using System.Threading.Tasks;
+ using Microsoft.Playwright.MSTest;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ namespace Playwright.TestingHarnessTest.MSTest;
+
+ [TestClass]
+ public class : PageTest
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ await Page.GotoAsync("about:blank");
+ Console.WriteLine("User-Agent: " + await Page.EvaluateAsync("() => navigator.userAgent"));
+ }
+ }`,
+ '.runsettings': `
+
+
+
+
+ false
+
+
+
+ `,
+ }, 'dotnet test --settings=.runsettings');
+ expect(result.passed).toBe(1);
+ expect(result.failed).toBe(0);
+ expect(result.total).toBe(1);
+ expect(result.stdout).not.toContain("Headless");
+});
+
+test.describe('Expect() timeout', () => {
+ test('should have 5 seconds by default', async ({ runTest }) => {
+ const result = await runTest({
+ 'ExampleTests.cs': `
+ using System;
+ using System.Threading.Tasks;
+ using Microsoft.Playwright.MSTest;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ namespace Playwright.TestingHarnessTest.MSTest;
+
+ [TestClass]
+ public class : PageTest
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ await Page.GotoAsync("about:blank");
+ await Page.SetContentAsync("");
+ await Expect(Page.Locator("button")).ToHaveTextAsync("noooo-wrong-text");
+ }
+ }`,
+ }, 'dotnet test');
+ expect(result.passed).toBe(0);
+ expect(result.failed).toBe(1);
+ expect(result.total).toBe(1);
+ expect(result.rawStdout).toContain("Expect \"ToHaveTextAsync\" with timeout 5000ms")
+ });
+
+ test('should be able to override it via each Expect() call', async ({ runTest }) => {
+ const result = await runTest({
+ 'ExampleTests.cs': `
+ using System;
+ using System.Threading.Tasks;
+ using Microsoft.Playwright.MSTest;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ namespace Playwright.TestingHarnessTest.MSTest;
+
+ [TestClass]
+ public class : PageTest
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ await Page.GotoAsync("about:blank");
+ await Page.SetContentAsync("");
+ await Expect(Page.Locator("button")).ToHaveTextAsync("noooo-wrong-text", new() { Timeout = 100 });
+ }
+ }`,
+ }, 'dotnet test');
+ expect(result.passed).toBe(0);
+ expect(result.failed).toBe(1);
+ expect(result.total).toBe(1);
+ expect(result.rawStdout).toContain("Expect \"ToHaveTextAsync\" with timeout 100ms")
+ });
+ test('should be able to override it via the global settings', async ({ runTest }) => {
+ const result = await runTest({
+ 'ExampleTests.cs': `
+ using System;
+ using System.Threading.Tasks;
+ using Microsoft.Playwright.MSTest;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ namespace Playwright.TestingHarnessTest.MSTest;
+
+ [TestClass]
+ public class : PageTest
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ await Page.GotoAsync("about:blank");
+ await Page.SetContentAsync("");
+ await Expect(Page.Locator("button")).ToHaveTextAsync("noooo-wrong-text");
+ }
+ }`,
+ '.runsettings': `
+
+
+
+ 123
+
+
+ `,
+ }, 'dotnet test --settings=.runsettings');
+ expect(result.passed).toBe(0);
+ expect(result.failed).toBe(1);
+ expect(result.total).toBe(1);
+ expect(result.rawStdout).toContain("Expect \"ToHaveTextAsync\" with timeout 123ms")
+ });
+});
+
+test.describe('ConnectOptions', () => {
+ const ExampleTestWithConnectOptions = `
+ using System;
+ using System.Threading.Tasks;
+ using Microsoft.Playwright;
+ using Microsoft.Playwright.MSTest;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ namespace Playwright.TestingHarnessTest.MSTest;
+
+ [TestClass]
+ public class : PageTest
+ {
+ [TestMethod]
+ public async Task Test()
+ {
+ await Page.GotoAsync("about:blank");
+ }
+ public override async Task<(string, BrowserTypeConnectOptions)?> ConnectOptionsAsync()
+ {
+ return ("http://127.0.0.1:1234", null);
+ }
+ }`;
+
+ test('should fail when the server is not reachable', async ({ runTest }) => {
+ const result = await runTest({
+ 'ExampleTests.cs': ExampleTestWithConnectOptions,
+ }, 'dotnet test');
+ expect(result.passed).toBe(0);
+ expect(result.failed).toBe(1);
+ expect(result.total).toBe(1);
+ expect(result.rawStdout).toContain('connect ECONNREFUSED 127.0.0.1:1234')
+ });
+
+ test('should pass when the server is reachable', async ({ runTest, launchServer }) => {
+ await launchServer({ port: 1234 });
+ const result = await runTest({
+ 'ExampleTests.cs': ExampleTestWithConnectOptions,
+ }, 'dotnet test');
+ expect(result.passed).toBe(1);
+ expect(result.failed).toBe(0);
+ expect(result.total).toBe(1);
+ });
+});
diff --git a/src/Playwright.sln b/src/Playwright.sln
index ea7bf3258..2c6dabd1c 100644
--- a/src/Playwright.sln
+++ b/src/Playwright.sln
@@ -1,4 +1,5 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+
+Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31516.353
MinimumVisualStudioVersion = 10.0.40219.1
@@ -36,6 +37,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Playwright.Xunit", "Playwri
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Playwright.Xunit.v3", "Playwright.Xunit.v3\Playwright.Xunit.v3.csproj", "{6CFF37A8-7C6B-4203-9BF7-3A83752653E8}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Playwright.MSTest.v4", "Playwright.MSTest.v4\Playwright.MSTest.v4.csproj", "{391F8C08-8C76-4D26-BBCF-8A3E00252075}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -86,6 +89,10 @@ Global
{6CFF37A8-7C6B-4203-9BF7-3A83752653E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6CFF37A8-7C6B-4203-9BF7-3A83752653E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6CFF37A8-7C6B-4203-9BF7-3A83752653E8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {391F8C08-8C76-4D26-BBCF-8A3E00252075}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {391F8C08-8C76-4D26-BBCF-8A3E00252075}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {391F8C08-8C76-4D26-BBCF-8A3E00252075}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {391F8C08-8C76-4D26-BBCF-8A3E00252075}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/Playwright/Core/AssertionsBase.cs b/src/Playwright/Core/AssertionsBase.cs
index e57e1a191..22ed2b791 100644
--- a/src/Playwright/Core/AssertionsBase.cs
+++ b/src/Playwright/Core/AssertionsBase.cs
@@ -33,6 +33,7 @@
using Microsoft.Playwright.Transport.Protocol;
[assembly: InternalsVisibleTo("Microsoft.Playwright.MSTest, PublicKey=0024000004800000940000000602000000240000525341310004000001000100059a04ca5ca77c9b4eb2addd1afe3f8464b20ee6aefe73b8c23c0e6ca278d1a378b33382e7e18d4aa8300dd22d81f146e528d88368f73a288e5b8157da9710fe6f9fa9911fb786193f983408c5ebae0b1ba5d1d00111af2816f5db55871db03d7536f4a7a6c5152d630c1e1886b1a0fb68ba5e7f64a7f24ac372090889be2ffb")]
+[assembly: InternalsVisibleTo("Microsoft.Playwright.MSTest.v4, PublicKey=0024000004800000940000000602000000240000525341310004000001000100059a04ca5ca77c9b4eb2addd1afe3f8464b20ee6aefe73b8c23c0e6ca278d1a378b33382e7e18d4aa8300dd22d81f146e528d88368f73a288e5b8157da9710fe6f9fa9911fb786193f983408c5ebae0b1ba5d1d00111af2816f5db55871db03d7536f4a7a6c5152d630c1e1886b1a0fb68ba5e7f64a7f24ac372090889be2ffb")]
[assembly: InternalsVisibleTo("Microsoft.Playwright.NUnit, PublicKey=0024000004800000940000000602000000240000525341310004000001000100059a04ca5ca77c9b4eb2addd1afe3f8464b20ee6aefe73b8c23c0e6ca278d1a378b33382e7e18d4aa8300dd22d81f146e528d88368f73a288e5b8157da9710fe6f9fa9911fb786193f983408c5ebae0b1ba5d1d00111af2816f5db55871db03d7536f4a7a6c5152d630c1e1886b1a0fb68ba5e7f64a7f24ac372090889be2ffb")]
[assembly: InternalsVisibleTo("Microsoft.Playwright.Xunit, PublicKey=0024000004800000940000000602000000240000525341310004000001000100059a04ca5ca77c9b4eb2addd1afe3f8464b20ee6aefe73b8c23c0e6ca278d1a378b33382e7e18d4aa8300dd22d81f146e528d88368f73a288e5b8157da9710fe6f9fa9911fb786193f983408c5ebae0b1ba5d1d00111af2816f5db55871db03d7536f4a7a6c5152d630c1e1886b1a0fb68ba5e7f64a7f24ac372090889be2ffb")]
[assembly: InternalsVisibleTo("Microsoft.Playwright.Xunit.v3, PublicKey=0024000004800000940000000602000000240000525341310004000001000100059a04ca5ca77c9b4eb2addd1afe3f8464b20ee6aefe73b8c23c0e6ca278d1a378b33382e7e18d4aa8300dd22d81f146e528d88368f73a288e5b8157da9710fe6f9fa9911fb786193f983408c5ebae0b1ba5d1d00111af2816f5db55871db03d7536f4a7a6c5152d630c1e1886b1a0fb68ba5e7f64a7f24ac372090889be2ffb")]