diff --git a/.github/workflows/code-style.yml b/.github/workflows/code-style.yml index 5e879ff4dc..269e5c1bfa 100644 --- a/.github/workflows/code-style.yml +++ b/.github/workflows/code-style.yml @@ -8,20 +8,21 @@ on: branches: - main -jobs: - build: - - runs-on: windows-latest +env: + DOTNET_VERSION: '10.0.x' +jobs: + style: + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + - name: Check formatting + run: dotnet format whitespace ./src/PlaywrightSharp.sln --verify-no-changes && dotnet format style ./src/PlaywrightSharp.sln --verify-no-changes - name: We shouldn't mention puppeteer run: | chmod +x ./.github/workflows/no-puppeteer.sh ./.github/workflows/no-puppeteer.sh - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.100 - - name: Check formatting - run: dotnet tool update dotnet-format --tool-path ./dotnet-format/ && ./dotnet-format/dotnet-format -f ./src/ --check -v:diag diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 58f8bb8d22..0000000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Docfx - -on: - release: - types: [published] - workflow_dispatch: - -jobs: - docs: - name: generate docs - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.100 - - name: Extract Metadata - uses: nikeee/docfx-action@v1.0.0 - with: - args: metadata docfx_project/docfx.json - - name: Build Documentation - uses: nikeee/docfx-action@v1.0.0 - with: - args: build docfx_project/docfx.json -o docs - - name: Deploy 🚀 - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/_site diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml new file mode 100644 index 0000000000..53d821c3e5 --- /dev/null +++ b/.github/workflows/dotnet.yml @@ -0,0 +1,123 @@ +name: build + +on: + workflow_dispatch: + push: + branches: + - main + - release-* + merge_group: + pull_request: + paths: + - '**.yml' + - '**.cs' + - '**.json' + - '**.csproj' + - '**.runsettings' + +env: + DOTNET_VERSION: '10.0.x' + +jobs: + build: + name: ${{ matrix.browser }}-${{ matrix.mode }}-${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + browser: chromium + mode: headless + - os: ubuntu-latest + browser: chromium + mode: headful + - os: ubuntu-latest + browser: firefox + mode: headless + - os: ubuntu-latest + browser: firefox + mode: headful + - os: windows-latest + browser: chromium + mode: headless + - os: windows-latest + browser: chromium + mode: headful + - os: windows-latest + browser: firefox + mode: headless + - os: windows-latest + browser: firefox + mode: headful + steps: + - uses: actions/checkout@v3 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + - name: Install system dependencies (Linux) + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y libgbm-dev xvfb libdbus-glib-1-2 + npx playwright install-deps + - name: Create HTTPS certificate (Linux) + if: matrix.os == 'ubuntu-latest' + run: | + mkdir -p src/PlaywrightSharp.TestServer + dotnet dev-certs https --clean + dotnet dev-certs https -ep src/PlaywrightSharp.TestServer/testCert.cer + sudo openssl x509 -inform der -in src/PlaywrightSharp.TestServer/testCert.cer -out /usr/local/share/ca-certificates/testCert.crt -outform pem + sudo update-ca-certificates + - name: Create HTTPS certificate (Windows) + if: matrix.os == 'windows-latest' + shell: pwsh + run: | + dotnet dev-certs https --clean + dotnet dev-certs https -ep src/PlaywrightSharp.TestServer/testCert.cer + - name: Check formatting + if: ${{ matrix.os == 'ubuntu-latest' && matrix.browser == 'chromium' && matrix.mode == 'headless' }} + run: dotnet format whitespace ./src/PlaywrightSharp.sln --verify-no-changes && dotnet format style ./src/PlaywrightSharp.sln --verify-no-changes + - name: Check no puppeteer references + if: ${{ matrix.os == 'ubuntu-latest' && matrix.browser == 'chromium' && matrix.mode == 'headless' }} + run: | + chmod +x ./.github/workflows/no-puppeteer.sh + ./.github/workflows/no-puppeteer.sh + - name: Download drivers + run: dotnet run --project ./src/tools/PlaywrightSharp.Tooling/PlaywrightSharp.Tooling.csproj -- download-drivers --basepath . + - name: Patch driver browser revisions + shell: bash + run: | + # The -next driver has placeholder Firefox rev 1234 (no CDN builds). + # Use release 1.10.0 revisions: firefox=1238, webkit=1446. + find src/PlaywrightSharp/Drivers -name browsers.json -exec sed -i.bak \ + -e 's/"revision": "1234"/"revision": "1238"/' \ + -e 's/"revision": "1443"/"revision": "1446"/' {} + + - name: Build + run: dotnet build ./src/PlaywrightSharp.sln + - name: Disable AppArmor (Linux) + if: matrix.os == 'ubuntu-latest' + run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns + - name: Test (Linux headless) + if: ${{ matrix.os == 'ubuntu-latest' && matrix.mode == 'headless' }} + env: + PRODUCT: ${{ matrix.browser }} + HEADLESS: true + run: | + dotnet test ./src/PlaywrightSharp.Tests/PlaywrightSharp.Tests.csproj --no-build -f net10.0 -s src/PlaywrightSharp.Tests/test.runsettings + - name: Test (Linux headful) + if: ${{ matrix.os == 'ubuntu-latest' && matrix.mode == 'headful' }} + env: + PRODUCT: ${{ matrix.browser }} + HEADLESS: false + run: | + xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- \ + dotnet test ./src/PlaywrightSharp.Tests/PlaywrightSharp.Tests.csproj --no-build -f net10.0 -s src/PlaywrightSharp.Tests/test.runsettings + - name: Test (Windows) + if: matrix.os == 'windows-latest' + env: + PRODUCT: ${{ matrix.browser }} + HEADLESS: ${{ matrix.mode == 'headless' && 'true' || 'false' }} + run: | + dotnet test ./src/PlaywrightSharp.Tests/PlaywrightSharp.Tests.csproj --no-build -f net10.0 -s src/PlaywrightSharp.Tests/test.runsettings diff --git a/.github/workflows/nuget-package-tests.yml b/.github/workflows/nuget-package-tests.yml deleted file mode 100644 index e59e675076..0000000000 --- a/.github/workflows/nuget-package-tests.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: Tests Nuget Packages - -on: - push: - branches: - - main - pull_request: - branches: - - main - -jobs: - test-nuget-packages: - name: Nuget Tests on ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [windows-latest, ubuntu-latest, macos-latest] - steps: - - uses: actions/checkout@v2 - - name: Setup .NET Core 5 (On Mac) - if: ${{ matrix.os == 'macos-latest' }} - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.100 - env: - DOTNET_INSTALL_DIR: /users/runner/alternate/dotnet - - name: Setup .NET Core 5 (Not on mac) - if: ${{ matrix.os != 'macos-latest' }} - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.100 - - name: Cache drivers - uses: actions/cache@v2 - with: - path: ./src/Playwright/runtimes/ - key: ${{ hashFiles('./src/Common/PackageInfo.props') }} - - name: Download Drivers - run: dotnet run -p ./src/tools/PlaywrightSharp.Tooling/PlaywrightSharp.Tooling.csproj -- download-drivers --basepath . - - name: Build Project - run: dotnet build ./src/Playwright/Playwright.csproj -c Debug - - name: Delete browsers on Mac - if: matrix.os == 'macos-latest' - run: rm -r ~/Library/Caches/ms-playwright - - name: Delete browsers on Linux - if: ${{ matrix.os == 'ubuntu-latest' }} - run: rm -r ~/.cache/ms-playwright - - name: Delete browsers on windows - if: matrix.os == 'windows-latest' - run: Remove-Item -path $env:USERPROFILE\AppData\Local\ms-playwright -recurse - - name: Run Tests - run: dotnet test ./src/Playwright.LocalNugetTest/Playwright.LocalNugetTest.csproj diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml deleted file mode 100644 index f16a59994d..0000000000 --- a/.github/workflows/nuget.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Nuget - -on: - release: - types: [published] - workflow_dispatch: - -jobs: - docs: - name: Push to nuget - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.100 - - name: Download Drivers - run: dotnet run -p ./src/tools/PlaywrightSharp.Tooling/PlaywrightSharp.Tooling.csproj -- download-drivers --basepath . - - name: Publish Playwright Sharp - id: publish_nuget_playwright_sharp - uses: rohith/publish-nuget@v2 - with: - NUGET_KEY: ${{secrets.NUGET_API_KEY}} - PROJECT_FILE_PATH: src/PlaywrightSharp/PlaywrightSharp.csproj - VERSION_FILE_PATH: src/Common/PackageInfo.props - VERSION_REGEX: ^\s*(.*)<\/PackageVersion>\s*$ - INCLUDE_SYMBOLS: false - TAG_COMMIT: false - - name: Publish Playwright Sharp Tools - id: publish_nuget_playwright_sharp_tools - uses: rohith/publish-nuget@v2 - with: - NUGET_KEY: ${{secrets.NUGET_API_KEY}} - PROJECT_FILE_PATH: src/tools/PlaywrightSharpTool/PlaywrightSharpTool.csproj - VERSION_FILE_PATH: src/Common/PackageInfo.props - VERSION_REGEX: ^\s*(.*)<\/PackageVersion>\s*$ - INCLUDE_SYMBOLS: false - TAG_COMMIT: false diff --git a/.github/workflows/publish-nuget.yml b/.github/workflows/publish-nuget.yml new file mode 100644 index 0000000000..b175bb1079 --- /dev/null +++ b/.github/workflows/publish-nuget.yml @@ -0,0 +1,25 @@ +name: Publish NuGet Package + +on: + push: + tags: + - 'v*' + +env: + DOTNET_VERSION: '10.0.x' + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + - name: Build Release + run: dotnet build ./src/PlaywrightSharp.sln -c Release + - name: Pack + run: dotnet pack ./src/PlaywrightSharp/PlaywrightSharp.csproj -c Release --no-build -o ./nupkgs + - name: Push to NuGet + run: dotnet nuget push ./nupkgs/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml deleted file mode 100644 index 82b9089c86..0000000000 --- a/.github/workflows/tests.yml +++ /dev/null @@ -1,126 +0,0 @@ -name: Tests - -on: - push: - branches: - - main - - release-* - pull_request: - branches: - - main - - release-* - -jobs: - test_net5: - name: ${{ matrix.product }} on ${{ matrix.os }} using .NET 5 - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - product: [CHROMIUM, FIREFOX, WEBKIT] - os: [windows-latest, ubuntu-latest, macos-latest] - steps: - - name: Install Media Pack - if: ${{ matrix.os == 'windows-latest' }} - shell: powershell - run: Install-WindowsFeature Server-Media-Foundation - - uses: actions/checkout@v2 - - uses: microsoft/playwright-github-action@v1 - - name: Cache drivers - uses: actions/cache@v2 - with: - path: ./src/Playwright/runtimes/ - key: ${{ hashFiles('./src/Common/PackageInfo.props') }} - - name: Setup .NET Core (On Mac) - if: ${{ matrix.os == 'macos-latest' }} - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.100 - env: - DOTNET_INSTALL_DIR: /users/runner/alternate/dotnet - - name: Setup .NET Core (Not on mac) - if: ${{ matrix.os != 'macos-latest' }} - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.100 - - name: Create Certificate - run: | - dotnet dev-certs https --clean - dotnet dev-certs https -ep src/Playwright.Tests.TestServer/testCert.cer - - name: Clean - run: dotnet clean ./src/Playwright.sln --configuration Debug && dotnet nuget locals all --clear - - name: Download Drivers - run: dotnet run -p ./src/tools/PlaywrightSharp.Tooling/PlaywrightSharp.Tooling.csproj -- download-drivers --basepath . - - name: Run tests (!Linux) - if: ${{ matrix.os != 'ubuntu-latest' }} - env: - PRODUCT: ${{ matrix.product }} - run: | - dotnet test ./src/Playwright.Tests/Playwright.Tests.csproj -c Debug -f net5.0 --logger "trx;LogFileName=TestResults.xml" - - name: Run tests (Linux) - if: ${{ matrix.os == 'ubuntu-latest' }} - env: - PRODUCT: ${{ matrix.product }} - run: | - xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash -c "ulimit -c unlimited && dotnet test ./src/Playwright.Tests/Playwright.Tests.csproj -c Debug -f net5.0 --logger \"trx\"" - test_net31: - name: Chromium on Windows using .NET 3.1 - runs-on: windows-latest - strategy: - fail-fast: false - steps: - - name: Install Media Pack - if: ${{ matrix.os == 'windows-latest' }} - shell: powershell - run: Install-WindowsFeature Server-Media-Foundation - - uses: actions/checkout@v2 - - uses: microsoft/playwright-github-action@v1 - - name: Cache drivers - uses: actions/cache@v2 - with: - path: ./src/Playwright/runtimes/ - key: ${{ hashFiles('./src/Common/PackageInfo.props') }} - - name: Setup .NET Core (On Mac) - if: ${{ matrix.os == 'macos-latest' }} - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 3.1.100 - env: - DOTNET_INSTALL_DIR: /users/runner/alternate/dotnet - - name: Setup .NET Core (Not on mac) - if: ${{ matrix.os != 'macos-latest' }} - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 3.1.100 - - name: Create Certificate - run: | - dotnet dev-certs https --clean - dotnet dev-certs https -ep src/Playwright.Tests.TestServer/testCert.cer - - name: Setup .NET Core 5 (On Mac if needed) - if: ${{ matrix.os == 'macos-latest' }} - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.100 - env: - DOTNET_INSTALL_DIR: /users/runner/alternate/dotnet - - name: Setup .NET Core 5 (Not on mac if needed) - if: ${{ matrix.os != 'macos-latest' }} - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.100 - - name: Clean - run: dotnet clean ./src/Playwright.sln --configuration Debug && dotnet nuget locals all --clear - - name: Download Drivers - run: dotnet run -p ./src/tools/PlaywrightSharp.Tooling/PlaywrightSharp.Tooling.csproj -- download-drivers --basepath . - - name: Run tests (!Linux) - if: ${{ matrix.os != 'ubuntu-latest' }} - env: - PRODUCT: CHROMIUM - run: | - dotnet test ./src/Playwright.Tests/Playwright.Tests.csproj -c Debug -f netcoreapp3.1 --logger "trx;LogFileName=TestResults.xml" - - name: Run tests (Linux) - if: ${{ matrix.os == 'ubuntu-latest' }} - env: - PRODUCT: CHROMIUM - run: | - xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash -c "ulimit -c unlimited && dotnet test ./src/Playwright.Tests/Playwright.Tests.csproj -c Debug -f netcoreapp3.1 --logger \"trx\"" diff --git a/src/Playwright.Tests/BaseTests/PlaywrightSharpBaseTest.cs b/src/Playwright.Tests/BaseTests/PlaywrightSharpBaseTest.cs deleted file mode 100644 index b927f3a7d0..0000000000 --- a/src/Playwright.Tests/BaseTests/PlaywrightSharpBaseTest.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.IO; -using System.Reflection; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Microsoft.Playwright; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Helpers; -using Microsoft.Playwright.Tests.TestServer; -using Microsoft.Playwright.Transport.Channels; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests.BaseTests -{ - /// - /// This base tests setup logging and http servers - /// - public class PlaywrightSharpBaseTest : IDisposable - { - private readonly XunitLoggerProvider _loggerProvider; - private readonly ILogger _httpLogger; - - internal IPlaywright Playwright => PlaywrightSharpBrowserLoaderFixture.Playwright; - internal string BaseDirectory { get; set; } - internal IBrowserType BrowserType => Playwright[TestConstants.Product]; - - internal SimpleServer Server => PlaywrightSharpLoader.Server; - internal SimpleServer HttpsServer => PlaywrightSharpLoader.HttpsServer; - - internal PlaywrightSharpBaseTest(ITestOutputHelper output) - { - BaseDirectory = Path.Combine(Directory.GetCurrentDirectory(), "workspace"); - var dirInfo = new DirectoryInfo(BaseDirectory); - - if (!dirInfo.Exists) - { - dirInfo.Create(); - } - - Initialize(); - - _loggerProvider = new XunitLoggerProvider(output); - _httpLogger = TestConstants.LoggerFactory.CreateLogger(); - TestConstants.LoggerFactory.AddProvider(_loggerProvider); - Server.RequestReceived += Server_RequestReceived; - HttpsServer.RequestReceived += Server_RequestReceived; - - output.WriteLine($"Running {GetDisplayName(output)}"); - } - - private void Server_RequestReceived(object sender, RequestReceivedEventArgs e) - { - _httpLogger.LogInformation($"Incoming request: {e.Request.Path}"); - } - - private static string GetDisplayName(ITestOutputHelper output) - { - var type = output.GetType(); - var testMember = type.GetField("test", BindingFlags.Instance | BindingFlags.NonPublic); - var test = (ITest)testMember.GetValue(output); - return test.DisplayName; - } - - internal void Initialize() - { - Server.Reset(); - HttpsServer.Reset(); - } - - /// - public virtual void Dispose() - { - Server.RequestReceived -= Server_RequestReceived; - HttpsServer.RequestReceived -= Server_RequestReceived; - _loggerProvider.Dispose(); - } - } -} diff --git a/src/Playwright.Tests/BaseTests/PlaywrightSharpBrowserBaseTest.cs b/src/Playwright.Tests/BaseTests/PlaywrightSharpBrowserBaseTest.cs deleted file mode 100644 index 1132fd3668..0000000000 --- a/src/Playwright.Tests/BaseTests/PlaywrightSharpBrowserBaseTest.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests.BaseTests -{ - /// - /// Based on , this base class also creates a new Browser - /// - public class PlaywrightSharpBrowserBaseTest : PlaywrightSharpBaseTest - { - internal IBrowser Browser => PlaywrightSharpBrowserLoaderFixture.Browser; - - internal PlaywrightSharpBrowserBaseTest(ITestOutputHelper output) : base(output) - { - } - } -} diff --git a/src/Playwright.Tests/BaseTests/PlaywrightSharpBrowserContextBaseTest.cs b/src/Playwright.Tests/BaseTests/PlaywrightSharpBrowserContextBaseTest.cs deleted file mode 100644 index 554a461c24..0000000000 --- a/src/Playwright.Tests/BaseTests/PlaywrightSharpBrowserContextBaseTest.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.IO; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests.BaseTests -{ - /// - /// Based on , this calss creates a new - /// - public class PlaywrightSharpBrowserContextBaseTest : PlaywrightSharpBrowserBaseTest, IAsyncLifetime - { - internal PlaywrightSharpBrowserContextBaseTest(ITestOutputHelper output) : base(output) - { - } - - internal IBrowserContext Context { get; set; } - - /// - public virtual async Task DisposeAsync() - { - await Context.CloseAsync(); - } - - /// - public virtual async Task InitializeAsync() - { - Context = await Browser.NewContextAsync(); - Context.DefaultTimeout = TestConstants.DefaultPuppeteerTimeout; - } - } -} diff --git a/src/Playwright.Tests/BaseTests/PlaywrightSharpBrowserLoaderCollection.cs b/src/Playwright.Tests/BaseTests/PlaywrightSharpBrowserLoaderCollection.cs deleted file mode 100644 index 13fd06d05b..0000000000 --- a/src/Playwright.Tests/BaseTests/PlaywrightSharpBrowserLoaderCollection.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Xunit; - -namespace Microsoft.Playwright.Tests.BaseTests -{ - /// This class has no code, and is never created. Its purpose is simply - /// to be the place to apply [CollectionDefinition] and all the ICollectionFixture interfaces. - /// Recipe from https://xunit.github.io/docs/shared-context.html#class-fixture - [CollectionDefinition(TestConstants.TestFixtureBrowserCollectionName, DisableParallelization = true)] - public class PlaywrightSharpBrowserLoaderCollection : ICollectionFixture - { - } -} diff --git a/src/Playwright.Tests/BaseTests/PlaywrightSharpBrowserLoaderFixture.cs b/src/Playwright.Tests/BaseTests/PlaywrightSharpBrowserLoaderFixture.cs deleted file mode 100644 index 5c94e810c8..0000000000 --- a/src/Playwright.Tests/BaseTests/PlaywrightSharpBrowserLoaderFixture.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.Playwright.Tests.BaseTests -{ - /// - /// This class setup a single browser instance for tests. - /// - public class PlaywrightSharpBrowserLoaderFixture : IAsyncLifetime - { - internal static IPlaywright Playwright { get; private set; } - - internal static IBrowser Browser { get; private set; } - - /// - public Task InitializeAsync() => LaunchBrowserAsync(); - - /// - public Task DisposeAsync() => ShutDownAsync(); - - private static async Task LaunchBrowserAsync() - { - try - { - Playwright = await Microsoft.Playwright.Playwright.CreateAsync(TestConstants.LoggerFactory, debug: "pw*"); - Browser = await Playwright[TestConstants.Product].LaunchDefaultAsync(); - } - catch (Exception ex) - { - Console.WriteLine(ex); - throw new Exception("Launch failed", ex); - } - } - - internal static async Task ShutDownAsync() - { - try - { - await Browser.CloseAsync(); - Playwright.Dispose(); - } - catch (Exception ex) - { - Console.WriteLine(ex); - throw new Exception("Shutdown failed", ex); - } - } - - internal static async Task RestartAsync() - { - await Browser.CloseAsync(); - await LaunchBrowserAsync(); - } - } -} diff --git a/src/Playwright.Tests/BaseTests/PlaywrightSharpLoader.cs b/src/Playwright.Tests/BaseTests/PlaywrightSharpLoader.cs deleted file mode 100644 index 796847aa03..0000000000 --- a/src/Playwright.Tests/BaseTests/PlaywrightSharpLoader.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Playwright.Tests.TestServer; - -namespace Microsoft.Playwright.Tests.BaseTests -{ - /// - /// This class will build all http servers and download browsers - /// - public class PlaywrightSharpLoader - { - internal static SimpleServer Server { get; private set; } - internal static SimpleServer HttpsServer { get; private set; } - - internal static async Task SetupAsync() - { - Server = SimpleServer.Create(TestConstants.Port, TestUtils.FindParentDirectory("Playwright.Tests.TestServer")); - HttpsServer = SimpleServer.CreateHttps(TestConstants.HttpsPort, TestUtils.FindParentDirectory("Playwright.Tests.TestServer")); - - var serverStart = Server.StartAsync(); - var httpsServerStart = HttpsServer.StartAsync(); - - await Task.WhenAll(serverStart, httpsServerStart); - } - - internal static Task TeardownAsync() => Task.WhenAll(Server.StopAsync(), HttpsServer.StopAsync()); - } -} diff --git a/src/Playwright.Tests/BaseTests/PlaywrightXunitTestAssemblyRunner.cs b/src/Playwright.Tests/BaseTests/PlaywrightXunitTestAssemblyRunner.cs deleted file mode 100644 index f6bad556d8..0000000000 --- a/src/Playwright.Tests/BaseTests/PlaywrightXunitTestAssemblyRunner.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; -using Xunit.Sdk; - -namespace Microsoft.Playwright.Tests.BaseTests -{ - /// - public class PlaywrightXunitTestAssemblyRunner : XunitTestAssemblyRunner - { - /// - public PlaywrightXunitTestAssemblyRunner(ITestAssembly testAssembly, IEnumerable testCases, IMessageSink diagnosticMessageSink, IMessageSink executionMessageSink, ITestFrameworkExecutionOptions executionOptions) : base(testAssembly, testCases, diagnosticMessageSink, executionMessageSink, executionOptions) - { - } - - /// - protected override async Task AfterTestAssemblyStartingAsync() - { - await base.AfterTestAssemblyStartingAsync(); - await PlaywrightSharpLoader.SetupAsync(); - } - - /// - protected override async Task BeforeTestAssemblyFinishedAsync() - { - await base.BeforeTestAssemblyFinishedAsync(); - await PlaywrightSharpLoader.TeardownAsync(); - } - } -} diff --git a/src/Playwright.Tests/BaseTests/PlaywrightXunitTestFramework.cs b/src/Playwright.Tests/BaseTests/PlaywrightXunitTestFramework.cs deleted file mode 100644 index da80650bf5..0000000000 --- a/src/Playwright.Tests/BaseTests/PlaywrightXunitTestFramework.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Reflection; -using Xunit; -using Xunit.Abstractions; -using Xunit.Sdk; - -[assembly: TestFramework("Microsoft.Playwright.Tests.BaseTests.PlaywrightXunitTestFramework", "Microsoft.Playwright.Tests")] -[assembly: CollectionBehavior(DisableTestParallelization = true)] - -namespace Microsoft.Playwright.Tests.BaseTests -{ - /// - public class PlaywrightXunitTestFramework : XunitTestFramework - { - /// - public PlaywrightXunitTestFramework(IMessageSink messageSink) : base(messageSink) - { - } - - /// - protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName) - => new PlaywrightXunitTestFrameworkExecutor(assemblyName, SourceInformationProvider, DiagnosticMessageSink); - } -} diff --git a/src/Playwright.Tests/BaseTests/PlaywrightXunitTestFrameworkExecutor.cs b/src/Playwright.Tests/BaseTests/PlaywrightXunitTestFrameworkExecutor.cs deleted file mode 100644 index 841e629466..0000000000 --- a/src/Playwright.Tests/BaseTests/PlaywrightXunitTestFrameworkExecutor.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; -using System.Reflection; -using Xunit.Abstractions; -using Xunit.Sdk; - -namespace Microsoft.Playwright.Tests.BaseTests -{ - /// - public class PlaywrightXunitTestFrameworkExecutor : XunitTestFrameworkExecutor - { - /// - public PlaywrightXunitTestFrameworkExecutor(AssemblyName assemblyName, ISourceInformationProvider sourceInformationProvider, IMessageSink diagnosticMessageSink) : base(assemblyName, sourceInformationProvider, diagnosticMessageSink) - { - } - - /// - protected override void RunTestCases(IEnumerable testCases, IMessageSink executionMessageSink, ITestFrameworkExecutionOptions executionOptions) - { - using (var assemblyRunner = new PlaywrightXunitTestAssemblyRunner(TestAssembly, testCases, DiagnosticMessageSink, executionMessageSink, executionOptions)) - { - assemblyRunner.RunAsync(); - } - } - } -} diff --git a/src/Playwright.Tests/BrowserContextViewportTests.cs b/src/Playwright.Tests/BrowserContextViewportTests.cs deleted file mode 100644 index b524fb05a5..0000000000 --- a/src/Playwright.Tests/BrowserContextViewportTests.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextViewportTests : PlaywrightSharpPageBaseTest - { - /// - public BrowserContextViewportTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-viewport.spec.ts", "should get the proper default viewport size")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public Task ShouldGetTheProperDefaultViewPortSize() - => TestUtils.VerifyViewportAsync(Page, 1280, 720); - - - [PlaywrightTest("browsercontext-viewport.spec.ts", "should set the proper viewport size")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSetTheProperViewportSize() - { - await TestUtils.VerifyViewportAsync(Page, 1280, 720); - await Page.SetViewportSizeAsync(123, 456); - await TestUtils.VerifyViewportAsync(Page, 123, 456); - } - - [PlaywrightTest("browsercontext-viewport.spec.ts", "should emulate device width")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEmulateDeviceWidth() - { - await TestUtils.VerifyViewportAsync(Page, 1280, 720); - await Page.SetViewportSizeAsync(200, 200); - Assert.Equal(200, await Page.EvaluateAsync("window.innerWidth")); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(min-device-width: 100px)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(min-device-width: 300px)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(max-device-width: 100px)').matches")); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(max-device-width: 300px)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(device-width: 500px)').matches")); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(device-width: 200px)').matches")); - await Page.SetViewportSizeAsync(500, 500); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(min-device-width: 400px)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(min-device-width: 600px)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(max-device-width: 400px)').matches")); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(max-device-width: 600px)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(device-width: 200px)').matches")); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(device-width: 500px)').matches")); - } - - [PlaywrightTest("browsercontext-viewport.spec.ts", "should emulate device height")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEmulateDeviceHeight() - { - await TestUtils.VerifyViewportAsync(Page, 1280, 720); - await Page.SetViewportSizeAsync(200, 200); - Assert.Equal(200, await Page.EvaluateAsync("window.innerWidth")); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(min-device-height: 100px)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(min-device-height: 300px)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(max-device-height: 100px)').matches")); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(max-device-height: 300px)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(device-height: 500px)').matches")); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(device-height: 200px)').matches")); - await Page.SetViewportSizeAsync(500, 500); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(min-device-height: 400px)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(min-device-height: 600px)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(max-device-height: 400px)').matches")); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(max-device-height: 600px)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(device-height: 200px)').matches")); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(device-height: 500px)').matches")); - } - - [PlaywrightTest("browsercontext-viewport.spec.ts", "should not have touch by default")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotHaveTouchByDefault() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); - Assert.False(await Page.EvaluateAsync("'ontouchstart' in window")); - await Page.GoToAsync(TestConstants.ServerUrl + "/detect-touch.html"); - Assert.Equal("NO", await Page.EvaluateAsync("document.body.textContent.trim()")); - } - - [PlaywrightTest("browsercontext-viewport.spec.ts", "should support touch with null viewport")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportTouchWithNullViewport() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions { Viewport = null, HasTouch = true }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); - Assert.True(await page.EvaluateAsync("'ontouchstart' in window")); - } - } -} diff --git a/src/Playwright.Tests/Helpers/XunitLogger.cs b/src/Playwright.Tests/Helpers/XunitLogger.cs deleted file mode 100644 index fbec23c776..0000000000 --- a/src/Playwright.Tests/Helpers/XunitLogger.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using Microsoft.Extensions.Logging; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests.Helpers -{ - internal class XunitLogger : ILogger, IDisposable - { - private readonly ITestOutputHelper _output; - private bool _enabled = true; - - public XunitLogger(ITestOutputHelper output) - { - _output = output; - } - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) - { - if (_enabled) - { - try - { - _output.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}: {state}"); - } - catch { } - } - } - - public bool IsEnabled(LogLevel logLevel) => _enabled; - - public IDisposable BeginScope(TState state) => this; - - public void Dispose() => _enabled = false; - } -} diff --git a/src/Playwright.Tests/Helpers/XunitLoggerProvider.cs b/src/Playwright.Tests/Helpers/XunitLoggerProvider.cs deleted file mode 100644 index 966eb69f27..0000000000 --- a/src/Playwright.Tests/Helpers/XunitLoggerProvider.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using Microsoft.Extensions.Logging; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests.Helpers -{ - internal sealed class XunitLoggerProvider : ILoggerProvider - { - private readonly ITestOutputHelper _helper; - private readonly List _loggers = new List(); - - public void Dispose() - { - foreach (var logger in _loggers) - { - logger.Dispose(); - } - _loggers.Clear(); - } - - public XunitLoggerProvider(ITestOutputHelper helper) - { - _helper = helper; - } - - public ILogger CreateLogger(string categoryName) - { - var logger = new XunitLogger(_helper); - _loggers.Add(logger); - return logger; - } - } -} diff --git a/src/Playwright.Tests/InterceptionTests.cs b/src/Playwright.Tests/InterceptionTests.cs deleted file mode 100644 index 8cfd43555d..0000000000 --- a/src/Playwright.Tests/InterceptionTests.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class GlobTests : PlaywrightSharpPageBaseTest - { - /// - public GlobTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("interception.spec.ts", "should work with glob")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public void ShouldWorkWithGlob() - { - Assert.Matches(StringExtensions.GlobToRegex("**/*.js"), "https://localhost:8080/foo.js"); - Assert.DoesNotMatch(StringExtensions.GlobToRegex("**/*.css"), "https://localhost:8080/foo.js"); - Assert.DoesNotMatch(StringExtensions.GlobToRegex("*.js"), "https://localhost:8080/foo.js"); - Assert.Matches(StringExtensions.GlobToRegex("https://**/*.js"), "https://localhost:8080/foo.js"); - Assert.Matches(StringExtensions.GlobToRegex("http://localhost:8080/simple/path.js"), "http://localhost:8080/simple/path.js"); - Assert.Matches(StringExtensions.GlobToRegex("http://localhost:8080/?imple/path.js"), "http://localhost:8080/Simple/path.js"); - Assert.Matches(StringExtensions.GlobToRegex("**/{a,b}.js"), "https://localhost:8080/a.js"); - Assert.Matches(StringExtensions.GlobToRegex("**/{a,b}.js"), "https://localhost:8080/b.js"); - Assert.DoesNotMatch(StringExtensions.GlobToRegex("**/{a,b}.js"), "https://localhost:8080/c.js"); - - Assert.Matches(StringExtensions.GlobToRegex("**/*.{png,jpg,jpeg}"), "https://localhost:8080/c.jpg"); - Assert.Matches(StringExtensions.GlobToRegex("**/*.{png,jpg,jpeg}"), "https://localhost:8080/c.jpeg"); - Assert.Matches(StringExtensions.GlobToRegex("**/*.{png,jpg,jpeg}"), "https://localhost:8080/c.png"); - Assert.DoesNotMatch(StringExtensions.GlobToRegex("**/*.{png,jpg,jpeg}"), "https://localhost:8080/c.css"); - } - - [PlaywrightTest("interception.spec.ts", "should work with ignoreHTTPSErrors")] - // [Fact(Timeout = TestConstants.DefaultTestTimeout)] - [Fact(Skip = "Fix me #1058")] - public async Task ShouldWorkWitIgnoreHTTPSErrors() - { - await using var browser = await BrowserType.LaunchDefaultAsync(); - var context = await browser.NewContextAsync(new BrowserContextOptions - { - IgnoreHTTPSErrors = true - }); - - var page = await context.NewPageAsync(); - - await page.RouteAsync("**/*", (route) => route.ResumeAsync()); - var response = await page.GoToAsync(TestConstants.HttpsPrefix + "/empty.html"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - - - [PlaywrightTest("interception.spec.ts", "should work with navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithNavigation() - { - var requests = new Dictionary(); - await Page.RouteAsync("**/*", (route) => - { - requests.Add(route.Request.Url.Split('/').Last(), route.Request); - route.ResumeAsync(); - }); - - Server.SetRedirect("/rrredirect", "/frames/one-frame.html"); - await Page.GoToAsync(TestConstants.ServerUrl + "/rrredirect"); - Assert.True(requests["rrredirect"].IsNavigationRequest); - Assert.True(requests["frame.html"].IsNavigationRequest); - Assert.False(requests["script.js"].IsNavigationRequest); - Assert.False(requests["style.css"].IsNavigationRequest); - } - - [PlaywrightTest("interception.spec.ts", "should work with regular expression passed from a different context")] - [Fact(Skip = "We don't need to test Regex contexts")] - public void ShouldWorkWithRegularExpressionPassedFromADifferentContext() - { - } - - [PlaywrightTest("interception.spec.ts", "should intercept after a service worker")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldInterceptAfterAServiceWorker() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/serviceworkers/fetchdummy/sw.html"); - await Page.EvaluateAsync("() => window.activationPromise"); - - string swResponse = await Page.EvaluateAsync("() => fetchDummy('foo')"); - Assert.Equal("responseFromServiceWorker:foo", swResponse); - - await Page.RouteAsync("**/foo", (route) => - { - int slash = route.Request.Url.LastIndexOf("/"); - string name = route.Request.Url.Substring(slash + 1); - - route.FulfillAsync(HttpStatusCode.OK, "responseFromInterception:" + name, contentType: "text/css"); - }); - - string swResponse2 = await Page.EvaluateAsync("() => fetchDummy('foo')"); - Assert.Equal("responseFromServiceWorker:foo", swResponse2); - - string nonInterceptedResponse = await Page.EvaluateAsync("() => fetchDummy('passthrough')"); - Assert.Equal("FAILURE: Not Found", nonInterceptedResponse); - } - } -} diff --git a/src/Playwright.Tests/JSHandleToStringTests.cs b/src/Playwright.Tests/JSHandleToStringTests.cs deleted file mode 100644 index 570551d130..0000000000 --- a/src/Playwright.Tests/JSHandleToStringTests.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class JSHandleToStringTests : PlaywrightSharpPageBaseTest - { - /// - public JSHandleToStringTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("jshandle-to-string.spec.ts", "should work for primitives")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForPrimitives() - { - var numberHandle = await Page.EvaluateHandleAsync("() => 2"); - Assert.Equal("JSHandle@2", numberHandle.ToString()); - var stringHandle = await Page.EvaluateHandleAsync("() => 'a'"); - Assert.Equal("JSHandle@a", stringHandle.ToString()); - } - - [PlaywrightTest("jshandle-to-string.spec.ts", "should work for complicated objects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForComplicatedObjects() - { - var aHandle = await Page.EvaluateHandleAsync("() => window"); - Assert.Equal("JSHandle@object", aHandle.ToString()); - } - - [PlaywrightTest("jshandle-to-string.spec.ts", "should work for promises")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForPromises() - { - // wrap the promise in an object, otherwise we will await. - var wrapperHandle = await Page.EvaluateHandleAsync("() => ({ b: Promise.resolve(123)})"); - var bHandle = await wrapperHandle.GetPropertyAsync("b"); - Assert.Equal("JSHandle@promise", bHandle.ToString()); - } - - [PlaywrightTest("jshandle-to-string.spec.ts", "should work with different subtypes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithDifferentSubtypes() - { - Assert.Equal("JSHandle@function", (await Page.EvaluateHandleAsync("(function(){})")).ToString()); - Assert.Equal("JSHandle@12", (await Page.EvaluateHandleAsync("12")).ToString()); - Assert.Equal("JSHandle@true", (await Page.EvaluateHandleAsync("true")).ToString()); - Assert.Equal("JSHandle@undefined", (await Page.EvaluateHandleAsync("undefined")).ToString()); - Assert.Equal("JSHandle@foo", (await Page.EvaluateHandleAsync("\"foo\"")).ToString()); - Assert.Equal("JSHandle@symbol", (await Page.EvaluateHandleAsync("Symbol()")).ToString()); - Assert.Equal("JSHandle@map", (await Page.EvaluateHandleAsync("new Map()")).ToString()); - Assert.Equal("JSHandle@set", (await Page.EvaluateHandleAsync("new Set()")).ToString()); - Assert.Equal("JSHandle@array", (await Page.EvaluateHandleAsync("[]")).ToString()); - Assert.Equal("JSHandle@null", (await Page.EvaluateHandleAsync("null")).ToString()); - Assert.Equal("JSHandle@regexp", (await Page.EvaluateHandleAsync("/foo/")).ToString()); - // We get the preview faster than in node. - Assert.Contains((await Page.EvaluateHandleAsync("document.body")).ToString(), new[] { "JSHandle@node", "JSHandle@" }); - Assert.Equal("JSHandle@date", (await Page.EvaluateHandleAsync("new Date()")).ToString()); - Assert.Equal("JSHandle@weakmap", (await Page.EvaluateHandleAsync("new WeakMap()")).ToString()); - Assert.Equal("JSHandle@weakset", (await Page.EvaluateHandleAsync("new WeakSet()")).ToString()); - Assert.Equal("JSHandle@error", (await Page.EvaluateHandleAsync("new Error()")).ToString()); - Assert.Equal(TestConstants.IsWebKit ? "JSHandle@array" : "JSHandle@typedarray", (await Page.EvaluateHandleAsync("new Int32Array()")).ToString()); - Assert.Equal("JSHandle@proxy", (await Page.EvaluateHandleAsync("new Proxy({}, {})")).ToString()); - } - } -} diff --git a/src/Playwright.Tests/LauncherTests.cs b/src/Playwright.Tests/LauncherTests.cs deleted file mode 100644 index 160740b0f2..0000000000 --- a/src/Playwright.Tests/LauncherTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class LauncherTests : PlaywrightSharpBaseTest - { - /// - public LauncherTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("launcher.spec.ts", "should require top-level Errors")] - [Fact(Skip = "We don't need this test. Leaving for tracking purposes")] - public void ShouldRequireTopLevelErrors() { } - - [PlaywrightTest("launcher.spec.ts", "should require top-level DeviceDescriptors")] - [Fact(Skip = "We don't need this test. Leaving for tracking purposes")] - public void ShouldRequireTopLevelDeviceDescriptors() { } - } -} diff --git a/src/Playwright.Tests/LoggerTests.cs b/src/Playwright.Tests/LoggerTests.cs deleted file mode 100644 index 1f05146fb2..0000000000 --- a/src/Playwright.Tests/LoggerTests.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class LoggerTests : PlaywrightSharpBaseTest - { - /// - public LoggerTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("logger.spec.ts", "should log")] - [Fact(Skip = "We don't test CHANNEL")] - public void ShouldLog() - { - } - - [PlaywrightTest("logger.spec.ts", "should log context-level")] - [Fact(Skip = "We don't test CHANNEL")] - public void ShouldLogContextLevel() - { - } - } -} diff --git a/src/Playwright.Tests/PageClickTimeout1Tests.cs b/src/Playwright.Tests/PageClickTimeout1Tests.cs deleted file mode 100644 index 982f952faa..0000000000 --- a/src/Playwright.Tests/PageClickTimeout1Tests.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageClickTimeout1Tests : PlaywrightSharpPageBaseTest - { - /// - public PageClickTimeout1Tests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-click-timeout-1.spec.ts", "should avoid side effects after timeout")] - [Fact(Skip = "Ignore USES_HOOKS")] - public void ShouldAvoidSideEffectsAfterTimeout() - { - } - - [PlaywrightTest("page-click-timeout-1.spec.ts", "should timeout waiting for button to be enabled")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTimeoutWaitingForButtonToBeEnabled() - { - await Page.SetContentAsync(""); - var clickTask = Page.ClickAsync("text=Click target", timeout: 3000); - Assert.Null(await Page.EvaluateAsync("window.__CLICKED")); - - var exception = await Assert.ThrowsAsync(() => clickTask); - - Assert.Contains("Timeout 3000ms exceeded", exception.Message); - Assert.Contains("element is not enabled - waiting", exception.Message); - } - } -} diff --git a/src/Playwright.Tests/PageClickTimeout2Tests.cs b/src/Playwright.Tests/PageClickTimeout2Tests.cs deleted file mode 100644 index b609824aed..0000000000 --- a/src/Playwright.Tests/PageClickTimeout2Tests.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageClickTimeout2Tests : PlaywrightSharpPageBaseTest - { - /// - public PageClickTimeout2Tests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-click-timeout-2.spec.ts", "should timeout waiting for display:none to be gone")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTimeoutWaitingForDisplayNoneToBeGone() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvalOnSelectorAsync("button", "b => b.style.display = 'none'"); - var exception = await Assert.ThrowsAsync(() - => Page.ClickAsync("button", timeout: 5000)); - - Assert.Contains("Timeout 5000ms exceeded", exception.Message); - Assert.Contains("waiting for element to be visible, enabled and stable", exception.Message); - Assert.Contains("element is not visible - waiting", exception.Message); - } - - [PlaywrightTest("page-click-timeout-2.spec.ts", "should timeout waiting for visbility:hidden to be gone")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTimeoutWaitingForVisbilityHiddenToBeGone() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvalOnSelectorAsync("button", "b => b.style.visibility = 'hidden'"); - var clickTask = Page.ClickAsync("button", timeout: 5000); - var exception = await Assert.ThrowsAsync(() - => Page.ClickAsync("button", timeout: 5000)); - - Assert.Contains("Timeout 5000ms exceeded", exception.Message); - Assert.Contains("waiting for element to be visible, enabled and stable", exception.Message); - Assert.Contains("element is not visible - waiting", exception.Message); - } - - } -} diff --git a/src/Playwright.Tests/PageClickTimeout4Tests.cs b/src/Playwright.Tests/PageClickTimeout4Tests.cs deleted file mode 100644 index 91ab6447af..0000000000 --- a/src/Playwright.Tests/PageClickTimeout4Tests.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageClickTimeout4Tests : PlaywrightSharpPageBaseTest - { - /// - public PageClickTimeout4Tests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-click-timeout-4.spec.ts", "should timeout waiting for stable position")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTimeoutWaitingForStablePosition() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvalOnSelectorAsync("button", @"button => { - button.style.transition = 'margin 5s linear 0s'; - button.style.marginLeft = '200px'; - }"); - - var exception = await Assert.ThrowsAsync(() - => Page.ClickAsync("button", timeout: 3000)); - - Assert.Contains("Timeout 3000ms exceeded", exception.Message); - Assert.Contains("waiting for element to be visible, enabled and stable", exception.Message); - Assert.Contains("element is not stable - waiting", exception.Message); - } - } -} diff --git a/src/Playwright.Tests/PageCloseTests.cs b/src/Playwright.Tests/PageCloseTests.cs deleted file mode 100644 index 9c412f6ccb..0000000000 --- a/src/Playwright.Tests/PageCloseTests.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageCloseTests : PlaywrightSharpPageBaseTest - { - /// - public PageCloseTests(ITestOutputHelper output) : base(output) - { - } - - } -} diff --git a/src/Playwright.Tests/PageScrollTests.cs b/src/Playwright.Tests/PageScrollTests.cs deleted file mode 100644 index 32378973e0..0000000000 --- a/src/Playwright.Tests/PageScrollTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageScrollTests : PlaywrightSharpPageBaseTest - { - /// - public PageScrollTests(ITestOutputHelper output) : base(output) - { - } - } -} diff --git a/src/Playwright.Tests/ResourceTimingTests.cs b/src/Playwright.Tests/ResourceTimingTests.cs deleted file mode 100644 index 7c9211e164..0000000000 --- a/src/Playwright.Tests/ResourceTimingTests.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///resource-timing.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ResourceTimingTests : PlaywrightSharpPageBaseTest - { - /// - public ResourceTimingTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("resource-timing.spec.ts", "should work")] - [Fact] - public async Task ShouldWork() - { - var (request, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.RequestFinished), - Page.GoToAsync(TestConstants.EmptyPage)); - - var timing = request.Timing; - Assert.True(timing.DomainLookupStart >= -1); - Assert.True(timing.DomainLookupEnd >= timing.DomainLookupStart); - Assert.True(timing.ConnectStart >= timing.DomainLookupEnd); - Assert.Equal(-1, timing.SecureConnectionStart); - Assert.True(VerifyTimingValue(timing.ConnectEnd, timing.SecureConnectionStart)); - Assert.True(VerifyTimingValue(timing.RequestStart, timing.ConnectEnd)); - Assert.True(timing.ResponseStart > timing.RequestStart); - Assert.True(timing.ResponseEnd >= timing.ResponseStart); - Assert.True(timing.ResponseEnd < 10000); - } - - [PlaywrightTest("resource-timing.spec.ts", "should work for subresource")] - [Fact] - public async Task ShouldWorkForSubresource() - { - var requests = new List(); - - Page.RequestFinished += (_, e) => requests.Add(e); - await Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); - - Assert.Equal(2, requests.Count); - - var timing = requests[1].Timing; - if (TestConstants.IsWebKit && TestConstants.IsWindows) - { - Assert.True(timing.DomainLookupStart >= 0); - Assert.True(timing.DomainLookupEnd >= timing.DomainLookupStart); - Assert.True(timing.ConnectStart >= timing.DomainLookupEnd); - Assert.Equal(-1, timing.SecureConnectionStart); - Assert.True(timing.ConnectEnd > timing.SecureConnectionStart); - } - else - { - Assert.True(timing.DomainLookupStart == 0 || timing.DomainLookupStart == -1); - Assert.Equal(-1, timing.DomainLookupEnd); - Assert.Equal(-1, timing.ConnectStart); - Assert.Equal(-1, timing.SecureConnectionStart); - Assert.Equal(-1, timing.ConnectEnd); - } - - Assert.True(timing.RequestStart >= 0); - Assert.True(timing.ResponseStart >= timing.RequestStart); - Assert.True(timing.ResponseEnd >= timing.ResponseStart); - Assert.True(timing.ResponseEnd < 10000); - } - - [PlaywrightTest("resource-timing.spec.ts", "should work for SSL")] - [Fact(Skip = "Fix me #1058")] - public async Task ShouldWorkForSSL() - { - var page = await Browser.NewPageAsync(ignoreHTTPSErrors: true); - var (request, _) = await TaskUtils.WhenAll( - page.WaitForEventAsync(PageEvent.RequestFinished), - page.GoToAsync(TestConstants.HttpsPrefix + "/empty.html")); - - var timing = request.Timing; - if (!(TestConstants.IsWebKit && TestConstants.IsMacOSX)) - { - Assert.True(timing.DomainLookupStart >= 0); - Assert.True(timing.DomainLookupEnd >= timing.DomainLookupStart); - Assert.True(timing.ConnectStart >= timing.DomainLookupEnd); - Assert.True(timing.SecureConnectionStart >= timing.ConnectStart); - Assert.True(timing.ConnectEnd > timing.SecureConnectionStart); - Assert.True(timing.RequestStart >= timing.ConnectEnd); - } - - Assert.True(timing.ResponseStart > timing.RequestStart); - Assert.True(timing.ResponseEnd >= timing.ResponseStart); - Assert.True(timing.ResponseEnd < 10000); - await page.CloseAsync(); - } - - [PlaywrightTest("resource-timing.spec.ts", "should work for redirect")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task ShouldWorkForRedirect() - { - Server.SetRedirect("/foo.html", "/empty.html"); - var responses = new List(); - - Page.Response += (_, e) => responses.Add(e); - await Page.GoToAsync(TestConstants.ServerUrl + "/foo.html"); - - // This is different on purpose, promises work different in TS. - await responses[1].GetFinishedAsync(); - - Assert.Equal(2, responses.Count); - Assert.Equal(TestConstants.ServerUrl + "/foo.html", responses[0].Url); - Assert.Equal(TestConstants.ServerUrl + "/empty.html", responses[1].Url); - - var timing1 = responses[0].Request.Timing; - Assert.True(timing1.DomainLookupStart >= 0); - Assert.True(timing1.DomainLookupEnd >= timing1.DomainLookupStart); - Assert.True(timing1.ConnectStart >= timing1.DomainLookupEnd); - Assert.Equal(-1, timing1.SecureConnectionStart); - Assert.True(timing1.ConnectEnd > timing1.SecureConnectionStart); - Assert.True(timing1.RequestStart >= timing1.ConnectEnd); - Assert.True(timing1.ResponseStart > timing1.RequestStart); - Assert.True(timing1.ResponseEnd >= timing1.ResponseStart); - Assert.True(timing1.ResponseEnd < 10000); - - var timing2 = responses[1].Request.Timing; - Assert.Equal(-1, timing2.DomainLookupStart); - Assert.Equal(-1, timing2.DomainLookupEnd); - Assert.Equal(-1, timing2.ConnectStart); - Assert.Equal(-1, timing2.SecureConnectionStart); - Assert.Equal(-1, timing2.ConnectEnd); - Assert.True(timing2.RequestStart >= 0); - Assert.True(timing2.ResponseStart >= timing2.RequestStart); - Assert.True(timing2.ResponseEnd >= timing2.ResponseStart); - Assert.True(timing2.ResponseEnd < 10000); - } - - private bool VerifyTimingValue(float value, float previous) => value == -1 || value > 0 && value >= previous; - } -} diff --git a/src/Playwright.Tests/SelectorMiscTests.cs b/src/Playwright.Tests/SelectorMiscTests.cs deleted file mode 100644 index 541ae699f9..0000000000 --- a/src/Playwright.Tests/SelectorMiscTests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class SelectorMiscTests : PlaywrightSharpPageBaseTest - { - /// - public SelectorMiscTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("selectors-misc.spec.ts", "should work for open shadow roots")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForOpenShadowRoots() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/deep-shadow.html"); - Assert.Equal("Hello from root2", await Page.EvalOnSelectorAsync("id=target", "e => e.textContent")); - Assert.Equal("Hello from root1", await Page.EvalOnSelectorAsync("data-testid=foo", "e => e.textContent")); - Assert.Equal(3, await Page.EvalOnSelectorAllAsync("data-testid=foo", "els => els.length")); - Assert.Null(await Page.QuerySelectorAsync("id:light=target")); - Assert.Null(await Page.QuerySelectorAsync("data-testid:light=foo")); - Assert.Empty(await Page.QuerySelectorAllAsync("data-testid:light=foo")); - } - } -} diff --git a/src/Playwright.Tests/SelectorsCssTests.cs b/src/Playwright.Tests/SelectorsCssTests.cs deleted file mode 100644 index 7e6c9228b4..0000000000 --- a/src/Playwright.Tests/SelectorsCssTests.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class SelectorsCssTests : PlaywrightSharpPageBaseTest - { - /// - public SelectorsCssTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("selectors-css.spec.ts", "should work for open shadow roots")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForOpenShadowRoots() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/deep-shadow.html"); - Assert.Equal("Hello from root1", await Page.EvalOnSelectorAsync("css=span", "e => e.textContent")); - Assert.Equal("Hello from root3 #2", await Page.EvalOnSelectorAsync("css =[attr=\"value\\ space\"]", "e => e.textContent")); - Assert.Equal("Hello from root3 #2", await Page.EvalOnSelectorAsync("css =[attr='value\\ \\space']", "e => e.textContent")); - Assert.Equal("Hello from root2", await Page.EvalOnSelectorAsync("css=div div span", "e => e.textContent")); - Assert.Equal("Hello from root3 #2", await Page.EvalOnSelectorAsync("css=div span + span", "e => e.textContent")); - Assert.Equal("Hello from root3 #2", await Page.EvalOnSelectorAsync("css=span + [attr *=\"value\"]", "e => e.textContent")); - Assert.Equal("Hello from root3 #2", await Page.EvalOnSelectorAsync("css=[data-testid=\"foo\"] + [attr*=\"value\"]", "e => e.textContent")); - Assert.Equal("Hello from root2", await Page.EvalOnSelectorAsync("css=#target", "e => e.textContent")); - Assert.Equal("Hello from root2", await Page.EvalOnSelectorAsync("css=div #target", "e => e.textContent")); - Assert.Equal("Hello from root2", await Page.EvalOnSelectorAsync("css=div div #target", "e => e.textContent")); - Assert.Null(await Page.QuerySelectorAsync("css=div div div #target")); - Assert.Equal("Hello from root2", await Page.EvalOnSelectorAsync("css=section > div div span", "e => e.textContent")); - Assert.Equal("Hello from root3 #2", await Page.EvalOnSelectorAsync("css=section > div div span:nth-child(2)", "e => e.textContent")); - Assert.Null(await Page.QuerySelectorAsync("css=section div div div div")); - - var root2 = await Page.QuerySelectorAsync("css=div div"); - Assert.Equal("Hello from root2", await root2.EvalOnSelectorAsync("css=#target", "e => e.textContent")); - Assert.Null(await root2.QuerySelectorAsync("css:light=#target")); - var root2Shadow = (IElementHandle)await root2.EvaluateHandleAsync("r => r.shadowRoot"); - Assert.Equal("Hello from root2", await root2Shadow.EvalOnSelectorAsync("css:light=#target", "e => e.textContent")); - var root3 = (await Page.QuerySelectorAllAsync("css=div div")).ElementAt(1); - Assert.Equal("Hello from root3", await root3.EvalOnSelectorAsync("text=root3", "e => e.textContent")); - Assert.Equal("Hello from root3 #2", await root3.EvalOnSelectorAsync("css=[attr *=\"value\"]", "e => e.textContent")); - Assert.Null(await root3.QuerySelectorAsync("css:light=[attr*=\"value\"]")); - } - - [PlaywrightTest("selectors-css.spec.ts", "should work with > combinator and spaces")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithCombinatorAndSpaces() - { - await Page.SetContentAsync("
"); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"] > span", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"] > span", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"] > span", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"] > span", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"] > span", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"] > span", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"] > span", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"][bar=\"baz\"] > span", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"][bar=\"baz\"] > span", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"][bar=\"baz\"] > span", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"][bar=\"baz\"] > span", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"][bar=\"baz\"] > span", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"][bar=\"baz\"] > span", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div[foo=\"bar\"][bar=\"baz\"] > span", "e => e.outerHTML")); - } - - [PlaywrightTest("selectors-css.spec.ts", "should work with comma separated list")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithCommaSeparatedList() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/deep-shadow.html"); - Assert.Equal(5, await Page.EvalOnSelectorAllAsync("css=span, section #root1", "els => els.length")); - Assert.Equal(5, await Page.EvalOnSelectorAllAsync("css=section #root1, div span", "els => els.length")); - Assert.Equal("root1", await Page.EvalOnSelectorAsync("css=doesnotexist, section #root1", "e => e.id")); - Assert.Equal(1, await Page.EvalOnSelectorAllAsync("css=doesnotexist, section #root1", "els => els.length")); - Assert.Equal(4, await Page.EvalOnSelectorAllAsync("css=span,div span", "els => els.length")); - Assert.Equal(4, await Page.EvalOnSelectorAllAsync("css=span,div span, div div span", "els => els.length")); - Assert.Equal(2, await Page.EvalOnSelectorAllAsync("css=#target,[attr=\"value\\ space\"]", "els => els.length")); - Assert.Equal(4, await Page.EvalOnSelectorAllAsync("css=#target,[data-testid=\"foo\"],[attr=\"value\\ space\"]", "els => els.length")); - Assert.Equal(4, await Page.EvalOnSelectorAllAsync("css=#target,[data-testid=\"foo\"],[attr=\"value\\ space\"],span", "els => els.length")); - } - - [PlaywrightTest("selectors-css.spec.ts", "should keep dom order with comma separated list")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldKeepDomOrderWithCommaSeparatedList() - { - await Page.SetContentAsync("
"); - Assert.Equal("SPAN,DIV", await Page.EvalOnSelectorAllAsync("css=span, div", "els => els.map(e => e.nodeName).join(',')")); - Assert.Equal("SPAN,DIV", await Page.EvalOnSelectorAllAsync("css=div, span", "els => els.map(e => e.nodeName).join(',')")); - Assert.Equal("DIV", await Page.EvalOnSelectorAllAsync("css=span div, div", "els => els.map(e => e.nodeName).join(',')")); - Assert.Equal("SECTION", await Page.EvalOnSelectorAllAsync("*css = section >> css = div, span", "els => els.map(e => e.nodeName).join(',')")); - Assert.Equal("DIV", await Page.EvalOnSelectorAllAsync("css=section >> *css = div >> css = x, y", "els => els.map(e => e.nodeName).join(',')")); - Assert.Equal("SPAN,DIV", await Page.EvalOnSelectorAllAsync("css=section >> *css = div, span >> css = x, y", "els => els.map(e => e.nodeName).join(',')")); - Assert.Equal("SPAN,DIV", await Page.EvalOnSelectorAllAsync("css=section >> *css = div, span >> css = y", "els => els.map(e => e.nodeName).join(',')")); - } - - [PlaywrightTest("selectors-css.spec.ts", "should work with comma inside text")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithCommaInsideText() - { - await Page.SetContentAsync("
"); - Assert.Equal("
", await Page.EvalOnSelectorAsync("css=div[attr=\"hello,world!\"]", "e => e.outerHTML")); - Assert.Equal("
", await Page.EvalOnSelectorAsync("css =[attr=\"hello,world!\"]", "e => e.outerHTML")); - Assert.Equal("
", await Page.EvalOnSelectorAsync("css=div[attr='hello,world!']", "e => e.outerHTML")); - Assert.Equal("
", await Page.EvalOnSelectorAsync("css=[attr='hello,world!']", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("css=div[attr=\"hello,world!\"], span", "e => e.outerHTML")); - } - - [PlaywrightTest("selectors-css.spec.ts", "should work with attribute selectors")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithAttributeSelectors() - { - await Page.SetContentAsync("
>foo=bar[]\" attr3=\"] span\">
"); - await Page.EvaluateAsync("() => window.div = document.querySelector('div')"); - string[] selectors = new[] { - "[attr=\"hello world\"]", - "[attr = \"hello world\"]", - "[attr ~= world]", - "[attr ^=hello ]", - "[attr $= world ]", - "[attr *= \"llo wor\" ]", - "[attr2 |= hello]", - "[attr = \"Hello World\" i ]", - "[attr *= \"llo WOR\" i]", - "[attr $= woRLD i]", - "[attr2 = \"hello-''>>foo=bar[]\"]", - "[attr2 $=\"foo=bar[]\"]", - }; - - foreach (string selector in selectors) - { - Assert.True(await Page.EvalOnSelectorAsync(selector, "e => e === div")); - } - - Assert.True(await Page.EvalOnSelectorAsync("[attr*=hello] span", "e => e.parentNode === div")); - Assert.True(await Page.EvalOnSelectorAsync("[attr*=hello] >> span", "e => e.parentNode === div")); - Assert.True(await Page.EvalOnSelectorAsync("[attr3=\"] span\"] >> span", "e => e.parentNode === div")); - } - } -} diff --git a/src/Playwright.Tests/SelectorsRegisterTests.cs b/src/Playwright.Tests/SelectorsRegisterTests.cs deleted file mode 100644 index 386499feea..0000000000 --- a/src/Playwright.Tests/SelectorsRegisterTests.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///selectors-register.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class SelectorsRegisterTests : PlaywrightSharpPageBaseTest - { - /// - public SelectorsRegisterTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("selectors-register.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - const string createTagSelector = @"({ - create(root, target) { - return target.nodeName; - }, - query(root, selector) { - return root.querySelector(selector); - }, - queryAll(root, selector) { - return Array.from(root.querySelectorAll(selector)); - } - })"; - - await TestUtils.RegisterEngineAsync(Playwright, "tag", createTagSelector); - var context = await Browser.NewContextAsync(); - await TestUtils.RegisterEngineAsync(Playwright, "tag2", createTagSelector); - var page = await context.NewPageAsync(); - await page.SetContentAsync("
"); - - var exception = await Assert.ThrowsAnyAsync(() => page.QuerySelectorAsync("tAG=DIV")); - Assert.Contains("Unknown engine \"tAG\" while parsing selector tAG=DIV", exception.Message); - } - - [PlaywrightTest("selectors-register.spec.ts", "should work with path")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithPath() - { - await TestUtils.RegisterEngineWithPathAsync(Playwright, "foo", TestUtils.GetWebServerFile("sectionselectorengine.js")); - await Page.SetContentAsync("
"); - Assert.Equal("SECTION", await Page.EvalOnSelectorAsync("foo=whatever", "e => e.nodeName")); - } - - [PlaywrightTest("selectors-register.spec.ts", "should work in main and isolated world")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkInMainAndIsolatedWorld() - { - const string createTagSelector = @"({ - create(root, target) { }, - query(root, selector) { - return window['__answer']; - }, - queryAll(root, selector) { - return window['__answer'] ? [window['__answer'], document.body, document.documentElement] : []; - } - })"; - - await TestUtils.RegisterEngineAsync(Playwright, "main", createTagSelector); - await TestUtils.RegisterEngineAsync(Playwright, "isolated", createTagSelector, true); - await Page.SetContentAsync("
"); - await Page.EvaluateAsync("() => window['__answer'] = document.querySelector('span')"); - - Assert.Equal("SPAN", await Page.EvalOnSelectorAsync("main=ignored", "e => e.nodeName")); - Assert.Equal("SPAN", await Page.EvalOnSelectorAsync("css=div >> main=ignored", "e => e.nodeName")); - Assert.True(await Page.EvalOnSelectorAllAsync("main=ignored", "es => window['__answer'] !== undefined")); - Assert.Equal(3, await Page.EvalOnSelectorAllAsync("main=ignored", "es => es.filter(e => e).length")); - - Assert.Null(await Page.QuerySelectorAsync("isolated=ignored")); - Assert.Null(await Page.QuerySelectorAsync("css=div >> isolated=ignored")); - Assert.True(await Page.EvalOnSelectorAllAsync("isolated=ignored", "es => window['__answer'] !== undefined")); - Assert.Equal(3, await Page.EvalOnSelectorAllAsync("isolated=ignored", "es => es.filter(e => e).length")); - - Assert.Equal("SPAN", await Page.EvalOnSelectorAsync("main=ignored >> isolated=ignored", "e => e.nodeName")); - Assert.Equal("SPAN", await Page.EvalOnSelectorAsync("isolated=ignored >> main=ignored", "e => e.nodeName")); - - Assert.Equal("SECTION", await Page.EvalOnSelectorAsync("main=ignored >> css=section", "e => e.nodeName")); - } - - [PlaywrightTest("selectors-register.spec.ts", "should handle errors")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHandleErrors() - { - var exception = await Assert.ThrowsAnyAsync(() => Page.QuerySelectorAsync("neverregister=ignored")); - Assert.Contains("Unknown engine \"neverregister\" while parsing selector neverregister=ignored", exception.Message); - - const string createDummySelector = @"({ - create(root, target) { - return target.nodeName; - }, - query(root, selector) { - return root.querySelector('dummy'); - }, - queryAll(root, selector) { - return Array.from(root.querySelectorAll('dummy')); - } - })"; - - exception = await Assert.ThrowsAnyAsync(() => Playwright.Selectors.RegisterAsync("$", createDummySelector)); - Assert.Contains("Selector engine name may only contain [a-zA-Z0-9_] characters", exception.Message); - - await TestUtils.RegisterEngineAsync(Playwright, "dummy", createDummySelector); - await TestUtils.RegisterEngineAsync(Playwright, "duMMy", createDummySelector); - - exception = await Assert.ThrowsAnyAsync(() => Playwright.Selectors.RegisterAsync("dummy", createDummySelector)); - Assert.Contains("\"dummy\" selector engine has been already registered", exception.Message); - - exception = await Assert.ThrowsAnyAsync(() => Playwright.Selectors.RegisterAsync("css", createDummySelector)); - Assert.Contains("\"css\" is a predefined selector engine", exception.Message); - } - } -} diff --git a/src/Playwright.Tests/SelectorsTextTests.cs b/src/Playwright.Tests/SelectorsTextTests.cs deleted file mode 100644 index b01fbbb15e..0000000000 --- a/src/Playwright.Tests/SelectorsTextTests.cs +++ /dev/null @@ -1,229 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class SelectorsTextTests : PlaywrightSharpPageBaseTest - { - /// - public SelectorsTextTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("selectors-text.spec.ts", "query")] - [Fact(Skip = "We need to update this test", Timeout = TestConstants.DefaultTestTimeout)] - public async Task Query() - { - await Page.SetContentAsync("
yo
ya
\nye
"); - Assert.Equal("
ya
", await Page.EvalOnSelectorAsync("text=ya", "e => e.outerHTML")); - Assert.Equal("
ya
", await Page.EvalOnSelectorAsync("text=\"ya\"", "e => e.outerHTML")); - Assert.Equal("
ya
", await Page.EvalOnSelectorAsync("text=/^[ay]+$/", "e => e.outerHTML")); - Assert.Equal("
ya
", await Page.EvalOnSelectorAsync("text=/Ya/i", "e => e.outerHTML")); - Assert.Equal("
\nye
", await Page.EvalOnSelectorAsync("text=ye", "e => e.outerHTML")); - - await Page.SetContentAsync("
ye
ye
"); - Assert.Equal("
ye
", await Page.EvalOnSelectorAsync("text=\"ye\"", "e => e.outerHTML")); - - await Page.SetContentAsync("
yo
\"ya
hello world!
"); - Assert.Equal("
\"ya
", await Page.EvalOnSelectorAsync("text=\"\\\"ya\"", "e => e.outerHTML")); - Assert.Equal("
hello world!
", await Page.EvalOnSelectorAsync("text=/hello/", "e => e.outerHTML")); - Assert.Equal("
hello world!
", await Page.EvalOnSelectorAsync("text=/^\\s*heLLo/i", "e => e.outerHTML")); - - await Page.SetContentAsync("
yo
ya
hey
hey
"); - Assert.Equal("
yo
ya
hey
hey
", await Page.EvalOnSelectorAsync("text=hey", "e => e.outerHTML")); - Assert.Equal("
ya
", await Page.EvalOnSelectorAsync("text=\"yo\" >> text =\"ya\"", "e => e.outerHTML")); - Assert.Equal("
ya
", await Page.EvalOnSelectorAsync("text='yo' >> text =\"ya\"", "e => e.outerHTML")); - Assert.Equal("
ya
", await Page.EvalOnSelectorAsync("text=\"yo\" >> text='ya'", "e => e.outerHTML")); - Assert.Equal("
ya
", await Page.EvalOnSelectorAsync("text='yo' >> text='ya'", "e => e.outerHTML")); - Assert.Equal("
ya
", await Page.EvalOnSelectorAsync("'yo' >> \"ya\"", "e => e.outerHTML")); - Assert.Equal("
ya
", await Page.EvalOnSelectorAsync("\"yo\" >> 'ya'", "e => e.outerHTML")); - - await Page.SetContentAsync("
yo
yo
"); - Assert.Equal("
yo
\n
yo
", await Page.EvalOnSelectorAllAsync("text=yo", "es => es.map(e => e.outerHTML).join('\\n')")); - - await Page.SetContentAsync("
'
\"
\\
x
"); - Assert.Equal("
\'
", await Page.EvalOnSelectorAsync("text='\\''", "e => e.outerHTML")); - Assert.Equal("
\"
", await Page.EvalOnSelectorAsync("text='\"'", "e => e.outerHTML")); - Assert.Equal("
\"
", await Page.EvalOnSelectorAsync("text=\"\\\"\"", "e => e.outerHTML")); - Assert.Equal("
\'
", await Page.EvalOnSelectorAsync("text=\"'\"", "e => e.outerHTML")); - Assert.Equal("
x
", await Page.EvalOnSelectorAsync("text=\"\\x\"", "e => e.outerHTML")); - Assert.Equal("
x
", await Page.EvalOnSelectorAsync("text='\\x'", "e => e.outerHTML")); - Assert.Equal("
\\
", await Page.EvalOnSelectorAsync("text='\\\\'", "e => e.outerHTML")); - Assert.Equal("
\\
", await Page.EvalOnSelectorAsync("text=\"\\\\\"", "e => e.outerHTML")); - Assert.Equal("
\"
", await Page.EvalOnSelectorAsync("text=\"", "e => e.outerHTML")); - Assert.Equal("
\'
", await Page.EvalOnSelectorAsync("text='", "e => e.outerHTML")); - Assert.Equal("
x
", await Page.EvalOnSelectorAsync("\"x\"", "e => e.outerHTML")); - Assert.Equal("
x
", await Page.EvalOnSelectorAsync("'x'", "e => e.outerHTML")); - - await Assert.ThrowsAnyAsync(() => Page.QuerySelectorAsync("\"")); - await Assert.ThrowsAnyAsync(() => Page.QuerySelectorAsync("'")); - - await Page.SetContentAsync("
'
\"
"); - Assert.Equal("
\"
", await Page.EvalOnSelectorAsync("text=\"", "e => e.outerHTML")); - Assert.Equal("
\'
", await Page.EvalOnSelectorAsync("text='", "e => e.outerHTML")); - - await Page.SetContentAsync("
Hi''>>foo=bar
"); - Assert.Equal("
Hi''>>foo=bar
", await Page.EvalOnSelectorAsync("text=\"Hi''>>foo=bar\"", "e => e.outerHTML")); - await Page.SetContentAsync("
Hi'\">>foo=bar
"); - Assert.Equal("
Hi'\">>foo=bar
", await Page.EvalOnSelectorAsync("text=\"Hi'\\\">>foo=bar\"", "e => e.outerHTML")); - - await Page.SetContentAsync("
Hi>>
"); - Assert.Equal("", await Page.EvalOnSelectorAsync("text=\"Hi>>\">>span", "e => e.outerHTML")); - - await Page.SetContentAsync("
a
b
a
"); - Assert.Equal("
a
b
", await Page.EvalOnSelectorAsync("text=a", "e => e.outerHTML")); - Assert.Equal("
a
b
", await Page.EvalOnSelectorAsync("text=b", "e => e.outerHTML")); - Assert.Null(await Page.QuerySelectorAsync("text=ab")); - Assert.Equal(2, await Page.EvalOnSelectorAllAsync("text=a", "els => els.length")); - Assert.Equal(1, await Page.EvalOnSelectorAllAsync("text=b", "els => els.length")); - Assert.Equal(0, await Page.EvalOnSelectorAllAsync("text=ab", "els => els.length")); - - await Page.SetContentAsync("
"); - await Page.EvalOnSelectorAsync("div", @"div => - { - div.appendChild(document.createTextNode('hello')); - div.appendChild(document.createTextNode('world')); - }"); - - await Page.EvalOnSelectorAsync("span", @"span => - { - span.appendChild(document.createTextNode('hello')); - span.appendChild(document.createTextNode('world')); - }"); - Assert.Equal("
helloworld
", await Page.EvalOnSelectorAsync("text=lowo", "e => e.outerHTML")); - Assert.Equal("
helloworld
helloworld", await Page.EvalOnSelectorAllAsync("text=lowo", "els => els.map(e => e.outerHTML).join('')")); - } - - [PlaywrightTest("selectors-text.spec.ts", "create")] - [Fact(Skip = "Skip Hooks")] - public void Create() - { - } - - [PlaywrightTest("selectors-text.spec.ts", "should be case sensitive if quotes are specified")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeCaseSensitiveIfQuotesAreSpecified() - { - await Page.SetContentAsync("
yo
ya
\nye
"); - Assert.Equal("
ya
", await Page.EvalOnSelectorAsync("text=ya", "e => e.outerHTML")); - Assert.Null(await Page.QuerySelectorAsync("text=\"yA\"")); - } - - [PlaywrightTest("selectors-text.spec.ts", "should search for a substring without quotes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSearchForASubstringWithoutQuotes() - { - await Page.SetContentAsync("
textwithsubstring
"); - Assert.Equal("
textwithsubstring
", await Page.EvalOnSelectorAsync("text=with", "e => e.outerHTML")); - Assert.Null(await Page.QuerySelectorAsync("text=\"with\"")); - } - - [PlaywrightTest("selectors-text.spec.ts", "should skip head, script and style")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSkipHeadScriptAndStyle() - { - await Page.SetContentAsync(@" - - title - - - - - - -
title script style
- "); - - var head = await Page.QuerySelectorAsync("head"); - var title = await Page.QuerySelectorAsync("title"); - var script = await Page.QuerySelectorAsync("body script"); - var style = await Page.QuerySelectorAsync("body style"); - - foreach (string text in new[] { "title", "script", "style" }) - { - Assert.Equal("DIV", await Page.EvalOnSelectorAsync($"text={text}", "e => e.nodeName")); - Assert.Equal("DIV", await Page.EvalOnSelectorAllAsync($"text={text}", "els => els.map(e => e.nodeName).join('|')")); - - foreach (var root in new[] { head, title, script, style }) - { - Assert.Null(await root.QuerySelectorAsync($"text={text}")); - Assert.Equal(0, await root.EvalOnSelectorAllAsync($"text={text}", "els => els.length")); - } - } - } - - [PlaywrightTest("selectors-text.spec.ts", "should match input[type=button|submit]")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldMatchInputTypeButtonSubmit() - { - await Page.SetContentAsync(""); - Assert.Equal("", await Page.EvalOnSelectorAsync("text=hello", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("text=world", "e => e.outerHTML")); - } - - [PlaywrightTest("selectors-text.spec.ts", "should work for open shadow roots")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForOpenShadowRoots() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/deep-shadow.html"); - Assert.Equal("Hello from root1", await Page.EvalOnSelectorAsync("text=root1", "e => e.textContent")); - Assert.Equal("Hello from root2", await Page.EvalOnSelectorAsync("text=root2", "e => e.textContent")); - Assert.Equal("Hello from root3", await Page.EvalOnSelectorAsync("text=root3", "e => e.textContent")); - Assert.Equal("Hello from root3", await Page.EvalOnSelectorAsync("#root1 >> text=from root3", "e => e.textContent")); - Assert.Equal("Hello from root2", await Page.EvalOnSelectorAsync("#target >> text=from root2", "e => e.textContent")); - - Assert.Null(await Page.QuerySelectorAsync("text:light=root1")); - Assert.Null(await Page.QuerySelectorAsync("text:light=root2")); - Assert.Null(await Page.QuerySelectorAsync("text:light=root3")); - } - - [PlaywrightTest("selectors-text.spec.ts", "should prioritize light dom over shadow dom in the same parent")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldPrioritizeLightDomOverShadowDomInTheSameParent() - { - await Page.EvaluateAsync(@" - const div = document.createElement('div'); - document.body.appendChild(div); - - div.attachShadow({ mode: 'open' }); - const shadowSpan = document.createElement('span'); - shadowSpan.textContent = 'Hello from shadow'; - div.shadowRoot.appendChild(shadowSpan); - - const lightSpan = document.createElement('span'); - lightSpan.textContent = 'Hello from light'; - div.appendChild(lightSpan); - "); - - Assert.Equal("Hello from light", await Page.EvalOnSelectorAsync("div >> text=Hello", "e => e.textContent")); - } - - [PlaywrightTest("selectors-text.spec.ts", "should waitForSelector with distributed elements")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForSelectorWithDistributedElements() - { - var task = Page.WaitForSelectorAsync("div >> text=Hello"); - await Page.EvaluateAsync(@" - const div = document.createElement('div'); - document.body.appendChild(div); - - div.attachShadow({ mode: 'open' }); - const shadowSpan = document.createElement('span'); - shadowSpan.textContent = 'Hello from shadow'; - div.shadowRoot.appendChild(shadowSpan); - div.shadowRoot.appendChild(document.createElement('slot')); - - const lightSpan = document.createElement('span'); - lightSpan.textContent = 'Hello from light'; - div.appendChild(lightSpan); - "); - - var handle = await task; - Assert.Equal("Hello from light", await handle.TextContentAsync()); - } - } -} diff --git a/src/Playwright.Tests/xunit.runner.json b/src/Playwright.Tests/xunit.runner.json deleted file mode 100644 index c468fda9eb..0000000000 --- a/src/Playwright.Tests/xunit.runner.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", - "diagnosticMessages": true, - "parallelizeAssembly": false, - "maxParallelThreads": 1, - "longRunningTestSeconds": 5 -} \ No newline at end of file diff --git a/src/Playwright.Demo/Playwright.Demo.csproj b/src/PlaywrightSharp.Demo/PlaywrightSharp.Demo.csproj similarity index 71% rename from src/Playwright.Demo/Playwright.Demo.csproj rename to src/PlaywrightSharp.Demo/PlaywrightSharp.Demo.csproj index cd2b51b35f..0e289ebf75 100644 --- a/src/Playwright.Demo/Playwright.Demo.csproj +++ b/src/PlaywrightSharp.Demo/PlaywrightSharp.Demo.csproj @@ -4,11 +4,11 @@ Exe net10.0 0.0.0 - Microsoft.Playwright.Demo - Microsoft.Playwright.Demo + PlaywrightSharp.Demo + PlaywrightSharp.Demo - + diff --git a/src/Playwright.Demo/Program.cs b/src/PlaywrightSharp.Demo/Program.cs similarity index 92% rename from src/Playwright.Demo/Program.cs rename to src/PlaywrightSharp.Demo/Program.cs index 1c0da2d4e5..4fad48ba6f 100644 --- a/src/Playwright.Demo/Program.cs +++ b/src/PlaywrightSharp.Demo/Program.cs @@ -1,19 +1,19 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Playwright; - -namespace PlaywrightSharp.Demo -{ - class Program - { - static async Task Main() - { - using var playwright = await Playwright.CreateAsync(); - var chromium = playwright.Chromium; - var browser = await chromium.LaunchAsync(headless: false); - var page = await browser.NewPageAsync(); - await page.GoToAsync("https://example.com"); - Console.ReadLine(); - } - } -} +using System; +using System.Threading.Tasks; +using PlaywrightSharp; + +namespace PlaywrightSharp.Demo +{ + class Program + { + static async Task Main() + { + using var playwright = await Playwright.CreateAsync(); + var chromium = playwright.Chromium; + var browser = await chromium.LaunchAsync(headless: false); + var page = await browser.NewPageAsync(); + await page.GoToAsync("https://example.com"); + Console.ReadLine(); + } + } +} diff --git a/src/Playwright.LocalNugetTest/NuGet.Config b/src/PlaywrightSharp.LocalNugetTest/NuGet.Config similarity index 100% rename from src/Playwright.LocalNugetTest/NuGet.Config rename to src/PlaywrightSharp.LocalNugetTest/NuGet.Config diff --git a/src/Playwright.LocalNugetTest/NugetTests.cs b/src/PlaywrightSharp.LocalNugetTest/NugetTests.cs similarity index 92% rename from src/Playwright.LocalNugetTest/NugetTests.cs rename to src/PlaywrightSharp.LocalNugetTest/NugetTests.cs index 22b6933d55..33255a76d5 100644 --- a/src/Playwright.LocalNugetTest/NugetTests.cs +++ b/src/PlaywrightSharp.LocalNugetTest/NugetTests.cs @@ -3,7 +3,7 @@ using System.Threading.Tasks; using Xunit; -namespace Microsoft.Playwright.LocalNugetTest +namespace PlaywrightSharp.LocalNugetTest { public class NugetTests { diff --git a/src/Playwright.LocalNugetTest/Playwright.LocalNugetTest.sln b/src/PlaywrightSharp.LocalNugetTest/Playwright.LocalNugetTest.sln similarity index 87% rename from src/Playwright.LocalNugetTest/Playwright.LocalNugetTest.sln rename to src/PlaywrightSharp.LocalNugetTest/Playwright.LocalNugetTest.sln index 74e9129898..e1f7b9bd37 100644 --- a/src/Playwright.LocalNugetTest/Playwright.LocalNugetTest.sln +++ b/src/PlaywrightSharp.LocalNugetTest/Playwright.LocalNugetTest.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.31205.134 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Playwright.LocalNugetTest", "Playwright.LocalNugetTest.csproj", "{A4AEC544-D521-4CD4-9A8F-F6926DEFC233}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlaywrightSharp.LocalNugetTest", "PlaywrightSharp.LocalNugetTest.csproj", "{A4AEC544-D521-4CD4-9A8F-F6926DEFC233}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4611591F-E17F-4601-89AC-F4D9BE665940}" ProjectSection(SolutionItems) = preProject diff --git a/src/Playwright.LocalNugetTest/Playwright.LocalNugetTest.csproj b/src/PlaywrightSharp.LocalNugetTest/PlaywrightSharp.LocalNugetTest.csproj similarity index 75% rename from src/Playwright.LocalNugetTest/Playwright.LocalNugetTest.csproj rename to src/PlaywrightSharp.LocalNugetTest/PlaywrightSharp.LocalNugetTest.csproj index 0afd928144..a8c316d5a1 100644 --- a/src/Playwright.LocalNugetTest/Playwright.LocalNugetTest.csproj +++ b/src/PlaywrightSharp.LocalNugetTest/PlaywrightSharp.LocalNugetTest.csproj @@ -4,12 +4,12 @@ true 0.0.0 net10.0 - Microsoft.Playwright.LocalNugetTest - Microsoft.Playwright.LocalNugetTest + PlaywrightSharp.LocalNugetTest + PlaywrightSharp.LocalNugetTest - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Playwright.Testing.Xunit/Playwright.Testing.Xunit.csproj b/src/PlaywrightSharp.Nunit/PlaywrightSharp.Nunit.csproj similarity index 51% rename from src/Playwright.Testing.Xunit/Playwright.Testing.Xunit.csproj rename to src/PlaywrightSharp.Nunit/PlaywrightSharp.Nunit.csproj index de2bc6d30c..da3a377919 100644 --- a/src/Playwright.Testing.Xunit/Playwright.Testing.Xunit.csproj +++ b/src/PlaywrightSharp.Nunit/PlaywrightSharp.Nunit.csproj @@ -2,6 +2,9 @@ net10.0 - Microsoft.Playwright.Testing.Xunit + PlaywrightSharp.Nunit - \ No newline at end of file + + + + diff --git a/src/Playwright.Testing.Xunit/PlaywrightTestAttribute.cs b/src/PlaywrightSharp.Nunit/PlaywrightTestAttribute.cs similarity index 58% rename from src/Playwright.Testing.Xunit/PlaywrightTestAttribute.cs rename to src/PlaywrightSharp.Nunit/PlaywrightTestAttribute.cs index 028160d5cc..e96ae69ae0 100644 --- a/src/Playwright.Testing.Xunit/PlaywrightTestAttribute.cs +++ b/src/PlaywrightSharp.Nunit/PlaywrightTestAttribute.cs @@ -1,53 +1,79 @@ -using System; - -namespace Microsoft.Playwright.Testing.Xunit -{ - /// - /// Enables decorating test facts with information about the corresponding test in the upstream repository. - /// - [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - public class PlaywrightTestAttribute : Attribute - { - /// - /// Creates a new instance of the attribute. - /// - /// - /// - public PlaywrightTestAttribute(string fileName, string nameOfTest) - { - FileName = fileName; - TestName = nameOfTest; - } - - /// - /// Creates a new instance of the attribute. - /// - /// - /// - /// - public PlaywrightTestAttribute(string fileName, string describe, string nameOfTest) : this(fileName, nameOfTest) - { - Describe = describe; - } - - /// - /// The file name origin of the test. - /// - public string FileName { get; } - - /// - /// Returns the trimmed file name. - /// - public string TrimmedName => FileName.Substring(0, FileName.IndexOf('.')); - - /// - /// The name of the test, the decorated code is based on. - /// - public string TestName { get; } - - /// - /// The describe of the test, the decorated code is based on, if one exists. - /// - public string Describe { get; } - } -} +using System; +using NUnit.Framework; +using NUnit.Framework.Interfaces; +using NUnit.Framework.Internal; + +namespace PlaywrightSharp.Nunit +{ + /// + /// Enables decorating test facts with information about the corresponding test in the upstream repository. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + public class PlaywrightTestAttribute : NUnitAttribute, IApplyToTest + { + /// + /// Gets whether the current product is Chromium. + /// + public static readonly bool IsChromium = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("PRODUCT")) || + Environment.GetEnvironmentVariable("PRODUCT").Equals("CHROMIUM", StringComparison.OrdinalIgnoreCase); + + /// + /// Gets whether the current product is Firefox. + /// + public static readonly bool IsFirefox = + Environment.GetEnvironmentVariable("PRODUCT")?.Equals("FIREFOX", StringComparison.OrdinalIgnoreCase) == true; + + /// + /// Gets whether the current product is WebKit. + /// + public static readonly bool IsWebkit = + Environment.GetEnvironmentVariable("PRODUCT")?.Equals("WEBKIT", StringComparison.OrdinalIgnoreCase) == true; + + /// + /// Creates a new instance of the attribute. + /// + /// + /// + public PlaywrightTestAttribute(string fileName, string nameOfTest) + { + FileName = fileName; + TestName = nameOfTest; + } + + /// + /// Creates a new instance of the attribute. + /// + /// + /// + /// + public PlaywrightTestAttribute(string fileName, string describe, string nameOfTest) : this(fileName, nameOfTest) + { + Describe = describe; + } + + /// + /// The file name origin of the test. + /// + public string FileName { get; } + + /// + /// Returns the trimmed file name. + /// + public string TrimmedName => FileName.Substring(0, FileName.IndexOf('.')); + + /// + /// The name of the test, the decorated code is based on. + /// + public string TestName { get; } + + /// + /// The describe of the test, the decorated code is based on, if one exists. + /// + public string Describe { get; } + + /// + public void ApplyToTest(Test test) + { + } + } +} diff --git a/src/Playwright.Tests.TestServer/Playwright.Tests.TestServer.csproj b/src/PlaywrightSharp.TestServer/PlaywrightSharp.TestServer.csproj similarity index 66% rename from src/Playwright.Tests.TestServer/Playwright.Tests.TestServer.csproj rename to src/PlaywrightSharp.TestServer/PlaywrightSharp.TestServer.csproj index ff7f7b1d8e..fd924589db 100644 --- a/src/Playwright.Tests.TestServer/Playwright.Tests.TestServer.csproj +++ b/src/PlaywrightSharp.TestServer/PlaywrightSharp.TestServer.csproj @@ -4,8 +4,8 @@ net10.0 Library 0.0.0 - Microsoft.Playwright.Tests.TestServer - Microsoft.Playwright.Tests.TestServer + PlaywrightSharp.TestServer + PlaywrightSharp.TestServer diff --git a/src/Playwright.Tests.TestServer/Properties/launchSettings.json b/src/PlaywrightSharp.TestServer/Properties/launchSettings.json similarity index 100% rename from src/Playwright.Tests.TestServer/Properties/launchSettings.json rename to src/PlaywrightSharp.TestServer/Properties/launchSettings.json diff --git a/src/Playwright.Tests.TestServer/RequestReceivedEventArgs.cs b/src/PlaywrightSharp.TestServer/RequestReceivedEventArgs.cs similarity index 77% rename from src/Playwright.Tests.TestServer/RequestReceivedEventArgs.cs rename to src/PlaywrightSharp.TestServer/RequestReceivedEventArgs.cs index 179c23e898..40987a5b5c 100644 --- a/src/Playwright.Tests.TestServer/RequestReceivedEventArgs.cs +++ b/src/PlaywrightSharp.TestServer/RequestReceivedEventArgs.cs @@ -1,10 +1,10 @@ -using System; -using Microsoft.AspNetCore.Http; - -namespace Microsoft.Playwright.Tests.TestServer -{ - public class RequestReceivedEventArgs : EventArgs - { - public HttpRequest Request { get; set; } - } -} +using System; +using Microsoft.AspNetCore.Http; + +namespace PlaywrightSharp.TestServer +{ + public class RequestReceivedEventArgs : EventArgs + { + public HttpRequest Request { get; set; } + } +} diff --git a/src/Playwright.Tests.TestServer/SimpleCompressionMiddleware.cs b/src/PlaywrightSharp.TestServer/SimpleCompressionMiddleware.cs similarity index 94% rename from src/Playwright.Tests.TestServer/SimpleCompressionMiddleware.cs rename to src/PlaywrightSharp.TestServer/SimpleCompressionMiddleware.cs index 5b175817f3..e4672df881 100644 --- a/src/Playwright.Tests.TestServer/SimpleCompressionMiddleware.cs +++ b/src/PlaywrightSharp.TestServer/SimpleCompressionMiddleware.cs @@ -1,49 +1,49 @@ -using System; -using System.IO; -using System.IO.Compression; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; - -namespace Microsoft.Playwright.Tests.TestServer -{ - internal class SimpleCompressionMiddleware - { - private readonly RequestDelegate _next; - private readonly SimpleServer _server; - - public SimpleCompressionMiddleware(RequestDelegate next, SimpleServer server) - { - _next = next; - _server = server; - } - - public async Task Invoke(HttpContext context) - { - if (!_server.GzipRoutes.Contains(context.Request.Path)) - { - await _next(context); - return; - } - - var response = context.Response.Body; - var bodyWrapperStream = new MemoryStream(); - context.Response.Body = bodyWrapperStream; - - await _next(context); - using (var stream = new MemoryStream()) - { - using (var compressionStream = new GZipStream(stream, CompressionMode.Compress, true)) - { - bodyWrapperStream.Position = 0; - bodyWrapperStream.CopyTo(compressionStream); - } - - context.Response.Headers["Content-Encoding"] = "gzip"; - context.Response.Headers["Content-Length"] = stream.Length.ToString(); - stream.Position = 0; - await stream.CopyToAsync(response); - context.Response.Body = response; - } - } - } -} +using System; +using System.IO; +using System.IO.Compression; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace PlaywrightSharp.TestServer +{ + internal class SimpleCompressionMiddleware + { + private readonly RequestDelegate _next; + private readonly SimpleServer _server; + + public SimpleCompressionMiddleware(RequestDelegate next, SimpleServer server) + { + _next = next; + _server = server; + } + + public async Task Invoke(HttpContext context) + { + if (!_server.GzipRoutes.Contains(context.Request.Path)) + { + await _next(context); + return; + } + + var response = context.Response.Body; + var bodyWrapperStream = new MemoryStream(); + context.Response.Body = bodyWrapperStream; + + await _next(context); + using (var stream = new MemoryStream()) + { + using (var compressionStream = new GZipStream(stream, CompressionMode.Compress, true)) + { + bodyWrapperStream.Position = 0; + bodyWrapperStream.CopyTo(compressionStream); + } + + context.Response.Headers["Content-Encoding"] = "gzip"; + context.Response.Headers["Content-Length"] = stream.Length.ToString(); + stream.Position = 0; + await stream.CopyToAsync(response); + context.Response.Body = response; + } + } + } +} diff --git a/src/Playwright.Tests.TestServer/SimpleServer.cs b/src/PlaywrightSharp.TestServer/SimpleServer.cs similarity index 97% rename from src/Playwright.Tests.TestServer/SimpleServer.cs rename to src/PlaywrightSharp.TestServer/SimpleServer.cs index e7bb4d49e3..4f0907f42f 100644 --- a/src/Playwright.Tests.TestServer/SimpleServer.cs +++ b/src/PlaywrightSharp.TestServer/SimpleServer.cs @@ -1,289 +1,289 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Net; -using System.Net.WebSockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Configuration; - -namespace Microsoft.Playwright.Tests.TestServer -{ - public class SimpleServer - { - const int MaxMessageSize = 256 * 1024; - - private readonly IDictionary> _subscribers; - private readonly IDictionary> _requestWaits; - private readonly IDictionary _routes; - private readonly IDictionary _auths; - private readonly IDictionary _csp; - private readonly IWebHost _webHost; - private static int counter; - private readonly Dictionary _clients = new Dictionary(); - - internal IList GzipRoutes { get; } - - public event EventHandler RequestReceived; - - public static SimpleServer Create(int port, string contentRoot) => new SimpleServer(port, contentRoot, isHttps: false); - - public static SimpleServer CreateHttps(int port, string contentRoot) => new SimpleServer(port, contentRoot, isHttps: true); - - public SimpleServer(int port, string contentRoot, bool isHttps) - { - _subscribers = new ConcurrentDictionary>(); - _requestWaits = new ConcurrentDictionary>(); - _routes = new ConcurrentDictionary(); - _auths = new ConcurrentDictionary(); - _csp = new ConcurrentDictionary(); - GzipRoutes = new List(); - - _webHost = new WebHostBuilder() - .ConfigureAppConfiguration((context, builder) => builder - .SetBasePath(context.HostingEnvironment.ContentRootPath) - .AddEnvironmentVariables() - ) - .Configure(app => app -#if NETCOREAPP - .UseWebSockets() -#endif - .Use(async (context, next) => - { - RequestReceived?.Invoke(this, new RequestReceivedEventArgs { Request = context.Request }); - - if (context.Request.Path == "/ws") - { - if (context.WebSockets.IsWebSocketRequest) - { - var webSocket = await context.WebSockets.AcceptWebSocketAsync(); - await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes("incoming")), WebSocketMessageType.Text, true, CancellationToken.None); - await ReceiveLoopAsync(webSocket, context.Request.Headers["User-Agent"].ToString().Contains("Firefox"), CancellationToken.None); - } - else if (!context.Response.HasStarted) - { - context.Response.StatusCode = 400; - } - return; - } - - if (_auths.TryGetValue(context.Request.Path, out var auth) && !Authenticate(auth.username, auth.password, context)) - { - context.Response.Headers.Add("WWW-Authenticate", "Basic realm=\"Secure Area\""); - - if (!context.Response.HasStarted) - { - context.Response.StatusCode = StatusCodes.Status401Unauthorized; - } - await context.Response.WriteAsync("HTTP Error 401 Unauthorized: Access is denied"); - } - if (_subscribers.TryGetValue(context.Request.Path, out var subscriber)) - { - subscriber(context); - } - if (_requestWaits.TryGetValue(context.Request.Path, out var requestWait)) - { - requestWait(context); - } - if (_routes.TryGetValue(context.Request.Path + context.Request.QueryString, out var handler)) - { - await handler(context); - return; - } - - if ( - context.Request.Path.ToString().Contains("/cached/") && - !string.IsNullOrEmpty(context.Request.Headers["if-modified-since"]) && - !context.Response.HasStarted) - { - context.Response.StatusCode = StatusCodes.Status304NotModified; - } - - await next(); - }) - .UseMiddleware(this) - .UseStaticFiles(new StaticFileOptions - { - OnPrepareResponse = fileResponseContext => - { - if (_csp.TryGetValue(fileResponseContext.Context.Request.Path, out string csp)) - { - fileResponseContext.Context.Response.Headers["Content-Security-Policy"] = csp; - } - - if (fileResponseContext.Context.Request.Path.ToString().EndsWith(".html")) - { - fileResponseContext.Context.Response.Headers["Content-Type"] = "text/html; charset=utf-8"; - - if (fileResponseContext.Context.Request.Path.ToString().Contains("/cached/")) - { - fileResponseContext.Context.Response.Headers["Cache-Control"] = "public, max-age=31536000, no-cache"; - fileResponseContext.Context.Response.Headers["Last-Modified"] = DateTime.Now.ToString("s"); - } - else - { - fileResponseContext.Context.Response.Headers["Cache-Control"] = "no-cache, no-store"; - } - } - } - })) - .UseKestrel(options => - { - if (isHttps) - { - options.Listen(IPAddress.Loopback, port, listenOptions => listenOptions.UseHttps("testCert.cer")); - } - else - { - options.Listen(IPAddress.Loopback, port); - } - }) - .UseContentRoot(contentRoot) - .Build(); - } - - public void SetAuth(string path, string username, string password) => _auths.Add(path, (username, password)); - - public void SetCSP(string path, string csp) => _csp.Add(path, csp); - - public Task StartAsync() => _webHost.StartAsync(); - - public async Task StopAsync() - { - Reset(); - - await _webHost.StopAsync(); - } - - public void Reset() - { - _routes.Clear(); - _auths.Clear(); - _csp.Clear(); - _subscribers.Clear(); - _requestWaits.Clear(); - GzipRoutes.Clear(); - foreach (var subscriber in _subscribers.Values) - { - subscriber(null); - } - _subscribers.Clear(); - } - - public void EnableGzip(string path) => GzipRoutes.Add(path); - - public void SetRoute(string path, RequestDelegate handler) => _routes[path] = handler; - - public void SetRedirect(string from, string to) => SetRoute(from, context => - { - context.Response.Redirect(to); - return Task.CompletedTask; - }); - - public void Subscribe(string path, Action action) - => _subscribers.Add(path, action); - - public async Task WaitForRequest(string path, Func selector) - { - var taskCompletion = new TaskCompletionSource(); - _requestWaits.Add(path, context => - { - taskCompletion.SetResult(selector(context.Request)); - }); - - var request = await taskCompletion.Task; - _requestWaits.Remove(path); - - return request; - } - - public Task WaitForRequest(string path) => WaitForRequest(path, _ => true); - - private static bool Authenticate(string username, string password, HttpContext context) - { - string authHeader = context.Request.Headers["Authorization"]; - if (authHeader != null && authHeader.StartsWith("Basic", StringComparison.Ordinal)) - { - string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim(); - var encoding = Encoding.GetEncoding("iso-8859-1"); - string auth = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword)); - - return auth == $"{username}:{password}"; - } - return false; - } - - private async Task ReceiveLoopAsync(WebSocket webSocket, bool sendCloseMessage, CancellationToken token) - { - int connectionId = NextConnectionId(); - _clients.Add(connectionId, webSocket); - - byte[] buffer = new byte[MaxMessageSize]; - - try - { - while (true) - { - var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), token); - - if (result.MessageType == WebSocketMessageType.Close) - { - if (sendCloseMessage) - { - await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Close", CancellationToken.None); - } - break; - } - - var data = await ReadFrames(result, webSocket, buffer, token); - - if (data.Count == 0) - { - break; - } - } - } - finally - { - _clients.Remove(connectionId); - } - } - - private async Task> ReadFrames(WebSocketReceiveResult result, WebSocket webSocket, byte[] buffer, CancellationToken token) - { - int count = result.Count; - - while (!result.EndOfMessage) - { - if (count >= MaxMessageSize) - { - string closeMessage = string.Format("Maximum message size: {0} bytes.", MaxMessageSize); - await webSocket.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, CancellationToken.None); - return new ArraySegment(); - } - - result = await webSocket.ReceiveAsync(new ArraySegment(buffer, count, MaxMessageSize - count), CancellationToken.None); - count += result.Count; - - } - return new ArraySegment(buffer, 0, count); - } - - - private static int NextConnectionId() - { - int id = Interlocked.Increment(ref counter); - - if (id == int.MaxValue) - { - throw new Exception("connection id limit reached: " + id); - } - - return id; - } - } -} +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Net; +using System.Net.WebSockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; + +namespace PlaywrightSharp.TestServer +{ + public class SimpleServer + { + const int MaxMessageSize = 256 * 1024; + + private readonly IDictionary> _subscribers; + private readonly IDictionary> _requestWaits; + private readonly IDictionary _routes; + private readonly IDictionary _auths; + private readonly IDictionary _csp; + private readonly IWebHost _webHost; + private static int counter; + private readonly Dictionary _clients = new Dictionary(); + + internal IList GzipRoutes { get; } + + public event EventHandler RequestReceived; + + public static SimpleServer Create(int port, string contentRoot) => new SimpleServer(port, contentRoot, isHttps: false); + + public static SimpleServer CreateHttps(int port, string contentRoot) => new SimpleServer(port, contentRoot, isHttps: true); + + public SimpleServer(int port, string contentRoot, bool isHttps) + { + _subscribers = new ConcurrentDictionary>(); + _requestWaits = new ConcurrentDictionary>(); + _routes = new ConcurrentDictionary(); + _auths = new ConcurrentDictionary(); + _csp = new ConcurrentDictionary(); + GzipRoutes = new List(); + + _webHost = new WebHostBuilder() + .ConfigureAppConfiguration((context, builder) => builder + .SetBasePath(context.HostingEnvironment.ContentRootPath) + .AddEnvironmentVariables() + ) + .Configure(app => app +#if NETCOREAPP + .UseWebSockets() +#endif + .Use(async (context, next) => + { + RequestReceived?.Invoke(this, new RequestReceivedEventArgs { Request = context.Request }); + + if (context.Request.Path == "/ws") + { + if (context.WebSockets.IsWebSocketRequest) + { + var webSocket = await context.WebSockets.AcceptWebSocketAsync(); + await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes("incoming")), WebSocketMessageType.Text, true, CancellationToken.None); + await ReceiveLoopAsync(webSocket, context.Request.Headers["User-Agent"].ToString().Contains("Firefox"), CancellationToken.None); + } + else if (!context.Response.HasStarted) + { + context.Response.StatusCode = 400; + } + return; + } + + if (_auths.TryGetValue(context.Request.Path, out var auth) && !Authenticate(auth.username, auth.password, context)) + { + context.Response.Headers.Add("WWW-Authenticate", "Basic realm=\"Secure Area\""); + + if (!context.Response.HasStarted) + { + context.Response.StatusCode = StatusCodes.Status401Unauthorized; + } + await context.Response.WriteAsync("HTTP Error 401 Unauthorized: Access is denied"); + } + if (_subscribers.TryGetValue(context.Request.Path, out var subscriber)) + { + subscriber(context); + } + if (_requestWaits.TryGetValue(context.Request.Path, out var requestWait)) + { + requestWait(context); + } + if (_routes.TryGetValue(context.Request.Path + context.Request.QueryString, out var handler)) + { + await handler(context); + return; + } + + if ( + context.Request.Path.ToString().Contains("/cached/") && + !string.IsNullOrEmpty(context.Request.Headers["if-modified-since"]) && + !context.Response.HasStarted) + { + context.Response.StatusCode = StatusCodes.Status304NotModified; + } + + await next(); + }) + .UseMiddleware(this) + .UseStaticFiles(new StaticFileOptions + { + OnPrepareResponse = fileResponseContext => + { + if (_csp.TryGetValue(fileResponseContext.Context.Request.Path, out string csp)) + { + fileResponseContext.Context.Response.Headers["Content-Security-Policy"] = csp; + } + + if (fileResponseContext.Context.Request.Path.ToString().EndsWith(".html")) + { + fileResponseContext.Context.Response.Headers["Content-Type"] = "text/html; charset=utf-8"; + + if (fileResponseContext.Context.Request.Path.ToString().Contains("/cached/")) + { + fileResponseContext.Context.Response.Headers["Cache-Control"] = "public, max-age=31536000, no-cache"; + fileResponseContext.Context.Response.Headers["Last-Modified"] = DateTime.Now.ToString("s"); + } + else + { + fileResponseContext.Context.Response.Headers["Cache-Control"] = "no-cache, no-store"; + } + } + } + })) + .UseKestrel(options => + { + if (isHttps) + { + options.Listen(IPAddress.Loopback, port, listenOptions => listenOptions.UseHttps("testCert.cer")); + } + else + { + options.Listen(IPAddress.Loopback, port); + } + }) + .UseContentRoot(contentRoot) + .Build(); + } + + public void SetAuth(string path, string username, string password) => _auths.Add(path, (username, password)); + + public void SetCSP(string path, string csp) => _csp.Add(path, csp); + + public Task StartAsync() => _webHost.StartAsync(); + + public async Task StopAsync() + { + Reset(); + + await _webHost.StopAsync(); + } + + public void Reset() + { + _routes.Clear(); + _auths.Clear(); + _csp.Clear(); + _subscribers.Clear(); + _requestWaits.Clear(); + GzipRoutes.Clear(); + foreach (var subscriber in _subscribers.Values) + { + subscriber(null); + } + _subscribers.Clear(); + } + + public void EnableGzip(string path) => GzipRoutes.Add(path); + + public void SetRoute(string path, RequestDelegate handler) => _routes[path] = handler; + + public void SetRedirect(string from, string to) => SetRoute(from, context => + { + context.Response.Redirect(to); + return Task.CompletedTask; + }); + + public void Subscribe(string path, Action action) + => _subscribers.Add(path, action); + + public async Task WaitForRequest(string path, Func selector) + { + var taskCompletion = new TaskCompletionSource(); + _requestWaits.Add(path, context => + { + taskCompletion.SetResult(selector(context.Request)); + }); + + var request = await taskCompletion.Task; + _requestWaits.Remove(path); + + return request; + } + + public Task WaitForRequest(string path) => WaitForRequest(path, _ => true); + + private static bool Authenticate(string username, string password, HttpContext context) + { + string authHeader = context.Request.Headers["Authorization"]; + if (authHeader != null && authHeader.StartsWith("Basic", StringComparison.Ordinal)) + { + string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim(); + var encoding = Encoding.GetEncoding("iso-8859-1"); + string auth = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword)); + + return auth == $"{username}:{password}"; + } + return false; + } + + private async Task ReceiveLoopAsync(WebSocket webSocket, bool sendCloseMessage, CancellationToken token) + { + int connectionId = NextConnectionId(); + _clients.Add(connectionId, webSocket); + + byte[] buffer = new byte[MaxMessageSize]; + + try + { + while (true) + { + var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), token); + + if (result.MessageType == WebSocketMessageType.Close) + { + if (sendCloseMessage) + { + await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Close", CancellationToken.None); + } + break; + } + + var data = await ReadFrames(result, webSocket, buffer, token); + + if (data.Count == 0) + { + break; + } + } + } + finally + { + _clients.Remove(connectionId); + } + } + + private async Task> ReadFrames(WebSocketReceiveResult result, WebSocket webSocket, byte[] buffer, CancellationToken token) + { + int count = result.Count; + + while (!result.EndOfMessage) + { + if (count >= MaxMessageSize) + { + string closeMessage = string.Format("Maximum message size: {0} bytes.", MaxMessageSize); + await webSocket.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, CancellationToken.None); + return new ArraySegment(); + } + + result = await webSocket.ReceiveAsync(new ArraySegment(buffer, count, MaxMessageSize - count), CancellationToken.None); + count += result.Count; + + } + return new ArraySegment(buffer, 0, count); + } + + + private static int NextConnectionId() + { + int id = Interlocked.Increment(ref counter); + + if (id == int.MaxValue) + { + throw new Exception("connection id limit reached: " + id); + } + + return id; + } + } +} diff --git a/src/Playwright.Tests.TestServer/testCert.cer b/src/PlaywrightSharp.TestServer/testCert.cer similarity index 100% rename from src/Playwright.Tests.TestServer/testCert.cer rename to src/PlaywrightSharp.TestServer/testCert.cer diff --git a/src/Playwright.Tests.TestServer/wwwroot/background-color.html b/src/PlaywrightSharp.TestServer/wwwroot/background-color.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/background-color.html rename to src/PlaywrightSharp.TestServer/wwwroot/background-color.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/beforeunload.html b/src/PlaywrightSharp.TestServer/wwwroot/beforeunload.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/beforeunload.html rename to src/PlaywrightSharp.TestServer/wwwroot/beforeunload.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/button-overlay-oopif.html b/src/PlaywrightSharp.TestServer/wwwroot/button-overlay-oopif.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/button-overlay-oopif.html rename to src/PlaywrightSharp.TestServer/wwwroot/button-overlay-oopif.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/cached/one-style.css b/src/PlaywrightSharp.TestServer/wwwroot/cached/one-style.css similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/cached/one-style.css rename to src/PlaywrightSharp.TestServer/wwwroot/cached/one-style.css diff --git a/src/Playwright.Tests.TestServer/wwwroot/cached/one-style.html b/src/PlaywrightSharp.TestServer/wwwroot/cached/one-style.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/cached/one-style.html rename to src/PlaywrightSharp.TestServer/wwwroot/cached/one-style.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/checkerboard.html b/src/PlaywrightSharp.TestServer/wwwroot/checkerboard.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/checkerboard.html rename to src/PlaywrightSharp.TestServer/wwwroot/checkerboard.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/chromium-linux.zip b/src/PlaywrightSharp.TestServer/wwwroot/chromium-linux.zip similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/chromium-linux.zip rename to src/PlaywrightSharp.TestServer/wwwroot/chromium-linux.zip diff --git a/src/Playwright.Tests.TestServer/wwwroot/consolelog.html b/src/PlaywrightSharp.TestServer/wwwroot/consolelog.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/consolelog.html rename to src/PlaywrightSharp.TestServer/wwwroot/consolelog.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/csp.html b/src/PlaywrightSharp.TestServer/wwwroot/csp.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/csp.html rename to src/PlaywrightSharp.TestServer/wwwroot/csp.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/csscoverage/Dosis-Regular.ttf b/src/PlaywrightSharp.TestServer/wwwroot/csscoverage/Dosis-Regular.ttf similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/csscoverage/Dosis-Regular.ttf rename to src/PlaywrightSharp.TestServer/wwwroot/csscoverage/Dosis-Regular.ttf diff --git a/src/Playwright.Tests.TestServer/wwwroot/csscoverage/OFL.txt b/src/PlaywrightSharp.TestServer/wwwroot/csscoverage/OFL.txt similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/csscoverage/OFL.txt rename to src/PlaywrightSharp.TestServer/wwwroot/csscoverage/OFL.txt diff --git a/src/Playwright.Tests.TestServer/wwwroot/csscoverage/involved.html b/src/PlaywrightSharp.TestServer/wwwroot/csscoverage/involved.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/csscoverage/involved.html rename to src/PlaywrightSharp.TestServer/wwwroot/csscoverage/involved.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/csscoverage/media.html b/src/PlaywrightSharp.TestServer/wwwroot/csscoverage/media.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/csscoverage/media.html rename to src/PlaywrightSharp.TestServer/wwwroot/csscoverage/media.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/csscoverage/multiple.html b/src/PlaywrightSharp.TestServer/wwwroot/csscoverage/multiple.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/csscoverage/multiple.html rename to src/PlaywrightSharp.TestServer/wwwroot/csscoverage/multiple.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/csscoverage/simple.html b/src/PlaywrightSharp.TestServer/wwwroot/csscoverage/simple.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/csscoverage/simple.html rename to src/PlaywrightSharp.TestServer/wwwroot/csscoverage/simple.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/csscoverage/sourceurl.html b/src/PlaywrightSharp.TestServer/wwwroot/csscoverage/sourceurl.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/csscoverage/sourceurl.html rename to src/PlaywrightSharp.TestServer/wwwroot/csscoverage/sourceurl.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/csscoverage/stylesheet1.css b/src/PlaywrightSharp.TestServer/wwwroot/csscoverage/stylesheet1.css similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/csscoverage/stylesheet1.css rename to src/PlaywrightSharp.TestServer/wwwroot/csscoverage/stylesheet1.css diff --git a/src/Playwright.Tests.TestServer/wwwroot/csscoverage/stylesheet2.css b/src/PlaywrightSharp.TestServer/wwwroot/csscoverage/stylesheet2.css similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/csscoverage/stylesheet2.css rename to src/PlaywrightSharp.TestServer/wwwroot/csscoverage/stylesheet2.css diff --git a/src/Playwright.Tests.TestServer/wwwroot/csscoverage/unused.html b/src/PlaywrightSharp.TestServer/wwwroot/csscoverage/unused.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/csscoverage/unused.html rename to src/PlaywrightSharp.TestServer/wwwroot/csscoverage/unused.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/deep-shadow.html b/src/PlaywrightSharp.TestServer/wwwroot/deep-shadow.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/deep-shadow.html rename to src/PlaywrightSharp.TestServer/wwwroot/deep-shadow.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/detect-touch.html b/src/PlaywrightSharp.TestServer/wwwroot/detect-touch.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/detect-touch.html rename to src/PlaywrightSharp.TestServer/wwwroot/detect-touch.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/digits/0.png b/src/PlaywrightSharp.TestServer/wwwroot/digits/0.png similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/digits/0.png rename to src/PlaywrightSharp.TestServer/wwwroot/digits/0.png diff --git a/src/Playwright.Tests.TestServer/wwwroot/digits/1.png b/src/PlaywrightSharp.TestServer/wwwroot/digits/1.png similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/digits/1.png rename to src/PlaywrightSharp.TestServer/wwwroot/digits/1.png diff --git a/src/Playwright.Tests.TestServer/wwwroot/digits/2.png b/src/PlaywrightSharp.TestServer/wwwroot/digits/2.png similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/digits/2.png rename to src/PlaywrightSharp.TestServer/wwwroot/digits/2.png diff --git a/src/Playwright.Tests.TestServer/wwwroot/digits/3.png b/src/PlaywrightSharp.TestServer/wwwroot/digits/3.png similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/digits/3.png rename to src/PlaywrightSharp.TestServer/wwwroot/digits/3.png diff --git a/src/Playwright.Tests.TestServer/wwwroot/digits/4.png b/src/PlaywrightSharp.TestServer/wwwroot/digits/4.png similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/digits/4.png rename to src/PlaywrightSharp.TestServer/wwwroot/digits/4.png diff --git a/src/Playwright.Tests.TestServer/wwwroot/digits/5.png b/src/PlaywrightSharp.TestServer/wwwroot/digits/5.png similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/digits/5.png rename to src/PlaywrightSharp.TestServer/wwwroot/digits/5.png diff --git a/src/Playwright.Tests.TestServer/wwwroot/digits/6.png b/src/PlaywrightSharp.TestServer/wwwroot/digits/6.png similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/digits/6.png rename to src/PlaywrightSharp.TestServer/wwwroot/digits/6.png diff --git a/src/Playwright.Tests.TestServer/wwwroot/digits/7.png b/src/PlaywrightSharp.TestServer/wwwroot/digits/7.png similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/digits/7.png rename to src/PlaywrightSharp.TestServer/wwwroot/digits/7.png diff --git a/src/Playwright.Tests.TestServer/wwwroot/digits/8.png b/src/PlaywrightSharp.TestServer/wwwroot/digits/8.png similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/digits/8.png rename to src/PlaywrightSharp.TestServer/wwwroot/digits/8.png diff --git a/src/Playwright.Tests.TestServer/wwwroot/digits/9.png b/src/PlaywrightSharp.TestServer/wwwroot/digits/9.png similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/digits/9.png rename to src/PlaywrightSharp.TestServer/wwwroot/digits/9.png diff --git a/src/Playwright.Tests.TestServer/wwwroot/dom.html b/src/PlaywrightSharp.TestServer/wwwroot/dom.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/dom.html rename to src/PlaywrightSharp.TestServer/wwwroot/dom.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/download-blob.html b/src/PlaywrightSharp.TestServer/wwwroot/download-blob.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/download-blob.html rename to src/PlaywrightSharp.TestServer/wwwroot/download-blob.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/drag-n-drop.html b/src/PlaywrightSharp.TestServer/wwwroot/drag-n-drop.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/drag-n-drop.html rename to src/PlaywrightSharp.TestServer/wwwroot/drag-n-drop.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/dummy_bad_browser_executable.js b/src/PlaywrightSharp.TestServer/wwwroot/dummy_bad_browser_executable.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/dummy_bad_browser_executable.js rename to src/PlaywrightSharp.TestServer/wwwroot/dummy_bad_browser_executable.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/dynamic-oopif.html b/src/PlaywrightSharp.TestServer/wwwroot/dynamic-oopif.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/dynamic-oopif.html rename to src/PlaywrightSharp.TestServer/wwwroot/dynamic-oopif.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/empty.html b/src/PlaywrightSharp.TestServer/wwwroot/empty.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/empty.html rename to src/PlaywrightSharp.TestServer/wwwroot/empty.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/error.html b/src/PlaywrightSharp.TestServer/wwwroot/error.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/error.html rename to src/PlaywrightSharp.TestServer/wwwroot/error.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/es6/.eslintrc b/src/PlaywrightSharp.TestServer/wwwroot/es6/.eslintrc similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/es6/.eslintrc rename to src/PlaywrightSharp.TestServer/wwwroot/es6/.eslintrc diff --git a/src/Playwright.Tests.TestServer/wwwroot/es6/es6import.js b/src/PlaywrightSharp.TestServer/wwwroot/es6/es6import.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/es6/es6import.js rename to src/PlaywrightSharp.TestServer/wwwroot/es6/es6import.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/es6/es6module.js b/src/PlaywrightSharp.TestServer/wwwroot/es6/es6module.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/es6/es6module.js rename to src/PlaywrightSharp.TestServer/wwwroot/es6/es6module.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/es6/es6pathimport.js b/src/PlaywrightSharp.TestServer/wwwroot/es6/es6pathimport.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/es6/es6pathimport.js rename to src/PlaywrightSharp.TestServer/wwwroot/es6/es6pathimport.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/file-to-upload.txt b/src/PlaywrightSharp.TestServer/wwwroot/file-to-upload.txt similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/file-to-upload.txt rename to src/PlaywrightSharp.TestServer/wwwroot/file-to-upload.txt diff --git a/src/Playwright.Tests.TestServer/wwwroot/formatted-number.html b/src/PlaywrightSharp.TestServer/wwwroot/formatted-number.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/formatted-number.html rename to src/PlaywrightSharp.TestServer/wwwroot/formatted-number.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/frames/child-redirect.html b/src/PlaywrightSharp.TestServer/wwwroot/frames/child-redirect.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/frames/child-redirect.html rename to src/PlaywrightSharp.TestServer/wwwroot/frames/child-redirect.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/frames/frame.html b/src/PlaywrightSharp.TestServer/wwwroot/frames/frame.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/frames/frame.html rename to src/PlaywrightSharp.TestServer/wwwroot/frames/frame.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/frames/frameset.html b/src/PlaywrightSharp.TestServer/wwwroot/frames/frameset.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/frames/frameset.html rename to src/PlaywrightSharp.TestServer/wwwroot/frames/frameset.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/frames/lazy-frame.html b/src/PlaywrightSharp.TestServer/wwwroot/frames/lazy-frame.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/frames/lazy-frame.html rename to src/PlaywrightSharp.TestServer/wwwroot/frames/lazy-frame.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/frames/nested-frames.html b/src/PlaywrightSharp.TestServer/wwwroot/frames/nested-frames.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/frames/nested-frames.html rename to src/PlaywrightSharp.TestServer/wwwroot/frames/nested-frames.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/frames/one-frame.html b/src/PlaywrightSharp.TestServer/wwwroot/frames/one-frame.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/frames/one-frame.html rename to src/PlaywrightSharp.TestServer/wwwroot/frames/one-frame.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/frames/redirect-my-parent.html b/src/PlaywrightSharp.TestServer/wwwroot/frames/redirect-my-parent.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/frames/redirect-my-parent.html rename to src/PlaywrightSharp.TestServer/wwwroot/frames/redirect-my-parent.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/frames/script.js b/src/PlaywrightSharp.TestServer/wwwroot/frames/script.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/frames/script.js rename to src/PlaywrightSharp.TestServer/wwwroot/frames/script.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/frames/style.css b/src/PlaywrightSharp.TestServer/wwwroot/frames/style.css similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/frames/style.css rename to src/PlaywrightSharp.TestServer/wwwroot/frames/style.css diff --git a/src/Playwright.Tests.TestServer/wwwroot/frames/two-frames.html b/src/PlaywrightSharp.TestServer/wwwroot/frames/two-frames.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/frames/two-frames.html rename to src/PlaywrightSharp.TestServer/wwwroot/frames/two-frames.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/geolocation.html b/src/PlaywrightSharp.TestServer/wwwroot/geolocation.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/geolocation.html rename to src/PlaywrightSharp.TestServer/wwwroot/geolocation.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/global-var.html b/src/PlaywrightSharp.TestServer/wwwroot/global-var.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/global-var.html rename to src/PlaywrightSharp.TestServer/wwwroot/global-var.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/grid-iframe-in-shadow.html b/src/PlaywrightSharp.TestServer/wwwroot/grid-iframe-in-shadow.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/grid-iframe-in-shadow.html rename to src/PlaywrightSharp.TestServer/wwwroot/grid-iframe-in-shadow.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/grid.html b/src/PlaywrightSharp.TestServer/wwwroot/grid.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/grid.html rename to src/PlaywrightSharp.TestServer/wwwroot/grid.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/har.html b/src/PlaywrightSharp.TestServer/wwwroot/har.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/har.html rename to src/PlaywrightSharp.TestServer/wwwroot/har.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/highdpi.html b/src/PlaywrightSharp.TestServer/wwwroot/highdpi.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/highdpi.html rename to src/PlaywrightSharp.TestServer/wwwroot/highdpi.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/historyapi.html b/src/PlaywrightSharp.TestServer/wwwroot/historyapi.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/historyapi.html rename to src/PlaywrightSharp.TestServer/wwwroot/historyapi.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/injectedfile.js b/src/PlaywrightSharp.TestServer/wwwroot/injectedfile.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/injectedfile.js rename to src/PlaywrightSharp.TestServer/wwwroot/injectedfile.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/injectedstyle.css b/src/PlaywrightSharp.TestServer/wwwroot/injectedstyle.css similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/injectedstyle.css rename to src/PlaywrightSharp.TestServer/wwwroot/injectedstyle.css diff --git a/src/Playwright.Tests.TestServer/wwwroot/input/animating-button.html b/src/PlaywrightSharp.TestServer/wwwroot/input/animating-button.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/input/animating-button.html rename to src/PlaywrightSharp.TestServer/wwwroot/input/animating-button.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/input/button.html b/src/PlaywrightSharp.TestServer/wwwroot/input/button.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/input/button.html rename to src/PlaywrightSharp.TestServer/wwwroot/input/button.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/input/checkbox.html b/src/PlaywrightSharp.TestServer/wwwroot/input/checkbox.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/input/checkbox.html rename to src/PlaywrightSharp.TestServer/wwwroot/input/checkbox.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/input/fileupload.html b/src/PlaywrightSharp.TestServer/wwwroot/input/fileupload.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/input/fileupload.html rename to src/PlaywrightSharp.TestServer/wwwroot/input/fileupload.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/input/keyboard.html b/src/PlaywrightSharp.TestServer/wwwroot/input/keyboard.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/input/keyboard.html rename to src/PlaywrightSharp.TestServer/wwwroot/input/keyboard.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/input/mouse-helper.js b/src/PlaywrightSharp.TestServer/wwwroot/input/mouse-helper.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/input/mouse-helper.js rename to src/PlaywrightSharp.TestServer/wwwroot/input/mouse-helper.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/input/rotatedButton.html b/src/PlaywrightSharp.TestServer/wwwroot/input/rotatedButton.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/input/rotatedButton.html rename to src/PlaywrightSharp.TestServer/wwwroot/input/rotatedButton.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/input/scrollable.html b/src/PlaywrightSharp.TestServer/wwwroot/input/scrollable.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/input/scrollable.html rename to src/PlaywrightSharp.TestServer/wwwroot/input/scrollable.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/input/select.html b/src/PlaywrightSharp.TestServer/wwwroot/input/select.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/input/select.html rename to src/PlaywrightSharp.TestServer/wwwroot/input/select.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/input/textarea.html b/src/PlaywrightSharp.TestServer/wwwroot/input/textarea.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/input/textarea.html rename to src/PlaywrightSharp.TestServer/wwwroot/input/textarea.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/input/touches.html b/src/PlaywrightSharp.TestServer/wwwroot/input/touches.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/input/touches.html rename to src/PlaywrightSharp.TestServer/wwwroot/input/touches.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/jscoverage/eval.html b/src/PlaywrightSharp.TestServer/wwwroot/jscoverage/eval.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/jscoverage/eval.html rename to src/PlaywrightSharp.TestServer/wwwroot/jscoverage/eval.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/jscoverage/involved.html b/src/PlaywrightSharp.TestServer/wwwroot/jscoverage/involved.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/jscoverage/involved.html rename to src/PlaywrightSharp.TestServer/wwwroot/jscoverage/involved.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/jscoverage/multiple.html b/src/PlaywrightSharp.TestServer/wwwroot/jscoverage/multiple.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/jscoverage/multiple.html rename to src/PlaywrightSharp.TestServer/wwwroot/jscoverage/multiple.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/jscoverage/ranges.html b/src/PlaywrightSharp.TestServer/wwwroot/jscoverage/ranges.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/jscoverage/ranges.html rename to src/PlaywrightSharp.TestServer/wwwroot/jscoverage/ranges.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/jscoverage/script1.js b/src/PlaywrightSharp.TestServer/wwwroot/jscoverage/script1.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/jscoverage/script1.js rename to src/PlaywrightSharp.TestServer/wwwroot/jscoverage/script1.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/jscoverage/script2.js b/src/PlaywrightSharp.TestServer/wwwroot/jscoverage/script2.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/jscoverage/script2.js rename to src/PlaywrightSharp.TestServer/wwwroot/jscoverage/script2.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/jscoverage/simple.html b/src/PlaywrightSharp.TestServer/wwwroot/jscoverage/simple.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/jscoverage/simple.html rename to src/PlaywrightSharp.TestServer/wwwroot/jscoverage/simple.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/jscoverage/sourceurl.html b/src/PlaywrightSharp.TestServer/wwwroot/jscoverage/sourceurl.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/jscoverage/sourceurl.html rename to src/PlaywrightSharp.TestServer/wwwroot/jscoverage/sourceurl.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/jscoverage/unused.html b/src/PlaywrightSharp.TestServer/wwwroot/jscoverage/unused.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/jscoverage/unused.html rename to src/PlaywrightSharp.TestServer/wwwroot/jscoverage/unused.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/mobile.html b/src/PlaywrightSharp.TestServer/wwwroot/mobile.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/mobile.html rename to src/PlaywrightSharp.TestServer/wwwroot/mobile.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/modernizr.js b/src/PlaywrightSharp.TestServer/wwwroot/modernizr.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/modernizr.js rename to src/PlaywrightSharp.TestServer/wwwroot/modernizr.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/movie.mp4 b/src/PlaywrightSharp.TestServer/wwwroot/movie.mp4 similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/movie.mp4 rename to src/PlaywrightSharp.TestServer/wwwroot/movie.mp4 diff --git a/src/Playwright.Tests.TestServer/wwwroot/movie.ogv b/src/PlaywrightSharp.TestServer/wwwroot/movie.ogv similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/movie.ogv rename to src/PlaywrightSharp.TestServer/wwwroot/movie.ogv diff --git a/src/Playwright.Tests.TestServer/wwwroot/networkidle-frame.html b/src/PlaywrightSharp.TestServer/wwwroot/networkidle-frame.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/networkidle-frame.html rename to src/PlaywrightSharp.TestServer/wwwroot/networkidle-frame.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/networkidle.html b/src/PlaywrightSharp.TestServer/wwwroot/networkidle.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/networkidle.html rename to src/PlaywrightSharp.TestServer/wwwroot/networkidle.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/networkidle.js b/src/PlaywrightSharp.TestServer/wwwroot/networkidle.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/networkidle.js rename to src/PlaywrightSharp.TestServer/wwwroot/networkidle.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/offscreenbuttons.html b/src/PlaywrightSharp.TestServer/wwwroot/offscreenbuttons.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/offscreenbuttons.html rename to src/PlaywrightSharp.TestServer/wwwroot/offscreenbuttons.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/one-style.css b/src/PlaywrightSharp.TestServer/wwwroot/one-style.css similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/one-style.css rename to src/PlaywrightSharp.TestServer/wwwroot/one-style.css diff --git a/src/Playwright.Tests.TestServer/wwwroot/one-style.html b/src/PlaywrightSharp.TestServer/wwwroot/one-style.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/one-style.html rename to src/PlaywrightSharp.TestServer/wwwroot/one-style.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/overflow-large.html b/src/PlaywrightSharp.TestServer/wwwroot/overflow-large.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/overflow-large.html rename to src/PlaywrightSharp.TestServer/wwwroot/overflow-large.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/overflow.html b/src/PlaywrightSharp.TestServer/wwwroot/overflow.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/overflow.html rename to src/PlaywrightSharp.TestServer/wwwroot/overflow.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/player.html b/src/PlaywrightSharp.TestServer/wwwroot/player.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/player.html rename to src/PlaywrightSharp.TestServer/wwwroot/player.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/playground.html b/src/PlaywrightSharp.TestServer/wwwroot/playground.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/playground.html rename to src/PlaywrightSharp.TestServer/wwwroot/playground.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/playwrightweb.html b/src/PlaywrightSharp.TestServer/wwwroot/playwrightweb.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/playwrightweb.html rename to src/PlaywrightSharp.TestServer/wwwroot/playwrightweb.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/popup/popup.html b/src/PlaywrightSharp.TestServer/wwwroot/popup/popup.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/popup/popup.html rename to src/PlaywrightSharp.TestServer/wwwroot/popup/popup.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/popup/window-open.html b/src/PlaywrightSharp.TestServer/wwwroot/popup/window-open.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/popup/window-open.html rename to src/PlaywrightSharp.TestServer/wwwroot/popup/window-open.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/pptr.png b/src/PlaywrightSharp.TestServer/wwwroot/pptr.png similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/pptr.png rename to src/PlaywrightSharp.TestServer/wwwroot/pptr.png diff --git a/src/Playwright.Tests.TestServer/wwwroot/react.html b/src/PlaywrightSharp.TestServer/wwwroot/react.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/react.html rename to src/PlaywrightSharp.TestServer/wwwroot/react.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/react/react-dom@16.13.1.production.min.js b/src/PlaywrightSharp.TestServer/wwwroot/react/react-dom@16.13.1.production.min.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/react/react-dom@16.13.1.production.min.js rename to src/PlaywrightSharp.TestServer/wwwroot/react/react-dom@16.13.1.production.min.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/react/react@16.13.1.production.min.js b/src/PlaywrightSharp.TestServer/wwwroot/react/react@16.13.1.production.min.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/react/react@16.13.1.production.min.js rename to src/PlaywrightSharp.TestServer/wwwroot/react/react@16.13.1.production.min.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/redirectloop1.html b/src/PlaywrightSharp.TestServer/wwwroot/redirectloop1.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/redirectloop1.html rename to src/PlaywrightSharp.TestServer/wwwroot/redirectloop1.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/redirectloop2.html b/src/PlaywrightSharp.TestServer/wwwroot/redirectloop2.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/redirectloop2.html rename to src/PlaywrightSharp.TestServer/wwwroot/redirectloop2.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/resetcss.html b/src/PlaywrightSharp.TestServer/wwwroot/resetcss.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/resetcss.html rename to src/PlaywrightSharp.TestServer/wwwroot/resetcss.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/rotate-z.html b/src/PlaywrightSharp.TestServer/wwwroot/rotate-z.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/rotate-z.html rename to src/PlaywrightSharp.TestServer/wwwroot/rotate-z.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/screenshots/canvas.html b/src/PlaywrightSharp.TestServer/wwwroot/screenshots/canvas.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/screenshots/canvas.html rename to src/PlaywrightSharp.TestServer/wwwroot/screenshots/canvas.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/screenshots/controls.html b/src/PlaywrightSharp.TestServer/wwwroot/screenshots/controls.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/screenshots/controls.html rename to src/PlaywrightSharp.TestServer/wwwroot/screenshots/controls.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/screenshots/translateZ.html b/src/PlaywrightSharp.TestServer/wwwroot/screenshots/translateZ.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/screenshots/translateZ.html rename to src/PlaywrightSharp.TestServer/wwwroot/screenshots/translateZ.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/screenshots/webgl.html b/src/PlaywrightSharp.TestServer/wwwroot/screenshots/webgl.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/screenshots/webgl.html rename to src/PlaywrightSharp.TestServer/wwwroot/screenshots/webgl.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/sectionselectorengine.js b/src/PlaywrightSharp.TestServer/wwwroot/sectionselectorengine.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/sectionselectorengine.js rename to src/PlaywrightSharp.TestServer/wwwroot/sectionselectorengine.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/self-request.html b/src/PlaywrightSharp.TestServer/wwwroot/self-request.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/self-request.html rename to src/PlaywrightSharp.TestServer/wwwroot/self-request.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/serviceworkers/empty/sw.html b/src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/empty/sw.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/serviceworkers/empty/sw.html rename to src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/empty/sw.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/serviceworkers/empty/sw.js b/src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/empty/sw.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/serviceworkers/empty/sw.js rename to src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/empty/sw.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/serviceworkers/fetch/style.css b/src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/fetch/style.css similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/serviceworkers/fetch/style.css rename to src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/fetch/style.css diff --git a/src/Playwright.Tests.TestServer/wwwroot/serviceworkers/fetch/sw.html b/src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/fetch/sw.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/serviceworkers/fetch/sw.html rename to src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/fetch/sw.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/serviceworkers/fetch/sw.js b/src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/fetch/sw.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/serviceworkers/fetch/sw.js rename to src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/fetch/sw.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/serviceworkers/fetchdummy/sw.html b/src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/fetchdummy/sw.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/serviceworkers/fetchdummy/sw.html rename to src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/fetchdummy/sw.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/serviceworkers/fetchdummy/sw.js b/src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/fetchdummy/sw.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/serviceworkers/fetchdummy/sw.js rename to src/PlaywrightSharp.TestServer/wwwroot/serviceworkers/fetchdummy/sw.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/shadow.html b/src/PlaywrightSharp.TestServer/wwwroot/shadow.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/shadow.html rename to src/PlaywrightSharp.TestServer/wwwroot/shadow.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/simple-extension/content-script.js b/src/PlaywrightSharp.TestServer/wwwroot/simple-extension/content-script.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/simple-extension/content-script.js rename to src/PlaywrightSharp.TestServer/wwwroot/simple-extension/content-script.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/simple-extension/index.js b/src/PlaywrightSharp.TestServer/wwwroot/simple-extension/index.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/simple-extension/index.js rename to src/PlaywrightSharp.TestServer/wwwroot/simple-extension/index.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/simple-extension/manifest.json b/src/PlaywrightSharp.TestServer/wwwroot/simple-extension/manifest.json similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/simple-extension/manifest.json rename to src/PlaywrightSharp.TestServer/wwwroot/simple-extension/manifest.json diff --git a/src/Playwright.Tests.TestServer/wwwroot/simple.json b/src/PlaywrightSharp.TestServer/wwwroot/simple.json similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/simple.json rename to src/PlaywrightSharp.TestServer/wwwroot/simple.json diff --git a/src/Playwright.Tests.TestServer/wwwroot/snapshot/one.css b/src/PlaywrightSharp.TestServer/wwwroot/snapshot/one.css similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/snapshot/one.css rename to src/PlaywrightSharp.TestServer/wwwroot/snapshot/one.css diff --git a/src/Playwright.Tests.TestServer/wwwroot/snapshot/snapshot-with-css.html b/src/PlaywrightSharp.TestServer/wwwroot/snapshot/snapshot-with-css.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/snapshot/snapshot-with-css.html rename to src/PlaywrightSharp.TestServer/wwwroot/snapshot/snapshot-with-css.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/snapshot/two.css b/src/PlaywrightSharp.TestServer/wwwroot/snapshot/two.css similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/snapshot/two.css rename to src/PlaywrightSharp.TestServer/wwwroot/snapshot/two.css diff --git a/src/Playwright.Tests.TestServer/wwwroot/tamperable.html b/src/PlaywrightSharp.TestServer/wwwroot/tamperable.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/tamperable.html rename to src/PlaywrightSharp.TestServer/wwwroot/tamperable.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/title.html b/src/PlaywrightSharp.TestServer/wwwroot/title.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/title.html rename to src/PlaywrightSharp.TestServer/wwwroot/title.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/video.html b/src/PlaywrightSharp.TestServer/wwwroot/video.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/video.html rename to src/PlaywrightSharp.TestServer/wwwroot/video.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/video_mp4.html b/src/PlaywrightSharp.TestServer/wwwroot/video_mp4.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/video_mp4.html rename to src/PlaywrightSharp.TestServer/wwwroot/video_mp4.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/wasm/table2.html b/src/PlaywrightSharp.TestServer/wwwroot/wasm/table2.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/wasm/table2.html rename to src/PlaywrightSharp.TestServer/wwwroot/wasm/table2.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/wasm/table2.wasm b/src/PlaywrightSharp.TestServer/wwwroot/wasm/table2.wasm similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/wasm/table2.wasm rename to src/PlaywrightSharp.TestServer/wwwroot/wasm/table2.wasm diff --git a/src/Playwright.Tests.TestServer/wwwroot/worker/worker.html b/src/PlaywrightSharp.TestServer/wwwroot/worker/worker.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/worker/worker.html rename to src/PlaywrightSharp.TestServer/wwwroot/worker/worker.html diff --git a/src/Playwright.Tests.TestServer/wwwroot/worker/worker.js b/src/PlaywrightSharp.TestServer/wwwroot/worker/worker.js similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/worker/worker.js rename to src/PlaywrightSharp.TestServer/wwwroot/worker/worker.js diff --git a/src/Playwright.Tests.TestServer/wwwroot/wrappedlink.html b/src/PlaywrightSharp.TestServer/wwwroot/wrappedlink.html similarity index 100% rename from src/Playwright.Tests.TestServer/wwwroot/wrappedlink.html rename to src/PlaywrightSharp.TestServer/wwwroot/wrappedlink.html diff --git a/src/PlaywrightSharp.Tests/AssemblyInfo.cs b/src/PlaywrightSharp.Tests/AssemblyInfo.cs new file mode 100644 index 0000000000..132cc53a70 --- /dev/null +++ b/src/PlaywrightSharp.Tests/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using NUnit.Framework; + +[assembly: NonParallelizable] diff --git a/src/Playwright.Tests/Attributes/SkipBrowserAndPlatformFact.cs b/src/PlaywrightSharp.Tests/Attributes/SkipBrowserAndPlatformFact.cs similarity index 52% rename from src/Playwright.Tests/Attributes/SkipBrowserAndPlatformFact.cs rename to src/PlaywrightSharp.Tests/Attributes/SkipBrowserAndPlatformFact.cs index 092e9d1ef6..b3fa2f5864 100644 --- a/src/Playwright.Tests/Attributes/SkipBrowserAndPlatformFact.cs +++ b/src/PlaywrightSharp.Tests/Attributes/SkipBrowserAndPlatformFact.cs @@ -1,62 +1,81 @@ -using System.Runtime.InteropServices; -using Xunit; - -namespace Microsoft.Playwright.Tests.Attributes -{ - /// - /// Skip browsers and/or platforms - /// - public class SkipBrowserAndPlatformFact : FactAttribute - { - /// - /// Creates a new - /// - /// Skip firefox - /// Skip Chromium - /// Skip Webkit - /// Skip OSX - /// Skip Windows - /// Skip Linux - public SkipBrowserAndPlatformFact( - bool skipFirefox = false, - bool skipChromium = false, - bool skipWebkit = false, - bool skipOSX = false, - bool skipWindows = false, - bool skipLinux = false) - { - Timeout = TestConstants.DefaultTestTimeout; - - if (SkipBrowser(skipFirefox, skipChromium, skipWebkit) && SkipPlatform(skipOSX, skipWindows, skipLinux)) - { - Skip = "Skipped by browser/platform"; - } - } - - private static bool SkipPlatform(bool skipOSX, bool skipWindows, bool skipLinux) - => - ( - (skipOSX && RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) || - (skipWindows && RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) || - (skipLinux && RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - ) || - ( - !skipOSX && - !skipLinux && - !skipWindows - ); - - private static bool SkipBrowser(bool skipFirefox, bool skipChromium, bool skipWebkit) - => - ( - (skipFirefox && TestConstants.IsFirefox) || - (skipWebkit && TestConstants.IsWebKit) || - (skipChromium && TestConstants.IsChromium) - ) || - ( - !skipFirefox && - !skipWebkit && - !skipChromium - ); - } -} +using System; +using NUnit.Framework; +using NUnit.Framework.Interfaces; +using NUnit.Framework.Internal; +using OSPlatform = System.Runtime.InteropServices.OSPlatform; +using RuntimeInformation = System.Runtime.InteropServices.RuntimeInformation; + +namespace PlaywrightSharp.Tests.Attributes +{ + /// + /// Skip browsers and/or platforms. Also marks the method as a [Test]. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class SkipBrowserAndPlatformFact : NUnitAttribute, IApplyToTest + { + private readonly bool _skip; + private readonly string _reason; + + /// + /// Creates a new + /// + /// Skip firefox + /// Skip Chromium + /// Skip Webkit + /// Skip OSX + /// Skip Windows + /// Skip Linux + public SkipBrowserAndPlatformFact( + bool skipFirefox = false, + bool skipChromium = false, + bool skipWebkit = false, + bool skipOSX = false, + bool skipWindows = false, + bool skipLinux = false) + { + if (ShouldSkipBrowser(skipFirefox, skipChromium, skipWebkit) && ShouldSkipPlatform(skipOSX, skipWindows, skipLinux)) + { + _skip = true; + _reason = "Skipped by browser/platform"; + } + } + + /// + public void ApplyToTest(Test test) + { + test.Properties.Add(PropertyNames.Category, TestConstants.Product.ToLower()); + + if (_skip) + { + test.RunState = RunState.Ignored; + test.Properties.Set(PropertyNames.SkipReason, _reason); + } + } + + private static bool ShouldSkipPlatform(bool skipOSX, bool skipWindows, bool skipLinux) + => + ( + (skipOSX && RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) || + (skipWindows && RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) || + (skipLinux && RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + ) || + ( + !skipOSX && + !skipLinux && + !skipWindows + ); + + private static bool ShouldSkipBrowser(bool skipFirefox, bool skipChromium, bool skipWebkit) + => + ( + (skipFirefox && TestConstants.IsFirefox) || + (skipWebkit && TestConstants.IsWebKit) || + (skipChromium && TestConstants.IsChromium) + ) || + ( + !skipFirefox && + !skipWebkit && + !skipChromium + ); + } +} diff --git a/src/PlaywrightSharp.Tests/BaseTests/PlaywrightSharpBaseTest.cs b/src/PlaywrightSharp.Tests/BaseTests/PlaywrightSharpBaseTest.cs new file mode 100644 index 0000000000..acd9476942 --- /dev/null +++ b/src/PlaywrightSharp.Tests/BaseTests/PlaywrightSharpBaseTest.cs @@ -0,0 +1,34 @@ +using System.IO; +using NUnit.Framework; +using PlaywrightSharp.TestServer; + +namespace PlaywrightSharp.Tests.BaseTests +{ + /// + /// This base tests setup logging and http servers + /// + public class PlaywrightSharpBaseTest + { + internal IPlaywright Playwright => TestServerSetup.Playwright; + internal string BaseDirectory { get; set; } + internal IBrowserType BrowserType => Playwright[TestConstants.Product]; + + internal SimpleServer Server => TestServerSetup.Server; + internal SimpleServer HttpsServer => TestServerSetup.HttpsServer; + + [SetUp] + public void BaseSetUp() + { + BaseDirectory = Path.Combine(Directory.GetCurrentDirectory(), "workspace"); + var dirInfo = new DirectoryInfo(BaseDirectory); + + if (!dirInfo.Exists) + { + dirInfo.Create(); + } + + Server.Reset(); + HttpsServer.Reset(); + } + } +} diff --git a/src/PlaywrightSharp.Tests/BaseTests/PlaywrightSharpBrowserBaseTest.cs b/src/PlaywrightSharp.Tests/BaseTests/PlaywrightSharpBrowserBaseTest.cs new file mode 100644 index 0000000000..8bfd019966 --- /dev/null +++ b/src/PlaywrightSharp.Tests/BaseTests/PlaywrightSharpBrowserBaseTest.cs @@ -0,0 +1,10 @@ +namespace PlaywrightSharp.Tests.BaseTests +{ + /// + /// Based on , this base class also creates a new Browser + /// + public class PlaywrightSharpBrowserBaseTest : PlaywrightSharpBaseTest + { + internal IBrowser Browser => TestServerSetup.Browser; + } +} diff --git a/src/PlaywrightSharp.Tests/BaseTests/PlaywrightSharpBrowserContextBaseTest.cs b/src/PlaywrightSharp.Tests/BaseTests/PlaywrightSharpBrowserContextBaseTest.cs new file mode 100644 index 0000000000..378cceeb2d --- /dev/null +++ b/src/PlaywrightSharp.Tests/BaseTests/PlaywrightSharpBrowserContextBaseTest.cs @@ -0,0 +1,29 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace PlaywrightSharp.Tests.BaseTests +{ + /// + /// Based on , this class creates a new + /// + public class PlaywrightSharpBrowserContextBaseTest : PlaywrightSharpBrowserBaseTest + { + internal IBrowserContext Context { get; set; } + + [SetUp] + public async Task ContextSetUp() + { + Context = await Browser.NewContextAsync().ConfigureAwait(false); + Context.DefaultTimeout = TestConstants.DefaultContextTimeout; + } + + [TearDown] + public async Task ContextTearDown() + { + if (Context != null) + { + await Context.CloseAsync().ConfigureAwait(false); + } + } + } +} diff --git a/src/Playwright.Tests/BaseTests/PlaywrightSharpPageBaseTest.cs b/src/PlaywrightSharp.Tests/BaseTests/PlaywrightSharpPageBaseTest.cs similarity index 78% rename from src/Playwright.Tests/BaseTests/PlaywrightSharpPageBaseTest.cs rename to src/PlaywrightSharp.Tests/BaseTests/PlaywrightSharpPageBaseTest.cs index e66b6b7388..ba60441573 100644 --- a/src/Playwright.Tests/BaseTests/PlaywrightSharpPageBaseTest.cs +++ b/src/PlaywrightSharp.Tests/BaseTests/PlaywrightSharpPageBaseTest.cs @@ -1,73 +1,66 @@ -/* - * MIT License - * - * Copyright (c) 2020 Darío Kondratiuk - * Copyright (c) 2020 Meir Blachman - * Modifications 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. - */ -using System; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests.BaseTests -{ - /// - /// Based on , this class will create a new Page. - /// - public class PlaywrightSharpPageBaseTest : PlaywrightSharpBrowserContextBaseTest - { - internal PlaywrightSharpPageBaseTest(ITestOutputHelper output) : base(output) - { - } - - /// - /// Gets or sets the Page. - /// - protected IPage Page { get; set; } - - /// - public override async Task InitializeAsync() - { - await base.InitializeAsync(); - Page = await Context.NewPageAsync(); - } - - /// - /// Wait for an error event. - /// - /// A that completes when the error is received - protected Task WaitForError() - { - var wrapper = new TaskCompletionSource(); - - void errorEvent(object sender, IPage e) - { - wrapper.SetResult(true); - Page.Crash -= errorEvent; - } - - Page.Crash += errorEvent; - - return wrapper.Task; - } - } -} +/* + * MIT License + * + * Copyright (c) 2020 Dario Kondratiuk + * Copyright (c) 2020 Meir Blachman + * Modifications 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. + */ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace PlaywrightSharp.Tests.BaseTests +{ + /// + /// Based on , this class will create a new Page. + /// + public class PlaywrightSharpPageBaseTest : PlaywrightSharpBrowserContextBaseTest + { + /// + /// Gets or sets the Page. + /// + protected IPage Page { get; set; } + + [SetUp] + public async Task PageSetUp() + { + Page = await Context.NewPageAsync().ConfigureAwait(false); + } + + /// + /// Wait for an error event. + /// + /// A that completes when the error is received + protected Task WaitForError() + { + var wrapper = new TaskCompletionSource(); + + void errorEvent(object sender, IPage e) + { + wrapper.SetResult(true); + Page.Crash -= errorEvent; + } + + Page.Crash += errorEvent; + + return wrapper.Task; + } + } +} diff --git a/src/PlaywrightSharp.Tests/BaseTests/TestServerSetup.cs b/src/PlaywrightSharp.Tests/BaseTests/TestServerSetup.cs new file mode 100644 index 0000000000..11c8603ab7 --- /dev/null +++ b/src/PlaywrightSharp.Tests/BaseTests/TestServerSetup.cs @@ -0,0 +1,42 @@ +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.TestServer; + +namespace PlaywrightSharp.Tests +{ + [SetUpFixture] + public class TestServerSetup + { + public static SimpleServer Server { get; private set; } + public static SimpleServer HttpsServer { get; private set; } + public static IPlaywright Playwright { get; private set; } + public static IBrowser Browser { get; private set; } + + [OneTimeSetUp] + public async Task InitAllAsync() + { + Server = SimpleServer.Create(TestConstants.Port, TestUtils.FindParentDirectory("PlaywrightSharp.TestServer")); + HttpsServer = SimpleServer.CreateHttps(TestConstants.HttpsPort, TestUtils.FindParentDirectory("PlaywrightSharp.TestServer")); + + var serverStart = Server.StartAsync(); + var httpsServerStart = HttpsServer.StartAsync(); + + await Task.WhenAll(serverStart, httpsServerStart).ConfigureAwait(false); + + Playwright = await PlaywrightSharp.Playwright.CreateAsync(TestConstants.LoggerFactory, debug: "pw*").ConfigureAwait(false); + Browser = await Playwright[TestConstants.Product].LaunchDefaultAsync().ConfigureAwait(false); + } + + [OneTimeTearDown] + public async Task ShutDownAsync() + { + if (Browser != null) + { + await Browser.CloseAsync().ConfigureAwait(false); + } + + Playwright?.Dispose(); + await Task.WhenAll(Server.StopAsync(), HttpsServer.StopAsync()).ConfigureAwait(false); + } + } +} diff --git a/src/Playwright.Tests/BeforeUnloadTests.cs b/src/PlaywrightSharp.Tests/BeforeUnloadTests.cs similarity index 64% rename from src/Playwright.Tests/BeforeUnloadTests.cs rename to src/PlaywrightSharp.Tests/BeforeUnloadTests.cs index a16fe6c81e..55c36b44c7 100644 --- a/src/Playwright.Tests/BeforeUnloadTests.cs +++ b/src/PlaywrightSharp.Tests/BeforeUnloadTests.cs @@ -1,63 +1,55 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BeforeUnloadTests : PlaywrightSharpPageBaseTest - { - /// - public BeforeUnloadTests(ITestOutputHelper output) : base(output) - { - } - - - [PlaywrightTest("beforeunload.spec.ts", "should run beforeunload if asked for")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRunBeforeunloadIfAskedFor() - { - var newPage = await Context.NewPageAsync(); - await newPage.GoToAsync(TestConstants.ServerUrl + "/beforeunload.html"); - // We have to interact with a page so that 'beforeunload' handlers - // fire. - await newPage.ClickAsync("body"); - - var dialogTask = newPage.WaitForEventAsync(PageEvent.Dialog); - var pageClosingTask = newPage.CloseAsync(true); - var dialog = await dialogTask; - Assert.Equal(DialogType.BeforeUnload, dialog.Type); - Assert.Empty(dialog.DefaultValue); - if (TestConstants.IsChromium) - { - Assert.Empty(dialog.Message); - } - else if (TestConstants.IsWebKit) - { - Assert.Equal("Leave?", dialog.Message); - } - else - { - Assert.Equal("This page is asking you to confirm that you want to leave - data you have entered may not be saved.", dialog.Message); - } - - await dialog.AcceptAsync(); - await pageClosingTask; - } - - [PlaywrightTest("beforeunload.spec.ts", "should *not* run beforeunload by default")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotRunBeforeunloadByDefault() - { - var newPage = await Context.NewPageAsync(); - await newPage.GoToAsync(TestConstants.ServerUrl + "/beforeunload.html"); - // We have to interact with a page so that 'beforeunload' handlers - // fire. - await newPage.ClickAsync("body"); - await newPage.CloseAsync(); - } - - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BeforeUnloadTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("beforeunload.spec.ts", "should run beforeunload if asked for")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRunBeforeunloadIfAskedFor() + { + var newPage = await Context.NewPageAsync(); + await newPage.GoToAsync(TestConstants.ServerUrl + "/beforeunload.html"); + // We have to interact with a page so that 'beforeunload' handlers + // fire. + await newPage.ClickAsync("body"); + + var dialogTask = newPage.WaitForEventAsync(PageEvent.Dialog); + var pageClosingTask = newPage.CloseAsync(true); + var dialog = await dialogTask; + Assert.That(dialog.Type, Is.EqualTo(DialogType.BeforeUnload)); + Assert.That(dialog.DefaultValue, Is.Empty); + if (TestConstants.IsChromium) + { + Assert.That(dialog.Message, Is.Empty); + } + else if (TestConstants.IsWebKit) + { + Assert.That(dialog.Message, Is.EqualTo("Leave?")); + } + else + { + Assert.That(dialog.Message, Is.EqualTo("This page is asking you to confirm that you want to leave - data you have entered may not be saved.")); + } + + await dialog.AcceptAsync(); + await pageClosingTask; + } + + [PlaywrightTest("beforeunload.spec.ts", "should *not* run beforeunload by default")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotRunBeforeunloadByDefault() + { + var newPage = await Context.NewPageAsync(); + await newPage.GoToAsync(TestConstants.ServerUrl + "/beforeunload.html"); + // We have to interact with a page so that 'beforeunload' handlers + // fire. + await newPage.ClickAsync("body"); + await newPage.CloseAsync(); + } + + } +} diff --git a/src/Playwright.Tests/BrowserContextAddCookiesTests.cs b/src/PlaywrightSharp.Tests/BrowserContextAddCookiesTests.cs similarity index 66% rename from src/Playwright.Tests/BrowserContextAddCookiesTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextAddCookiesTests.cs index 302f24c64e..743f4e5ce1 100644 --- a/src/Playwright.Tests/BrowserContextAddCookiesTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextAddCookiesTests.cs @@ -1,476 +1,477 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextAddCookiesTests : PlaywrightSharpPageBaseTest - { - /// - public BrowserContextAddCookiesTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Context.AddCookiesAsync(new[] { new Cookie() - { - Url = TestConstants.EmptyPage, - Name = "password", - Value = "123456" - } }); - Assert.Equal("password=123456", await Page.EvaluateAsync("document.cookie")); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should roundtrip cookie")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRoundtripCookie() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal("username=John Doe", await Page.EvaluateAsync(@"timestamp => { - const date = new Date(timestamp); - document.cookie = `username=John Doe;expires=${date.toUTCString()}`; - return document.cookie; - }", new DateTime(2038, 1, 1))); - var cookies = await Context.GetCookiesAsync(); - await Context.ClearCookiesAsync(); - Assert.Empty(await Context.GetCookiesAsync()); - await Context.AddCookiesAsync(cookies.Select(c => new Cookie() - { - Domain = c.Domain, - Expires = c.Expires, - HttpOnly = c.HttpOnly, - Name = c.Name, - Path = c.Path, - SameSite = c.SameSite, - Secure = c.Secure, - Value = c.Value - })); - var newCookies = await Context.GetCookiesAsync(); - Assert.Equal(cookies, newCookies); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should send cookie header")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSendCookieHeader() - { - string cookie = string.Empty; - Server.SetRoute("/empty.html", context => - { - cookie = string.Join(";", context.Request.Cookies.Select(c => $"{c.Key}={c.Value}")); - return Task.CompletedTask; - }); - - await Context.AddCookiesAsync(new Cookie - { - Name = "cookie", - Value = "value", - Url = TestConstants.EmptyPage - }); - - var page = await Context.NewPageAsync(); - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal("cookie=value", cookie); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should isolate cookies in browser contexts")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldIsolateCookiesInBrowserContexts() - { - await using var anotherContext = await Browser.NewContextAsync(); - await Context.AddCookiesAsync(new Cookie - { - Name = "isolatecookie", - Value = "page1value", - Url = TestConstants.EmptyPage - }); - - await anotherContext.AddCookiesAsync(new Cookie - { - Name = "isolatecookie", - Value = "page2value", - Url = TestConstants.EmptyPage - }); - - var cookies1 = await Context.GetCookiesAsync(); - var cookies2 = await anotherContext.GetCookiesAsync(); - - Assert.Single(cookies1); - Assert.Single(cookies2); - Assert.Equal("isolatecookie", cookies1.ElementAt(0).Name); - Assert.Equal("page1value", cookies1.ElementAt(0).Value); - Assert.Equal("isolatecookie", cookies2.ElementAt(0).Name); - Assert.Equal("page2value", cookies2.ElementAt(0).Value); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should isolate session cookies")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldIsolateSessionCookies() - { - Server.SetRoute("/setcookie.html", context => - { - context.Response.Cookies.Append("session", "value"); - return Task.CompletedTask; - }); - - var page = await Context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/setcookie.html"); - - page = await Context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - - await using var context2 = await Browser.NewContextAsync(); - page = await context2.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - var cookies = await context2.GetCookiesAsync(); - Assert.Empty(cookies); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should isolate persistent cookies")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldIsolatePersistentCookies() - { - Server.SetRoute("/setcookie.html", context => - { - context.Response.Cookies.Append("persistent", "persistent-value", new CookieOptions { MaxAge = TimeSpan.FromSeconds(3600) }); - return Task.CompletedTask; - }); - - var page = await Context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/setcookie.html"); - - await using var context2 = await Browser.NewContextAsync(); - var (page1, page2) = await TaskUtils.WhenAll(Context.NewPageAsync(), context2.NewPageAsync()); - await TaskUtils.WhenAll( - page1.GoToAsync(TestConstants.EmptyPage), - page2.GoToAsync(TestConstants.EmptyPage)); - - var (cookies1, cookies2) = await TaskUtils.WhenAll(Context.GetCookiesAsync(), context2.GetCookiesAsync()); - Assert.Single(cookies1); - Assert.Equal("persistent", cookies1.First().Name); - Assert.Equal("persistent-value", cookies1.First().Value); - Assert.Empty(cookies2); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should isolate send cookie header")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldIsolateSendCookieHeader() - { - string cookie = string.Empty; - Server.SetRoute("/empty.html", context => - { - cookie = string.Join(";", context.Request.Cookies.Select(c => $"{c.Key}={c.Value}")); - return Task.CompletedTask; - }); - - await Context.AddCookiesAsync(new Cookie - { - Name = "sendcookie", - Value = "value", - Url = TestConstants.EmptyPage - }); - - var page = await Context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/empty.html"); - Assert.Equal("sendcookie=value", cookie); - - var context = await Browser.NewContextAsync(); - page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - Assert.Empty(cookie); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should isolate cookies between launches")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldIsolateCookiesBetweenLaunches() - { - await using (var browser1 = await Playwright[TestConstants.Product].LaunchDefaultAsync()) - { - var context1 = await Browser.NewContextAsync(); - - await Context.AddCookiesAsync(new Cookie - { - Name = "cookie-in-context-1", - Value = "value", - Expires = DateTimeOffset.Now.ToUnixTimeSeconds() + 10000, - Url = TestConstants.EmptyPage - }); - } - - await using (var browser2 = await Playwright[TestConstants.Product].LaunchDefaultAsync()) - { - var context1 = await Browser.NewContextAsync(); - var cookies = await context1.GetCookiesAsync(); - Assert.Empty(cookies); - } - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should set multiple cookies")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSetMultipleCookies() - { - await Page.GoToAsync(TestConstants.EmptyPage); - - await Context.AddCookiesAsync( - new Cookie - { - Url = TestConstants.EmptyPage, - Name = "multiple-1", - Value = "123456" - }, - new Cookie - { - Url = TestConstants.EmptyPage, - Name = "multiple-2", - Value = "bar" - } - ); - - Assert.Equal( - new[] - { - "multiple-1=123456", - "multiple-2=bar" - }, - await Page.EvaluateAsync(@"() => { - const cookies = document.cookie.split(';'); - return cookies.map(cookie => cookie.trim()).sort(); - }") - ); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should have |expires| set to |-1| for session cookies")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHaveExpiresSetToMinus1ForSessionCookies() - { - await Context.AddCookiesAsync(new Cookie - { - Url = TestConstants.EmptyPage, - Name = "expires", - Value = "123456" - }); - - var cookies = await Context.GetCookiesAsync(); - - Assert.Equal(-1, cookies.ElementAt(0).Expires); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should set cookie with reasonable defaults")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSetCookieWithReasonableDefaults() - { - await Context.AddCookiesAsync(new Cookie - { - Url = TestConstants.EmptyPage, - Name = "defaults", - Value = "123456" - }); - - var cookie = Assert.Single(await Context.GetCookiesAsync()); - Assert.Equal("defaults", cookie.Name); - Assert.Equal("123456", cookie.Value); - Assert.Equal("localhost", cookie.Domain); - Assert.Equal("/", cookie.Path); - Assert.Equal(-1, cookie.Expires); - Assert.False(cookie.HttpOnly); - Assert.False(cookie.Secure); - Assert.Equal(SameSiteAttribute.None, cookie.SameSite); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should set a cookie with a path")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSetACookieWithAPath() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - await Context.AddCookiesAsync(new Cookie - { - Domain = "localhost", - Path = "/grid.html", - Name = "gridcookie", - Value = "GRID" - }); - var cookie = Assert.Single(await Context.GetCookiesAsync()); - Assert.Equal("gridcookie", cookie.Name); - Assert.Equal("GRID", cookie.Value); - Assert.Equal("localhost", cookie.Domain); - Assert.Equal("/grid.html", cookie.Path); - Assert.Equal(cookie.Expires, -1); - Assert.False(cookie.HttpOnly); - Assert.False(cookie.Secure); - Assert.Equal(SameSiteAttribute.None, cookie.SameSite); - - Assert.Equal("gridcookie=GRID", await Page.EvaluateAsync("document.cookie")); - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Empty(await Page.EvaluateAsync("document.cookie")); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - Assert.Equal("gridcookie=GRID", await Page.EvaluateAsync("document.cookie")); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should not set a cookie with blank page URL")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotSetACookieWithBlankPageURL() - { - await Page.GoToAsync(TestConstants.AboutBlank); - - var exception = await Assert.ThrowsAsync(async () - => await Context.AddCookiesAsync( - new Cookie - { - Url = TestConstants.EmptyPage, - Name = "example-cookie", - Value = "best" - }, - new Cookie - { - Url = "about:blank", - Name = "example-cookie-blank", - Value = "best" - })); - Assert.Equal("Blank page can not have cookie \"example-cookie-blank\"", exception.Message); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should not set a cookie on a data URL page")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotSetACookieOnADataURLPage() - { - await Page.GoToAsync("data:,Hello%2C%20World!"); - var exception = await Assert.ThrowsAnyAsync(async () - => await Context.AddCookiesAsync( - new Cookie - { - Url = "data:,Hello%2C%20World!", - Name = "example-cookie", - Value = "best" - })); - - Assert.Equal("Data URL page can not have cookie \"example-cookie\"", exception.Message); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should default to setting secure cookie for HTTPS websites")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDefaultToSettingSecureCookieForHttpsWebsites() - { - await Page.GoToAsync(TestConstants.EmptyPage); - const string secureUrl = "https://example.com"; - - await Context.AddCookiesAsync(new Cookie - { - Url = secureUrl, - Name = "foo", - Value = "bar" - }); - var cookie = Assert.Single(await Context.GetCookiesAsync(secureUrl)); - Assert.True(cookie.Secure); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should be able to set unsecure cookie for HTTP website")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToSetUnsecureCookieForHttpWebSite() - { - await Page.GoToAsync(TestConstants.EmptyPage); - string SecureUrl = "http://example.com"; - - await Context.AddCookiesAsync(new Cookie - { - Url = SecureUrl, - Name = "foo", - Value = "bar" - }); - var cookie = Assert.Single(await Context.GetCookiesAsync(SecureUrl)); - Assert.False(cookie.Secure); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should set a cookie on a different domain")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSetACookieOnADifferentDomain() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - await Context.AddCookiesAsync(new Cookie { Name = "example-cookie", Value = "best", Url = "https://www.example.com" }); - Assert.Equal(string.Empty, await Page.EvaluateAsync("document.cookie")); - var cookie = Assert.Single(await Context.GetCookiesAsync("https://www.example.com")); - Assert.Equal("example-cookie", cookie.Name); - Assert.Equal("best", cookie.Value); - Assert.Equal("www.example.com", cookie.Domain); - Assert.Equal("/", cookie.Path); - Assert.Equal(cookie.Expires, -1); - Assert.False(cookie.HttpOnly); - Assert.True(cookie.Secure); - Assert.Equal(SameSiteAttribute.None, cookie.SameSite); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should set cookies for a frame")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSetCookiesForAFrame() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Context.AddCookiesAsync( - new Cookie - { - Url = TestConstants.ServerUrl, - Name = "frame-cookie", - Value = "value" - }); - - await Page.EvaluateAsync(@"src => { - let fulfill; - const promise = new Promise(x => fulfill = x); - const iframe = document.createElement('iframe'); - document.body.appendChild(iframe); - iframe.onload = fulfill; - iframe.src = src; - return promise; - }", TestConstants.ServerUrl + "/grid.html"); - - Assert.Equal("frame-cookie=value", await Page.FirstChildFrame().EvaluateAsync("document.cookie")); - } - - [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should(not) block third party cookies")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotBlockThirdPartyCookies() - { - await Page.GoToAsync(TestConstants.EmptyPage); - - await Page.EvaluateAsync(@"src => { - let fulfill; - const promise = new Promise(x => fulfill = x); - const iframe = document.createElement('iframe'); - document.body.appendChild(iframe); - iframe.onload = fulfill; - iframe.src = src; - return promise; - }", TestConstants.CrossProcessUrl + "/grid.html"); - - await Page.FirstChildFrame().EvaluateAsync("document.cookie = 'username=John Doe'"); - await Page.WaitForTimeoutAsync(2000); - bool allowsThirdPart = !TestConstants.IsWebKit; - var cookies = await Context.GetCookiesAsync(TestConstants.CrossProcessUrl + "/grid.html"); - - if (allowsThirdPart) - { - Assert.Single(cookies); - var cookie = cookies.First(); - Assert.Equal("127.0.0.1", cookie.Domain); - Assert.Equal(cookie.Expires, -1); - Assert.False(cookie.HttpOnly); - Assert.Equal("username", cookie.Name); - Assert.Equal("/", cookie.Path); - Assert.Equal(SameSiteAttribute.None, cookie.SameSite); - Assert.False(cookie.Secure); - Assert.Equal("John Doe", cookie.Value); - } - else - { - Assert.Empty(cookies); - } - } - } -} +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextAddCookiesTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Context.AddCookiesAsync(new[] { new Cookie() + { + Url = TestConstants.EmptyPage, + Name = "password", + Value = "123456" + } }); + Assert.That(await Page.EvaluateAsync("document.cookie"), Is.EqualTo("password=123456")); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should roundtrip cookie")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRoundtripCookie() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await Page.EvaluateAsync(@"timestamp => { + const date = new Date(timestamp); + document.cookie = `username=John Doe;expires=${date.toUTCString()}`; + return document.cookie; + }", new DateTime(2038, 1, 1)), Is.EqualTo("username=John Doe")); + var cookies = await Context.GetCookiesAsync(); + await Context.ClearCookiesAsync(); + Assert.That(await Context.GetCookiesAsync(), Is.Empty); + await Context.AddCookiesAsync(cookies.Select(c => new Cookie() + { + Domain = c.Domain, + Expires = c.Expires, + HttpOnly = c.HttpOnly, + Name = c.Name, + Path = c.Path, + SameSite = c.SameSite, + Secure = c.Secure, + Value = c.Value + })); + var newCookies = await Context.GetCookiesAsync(); + Assert.That(newCookies, Is.EqualTo(cookies)); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should send cookie header")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSendCookieHeader() + { + string cookie = string.Empty; + Server.SetRoute("/empty.html", context => + { + cookie = string.Join(";", context.Request.Cookies.Select(c => $"{c.Key}={c.Value}")); + return Task.CompletedTask; + }); + + await Context.AddCookiesAsync(new Cookie + { + Name = "cookie", + Value = "value", + Url = TestConstants.EmptyPage + }); + + var page = await Context.NewPageAsync(); + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(cookie, Is.EqualTo("cookie=value")); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should isolate cookies in browser contexts")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldIsolateCookiesInBrowserContexts() + { + await using var anotherContext = await Browser.NewContextAsync(); + await Context.AddCookiesAsync(new Cookie + { + Name = "isolatecookie", + Value = "page1value", + Url = TestConstants.EmptyPage + }); + + await anotherContext.AddCookiesAsync(new Cookie + { + Name = "isolatecookie", + Value = "page2value", + Url = TestConstants.EmptyPage + }); + + var cookies1 = await Context.GetCookiesAsync(); + var cookies2 = await anotherContext.GetCookiesAsync(); + + Assert.That(cookies1, Has.Exactly(1).Items); + Assert.That(cookies2, Has.Exactly(1).Items); + Assert.That(cookies1.ElementAt(0).Name, Is.EqualTo("isolatecookie")); + Assert.That(cookies1.ElementAt(0).Value, Is.EqualTo("page1value")); + Assert.That(cookies2.ElementAt(0).Name, Is.EqualTo("isolatecookie")); + Assert.That(cookies2.ElementAt(0).Value, Is.EqualTo("page2value")); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should isolate session cookies")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldIsolateSessionCookies() + { + Server.SetRoute("/setcookie.html", context => + { + context.Response.Cookies.Append("session", "value"); + return Task.CompletedTask; + }); + + var page = await Context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/setcookie.html"); + + page = await Context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + + await using var context2 = await Browser.NewContextAsync(); + page = await context2.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + var cookies = await context2.GetCookiesAsync(); + Assert.That(cookies, Is.Empty); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should isolate persistent cookies")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldIsolatePersistentCookies() + { + Server.SetRoute("/setcookie.html", context => + { + context.Response.Cookies.Append("persistent", "persistent-value", new CookieOptions { MaxAge = TimeSpan.FromSeconds(3600) }); + return Task.CompletedTask; + }); + + var page = await Context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/setcookie.html"); + + await using var context2 = await Browser.NewContextAsync(); + var (page1, page2) = await TaskUtils.WhenAll(Context.NewPageAsync(), context2.NewPageAsync()); + await TaskUtils.WhenAll( + page1.GoToAsync(TestConstants.EmptyPage), + page2.GoToAsync(TestConstants.EmptyPage)); + + var (cookies1, cookies2) = await TaskUtils.WhenAll(Context.GetCookiesAsync(), context2.GetCookiesAsync()); + Assert.That(cookies1, Has.Exactly(1).Items); + Assert.That(cookies1.First().Name, Is.EqualTo("persistent")); + Assert.That(cookies1.First().Value, Is.EqualTo("persistent-value")); + Assert.That(cookies2, Is.Empty); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should isolate send cookie header")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldIsolateSendCookieHeader() + { + string cookie = string.Empty; + Server.SetRoute("/empty.html", context => + { + cookie = string.Join(";", context.Request.Cookies.Select(c => $"{c.Key}={c.Value}")); + return Task.CompletedTask; + }); + + await Context.AddCookiesAsync(new Cookie + { + Name = "sendcookie", + Value = "value", + Url = TestConstants.EmptyPage + }); + + var page = await Context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/empty.html"); + Assert.That(cookie, Is.EqualTo("sendcookie=value")); + + var context = await Browser.NewContextAsync(); + page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(cookie, Is.Empty); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should isolate cookies between launches")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldIsolateCookiesBetweenLaunches() + { + await using (var browser1 = await Playwright[TestConstants.Product].LaunchDefaultAsync()) + { + var context1 = await Browser.NewContextAsync(); + + await Context.AddCookiesAsync(new Cookie + { + Name = "cookie-in-context-1", + Value = "value", + Expires = DateTimeOffset.Now.ToUnixTimeSeconds() + 10000, + Url = TestConstants.EmptyPage + }); + } + + await using (var browser2 = await Playwright[TestConstants.Product].LaunchDefaultAsync()) + { + var context1 = await Browser.NewContextAsync(); + var cookies = await context1.GetCookiesAsync(); + Assert.That(cookies, Is.Empty); + } + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should set multiple cookies")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSetMultipleCookies() + { + await Page.GoToAsync(TestConstants.EmptyPage); + + await Context.AddCookiesAsync( + new Cookie + { + Url = TestConstants.EmptyPage, + Name = "multiple-1", + Value = "123456" + }, + new Cookie + { + Url = TestConstants.EmptyPage, + Name = "multiple-2", + Value = "bar" + } + ); + + Assert.That(await Page.EvaluateAsync(@"() => { + const cookies = document.cookie.split(';'); + return cookies.map(cookie => cookie.trim()).sort(); + }"), Is.EqualTo(new[] + { + "multiple-1=123456", + "multiple-2=bar" + })); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should have |expires| set to |-1| for session cookies")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHaveExpiresSetToMinus1ForSessionCookies() + { + await Context.AddCookiesAsync(new Cookie + { + Url = TestConstants.EmptyPage, + Name = "expires", + Value = "123456" + }); + + var cookies = await Context.GetCookiesAsync(); + + Assert.That(cookies.ElementAt(0).Expires, Is.EqualTo(-1)); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should set cookie with reasonable defaults")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSetCookieWithReasonableDefaults() + { + await Context.AddCookiesAsync(new Cookie + { + Url = TestConstants.EmptyPage, + Name = "defaults", + Value = "123456" + }); + + Assert.That(await Context.GetCookiesAsync(), Has.Exactly(1).Items); + + + var cookie = (await Context.GetCookiesAsync()).First(); + Assert.That(cookie.Name, Is.EqualTo("defaults")); + Assert.That(cookie.Value, Is.EqualTo("123456")); + Assert.That(cookie.Domain, Is.EqualTo("localhost")); + Assert.That(cookie.Path, Is.EqualTo("/")); + Assert.That(cookie.Expires, Is.EqualTo(-1)); + Assert.That(cookie.HttpOnly, Is.False); + Assert.That(cookie.Secure, Is.False); + Assert.That(cookie.SameSite, Is.EqualTo(SameSiteAttribute.None)); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should set a cookie with a path")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSetACookieWithAPath() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + await Context.AddCookiesAsync(new Cookie + { + Domain = "localhost", + Path = "/grid.html", + Name = "gridcookie", + Value = "GRID" + }); + Assert.That(await Context.GetCookiesAsync(), Has.Exactly(1).Items); + + var cookie = (await Context.GetCookiesAsync()).First(); + Assert.That(cookie.Name, Is.EqualTo("gridcookie")); + Assert.That(cookie.Value, Is.EqualTo("GRID")); + Assert.That(cookie.Domain, Is.EqualTo("localhost")); + Assert.That(cookie.Path, Is.EqualTo("/grid.html")); + Assert.That(cookie.Expires, Is.EqualTo(-1)); + Assert.That(cookie.HttpOnly, Is.False); + Assert.That(cookie.Secure, Is.False); + Assert.That(cookie.SameSite, Is.EqualTo(SameSiteAttribute.None)); + + Assert.That(await Page.EvaluateAsync("document.cookie"), Is.EqualTo("gridcookie=GRID")); + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await Page.EvaluateAsync("document.cookie"), Is.Empty); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + Assert.That(await Page.EvaluateAsync("document.cookie"), Is.EqualTo("gridcookie=GRID")); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should not set a cookie with blank page URL")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotSetACookieWithBlankPageURL() + { + await Page.GoToAsync(TestConstants.AboutBlank); + + var exception = Assert.ThrowsAsync(async () + => await Context.AddCookiesAsync( + new Cookie + { + Url = TestConstants.EmptyPage, + Name = "example-cookie", + Value = "best" + }, + new Cookie + { + Url = "about:blank", + Name = "example-cookie-blank", + Value = "best" + })); + Assert.That(exception.Message, Is.EqualTo("Blank page can not have cookie \"example-cookie-blank\"")); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should not set a cookie on a data URL page")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotSetACookieOnADataURLPage() + { + await Page.GoToAsync("data:,Hello%2C%20World!"); + var exception = Assert.CatchAsync(async () + => await Context.AddCookiesAsync( + new Cookie + { + Url = "data:,Hello%2C%20World!", + Name = "example-cookie", + Value = "best" + })); + + Assert.That(exception.Message, Is.EqualTo("Data URL page can not have cookie \"example-cookie\"")); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should default to setting secure cookie for HTTPS websites")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDefaultToSettingSecureCookieForHttpsWebsites() + { + await Page.GoToAsync(TestConstants.EmptyPage); + const string secureUrl = "https://example.com"; + + await Context.AddCookiesAsync(new Cookie + { + Url = secureUrl, + Name = "foo", + Value = "bar" + }); + Assert.That(await Context.GetCookiesAsync(secureUrl), Has.Exactly(1).Items); + + var cookie = (await Context.GetCookiesAsync(secureUrl)).First(); + Assert.That(cookie.Secure, Is.True); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should be able to set unsecure cookie for HTTP website")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToSetUnsecureCookieForHttpWebSite() + { + await Page.GoToAsync(TestConstants.EmptyPage); + string SecureUrl = "http://example.com"; + + await Context.AddCookiesAsync(new Cookie + { + Url = SecureUrl, + Name = "foo", + Value = "bar" + }); + Assert.That(await Context.GetCookiesAsync(SecureUrl), Has.Exactly(1).Items); + + var cookie = (await Context.GetCookiesAsync(SecureUrl)).First(); + Assert.That(cookie.Secure, Is.False); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should set a cookie on a different domain")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSetACookieOnADifferentDomain() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + await Context.AddCookiesAsync(new Cookie { Name = "example-cookie", Value = "best", Url = "https://www.example.com" }); + Assert.That(await Page.EvaluateAsync("document.cookie"), Is.EqualTo(string.Empty)); + Assert.That(await Context.GetCookiesAsync("https://www.example.com"), Has.Exactly(1).Items); + + var cookie = (await Context.GetCookiesAsync("https://www.example.com")).First(); + Assert.That(cookie.Name, Is.EqualTo("example-cookie")); + Assert.That(cookie.Value, Is.EqualTo("best")); + Assert.That(cookie.Domain, Is.EqualTo("www.example.com")); + Assert.That(cookie.Path, Is.EqualTo("/")); + Assert.That(cookie.Expires, Is.EqualTo(-1)); + Assert.That(cookie.HttpOnly, Is.False); + Assert.That(cookie.Secure, Is.True); + Assert.That(cookie.SameSite, Is.EqualTo(SameSiteAttribute.None)); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should set cookies for a frame")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSetCookiesForAFrame() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Context.AddCookiesAsync( + new Cookie + { + Url = TestConstants.ServerUrl, + Name = "frame-cookie", + Value = "value" + }); + + await Page.EvaluateAsync(@"src => { + let fulfill; + const promise = new Promise(x => fulfill = x); + const iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + iframe.onload = fulfill; + iframe.src = src; + return promise; + }", TestConstants.ServerUrl + "/grid.html"); + + Assert.That(await Page.FirstChildFrame().EvaluateAsync("document.cookie"), Is.EqualTo("frame-cookie=value")); + } + + [PlaywrightTest("browsercontext-add-cookies.spec.ts", "should(not) block third party cookies")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotBlockThirdPartyCookies() + { + await Page.GoToAsync(TestConstants.EmptyPage); + + await Page.EvaluateAsync(@"src => { + let fulfill; + const promise = new Promise(x => fulfill = x); + const iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + iframe.onload = fulfill; + iframe.src = src; + return promise; + }", TestConstants.CrossProcessUrl + "/grid.html"); + + await Page.FirstChildFrame().EvaluateAsync("document.cookie = 'username=John Doe'"); + await Page.WaitForTimeoutAsync(2000); + bool allowsThirdPart = !TestConstants.IsWebKit; + var cookies = await Context.GetCookiesAsync(TestConstants.CrossProcessUrl + "/grid.html"); + + if (allowsThirdPart) + { + Assert.That(cookies, Has.Exactly(1).Items); + var cookie = cookies.First(); + Assert.That(cookie.Domain, Is.EqualTo("127.0.0.1")); + Assert.That(cookie.Expires, Is.EqualTo(-1)); + Assert.That(cookie.HttpOnly, Is.False); + Assert.That(cookie.Name, Is.EqualTo("username")); + Assert.That(cookie.Path, Is.EqualTo("/")); + Assert.That(cookie.SameSite, Is.EqualTo(SameSiteAttribute.None)); + Assert.That(cookie.Secure, Is.False); + Assert.That(cookie.Value, Is.EqualTo("John Doe")); + } + else + { + Assert.That(cookies, Is.Empty); + } + } + } +} diff --git a/src/Playwright.Tests/BrowserContextBasicTests.cs b/src/PlaywrightSharp.Tests/BrowserContextBasicTests.cs similarity index 65% rename from src/Playwright.Tests/BrowserContextBasicTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextBasicTests.cs index b5baf835d7..97c880279a 100644 --- a/src/Playwright.Tests/BrowserContextBasicTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextBasicTests.cs @@ -1,313 +1,304 @@ -using System; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextBasicTests : PlaywrightSharpBrowserBaseTest - { - /// - public BrowserContextBasicTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "should create new context")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCreateNewContext() - { - await using var browser = await BrowserType.LaunchDefaultAsync(); - Assert.Empty(browser.Contexts); - await using var context = await browser.NewContextAsync(); - Assert.Single(browser.Contexts); - Assert.Contains(context, browser.Contexts); - Assert.Same(browser, context.Browser); - await context.CloseAsync(); - Assert.Empty(browser.Contexts); - Assert.Same(browser, context.Browser); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "window.open should use parent tab context")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task WindowOpenShouldUseParentTabContext() - { - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - var popupTargetCompletion = new TaskCompletionSource(); - page.Popup += (_, e) => popupTargetCompletion.SetResult(e); - - var (popupTarget, _) = await TaskUtils.WhenAll( - popupTargetCompletion.Task, - page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage) - ); - - Assert.Same(context, popupTarget.Context); - await context.CloseAsync(); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "should isolate localStorage and cookies")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldIsolateLocalStorageAndCookies() - { - // Create two incognito contexts. - await using var browser = await BrowserType.LaunchDefaultAsync(); - var context1 = await browser.NewContextAsync(); - var context2 = await browser.NewContextAsync(); - Assert.Empty(context1.Pages); - Assert.Empty(context2.Pages); - - // Create a page in first incognito context. - var page1 = await context1.NewPageAsync(); - await page1.GoToAsync(TestConstants.EmptyPage); - await page1.EvaluateAsync(@"() => { - localStorage.setItem('name', 'page1'); - document.cookie = 'name=page1'; - }"); - - Assert.Single(context1.Pages); - Assert.Empty(context2.Pages); - - // Create a page in second incognito context. - var page2 = await context2.NewPageAsync(); - await page2.GoToAsync(TestConstants.EmptyPage); - await page2.EvaluateAsync(@"() => { - localStorage.setItem('name', 'page2'); - document.cookie = 'name=page2'; - }"); - - Assert.Single(context1.Pages); - Assert.Equal(page1, context1.Pages.FirstOrDefault()); - Assert.Single(context2.Pages); - Assert.Equal(page2, context2.Pages.FirstOrDefault()); - - // Make sure pages don't share localstorage or cookies. - Assert.Equal("page1", await page1.EvaluateAsync("() => localStorage.getItem('name')")); - Assert.Equal("name=page1", await page1.EvaluateAsync("() => document.cookie")); - Assert.Equal("page2", await page2.EvaluateAsync("() => localStorage.getItem('name')")); - Assert.Equal("name=page2", await page2.EvaluateAsync("() => document.cookie")); - - // Cleanup contexts. - await TaskUtils.WhenAll(context1.CloseAsync(), context2.CloseAsync()); - Assert.Empty(browser.Contexts); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "should propagate default viewport to the page")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldPropagateDefaultViewportToThePage() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 456, - Height = 789 - } - }); - - var page = await context.NewPageAsync(); - await TestUtils.VerifyViewportAsync(page, 456, 789); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "should make a copy of default viewport")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldMakeACopyOfDefaultViewport() - { - var viewport = new ViewportSize - { - Width = 456, - Height = 789 - }; - - await using var context = await Browser.NewContextAsync(new BrowserContextOptions { Viewport = viewport }); - - viewport.Width = 567; - - var page = await context.NewPageAsync(); - - await TestUtils.VerifyViewportAsync(page, 456, 789); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "should respect deviceScaleFactor")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRespectDeviceScaleFactor() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - DeviceScaleFactor = 3 - }); - - var page = await context.NewPageAsync(); - Assert.Equal(3, await page.EvaluateAsync("window.devicePixelRatio")); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "should not allow deviceScaleFactor with null viewport")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotAllowDeviceScaleFactorWithViewportDisabled() - { - var exception = await Assert.ThrowsAsync(() => Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = ViewportSize.NoViewport, - DeviceScaleFactor = 3, - })); - Assert.Equal("\"deviceScaleFactor\" option is not supported with null \"viewport\"", exception.Message); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "should not allow isMobile with null viewport")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotAllowIsMobileWithViewportDisabled() - { - var exception = await Assert.ThrowsAsync(() => Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = ViewportSize.NoViewport, - IsMobile = true, - })); - Assert.Equal("\"isMobile\" option is not supported with null \"viewport\"", exception.Message); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "close() should work for empty context")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task CloseShouldWorkForEmptyContext() - { - var context = await Browser.NewContextAsync(); - await context.CloseAsync(); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "close() should abort waitForEvent")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task CloseShouldAbortWaitForEvent() - { - var context = await Browser.NewContextAsync(); - var waitTask = context.WaitForEventAsync(ContextEvent.Page); - await context.CloseAsync(); - var exception = await Assert.ThrowsAsync(() => waitTask); - Assert.Equal("Context closed", exception.Message); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "should not report frameless pages on error")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotReportFramelessPagesOnError() - { - var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - Server.SetRoute("/empty.html", context => - { - context.Response.ContentType = "text/html"; - return context.Response.WriteAsync($"Click me"); - }); - - IPage popup = null; - context.Page += (_, e) => popup = e; - await page.GoToAsync(TestConstants.EmptyPage); - await page.ClickAsync("'Click me'"); - await context.CloseAsync(); - - if (popup != null) - { - Assert.True(popup.IsClosed); - Assert.NotNull(popup.MainFrame); - } - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "close() should be callable twice")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task CloseShouldBeCallableTwice() - { - var context = await Browser.NewContextAsync(); - await TaskUtils.WhenAll(context.CloseAsync(), context.CloseAsync()); - await context.CloseAsync(); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "should return all of the pages")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnAllOfThePages() - { - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - var second = await context.NewPageAsync(); - - Assert.Equal(2, context.Pages.Count); - Assert.Contains(page, context.Pages); - Assert.Contains(second, context.Pages); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "BrowserContext.pages()", "should close all belonging pages once closing context")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCloseAllBelongingPagesOnceClosingContext() - { - await using var context = await Browser.NewContextAsync(); - await context.NewPageAsync(); - - Assert.Single(context.Pages); - - await context.CloseAsync(); - - Assert.Empty(context.Pages); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "should disable javascript")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDisableJavascript() - { - await using (var context = await Browser.NewContextAsync(javaScriptEnabled: false)) - { - var page = await context.NewPageAsync(); - await page.GoToAsync("data:text/html, "); - - var exception = await Assert.ThrowsAnyAsync(async () => await page.EvaluateAsync("something")); - - Assert.Contains( - TestConstants.IsWebKit ? "Can\'t find variable: something" : "something is not defined", - exception.Message); - } - - await using (var context = await Browser.NewContextAsync()) - { - var page = await context.NewPageAsync(); - await page.GoToAsync("data:text/html, "); - Assert.Equal("forbidden", await page.EvaluateAsync("something")); - } - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "should be able to navigate after disabling javascript")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToNavigateAfterDisablingJavascript() - { - await using var context = await Browser.NewContextAsync(javaScriptEnabled: false); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "should work with offline option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithOfflineOption() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions { Offline = true }); - var page = await context.NewPageAsync(); - await Assert.ThrowsAsync(() => page.GoToAsync(TestConstants.EmptyPage)); - await context.SetOfflineAsync(false); - var response = await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - - [PlaywrightTest("browsercontext-basic.spec.ts", "should emulate navigator.onLine")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldEmulateNavigatorOnLine() - { - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - Assert.True(await page.EvaluateAsync("() => window.navigator.onLine")); - await context.SetOfflineAsync(true); - Assert.False(await page.EvaluateAsync("() => window.navigator.onLine")); - await context.SetOfflineAsync(false); - Assert.True(await page.EvaluateAsync("() => window.navigator.onLine")); - } - } -} +using System; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextBasicTests : PlaywrightSharpBrowserBaseTest + { + [PlaywrightTest("browsercontext-basic.spec.ts", "should create new context")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCreateNewContext() + { + await using var browser = await BrowserType.LaunchDefaultAsync(); + Assert.That(browser.Contexts, Is.Empty); + await using var context = await browser.NewContextAsync(); + Assert.That(browser.Contexts, Has.Exactly(1).Items); + Assert.That(browser.Contexts, Does.Contain(context)); + Assert.That(context.Browser, Is.SameAs(browser)); + await context.CloseAsync(); + Assert.That(browser.Contexts, Is.Empty); + Assert.That(context.Browser, Is.SameAs(browser)); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "window.open should use parent tab context")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task WindowOpenShouldUseParentTabContext() + { + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + var popupTargetCompletion = new TaskCompletionSource(); + page.Popup += (_, e) => popupTargetCompletion.SetResult(e); + + var (popupTarget, _) = await TaskUtils.WhenAll( + popupTargetCompletion.Task, + page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage) + ); + + Assert.That(popupTarget.Context, Is.SameAs(context)); + await context.CloseAsync(); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "should isolate localStorage and cookies")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldIsolateLocalStorageAndCookies() + { + // Create two incognito contexts. + await using var browser = await BrowserType.LaunchDefaultAsync(); + var context1 = await browser.NewContextAsync(); + var context2 = await browser.NewContextAsync(); + Assert.That(context1.Pages, Is.Empty); + Assert.That(context2.Pages, Is.Empty); + + // Create a page in first incognito context. + var page1 = await context1.NewPageAsync(); + await page1.GoToAsync(TestConstants.EmptyPage); + await page1.EvaluateAsync(@"() => { + localStorage.setItem('name', 'page1'); + document.cookie = 'name=page1'; + }"); + + Assert.That(context1.Pages, Has.Exactly(1).Items); + Assert.That(context2.Pages, Is.Empty); + + // Create a page in second incognito context. + var page2 = await context2.NewPageAsync(); + await page2.GoToAsync(TestConstants.EmptyPage); + await page2.EvaluateAsync(@"() => { + localStorage.setItem('name', 'page2'); + document.cookie = 'name=page2'; + }"); + + Assert.That(context1.Pages, Has.Exactly(1).Items); + Assert.That(context1.Pages.FirstOrDefault(), Is.EqualTo(page1)); + Assert.That(context2.Pages, Has.Exactly(1).Items); + Assert.That(context2.Pages.FirstOrDefault(), Is.EqualTo(page2)); + + // Make sure pages don't share localstorage or cookies. + Assert.That(await page1.EvaluateAsync("() => localStorage.getItem('name')"), Is.EqualTo("page1")); + Assert.That(await page1.EvaluateAsync("() => document.cookie"), Is.EqualTo("name=page1")); + Assert.That(await page2.EvaluateAsync("() => localStorage.getItem('name')"), Is.EqualTo("page2")); + Assert.That(await page2.EvaluateAsync("() => document.cookie"), Is.EqualTo("name=page2")); + + // Cleanup contexts. + await TaskUtils.WhenAll(context1.CloseAsync(), context2.CloseAsync()); + Assert.That(browser.Contexts, Is.Empty); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "should propagate default viewport to the page")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldPropagateDefaultViewportToThePage() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 456, + Height = 789 + } + }); + + var page = await context.NewPageAsync(); + await TestUtils.VerifyViewportAsync(page, 456, 789); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "should make a copy of default viewport")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldMakeACopyOfDefaultViewport() + { + var viewport = new ViewportSize + { + Width = 456, + Height = 789 + }; + + await using var context = await Browser.NewContextAsync(new BrowserContextOptions { Viewport = viewport }); + + viewport.Width = 567; + + var page = await context.NewPageAsync(); + + await TestUtils.VerifyViewportAsync(page, 456, 789); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "should respect deviceScaleFactor")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRespectDeviceScaleFactor() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + DeviceScaleFactor = 3 + }); + + var page = await context.NewPageAsync(); + Assert.That(await page.EvaluateAsync("window.devicePixelRatio"), Is.EqualTo(3)); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "should not allow deviceScaleFactor with null viewport")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotAllowDeviceScaleFactorWithViewportDisabled() + { + var exception = Assert.ThrowsAsync(() => Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = ViewportSize.NoViewport, + DeviceScaleFactor = 3, + })); + Assert.That(exception.Message, Is.EqualTo("\"deviceScaleFactor\" option is not supported with null \"viewport\"")); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "should not allow isMobile with null viewport")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotAllowIsMobileWithViewportDisabled() + { + var exception = Assert.ThrowsAsync(() => Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = ViewportSize.NoViewport, + IsMobile = true, + })); + Assert.That(exception.Message, Is.EqualTo("\"isMobile\" option is not supported with null \"viewport\"")); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "close() should work for empty context")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task CloseShouldWorkForEmptyContext() + { + var context = await Browser.NewContextAsync(); + await context.CloseAsync(); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "close() should abort waitForEvent")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task CloseShouldAbortWaitForEvent() + { + var context = await Browser.NewContextAsync(); + var waitTask = context.WaitForEventAsync(ContextEvent.Page); + await context.CloseAsync(); + var exception = Assert.ThrowsAsync(() => waitTask); + Assert.That(exception.Message, Is.EqualTo("Context closed")); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "should not report frameless pages on error")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotReportFramelessPagesOnError() + { + var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + Server.SetRoute("/empty.html", context => + { + context.Response.ContentType = "text/html"; + return context.Response.WriteAsync($"Click me"); + }); + + IPage popup = null; + context.Page += (_, e) => popup = e; + await page.GoToAsync(TestConstants.EmptyPage); + await page.ClickAsync("'Click me'"); + await context.CloseAsync(); + + if (popup != null) + { + Assert.That(popup.IsClosed, Is.True); + Assert.That(popup.MainFrame, Is.Not.Null); + } + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "close() should be callable twice")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task CloseShouldBeCallableTwice() + { + var context = await Browser.NewContextAsync(); + await TaskUtils.WhenAll(context.CloseAsync(), context.CloseAsync()); + await context.CloseAsync(); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "should return all of the pages")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnAllOfThePages() + { + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + var second = await context.NewPageAsync(); + + Assert.That(context.Pages.Count, Is.EqualTo(2)); + Assert.That(context.Pages, Does.Contain(page)); + Assert.That(context.Pages, Does.Contain(second)); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "BrowserContext.pages()", "should close all belonging pages once closing context")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCloseAllBelongingPagesOnceClosingContext() + { + await using var context = await Browser.NewContextAsync(); + await context.NewPageAsync(); + + Assert.That(context.Pages, Has.Exactly(1).Items); + + await context.CloseAsync(); + + Assert.That(context.Pages, Is.Empty); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "should disable javascript")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDisableJavascript() + { + await using (var context = await Browser.NewContextAsync(javaScriptEnabled: false)) + { + var page = await context.NewPageAsync(); + await page.GoToAsync("data:text/html, "); + + var exception = Assert.CatchAsync(async () => await page.EvaluateAsync("something")); + + Assert.That(exception.Message, Does.Contain(TestConstants.IsWebKit ? "Can\'t find variable: something" : "something is not defined")); + } + + await using (var context = await Browser.NewContextAsync()) + { + var page = await context.NewPageAsync(); + await page.GoToAsync("data:text/html, "); + Assert.That(await page.EvaluateAsync("something"), Is.EqualTo("forbidden")); + } + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "should be able to navigate after disabling javascript")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToNavigateAfterDisablingJavascript() + { + await using var context = await Browser.NewContextAsync(javaScriptEnabled: false); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "should work with offline option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithOfflineOption() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions { Offline = true }); + var page = await context.NewPageAsync(); + Assert.ThrowsAsync(() => page.GoToAsync(TestConstants.EmptyPage)); + await context.SetOfflineAsync(false); + var response = await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [PlaywrightTest("browsercontext-basic.spec.ts", "should emulate navigator.onLine")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldEmulateNavigatorOnLine() + { + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + Assert.That(await page.EvaluateAsync("() => window.navigator.onLine"), Is.True); + await context.SetOfflineAsync(true); + Assert.That(await page.EvaluateAsync("() => window.navigator.onLine"), Is.False); + await context.SetOfflineAsync(false); + Assert.That(await page.EvaluateAsync("() => window.navigator.onLine"), Is.True); + } + } +} diff --git a/src/Playwright.Tests/BrowserContextCSPTests.cs b/src/PlaywrightSharp.Tests/BrowserContextCSPTests.cs similarity index 75% rename from src/Playwright.Tests/BrowserContextCSPTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextCSPTests.cs index 7d4c8de8ca..600e32a99d 100644 --- a/src/Playwright.Tests/BrowserContextCSPTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextCSPTests.cs @@ -1,108 +1,101 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextCSPTests : PlaywrightSharpBrowserBaseTest - { - /// - public BrowserContextCSPTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-csp.spec.ts", "should bypass CSP meta tag")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBypassCSPMetatag() - { - // Make sure CSP prohibits addScriptTag. - await using (var context = await Browser.NewContextAsync()) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); - await page.AddScriptTagAsync(content: "window.__injected = 42;").ContinueWith(_ => Task.CompletedTask); - Assert.Null(await page.EvaluateAsync("window.__injected")); - } - // By-pass CSP and try one more time. - await using (var context = await Browser.NewContextAsync(bypassCSP: true)) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); - await page.AddScriptTagAsync(content: "window.__injected = 42;"); - Assert.Equal(42, await page.EvaluateAsync("window.__injected")); - } - } - - [PlaywrightTest("browsercontext-csp.spec.ts", "should bypass CSP header")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBypassCSPHeader() - { - // Make sure CSP prohibits addScriptTag. - Server.SetCSP("/empty.html", "default-src 'self'"); - - await using (var context = await Browser.NewContextAsync()) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - await page.AddScriptTagAsync(content: "window.__injected = 42;").ContinueWith(_ => Task.CompletedTask); - Assert.Null(await page.EvaluateAsync("window.__injected")); - } - - // By-pass CSP and try one more time. - await using (var context = await Browser.NewContextAsync(bypassCSP: true)) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - await page.AddScriptTagAsync(content: "window.__injected = 42;"); - Assert.Equal(42, await page.EvaluateAsync("window.__injected")); - } - } - - [PlaywrightTest("browsercontext-csp.spec.ts", "should bypass after cross-process navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBypassAfterCrossProcessNavigation() - { - await using var context = await Browser.NewContextAsync(bypassCSP: true); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); - await page.AddScriptTagAsync(content: "window.__injected = 42;"); - Assert.Equal(42, await page.EvaluateAsync("window.__injected")); - - await page.GoToAsync(TestConstants.CrossProcessUrl + "/csp.html"); - await page.AddScriptTagAsync(content: "window.__injected = 42;"); - Assert.Equal(42, await page.EvaluateAsync("window.__injected")); - } - - [PlaywrightTest("browsercontext-csp.spec.ts", "should bypass CSP in iframes as well")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBypassCSPInIframesAsWell() - { - await using (var context = await Browser.NewContextAsync()) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - - // Make sure CSP prohibits addScriptTag in an iframe. - var frame = await FrameUtils.AttachFrameAsync(page, "frame1", TestConstants.ServerUrl + "/csp.html"); - await frame.AddScriptTagAsync(content: "window.__injected = 42;").ContinueWith(_ => Task.CompletedTask); - Assert.Null(await frame.EvaluateAsync("() => window.__injected")); - } - - // By-pass CSP and try one more time. - await using (var context = await Browser.NewContextAsync(bypassCSP: true)) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - - // Make sure CSP prohibits addScriptTag in an iframe. - var frame = await FrameUtils.AttachFrameAsync(page, "frame1", TestConstants.ServerUrl + "/csp.html"); - await frame.AddScriptTagAsync(content: "window.__injected = 42;").ContinueWith(_ => Task.CompletedTask); - Assert.Equal(42, await frame.EvaluateAsync("() => window.__injected")); - - } - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextCSPTests : PlaywrightSharpBrowserBaseTest + { + [PlaywrightTest("browsercontext-csp.spec.ts", "should bypass CSP meta tag")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBypassCSPMetatag() + { + // Make sure CSP prohibits addScriptTag. + await using (var context = await Browser.NewContextAsync()) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); + await page.AddScriptTagAsync(content: "window.__injected = 42;").ContinueWith(_ => Task.CompletedTask); + Assert.That(await page.EvaluateAsync("window.__injected"), Is.Null); + } + // By-pass CSP and try one more time. + await using (var context = await Browser.NewContextAsync(bypassCSP: true)) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); + await page.AddScriptTagAsync(content: "window.__injected = 42;"); + Assert.That(await page.EvaluateAsync("window.__injected"), Is.EqualTo(42)); + } + } + + [PlaywrightTest("browsercontext-csp.spec.ts", "should bypass CSP header")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBypassCSPHeader() + { + // Make sure CSP prohibits addScriptTag. + Server.SetCSP("/empty.html", "default-src 'self'"); + + await using (var context = await Browser.NewContextAsync()) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + await page.AddScriptTagAsync(content: "window.__injected = 42;").ContinueWith(_ => Task.CompletedTask); + Assert.That(await page.EvaluateAsync("window.__injected"), Is.Null); + } + + // By-pass CSP and try one more time. + await using (var context = await Browser.NewContextAsync(bypassCSP: true)) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + await page.AddScriptTagAsync(content: "window.__injected = 42;"); + Assert.That(await page.EvaluateAsync("window.__injected"), Is.EqualTo(42)); + } + } + + [PlaywrightTest("browsercontext-csp.spec.ts", "should bypass after cross-process navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBypassAfterCrossProcessNavigation() + { + await using var context = await Browser.NewContextAsync(bypassCSP: true); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); + await page.AddScriptTagAsync(content: "window.__injected = 42;"); + Assert.That(await page.EvaluateAsync("window.__injected"), Is.EqualTo(42)); + + await page.GoToAsync(TestConstants.CrossProcessUrl + "/csp.html"); + await page.AddScriptTagAsync(content: "window.__injected = 42;"); + Assert.That(await page.EvaluateAsync("window.__injected"), Is.EqualTo(42)); + } + + [PlaywrightTest("browsercontext-csp.spec.ts", "should bypass CSP in iframes as well")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBypassCSPInIframesAsWell() + { + await using (var context = await Browser.NewContextAsync()) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + + // Make sure CSP prohibits addScriptTag in an iframe. + var frame = await FrameUtils.AttachFrameAsync(page, "frame1", TestConstants.ServerUrl + "/csp.html"); + await frame.AddScriptTagAsync(content: "window.__injected = 42;").ContinueWith(_ => Task.CompletedTask); + Assert.That(await frame.EvaluateAsync("() => window.__injected"), Is.Null); + } + + // By-pass CSP and try one more time. + await using (var context = await Browser.NewContextAsync(bypassCSP: true)) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + + // Make sure CSP prohibits addScriptTag in an iframe. + var frame = await FrameUtils.AttachFrameAsync(page, "frame1", TestConstants.ServerUrl + "/csp.html"); + await frame.AddScriptTagAsync(content: "window.__injected = 42;").ContinueWith(_ => Task.CompletedTask); + Assert.That(await frame.EvaluateAsync("() => window.__injected"), Is.EqualTo(42)); + + } + } + } +} diff --git a/src/Playwright.Tests/BrowserContextClearCookiesTests.cs b/src/PlaywrightSharp.Tests/BrowserContextClearCookiesTests.cs similarity index 56% rename from src/Playwright.Tests/BrowserContextClearCookiesTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextClearCookiesTests.cs index 840ae93b8f..13577f2626 100644 --- a/src/Playwright.Tests/BrowserContextClearCookiesTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextClearCookiesTests.cs @@ -1,66 +1,59 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextClearCookiesTests : PlaywrightSharpPageBaseTest - { - /// - public BrowserContextClearCookiesTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-clearcookies.spec.ts", "should clear cookies")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClearCookes() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Context.AddCookiesAsync(new Cookie - { - Url = TestConstants.EmptyPage, - Name = "cookie1", - Value = "1" - }); - Assert.Equal("cookie1=1", await Page.EvaluateAsync("document.cookie")); - await Context.ClearCookiesAsync(); - Assert.Empty(await Context.GetCookiesAsync()); - await Page.ReloadAsync(); - Assert.Empty(await Page.EvaluateAsync("document.cookie")); - } - - [PlaywrightTest("browsercontext-clearcookies.spec.ts", "should isolate cookies when clearing")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldIsolateWhenClearing() - { - await using var anotherContext = await Browser.NewContextAsync(); - await Context.AddCookiesAsync(new Cookie - { - Name = "page1cookie", - Value = "page1value", - Url = TestConstants.EmptyPage - }); - - await anotherContext.AddCookiesAsync(new Cookie - { - Name = "page2cookie", - Value = "page2value", - Url = TestConstants.EmptyPage - }); - - Assert.Single(await Context.GetCookiesAsync()); - Assert.Single(await anotherContext.GetCookiesAsync()); - - await Context.ClearCookiesAsync(); - Assert.Empty((await Context.GetCookiesAsync())); - Assert.Single((await anotherContext.GetCookiesAsync())); - - await anotherContext.ClearCookiesAsync(); - Assert.Empty(await Context.GetCookiesAsync()); - Assert.Empty(await anotherContext.GetCookiesAsync()); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextClearCookiesTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("browsercontext-clearcookies.spec.ts", "should clear cookies")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClearCookes() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Context.AddCookiesAsync(new Cookie + { + Url = TestConstants.EmptyPage, + Name = "cookie1", + Value = "1" + }); + Assert.That(await Page.EvaluateAsync("document.cookie"), Is.EqualTo("cookie1=1")); + await Context.ClearCookiesAsync(); + Assert.That(await Context.GetCookiesAsync(), Is.Empty); + await Page.ReloadAsync(); + Assert.That(await Page.EvaluateAsync("document.cookie"), Is.Empty); + } + + [PlaywrightTest("browsercontext-clearcookies.spec.ts", "should isolate cookies when clearing")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldIsolateWhenClearing() + { + await using var anotherContext = await Browser.NewContextAsync(); + await Context.AddCookiesAsync(new Cookie + { + Name = "page1cookie", + Value = "page1value", + Url = TestConstants.EmptyPage + }); + + await anotherContext.AddCookiesAsync(new Cookie + { + Name = "page2cookie", + Value = "page2value", + Url = TestConstants.EmptyPage + }); + + Assert.That(await Context.GetCookiesAsync(), Has.Exactly(1).Items); + Assert.That(await anotherContext.GetCookiesAsync(), Has.Exactly(1).Items); + + await Context.ClearCookiesAsync(); + Assert.That((await Context.GetCookiesAsync()), Is.Empty); + Assert.That((await anotherContext.GetCookiesAsync()), Has.Exactly(1).Items); + + await anotherContext.ClearCookiesAsync(); + Assert.That(await Context.GetCookiesAsync(), Is.Empty); + Assert.That(await anotherContext.GetCookiesAsync(), Is.Empty); + } + } +} diff --git a/src/Playwright.Tests/BrowserContextCookiesTests.cs b/src/PlaywrightSharp.Tests/BrowserContextCookiesTests.cs similarity index 50% rename from src/Playwright.Tests/BrowserContextCookiesTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextCookiesTests.cs index 4567322665..5f89439ed5 100644 --- a/src/Playwright.Tests/BrowserContextCookiesTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextCookiesTests.cs @@ -1,199 +1,192 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextCookiesTests : PlaywrightSharpPageBaseTest - { - /// - public BrowserContextCookiesTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-cookies.spec.ts", "should return no cookies in pristine browser context")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnNoCookiesInPristineBrowserContext() - => Assert.Empty(await Context.GetCookiesAsync()); - - [PlaywrightTest("browsercontext-cookies.spec.ts", "should get a cookie")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldGetACookie() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal("username=John Doe", await Page.EvaluateAsync(@"() => { - document.cookie = 'username=John Doe'; - return document.cookie; - }")); - - var cookie = (await Page.Context.GetCookiesAsync()).Single(); - Assert.Equal("username", cookie.Name); - Assert.Equal("John Doe", cookie.Value); - Assert.Equal("localhost", cookie.Domain); - Assert.Equal("/", cookie.Path); - Assert.Equal(-1, cookie.Expires); - Assert.False(cookie.HttpOnly); - Assert.False(cookie.Secure); - Assert.Equal(SameSiteAttribute.None, cookie.SameSite); - } - - [PlaywrightTest("browsercontext-cookies.spec.ts", "should get a non-session cookie")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldGetANonSessionCookie() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var date = new DateTime(2038, 1, 1); - Assert.Equal("username=John Doe", await Page.EvaluateAsync(@"timestamp => { - const date = new Date(timestamp); - document.cookie = `username=John Doe;expires=${date.toUTCString()}`; - return document.cookie; - }", date)); - - var cookie = (await Page.Context.GetCookiesAsync()).Single(); - Assert.Equal("username", cookie.Name); - Assert.Equal("John Doe", cookie.Value); - Assert.Equal("localhost", cookie.Domain); - Assert.Equal("/", cookie.Path); - Assert.Equal(new DateTimeOffset(date).ToUnixTimeSeconds(), cookie.Expires); - Assert.False(cookie.HttpOnly); - Assert.False(cookie.Secure); - Assert.Equal(SameSiteAttribute.None, cookie.SameSite); - } - - [PlaywrightTest("browsercontext-cookies.spec.ts", "should properly report httpOnly cookie")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldProperlyReportHttpOnlyCookie() - { - Server.SetRoute("/empty.html", context => - { - context.Response.Headers["Set-Cookie"] = "name=vaue;HttpOnly; Path=/"; - return Task.CompletedTask; - }); - await Page.GoToAsync(TestConstants.EmptyPage); - var cookies = await Context.GetCookiesAsync(); - Assert.Single(cookies); - Assert.True(cookies.ElementAt(0).HttpOnly); - } - - [PlaywrightTest("browsercontext-cookies.spec.ts", @"should properly report ""Strict"" sameSite cookie")] - [SkipBrowserAndPlatformFact(skipWebkit: true, skipWindows: true)] - public async Task ShouldProperlyReportStrictSameSiteCookie() - { - Server.SetRoute("/empty.html", context => - { - context.Response.Headers["Set-Cookie"] = "name=value;SameSite=Strict"; - return Task.CompletedTask; - }); - await Page.GoToAsync(TestConstants.EmptyPage); - var cookies = await Context.GetCookiesAsync(); - Assert.Single(cookies); - Assert.Equal(SameSiteAttribute.Strict, cookies.ElementAt(0).SameSite); - } - - [PlaywrightTest("browsercontext-cookies.spec.ts", @"should properly report ""Lax"" sameSite cookie")] - [SkipBrowserAndPlatformFact(skipWebkit: true, skipWindows: true)] - public async Task ShouldProperlyReportLaxSameSiteCookie() - { - Server.SetRoute("/empty.html", context => - { - context.Response.Headers["Set-Cookie"] = "name=value;SameSite=Lax"; - return Task.CompletedTask; - }); - await Page.GoToAsync(TestConstants.EmptyPage); - var cookies = await Context.GetCookiesAsync(); - Assert.Single(cookies); - Assert.Equal(SameSiteAttribute.Lax, cookies.ElementAt(0).SameSite); - } - - [PlaywrightTest("browsercontext-cookies.spec.ts", "should get multiple cookies")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldGetMultipleCookies() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Empty(await Context.GetCookiesAsync()); - - string documentCookie = await Page.EvaluateAsync(@"() => { - document.cookie = 'username=John Doe'; - document.cookie = 'password=1234'; - return document.cookie.split('; ').sort().join('; '); - }"); - - var cookies = (await Context.GetCookiesAsync()).OrderBy(c => c.Name).ToList(); - Assert.Equal("password=1234; username=John Doe", documentCookie); - var cookie = cookies[0]; - Assert.Equal("password", cookie.Name); - Assert.Equal("1234", cookie.Value); - Assert.Equal("localhost", cookie.Domain); - Assert.Equal("/", cookie.Path); - Assert.Equal(cookie.Expires, -1); - Assert.False(cookie.HttpOnly); - Assert.False(cookie.Secure); - Assert.Equal(SameSiteAttribute.None, cookie.SameSite); - - cookie = cookies[1]; - Assert.Equal("username", cookie.Name); - Assert.Equal("John Doe", cookie.Value); - Assert.Equal("localhost", cookie.Domain); - Assert.Equal("/", cookie.Path); - Assert.Equal(cookie.Expires, -1); - Assert.False(cookie.HttpOnly); - Assert.False(cookie.Secure); - Assert.Equal(SameSiteAttribute.None, cookie.SameSite); - } - - [PlaywrightTest("browsercontext-cookies.spec.ts", "should get cookies from multiple urls")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldGetCookiesFromMultipleUrls() - { - await Context.AddCookiesAsync( - new Cookie - { - Url = "https://foo.com", - Name = "doggo", - Value = "woofs" - }, - new Cookie - { - Url = "https://bar.com", - Name = "catto", - Value = "purrs" - }, - new Cookie - { - Url = "https://baz.com", - Name = "birdo", - Value = "tweets" - } - ); - var cookies = (await Context.GetCookiesAsync("https://foo.com", "https://baz.com")).OrderBy(c => c.Name).ToList(); - - Assert.Equal(2, cookies.Count); - - var cookie = cookies[0]; - Assert.Equal("birdo", cookie.Name); - Assert.Equal("tweets", cookie.Value); - Assert.Equal("baz.com", cookie.Domain); - Assert.Equal("/", cookie.Path); - Assert.Equal(cookie.Expires, -1); - Assert.False(cookie.HttpOnly); - Assert.True(cookie.Secure); - Assert.Equal(SameSiteAttribute.None, cookie.SameSite); - - cookie = cookies[1]; - Assert.Equal("doggo", cookie.Name); - Assert.Equal("woofs", cookie.Value); - Assert.Equal("foo.com", cookie.Domain); - Assert.Equal("/", cookie.Path); - Assert.Equal(cookie.Expires, -1); - Assert.False(cookie.HttpOnly); - Assert.True(cookie.Secure); - Assert.Equal(SameSiteAttribute.None, cookie.SameSite); - } - } -} +using System; +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextCookiesTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("browsercontext-cookies.spec.ts", "should return no cookies in pristine browser context")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnNoCookiesInPristineBrowserContext() + => Assert.That(await Context.GetCookiesAsync(), Is.Empty); + + [PlaywrightTest("browsercontext-cookies.spec.ts", "should get a cookie")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldGetACookie() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await Page.EvaluateAsync(@"() => { + document.cookie = 'username=John Doe'; + return document.cookie; + }"), Is.EqualTo("username=John Doe")); + + var cookie = (await Page.Context.GetCookiesAsync()).Single(); + Assert.That(cookie.Name, Is.EqualTo("username")); + Assert.That(cookie.Value, Is.EqualTo("John Doe")); + Assert.That(cookie.Domain, Is.EqualTo("localhost")); + Assert.That(cookie.Path, Is.EqualTo("/")); + Assert.That(cookie.Expires, Is.EqualTo(-1)); + Assert.That(cookie.HttpOnly, Is.False); + Assert.That(cookie.Secure, Is.False); + Assert.That(cookie.SameSite, Is.EqualTo(SameSiteAttribute.None)); + } + + [PlaywrightTest("browsercontext-cookies.spec.ts", "should get a non-session cookie")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldGetANonSessionCookie() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var date = new DateTime(2038, 1, 1); + Assert.That(await Page.EvaluateAsync(@"timestamp => { + const date = new Date(timestamp); + document.cookie = `username=John Doe;expires=${date.toUTCString()}`; + return document.cookie; + }", date), Is.EqualTo("username=John Doe")); + + var cookie = (await Page.Context.GetCookiesAsync()).Single(); + Assert.That(cookie.Name, Is.EqualTo("username")); + Assert.That(cookie.Value, Is.EqualTo("John Doe")); + Assert.That(cookie.Domain, Is.EqualTo("localhost")); + Assert.That(cookie.Path, Is.EqualTo("/")); + Assert.That(cookie.Expires, Is.EqualTo(new DateTimeOffset(date).ToUnixTimeSeconds())); + Assert.That(cookie.HttpOnly, Is.False); + Assert.That(cookie.Secure, Is.False); + Assert.That(cookie.SameSite, Is.EqualTo(SameSiteAttribute.None)); + } + + [PlaywrightTest("browsercontext-cookies.spec.ts", "should properly report httpOnly cookie")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldProperlyReportHttpOnlyCookie() + { + Server.SetRoute("/empty.html", context => + { + context.Response.Headers["Set-Cookie"] = "name=vaue;HttpOnly; Path=/"; + return Task.CompletedTask; + }); + await Page.GoToAsync(TestConstants.EmptyPage); + var cookies = await Context.GetCookiesAsync(); + Assert.That(cookies, Has.Exactly(1).Items); + Assert.That(cookies.ElementAt(0).HttpOnly, Is.True); + } + + [PlaywrightTest("browsercontext-cookies.spec.ts", @"should properly report ""Strict"" sameSite cookie")] + [SkipBrowserAndPlatformFact(skipWebkit: true, skipWindows: true)] + public async Task ShouldProperlyReportStrictSameSiteCookie() + { + Server.SetRoute("/empty.html", context => + { + context.Response.Headers["Set-Cookie"] = "name=value;SameSite=Strict"; + return Task.CompletedTask; + }); + await Page.GoToAsync(TestConstants.EmptyPage); + var cookies = await Context.GetCookiesAsync(); + Assert.That(cookies, Has.Exactly(1).Items); + Assert.That(cookies.ElementAt(0).SameSite, Is.EqualTo(SameSiteAttribute.Strict)); + } + + [PlaywrightTest("browsercontext-cookies.spec.ts", @"should properly report ""Lax"" sameSite cookie")] + [SkipBrowserAndPlatformFact(skipWebkit: true, skipWindows: true)] + public async Task ShouldProperlyReportLaxSameSiteCookie() + { + Server.SetRoute("/empty.html", context => + { + context.Response.Headers["Set-Cookie"] = "name=value;SameSite=Lax"; + return Task.CompletedTask; + }); + await Page.GoToAsync(TestConstants.EmptyPage); + var cookies = await Context.GetCookiesAsync(); + Assert.That(cookies, Has.Exactly(1).Items); + Assert.That(cookies.ElementAt(0).SameSite, Is.EqualTo(SameSiteAttribute.Lax)); + } + + [PlaywrightTest("browsercontext-cookies.spec.ts", "should get multiple cookies")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldGetMultipleCookies() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await Context.GetCookiesAsync(), Is.Empty); + + string documentCookie = await Page.EvaluateAsync(@"() => { + document.cookie = 'username=John Doe'; + document.cookie = 'password=1234'; + return document.cookie.split('; ').sort().join('; '); + }"); + + var cookies = (await Context.GetCookiesAsync()).OrderBy(c => c.Name).ToList(); + Assert.That(documentCookie, Is.EqualTo("password=1234; username=John Doe")); + var cookie = cookies[0]; + Assert.That(cookie.Name, Is.EqualTo("password")); + Assert.That(cookie.Value, Is.EqualTo("1234")); + Assert.That(cookie.Domain, Is.EqualTo("localhost")); + Assert.That(cookie.Path, Is.EqualTo("/")); + Assert.That(cookie.Expires, Is.EqualTo(-1)); + Assert.That(cookie.HttpOnly, Is.False); + Assert.That(cookie.Secure, Is.False); + Assert.That(cookie.SameSite, Is.EqualTo(SameSiteAttribute.None)); + + cookie = cookies[1]; + Assert.That(cookie.Name, Is.EqualTo("username")); + Assert.That(cookie.Value, Is.EqualTo("John Doe")); + Assert.That(cookie.Domain, Is.EqualTo("localhost")); + Assert.That(cookie.Path, Is.EqualTo("/")); + Assert.That(cookie.Expires, Is.EqualTo(-1)); + Assert.That(cookie.HttpOnly, Is.False); + Assert.That(cookie.Secure, Is.False); + Assert.That(cookie.SameSite, Is.EqualTo(SameSiteAttribute.None)); + } + + [PlaywrightTest("browsercontext-cookies.spec.ts", "should get cookies from multiple urls")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldGetCookiesFromMultipleUrls() + { + await Context.AddCookiesAsync( + new Cookie + { + Url = "https://foo.com", + Name = "doggo", + Value = "woofs" + }, + new Cookie + { + Url = "https://bar.com", + Name = "catto", + Value = "purrs" + }, + new Cookie + { + Url = "https://baz.com", + Name = "birdo", + Value = "tweets" + } + ); + var cookies = (await Context.GetCookiesAsync("https://foo.com", "https://baz.com")).OrderBy(c => c.Name).ToList(); + + Assert.That(cookies.Count, Is.EqualTo(2)); + + var cookie = cookies[0]; + Assert.That(cookie.Name, Is.EqualTo("birdo")); + Assert.That(cookie.Value, Is.EqualTo("tweets")); + Assert.That(cookie.Domain, Is.EqualTo("baz.com")); + Assert.That(cookie.Path, Is.EqualTo("/")); + Assert.That(cookie.Expires, Is.EqualTo(-1)); + Assert.That(cookie.HttpOnly, Is.False); + Assert.That(cookie.Secure, Is.True); + Assert.That(cookie.SameSite, Is.EqualTo(SameSiteAttribute.None)); + + cookie = cookies[1]; + Assert.That(cookie.Name, Is.EqualTo("doggo")); + Assert.That(cookie.Value, Is.EqualTo("woofs")); + Assert.That(cookie.Domain, Is.EqualTo("foo.com")); + Assert.That(cookie.Path, Is.EqualTo("/")); + Assert.That(cookie.Expires, Is.EqualTo(-1)); + Assert.That(cookie.HttpOnly, Is.False); + Assert.That(cookie.Secure, Is.True); + Assert.That(cookie.SameSite, Is.EqualTo(SameSiteAttribute.None)); + } + } +} diff --git a/src/Playwright.Tests/BrowserContextDeviceTests.cs b/src/PlaywrightSharp.Tests/BrowserContextDeviceTests.cs similarity index 73% rename from src/Playwright.Tests/BrowserContextDeviceTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextDeviceTests.cs index 1b02c0b0e0..54b5c53f7e 100644 --- a/src/Playwright.Tests/BrowserContextDeviceTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextDeviceTests.cs @@ -1,68 +1,60 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextDeviceTests : PlaywrightSharpBrowserBaseTest - { - private readonly BrowserContextOptions _iPhone = TestConstants.iPhone6; - - /// - public BrowserContextDeviceTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-device.spec.ts", "should work")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWork() - { - await using var context = await Browser.NewContextAsync(_iPhone); - var page = await context.NewPageAsync(); - - await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); - Assert.Equal(375, await page.EvaluateAsync("window.innerWidth")); - Assert.Contains("iPhone", await page.EvaluateAsync("navigator.userAgent")); - } - - [PlaywrightTest("browsercontext-device.spec.ts", "should support clicking")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldSupportClicking() - { - await using var context = await Browser.NewContextAsync(_iPhone); - var page = await context.NewPageAsync(); - - await page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - var button = await page.QuerySelectorAsync("button"); - await button.EvaluateAsync("button => button.style.marginTop = '200px'", button); - await button.ClickAsync(); - Assert.Equal("Clicked", await page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("browsercontext-device.spec.ts", "should scroll to click")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldScrollToClick() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 400, - Height = 400, - }, - DeviceScaleFactor = 1, - IsMobile = true, - }); - var page = await context.NewPageAsync(); - - await page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); - var element = await page.QuerySelectorAsync("#button-91"); - await element.ClickAsync(); - Assert.Equal("clicked", await element.TextContentAsync()); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextDeviceTests : PlaywrightSharpBrowserBaseTest + { + private readonly BrowserContextOptions _iPhone = TestConstants.iPhone6; + [PlaywrightTest("browsercontext-device.spec.ts", "should work")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWork() + { + await using var context = await Browser.NewContextAsync(_iPhone); + var page = await context.NewPageAsync(); + + await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); + Assert.That(await page.EvaluateAsync("window.innerWidth"), Is.EqualTo(375)); + Assert.That(await page.EvaluateAsync("navigator.userAgent"), Does.Contain("iPhone")); + } + + [PlaywrightTest("browsercontext-device.spec.ts", "should support clicking")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldSupportClicking() + { + await using var context = await Browser.NewContextAsync(_iPhone); + var page = await context.NewPageAsync(); + + await page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + var button = await page.QuerySelectorAsync("button"); + await button.EvaluateAsync("button => button.style.marginTop = '200px'", button); + await button.ClickAsync(); + Assert.That(await page.EvaluateAsync("() => result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("browsercontext-device.spec.ts", "should scroll to click")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldScrollToClick() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 400, + Height = 400, + }, + DeviceScaleFactor = 1, + IsMobile = true, + }); + var page = await context.NewPageAsync(); + + await page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); + var element = await page.QuerySelectorAsync("#button-91"); + await element.ClickAsync(); + Assert.That(await element.TextContentAsync(), Is.EqualTo("clicked")); + } + } +} diff --git a/src/Playwright.Tests/BrowserContextExposeFunctionTests.cs b/src/PlaywrightSharp.Tests/BrowserContextExposeFunctionTests.cs similarity index 61% rename from src/Playwright.Tests/BrowserContextExposeFunctionTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextExposeFunctionTests.cs index 810e7b4474..2b152b2a1f 100644 --- a/src/Playwright.Tests/BrowserContextExposeFunctionTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextExposeFunctionTests.cs @@ -1,120 +1,113 @@ -using System.Collections.Generic; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextExposeFunctionTests : PlaywrightSharpBrowserContextBaseTest - { - /// - public BrowserContextExposeFunctionTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-expose-function.spec.ts", "expose binding should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ExposeBindingShouldWork() - { - BindingSource bindingSource = null; - - await Context.ExposeBindingAsync("add", (BindingSource source, int a, int b) => - { - bindingSource = source; - return a + b; - }); - - var page = await Context.NewPageAsync(); - int result = await page.EvaluateAsync(@"async function() { - return await add(5, 6); - }"); - - Assert.Same(Context, bindingSource.Context); - Assert.Same(page, bindingSource.Page); - Assert.Same(page.MainFrame, bindingSource.Frame); - - Assert.Equal(11, result); - } - - [PlaywrightTest("browsercontext-expose-function.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Context.ExposeFunctionAsync("add", (int a, int b) => a + b); - var page = await Context.NewPageAsync(); - - await page.ExposeFunctionAsync("mul", (int a, int b) => a * b); - await Context.ExposeFunctionAsync("sub", (int a, int b) => a - b); - - var result = await page.EvaluateAsync(@"async function() { - return { mul: await mul(9, 4), add: await add(9, 4), sub: await sub(9, 4) }; - }"); - Assert.Equal(36, result.GetProperty("mul").GetInt32()); - Assert.Equal(13, result.GetProperty("add").GetInt32()); - Assert.Equal(5, result.GetProperty("sub").GetInt32()); - } - - [PlaywrightTest("browsercontext-expose-function.spec.ts", "should throw for duplicate registrations")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowForDuplicateRegistrations() - { - await Context.ExposeFunctionAsync("foo", () => { }); - await Context.ExposeFunctionAsync("bar", () => { }); - - var exception = await Assert.ThrowsAnyAsync(() => Context.ExposeFunctionAsync("foo", () => { })); - Assert.Equal("Function \"foo\" has been already registered", exception.Message); - - var page = await Context.NewPageAsync(); - exception = await Assert.ThrowsAnyAsync(() => page.ExposeFunctionAsync("foo", () => { })); - Assert.Equal("Function \"foo\" has been already registered in the browser context", exception.Message); - - await page.ExposeFunctionAsync("baz", () => { }); - exception = await Assert.ThrowsAnyAsync(() => Context.ExposeFunctionAsync("baz", () => { })); - Assert.Equal("Function \"baz\" has been already registered in one of the pages", exception.Message); - } - - [PlaywrightTest("browsercontext-expose-function.spec.ts", "should be callable from-inside addInitScript")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeCallableFromInsideAddInitScript() - { - var args = new List(); - await using var context = await Browser.NewContextAsync(); - await context.ExposeFunctionAsync("woof", (string arg) => { args.Add(arg); }); - - await context.AddInitScriptAsync("() => woof('context')"); - var page = await context.NewPageAsync(); - await page.AddInitScriptAsync("() => woof('page')"); - - args.Clear(); - await page.ReloadAsync(); - Assert.Contains("context", args); - Assert.Contains("page", args); - } - - [PlaywrightTest("browsercontext-expose-function.spec.ts", "exposeBindingHandle should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ExposeBindingHandleShouldWork() - { - IJSHandle target = null; - await Context.ExposeBindingAsync( - "logme", - (BindingSource _, IJSHandle t) => - { - target = t; - return 17; - }); - - var page = await Context.NewPageAsync(); - int result = await page.EvaluateAsync(@"async function() { - return window['logme']({ foo: 42 }); - }"); - - Assert.Equal(42, await target.EvaluateAsync("x => x.foo")); - Assert.Equal(17, result); - } - } -} +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextExposeFunctionTests : PlaywrightSharpBrowserContextBaseTest + { + [PlaywrightTest("browsercontext-expose-function.spec.ts", "expose binding should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ExposeBindingShouldWork() + { + BindingSource bindingSource = null; + + await Context.ExposeBindingAsync("add", (BindingSource source, int a, int b) => + { + bindingSource = source; + return a + b; + }); + + var page = await Context.NewPageAsync(); + int result = await page.EvaluateAsync(@"async function() { + return await add(5, 6); + }"); + + Assert.That(bindingSource.Context, Is.SameAs(Context)); + Assert.That(bindingSource.Page, Is.SameAs(page)); + Assert.That(bindingSource.Frame, Is.SameAs(page.MainFrame)); + + Assert.That(result, Is.EqualTo(11)); + } + + [PlaywrightTest("browsercontext-expose-function.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Context.ExposeFunctionAsync("add", (int a, int b) => a + b); + var page = await Context.NewPageAsync(); + + await page.ExposeFunctionAsync("mul", (int a, int b) => a * b); + await Context.ExposeFunctionAsync("sub", (int a, int b) => a - b); + + var result = await page.EvaluateAsync(@"async function() { + return { mul: await mul(9, 4), add: await add(9, 4), sub: await sub(9, 4) }; + }"); + Assert.That(result.GetProperty("mul").GetInt32(), Is.EqualTo(36)); + Assert.That(result.GetProperty("add").GetInt32(), Is.EqualTo(13)); + Assert.That(result.GetProperty("sub").GetInt32(), Is.EqualTo(5)); + } + + [PlaywrightTest("browsercontext-expose-function.spec.ts", "should throw for duplicate registrations")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowForDuplicateRegistrations() + { + await Context.ExposeFunctionAsync("foo", () => { }); + await Context.ExposeFunctionAsync("bar", () => { }); + + var exception = Assert.CatchAsync(() => Context.ExposeFunctionAsync("foo", () => { })); + Assert.That(exception.Message, Is.EqualTo("Function \"foo\" has been already registered")); + + var page = await Context.NewPageAsync(); + exception = Assert.CatchAsync(() => page.ExposeFunctionAsync("foo", () => { })); + Assert.That(exception.Message, Is.EqualTo("Function \"foo\" has been already registered in the browser context")); + + await page.ExposeFunctionAsync("baz", () => { }); + exception = Assert.CatchAsync(() => Context.ExposeFunctionAsync("baz", () => { })); + Assert.That(exception.Message, Is.EqualTo("Function \"baz\" has been already registered in one of the pages")); + } + + [PlaywrightTest("browsercontext-expose-function.spec.ts", "should be callable from-inside addInitScript")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeCallableFromInsideAddInitScript() + { + var args = new List(); + await using var context = await Browser.NewContextAsync(); + await context.ExposeFunctionAsync("woof", (string arg) => { args.Add(arg); }); + + await context.AddInitScriptAsync("() => woof('context')"); + var page = await context.NewPageAsync(); + await page.AddInitScriptAsync("() => woof('page')"); + + args.Clear(); + await page.ReloadAsync(); + Assert.That(args, Does.Contain("context")); + Assert.That(args, Does.Contain("page")); + } + + [PlaywrightTest("browsercontext-expose-function.spec.ts", "exposeBindingHandle should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ExposeBindingHandleShouldWork() + { + IJSHandle target = null; + await Context.ExposeBindingAsync( + "logme", + (BindingSource _, IJSHandle t) => + { + target = t; + return 17; + }); + + var page = await Context.NewPageAsync(); + int result = await page.EvaluateAsync(@"async function() { + return window['logme']({ foo: 42 }); + }"); + + Assert.That(await target.EvaluateAsync("x => x.foo"), Is.EqualTo(42)); + Assert.That(result, Is.EqualTo(17)); + } + } +} diff --git a/src/Playwright.Tests/BrowserContextHttpCredentialsTests.cs b/src/PlaywrightSharp.Tests/BrowserContextHttpCredentialsTests.cs similarity index 72% rename from src/Playwright.Tests/BrowserContextHttpCredentialsTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextHttpCredentialsTests.cs index c4659faee5..9990f86d06 100644 --- a/src/Playwright.Tests/BrowserContextHttpCredentialsTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextHttpCredentialsTests.cs @@ -1,96 +1,89 @@ -using System.Net; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextCredentialsTests : PlaywrightSharpBrowserBaseTest - { - /// - public BrowserContextCredentialsTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-credentials.spec.ts", "should fail without credentials")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWithoutCredentials() - { - Server.SetAuth("/empty.html", "user", "pass"); - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - var response = await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); - } - - [PlaywrightTest("browsercontext-credentials.spec.ts", "should work with setHTTPCredentials")] - [Fact(Skip = "This test is no longer applicable as the API no longer exists.")] - public void ShouldWorkWithSetHTTPCredentials() - { - } - - [PlaywrightTest("browsercontext-credentials.spec.ts", "should work with correct credentials")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithCorrectCredentials() - { - // Use unique user/password since Chromium caches credentials per origin. - Server.SetAuth("/empty.html", "user", "pass"); - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - HttpCredentials = new HttpCredentials - { - Username = "user", - Password = "pass" - }, - }); - - var page = await context.NewPageAsync(); - var response = await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - - [PlaywrightTest("browsercontext-credentials.spec.ts", "should fail if wrong credentials")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailIfWrongCredentials() - { - // Use unique user/password since Chromium caches credentials per origin. - Server.SetAuth("/empty.html", "user", "pass"); - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - HttpCredentials = new HttpCredentials - { - Username = "foo", - Password = "bar" - }, - }); - - var page = await context.NewPageAsync(); - var response = await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); - } - - [PlaywrightTest("browsercontext-credentials.spec.ts", "should return resource body")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnResourceBody() - { - Server.SetAuth("/playground.html", "user", "pass"); - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - HttpCredentials = new HttpCredentials - { - Username = "user", - Password = "pass" - }, - }); - - var page = await context.NewPageAsync(); - var response = await page.GoToAsync(TestConstants.ServerUrl + "/playground.html"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("Playground", await page.TitleAsync()); - Assert.Contains("Playground", await response.GetTextAsync()); - } - } -} +using System.Net; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextCredentialsTests : PlaywrightSharpBrowserBaseTest + { + [PlaywrightTest("browsercontext-credentials.spec.ts", "should fail without credentials")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWithoutCredentials() + { + Server.SetAuth("/empty.html", "user", "pass"); + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + var response = await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.Unauthorized)); + } + + [PlaywrightTest("browsercontext-credentials.spec.ts", "should work with setHTTPCredentials")] + [Test, Ignore("This test is no longer applicable as the API no longer exists.")] + public void ShouldWorkWithSetHTTPCredentials() + { + } + + [PlaywrightTest("browsercontext-credentials.spec.ts", "should work with correct credentials")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithCorrectCredentials() + { + // Use unique user/password since Chromium caches credentials per origin. + Server.SetAuth("/empty.html", "user", "pass"); + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + HttpCredentials = new HttpCredentials + { + Username = "user", + Password = "pass" + }, + }); + + var page = await context.NewPageAsync(); + var response = await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [PlaywrightTest("browsercontext-credentials.spec.ts", "should fail if wrong credentials")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailIfWrongCredentials() + { + // Use unique user/password since Chromium caches credentials per origin. + Server.SetAuth("/empty.html", "user", "pass"); + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + HttpCredentials = new HttpCredentials + { + Username = "foo", + Password = "bar" + }, + }); + + var page = await context.NewPageAsync(); + var response = await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.Unauthorized)); + } + + [PlaywrightTest("browsercontext-credentials.spec.ts", "should return resource body")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnResourceBody() + { + Server.SetAuth("/playground.html", "user", "pass"); + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + HttpCredentials = new HttpCredentials + { + Username = "user", + Password = "pass" + }, + }); + + var page = await context.NewPageAsync(); + var response = await page.GoToAsync(TestConstants.ServerUrl + "/playground.html"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + Assert.That(await page.TitleAsync(), Is.EqualTo("Playground")); + Assert.That(await response.GetTextAsync(), Does.Contain("Playground")); + } + } +} diff --git a/src/Playwright.Tests/BrowserContextLocaleTests.cs b/src/PlaywrightSharp.Tests/BrowserContextLocaleTests.cs similarity index 73% rename from src/Playwright.Tests/BrowserContextLocaleTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextLocaleTests.cs index 5ea0d9a1cc..ebe65a829a 100644 --- a/src/Playwright.Tests/BrowserContextLocaleTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextLocaleTests.cs @@ -1,148 +1,137 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextLocaleTests : PlaywrightSharpBrowserBaseTest - { - /// - public BrowserContextLocaleTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-locale.spec.ts", "should affect accept-language header")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAffectAcceptLanguageHeader() - { - await using var context = await Browser.NewContextAsync(locale: "fr-CH"); - string acceptLanguage = string.Empty; - var page = await context.NewPageAsync(); - var requestTask = Server.WaitForRequest("/empty.html", c => acceptLanguage = c.Headers["accept-language"]); - - await TaskUtils.WhenAll( - requestTask, - page.GoToAsync(TestConstants.EmptyPage)); - - Assert.StartsWith("fr-CH", acceptLanguage); - } - - [PlaywrightTest("browsercontext-locale.spec.ts", "should affect navigator.language")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAffectNavigatorLanguage() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Locale = "fr-CH" - }); - var page = await context.NewPageAsync(); - Assert.Equal("fr-CH", await page.EvaluateAsync("navigator.language")); - } - - [PlaywrightTest("browsercontext-locale.spec.ts", "should format number")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFormatNumber() - { - await using (var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Locale = "en-US" - })) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal("1,000,000.5", await page.EvaluateAsync("() => (1000000.50).toLocaleString()")); - } - - await using (var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Locale = "fr-CH" - })) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - string value = await page.EvaluateAsync("() => (1000000.50).toLocaleString().replace(/\\s/g, ' ')"); - Assert.Equal("1 000 000,5", value); - } - } - - [PlaywrightTest("browsercontext-locale.spec.ts", "should format date")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFormatDate() - { - await using (var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Locale = "en-US", - TimezoneId = "America/Los_Angeles", - })) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal( - "Sat Nov 19 2016 10:12:34 GMT-0800 (Pacific Standard Time)", - await page.EvaluateAsync("() => new Date(1479579154987).toString()")); - } - - await using (var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Locale = "de-DE", - TimezoneId = "Europe/Berlin", - })) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal( - "Sat Nov 19 2016 19:12:34 GMT+0100 (Mitteleuropäische Normalzeit)", - await page.EvaluateAsync("() => new Date(1479579154987).toString()")); - } - } - - [PlaywrightTest("browsercontext-locale.spec.ts", "should format number in popups")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFormatNumberInPopups() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Locale = "fr-CH" - }); - - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - var popupTask = page.WaitForEventAsync(PageEvent.Popup); - - await TaskUtils.WhenAll( - popupTask, - page.EvaluateAsync("url => window._popup = window.open(url)", TestConstants.ServerUrl + "/formatted-number.html")); - - var popup = popupTask.Result; - await popup.WaitForLoadStateAsync(LoadState.DOMContentLoaded); - Assert.Equal("1 000 000,5", await popup.EvaluateAsync("() => window.result")); - } - - [PlaywrightTest("browsercontext-locale.spec.ts", "should affect navigator.language in popups")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAffectNavigatorLanguageInPopups() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Locale = "fr-CH" - }); - - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - var popupTask = page.WaitForEventAsync(PageEvent.Popup); - - await TaskUtils.WhenAll( - popupTask, - page.EvaluateAsync("url => window._popup = window.open(url)", TestConstants.ServerUrl + "/formatted-number.html")); - - var popup = popupTask.Result; - await popup.WaitForLoadStateAsync(LoadState.DOMContentLoaded); - Assert.Equal("fr-CH", await popup.EvaluateAsync("() => window.initialNavigatorLanguage")); - } - } -} +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextLocaleTests : PlaywrightSharpBrowserBaseTest + { + [PlaywrightTest("browsercontext-locale.spec.ts", "should affect accept-language header")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAffectAcceptLanguageHeader() + { + await using var context = await Browser.NewContextAsync(locale: "fr-CH"); + string acceptLanguage = string.Empty; + var page = await context.NewPageAsync(); + var requestTask = Server.WaitForRequest("/empty.html", c => acceptLanguage = c.Headers["accept-language"]); + + await TaskUtils.WhenAll( + requestTask, + page.GoToAsync(TestConstants.EmptyPage)); + + Assert.That(acceptLanguage, Does.StartWith("fr-CH")); + } + + [PlaywrightTest("browsercontext-locale.spec.ts", "should affect navigator.language")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAffectNavigatorLanguage() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Locale = "fr-CH" + }); + var page = await context.NewPageAsync(); + Assert.That(await page.EvaluateAsync("navigator.language"), Is.EqualTo("fr-CH")); + } + + [PlaywrightTest("browsercontext-locale.spec.ts", "should format number")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFormatNumber() + { + await using (var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Locale = "en-US" + })) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await page.EvaluateAsync("() => (1000000.50).toLocaleString()"), Is.EqualTo("1,000,000.5")); + } + + await using (var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Locale = "fr-CH" + })) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + string value = await page.EvaluateAsync("() => (1000000.50).toLocaleString().replace(/\\s/g, ' ')"); + Assert.That(value, Is.EqualTo("1 000 000,5")); + } + } + + [PlaywrightTest("browsercontext-locale.spec.ts", "should format date")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFormatDate() + { + await using (var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Locale = "en-US", + TimezoneId = "America/Los_Angeles", + })) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await page.EvaluateAsync("() => new Date(1479579154987).toString()"), Is.EqualTo("Sat Nov 19 2016 10:12:34 GMT-0800 (Pacific Standard Time)")); + } + + await using (var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Locale = "de-DE", + TimezoneId = "Europe/Berlin", + })) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await page.EvaluateAsync("() => new Date(1479579154987).toString()"), Is.EqualTo("Sat Nov 19 2016 19:12:34 GMT+0100 (Mitteleuropäische Normalzeit)")); + } + } + + [PlaywrightTest("browsercontext-locale.spec.ts", "should format number in popups")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFormatNumberInPopups() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Locale = "fr-CH" + }); + + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + var popupTask = page.WaitForEventAsync(PageEvent.Popup); + + await TaskUtils.WhenAll( + popupTask, + page.EvaluateAsync("url => window._popup = window.open(url)", TestConstants.ServerUrl + "/formatted-number.html")); + + var popup = popupTask.Result; + await popup.WaitForLoadStateAsync(LoadState.DOMContentLoaded); + Assert.That(await popup.EvaluateAsync("() => window.result"), Is.EqualTo("1 000 000,5")); + } + + [PlaywrightTest("browsercontext-locale.spec.ts", "should affect navigator.language in popups")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAffectNavigatorLanguageInPopups() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Locale = "fr-CH" + }); + + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + var popupTask = page.WaitForEventAsync(PageEvent.Popup); + + await TaskUtils.WhenAll( + popupTask, + page.EvaluateAsync("url => window._popup = window.open(url)", TestConstants.ServerUrl + "/formatted-number.html")); + + var popup = popupTask.Result; + await popup.WaitForLoadStateAsync(LoadState.DOMContentLoaded); + Assert.That(await popup.EvaluateAsync("() => window.initialNavigatorLanguage"), Is.EqualTo("fr-CH")); + } + } +} diff --git a/src/Playwright.Tests/BrowserContextPageEventTests.cs b/src/PlaywrightSharp.Tests/BrowserContextPageEventTests.cs similarity index 77% rename from src/Playwright.Tests/BrowserContextPageEventTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextPageEventTests.cs index 1f049a85fb..ab0ddb586f 100644 --- a/src/Playwright.Tests/BrowserContextPageEventTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextPageEventTests.cs @@ -1,234 +1,224 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextPageEventTests : PlaywrightSharpBrowserBaseTest - { - /// - public BrowserContextPageEventTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-page-event.spec.ts", "should have url")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHaveUrl() - { - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - - var (otherPage, _) = await TaskUtils.WhenAll( - context.WaitForEventAsync(ContextEvent.Page), - page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); - - Assert.Equal(TestConstants.EmptyPage, otherPage.Url); - } - - [PlaywrightTest("browsercontext-page-event.spec.ts", "should have url after domcontentloaded")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHaveUrlAfterDomcontentloaded() - { - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - - var (otherPage, _) = await TaskUtils.WhenAll( - context.WaitForEventAsync(ContextEvent.Page), - page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); - - await otherPage.WaitForLoadStateAsync(LoadState.DOMContentLoaded); - Assert.Equal(TestConstants.EmptyPage, otherPage.Url); - } - - [PlaywrightTest("browsercontext-page-event.spec.ts", "should have about:blank url with domcontentloaded")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHaveAboutBlankUrlWithDomcontentloaded() - { - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - - var (otherPage, _) = await TaskUtils.WhenAll( - context.WaitForEventAsync(ContextEvent.Page), - page.EvaluateAsync("url => window.open(url)", "about:blank")); - - await otherPage.WaitForLoadStateAsync(LoadState.DOMContentLoaded); - Assert.Equal("about:blank", otherPage.Url); - } - - [PlaywrightTest("browsercontext-page-event.spec.ts", "should have about:blank for empty url with domcontentloaded")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHaveAboutBlankUrlForEmptyUrlWithDomcontentloaded() - { - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - - var (otherPage, _) = await TaskUtils.WhenAll( - context.WaitForEventAsync(ContextEvent.Page), - page.EvaluateAsync("() => window.open()")); - - await otherPage.WaitForLoadStateAsync(LoadState.DOMContentLoaded); - Assert.Equal("about:blank", otherPage.Url); - } - - [PlaywrightTest("browsercontext-page-event.spec.ts", "should report when a new page is created and closed")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReportWhenANewPageIsCreatedAndClosed() - { - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - - var (otherPageEvent, _) = await TaskUtils.WhenAll( - context.WaitForEventAsync(ContextEvent.Page), - page.EvaluateAsync("url => window.open(url)", TestConstants.CrossProcessUrl + "/empty.html")); - var otherPage = otherPageEvent; - - Assert.Contains(TestConstants.CrossProcessUrl, otherPage.Url); - Assert.Equal("Hello world", await otherPage.EvaluateAsync("() => ['Hello', 'world'].join(' ')")); - Assert.NotNull(await otherPage.QuerySelectorAsync("body")); - - - var allPages = context.Pages; - Assert.Contains(page, allPages); - Assert.Contains(otherPage, allPages); - - var closeEventReceived = new TaskCompletionSource(); - otherPage.Close += (_, _) => closeEventReceived.TrySetResult(true); - - await otherPage.CloseAsync(); - await closeEventReceived.Task.WithTimeout(TestConstants.DefaultTaskTimeout); - - allPages = context.Pages; - Assert.Contains(page, allPages); - Assert.DoesNotContain(otherPage, allPages); - } - - [PlaywrightTest("browsercontext-page-event.spec.ts", "should report initialized pages")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReportInitializedPages() - { - await using var context = await Browser.NewContextAsync(); - var pageTask = context.WaitForEventAsync(ContextEvent.Page); - _ = context.NewPageAsync(); - var newPage = await pageTask; - Assert.Equal("about:blank", newPage.Url); - - var popupTask = context.WaitForEventAsync(ContextEvent.Page); - var evaluateTask = newPage.EvaluateAsync("() => window.open('about:blank')"); - var popup = await popupTask; - Assert.Equal("about:blank", popup.Url); - await evaluateTask; - } - - [PlaywrightTest("browsercontext-page-event.spec.ts", "should not crash while redirecting of original request was missed")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotCrashWhileRedirectingOfOriginalRequestWasMissed() - { - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - - Server.SetRoute("/one-style.css", context => - { - context.Response.Redirect("/one-style.css"); - return Task.CompletedTask; - }); - - // Open a new page. Use window.open to connect to the page later. - var pageCreatedTask = context.WaitForEventAsync(ContextEvent.Page); - await TaskUtils.WhenAll( - pageCreatedTask, - page.EvaluateAsync("url => window.open(url)", TestConstants.ServerUrl + "/one-style.html"), - Server.WaitForRequest("/one-style.css")); - - var newPage = pageCreatedTask.Result; - - await newPage.WaitForLoadStateAsync(LoadState.DOMContentLoaded); - Assert.Equal(TestConstants.ServerUrl + "/one-style.html", newPage.Url); - } - - [PlaywrightTest("browsercontext-page-event.spec.ts", "should have an opener")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHaveAnOpener() - { - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - - var (popupEvent, _) = await TaskUtils.WhenAll( - context.WaitForEventAsync(ContextEvent.Page), - page.GoToAsync(TestConstants.ServerUrl + "/popup/window-open.html")); - - var popup = popupEvent; - Assert.Equal(TestConstants.ServerUrl + "/popup/popup.html", popup.Url); - Assert.Same(page, await popup.OpenerAsync()); - Assert.Null(await page.OpenerAsync()); - } - - [PlaywrightTest("browsercontext-page-event.spec.ts", "should fire page lifecycle events")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFirePageLoadStates() - { - await using var context = await Browser.NewContextAsync(); - var events = new List(); - - context.Page += (_, e) => - { - events.Add("CREATED: " + e.Url); - e.Close += (sender, _) => events.Add("DESTROYED: " + ((IPage)sender).Url); - }; - - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - await page.CloseAsync(); - Assert.Equal( - new List() - { - "CREATED: about:blank", - $"DESTROYED: {TestConstants.EmptyPage}" - }, - events); - } - - [PlaywrightTest("browsercontext-page-event.spec.ts", "should work with Shift-clicking")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task ShouldWorkWithShiftClicking() - { - // WebKit: Shift+Click does not open a new window. - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - await page.SetContentAsync("yo"); - - var popupEventTask = context.WaitForEventAsync(ContextEvent.Page); - await TaskUtils.WhenAll( - popupEventTask, - page.ClickAsync("a", modifiers: new[] { KeyboardModifier.Shift })); - - Assert.Null(await popupEventTask.Result.OpenerAsync()); - } - - [PlaywrightTest("browsercontext-page-event.spec.ts", "should report when a new page is created and closed")] - [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] - public async Task ShouldWorkWithCtrlClicking() - { - // Firefox: reports an opener in this case. - // WebKit: Ctrl+Click does not open a new tab. - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - await page.SetContentAsync("yo"); - - var popupEventTask = context.WaitForEventAsync(ContextEvent.Page); - await TaskUtils.WhenAll( - popupEventTask, - page.ClickAsync("a", modifiers: new[] { TestConstants.IsMacOSX ? KeyboardModifier.Meta : KeyboardModifier.Control })); - - Assert.Null(await popupEventTask.Result.OpenerAsync()); - } - } -} +using System.Collections.Generic; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextPageEventTests : PlaywrightSharpBrowserBaseTest + { + [PlaywrightTest("browsercontext-page-event.spec.ts", "should have url")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHaveUrl() + { + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + + var (otherPage, _) = await TaskUtils.WhenAll( + context.WaitForEventAsync(ContextEvent.Page), + page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); + + Assert.That(otherPage.Url, Is.EqualTo(TestConstants.EmptyPage)); + } + + [PlaywrightTest("browsercontext-page-event.spec.ts", "should have url after domcontentloaded")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHaveUrlAfterDomcontentloaded() + { + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + + var (otherPage, _) = await TaskUtils.WhenAll( + context.WaitForEventAsync(ContextEvent.Page), + page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); + + await otherPage.WaitForLoadStateAsync(LoadState.DOMContentLoaded); + Assert.That(otherPage.Url, Is.EqualTo(TestConstants.EmptyPage)); + } + + [PlaywrightTest("browsercontext-page-event.spec.ts", "should have about:blank url with domcontentloaded")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHaveAboutBlankUrlWithDomcontentloaded() + { + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + + var (otherPage, _) = await TaskUtils.WhenAll( + context.WaitForEventAsync(ContextEvent.Page), + page.EvaluateAsync("url => window.open(url)", "about:blank")); + + await otherPage.WaitForLoadStateAsync(LoadState.DOMContentLoaded); + Assert.That(otherPage.Url, Is.EqualTo("about:blank")); + } + + [PlaywrightTest("browsercontext-page-event.spec.ts", "should have about:blank for empty url with domcontentloaded")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHaveAboutBlankUrlForEmptyUrlWithDomcontentloaded() + { + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + + var (otherPage, _) = await TaskUtils.WhenAll( + context.WaitForEventAsync(ContextEvent.Page), + page.EvaluateAsync("() => window.open()")); + + await otherPage.WaitForLoadStateAsync(LoadState.DOMContentLoaded); + Assert.That(otherPage.Url, Is.EqualTo("about:blank")); + } + + [PlaywrightTest("browsercontext-page-event.spec.ts", "should report when a new page is created and closed")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReportWhenANewPageIsCreatedAndClosed() + { + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + + var (otherPageEvent, _) = await TaskUtils.WhenAll( + context.WaitForEventAsync(ContextEvent.Page), + page.EvaluateAsync("url => window.open(url)", TestConstants.CrossProcessUrl + "/empty.html")); + var otherPage = otherPageEvent; + + Assert.That(otherPage.Url, Does.Contain(TestConstants.CrossProcessUrl)); + Assert.That(await otherPage.EvaluateAsync("() => ['Hello', 'world'].join(' ')"), Is.EqualTo("Hello world")); + Assert.That(await otherPage.QuerySelectorAsync("body"), Is.Not.Null); + + var allPages = context.Pages; + Assert.That(allPages, Does.Contain(page)); + Assert.That(allPages, Does.Contain(otherPage)); + + var closeEventReceived = new TaskCompletionSource(); + otherPage.Close += (_, _) => closeEventReceived.TrySetResult(true); + + await otherPage.CloseAsync(); + await closeEventReceived.Task.WithTimeout(TestConstants.DefaultTaskTimeout); + + allPages = context.Pages; + Assert.That(allPages, Does.Contain(page)); + Assert.That(allPages, Does.Not.Contain(otherPage)); + } + + [PlaywrightTest("browsercontext-page-event.spec.ts", "should report initialized pages")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReportInitializedPages() + { + await using var context = await Browser.NewContextAsync(); + var pageTask = context.WaitForEventAsync(ContextEvent.Page); + _ = context.NewPageAsync(); + var newPage = await pageTask; + Assert.That(newPage.Url, Is.EqualTo("about:blank")); + + var popupTask = context.WaitForEventAsync(ContextEvent.Page); + var evaluateTask = newPage.EvaluateAsync("() => window.open('about:blank')"); + var popup = await popupTask; + Assert.That(popup.Url, Is.EqualTo("about:blank")); + await evaluateTask; + } + + [PlaywrightTest("browsercontext-page-event.spec.ts", "should not crash while redirecting of original request was missed")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotCrashWhileRedirectingOfOriginalRequestWasMissed() + { + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + + Server.SetRoute("/one-style.css", context => + { + context.Response.Redirect("/one-style.css"); + return Task.CompletedTask; + }); + + // Open a new page. Use window.open to connect to the page later. + var pageCreatedTask = context.WaitForEventAsync(ContextEvent.Page); + await TaskUtils.WhenAll( + pageCreatedTask, + page.EvaluateAsync("url => window.open(url)", TestConstants.ServerUrl + "/one-style.html"), + Server.WaitForRequest("/one-style.css")); + + var newPage = pageCreatedTask.Result; + + await newPage.WaitForLoadStateAsync(LoadState.DOMContentLoaded); + Assert.That(newPage.Url, Is.EqualTo(TestConstants.ServerUrl + "/one-style.html")); + } + + [PlaywrightTest("browsercontext-page-event.spec.ts", "should have an opener")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHaveAnOpener() + { + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + + var (popupEvent, _) = await TaskUtils.WhenAll( + context.WaitForEventAsync(ContextEvent.Page), + page.GoToAsync(TestConstants.ServerUrl + "/popup/window-open.html")); + + var popup = popupEvent; + Assert.That(popup.Url, Is.EqualTo(TestConstants.ServerUrl + "/popup/popup.html")); + Assert.That(await popup.OpenerAsync(), Is.SameAs(page)); + Assert.That(await page.OpenerAsync(), Is.Null); + } + + [PlaywrightTest("browsercontext-page-event.spec.ts", "should fire page lifecycle events")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFirePageLoadStates() + { + await using var context = await Browser.NewContextAsync(); + var events = new List(); + + context.Page += (_, e) => + { + events.Add("CREATED: " + e.Url); + e.Close += (sender, _) => events.Add("DESTROYED: " + ((IPage)sender).Url); + }; + + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + await page.CloseAsync(); + Assert.That(events, Is.EqualTo(new List() + { + "CREATED: about:blank", + $"DESTROYED: {TestConstants.EmptyPage}" + })); + } + + [PlaywrightTest("browsercontext-page-event.spec.ts", "should work with Shift-clicking")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task ShouldWorkWithShiftClicking() + { + // WebKit: Shift+Click does not open a new window. + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + await page.SetContentAsync("yo"); + + var popupEventTask = context.WaitForEventAsync(ContextEvent.Page); + await TaskUtils.WhenAll( + popupEventTask, + page.ClickAsync("a", modifiers: new[] { KeyboardModifier.Shift })); + + Assert.That(await popupEventTask.Result.OpenerAsync(), Is.Null); + } + + [PlaywrightTest("browsercontext-page-event.spec.ts", "should report when a new page is created and closed")] + [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] + public async Task ShouldWorkWithCtrlClicking() + { + // Firefox: reports an opener in this case. + // WebKit: Ctrl+Click does not open a new tab. + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + await page.SetContentAsync("yo"); + + var popupEventTask = context.WaitForEventAsync(ContextEvent.Page); + await TaskUtils.WhenAll( + popupEventTask, + page.ClickAsync("a", modifiers: new[] { TestConstants.IsMacOSX ? KeyboardModifier.Meta : KeyboardModifier.Control })); + + Assert.That(await popupEventTask.Result.OpenerAsync(), Is.Null); + } + } +} diff --git a/src/Playwright.Tests/BrowserContextRouteTests.cs b/src/PlaywrightSharp.Tests/BrowserContextRouteTests.cs similarity index 68% rename from src/Playwright.Tests/BrowserContextRouteTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextRouteTests.cs index aed1100c1d..3d32a160f3 100644 --- a/src/Playwright.Tests/BrowserContextRouteTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextRouteTests.cs @@ -1,140 +1,133 @@ -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.Playwright.Contracts.Constants; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextRouteTests : PlaywrightSharpBrowserBaseTest - { - /// - public BrowserContextRouteTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-route.spec.ts", "should intercept")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldIntercept() - { - bool intercepted = false; - - await using var context = await Browser.NewContextAsync(); - IPage page = null; - - await context.RouteAsync("**/empty.html", (route) => - { - intercepted = true; - - Assert.Contains("empty.html", route.Request.Url); - Assert.False(string.IsNullOrEmpty(route.Request.GetHeaderValue("user-agent"))); - Assert.Equal(HttpMethod.Get.Method, route.Request.Method); - Assert.Null(route.Request.PostData); - Assert.True(route.Request.IsNavigationRequest); - Assert.Equal(ResourceTypes.Document, route.Request.ResourceType, false); - Assert.Same(page.MainFrame, route.Request.Frame); - Assert.Equal("about:blank", page.MainFrame.Url); - - route.ResumeAsync(); - }); - - page = await context.NewPageAsync(); - var response = await page.GoToAsync(TestConstants.EmptyPage); - Assert.True(response.Ok); - Assert.True(intercepted); - } - - [PlaywrightTest("browsercontext-route.spec.ts", "should unroute")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldUnroute() - { - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - var intercepted = new List(); - - Action handler1 = (route) => - { - intercepted.Add(1); - route.ResumeAsync(); - }; - - await context.RouteAsync("**/empty.html", handler1); - await context.RouteAsync("**/empty.html", (route) => - { - intercepted.Add(2); - route.ResumeAsync(); - }); - - await context.RouteAsync("**/empty.html", (route) => - { - intercepted.Add(3); - route.ResumeAsync(); - }); - - await context.RouteAsync("**/*", (route) => - { - intercepted.Add(4); - route.ResumeAsync(); - }); - - await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(new List() { 1 }, intercepted); - - intercepted.Clear(); - await context.UnrouteAsync("**/empty.html", handler1); - await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(new List() { 2 }, intercepted); - - intercepted.Clear(); - await context.UnrouteAsync("**/empty.html"); - await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(new List() { 4 }, intercepted); - } - - [PlaywrightTest("browsercontext-route.spec.ts", "should yield to page.route")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldYieldToPageRoute() - { - await using var context = await Browser.NewContextAsync(); - await context.RouteAsync("**/empty.html", (route) => - { - route.FulfillAsync(HttpStatusCode.OK, "context"); - }); - - var page = await context.NewPageAsync(); - await page.RouteAsync("**/empty.html", (route) => - { - route.FulfillAsync(HttpStatusCode.OK, "page"); - }); - - var response = await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal("page", await response.GetTextAsync()); - } - - [PlaywrightTest("browsercontext-route.spec.ts", "should fall back to context.route")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFallBackToContextRoute() - { - await using var context = await Browser.NewContextAsync(); - await context.RouteAsync("**/empty.html", (route) => - { - route.FulfillAsync(HttpStatusCode.OK, "context"); - }); - - var page = await context.NewPageAsync(); - await page.RouteAsync("**/non-empty.html", (route) => - { - route.FulfillAsync(HttpStatusCode.OK, "page"); - }); - - var response = await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal("context", await response.GetTextAsync()); - } - } -} +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Contracts.Constants; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextRouteTests : PlaywrightSharpBrowserBaseTest + { + [PlaywrightTest("browsercontext-route.spec.ts", "should intercept")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldIntercept() + { + bool intercepted = false; + + await using var context = await Browser.NewContextAsync(); + IPage page = null; + + await context.RouteAsync("**/empty.html", (route) => + { + intercepted = true; + + Assert.That(route.Request.Url, Does.Contain("empty.html")); + Assert.That(string.IsNullOrEmpty(route.Request.GetHeaderValue("user-agent")), Is.False); + Assert.That(route.Request.Method, Is.EqualTo(HttpMethod.Get.Method)); + Assert.That(route.Request.PostData, Is.Null); + Assert.That(route.Request.IsNavigationRequest, Is.True); + Assert.That(route.Request.ResourceType, Is.EqualTo(ResourceTypes.Document)); + Assert.That(route.Request.Frame, Is.SameAs(page.MainFrame)); + Assert.That(page.MainFrame.Url, Is.EqualTo("about:blank")); + + route.ResumeAsync(); + }); + + page = await context.NewPageAsync(); + var response = await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.Ok, Is.True); + Assert.That(intercepted, Is.True); + } + + [PlaywrightTest("browsercontext-route.spec.ts", "should unroute")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldUnroute() + { + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + var intercepted = new List(); + + Action handler1 = (route) => + { + intercepted.Add(1); + route.ResumeAsync(); + }; + + await context.RouteAsync("**/empty.html", handler1); + await context.RouteAsync("**/empty.html", (route) => + { + intercepted.Add(2); + route.ResumeAsync(); + }); + + await context.RouteAsync("**/empty.html", (route) => + { + intercepted.Add(3); + route.ResumeAsync(); + }); + + await context.RouteAsync("**/*", (route) => + { + intercepted.Add(4); + route.ResumeAsync(); + }); + + await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(intercepted, Is.EqualTo(new List() { 1 })); + + intercepted.Clear(); + await context.UnrouteAsync("**/empty.html", handler1); + await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(intercepted, Is.EqualTo(new List() { 2 })); + + intercepted.Clear(); + await context.UnrouteAsync("**/empty.html"); + await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(intercepted, Is.EqualTo(new List() { 4 })); + } + + [PlaywrightTest("browsercontext-route.spec.ts", "should yield to page.route")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldYieldToPageRoute() + { + await using var context = await Browser.NewContextAsync(); + await context.RouteAsync("**/empty.html", (route) => + { + route.FulfillAsync(HttpStatusCode.OK, "context"); + }); + + var page = await context.NewPageAsync(); + await page.RouteAsync("**/empty.html", (route) => + { + route.FulfillAsync(HttpStatusCode.OK, "page"); + }); + + var response = await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await response.GetTextAsync(), Is.EqualTo("page")); + } + + [PlaywrightTest("browsercontext-route.spec.ts", "should fall back to context.route")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFallBackToContextRoute() + { + await using var context = await Browser.NewContextAsync(); + await context.RouteAsync("**/empty.html", (route) => + { + route.FulfillAsync(HttpStatusCode.OK, "context"); + }); + + var page = await context.NewPageAsync(); + await page.RouteAsync("**/non-empty.html", (route) => + { + route.FulfillAsync(HttpStatusCode.OK, "page"); + }); + + var response = await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await response.GetTextAsync(), Is.EqualTo("context")); + } + } +} diff --git a/src/Playwright.Tests/BrowserContextStorageStateTests.cs b/src/PlaywrightSharp.Tests/BrowserContextStorageStateTests.cs similarity index 73% rename from src/Playwright.Tests/BrowserContextStorageStateTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextStorageStateTests.cs index 938927c55d..66f6d10f9e 100644 --- a/src/Playwright.Tests/BrowserContextStorageStateTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextStorageStateTests.cs @@ -1,89 +1,82 @@ -using System.Collections.Generic; -using System.IO; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Microsoft.Playwright.Tests.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public sealed class BrowsercontextStorageStateTests : PlaywrightSharpPageBaseTest - { - /// - public BrowsercontextStorageStateTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-storage-state.spec.ts", "should capture local storage")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCaptureLocalStorage() - { - var page1 = await Context.NewPageAsync(); - await page1.RouteAsync("**/*", (route) => - { - route.FulfillAsync(body: ""); - }); - - await page1.GoToAsync("https://www.example.com"); - await page1.EvaluateAsync(@"() => - { - localStorage['name1'] = 'value1'; - }"); - await page1.GoToAsync("https://www.domain.com"); - await page1.EvaluateAsync(@"() => - { - localStorage['name2'] = 'value2'; - }"); - - string storage = await Context.StorageStateAsync(); - - // TODO: think about IVT-in the StorageState and serializing - string expected = @"{""cookies"":[],""origins"":[{""origin"":""https://www.example.com"",""localStorage"":[{""name"":""name1"",""value"":""value1""}]},{""origin"":""https://www.domain.com"",""localStorage"":[{""name"":""name2"",""value"":""value2""}]}]}"; - Assert.Equal(storage, expected); - } - - [PlaywrightTest("browsercontext-storage-state.spec.ts", "should set local storage")] - [Fact(Timeout = TestConstants.DefaultTestTimeout, Skip = "Needs to be implemented.")] - public void ShouldSetLocalStorage() - { - } - - [PlaywrightTest("browsercontext-storage-state.spec.ts", "should round-trip through the file")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRoundTripThroughTheFile() - { - var page1 = await Context.NewPageAsync(); - await page1.RouteAsync("**/*", (route) => - { - route.FulfillAsync(body: ""); - }); - - await page1.GoToAsync("https://www.example.com"); - await page1.EvaluateAsync(@"() => - { - localStorage['name1'] = 'value1'; - document.cookie = 'username=John Doe'; - }"); - using var tempDir = new TempDirectory(); - string path = Path.Combine(tempDir.Path, "storage-state.json"); - string storage = await Context.StorageStateAsync(path); - Assert.Equal(storage, File.ReadAllText(path)); - - await using var context = await Browser.NewContextAsync(storageStatePath: path); - var page2 = await context.NewPageAsync(); - await page1.RouteAsync("**/*", (route) => - { - route.FulfillAsync(body: ""); - }); - - await page1.GoToAsync("https://www.example.com"); - Assert.Equal("value1", await page1.EvaluateAsync("localStorage['name1']")); - Assert.Equal("username=John Doe", await page1.EvaluateAsync("document.cookie")); - } - } -} +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; +using PlaywrightSharp.Tests.Helpers; + +namespace PlaywrightSharp.Tests +{ + public sealed class BrowsercontextStorageStateTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("browsercontext-storage-state.spec.ts", "should capture local storage")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCaptureLocalStorage() + { + var page1 = await Context.NewPageAsync(); + await page1.RouteAsync("**/*", (route) => + { + route.FulfillAsync(body: ""); + }); + + await page1.GoToAsync("https://www.example.com"); + await page1.EvaluateAsync(@"() => + { + localStorage['name1'] = 'value1'; + }"); + await page1.GoToAsync("https://www.domain.com"); + await page1.EvaluateAsync(@"() => + { + localStorage['name2'] = 'value2'; + }"); + + string storage = await Context.StorageStateAsync(); + + // TODO: think about IVT-in the StorageState and serializing + string expected = @"{""cookies"":[],""origins"":[{""origin"":""https://www.example.com"",""localStorage"":[{""name"":""name1"",""value"":""value1""}]},{""origin"":""https://www.domain.com"",""localStorage"":[{""name"":""name2"",""value"":""value2""}]}]}"; + Assert.That(expected, Is.EqualTo(storage)); + } + + [PlaywrightTest("browsercontext-storage-state.spec.ts", "should set local storage")] + [Test, Ignore("Needs to be implemented.")] + public void ShouldSetLocalStorage() + { + } + + [PlaywrightTest("browsercontext-storage-state.spec.ts", "should round-trip through the file")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRoundTripThroughTheFile() + { + var page1 = await Context.NewPageAsync(); + await page1.RouteAsync("**/*", (route) => + { + route.FulfillAsync(body: ""); + }); + + await page1.GoToAsync("https://www.example.com"); + await page1.EvaluateAsync(@"() => + { + localStorage['name1'] = 'value1'; + document.cookie = 'username=John Doe'; + }"); + using var tempDir = new TempDirectory(); + string path = Path.Combine(tempDir.Path, "storage-state.json"); + string storage = await Context.StorageStateAsync(path); + Assert.That(File.ReadAllText(path), Is.EqualTo(storage)); + + await using var context = await Browser.NewContextAsync(storageStatePath: path); + var page2 = await context.NewPageAsync(); + await page1.RouteAsync("**/*", (route) => + { + route.FulfillAsync(body: ""); + }); + + await page1.GoToAsync("https://www.example.com"); + Assert.That(await page1.EvaluateAsync("localStorage['name1']"), Is.EqualTo("value1")); + Assert.That(await page1.EvaluateAsync("document.cookie"), Is.EqualTo("username=John Doe")); + } + } +} diff --git a/src/Playwright.Tests/BrowserContextTimezoneIdTests.cs b/src/PlaywrightSharp.Tests/BrowserContextTimezoneIdTests.cs similarity index 61% rename from src/Playwright.Tests/BrowserContextTimezoneIdTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextTimezoneIdTests.cs index f05231a428..96900d0714 100644 --- a/src/Playwright.Tests/BrowserContextTimezoneIdTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextTimezoneIdTests.cs @@ -1,94 +1,79 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextTimezoneIdTests : PlaywrightSharpBrowserBaseTest - { - /// - public BrowserContextTimezoneIdTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-timezone-id.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await using var browser = await Playwright[TestConstants.Product].LaunchDefaultAsync(); - - const string func = "() => new Date(1479579154987).toString()"; - await using (var context = await browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "America/Jamaica" })) - { - var page = await context.NewPageAsync(); - string result = await page.EvaluateAsync(func); - Assert.Equal( - "Sat Nov 19 2016 13:12:34 GMT-0500 (Eastern Standard Time)", - result); - } - - await using (var context = await browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "Pacific/Honolulu" })) - { - var page = await context.NewPageAsync(); - Assert.Equal( - "Sat Nov 19 2016 08:12:34 GMT-1000 (Hawaii-Aleutian Standard Time)", - await page.EvaluateAsync(func)); - } - - await using (var context = await browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "America/Buenos_Aires" })) - { - var page = await context.NewPageAsync(); - Assert.Equal( - "Sat Nov 19 2016 15:12:34 GMT-0300 (Argentina Standard Time)", - await page.EvaluateAsync(func)); - } - - await using (var context = await browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "Europe/Berlin" })) - { - var page = await context.NewPageAsync(); - Assert.Equal( - "Sat Nov 19 2016 19:12:34 GMT+0100 (Central European Standard Time)", - await page.EvaluateAsync(func)); - } - } - - [PlaywrightTest("browsercontext-timezone-id.spec.ts", "should throw for invalid timezone IDs")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowForInvalidTimezoneId() - { - await using (var context = await Browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "Foo/Bar" })) - { - var exception = await Assert.ThrowsAnyAsync(() => context.NewPageAsync()); - Assert.Contains("Invalid timezone ID: Foo/Bar", exception.Message); - } - - await using (var context = await Browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "Baz/Qux" })) - { - var exception = await Assert.ThrowsAnyAsync(() => context.NewPageAsync()); - Assert.Contains("Invalid timezone ID: Baz/Qux", exception.Message); - } - } - - [PlaywrightTest("browsercontext-timezone-id.spec.ts", "should work for multiple pages sharing same process")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForMultiplePagesSharingSameProcess() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "Europe/Moscow" }); - - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - - await TaskUtils.WhenAll( - page.WaitForEventAsync(PageEvent.Popup), - page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); - - await TaskUtils.WhenAll( - page.WaitForEventAsync(PageEvent.Popup), - page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextTimezoneIdTests : PlaywrightSharpBrowserBaseTest + { + [PlaywrightTest("browsercontext-timezone-id.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await using var browser = await Playwright[TestConstants.Product].LaunchDefaultAsync(); + + const string func = "() => new Date(1479579154987).toString()"; + await using (var context = await browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "America/Jamaica" })) + { + var page = await context.NewPageAsync(); + string result = await page.EvaluateAsync(func); + Assert.That(result, Is.EqualTo("Sat Nov 19 2016 13:12:34 GMT-0500 (Eastern Standard Time)")); + } + + await using (var context = await browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "Pacific/Honolulu" })) + { + var page = await context.NewPageAsync(); + Assert.That(await page.EvaluateAsync(func), Is.EqualTo("Sat Nov 19 2016 08:12:34 GMT-1000 (Hawaii-Aleutian Standard Time)")); + } + + await using (var context = await browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "America/Buenos_Aires" })) + { + var page = await context.NewPageAsync(); + Assert.That(await page.EvaluateAsync(func), Is.EqualTo("Sat Nov 19 2016 15:12:34 GMT-0300 (Argentina Standard Time)")); + } + + await using (var context = await browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "Europe/Berlin" })) + { + var page = await context.NewPageAsync(); + Assert.That(await page.EvaluateAsync(func), Is.EqualTo("Sat Nov 19 2016 19:12:34 GMT+0100 (Central European Standard Time)")); + } + } + + [PlaywrightTest("browsercontext-timezone-id.spec.ts", "should throw for invalid timezone IDs")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowForInvalidTimezoneId() + { + await using (var context = await Browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "Foo/Bar" })) + { + var exception = Assert.CatchAsync(() => context.NewPageAsync()); + Assert.That(exception.Message, Does.Contain("Invalid timezone ID: Foo/Bar")); + } + + await using (var context = await Browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "Baz/Qux" })) + { + var exception = Assert.CatchAsync(() => context.NewPageAsync()); + Assert.That(exception.Message, Does.Contain("Invalid timezone ID: Baz/Qux")); + } + } + + [PlaywrightTest("browsercontext-timezone-id.spec.ts", "should work for multiple pages sharing same process")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForMultiplePagesSharingSameProcess() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions { TimezoneId = "Europe/Moscow" }); + + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + + await TaskUtils.WhenAll( + page.WaitForEventAsync(PageEvent.Popup), + page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); + + await TaskUtils.WhenAll( + page.WaitForEventAsync(PageEvent.Popup), + page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); + } + } +} diff --git a/src/Playwright.Tests/BrowserContextUserAgentTests.cs b/src/PlaywrightSharp.Tests/BrowserContextUserAgentTests.cs similarity index 72% rename from src/Playwright.Tests/BrowserContextUserAgentTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextUserAgentTests.cs index 83f2e1fe39..fdb9cfc91d 100644 --- a/src/Playwright.Tests/BrowserContextUserAgentTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextUserAgentTests.cs @@ -1,100 +1,93 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextUserAgentTests : PlaywrightSharpBrowserBaseTest - { - /// - public BrowserContextUserAgentTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-user-agent.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await using (var context = await Browser.NewContextAsync()) - { - var page = await context.NewPageAsync(); - Assert.Contains("Mozilla", await page.EvaluateAsync("() => navigator.userAgent")); - } - - await using (var context = await Browser.NewContextAsync(new BrowserContextOptions { UserAgent = "foobar" })) - { - var page = await context.NewPageAsync(); - - var (userAgent, _) = await TaskUtils.WhenAll( - Server.WaitForRequest("/empty.html", request => request.Headers["User-Agent"].ToString()), - page.GoToAsync(TestConstants.EmptyPage) - ); - Assert.Equal("foobar", userAgent); - } - } - - [PlaywrightTest("browsercontext-user-agent.spec.ts", "should work for subframes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForSubframes() - { - await using (var context = await Browser.NewContextAsync()) - { - var page = await context.NewPageAsync(); - Assert.Contains("Mozilla", await page.EvaluateAsync("navigator.userAgent")); - } - - await using (var context = await Browser.NewContextAsync(new BrowserContextOptions { UserAgent = "foobar" })) - { - var page = await context.NewPageAsync(); - - var (userAgent, _) = await TaskUtils.WhenAll( - Server.WaitForRequest("/empty.html", (request) => request.Headers["user-agent"]), - FrameUtils.AttachFrameAsync(page, "frame1", TestConstants.EmptyPage)); - - Assert.Equal("foobar", userAgent); - } - } - - [PlaywrightTest("browsercontext-user-agent.spec.ts", "should emulate device user-agent")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEmulateDeviceUserAgent() - { - await using (var context = await Browser.NewContextAsync()) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); - Assert.DoesNotContain("iPhone", await page.EvaluateAsync("navigator.userAgent")); - } - - await using (var context = await Browser.NewContextAsync(new BrowserContextOptions { UserAgent = "iPhone" })) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); - Assert.Contains("iPhone", await page.EvaluateAsync("navigator.userAgent")); - } - } - - [PlaywrightTest("browsercontext-user-agent.spec.ts", "should make a copy of default options")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldMakeACopyOfDefaultOptions() - { - var options = new BrowserContextOptions - { - UserAgent = "foobar" - }; - - await using var context = await Browser.NewContextAsync(options); - options.UserAgent = "wrong"; - var page = await context.NewPageAsync(); - - var (userAgent, _) = await TaskUtils.WhenAll( - Server.WaitForRequest("/empty.html", request => request.Headers["User-Agent"].ToString()), - page.GoToAsync(TestConstants.EmptyPage) - ); - Assert.Equal("foobar", userAgent); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextUserAgentTests : PlaywrightSharpBrowserBaseTest + { + [PlaywrightTest("browsercontext-user-agent.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await using (var context = await Browser.NewContextAsync()) + { + var page = await context.NewPageAsync(); + Assert.That(await page.EvaluateAsync("() => navigator.userAgent"), Does.Contain("Mozilla")); + } + + await using (var context = await Browser.NewContextAsync(new BrowserContextOptions { UserAgent = "foobar" })) + { + var page = await context.NewPageAsync(); + + var (userAgent, _) = await TaskUtils.WhenAll( + Server.WaitForRequest("/empty.html", request => request.Headers["User-Agent"].ToString()), + page.GoToAsync(TestConstants.EmptyPage) + ); + Assert.That(userAgent, Is.EqualTo("foobar")); + } + } + + [PlaywrightTest("browsercontext-user-agent.spec.ts", "should work for subframes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForSubframes() + { + await using (var context = await Browser.NewContextAsync()) + { + var page = await context.NewPageAsync(); + Assert.That(await page.EvaluateAsync("navigator.userAgent"), Does.Contain("Mozilla")); + } + + await using (var context = await Browser.NewContextAsync(new BrowserContextOptions { UserAgent = "foobar" })) + { + var page = await context.NewPageAsync(); + + var (userAgent, _) = await TaskUtils.WhenAll( + Server.WaitForRequest("/empty.html", (request) => request.Headers["user-agent"]), + FrameUtils.AttachFrameAsync(page, "frame1", TestConstants.EmptyPage)); + + Assert.That(userAgent, Is.EqualTo("foobar")); + } + } + + [PlaywrightTest("browsercontext-user-agent.spec.ts", "should emulate device user-agent")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEmulateDeviceUserAgent() + { + await using (var context = await Browser.NewContextAsync()) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); + Assert.That(await page.EvaluateAsync("navigator.userAgent"), Does.Not.Contain("iPhone")); + } + + await using (var context = await Browser.NewContextAsync(new BrowserContextOptions { UserAgent = "iPhone" })) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); + Assert.That(await page.EvaluateAsync("navigator.userAgent"), Does.Contain("iPhone")); + } + } + + [PlaywrightTest("browsercontext-user-agent.spec.ts", "should make a copy of default options")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldMakeACopyOfDefaultOptions() + { + var options = new BrowserContextOptions + { + UserAgent = "foobar" + }; + + await using var context = await Browser.NewContextAsync(options); + options.UserAgent = "wrong"; + var page = await context.NewPageAsync(); + + var (userAgent, _) = await TaskUtils.WhenAll( + Server.WaitForRequest("/empty.html", request => request.Headers["User-Agent"].ToString()), + page.GoToAsync(TestConstants.EmptyPage) + ); + Assert.That(userAgent, Is.EqualTo("foobar")); + } + } +} diff --git a/src/Playwright.Tests/BrowserContextViewportMobileTests.cs b/src/PlaywrightSharp.Tests/BrowserContextViewportMobileTests.cs similarity index 80% rename from src/Playwright.Tests/BrowserContextViewportMobileTests.cs rename to src/PlaywrightSharp.Tests/BrowserContextViewportMobileTests.cs index e84521975c..e2fde4b602 100644 --- a/src/Playwright.Tests/BrowserContextViewportMobileTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserContextViewportMobileTests.cs @@ -1,193 +1,185 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserContextViewportMobileTests : PlaywrightSharpBrowserBaseTest - { - private readonly BrowserContextOptions _iPhone = TestConstants.iPhone6; - private readonly BrowserContextOptions _iPhoneLandscape = TestConstants.iPhone6Landscape; - - /// - public BrowserContextViewportMobileTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should support mobile emulation")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldSupportMobileEmulation() - { - await using var context = await Browser.NewContextAsync(_iPhone); - var page = await context.NewPageAsync(); - - await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); - Assert.Equal(375, await page.EvaluateAsync("window.innerWidth")); - await page.SetViewportSizeAsync(400, 300); - Assert.Equal(400, await page.EvaluateAsync("window.innerWidth")); - } - - [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should support touch emulation")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldSupportTouchEmulation() - { - const string dispatchTouch = @" - function dispatchTouch() { - let fulfill; - const promise = new Promise(x => fulfill = x); - window.ontouchstart = function(e) { - fulfill('Received touch'); - }; - window.dispatchEvent(new Event('touchstart')); - - fulfill('Did not receive touch'); - - return promise; - }"; - - await using var context = await Browser.NewContextAsync(_iPhone); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); - Assert.True(await page.EvaluateAsync("'ontouchstart' in window")); - Assert.Equal("Received touch", await page.EvaluateAsync(dispatchTouch)); - } - - [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should be detectable by Modernizr")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldBeDetectableByModernizr() - { - await using var context = await Browser.NewContextAsync(_iPhone); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/detect-touch.html"); - Assert.Equal("YES", await page.EvaluateAsync("document.body.textContent.trim()")); - } - - [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should detect touch when applying viewport with touches")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldDetectTouchWhenApplyingViewportWithTouches() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 800, - Height = 600, - }, - HasTouch = true, - }); - - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - await page.AddScriptTagAsync(url: TestConstants.ServerUrl + "/modernizr.js"); - Assert.True(await page.EvaluateAsync("() => Modernizr.touchevents")); - } - - [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should support landscape emulation")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldSupportLandscapeEmulation() - { - await using var context1 = await Browser.NewContextAsync(_iPhone); - var page1 = await context1.NewPageAsync(); - await page1.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); - Assert.False(await page1.EvaluateAsync("() => matchMedia('(orientation: landscape)').matches")); - - await using var context2 = await Browser.NewContextAsync(_iPhoneLandscape); - var page2 = await context2.NewPageAsync(); - await page2.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); - Assert.True(await page2.EvaluateAsync("() => matchMedia('(orientation: landscape)').matches")); - } - - [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should support window.orientation emulation")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldSupportWindowOrientationEmulation() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 300, - Height = 400, - }, - IsMobile = true, - }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); - Assert.Equal(0, await page.EvaluateAsync("() => window.orientation")); - - await page.SetViewportSizeAsync(400, 300); - Assert.Equal(90, await page.EvaluateAsync("() => window.orientation")); - } - - [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should fire orientationchange event")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldFireOrientationChangeEvent() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 300, - Height = 400, - }, - IsMobile = true, - }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); - await page.EvaluateAsync(@"() => { - window.counter = 0; - window.addEventListener('orientationchange', () => console.log(++window.counter)); - }"); - - var event1Task = page.WaitForEventAsync(PageEvent.Console); - await page.SetViewportSizeAsync(400, 300); - var event1 = await event1Task; - Assert.Equal("1", event1.Text); - - var event2Task = page.WaitForEventAsync(PageEvent.Console); - await page.SetViewportSizeAsync(300, 400); - var event2 = await event2Task; - Assert.Equal("2", event2.Text); - } - - [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "default mobile viewports to 980 width")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task DefaultMobileViewportsTo980Width() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 320, - Height = 480, - }, - IsMobile = true, - }); - var page = await context.NewPageAsync(); - - await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(980, await page.EvaluateAsync("() => window.innerWidth")); - } - - [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "respect meta viewport tag")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task RespectMetaViewportTag() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 320, - Height = 480, - }, - IsMobile = true, - }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); - Assert.Equal(320, await page.EvaluateAsync("() => window.innerWidth")); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextViewportMobileTests : PlaywrightSharpBrowserBaseTest + { + private readonly BrowserContextOptions _iPhone = TestConstants.iPhone6; + private readonly BrowserContextOptions _iPhoneLandscape = TestConstants.iPhone6Landscape; + [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should support mobile emulation")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldSupportMobileEmulation() + { + await using var context = await Browser.NewContextAsync(_iPhone); + var page = await context.NewPageAsync(); + + await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); + Assert.That(await page.EvaluateAsync("window.innerWidth"), Is.EqualTo(375)); + await page.SetViewportSizeAsync(400, 300); + Assert.That(await page.EvaluateAsync("window.innerWidth"), Is.EqualTo(400)); + } + + [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should support touch emulation")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldSupportTouchEmulation() + { + const string dispatchTouch = @" + function dispatchTouch() { + let fulfill; + const promise = new Promise(x => fulfill = x); + window.ontouchstart = function(e) { + fulfill('Received touch'); + }; + window.dispatchEvent(new Event('touchstart')); + + fulfill('Did not receive touch'); + + return promise; + }"; + + await using var context = await Browser.NewContextAsync(_iPhone); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); + Assert.That(await page.EvaluateAsync("'ontouchstart' in window"), Is.True); + Assert.That(await page.EvaluateAsync(dispatchTouch), Is.EqualTo("Received touch")); + } + + [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should be detectable by Modernizr")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldBeDetectableByModernizr() + { + await using var context = await Browser.NewContextAsync(_iPhone); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/detect-touch.html"); + Assert.That(await page.EvaluateAsync("document.body.textContent.trim()"), Is.EqualTo("YES")); + } + + [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should detect touch when applying viewport with touches")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldDetectTouchWhenApplyingViewportWithTouches() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 800, + Height = 600, + }, + HasTouch = true, + }); + + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + await page.AddScriptTagAsync(url: TestConstants.ServerUrl + "/modernizr.js"); + Assert.That(await page.EvaluateAsync("() => Modernizr.touchevents"), Is.True); + } + + [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should support landscape emulation")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldSupportLandscapeEmulation() + { + await using var context1 = await Browser.NewContextAsync(_iPhone); + var page1 = await context1.NewPageAsync(); + await page1.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); + Assert.That(await page1.EvaluateAsync("() => matchMedia('(orientation: landscape)').matches"), Is.False); + + await using var context2 = await Browser.NewContextAsync(_iPhoneLandscape); + var page2 = await context2.NewPageAsync(); + await page2.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); + Assert.That(await page2.EvaluateAsync("() => matchMedia('(orientation: landscape)').matches"), Is.True); + } + + [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should support window.orientation emulation")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldSupportWindowOrientationEmulation() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 300, + Height = 400, + }, + IsMobile = true, + }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); + Assert.That(await page.EvaluateAsync("() => window.orientation"), Is.EqualTo(0)); + + await page.SetViewportSizeAsync(400, 300); + Assert.That(await page.EvaluateAsync("() => window.orientation"), Is.EqualTo(90)); + } + + [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "should fire orientationchange event")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldFireOrientationChangeEvent() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 300, + Height = 400, + }, + IsMobile = true, + }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); + await page.EvaluateAsync(@"() => { + window.counter = 0; + window.addEventListener('orientationchange', () => console.log(++window.counter)); + }"); + + var event1Task = page.WaitForEventAsync(PageEvent.Console); + await page.SetViewportSizeAsync(400, 300); + var event1 = await event1Task; + Assert.That(event1.Text, Is.EqualTo("1")); + + var event2Task = page.WaitForEventAsync(PageEvent.Console); + await page.SetViewportSizeAsync(300, 400); + var event2 = await event2Task; + Assert.That(event2.Text, Is.EqualTo("2")); + } + + [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "default mobile viewports to 980 width")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task DefaultMobileViewportsTo980Width() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 320, + Height = 480, + }, + IsMobile = true, + }); + var page = await context.NewPageAsync(); + + await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await page.EvaluateAsync("() => window.innerWidth"), Is.EqualTo(980)); + } + + [PlaywrightTest("browsercontext-viewport-mobile.spec.ts", "respect meta viewport tag")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task RespectMetaViewportTag() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 320, + Height = 480, + }, + IsMobile = true, + }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); + Assert.That(await page.EvaluateAsync("() => window.innerWidth"), Is.EqualTo(320)); + } + } +} diff --git a/src/PlaywrightSharp.Tests/BrowserContextViewportTests.cs b/src/PlaywrightSharp.Tests/BrowserContextViewportTests.cs new file mode 100644 index 0000000000..8cc9275ff7 --- /dev/null +++ b/src/PlaywrightSharp.Tests/BrowserContextViewportTests.cs @@ -0,0 +1,88 @@ +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserContextViewportTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("browsercontext-viewport.spec.ts", "should get the proper default viewport size")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public Task ShouldGetTheProperDefaultViewPortSize() + => TestUtils.VerifyViewportAsync(Page, 1280, 720); + + [PlaywrightTest("browsercontext-viewport.spec.ts", "should set the proper viewport size")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSetTheProperViewportSize() + { + await TestUtils.VerifyViewportAsync(Page, 1280, 720); + await Page.SetViewportSizeAsync(123, 456); + await TestUtils.VerifyViewportAsync(Page, 123, 456); + } + + [PlaywrightTest("browsercontext-viewport.spec.ts", "should emulate device width")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEmulateDeviceWidth() + { + await TestUtils.VerifyViewportAsync(Page, 1280, 720); + await Page.SetViewportSizeAsync(200, 200); + Assert.That(await Page.EvaluateAsync("window.innerWidth"), Is.EqualTo(200)); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(min-device-width: 100px)').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(min-device-width: 300px)').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(max-device-width: 100px)').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(max-device-width: 300px)').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(device-width: 500px)').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(device-width: 200px)').matches"), Is.True); + await Page.SetViewportSizeAsync(500, 500); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(min-device-width: 400px)').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(min-device-width: 600px)').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(max-device-width: 400px)').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(max-device-width: 600px)').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(device-width: 200px)').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(device-width: 500px)').matches"), Is.True); + } + + [PlaywrightTest("browsercontext-viewport.spec.ts", "should emulate device height")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEmulateDeviceHeight() + { + await TestUtils.VerifyViewportAsync(Page, 1280, 720); + await Page.SetViewportSizeAsync(200, 200); + Assert.That(await Page.EvaluateAsync("window.innerWidth"), Is.EqualTo(200)); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(min-device-height: 100px)').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(min-device-height: 300px)').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(max-device-height: 100px)').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(max-device-height: 300px)').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(device-height: 500px)').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(device-height: 200px)').matches"), Is.True); + await Page.SetViewportSizeAsync(500, 500); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(min-device-height: 400px)').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(min-device-height: 600px)').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(max-device-height: 400px)').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(max-device-height: 600px)').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(device-height: 200px)').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(device-height: 500px)').matches"), Is.True); + } + + [PlaywrightTest("browsercontext-viewport.spec.ts", "should not have touch by default")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotHaveTouchByDefault() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); + Assert.That(await Page.EvaluateAsync("'ontouchstart' in window"), Is.False); + await Page.GoToAsync(TestConstants.ServerUrl + "/detect-touch.html"); + Assert.That(await Page.EvaluateAsync("document.body.textContent.trim()"), Is.EqualTo("NO")); + } + + [PlaywrightTest("browsercontext-viewport.spec.ts", "should support touch with null viewport")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportTouchWithNullViewport() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions { Viewport = null, HasTouch = true }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); + Assert.That(await page.EvaluateAsync("'ontouchstart' in window"), Is.True); + } + } +} diff --git a/src/Playwright.Tests/BrowserTests.cs b/src/PlaywrightSharp.Tests/BrowserTests.cs similarity index 54% rename from src/Playwright.Tests/BrowserTests.cs rename to src/PlaywrightSharp.Tests/BrowserTests.cs index b00b5182a7..648fee57d2 100644 --- a/src/Playwright.Tests/BrowserTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserTests.cs @@ -1,62 +1,55 @@ -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///browser.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserTests : PlaywrightSharpBrowserBaseTest - { - /// - public BrowserTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browser.spec.ts", "should create new page")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCreateNewPage() - { - var browser = await Playwright[TestConstants.Product].LaunchDefaultAsync(); - var page1 = await browser.NewPageAsync(); - Assert.Single(browser.Contexts); - - var page2 = await browser.NewPageAsync(); - Assert.Equal(2, browser.Contexts.Count); - - await page1.CloseAsync(); - Assert.Single(browser.Contexts); - - await page2.CloseAsync(); - } - - [PlaywrightTest("browser.spec.ts", "should throw upon second create new page")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowUponSecondCreateNewPage() - { - var page = await Browser.NewPageAsync(); - var ex = await Assert.ThrowsAsync(() => page.Context.NewPageAsync()); - await page.CloseAsync(); - Assert.Contains("Please use Browser.NewContextAsync()", ex.Message); - } - - [PlaywrightTest("browser.spec.ts", "version should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public void VersionShouldWork() - { - string version = Browser.Version; - - if (TestConstants.IsChromium) - { - Assert.Matches(new Regex("\\d+\\.\\d+\\.\\d+\\.\\d+"), version); - } - else - { - Assert.Matches(new Regex("\\d+\\.\\d+"), version); - } - } - } -} +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///browser.spec.ts + public class BrowserTests : PlaywrightSharpBrowserBaseTest + { + [PlaywrightTest("browser.spec.ts", "should create new page")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCreateNewPage() + { + var browser = await Playwright[TestConstants.Product].LaunchDefaultAsync(); + var page1 = await browser.NewPageAsync(); + Assert.That(browser.Contexts, Has.Exactly(1).Items); + + var page2 = await browser.NewPageAsync(); + Assert.That(browser.Contexts.Count, Is.EqualTo(2)); + + await page1.CloseAsync(); + Assert.That(browser.Contexts, Has.Exactly(1).Items); + + await page2.CloseAsync(); + } + + [PlaywrightTest("browser.spec.ts", "should throw upon second create new page")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowUponSecondCreateNewPage() + { + var page = await Browser.NewPageAsync(); + var ex = Assert.ThrowsAsync(() => page.Context.NewPageAsync()); + await page.CloseAsync(); + Assert.That(ex.Message, Does.Contain("Please use Browser.NewContextAsync()")); + } + + [PlaywrightTest("browser.spec.ts", "version should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public void VersionShouldWork() + { + string version = Browser.Version; + + if (TestConstants.IsChromium) + { + Assert.That(version, Does.Match(new Regex("\\d+\\.\\d+\\.\\d+\\.\\d+"))); + } + else + { + Assert.That(version, Does.Match(new Regex("\\d+\\.\\d+"))); + } + } + } +} diff --git a/src/Playwright.Tests/BrowserTypeBasicTests.cs b/src/PlaywrightSharp.Tests/BrowserTypeBasicTests.cs similarity index 52% rename from src/Playwright.Tests/BrowserTypeBasicTests.cs rename to src/PlaywrightSharp.Tests/BrowserTypeBasicTests.cs index 0ba98c46dd..ddf9a637ec 100644 --- a/src/Playwright.Tests/BrowserTypeBasicTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserTypeBasicTests.cs @@ -1,34 +1,26 @@ -using System.IO; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserTypeBasicTests : PlaywrightSharpBaseTest - { - /// - public BrowserTypeBasicTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsertype-basic.spec.ts", "browserType.executablePath should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public void BrowserTypeExecutablePathShouldWork() => Assert.True(File.Exists(BrowserType.ExecutablePath)); - - [PlaywrightTest("browsertype-basic.spec.ts", "browserType.name should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public void BrowserTypeNameShouldWork() - => Assert.Equal( - TestConstants.Product switch - { - TestConstants.WebkitProduct => "webkit", - TestConstants.FirefoxProduct => "firefox", - TestConstants.ChromiumProduct => "chromium", - _ => null - }, - BrowserType.Name); - } -} +using System.IO; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class BrowserTypeBasicTests : PlaywrightSharpBaseTest + { + [PlaywrightTest("browsertype-basic.spec.ts", "browserType.executablePath should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public void BrowserTypeExecutablePathShouldWork() => Assert.That(File.Exists(BrowserType.ExecutablePath), Is.True); + + [PlaywrightTest("browsertype-basic.spec.ts", "browserType.name should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public void BrowserTypeNameShouldWork() + => Assert.That(BrowserType.Name, Is.EqualTo( + TestConstants.Product switch + { + TestConstants.WebkitProduct => "webkit", + TestConstants.FirefoxProduct => "firefox", + TestConstants.ChromiumProduct => "chromium", + _ => null + })); + } +} diff --git a/src/Playwright.Tests/BrowserTypeConnectTests.cs b/src/PlaywrightSharp.Tests/BrowserTypeConnectTests.cs similarity index 80% rename from src/Playwright.Tests/BrowserTypeConnectTests.cs rename to src/PlaywrightSharp.Tests/BrowserTypeConnectTests.cs index 0dc30a1e88..af3479abe8 100644 --- a/src/Playwright.Tests/BrowserTypeConnectTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserTypeConnectTests.cs @@ -1,100 +1,93 @@ -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///browsertype-connect.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserTypeConnectTests : PlaywrightSharpBaseTest - { - /// - public BrowserTypeConnectTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsertype-connect.spec.ts", "should be able to reconnect to a browser")] - [Fact(Skip = "SKIP WIRE")] - public void ShouldBeAbleToReconnectToABrowser() - { - /* - await using var browserServer = await BrowserType.LaunchServerAsync(TestConstants.GetDefaultBrowserOptions()); - await using var browser = await BrowserType.ConnectAsync(browserServer.WSEndpoint); - var context = await browser.NewContextAsync(); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - - await browser.CloseAsync(); - - await using var remote = await BrowserType.ConnectAsync(browserServer.WSEndpoint); - - context = await remote.NewContextAsync(); - page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - await remote.CloseAsync(); - await browserServer.CloseAsync(); - */ - } - - [PlaywrightTest("browsertype-connect.spec.ts", "should be able to connect two browsers at the same time")] - [Fact(Skip = "SKIP WIRE")] - public void ShouldBeAbleToConnectTwoBrowsersAtTheSameTime() - { - } - - [PlaywrightTest("browsertype-connect.spec.ts", "disconnected event should be emitted when browser is closed or server is closed")] - [Fact(Skip = "SKIP WIRE")] - public void DisconnectedEventShouldBeEmittedWhenBrowserIsClosedOrServerIsClosed() - { - } - - [PlaywrightTest("browsertype-connect.spec.ts", "should handle exceptions during connect")] - [Fact(Skip = "SKIP WIRE")] - public void ShouldHandleExceptionsDuringConnect() - { - } - - [PlaywrightTest("browsertype-connect.spec.ts", "should set the browser connected state")] - [Fact(Skip = "SKIP WIRE")] - public void ShouldSetTheBrowserConnectedState() - { - } - - [PlaywrightTest("browsertype-connect.spec.ts", "should throw when used after isConnected returns false")] - [Fact(Skip = "SKIP WIRE")] - public void ShouldThrowWhenUsedAfterIsConnectedReturnsFalse() - { - } - - [PlaywrightTest("browsertype-connect.spec.ts", "should reject navigation when browser closes")] - [Fact(Skip = "SKIP WIRE")] - public void ShouldRejectNavigationWhenBrowserCloses() - { - } - - [PlaywrightTest("browsertype-connect.spec.ts", "should reject waitForSelector when browser closes")] - [Fact(Skip = "SKIP WIRE")] - public void ShouldRejectWaitForSelectorWhenBrowserCloses() - { - } - - [PlaywrightTest("browsertype-connect.spec.ts", "should emit close events on pages and contexts")] - [Fact(Skip = "SKIP WIRE")] - public void ShouldEmitCloseEventsOnPagesAndContexts() - { - } - - [PlaywrightTest("browsertype-connect.spec.ts", "should terminate network waiters")] - [Fact(Skip = "SKIP WIRE")] - public void ShouldTerminateNetworkWaiters() - { - } - - [PlaywrightTest("browsertype-connect.spec.ts", "should respect selectors")] - [Fact(Skip = "SKIP WIRE")] - public void ShouldRespectSelectors() - { - } - } -} +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///browsertype-connect.spec.ts + public class BrowserTypeConnectTests : PlaywrightSharpBaseTest + { + [PlaywrightTest("browsertype-connect.spec.ts", "should be able to reconnect to a browser")] + [Test, Ignore("SKIP WIRE")] + public void ShouldBeAbleToReconnectToABrowser() + { + /* + await using var browserServer = await BrowserType.LaunchServerAsync(TestConstants.GetDefaultBrowserOptions()); + await using var browser = await BrowserType.ConnectAsync(browserServer.WSEndpoint); + var context = await browser.NewContextAsync(); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + + await browser.CloseAsync(); + + await using var remote = await BrowserType.ConnectAsync(browserServer.WSEndpoint); + + context = await remote.NewContextAsync(); + page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + await remote.CloseAsync(); + await browserServer.CloseAsync(); + */ + } + + [PlaywrightTest("browsertype-connect.spec.ts", "should be able to connect two browsers at the same time")] + [Test, Ignore("SKIP WIRE")] + public void ShouldBeAbleToConnectTwoBrowsersAtTheSameTime() + { + } + + [PlaywrightTest("browsertype-connect.spec.ts", "disconnected event should be emitted when browser is closed or server is closed")] + [Test, Ignore("SKIP WIRE")] + public void DisconnectedEventShouldBeEmittedWhenBrowserIsClosedOrServerIsClosed() + { + } + + [PlaywrightTest("browsertype-connect.spec.ts", "should handle exceptions during connect")] + [Test, Ignore("SKIP WIRE")] + public void ShouldHandleExceptionsDuringConnect() + { + } + + [PlaywrightTest("browsertype-connect.spec.ts", "should set the browser connected state")] + [Test, Ignore("SKIP WIRE")] + public void ShouldSetTheBrowserConnectedState() + { + } + + [PlaywrightTest("browsertype-connect.spec.ts", "should throw when used after isConnected returns false")] + [Test, Ignore("SKIP WIRE")] + public void ShouldThrowWhenUsedAfterIsConnectedReturnsFalse() + { + } + + [PlaywrightTest("browsertype-connect.spec.ts", "should reject navigation when browser closes")] + [Test, Ignore("SKIP WIRE")] + public void ShouldRejectNavigationWhenBrowserCloses() + { + } + + [PlaywrightTest("browsertype-connect.spec.ts", "should reject waitForSelector when browser closes")] + [Test, Ignore("SKIP WIRE")] + public void ShouldRejectWaitForSelectorWhenBrowserCloses() + { + } + + [PlaywrightTest("browsertype-connect.spec.ts", "should emit close events on pages and contexts")] + [Test, Ignore("SKIP WIRE")] + public void ShouldEmitCloseEventsOnPagesAndContexts() + { + } + + [PlaywrightTest("browsertype-connect.spec.ts", "should terminate network waiters")] + [Test, Ignore("SKIP WIRE")] + public void ShouldTerminateNetworkWaiters() + { + } + + [PlaywrightTest("browsertype-connect.spec.ts", "should respect selectors")] + [Test, Ignore("SKIP WIRE")] + public void ShouldRespectSelectors() + { + } + } +} diff --git a/src/Playwright.Tests/BrowserTypeLaunchTests.cs b/src/PlaywrightSharp.Tests/BrowserTypeLaunchTests.cs similarity index 65% rename from src/Playwright.Tests/BrowserTypeLaunchTests.cs rename to src/PlaywrightSharp.Tests/BrowserTypeLaunchTests.cs index cf9a0f30f7..d089c3341b 100644 --- a/src/Playwright.Tests/BrowserTypeLaunchTests.cs +++ b/src/PlaywrightSharp.Tests/BrowserTypeLaunchTests.cs @@ -1,166 +1,159 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Microsoft.Playwright.Transport; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///browsertype-launch.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class BrowserTypeLaunchTests : PlaywrightSharpBaseTest - { - /// - public BrowserTypeLaunchTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("browsertype-launch.spec.ts", "should reject all promises when browser is closed")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRejectAllPromisesWhenBrowserIsClosed() - { - await using var browser = await BrowserType.LaunchDefaultAsync(); - var page = await (await browser.NewContextAsync()).NewPageAsync(); - var neverResolves = page.EvaluateHandleAsync("() => new Promise(r => {})"); - await browser.CloseAsync(); - var exception = await Assert.ThrowsAsync(() => neverResolves); - Assert.Contains("Protocol error", exception.Message); - - } - - [PlaywrightTest("browsertype-launch.spec.ts", "should throw if port option is passed")] - [Fact(Skip = "We don't need this test")] - public void ShouldThrowIfPortOptionIsPassed() - { - } - - [PlaywrightTest("browsertype-launch.spec.ts", "should throw if userDataDir option is passed")] - [Fact(Skip = "This isn't supported in our language port.")] - public void ShouldThrowIfUserDataDirOptionIsPassed() - { - } - - [PlaywrightTest("browsertype-launch.spec.ts", "should throw if port option is passed for persistent context")] - [Fact(Skip = "We don't need this test")] - public void ShouldThrowIfPortOptionIsPassedForPersistenContext() - { - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should throw if page argument is passed")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldThrowIfPageArgumentIsPassed() - { - await Assert.ThrowsAnyAsync(() => BrowserType.LaunchDefaultAsync(args: new[] { TestConstants.EmptyPage })); - } - - [PlaywrightTest("browsertype-launch.spec.ts", "should reject if launched browser fails immediately")] - [Fact(Skip = "Skipped in playwright")] - public void ShouldRejectIfLaunchedBrowserFailsImmediately() - { - } - - /// - /// Should curante the message coming from Playwright - /// - /// - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCurateTheLaunchError() - { - // Set an invalid location - using var playwright = await Microsoft.Playwright.Playwright.CreateAsync(browsersPath: Path.Combine(typeof(Microsoft.Playwright.Playwright).Assembly.Location)); - var exception = await Assert.ThrowsAsync(() => playwright[TestConstants.Product].LaunchAsync()); - - Assert.Contains("Failed to launch", exception.Message); - Assert.Contains("Try re-installing the browsers running `playwright.cmd install` in windows or `./playwright.sh install` in MacOS or Linux.", exception.Message); - Assert.DoesNotContain("npm install playwright", exception.Message); - Environment.SetEnvironmentVariable(EnvironmentVariables.BrowsersPathEnvironmentVariable, null); - } - - [PlaywrightTest("browsertype-launch.spec.ts", "should reject if executable path is invalid")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRejectIfExecutablePathIsInvalid() - { - var exception = await Assert.ThrowsAsync(() => BrowserType.LaunchAsync(executablePath: "random-invalid-path")); - - Assert.Contains("Failed to launch", exception.Message); - } - - [PlaywrightTest("browsertype-launch.spec.ts", "should handle timeout")] - [Fact(Skip = "We ignore hook tests")] - public void ShouldHandleTimeout() - { - } - - [PlaywrightTest("browsertype-launch.spec.ts", "should report launch log")] - [Fact(Skip = "We ignore hook tests")] - public void ShouldReportLaunchLog() - { - } - - [PlaywrightTest("browsertype-launch.spec.ts", "should accept objects as options")] - [Fact(Skip = "We don't need to test this")] - public void ShouldAcceptObjectsAsOptions() - { - } - - [PlaywrightTest("browsertype-launch.spec.ts", "should fire close event for all contexts")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFireCloseEventForAllContexts() - { - await using var browser = await BrowserType.LaunchDefaultAsync(); - var context = await browser.NewContextAsync(); - var closeTask = new TaskCompletionSource(); - - context.Close += (_, _) => closeTask.TrySetResult(true); - - await TaskUtils.WhenAll(browser.CloseAsync(), closeTask.Task); - } - - [PlaywrightTest("browsertype-launch.spec.ts", "should be callable twice")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeCallableTwice() - { - await using var browser = await BrowserType.LaunchDefaultAsync(); - await TaskUtils.WhenAll(browser.CloseAsync(), browser.CloseAsync()); - await browser.CloseAsync(); - } - - /// - /// PuppeteerSharp test. It's not in upstream - /// - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithEnvironmentVariables() - { - var env = new Dictionary - { - ["Foo"] = "Var" - }; - - await using var browser = await BrowserType.LaunchAsync(env: env); - } - - /// - /// PuppeteerSharp test. It's not in upstream - /// - [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] - public async Task ShouldWorkWithIgnoreDefaultArgs() - { - string[] args = new[] - { - "--remote-debugging-pipe", - "--headless", - "--hide-scrollbars", - "--mute-audio", - "--blink-settings=primaryHoverType=2,availableHoverTypes=2,primaryPointerType=4,availablePointerTypes=4" - }; - - await using var browser = await BrowserType.LaunchAsync(ignoreAllDefaultArgs: true, args: args); - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; +using PlaywrightSharp.Transport; + +namespace PlaywrightSharp.Tests +{ + ///browsertype-launch.spec.ts + public class BrowserTypeLaunchTests : PlaywrightSharpBaseTest + { + [PlaywrightTest("browsertype-launch.spec.ts", "should reject all promises when browser is closed")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRejectAllPromisesWhenBrowserIsClosed() + { + await using var browser = await BrowserType.LaunchDefaultAsync(); + var page = await (await browser.NewContextAsync()).NewPageAsync(); + var neverResolves = page.EvaluateHandleAsync("() => new Promise(r => {})"); + await browser.CloseAsync(); + var exception = Assert.ThrowsAsync(() => neverResolves); + Assert.That(exception.Message, Does.Contain("Protocol error")); + + } + + [PlaywrightTest("browsertype-launch.spec.ts", "should throw if port option is passed")] + [Test, Ignore("We don't need this test")] + public void ShouldThrowIfPortOptionIsPassed() + { + } + + [PlaywrightTest("browsertype-launch.spec.ts", "should throw if userDataDir option is passed")] + [Test, Ignore("This isn't supported in our language port.")] + public void ShouldThrowIfUserDataDirOptionIsPassed() + { + } + + [PlaywrightTest("browsertype-launch.spec.ts", "should throw if port option is passed for persistent context")] + [Test, Ignore("We don't need this test")] + public void ShouldThrowIfPortOptionIsPassedForPersistenContext() + { + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should throw if page argument is passed")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldThrowIfPageArgumentIsPassed() + { + Assert.CatchAsync(() => BrowserType.LaunchDefaultAsync(args: new[] { TestConstants.EmptyPage })); + } + + [PlaywrightTest("browsertype-launch.spec.ts", "should reject if launched browser fails immediately")] + [Test, Ignore("Skipped in playwright")] + public void ShouldRejectIfLaunchedBrowserFailsImmediately() + { + } + + /// + /// Should curante the message coming from Playwright + /// + /// + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCurateTheLaunchError() + { + // Set an invalid location + using var playwright = await PlaywrightSharp.Playwright.CreateAsync(browsersPath: Path.Combine(typeof(PlaywrightSharp.Playwright).Assembly.Location)); + var exception = Assert.ThrowsAsync(() => playwright[TestConstants.Product].LaunchAsync()); + + Assert.That(exception.Message, Does.Contain("Failed to launch")); + Assert.That(exception.Message, Does.Contain("Try re-installing the browsers running `playwright.cmd install` in windows or `./playwright.sh install` in MacOS or Linux.")); + Assert.That(exception.Message, Does.Not.Contain("npm install playwright")); + Environment.SetEnvironmentVariable(EnvironmentVariables.BrowsersPathEnvironmentVariable, null); + } + + [PlaywrightTest("browsertype-launch.spec.ts", "should reject if executable path is invalid")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRejectIfExecutablePathIsInvalid() + { + var exception = Assert.ThrowsAsync(() => BrowserType.LaunchAsync(executablePath: "random-invalid-path")); + + Assert.That(exception.Message, Does.Contain("Failed to launch")); + } + + [PlaywrightTest("browsertype-launch.spec.ts", "should handle timeout")] + [Test, Ignore("We ignore hook tests")] + public void ShouldHandleTimeout() + { + } + + [PlaywrightTest("browsertype-launch.spec.ts", "should report launch log")] + [Test, Ignore("We ignore hook tests")] + public void ShouldReportLaunchLog() + { + } + + [PlaywrightTest("browsertype-launch.spec.ts", "should accept objects as options")] + [Test, Ignore("We don't need to test this")] + public void ShouldAcceptObjectsAsOptions() + { + } + + [PlaywrightTest("browsertype-launch.spec.ts", "should fire close event for all contexts")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFireCloseEventForAllContexts() + { + await using var browser = await BrowserType.LaunchDefaultAsync(); + var context = await browser.NewContextAsync(); + var closeTask = new TaskCompletionSource(); + + context.Close += (_, _) => closeTask.TrySetResult(true); + + await TaskUtils.WhenAll(browser.CloseAsync(), closeTask.Task); + } + + [PlaywrightTest("browsertype-launch.spec.ts", "should be callable twice")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeCallableTwice() + { + await using var browser = await BrowserType.LaunchDefaultAsync(); + await TaskUtils.WhenAll(browser.CloseAsync(), browser.CloseAsync()); + await browser.CloseAsync(); + } + + /// + /// PlaywrightSharp test. It's not in upstream + /// + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithEnvironmentVariables() + { + var env = new Dictionary + { + ["Foo"] = "Var" + }; + + await using var browser = await BrowserType.LaunchAsync(env: env); + } + + /// + /// PlaywrightSharp test. It's not in upstream + /// + [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] + public async Task ShouldWorkWithIgnoreDefaultArgs() + { + string[] args = new[] + { + "--remote-debugging-pipe", + "--headless", + "--hide-scrollbars", + "--mute-audio", + "--blink-settings=primaryHoverType=2,availableHoverTypes=2,primaryPointerType=4,availablePointerTypes=4" + }; + + await using var browser = await BrowserType.LaunchAsync(ignoreAllDefaultArgs: true, args: args); + } + } +} diff --git a/src/Playwright.Tests/CapabilitiesTests.cs b/src/PlaywrightSharp.Tests/CapabilitiesTests.cs similarity index 78% rename from src/Playwright.Tests/CapabilitiesTests.cs rename to src/PlaywrightSharp.Tests/CapabilitiesTests.cs index c3af56ec7e..c98deda736 100644 --- a/src/Playwright.Tests/CapabilitiesTests.cs +++ b/src/PlaywrightSharp.Tests/CapabilitiesTests.cs @@ -1,78 +1,71 @@ -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///capabilities.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class CapabilitiesTests : PlaywrightSharpPageBaseTest - { - /// - public CapabilitiesTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("capabilities.spec.ts", "Web Assembly should work")] - [SkipBrowserAndPlatformFact(skipWebkit: true, skipWindows: true)] - public async Task WebAssemblyShouldWork() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/wasm/table2.html"); - Assert.Equal("42, 83", await Page.EvaluateAsync("() => loadTable()")); - } - -#if NETCOREAPP - [PlaywrightTest("capabilities.spec.ts", "WebSocket should work")] - [SkipBrowserAndPlatformFact(skipWebkit: true, skipWindows: true)] - public async Task WebSocketShouldWork() - { - string value = await Page.EvaluateAsync( - $@"(port) => {{ - let cb; - const result = new Promise(f => cb = f); - const ws = new WebSocket('ws://localhost:' + port + '/ws'); - ws.addEventListener('message', data => {{ ws.close(); cb(data.data); console.log(data); console.log(data.data) }}); - ws.addEventListener('error', error => cb('Error')); - return result; - }}", - TestConstants.Port); - Assert.Equal("incoming", value); - } -#endif - - [PlaywrightTest("capabilities.spec.ts", "should respect CSP")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRespectCSP() - { - Server.SetRoute("/empty.html", context => - { - const string message = @" - - "; - - context.Response.Headers["Content-Length"] = message.Length.ToString(); - context.Response.Headers["Content-Security-Policy"] = "script-src 'unsafe-inline';"; - return context.Response.WriteAsync(message); - }); - - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal("SUCCESS", await Page.EvaluateAsync("() => window.testStatus")); - } - - [PlaywrightTest("capabilities.spec.ts", "should play video")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task ShouldPlayVideo() - { - await Page.GoToAsync(TestConstants.ServerUrl + (TestConstants.IsWebKit ? "/video_mp4.html" : "/video.html")); - await Page.EvalOnSelectorAsync("video", "v => v.play()"); - await Page.EvalOnSelectorAsync("video", "v => v.pause()"); - } - } -} +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///capabilities.spec.ts + public class CapabilitiesTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("capabilities.spec.ts", "Web Assembly should work")] + [SkipBrowserAndPlatformFact(skipWebkit: true, skipWindows: true)] + public async Task WebAssemblyShouldWork() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/wasm/table2.html"); + Assert.That(await Page.EvaluateAsync("() => loadTable()"), Is.EqualTo("42, 83")); + } + +#if NETCOREAPP + [PlaywrightTest("capabilities.spec.ts", "WebSocket should work")] + [SkipBrowserAndPlatformFact(skipWebkit: true, skipWindows: true)] + public async Task WebSocketShouldWork() + { + string value = await Page.EvaluateAsync( + $@"(port) => {{ + let cb; + const result = new Promise(f => cb = f); + const ws = new WebSocket('ws://localhost:' + port + '/ws'); + ws.addEventListener('message', data => {{ ws.close(); cb(data.data); console.log(data); console.log(data.data) }}); + ws.addEventListener('error', error => cb('Error')); + return result; + }}", + TestConstants.Port); + Assert.That(value, Is.EqualTo("incoming")); + } +#endif + + [PlaywrightTest("capabilities.spec.ts", "should respect CSP")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRespectCSP() + { + Server.SetRoute("/empty.html", context => + { + const string message = @" + + "; + + context.Response.Headers["Content-Length"] = message.Length.ToString(); + context.Response.Headers["Content-Security-Policy"] = "script-src 'unsafe-inline';"; + return context.Response.WriteAsync(message); + }); + + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await Page.EvaluateAsync("() => window.testStatus"), Is.EqualTo("SUCCESS")); + } + + [PlaywrightTest("capabilities.spec.ts", "should play video")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task ShouldPlayVideo() + { + await Page.GoToAsync(TestConstants.ServerUrl + (TestConstants.IsWebKit ? "/video_mp4.html" : "/video.html")); + await Page.EvalOnSelectorAsync("video", "v => v.play()"); + await Page.EvalOnSelectorAsync("video", "v => v.pause()"); + } + } +} diff --git a/src/Playwright.Tests/ChromiumCSSCoverageTests.cs b/src/PlaywrightSharp.Tests/ChromiumCSSCoverageTests.cs similarity index 73% rename from src/Playwright.Tests/ChromiumCSSCoverageTests.cs rename to src/PlaywrightSharp.Tests/ChromiumCSSCoverageTests.cs index 784268d622..b478e90154 100644 --- a/src/Playwright.Tests/ChromiumCSSCoverageTests.cs +++ b/src/PlaywrightSharp.Tests/ChromiumCSSCoverageTests.cs @@ -1,201 +1,192 @@ -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Newtonsoft.Json; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ChromiumCSSCoverageTests : PlaywrightSharpPageBaseTest - { - /// - public ChromiumCSSCoverageTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should work")] - [Fact(Skip = "We won't support coverage")] - public void ShouldWork() - { - /* - await Page.Coverage.StartCSSCoverageAsync(); - await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/simple.html"); - var coverage = await Page.Coverage.StopCSSCoverageAsync(); - Assert.Single(coverage); - Assert.Contains("/csscoverage/simple.html", coverage[0].Url); - Assert.Equal(new[] - { - new CSSCoverageEntryRange - { - Start = 1, - End = 22 - } - }, coverage[0].Ranges); - var range = coverage[0].Ranges[0]; - Assert.Equal("div { color: green; }", coverage[0].Text.Substring(range.Start, range.End - range.Start)); - */ - } - - [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should report sourceURLs")] - [Fact(Skip = "We won't support coverage")] - public void ShouldReportSourceUrls() - { - /* - await Page.Coverage.StartCSSCoverageAsync(); - await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/sourceurl.html"); - var coverage = await Page.Coverage.StopCSSCoverageAsync(); - Assert.Single(coverage); - Assert.Equal("nicename.css", coverage[0].Url); - */ - } - - [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should report multiple stylesheets")] - [Fact(Skip = "We won't support coverage")] - public void ShouldReportMultipleStylesheets() - { - /* - await Page.Coverage.StartCSSCoverageAsync(); - await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/multiple.html"); - var coverage = await Page.Coverage.StopCSSCoverageAsync(); - Assert.Equal(2, coverage.Length); - var orderedList = coverage.OrderBy(c => c.Url).ToArray(); - Assert.Contains("/csscoverage/stylesheet1.css", orderedList[0].Url); - Assert.Contains("/csscoverage/stylesheet2.css", orderedList[1].Url); - */ - } - - [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should report stylesheets that have no coverage")] - [Fact(Skip = "We won't support coverage")] - public void ShouldReportStylesheetsThatHaveNoCoverage() - { - /* - await Page.Coverage.StartCSSCoverageAsync(); - await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/unused.html"); - var coverage = await Page.Coverage.StopCSSCoverageAsync(); - Assert.Single(coverage); - var entry = coverage[0]; - Assert.Contains("unused.css", entry.Url); - Assert.Empty(entry.Ranges); - */ - } - - [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should work with media queries")] - [Fact(Skip = "We won't support coverage")] - public void ShouldWorkWithMediaQueries() - { - /* - await Page.Coverage.StartCSSCoverageAsync(); - await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/media.html"); - var coverage = await Page.Coverage.StopCSSCoverageAsync(); - Assert.Single(coverage); - var entry = coverage[0]; - Assert.Contains("/csscoverage/media.html", entry.Url); - Assert.Equal(new[] - { - new CSSCoverageEntryRange - { - Start = 17, - End = 38 - } - }, coverage[0].Ranges); - */ - } - - [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should work with complicated usecases")] - [Fact(Skip = "We won't support coverage")] - public void ShouldWorkWithComplicatedUseCases() - { - /* - const string involved = @"[ - { - ""Url"": ""http://localhost:/csscoverage/involved.html"", - ""Ranges"": [ - { - ""Start"": 149, - ""End"": 297 - }, - { - ""Start"": 327, - ""End"": 433 - } - ], - ""Text"": ""\n @charset \""utf - 8\"";\n@namespace svg url(http://www.w3.org/2000/svg);\n@font-face {\n font-family: \""Example Font\"";\n src: url(\""./Dosis-Regular.ttf\"");\n}\n\n#fluffy {\n border: 1px solid black;\n z-index: 1;\n /\n -lol-cats: \""dogs\"" \n}\n\n@media (min-width: 1px) {\n span {\n -webkit-border-radius: 10px;\n font-family: \""Example Font\"";\n animation: 1s identifier;\n }\n}\n"" - } - ]"; - await Page.Coverage.StartCSSCoverageAsync(); - await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/involved.html"); - var coverage = await Page.Coverage.StopCSSCoverageAsync(); - Assert.Equal( - TestUtils.CompressText(involved), - Regex.Replace(TestUtils.CompressText(JsonConvert.SerializeObject(coverage)), @":\d{4}\/", ":/")); - */ - } - - [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should ignore injected stylesheets")] - [Fact(Skip = "We won't support coverage")] - public void ShouldIgnoreInjectedStylesheets() - { - /* - await Page.Coverage.StartCSSCoverageAsync(); - await Page.AddStyleTagAsync(content: "body { margin: 10px;}"); - // trigger style recalc - string margin = await Page.EvaluateAsync("window.getComputedStyle(document.body).margin"); - Assert.Equal("10px", margin); - var coverage = await Page.Coverage.StopCSSCoverageAsync(); - Assert.Empty(coverage); - */ - } - - [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should report stylesheets across navigations")] - [Fact(Skip = "We won't support coverage")] - public void ShouldReportStylesheetsAcrossNavigations() - { - /* - await Page.Coverage.StartCSSCoverageAsync(false); - await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/multiple.html"); - await Page.GoToAsync(TestConstants.EmptyPage); - var coverage = await Page.Coverage.StopCSSCoverageAsync(); - Assert.Equal(2, coverage.Length); - */ - } - - [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should NOT report stylesheets across navigations")] - [Fact(Skip = "We won't support coverage")] - public void ShouldNotReportScriptsAcrossNavigations() - { - /* - await Page.Coverage.StartCSSCoverageAsync(); - await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/multiple.html"); - await Page.GoToAsync(TestConstants.EmptyPage); - var coverage = await Page.Coverage.StopCSSCoverageAsync(); - Assert.Empty(coverage); - */ - } - - [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should work with a recently loaded stylesheet")] - [Fact(Skip = "We won't support coverage")] - public void ShouldWorkWithArRecentlyLoadedStylesheet() - { - /* - await Page.Coverage.StartCSSCoverageAsync(); - await Page.EvaluateAsync(@"async url => { - document.body.textContent = 'hello, world'; - - const link = document.createElement('link'); - link.rel = 'stylesheet'; - link.href = url; - document.head.appendChild(link); - await new Promise(x => link.onload = x); - await new Promise(f => requestAnimationFrame(f)); - }", TestConstants.ServerUrl + "/csscoverage/stylesheet1.css"); - var coverage = await Page.Coverage.StopCSSCoverageAsync(); - Assert.Single(coverage); - */ - } - } -} +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Newtonsoft.Json; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class ChromiumCSSCoverageTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should work")] + [Test, Ignore("We won't support coverage")] + public void ShouldWork() + { + /* + await Page.Coverage.StartCSSCoverageAsync(); + await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/simple.html"); + var coverage = await Page.Coverage.StopCSSCoverageAsync(); + Assert.That(coverage, Has.Exactly(1).Items); + Assert.That(coverage[0].Url, Does.Contain("/csscoverage/simple.html")); + Assert.That(coverage[0].Ranges, Is.EqualTo(new[] + { + new CSSCoverageEntryRange + { + Start = 1, + End = 22 + } + })); + var range = coverage[0].Ranges[0]; + Assert.That(coverage[0].Text.Substring(range.Start, range.End - range.Start), Is.EqualTo("div { color: green; }")); + */ + } + + [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should report sourceURLs")] + [Test, Ignore("We won't support coverage")] + public void ShouldReportSourceUrls() + { + /* + await Page.Coverage.StartCSSCoverageAsync(); + await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/sourceurl.html"); + var coverage = await Page.Coverage.StopCSSCoverageAsync(); + Assert.That(coverage, Has.Exactly(1).Items); + Assert.That(coverage[0].Url, Is.EqualTo("nicename.css")); + */ + } + + [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should report multiple stylesheets")] + [Test, Ignore("We won't support coverage")] + public void ShouldReportMultipleStylesheets() + { + /* + await Page.Coverage.StartCSSCoverageAsync(); + await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/multiple.html"); + var coverage = await Page.Coverage.StopCSSCoverageAsync(); + Assert.That(coverage.Length, Is.EqualTo(2)); + var orderedList = coverage.OrderBy(c => c.Url).ToArray(); + Assert.That(orderedList[0].Url, Does.Contain("/csscoverage/stylesheet1.css")); + Assert.That(orderedList[1].Url, Does.Contain("/csscoverage/stylesheet2.css")); + */ + } + + [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should report stylesheets that have no coverage")] + [Test, Ignore("We won't support coverage")] + public void ShouldReportStylesheetsThatHaveNoCoverage() + { + /* + await Page.Coverage.StartCSSCoverageAsync(); + await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/unused.html"); + var coverage = await Page.Coverage.StopCSSCoverageAsync(); + Assert.That(coverage, Has.Exactly(1).Items); + var entry = coverage[0]; + Assert.That(entry.Url, Does.Contain("unused.css")); + Assert.That(entry.Ranges, Is.Empty); + */ + } + + [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should work with media queries")] + [Test, Ignore("We won't support coverage")] + public void ShouldWorkWithMediaQueries() + { + /* + await Page.Coverage.StartCSSCoverageAsync(); + await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/media.html"); + var coverage = await Page.Coverage.StopCSSCoverageAsync(); + Assert.That(coverage, Has.Exactly(1).Items); + var entry = coverage[0]; + Assert.That(entry.Url, Does.Contain("/csscoverage/media.html")); + Assert.That(coverage[0].Ranges, Is.EqualTo(new[] + { + new CSSCoverageEntryRange + { + Start = 17, + End = 38 + } + })); + */ + } + + [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should work with complicated usecases")] + [Test, Ignore("We won't support coverage")] + public void ShouldWorkWithComplicatedUseCases() + { + /* + const string involved = @"[ + { + ""Url"": ""http://localhost:/csscoverage/involved.html"", + ""Ranges"": [ + { + ""Start"": 149, + ""End"": 297 + }, + { + ""Start"": 327, + ""End"": 433 + } + ], + ""Text"": ""\n @charset \""utf - 8\"";\n@namespace svg url(http://www.w3.org/2000/svg);\n@font-face {\n font-family: \""Example Font\"";\n src: url(\""./Dosis-Regular.ttf\"");\n}\n\n#fluffy {\n border: 1px solid black;\n z-index: 1;\n /\n -lol-cats: \""dogs\"" \n}\n\n@media (min-width: 1px) {\n span {\n -webkit-border-radius: 10px;\n font-family: \""Example Font\"";\n animation: 1s identifier;\n }\n}\n"" + } + ]"; + await Page.Coverage.StartCSSCoverageAsync(); + await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/involved.html"); + var coverage = await Page.Coverage.StopCSSCoverageAsync(); + Assert.That(Regex.Replace(TestUtils.CompressText(JsonConvert.SerializeObject(coverage)), @":\d{4}\/", ":/"), Is.EqualTo(TestUtils.CompressText(involved))); + */ + } + + [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should ignore injected stylesheets")] + [Test, Ignore("We won't support coverage")] + public void ShouldIgnoreInjectedStylesheets() + { + /* + await Page.Coverage.StartCSSCoverageAsync(); + await Page.AddStyleTagAsync(content: "body { margin: 10px;}"); + // trigger style recalc + string margin = await Page.EvaluateAsync("window.getComputedStyle(document.body).margin"); + Assert.That(margin, Is.EqualTo("10px")); + var coverage = await Page.Coverage.StopCSSCoverageAsync(); + Assert.That(coverage, Is.Empty); + */ + } + + [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should report stylesheets across navigations")] + [Test, Ignore("We won't support coverage")] + public void ShouldReportStylesheetsAcrossNavigations() + { + /* + await Page.Coverage.StartCSSCoverageAsync(false); + await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/multiple.html"); + await Page.GoToAsync(TestConstants.EmptyPage); + var coverage = await Page.Coverage.StopCSSCoverageAsync(); + Assert.That(coverage.Length, Is.EqualTo(2)); + */ + } + + [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should NOT report stylesheets across navigations")] + [Test, Ignore("We won't support coverage")] + public void ShouldNotReportScriptsAcrossNavigations() + { + /* + await Page.Coverage.StartCSSCoverageAsync(); + await Page.GoToAsync(TestConstants.ServerUrl + "/csscoverage/multiple.html"); + await Page.GoToAsync(TestConstants.EmptyPage); + var coverage = await Page.Coverage.StopCSSCoverageAsync(); + Assert.That(coverage, Is.Empty); + */ + } + + [PlaywrightTest("chromium-css-coverage.spec.ts", "CSS Coverage", "should work with a recently loaded stylesheet")] + [Test, Ignore("We won't support coverage")] + public void ShouldWorkWithArRecentlyLoadedStylesheet() + { + /* + await Page.Coverage.StartCSSCoverageAsync(); + await Page.EvaluateAsync(@"async url => { + document.body.textContent = 'hello, world'; + + const link = document.createElement('link'); + link.rel = 'stylesheet'; + link.href = url; + document.head.appendChild(link); + await new Promise(x => link.onload = x); + await new Promise(f => requestAnimationFrame(f)); + }", TestConstants.ServerUrl + "/csscoverage/stylesheet1.css"); + var coverage = await Page.Coverage.StopCSSCoverageAsync(); + Assert.That(coverage, Has.Exactly(1).Items); + */ + } + } +} diff --git a/src/Playwright.Tests/ChromiumJSCoverageTests.cs b/src/PlaywrightSharp.Tests/ChromiumJSCoverageTests.cs similarity index 70% rename from src/Playwright.Tests/ChromiumJSCoverageTests.cs rename to src/PlaywrightSharp.Tests/ChromiumJSCoverageTests.cs index f9e9f9439e..e4218af673 100644 --- a/src/Playwright.Tests/ChromiumJSCoverageTests.cs +++ b/src/PlaywrightSharp.Tests/ChromiumJSCoverageTests.cs @@ -1,126 +1,119 @@ -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ChromiumJSCoverageTests : PlaywrightSharpPageBaseTest - { - /// - public ChromiumJSCoverageTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should work")] - [Fact(Skip = "We won't support coverage")] - public void ShouldWork() - { - /* - await Page.Coverage.StartJSCoverageAsync(); - await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/simple.html", LoadState.NetworkIdle); - var coverage = await Page.Coverage.StopJSCoverageAsync(); - Assert.Single(coverage); - Assert.Contains("/jscoverage/simple.html", coverage[0].Url); - Assert.Equal(1, coverage[0].Functions.Single(f => f.FunctionName == "foo").Ranges[0].Count); - */ - } - - [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should report sourceURLs")] - [Fact(Skip = "We won't support coverage")] - public void ShouldReportSourceUrls() - { - /* - await Page.Coverage.StartJSCoverageAsync(); - await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/sourceurl.html"); - var coverage = await Page.Coverage.StopJSCoverageAsync(); - Assert.Single(coverage); - Assert.Equal("nicename.js", coverage[0].Url); - */ - } - - [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should ignore eval() scripts by default")] - [Fact(Skip = "We won't support coverage")] - public void ShouldIgnoreEvalScriptsByDefault() - { - /* - await Page.Coverage.StartJSCoverageAsync(); - await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/eval.html"); - var coverage = await Page.Coverage.StopJSCoverageAsync(); - Assert.Single(coverage); - */ - } - - [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "shouldn't ignore eval() scripts if reportAnonymousScripts is true")] - [Fact(Skip = "We won't support coverage")] - public void ShouldNotIgnoreEvalScriptsIfReportAnonymousScriptsIsTrue() - { - /* - await Page.Coverage.StartJSCoverageAsync(reportAnonymousScripts: true); - await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/eval.html"); - var coverage = await Page.Coverage.StopJSCoverageAsync(); - Assert.Equal("console.log(\"foo\")", coverage.Single(entry => entry.Url == string.Empty).Source); - Assert.Equal(2, coverage.Length); - */ - } - - [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should report multiple scripts")] - [Fact(Skip = "We won't support coverage")] - public void ShouldReportMultipleScripts() - { - /* - await Page.Coverage.StartJSCoverageAsync(); - await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/multiple.html"); - var coverage = await Page.Coverage.StopJSCoverageAsync(); - Assert.Equal(2, coverage.Length); - var orderedList = coverage.OrderBy(c => c.Url).ToArray(); - Assert.Contains("/jscoverage/script1.js", orderedList[0].Url); - Assert.Contains("/jscoverage/script2.js", orderedList[1].Url); - */ - } - - [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should report scripts across navigations when disabled")] - [Fact(Skip = "We won't support coverage")] - public void ShouldReportScriptsAcrossNavigationsWhenDisabled() - { - /* - await Page.Coverage.StartJSCoverageAsync(false); - await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/multiple.html"); - await Page.GoToAsync(TestConstants.EmptyPage); - var coverage = await Page.Coverage.StopJSCoverageAsync(); - Assert.Equal(2, coverage.Length); - */ - } - - [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should NOT report scripts across navigations when enabled")] - [Fact(Skip = "We won't support coverage")] - public void ShouldNotReportScriptsAcrossNavigationsWhenEnabled() - { - /* - await Page.Coverage.StartJSCoverageAsync(); - await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/multiple.html"); - await Page.GoToAsync(TestConstants.EmptyPage); - var coverage = await Page.Coverage.StopJSCoverageAsync(); - Assert.Empty(coverage); - */ - } - - [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should not hang when there is a debugger statement")] - [Fact(Skip = "We won't support coverage")] - public void ShouldNotHangWhenThereIsADebuggerStatement() - { - /* - await Page.Coverage.StartJSCoverageAsync(); - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.EvaluateAsync(@"() => { - debugger; // eslint-disable-line no-debugger - }"); - await Page.Coverage.StopJSCoverageAsync(); - */ - } - } -} +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class ChromiumJSCoverageTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should work")] + [Test, Ignore("We won't support coverage")] + public void ShouldWork() + { + /* + await Page.Coverage.StartJSCoverageAsync(); + await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/simple.html", LoadState.NetworkIdle); + var coverage = await Page.Coverage.StopJSCoverageAsync(); + Assert.That(coverage, Has.Exactly(1).Items); + Assert.That(coverage[0].Url, Does.Contain("/jscoverage/simple.html")); + Assert.That(coverage[0].Functions.Single(f => f.FunctionName == "foo").Ranges[0].Count, Is.EqualTo(1)); + */ + } + + [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should report sourceURLs")] + [Test, Ignore("We won't support coverage")] + public void ShouldReportSourceUrls() + { + /* + await Page.Coverage.StartJSCoverageAsync(); + await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/sourceurl.html"); + var coverage = await Page.Coverage.StopJSCoverageAsync(); + Assert.That(coverage, Has.Exactly(1).Items); + Assert.That(coverage[0].Url, Is.EqualTo("nicename.js")); + */ + } + + [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should ignore eval() scripts by default")] + [Test, Ignore("We won't support coverage")] + public void ShouldIgnoreEvalScriptsByDefault() + { + /* + await Page.Coverage.StartJSCoverageAsync(); + await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/eval.html"); + var coverage = await Page.Coverage.StopJSCoverageAsync(); + Assert.That(coverage, Has.Exactly(1).Items); + */ + } + + [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "shouldn't ignore eval() scripts if reportAnonymousScripts is true")] + [Test, Ignore("We won't support coverage")] + public void ShouldNotIgnoreEvalScriptsIfReportAnonymousScriptsIsTrue() + { + /* + await Page.Coverage.StartJSCoverageAsync(reportAnonymousScripts: true); + await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/eval.html"); + var coverage = await Page.Coverage.StopJSCoverageAsync(); + Assert.That(coverage.Single(entry => entry.Url == string.Empty).Source, Is.EqualTo("console.log(\"foo\")")); + Assert.That(coverage.Length, Is.EqualTo(2)); + */ + } + + [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should report multiple scripts")] + [Test, Ignore("We won't support coverage")] + public void ShouldReportMultipleScripts() + { + /* + await Page.Coverage.StartJSCoverageAsync(); + await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/multiple.html"); + var coverage = await Page.Coverage.StopJSCoverageAsync(); + Assert.That(coverage.Length, Is.EqualTo(2)); + var orderedList = coverage.OrderBy(c => c.Url).ToArray(); + Assert.That(orderedList[0].Url, Does.Contain("/jscoverage/script1.js")); + Assert.That(orderedList[1].Url, Does.Contain("/jscoverage/script2.js")); + */ + } + + [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should report scripts across navigations when disabled")] + [Test, Ignore("We won't support coverage")] + public void ShouldReportScriptsAcrossNavigationsWhenDisabled() + { + /* + await Page.Coverage.StartJSCoverageAsync(false); + await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/multiple.html"); + await Page.GoToAsync(TestConstants.EmptyPage); + var coverage = await Page.Coverage.StopJSCoverageAsync(); + Assert.That(coverage.Length, Is.EqualTo(2)); + */ + } + + [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should NOT report scripts across navigations when enabled")] + [Test, Ignore("We won't support coverage")] + public void ShouldNotReportScriptsAcrossNavigationsWhenEnabled() + { + /* + await Page.Coverage.StartJSCoverageAsync(); + await Page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/multiple.html"); + await Page.GoToAsync(TestConstants.EmptyPage); + var coverage = await Page.Coverage.StopJSCoverageAsync(); + Assert.That(coverage, Is.Empty); + */ + } + + [PlaywrightTest("chromium-js-coverage.spec.ts", "JS Coverage", "should not hang when there is a debugger statement")] + [Test, Ignore("We won't support coverage")] + public void ShouldNotHangWhenThereIsADebuggerStatement() + { + /* + await Page.Coverage.StartJSCoverageAsync(); + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.EvaluateAsync(@"() => { + debugger; // eslint-disable-line no-debugger + }"); + await Page.Coverage.StopJSCoverageAsync(); + */ + } + } +} diff --git a/src/Playwright.Tests/DefaultBrowserContext1Tests.cs b/src/PlaywrightSharp.Tests/DefaultBrowserContext1Tests.cs similarity index 67% rename from src/Playwright.Tests/DefaultBrowserContext1Tests.cs rename to src/PlaywrightSharp.Tests/DefaultBrowserContext1Tests.cs index d9eceb55fd..b9504e46a4 100644 --- a/src/Playwright.Tests/DefaultBrowserContext1Tests.cs +++ b/src/PlaywrightSharp.Tests/DefaultBrowserContext1Tests.cs @@ -1,306 +1,299 @@ -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Microsoft.Playwright.Tests.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class DefaultBrowserContext1Tests : PlaywrightSharpBaseTest - { - /// - public DefaultBrowserContext1Tests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "context.cookies() should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ContextCookiesShouldWork() - { - var (tmp, context, page) = await LaunchAsync(); - - await page.GoToAsync(TestConstants.EmptyPage); - - string documentCookie = await page.EvaluateAsync(@"() => { - document.cookie = 'username=John Doe'; - return document.cookie; - }"); - - Assert.Equal("username=John Doe", documentCookie); - var cookie = (await page.Context.GetCookiesAsync()).Single(); - Assert.Equal("username", cookie.Name); - Assert.Equal("John Doe", cookie.Value); - Assert.Equal("localhost", cookie.Domain); - Assert.Equal("/", cookie.Path); - Assert.Equal(-1, cookie.Expires); - Assert.False(cookie.HttpOnly); - Assert.False(cookie.Secure); - Assert.Equal(SameSiteAttribute.None, cookie.SameSite); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "context.addCookies() should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ContextAddCookiesShouldWork() - { - var (tmp, context, page) = await LaunchAsync(); - - await page.GoToAsync(TestConstants.EmptyPage); - await context.AddCookiesAsync(new Cookie - { - Url = TestConstants.EmptyPage, - Name = "username", - Value = "John Doe", - }); - - Assert.Equal("username=John Doe", await page.EvaluateAsync(@"() => document.cookie")); - - var cookie = (await page.Context.GetCookiesAsync()).Single(); - Assert.Equal("username", cookie.Name); - Assert.Equal("John Doe", cookie.Value); - Assert.Equal("localhost", cookie.Domain); - Assert.Equal("/", cookie.Path); - Assert.Equal(-1, cookie.Expires); - Assert.False(cookie.HttpOnly); - Assert.False(cookie.Secure); - Assert.Equal(SameSiteAttribute.None, cookie.SameSite); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "context.clearCookies() should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ContextClearCookiesShouldWork() - { - var (tmp, context, page) = await LaunchAsync(); - - await page.GoToAsync(TestConstants.EmptyPage); - await context.AddCookiesAsync( - new Cookie - { - Url = TestConstants.EmptyPage, - Name = "cookie1", - Value = "1", - }, - new Cookie - { - Url = TestConstants.EmptyPage, - Name = "cookie2", - Value = "2", - }); - - Assert.Equal("cookie1=1; cookie2=2", await page.EvaluateAsync(@"() => document.cookie")); - - await context.ClearCookiesAsync(); - await page.ReloadAsync(); - Assert.Empty(await page.Context.GetCookiesAsync()); - Assert.Empty(await page.EvaluateAsync(@"() => document.cookie")); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should(not) block third party cookies")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotBlockThirdPartyCookies() - { - var (tmp, context, page) = await LaunchAsync(); - - await page.GoToAsync(TestConstants.EmptyPage); - await page.EvaluateAsync(@"src => { - let fulfill; - const promise = new Promise(x => fulfill = x); - const iframe = document.createElement('iframe'); - document.body.appendChild(iframe); - iframe.onload = fulfill; - iframe.src = src; - return promise; - }", TestConstants.CrossProcessUrl + "/grid.html"); - - await page.FirstChildFrame().EvaluateAsync("document.cookie = 'username=John Doe'"); - await page.WaitForTimeoutAsync(2000); - bool allowsThirdPart = !TestConstants.IsWebKit; - var cookies = await context.GetCookiesAsync(TestConstants.CrossProcessUrl + "/grid.html"); - - if (allowsThirdPart) - { - Assert.Single(cookies); - var cookie = cookies.First(); - Assert.Equal("127.0.0.1", cookie.Domain); - Assert.Equal(cookie.Expires, -1); - Assert.False(cookie.HttpOnly); - Assert.Equal("username", cookie.Name); - Assert.Equal("/", cookie.Path); - Assert.Equal(SameSiteAttribute.None, cookie.SameSite); - Assert.False(cookie.Secure); - Assert.Equal("John Doe", cookie.Value); - } - else - { - Assert.Empty(cookies); - } - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support viewport option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportViewportOption() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 456, - Height = 789 - } - }); - - await TestUtils.VerifyViewportAsync(page, 456, 789); - page = await context.NewPageAsync(); - await TestUtils.VerifyViewportAsync(page, 456, 789); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support deviceScaleFactor option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportDeviceScaleFactorOption() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - DeviceScaleFactor = 3 - }); - - Assert.Equal(3, await page.EvaluateAsync("window.devicePixelRatio")); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support userAgent option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportUserAgentOption() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - UserAgent = "foobar" - }); - - string userAgent = string.Empty; - - await TaskUtils.WhenAll( - Server.WaitForRequest("/empty.html", r => userAgent = r.Headers["user-agent"]), - page.GoToAsync(TestConstants.EmptyPage)); - - Assert.Equal("foobar", userAgent); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support bypassCSP option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportBypassCSPOption() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - BypassCSP = true - }); - - await page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); - await page.AddScriptTagAsync(content: "window.__injected = 42;"); - Assert.Equal(42, await page.EvaluateAsync("window.__injected")); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support javascriptEnabled option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportJavascriptEnabledOption() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - JavaScriptEnabled = false - }); - - await page.GoToAsync("data:text/html, "); - var exception = await Assert.ThrowsAnyAsync(() => page.EvaluateAsync("something")); - - if (TestConstants.IsWebKit) - { - Assert.Contains("Can't find variable: something", exception.Message); - } - else - { - Assert.Contains("something is not defined", exception.Message); - } - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support httpCredentials option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRupportHttpCredentialsOption() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - HttpCredentials = new HttpCredentials - { - Username = "user", - Password = "pass", - } - }); - - Server.SetAuth("/playground.html", "user", "pass"); - var response = await page.GoToAsync(TestConstants.ServerUrl + "/playground.html"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support offline option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportOfflineOption() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - Offline = true - }); - - await Assert.ThrowsAnyAsync(() => page.GoToAsync(TestConstants.EmptyPage)); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support acceptDownloads option")] - [Fact(Skip = "Skipped on playwright")] - public void ShouldSupportAcceptDownloadsOption() - { - } - - private async Task<(TempDirectory tmp, IBrowserContext context, IPage page)> LaunchAsync(BrowserContextOptions options = null) - { - var tmp = new TempDirectory(); - var context = await BrowserType.LaunchDefaultPersistentContext( - tmp.Path, - options: options); - var page = context.Pages.First(); - - return (tmp, context, page); - } - } -} +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; +using PlaywrightSharp.Tests.Helpers; + +namespace PlaywrightSharp.Tests +{ + public class DefaultBrowserContext1Tests : PlaywrightSharpBaseTest + { + [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "context.cookies() should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ContextCookiesShouldWork() + { + var (tmp, context, page) = await LaunchAsync(); + + await page.GoToAsync(TestConstants.EmptyPage); + + string documentCookie = await page.EvaluateAsync(@"() => { + document.cookie = 'username=John Doe'; + return document.cookie; + }"); + + Assert.That(documentCookie, Is.EqualTo("username=John Doe")); + var cookie = (await page.Context.GetCookiesAsync()).Single(); + Assert.That(cookie.Name, Is.EqualTo("username")); + Assert.That(cookie.Value, Is.EqualTo("John Doe")); + Assert.That(cookie.Domain, Is.EqualTo("localhost")); + Assert.That(cookie.Path, Is.EqualTo("/")); + Assert.That(cookie.Expires, Is.EqualTo(-1)); + Assert.That(cookie.HttpOnly, Is.False); + Assert.That(cookie.Secure, Is.False); + Assert.That(cookie.SameSite, Is.EqualTo(SameSiteAttribute.None)); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "context.addCookies() should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ContextAddCookiesShouldWork() + { + var (tmp, context, page) = await LaunchAsync(); + + await page.GoToAsync(TestConstants.EmptyPage); + await context.AddCookiesAsync(new Cookie + { + Url = TestConstants.EmptyPage, + Name = "username", + Value = "John Doe", + }); + + Assert.That(await page.EvaluateAsync(@"() => document.cookie"), Is.EqualTo("username=John Doe")); + + var cookie = (await page.Context.GetCookiesAsync()).Single(); + Assert.That(cookie.Name, Is.EqualTo("username")); + Assert.That(cookie.Value, Is.EqualTo("John Doe")); + Assert.That(cookie.Domain, Is.EqualTo("localhost")); + Assert.That(cookie.Path, Is.EqualTo("/")); + Assert.That(cookie.Expires, Is.EqualTo(-1)); + Assert.That(cookie.HttpOnly, Is.False); + Assert.That(cookie.Secure, Is.False); + Assert.That(cookie.SameSite, Is.EqualTo(SameSiteAttribute.None)); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "context.clearCookies() should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ContextClearCookiesShouldWork() + { + var (tmp, context, page) = await LaunchAsync(); + + await page.GoToAsync(TestConstants.EmptyPage); + await context.AddCookiesAsync( + new Cookie + { + Url = TestConstants.EmptyPage, + Name = "cookie1", + Value = "1", + }, + new Cookie + { + Url = TestConstants.EmptyPage, + Name = "cookie2", + Value = "2", + }); + + Assert.That(await page.EvaluateAsync(@"() => document.cookie"), Is.EqualTo("cookie1=1; cookie2=2")); + + await context.ClearCookiesAsync(); + await page.ReloadAsync(); + Assert.That(await page.Context.GetCookiesAsync(), Is.Empty); + Assert.That(await page.EvaluateAsync(@"() => document.cookie"), Is.Empty); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should(not) block third party cookies")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotBlockThirdPartyCookies() + { + var (tmp, context, page) = await LaunchAsync(); + + await page.GoToAsync(TestConstants.EmptyPage); + await page.EvaluateAsync(@"src => { + let fulfill; + const promise = new Promise(x => fulfill = x); + const iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + iframe.onload = fulfill; + iframe.src = src; + return promise; + }", TestConstants.CrossProcessUrl + "/grid.html"); + + await page.FirstChildFrame().EvaluateAsync("document.cookie = 'username=John Doe'"); + await page.WaitForTimeoutAsync(2000); + bool allowsThirdPart = !TestConstants.IsWebKit; + var cookies = await context.GetCookiesAsync(TestConstants.CrossProcessUrl + "/grid.html"); + + if (allowsThirdPart) + { + Assert.That(cookies, Has.Exactly(1).Items); + var cookie = cookies.First(); + Assert.That(cookie.Domain, Is.EqualTo("127.0.0.1")); + Assert.That(cookie.Expires, Is.EqualTo(-1)); + Assert.That(cookie.HttpOnly, Is.False); + Assert.That(cookie.Name, Is.EqualTo("username")); + Assert.That(cookie.Path, Is.EqualTo("/")); + Assert.That(cookie.SameSite, Is.EqualTo(SameSiteAttribute.None)); + Assert.That(cookie.Secure, Is.False); + Assert.That(cookie.Value, Is.EqualTo("John Doe")); + } + else + { + Assert.That(cookies, Is.Empty); + } + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support viewport option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportViewportOption() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 456, + Height = 789 + } + }); + + await TestUtils.VerifyViewportAsync(page, 456, 789); + page = await context.NewPageAsync(); + await TestUtils.VerifyViewportAsync(page, 456, 789); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support deviceScaleFactor option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportDeviceScaleFactorOption() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + DeviceScaleFactor = 3 + }); + + Assert.That(await page.EvaluateAsync("window.devicePixelRatio"), Is.EqualTo(3)); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support userAgent option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportUserAgentOption() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + UserAgent = "foobar" + }); + + string userAgent = string.Empty; + + await TaskUtils.WhenAll( + Server.WaitForRequest("/empty.html", r => userAgent = r.Headers["user-agent"]), + page.GoToAsync(TestConstants.EmptyPage)); + + Assert.That(userAgent, Is.EqualTo("foobar")); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support bypassCSP option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportBypassCSPOption() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + BypassCSP = true + }); + + await page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); + await page.AddScriptTagAsync(content: "window.__injected = 42;"); + Assert.That(await page.EvaluateAsync("window.__injected"), Is.EqualTo(42)); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support javascriptEnabled option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportJavascriptEnabledOption() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + JavaScriptEnabled = false + }); + + await page.GoToAsync("data:text/html, "); + var exception = Assert.CatchAsync(() => page.EvaluateAsync("something")); + + if (TestConstants.IsWebKit) + { + Assert.That(exception.Message, Does.Contain("Can't find variable: something")); + } + else + { + Assert.That(exception.Message, Does.Contain("something is not defined")); + } + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support httpCredentials option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRupportHttpCredentialsOption() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + HttpCredentials = new HttpCredentials + { + Username = "user", + Password = "pass", + } + }); + + Server.SetAuth("/playground.html", "user", "pass"); + var response = await page.GoToAsync(TestConstants.ServerUrl + "/playground.html"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support offline option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportOfflineOption() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + Offline = true + }); + + Assert.CatchAsync(() => page.GoToAsync(TestConstants.EmptyPage)); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-1.spec.ts", "should support acceptDownloads option")] + [Test, Ignore("Skipped on playwright")] + public void ShouldSupportAcceptDownloadsOption() + { + } + + private async Task<(TempDirectory tmp, IBrowserContext context, IPage page)> LaunchAsync(BrowserContextOptions options = null) + { + var tmp = new TempDirectory(); + var context = await BrowserType.LaunchDefaultPersistentContext( + tmp.Path, + options: options); + var page = context.Pages.First(); + + return (tmp, context, page); + } + } +} diff --git a/src/Playwright.Tests/DefaultBrowsercontext2Tests.cs b/src/PlaywrightSharp.Tests/DefaultBrowsercontext2Tests.cs similarity index 74% rename from src/Playwright.Tests/DefaultBrowsercontext2Tests.cs rename to src/PlaywrightSharp.Tests/DefaultBrowsercontext2Tests.cs index 2f24c5c7b5..2e6c1195fe 100644 --- a/src/Playwright.Tests/DefaultBrowsercontext2Tests.cs +++ b/src/PlaywrightSharp.Tests/DefaultBrowsercontext2Tests.cs @@ -1,376 +1,368 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Microsoft.Playwright.Tests.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - /// defaultbrowsercontext-2.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class DefaultBrowsercontext2Tests : PlaywrightSharpBaseTest - { - /// - public DefaultBrowsercontext2Tests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support hasTouch option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportHasTouchOption() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - HasTouch = true - }); - - await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); - Assert.True(await page.EvaluateAsync("() => 'ontouchstart' in window")); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should work in persistent context")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWorkInPersistentContext() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 320, - Height = 480, - }, - IsMobile = true, - }); - - await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(980, await page.EvaluateAsync("() => window.innerWidth")); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support colorScheme option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportColorSchemeOption() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - ColorScheme = ColorScheme.Dark, - }); - - Assert.False(await page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches")); - Assert.True(await page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches")); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support timezoneId option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportTimezoneIdOption() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - TimezoneId = "America/Jamaica", - }); - - Assert.Equal("Sat Nov 19 2016 13:12:34 GMT-0500 (Eastern Standard Time)", await page.EvaluateAsync("() => new Date(1479579154987).toString()")); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support locale option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportLocaleOption() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - Locale = "fr-CH", - }); - - Assert.Equal("fr-CH", await page.EvaluateAsync("() => navigator.language")); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support geolocation and permissions options")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportGeolocationAndPermissionsOptions() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - Geolocation = new Geolocation - { - Latitude = 10, - Longitude = 10, - }, - Permissions = new[] { ContextPermissions.Geolocation }, - }); - - await page.GoToAsync(TestConstants.EmptyPage); - var geolocation = await page.EvaluateAsync(@"() => new Promise(resolve => navigator.geolocation.getCurrentPosition(position => { - resolve({latitude: position.coords.latitude, longitude: position.coords.longitude}); - }))"); - Assert.Equal(10, geolocation.Latitude); - Assert.Equal(10, geolocation.Longitude); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support ignoreHTTPSErrors option")] - // [Fact(Timeout = TestConstants.DefaultTestTimeout)] - [Fact(Skip = "Fix me #1058")] - public async Task ShouldSupportIgnoreHTTPSErrorsOption() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - IgnoreHTTPSErrors = true - }); - - var response = await page.GoToAsync(TestConstants.HttpsPrefix + "/empty.html"); - Assert.True(response.Ok); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support extraHTTPHeaders option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportExtraHTTPHeadersOption() - { - var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions - { - ExtraHTTPHeaders = new Dictionary - { - ["foo"] = "bar", - }, - }); - - string fooHeader = string.Empty; - - await TaskUtils.WhenAll( - Server.WaitForRequest("/empty.html", r => fooHeader = r.Headers["foo"]), - page.GoToAsync(TestConstants.EmptyPage)); - - Assert.Equal("bar", fooHeader); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should accept userDataDir")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptUserDataDir() - { - var (tmp, context, _) = await LaunchAsync(); - Assert.NotEmpty(new DirectoryInfo(tmp.Path).GetDirectories()); - await context.CloseAsync(); - Assert.NotEmpty(new DirectoryInfo(tmp.Path).GetDirectories()); - - tmp.Dispose(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should restore state from userDataDir")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRestoreStateFromUserDataDir() - { - using var userDataDir = new TempDirectory(); - - - await using (var browserContext = await BrowserType.LaunchDefaultPersistentContext(userDataDir.Path)) - { - var page = await browserContext.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - await page.EvaluateAsync("() => localStorage.hey = 'hello'"); - } - - await using (var browserContext2 = await BrowserType.LaunchDefaultPersistentContext(userDataDir.Path)) - { - var page = await browserContext2.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal("hello", await page.EvaluateAsync("() => localStorage.hey")); - } - - using var userDataDir2 = new TempDirectory(); - await using (var browserContext2 = await BrowserType.LaunchDefaultPersistentContext(userDataDir2.Path)) - { - var page = await browserContext2.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - Assert.NotEqual("hello", await page.EvaluateAsync("() => localStorage.hey")); - } - - userDataDir2.Dispose(); - userDataDir.Dispose(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should restore cookies from userDataDir")] - [SkipBrowserAndPlatformFact(skipChromium: true, skipWindows: true, skipOSX: true)] - public async Task ShouldRestoreCookiesFromUserDataDir() - { - var userDataDir = new TempDirectory(); - - await using (var browserContext = await BrowserType.LaunchDefaultPersistentContext(userDataDir.Path)) - { - var page = await browserContext.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - string documentCookie = await page.EvaluateAsync(@"() => { - document.cookie = 'doSomethingOnlyOnce=true; expires=Fri, 31 Dec 9999 23:59:59 GMT'; - return document.cookie; - }"); - - Assert.Equal("doSomethingOnlyOnce=true", documentCookie); - } - - await using (var browserContext2 = await BrowserType.LaunchDefaultPersistentContext(userDataDir.Path)) - { - var page = await browserContext2.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal("doSomethingOnlyOnce=true", await page.EvaluateAsync("() => document.cookie")); - } - - var userDataDir2 = new TempDirectory(); - await using (var browserContext2 = await BrowserType.LaunchDefaultPersistentContext(userDataDir2.Path)) - { - var page = await browserContext2.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - Assert.NotEqual("doSomethingOnlyOnce=true", await page.EvaluateAsync("() => document.cookie")); - } - - userDataDir2.Dispose(); - userDataDir.Dispose(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should have default URL when launching browser")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHaveDefaultURLWhenLaunchingBrowser() - { - var (tmp, context, page) = await LaunchAsync(); - - string[] urls = context.Pages.Select(p => p.Url).ToArray(); - Assert.Equal(new[] { "about:blank" }, urls); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should throw if page argument is passed")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldThrowIfPageArgumentIsPassed() - { - var tmp = new TempDirectory(); - await Assert.ThrowsAnyAsync(() => - BrowserType.LaunchDefaultPersistentContext(tmp.Path, new[] { TestConstants.EmptyPage })); - - tmp.Dispose(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should have passed URL when launching with ignoreDefaultArgs: true")] - [Fact(Skip = "Skip USES_HOOKS")] - public void ShouldHavePassedURLWhenLaunchingWithIgnoreDefaultArgsTrue() - { - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should handle timeout")] - [Fact(Skip = "Skip USES_HOOKS")] - public void ShouldHandleTimeout() - { - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should handle exception")] - [Fact(Skip = "Skip USES_HOOKS")] - public void ShouldHandleException() - { - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should fire close event for a persistent context")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFireCloseEventForAPersistentContext() - { - var (tmp, context, _) = await LaunchAsync(); - bool closed = false; - context.Close += (_, _) => closed = true; - await context.CloseAsync(); - - Assert.True(closed); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "coverage should work")] - [Fact(Skip = "We won't support coverage")] - public void CoverageShouldWork() - { - /* - var (tmp, context, page) = await LaunchAsync(); - - await page.Coverage.StartJSCoverageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/simple.html", LoadState.NetworkIdle); - var coverage = await page.Coverage.StopJSCoverageAsync(); - Assert.Single(coverage); - Assert.Contains("/jscoverage/simple.html", coverage[0].Url); - Assert.Equal(1, coverage[0].Functions.Single(f => f.FunctionName == "foo").Ranges[0].Count); - - tmp.Dispose(); - await context.DisposeAsync(); - */ - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "coverage should be missing")] - [Fact(Skip = "We won't support coverage")] - public void CoverageShouldBeMissing() - { - /* - var (tmp, context, page) = await LaunchAsync(); - Assert.Null(page.Coverage); - tmp.Dispose(); - await context.DisposeAsync(); - */ - } - - [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should respect selectors")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRespectSelectors() - { - var (tmp, context, page) = await LaunchAsync(); - const string defaultContextCSS = @"({ - create(root, target) {}, - query(root, selector) { - return root.querySelector(selector); - }, - queryAll(root, selector) { - return Array.from(root.querySelectorAll(selector)); - } - })"; - - await TestUtils.RegisterEngineAsync(Playwright, "defaultContextCSS", defaultContextCSS); - await page.SetContentAsync("
hello
"); - Assert.Equal("hello", await page.InnerHTMLAsync("css=div")); - Assert.Equal("hello", await page.InnerHTMLAsync("defaultContextCSS=div")); - - tmp.Dispose(); - await context.DisposeAsync(); - } - - private async Task<(TempDirectory tmp, IBrowserContext context, IPage page)> LaunchAsync(BrowserContextOptions options = null) - { - var tmp = new TempDirectory(); - var context = await BrowserType.LaunchDefaultPersistentContext(tmp.Path, null, options); - var page = context.Pages.First(); - - return (tmp, context, page); - } - } -} +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; +using PlaywrightSharp.Tests.Helpers; + +namespace PlaywrightSharp.Tests +{ + /// defaultbrowsercontext-2.spec.ts + public class DefaultBrowsercontext2Tests : PlaywrightSharpBaseTest + { + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support hasTouch option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportHasTouchOption() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + HasTouch = true + }); + + await page.GoToAsync(TestConstants.ServerUrl + "/mobile.html"); + Assert.That(await page.EvaluateAsync("() => 'ontouchstart' in window"), Is.True); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should work in persistent context")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWorkInPersistentContext() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 320, + Height = 480, + }, + IsMobile = true, + }); + + await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await page.EvaluateAsync("() => window.innerWidth"), Is.EqualTo(980)); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support colorScheme option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportColorSchemeOption() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + ColorScheme = ColorScheme.Dark, + }); + + Assert.That(await page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches"), Is.False); + Assert.That(await page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches"), Is.True); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support timezoneId option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportTimezoneIdOption() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + TimezoneId = "America/Jamaica", + }); + + Assert.That(await page.EvaluateAsync("() => new Date(1479579154987).toString()"), Is.EqualTo("Sat Nov 19 2016 13:12:34 GMT-0500 (Eastern Standard Time)")); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support locale option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportLocaleOption() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + Locale = "fr-CH", + }); + + Assert.That(await page.EvaluateAsync("() => navigator.language"), Is.EqualTo("fr-CH")); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support geolocation and permissions options")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportGeolocationAndPermissionsOptions() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + Geolocation = new Geolocation + { + Latitude = 10, + Longitude = 10, + }, + Permissions = new[] { ContextPermissions.Geolocation }, + }); + + await page.GoToAsync(TestConstants.EmptyPage); + var geolocation = await page.EvaluateAsync(@"() => new Promise(resolve => navigator.geolocation.getCurrentPosition(position => { + resolve({latitude: position.coords.latitude, longitude: position.coords.longitude}); + }))"); + Assert.That(geolocation.Latitude, Is.EqualTo(10)); + Assert.That(geolocation.Longitude, Is.EqualTo(10)); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support ignoreHTTPSErrors option")] + // [Test, Timeout(TestConstants.DefaultTestTimeout)] + [Test, Ignore("Fix me #1058")] + public async Task ShouldSupportIgnoreHTTPSErrorsOption() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + IgnoreHTTPSErrors = true + }); + + var response = await page.GoToAsync(TestConstants.HttpsPrefix + "/empty.html"); + Assert.That(response.Ok, Is.True); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should support extraHTTPHeaders option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportExtraHTTPHeadersOption() + { + var (tmp, context, page) = await LaunchAsync(new BrowserContextOptions + { + ExtraHTTPHeaders = new Dictionary + { + ["foo"] = "bar", + }, + }); + + string fooHeader = string.Empty; + + await TaskUtils.WhenAll( + Server.WaitForRequest("/empty.html", r => fooHeader = r.Headers["foo"]), + page.GoToAsync(TestConstants.EmptyPage)); + + Assert.That(fooHeader, Is.EqualTo("bar")); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should accept userDataDir")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptUserDataDir() + { + var (tmp, context, _) = await LaunchAsync(); + Assert.That(new DirectoryInfo(tmp.Path).GetDirectories(), Is.Not.Empty); + await context.CloseAsync(); + Assert.That(new DirectoryInfo(tmp.Path).GetDirectories(), Is.Not.Empty); + + tmp.Dispose(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should restore state from userDataDir")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRestoreStateFromUserDataDir() + { + using var userDataDir = new TempDirectory(); + + await using (var browserContext = await BrowserType.LaunchDefaultPersistentContext(userDataDir.Path)) + { + var page = await browserContext.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + await page.EvaluateAsync("() => localStorage.hey = 'hello'"); + } + + await using (var browserContext2 = await BrowserType.LaunchDefaultPersistentContext(userDataDir.Path)) + { + var page = await browserContext2.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await page.EvaluateAsync("() => localStorage.hey"), Is.EqualTo("hello")); + } + + using var userDataDir2 = new TempDirectory(); + await using (var browserContext2 = await BrowserType.LaunchDefaultPersistentContext(userDataDir2.Path)) + { + var page = await browserContext2.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await page.EvaluateAsync("() => localStorage.hey"), Is.Not.EqualTo("hello")); + } + + userDataDir2.Dispose(); + userDataDir.Dispose(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should restore cookies from userDataDir")] + [SkipBrowserAndPlatformFact(skipChromium: true, skipWindows: true, skipOSX: true)] + public async Task ShouldRestoreCookiesFromUserDataDir() + { + var userDataDir = new TempDirectory(); + + await using (var browserContext = await BrowserType.LaunchDefaultPersistentContext(userDataDir.Path)) + { + var page = await browserContext.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + string documentCookie = await page.EvaluateAsync(@"() => { + document.cookie = 'doSomethingOnlyOnce=true; expires=Fri, 31 Dec 9999 23:59:59 GMT'; + return document.cookie; + }"); + + Assert.That(documentCookie, Is.EqualTo("doSomethingOnlyOnce=true")); + } + + await using (var browserContext2 = await BrowserType.LaunchDefaultPersistentContext(userDataDir.Path)) + { + var page = await browserContext2.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await page.EvaluateAsync("() => document.cookie"), Is.EqualTo("doSomethingOnlyOnce=true")); + } + + var userDataDir2 = new TempDirectory(); + await using (var browserContext2 = await BrowserType.LaunchDefaultPersistentContext(userDataDir2.Path)) + { + var page = await browserContext2.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await page.EvaluateAsync("() => document.cookie"), Is.Not.EqualTo("doSomethingOnlyOnce=true")); + } + + userDataDir2.Dispose(); + userDataDir.Dispose(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should have default URL when launching browser")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHaveDefaultURLWhenLaunchingBrowser() + { + var (tmp, context, page) = await LaunchAsync(); + + string[] urls = context.Pages.Select(p => p.Url).ToArray(); + Assert.That(urls, Is.EqualTo(new[] { "about:blank" })); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should throw if page argument is passed")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldThrowIfPageArgumentIsPassed() + { + var tmp = new TempDirectory(); + Assert.CatchAsync(() => + BrowserType.LaunchDefaultPersistentContext(tmp.Path, new[] { TestConstants.EmptyPage })); + + tmp.Dispose(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should have passed URL when launching with ignoreDefaultArgs: true")] + [Test, Ignore("Skip USES_HOOKS")] + public void ShouldHavePassedURLWhenLaunchingWithIgnoreDefaultArgsTrue() + { + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should handle timeout")] + [Test, Ignore("Skip USES_HOOKS")] + public void ShouldHandleTimeout() + { + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should handle exception")] + [Test, Ignore("Skip USES_HOOKS")] + public void ShouldHandleException() + { + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should fire close event for a persistent context")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFireCloseEventForAPersistentContext() + { + var (tmp, context, _) = await LaunchAsync(); + bool closed = false; + context.Close += (_, _) => closed = true; + await context.CloseAsync(); + + Assert.That(closed, Is.True); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "coverage should work")] + [Test, Ignore("We won't support coverage")] + public void CoverageShouldWork() + { + /* + var (tmp, context, page) = await LaunchAsync(); + + await page.Coverage.StartJSCoverageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/jscoverage/simple.html", LoadState.NetworkIdle); + var coverage = await page.Coverage.StopJSCoverageAsync(); + Assert.That(coverage, Has.Exactly(1).Items); + Assert.That(coverage[0].Url, Does.Contain("/jscoverage/simple.html")); + Assert.That(coverage[0].Functions.Single(f => f.FunctionName == "foo").Ranges[0].Count, Is.EqualTo(1)); + + tmp.Dispose(); + await context.DisposeAsync(); + */ + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "coverage should be missing")] + [Test, Ignore("We won't support coverage")] + public void CoverageShouldBeMissing() + { + /* + var (tmp, context, page) = await LaunchAsync(); + Assert.That(page.Coverage, Is.Null); + tmp.Dispose(); + await context.DisposeAsync(); + */ + } + + [PlaywrightTest("defaultbrowsercontext-2.spec.ts", "should respect selectors")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRespectSelectors() + { + var (tmp, context, page) = await LaunchAsync(); + const string defaultContextCSS = @"({ + create(root, target) {}, + query(root, selector) { + return root.querySelector(selector); + }, + queryAll(root, selector) { + return Array.from(root.querySelectorAll(selector)); + } + })"; + + await TestUtils.RegisterEngineAsync(Playwright, "defaultContextCSS", defaultContextCSS); + await page.SetContentAsync("
hello
"); + Assert.That(await page.InnerHTMLAsync("css=div"), Is.EqualTo("hello")); + Assert.That(await page.InnerHTMLAsync("defaultContextCSS=div"), Is.EqualTo("hello")); + + tmp.Dispose(); + await context.DisposeAsync(); + } + + private async Task<(TempDirectory tmp, IBrowserContext context, IPage page)> LaunchAsync(BrowserContextOptions options = null) + { + var tmp = new TempDirectory(); + var context = await BrowserType.LaunchDefaultPersistentContext(tmp.Path, null, options); + var page = context.Pages.First(); + + return (tmp, context, page); + } + } +} diff --git a/src/Playwright.Tests/DownloadTests.cs b/src/PlaywrightSharp.Tests/DownloadTests.cs similarity index 74% rename from src/Playwright.Tests/DownloadTests.cs rename to src/PlaywrightSharp.Tests/DownloadTests.cs index 7e938e314d..82c3dcf159 100644 --- a/src/Playwright.Tests/DownloadTests.cs +++ b/src/PlaywrightSharp.Tests/DownloadTests.cs @@ -1,453 +1,451 @@ -using System.IO; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Microsoft.Playwright.Tests.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///download.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class DownloadTests : PlaywrightSharpPageBaseTest - { - /// - public DownloadTests(ITestOutputHelper output) : base(output) - { - Server.SetRoute("/download", context => - { - context.Response.Headers["Content-Type"] = "application/octet-stream"; - context.Response.Headers["Content-Disposition"] = "attachment"; - return context.Response.WriteAsync("Hello world"); - }); - - Server.SetRoute("/downloadWithFilename", context => - { - context.Response.Headers["Content-Type"] = "application/octet-stream"; - context.Response.Headers["Content-Disposition"] = "attachment; filename=file.txt"; - return context.Response.WriteAsync("Hello world"); - }); - } - - [PlaywrightTest("download.spec.ts", "should report downloads with acceptDownloads: false")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReportDownloadsWithAcceptDownloadsFalse() - { - await Page.SetContentAsync($"download"); - var downloadTask = Page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - Page.ClickAsync("a")); - - var download = downloadTask.Result; - Assert.Equal($"{TestConstants.ServerUrl}/downloadWithFilename", download.Url); - Assert.Equal("file.txt", download.SuggestedFilename); - - var exception = await Assert.ThrowsAnyAsync(() => download.PathAsync()); - Assert.Contains("acceptDownloads", await download.FailureAsync()); - Assert.Contains("acceptDownloads: true", exception.Message); - } - - [PlaywrightTest("download.spec.ts", "should report downloads with acceptDownloads: true")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReportDownloadsWithAcceptDownloadsTrue() - { - var page = await Browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - var download = downloadTask.Result; - string path = await download.PathAsync(); - - Assert.True(new FileInfo(path).Exists); - Assert.Equal("Hello world", File.ReadAllText(path)); - } - - [PlaywrightTest("download.spec.ts", "should save to user-specified path")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSaveToUserSpecifiedPath() - { - var page = await Browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - using var tmpDir = new TempDirectory(); - string userPath = Path.Combine(tmpDir.Path, "download.txt"); - var download = downloadTask.Result; - await download.SaveAsAsync(userPath); - - Assert.True(new FileInfo(userPath).Exists); - Assert.Equal("Hello world", File.ReadAllText(userPath)); - await page.CloseAsync(); - } - - [PlaywrightTest("download.spec.ts", "should save to user-specified path without updating original path")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSaveToUserSpecifiedPathWithoutUpdatingOriginalPath() - { - var page = await Browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - using var tmpDir = new TempDirectory(); - string userPath = Path.Combine(tmpDir.Path, "download.txt"); - var download = downloadTask.Result; - await download.SaveAsAsync(userPath); - - Assert.True(new FileInfo(userPath).Exists); - Assert.Equal("Hello world", File.ReadAllText(userPath)); - - string originalPath = await download.PathAsync(); - Assert.True(new FileInfo(originalPath).Exists); - Assert.Equal("Hello world", File.ReadAllText(originalPath)); - - await page.CloseAsync(); - } - - [PlaywrightTest("download.spec.ts", "should save to two different paths with multiple saveAs calls")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSaveToTwoDifferentPathsWithMultipleSaveAsCalls() - { - var page = await Browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - using var tmpDir = new TempDirectory(); - string userPath = Path.Combine(tmpDir.Path, "download.txt"); - var download = downloadTask.Result; - await download.SaveAsAsync(userPath); - Assert.True(new FileInfo(userPath).Exists); - Assert.Equal("Hello world", File.ReadAllText(userPath)); - - string anotherUserPath = Path.Combine(tmpDir.Path, "download (2).txt"); - await download.SaveAsAsync(anotherUserPath); - Assert.True(new FileInfo(anotherUserPath).Exists); - Assert.Equal("Hello world", File.ReadAllText(anotherUserPath)); - - await page.CloseAsync(); - } - - [PlaywrightTest("download.spec.ts", "should save to overwritten filepath")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSaveToOverwrittenFilepath() - { - var page = await Browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - using var tmpDir = new TempDirectory(); - string userPath = Path.Combine(tmpDir.Path, "download.txt"); - var download = downloadTask.Result; - await download.SaveAsAsync(userPath); - Assert.Single(new DirectoryInfo(tmpDir.Path).GetFiles()); - await download.SaveAsAsync(userPath); - Assert.Single(new DirectoryInfo(tmpDir.Path).GetFiles()); - - await page.CloseAsync(); - } - - [PlaywrightTest("download.spec.ts", "should create subdirectories when saving to non-existent user-specified path")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCreateSubdirectoriesWhenSavingToNonExistentUserSpecifiedPath() - { - var page = await Browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - using var tmpDir = new TempDirectory(); - string userPath = Path.Combine(tmpDir.Path, "these", "are", "directories", "download.txt"); - var download = downloadTask.Result; - await download.SaveAsAsync(userPath); - Assert.True(new FileInfo(userPath).Exists); - Assert.Equal("Hello world", File.ReadAllText(userPath)); - - await page.CloseAsync(); - } - - [PlaywrightTest("download.spec.ts", "should save when connected remotely")] - [Fact(Skip = "SKIP WIRE")] - public void ShouldSaveWhenConnectedRemotely() - { - } - - [PlaywrightTest("download.spec.ts", "should error when saving with downloads disabled")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldErrorWhenSavingWithDownloadsDisabled() - { - var page = await Browser.NewPageAsync(acceptDownloads: false); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - using var tmpDir = new TempDirectory(); - string userPath = Path.Combine(tmpDir.Path, "download.txt"); - var download = downloadTask.Result; - - var exception = await Assert.ThrowsAnyAsync(() => download.SaveAsAsync(userPath)); - Assert.Contains("Pass { acceptDownloads: true } when you are creating your browser context", exception.Message); - } - - [PlaywrightTest("download.spec.ts", "should error when saving after deletion")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldErrorWhenSavingAfterDeletion() - { - var page = await Browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - using var tmpDir = new TempDirectory(); - string userPath = Path.Combine(tmpDir.Path, "download.txt"); - var download = downloadTask.Result; - await download.DeleteAsync(); - var exception = await Assert.ThrowsAnyAsync(() => download.SaveAsAsync(userPath)); - Assert.Contains("Download already deleted. Save before deleting.", exception.Message); - } - - [PlaywrightTest("download.spec.ts", "should error when saving after deletion when connected remotely")] - [Fact(Skip = "SKIP WIRE")] - public void ShouldErrorWhenSavingAfterDeletionWhenConnectedRemotely() - { - } - - [PlaywrightTest("download.spec.ts", "should report non-navigation downloads")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReportNonNavigationDownloads() - { - Server.SetRoute("/download", context => - { - context.Response.Headers["Content-Type"] = "application/octet-stream"; - return context.Response.WriteAsync("Hello world"); - }); - - var page = await Browser.NewPageAsync(acceptDownloads: true); - await page.GoToAsync(TestConstants.EmptyPage); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - var download = downloadTask.Result; - Assert.Equal("file.txt", download.SuggestedFilename); - string path = await download.PathAsync(); - - Assert.True(new FileInfo(path).Exists); - Assert.Equal("Hello world", File.ReadAllText(path)); - await page.CloseAsync(); - } - - [PlaywrightTest("download.spec.ts", "should report download path within page.on('download', …) handler for Files")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReportDownloadPathWithinPageOnDownloadHandlerForFiles() - { - var downloadPathTcs = new TaskCompletionSource(); - var page = await Browser.NewPageAsync(acceptDownloads: true); - page.Download += async (_, e) => - { - downloadPathTcs.TrySetResult(await e.PathAsync()); - }; - - await page.SetContentAsync($"download"); - await page.ClickAsync("a"); - string path = await downloadPathTcs.Task; - - Assert.Equal("Hello world", File.ReadAllText(path)); - await page.CloseAsync(); - } - - [PlaywrightTest("download.spec.ts", "should report download path within page.on('download', …) handler for Blobs")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReportDownloadPathWithinPageOnDownloadHandlerForBlobs() - { - var downloadPathTcs = new TaskCompletionSource(); - var page = await Browser.NewPageAsync(acceptDownloads: true); - page.Download += async (_, e) => - { - downloadPathTcs.TrySetResult(await e.PathAsync()); - }; - - await page.GoToAsync(TestConstants.ServerUrl + "/download-blob.html"); - await page.ClickAsync("a"); - string path = await downloadPathTcs.Task; - - Assert.Equal("Hello world", File.ReadAllText(path)); - await page.CloseAsync(); - } - - [PlaywrightTest("download.spec.ts", "should report alt-click downloads")] - [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] - public async Task ShouldReportAltClickDownloads() - { - Server.SetRoute("/download", context => - { - context.Response.Headers["Content-Type"] = "application/octet-stream"; - return context.Response.WriteAsync("Hello world"); - }); - - var page = await Browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a", modifiers: new[] { KeyboardModifier.Alt })); - - var download = downloadTask.Result; - string path = await download.PathAsync(); - - Assert.True(new FileInfo(path).Exists); - Assert.Equal("Hello world", File.ReadAllText(path)); - } - - [PlaywrightTest("download.spec.ts", "should report new window downloads")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReportNewWindowDownloads() - { - var page = await Browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - var download = downloadTask.Result; - string path = await download.PathAsync(); - - Assert.True(new FileInfo(path).Exists); - Assert.Equal("Hello world", File.ReadAllText(path)); - } - - [PlaywrightTest("download.spec.ts", "should delete file")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDeleteFile() - { - var page = await Browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - var download = downloadTask.Result; - string path = await download.PathAsync(); - - Assert.True(new FileInfo(path).Exists); - await download.DeleteAsync(); - Assert.False(new FileInfo(path).Exists); - await page.CloseAsync(); - } - - [PlaywrightTest("download.spec.ts", "should expose stream")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldExposeStream() - { - var page = await Browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - var download = downloadTask.Result; - using var stream = await download.CreateReadStreamAsync(); - Assert.Equal("Hello world", await new StreamReader(stream).ReadToEndAsync()); - - await page.CloseAsync(); - } - - [PlaywrightTest("download.spec.ts", "should delete downloads on context destruction")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDeleteDownloadsOnContextDestruction() - { - var page = await Browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var download1Task = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - download1Task, - page.ClickAsync("a")); - - var download2Task = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - download2Task, - page.ClickAsync("a")); - - string path1 = await download1Task.Result.PathAsync(); - string path2 = await download2Task.Result.PathAsync(); - Assert.True(new FileInfo(path1).Exists); - Assert.True(new FileInfo(path2).Exists); - await page.Context.CloseAsync(); - Assert.False(new FileInfo(path1).Exists); - Assert.False(new FileInfo(path2).Exists); - } - - [PlaywrightTest("download.spec.ts", "should delete downloads on browser gone")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDeleteDownloadsOnBrowserGone() - { - var browser = await BrowserType.LaunchDefaultAsync(); - var page = await browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var download1Task = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - download1Task, - page.ClickAsync("a")); - - var download2Task = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - download2Task, - page.ClickAsync("a")); - - string path1 = await download1Task.Result.PathAsync(); - string path2 = await download2Task.Result.PathAsync(); - Assert.True(new FileInfo(path1).Exists); - Assert.True(new FileInfo(path2).Exists); - await browser.CloseAsync(); - Assert.False(new FileInfo(path1).Exists); - Assert.False(new FileInfo(path2).Exists); - Assert.False(new FileInfo(Path.Combine(path1, "..")).Exists); - } - } -} +using System.IO; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; +using PlaywrightSharp.Tests.Helpers; + +namespace PlaywrightSharp.Tests +{ + ///download.spec.ts + public class DownloadTests : PlaywrightSharpPageBaseTest + { + [SetUp] + public void DownloadSetUp() + { + Server.SetRoute("/download", context => + { + context.Response.Headers["Content-Type"] = "application/octet-stream"; + context.Response.Headers["Content-Disposition"] = "attachment"; + return context.Response.WriteAsync("Hello world"); + }); + + Server.SetRoute("/downloadWithFilename", context => + { + context.Response.Headers["Content-Type"] = "application/octet-stream"; + context.Response.Headers["Content-Disposition"] = "attachment; filename=file.txt"; + return context.Response.WriteAsync("Hello world"); + }); + } + + [PlaywrightTest("download.spec.ts", "should report downloads with acceptDownloads: false")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReportDownloadsWithAcceptDownloadsFalse() + { + await Page.SetContentAsync($"download"); + var downloadTask = Page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + Page.ClickAsync("a")); + + var download = downloadTask.Result; + Assert.That(download.Url, Is.EqualTo($"{TestConstants.ServerUrl}/downloadWithFilename")); + Assert.That(download.SuggestedFilename, Is.EqualTo("file.txt")); + + var exception = Assert.CatchAsync(() => download.PathAsync()); + Assert.That(await download.FailureAsync(), Does.Contain("acceptDownloads")); + Assert.That(exception.Message, Does.Contain("acceptDownloads: true")); + } + + [PlaywrightTest("download.spec.ts", "should report downloads with acceptDownloads: true")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReportDownloadsWithAcceptDownloadsTrue() + { + var page = await Browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + var download = downloadTask.Result; + string path = await download.PathAsync(); + + Assert.That(new FileInfo(path).Exists, Is.True); + Assert.That(File.ReadAllText(path), Is.EqualTo("Hello world")); + } + + [PlaywrightTest("download.spec.ts", "should save to user-specified path")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSaveToUserSpecifiedPath() + { + var page = await Browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + using var tmpDir = new TempDirectory(); + string userPath = Path.Combine(tmpDir.Path, "download.txt"); + var download = downloadTask.Result; + await download.SaveAsAsync(userPath); + + Assert.That(new FileInfo(userPath).Exists, Is.True); + Assert.That(File.ReadAllText(userPath), Is.EqualTo("Hello world")); + await page.CloseAsync(); + } + + [PlaywrightTest("download.spec.ts", "should save to user-specified path without updating original path")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSaveToUserSpecifiedPathWithoutUpdatingOriginalPath() + { + var page = await Browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + using var tmpDir = new TempDirectory(); + string userPath = Path.Combine(tmpDir.Path, "download.txt"); + var download = downloadTask.Result; + await download.SaveAsAsync(userPath); + + Assert.That(new FileInfo(userPath).Exists, Is.True); + Assert.That(File.ReadAllText(userPath), Is.EqualTo("Hello world")); + + string originalPath = await download.PathAsync(); + Assert.That(new FileInfo(originalPath).Exists, Is.True); + Assert.That(File.ReadAllText(originalPath), Is.EqualTo("Hello world")); + + await page.CloseAsync(); + } + + [PlaywrightTest("download.spec.ts", "should save to two different paths with multiple saveAs calls")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSaveToTwoDifferentPathsWithMultipleSaveAsCalls() + { + var page = await Browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + using var tmpDir = new TempDirectory(); + string userPath = Path.Combine(tmpDir.Path, "download.txt"); + var download = downloadTask.Result; + await download.SaveAsAsync(userPath); + Assert.That(new FileInfo(userPath).Exists, Is.True); + Assert.That(File.ReadAllText(userPath), Is.EqualTo("Hello world")); + + string anotherUserPath = Path.Combine(tmpDir.Path, "download (2).txt"); + await download.SaveAsAsync(anotherUserPath); + Assert.That(new FileInfo(anotherUserPath).Exists, Is.True); + Assert.That(File.ReadAllText(anotherUserPath), Is.EqualTo("Hello world")); + + await page.CloseAsync(); + } + + [PlaywrightTest("download.spec.ts", "should save to overwritten filepath")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSaveToOverwrittenFilepath() + { + var page = await Browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + using var tmpDir = new TempDirectory(); + string userPath = Path.Combine(tmpDir.Path, "download.txt"); + var download = downloadTask.Result; + await download.SaveAsAsync(userPath); + Assert.That(new DirectoryInfo(tmpDir.Path).GetFiles(), Has.Exactly(1).Items); + await download.SaveAsAsync(userPath); + Assert.That(new DirectoryInfo(tmpDir.Path).GetFiles(), Has.Exactly(1).Items); + + await page.CloseAsync(); + } + + [PlaywrightTest("download.spec.ts", "should create subdirectories when saving to non-existent user-specified path")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCreateSubdirectoriesWhenSavingToNonExistentUserSpecifiedPath() + { + var page = await Browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + using var tmpDir = new TempDirectory(); + string userPath = Path.Combine(tmpDir.Path, "these", "are", "directories", "download.txt"); + var download = downloadTask.Result; + await download.SaveAsAsync(userPath); + Assert.That(new FileInfo(userPath).Exists, Is.True); + Assert.That(File.ReadAllText(userPath), Is.EqualTo("Hello world")); + + await page.CloseAsync(); + } + + [PlaywrightTest("download.spec.ts", "should save when connected remotely")] + [Test, Ignore("SKIP WIRE")] + public void ShouldSaveWhenConnectedRemotely() + { + } + + [PlaywrightTest("download.spec.ts", "should error when saving with downloads disabled")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldErrorWhenSavingWithDownloadsDisabled() + { + var page = await Browser.NewPageAsync(acceptDownloads: false); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + using var tmpDir = new TempDirectory(); + string userPath = Path.Combine(tmpDir.Path, "download.txt"); + var download = downloadTask.Result; + + var exception = Assert.CatchAsync(() => download.SaveAsAsync(userPath)); + Assert.That(exception.Message, Does.Contain("Pass { acceptDownloads: true } when you are creating your browser context")); + } + + [PlaywrightTest("download.spec.ts", "should error when saving after deletion")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldErrorWhenSavingAfterDeletion() + { + var page = await Browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + using var tmpDir = new TempDirectory(); + string userPath = Path.Combine(tmpDir.Path, "download.txt"); + var download = downloadTask.Result; + await download.DeleteAsync(); + var exception = Assert.CatchAsync(() => download.SaveAsAsync(userPath)); + Assert.That(exception.Message, Does.Contain("Download already deleted. Save before deleting.")); + } + + [PlaywrightTest("download.spec.ts", "should error when saving after deletion when connected remotely")] + [Test, Ignore("SKIP WIRE")] + public void ShouldErrorWhenSavingAfterDeletionWhenConnectedRemotely() + { + } + + [PlaywrightTest("download.spec.ts", "should report non-navigation downloads")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReportNonNavigationDownloads() + { + Server.SetRoute("/download", context => + { + context.Response.Headers["Content-Type"] = "application/octet-stream"; + return context.Response.WriteAsync("Hello world"); + }); + + var page = await Browser.NewPageAsync(acceptDownloads: true); + await page.GoToAsync(TestConstants.EmptyPage); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + var download = downloadTask.Result; + Assert.That(download.SuggestedFilename, Is.EqualTo("file.txt")); + string path = await download.PathAsync(); + + Assert.That(new FileInfo(path).Exists, Is.True); + Assert.That(File.ReadAllText(path), Is.EqualTo("Hello world")); + await page.CloseAsync(); + } + + [PlaywrightTest("download.spec.ts", "should report download path within page.on('download', …) handler for Files")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReportDownloadPathWithinPageOnDownloadHandlerForFiles() + { + var downloadPathTcs = new TaskCompletionSource(); + var page = await Browser.NewPageAsync(acceptDownloads: true); + page.Download += async (_, e) => + { + downloadPathTcs.TrySetResult(await e.PathAsync()); + }; + + await page.SetContentAsync($"download"); + await page.ClickAsync("a"); + string path = await downloadPathTcs.Task; + + Assert.That(File.ReadAllText(path), Is.EqualTo("Hello world")); + await page.CloseAsync(); + } + + [PlaywrightTest("download.spec.ts", "should report download path within page.on('download', …) handler for Blobs")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReportDownloadPathWithinPageOnDownloadHandlerForBlobs() + { + var downloadPathTcs = new TaskCompletionSource(); + var page = await Browser.NewPageAsync(acceptDownloads: true); + page.Download += async (_, e) => + { + downloadPathTcs.TrySetResult(await e.PathAsync()); + }; + + await page.GoToAsync(TestConstants.ServerUrl + "/download-blob.html"); + await page.ClickAsync("a"); + string path = await downloadPathTcs.Task; + + Assert.That(File.ReadAllText(path), Is.EqualTo("Hello world")); + await page.CloseAsync(); + } + + [PlaywrightTest("download.spec.ts", "should report alt-click downloads")] + [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] + public async Task ShouldReportAltClickDownloads() + { + Server.SetRoute("/download", context => + { + context.Response.Headers["Content-Type"] = "application/octet-stream"; + return context.Response.WriteAsync("Hello world"); + }); + + var page = await Browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a", modifiers: new[] { KeyboardModifier.Alt })); + + var download = downloadTask.Result; + string path = await download.PathAsync(); + + Assert.That(new FileInfo(path).Exists, Is.True); + Assert.That(File.ReadAllText(path), Is.EqualTo("Hello world")); + } + + [PlaywrightTest("download.spec.ts", "should report new window downloads")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReportNewWindowDownloads() + { + var page = await Browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + var download = downloadTask.Result; + string path = await download.PathAsync(); + + Assert.That(new FileInfo(path).Exists, Is.True); + Assert.That(File.ReadAllText(path), Is.EqualTo("Hello world")); + } + + [PlaywrightTest("download.spec.ts", "should delete file")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDeleteFile() + { + var page = await Browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + var download = downloadTask.Result; + string path = await download.PathAsync(); + + Assert.That(new FileInfo(path).Exists, Is.True); + await download.DeleteAsync(); + Assert.That(new FileInfo(path).Exists, Is.False); + await page.CloseAsync(); + } + + [PlaywrightTest("download.spec.ts", "should expose stream")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldExposeStream() + { + var page = await Browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + var download = downloadTask.Result; + using var stream = await download.CreateReadStreamAsync(); + Assert.That(await new StreamReader(stream).ReadToEndAsync(), Is.EqualTo("Hello world")); + + await page.CloseAsync(); + } + + [PlaywrightTest("download.spec.ts", "should delete downloads on context destruction")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDeleteDownloadsOnContextDestruction() + { + var page = await Browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var download1Task = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + download1Task, + page.ClickAsync("a")); + + var download2Task = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + download2Task, + page.ClickAsync("a")); + + string path1 = await download1Task.Result.PathAsync(); + string path2 = await download2Task.Result.PathAsync(); + Assert.That(new FileInfo(path1).Exists, Is.True); + Assert.That(new FileInfo(path2).Exists, Is.True); + await page.Context.CloseAsync(); + Assert.That(new FileInfo(path1).Exists, Is.False); + Assert.That(new FileInfo(path2).Exists, Is.False); + } + + [PlaywrightTest("download.spec.ts", "should delete downloads on browser gone")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDeleteDownloadsOnBrowserGone() + { + var browser = await BrowserType.LaunchDefaultAsync(); + var page = await browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var download1Task = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + download1Task, + page.ClickAsync("a")); + + var download2Task = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + download2Task, + page.ClickAsync("a")); + + string path1 = await download1Task.Result.PathAsync(); + string path2 = await download2Task.Result.PathAsync(); + Assert.That(new FileInfo(path1).Exists, Is.True); + Assert.That(new FileInfo(path2).Exists, Is.True); + await browser.CloseAsync(); + Assert.That(new FileInfo(path1).Exists, Is.False); + Assert.That(new FileInfo(path2).Exists, Is.False); + Assert.That(new FileInfo(Path.Combine(path1, "..")).Exists, Is.False); + } + } +} diff --git a/src/Playwright.Tests/DownloadsPathTests.cs b/src/PlaywrightSharp.Tests/DownloadsPathTests.cs similarity index 69% rename from src/Playwright.Tests/DownloadsPathTests.cs rename to src/PlaywrightSharp.Tests/DownloadsPathTests.cs index 68b77ba34c..a5fb0d068a 100644 --- a/src/Playwright.Tests/DownloadsPathTests.cs +++ b/src/PlaywrightSharp.Tests/DownloadsPathTests.cs @@ -1,104 +1,100 @@ -using System.IO; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Microsoft.Playwright.Tests.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class DownloadsPathTests : PlaywrightSharpBaseTest, IAsyncLifetime - { - private IBrowser _browser { get; set; } - private TempDirectory _tmp = null; - - /// - public DownloadsPathTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("downloads-path.spec.ts", "should keep downloadsPath folder")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldKeepDownloadsPathFolder() - { - var page = await _browser.NewPageAsync(); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - var download = downloadTask.Result; - Assert.Equal($"{TestConstants.ServerUrl}/download", download.Url); - Assert.Equal("file.txt", download.SuggestedFilename); - - var exception = await Assert.ThrowsAnyAsync(() => download.PathAsync()); - - await page.CloseAsync(); - await _browser.CloseAsync(); - Assert.True(new DirectoryInfo(_tmp.Path).Exists); - } - - [PlaywrightTest("downloads-path.spec.ts", "should delete downloads when context closes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDeleteDownloadsWhenContextCloses() - { - var page = await _browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - var download = downloadTask.Result; - string path = await download.PathAsync(); - Assert.True(new FileInfo(path).Exists); - await page.CloseAsync(); - Assert.False(new FileInfo(path).Exists); - } - - [PlaywrightTest("downloads-path.spec.ts", "should report downloads in downloadsPath folder")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReportDownloadsInDownloadsPathFolder() - { - var page = await _browser.NewPageAsync(acceptDownloads: true); - await page.SetContentAsync($"download"); - var downloadTask = page.WaitForEventAsync(PageEvent.Download); - - await TaskUtils.WhenAll( - downloadTask, - page.ClickAsync("a")); - - var download = downloadTask.Result; - string path = await download.PathAsync(); - Assert.StartsWith(_tmp.Path, path); - await page.CloseAsync(); - } - - /// - public async Task InitializeAsync() - { - Server.SetRoute("/download", context => - { - context.Response.Headers["Content-Type"] = "application/octet-stream"; - context.Response.Headers["Content-Disposition"] = "attachment; filename=file.txt"; - return context.Response.WriteAsync("Hello world"); - }); - - _tmp = new TempDirectory(); - _browser = await Playwright[TestConstants.Product].LaunchDefaultAsync(downloadsPath: _tmp.Path); - } - - /// - public async Task DisposeAsync() - { - _tmp?.Dispose(); - await _browser.CloseAsync(); - } - } -} +using System.IO; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; +using PlaywrightSharp.Tests.Helpers; + +namespace PlaywrightSharp.Tests +{ + public class DownloadsPathTests : PlaywrightSharpBaseTest + { + private IBrowser _browser { get; set; } + private TempDirectory _tmp = null; + + [SetUp] + public async Task InitializeAsync() + { + Server.SetRoute("/download", context => + { + context.Response.Headers["Content-Type"] = "application/octet-stream"; + context.Response.Headers["Content-Disposition"] = "attachment; filename=file.txt"; + return context.Response.WriteAsync("Hello world"); + }); + + _tmp = new TempDirectory(); + _browser = await Playwright[TestConstants.Product].LaunchDefaultAsync(downloadsPath: _tmp.Path).ConfigureAwait(false); + } + + [TearDown] + public async Task DisposeAsync() + { + _tmp?.Dispose(); + if (_browser != null) + { + await _browser.CloseAsync().ConfigureAwait(false); + } + } + + [PlaywrightTest("downloads-path.spec.ts", "should keep downloadsPath folder")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldKeepDownloadsPathFolder() + { + var page = await _browser.NewPageAsync(); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + var download = downloadTask.Result; + Assert.That(download.Url, Is.EqualTo($"{TestConstants.ServerUrl}/download")); + Assert.That(download.SuggestedFilename, Is.EqualTo("file.txt")); + + var exception = Assert.CatchAsync(() => download.PathAsync()); + + await page.CloseAsync(); + await _browser.CloseAsync(); + Assert.That(new DirectoryInfo(_tmp.Path).Exists, Is.True); + } + + [PlaywrightTest("downloads-path.spec.ts", "should delete downloads when context closes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDeleteDownloadsWhenContextCloses() + { + var page = await _browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + var download = downloadTask.Result; + string path = await download.PathAsync(); + Assert.That(new FileInfo(path).Exists, Is.True); + await page.CloseAsync(); + Assert.That(new FileInfo(path).Exists, Is.False); + } + + [PlaywrightTest("downloads-path.spec.ts", "should report downloads in downloadsPath folder")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReportDownloadsInDownloadsPathFolder() + { + var page = await _browser.NewPageAsync(acceptDownloads: true); + await page.SetContentAsync($"download"); + var downloadTask = page.WaitForEventAsync(PageEvent.Download); + + await TaskUtils.WhenAll( + downloadTask, + page.ClickAsync("a")); + + var download = downloadTask.Result; + string path = await download.PathAsync(); + Assert.That(path, Does.StartWith(_tmp.Path)); + await page.CloseAsync(); + } + } +} diff --git a/src/Playwright.Tests/ElementHandleBoundingBoxTests.cs b/src/PlaywrightSharp.Tests/ElementHandleBoundingBoxTests.cs similarity index 72% rename from src/Playwright.Tests/ElementHandleBoundingBoxTests.cs rename to src/PlaywrightSharp.Tests/ElementHandleBoundingBoxTests.cs index 24ce86d282..221bd466ec 100644 --- a/src/Playwright.Tests/ElementHandleBoundingBoxTests.cs +++ b/src/PlaywrightSharp.Tests/ElementHandleBoundingBoxTests.cs @@ -1,144 +1,137 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ElementHandleBoundingBoxTests : PlaywrightSharpPageBaseTest - { - /// - public ElementHandleBoundingBoxTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - var elementHandle = await Page.QuerySelectorAsync(".box:nth-of-type(13)"); - var box = await elementHandle.BoundingBoxAsync(); - Assert.Equal(new ElementHandleBoundingBoxResult(x: 100, y: 50, width: 50, height: 50), box); - } - - [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should handle nested frames")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHandleNestedFrames() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/frames/nested-frames.html"); - var nestedFrame = Page.Frames.First(frame => frame.Name == "dos"); - var elementHandle = await nestedFrame.QuerySelectorAsync("div"); - var box = await elementHandle.BoundingBoxAsync(); - Assert.Equal(new ElementHandleBoundingBoxResult(x: 24, y: 224, width: 268, height: 18), box); - } - - [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should return null for invisible elements")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnNullForInvisibleElements() - { - await Page.SetContentAsync("
hi
"); - var element = await Page.QuerySelectorAsync("div"); - Assert.Null(await element.BoundingBoxAsync()); - } - - [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should force a layout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldForceALayout() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.SetContentAsync("
hello
"); - var elementHandle = await Page.QuerySelectorAsync("div"); - await Page.EvaluateAsync("element => element.style.height = '200px'", elementHandle); - var box = await elementHandle.BoundingBoxAsync(); - Assert.Equal(new ElementHandleBoundingBoxResult(x: 8, y: 8, width: 100, height: 200), box); - } - - [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should work with SVG nodes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithSVGNodes() - { - await Page.SetContentAsync(@" - - - "); - var element = await Page.QuerySelectorAsync("#therect"); - var pwBoundingBox = await element.BoundingBoxAsync(); - var webBoundingBox = await Page.EvaluateAsync(@"e => { - const rect = e.getBoundingClientRect(); - return { x: rect.x, y: rect.y, width: rect.width, height: rect.height}; - }", element); - Assert.Equal(webBoundingBox, pwBoundingBox); - } - - [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should work with page scale")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWorkWithPageScale() - { - var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Height = 400, - Width = 400, - }, - IsMobile = true, - }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - var button = await page.QuerySelectorAsync("button"); - - await button.EvaluateAsync(@"button => { - document.body.style.margin = '0'; - button.style.borderWidth = '0'; - button.style.width = '200px'; - button.style.height = '20px'; - button.style.marginLeft = '17px'; - button.style.marginTop = '23px'; - }"); - - var box = await button.BoundingBoxAsync(); - Assert.Equal(17 * 100, Math.Round(box.X * 100)); - Assert.Equal(23 * 100, Math.Round(box.Y * 100)); - Assert.Equal(200 * 100, Math.Round(box.Width * 100)); - Assert.Equal(20 * 100, Math.Round(box.Height * 100)); - } - - [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should work when inline box child is outside of viewport")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWhenInlineBoxChildIsOutsideOfViewport() - { - await Page.SetContentAsync(@" - - woofdoggo"); - - var handle = await Page.QuerySelectorAsync("span"); - var box = await handle.BoundingBoxAsync(); - var webBoundingBox = await Page.EvaluateAsync(@"e => { - const rect = e.getBoundingClientRect(); - return { x: rect.x, y: rect.y, width: rect.width, height: rect.height}; - }", handle); - - Assert.Equal(Math.Round(webBoundingBox.X * 100), Math.Round(box.X * 100)); - Assert.Equal(Math.Round(webBoundingBox.Y * 100), Math.Round(box.Y * 100)); - Assert.Equal(Math.Round(webBoundingBox.Width * 100), Math.Round(box.Width * 100)); - Assert.Equal(Math.Round(webBoundingBox.Height * 100), Math.Round(box.Height * 100)); - } - } -} +using System; +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class ElementHandleBoundingBoxTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + var elementHandle = await Page.QuerySelectorAsync(".box:nth-of-type(13)"); + var box = await elementHandle.BoundingBoxAsync(); + Assert.That(box, Is.EqualTo(new ElementHandleBoundingBoxResult(x: 100, y: 50, width: 50, height: 50))); + } + + [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should handle nested frames")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHandleNestedFrames() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/frames/nested-frames.html"); + var nestedFrame = Page.Frames.First(frame => frame.Name == "dos"); + var elementHandle = await nestedFrame.QuerySelectorAsync("div"); + var box = await elementHandle.BoundingBoxAsync(); + Assert.That(box, Is.EqualTo(new ElementHandleBoundingBoxResult(x: 24, y: 224, width: 268, height: 18))); + } + + [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should return null for invisible elements")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnNullForInvisibleElements() + { + await Page.SetContentAsync("
hi
"); + var element = await Page.QuerySelectorAsync("div"); + Assert.That(await element.BoundingBoxAsync(), Is.Null); + } + + [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should force a layout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldForceALayout() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.SetContentAsync("
hello
"); + var elementHandle = await Page.QuerySelectorAsync("div"); + await Page.EvaluateAsync("element => element.style.height = '200px'", elementHandle); + var box = await elementHandle.BoundingBoxAsync(); + Assert.That(box, Is.EqualTo(new ElementHandleBoundingBoxResult(x: 8, y: 8, width: 100, height: 200))); + } + + [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should work with SVG nodes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithSVGNodes() + { + await Page.SetContentAsync(@" + + + "); + var element = await Page.QuerySelectorAsync("#therect"); + var pwBoundingBox = await element.BoundingBoxAsync(); + var webBoundingBox = await Page.EvaluateAsync(@"e => { + const rect = e.getBoundingClientRect(); + return { x: rect.x, y: rect.y, width: rect.width, height: rect.height}; + }", element); + Assert.That(pwBoundingBox, Is.EqualTo(webBoundingBox)); + } + + [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should work with page scale")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWorkWithPageScale() + { + var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Height = 400, + Width = 400, + }, + IsMobile = true, + }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + var button = await page.QuerySelectorAsync("button"); + + await button.EvaluateAsync(@"button => { + document.body.style.margin = '0'; + button.style.borderWidth = '0'; + button.style.width = '200px'; + button.style.height = '20px'; + button.style.marginLeft = '17px'; + button.style.marginTop = '23px'; + }"); + + var box = await button.BoundingBoxAsync(); + Assert.That(Math.Round(box.X * 100), Is.EqualTo(17 * 100)); + Assert.That(Math.Round(box.Y * 100), Is.EqualTo(23 * 100)); + Assert.That(Math.Round(box.Width * 100), Is.EqualTo(200 * 100)); + Assert.That(Math.Round(box.Height * 100), Is.EqualTo(20 * 100)); + } + + [PlaywrightTest("elementhandle-bounding-box.spec.ts", "should work when inline box child is outside of viewport")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWhenInlineBoxChildIsOutsideOfViewport() + { + await Page.SetContentAsync(@" + + woofdoggo"); + + var handle = await Page.QuerySelectorAsync("span"); + var box = await handle.BoundingBoxAsync(); + var webBoundingBox = await Page.EvaluateAsync(@"e => { + const rect = e.getBoundingClientRect(); + return { x: rect.x, y: rect.y, width: rect.width, height: rect.height}; + }", handle); + + Assert.That(Math.Round(box.X * 100), Is.EqualTo(Math.Round(webBoundingBox.X * 100))); + Assert.That(Math.Round(box.Y * 100), Is.EqualTo(Math.Round(webBoundingBox.Y * 100))); + Assert.That(Math.Round(box.Width * 100), Is.EqualTo(Math.Round(webBoundingBox.Width * 100))); + Assert.That(Math.Round(box.Height * 100), Is.EqualTo(Math.Round(webBoundingBox.Height * 100))); + } + } +} diff --git a/src/Playwright.Tests/ElementHandleClickTests.cs b/src/PlaywrightSharp.Tests/ElementHandleClickTests.cs similarity index 64% rename from src/Playwright.Tests/ElementHandleClickTests.cs rename to src/PlaywrightSharp.Tests/ElementHandleClickTests.cs index 1740ce39a1..ba7dc08c4d 100644 --- a/src/Playwright.Tests/ElementHandleClickTests.cs +++ b/src/PlaywrightSharp.Tests/ElementHandleClickTests.cs @@ -1,121 +1,114 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ElementHandleClickTests : PlaywrightSharpPageBaseTest - { - /// - public ElementHandleClickTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("elementhandle-click.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - var button = await Page.QuerySelectorAsync("button"); - await button.ClickAsync(); - Assert.Equal("Clicked", await Page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("elementhandle-click.spec.ts", "should work with Node removed")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithNodeRemoved() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvaluateAsync("() => delete window['Node']"); - var button = await Page.QuerySelectorAsync("button"); - await button.ClickAsync(); - Assert.Equal("Clicked", await Page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("elementhandle-click.spec.ts", "should work for Shadow DOM v1")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForShadowDOMV1() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/shadow.html"); - var buttonHandle = (IElementHandle)await Page.EvaluateHandleAsync("() => button"); - await buttonHandle.ClickAsync(); - Assert.True(await Page.EvaluateAsync("() => clicked")); - } - - [PlaywrightTest("elementhandle-click.spec.ts", "should work for TextNodes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForTextNodes() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - var buttonTextNode = (IElementHandle)await Page.EvaluateHandleAsync("() => document.querySelector('button').firstChild"); - await buttonTextNode.ClickAsync(); - Assert.Equal("Clicked", await Page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("elementhandle-click.spec.ts", "should throw for detached nodes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowForDetachedNodes() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - var button = await Page.QuerySelectorAsync("button"); - await Page.EvaluateAsync("button => button.remove()", button); - var exception = await Assert.ThrowsAsync(() => button.ClickAsync()); - Assert.Contains("Element is not attached to the DOM", exception.Message); - } - - [PlaywrightTest("elementhandle-click.spec.ts", "should throw for hidden nodes with force")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowForHiddenNodesWithForce() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - var button = await Page.QuerySelectorAsync("button"); - await Page.EvaluateAsync("button => button.style.display = 'none'", button); - var exception = await Assert.ThrowsAsync(() => button.ClickAsync(force: true)); - Assert.Contains("Element is not visible", exception.Message); - } - - [PlaywrightTest("elementhandle-click.spec.ts", "should throw for recursively hidden nodes with force")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowForRecursivelyHiddenNodesWithForce() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - var button = await Page.QuerySelectorAsync("button"); - await Page.EvaluateAsync("button => button.parentElement.style.display = 'none'", button); - var exception = await Assert.ThrowsAsync(() => button.ClickAsync(force: true)); - Assert.Contains("Element is not visible", exception.Message); - } - - [PlaywrightTest("elementhandle-click.spec.ts", "should throw for <br> elements with force")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowForBrElementsWithforce() - { - await Page.SetContentAsync("hello
goodbye"); - var br = await Page.QuerySelectorAsync("br"); - var exception = await Assert.ThrowsAsync(() => br.ClickAsync(force: true)); - Assert.Contains("Element is outside of the viewport", exception.Message); - } - - [PlaywrightTest("elementhandle-click.spec.ts", "should double click the button")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDoubleClickTheButton() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvaluateAsync(@"() => { - window.double = false; - const button = document.querySelector('button'); - button.addEventListener('dblclick', event => { - window.double = true; - }); - }"); - - var button = await Page.QuerySelectorAsync("button"); - await button.DblClickAsync(); - - Assert.True(await Page.EvaluateAsync("double")); - Assert.Equal("Clicked", await Page.EvaluateAsync("() => result")); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class ElementHandleClickTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("elementhandle-click.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + var button = await Page.QuerySelectorAsync("button"); + await button.ClickAsync(); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("elementhandle-click.spec.ts", "should work with Node removed")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithNodeRemoved() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvaluateAsync("() => delete window['Node']"); + var button = await Page.QuerySelectorAsync("button"); + await button.ClickAsync(); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("elementhandle-click.spec.ts", "should work for Shadow DOM v1")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForShadowDOMV1() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/shadow.html"); + var buttonHandle = (IElementHandle)await Page.EvaluateHandleAsync("() => button"); + await buttonHandle.ClickAsync(); + Assert.That(await Page.EvaluateAsync("() => clicked"), Is.True); + } + + [PlaywrightTest("elementhandle-click.spec.ts", "should work for TextNodes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForTextNodes() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + var buttonTextNode = (IElementHandle)await Page.EvaluateHandleAsync("() => document.querySelector('button').firstChild"); + await buttonTextNode.ClickAsync(); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("elementhandle-click.spec.ts", "should throw for detached nodes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowForDetachedNodes() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + var button = await Page.QuerySelectorAsync("button"); + await Page.EvaluateAsync("button => button.remove()", button); + var exception = Assert.ThrowsAsync(() => button.ClickAsync()); + Assert.That(exception.Message, Does.Contain("Element is not attached to the DOM")); + } + + [PlaywrightTest("elementhandle-click.spec.ts", "should throw for hidden nodes with force")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowForHiddenNodesWithForce() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + var button = await Page.QuerySelectorAsync("button"); + await Page.EvaluateAsync("button => button.style.display = 'none'", button); + var exception = Assert.ThrowsAsync(() => button.ClickAsync(force: true)); + Assert.That(exception.Message, Does.Contain("Element is not visible")); + } + + [PlaywrightTest("elementhandle-click.spec.ts", "should throw for recursively hidden nodes with force")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowForRecursivelyHiddenNodesWithForce() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + var button = await Page.QuerySelectorAsync("button"); + await Page.EvaluateAsync("button => button.parentElement.style.display = 'none'", button); + var exception = Assert.ThrowsAsync(() => button.ClickAsync(force: true)); + Assert.That(exception.Message, Does.Contain("Element is not visible")); + } + + [PlaywrightTest("elementhandle-click.spec.ts", "should throw for <br> elements with force")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowForBrElementsWithforce() + { + await Page.SetContentAsync("hello
goodbye"); + var br = await Page.QuerySelectorAsync("br"); + var exception = Assert.ThrowsAsync(() => br.ClickAsync(force: true)); + Assert.That(exception.Message, Does.Contain("Element is outside of the viewport")); + } + + [PlaywrightTest("elementhandle-click.spec.ts", "should double click the button")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDoubleClickTheButton() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvaluateAsync(@"() => { + window.double = false; + const button = document.querySelector('button'); + button.addEventListener('dblclick', event => { + window.double = true; + }); + }"); + + var button = await Page.QuerySelectorAsync("button"); + await button.DblClickAsync(); + + Assert.That(await Page.EvaluateAsync("double"), Is.True); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("Clicked")); + } + } +} diff --git a/src/Playwright.Tests/ElementHandleContentFrameTests.cs b/src/PlaywrightSharp.Tests/ElementHandleContentFrameTests.cs similarity index 72% rename from src/Playwright.Tests/ElementHandleContentFrameTests.cs rename to src/PlaywrightSharp.Tests/ElementHandleContentFrameTests.cs index 3800d4b8fd..350fc61d28 100644 --- a/src/Playwright.Tests/ElementHandleContentFrameTests.cs +++ b/src/PlaywrightSharp.Tests/ElementHandleContentFrameTests.cs @@ -1,73 +1,66 @@ -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ElementHandleContentFrameTests : PlaywrightSharpPageBaseTest - { - /// - public ElementHandleContentFrameTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("elementhandle-content-frame.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - var elementHandle = await Page.QuerySelectorAsync("#frame1"); - var frame = await elementHandle.ContentFrameAsync(); - Assert.Equal(Page.Frames.ElementAt(1), frame); - } - - [PlaywrightTest("elementhandle-content-frame.spec.ts", "should work for cross-process iframes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForCrossProcessIframes() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.CrossProcessUrl + "/empty.html"); - var elementHandle = await Page.QuerySelectorAsync("#frame1"); - var frame = await elementHandle.ContentFrameAsync(); - Assert.Equal(Page.Frames.ElementAt(1), frame); - } - - [PlaywrightTest("elementhandle-content-frame.spec.ts", "should work for cross-frame evaluations")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForCrossFrameEvaluations() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - var frame = Page.Frames.ElementAt(1); - var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => window.top.document.querySelector('#frame1')"); - Assert.Equal(frame, await elementHandle.ContentFrameAsync()); - } - - [PlaywrightTest("elementhandle-content-frame.spec.ts", "should return null for non-iframes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnNullForNonIframes() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - var frame = Page.Frames.ElementAt(1); - var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document.body"); - Assert.Null(await elementHandle.ContentFrameAsync()); - } - - [PlaywrightTest("elementhandle-content-frame.spec.ts", "should return null for document.documentElement")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnNullForDocumentDocumentElement() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - var frame = Page.Frames.ElementAt(1); - var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document.documentElement"); - Assert.Null(await elementHandle.ContentFrameAsync()); - } - } -} +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class ElementHandleContentFrameTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("elementhandle-content-frame.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + var elementHandle = await Page.QuerySelectorAsync("#frame1"); + var frame = await elementHandle.ContentFrameAsync(); + Assert.That(frame, Is.EqualTo(Page.Frames.ElementAt(1))); + } + + [PlaywrightTest("elementhandle-content-frame.spec.ts", "should work for cross-process iframes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForCrossProcessIframes() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.CrossProcessUrl + "/empty.html"); + var elementHandle = await Page.QuerySelectorAsync("#frame1"); + var frame = await elementHandle.ContentFrameAsync(); + Assert.That(frame, Is.EqualTo(Page.Frames.ElementAt(1))); + } + + [PlaywrightTest("elementhandle-content-frame.spec.ts", "should work for cross-frame evaluations")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForCrossFrameEvaluations() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + var frame = Page.Frames.ElementAt(1); + var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => window.top.document.querySelector('#frame1')"); + Assert.That(await elementHandle.ContentFrameAsync(), Is.EqualTo(frame)); + } + + [PlaywrightTest("elementhandle-content-frame.spec.ts", "should return null for non-iframes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnNullForNonIframes() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + var frame = Page.Frames.ElementAt(1); + var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document.body"); + Assert.That(await elementHandle.ContentFrameAsync(), Is.Null); + } + + [PlaywrightTest("elementhandle-content-frame.spec.ts", "should return null for document.documentElement")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnNullForDocumentDocumentElement() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + var frame = Page.Frames.ElementAt(1); + var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document.documentElement"); + Assert.That(await elementHandle.ContentFrameAsync(), Is.Null); + } + } +} diff --git a/src/Playwright.Tests/ElementHandleConvenienceTests.cs b/src/PlaywrightSharp.Tests/ElementHandleConvenienceTests.cs similarity index 60% rename from src/Playwright.Tests/ElementHandleConvenienceTests.cs rename to src/PlaywrightSharp.Tests/ElementHandleConvenienceTests.cs index 69c95f205d..974f83feb8 100644 --- a/src/Playwright.Tests/ElementHandleConvenienceTests.cs +++ b/src/PlaywrightSharp.Tests/ElementHandleConvenienceTests.cs @@ -1,273 +1,266 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///elementhandle-convenience.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ElementHandleConvenienceTests : PlaywrightSharpPageBaseTest - { - /// - public ElementHandleConvenienceTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "should have a nice preview")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHaveANicePreview() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/dom.html"); - var outer = await Page.QuerySelectorAsync("#outer"); - var inner = await Page.QuerySelectorAsync("#inner"); - var check = await Page.QuerySelectorAsync("#check"); - var text = await inner.EvaluateHandleAsync("e => e.firstChild"); - await Page.EvaluateAsync("() => 1"); // Give them a chance to calculate the preview. - Assert.Equal("JSHandle@
", outer.ToString()); - Assert.Equal("JSHandle@
Text,↵more text
", inner.ToString()); - Assert.Equal("JSHandle@#text=Text,↵more text", text.ToString()); - Assert.Equal("JSHandle@", check.ToString()); - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "getAttribute should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task GetAttributeShouldWork() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/dom.html"); - var handle = await Page.QuerySelectorAsync("#outer"); - - Assert.Equal("value", await handle.GetAttributeAsync("name")); - Assert.Equal("value", await Page.GetAttributeAsync("#outer", "name")); - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "innerHTML should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task InnerHTMLShouldWork() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/dom.html"); - var handle = await Page.QuerySelectorAsync("#outer"); - - Assert.Equal("
Text,\nmore text
", await handle.InnerHTMLAsync()); - Assert.Equal("
Text,\nmore text
", await Page.InnerHTMLAsync("#outer")); - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "innerText should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task InnerTextShouldWork() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/dom.html"); - var handle = await Page.QuerySelectorAsync("#inner"); - - Assert.Equal("Text, more text", await handle.InnerTextAsync()); - Assert.Equal("Text, more text", await Page.InnerTextAsync("#inner")); - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "'innerText should throw")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task InnerTextShouldThrow() - { - await Page.SetContentAsync("text"); - var exception1 = await Assert.ThrowsAnyAsync(() => Page.InnerTextAsync("svg")); - Assert.Contains("Not an HTMLElement", exception1.Message); - - var handle = await Page.QuerySelectorAsync("svg"); - var exception2 = await Assert.ThrowsAnyAsync(() => handle.InnerTextAsync()); - Assert.Contains("Not an HTMLElement", exception1.Message); - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "textContent should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task TextContentShouldWork() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/dom.html"); - var handle = await Page.QuerySelectorAsync("#outer"); - - Assert.Equal("Text,\nmore text", await handle.TextContentAsync()); - Assert.Equal("Text,\nmore text", await Page.TextContentAsync("#outer")); - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "Page.dispatchEvent(click)", "textContent should be atomic")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task TextContentShouldBeAtomic() - { - const string createDummySelector = @"({ - create(root, target) { }, - query(root, selector) { - const result = root.querySelector(selector); - if (result) - Promise.resolve().then(() => result.textContent = 'modified'); - return result; - }, - queryAll(root, selector) { - const result = Array.from(root.querySelectorAll(selector)); - for (const e of result) - Promise.resolve().then(() => e.textContent = 'modified'); - return result; - } - })"; - - await TestUtils.RegisterEngineAsync(Playwright, "textContent", createDummySelector); - await Page.SetContentAsync("
Hello
"); - string tc = await Page.TextContentAsync("textContent=div"); - Assert.Equal("Hello", tc); - Assert.Equal("modified", await Page.EvaluateAsync("() => document.querySelector('div').textContent")); - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "Page.dispatchEvent(click)", "innerText should be atomic")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task InnerTextShouldBeAtomic() - { - const string createDummySelector = @"({ - create(root, target) { }, - query(root, selector) { - const result = root.querySelector(selector); - if (result) - Promise.resolve().then(() => result.textContent = 'modified'); - return result; - }, - queryAll(root, selector) { - const result = Array.from(root.querySelectorAll(selector)); - for (const e of result) - Promise.resolve().then(() => e.textContent = 'modified'); - return result; - } - })"; - - await TestUtils.RegisterEngineAsync(Playwright, "innerText", createDummySelector); - await Page.SetContentAsync("
Hello
"); - string tc = await Page.InnerTextAsync("innerText=div"); - Assert.Equal("Hello", tc); - Assert.Equal("modified", await Page.EvaluateAsync("() => document.querySelector('div').textContent")); - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "Page.dispatchEvent(click)", "innerHTML should be atomic")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task InnerHtmlShouldBeAtomic() - { - const string createDummySelector = @"({ - create(root, target) { }, - query(root, selector) { - const result = root.querySelector(selector); - if (result) - Promise.resolve().then(() => result.textContent = 'modified'); - return result; - }, - queryAll(root, selector) { - const result = Array.from(root.querySelectorAll(selector)); - for (const e of result) - Promise.resolve().then(() => e.textContent = 'modified'); - return result; - } - })"; - - await TestUtils.RegisterEngineAsync(Playwright, "innerHtml", createDummySelector); - await Page.SetContentAsync("
Hello
"); - string tc = await Page.InnerHTMLAsync("innerHtml=div"); - Assert.Equal("Hello", tc); - Assert.Equal("modified", await Page.EvaluateAsync("() => document.querySelector('div').textContent")); - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "Page.dispatchEvent(click)", "getAttribute should be atomic")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task GetAttributeShouldBeAtomic() - { - const string createDummySelector = @"({ - create(root, target) { }, - query(root, selector) { - const result = root.querySelector(selector); - if (result) - Promise.resolve().then(() => result.setAttribute('foo', 'modified')); - return result; - }, - queryAll(root, selector) { - const result = Array.from(root.querySelectorAll(selector)); - for (const e of result) - Promise.resolve().then(() => e.setAttribute('foo', 'modified')); - return result; - } - })"; - - await TestUtils.RegisterEngineAsync(Playwright, "getAttribute", createDummySelector); - await Page.SetContentAsync("
"); - string tc = await Page.GetAttributeAsync("getAttribute=div", "foo"); - Assert.Equal("Hello", tc); - Assert.Equal("modified", await Page.EvaluateAsync("() => document.querySelector('div').getAttribute('foo')")); - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "isVisible and isHidden should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task IsVisibleAndIsHiddenShouldWork() - { - await Page.SetContentAsync("
Hi
"); - var div = await Page.QuerySelectorAsync("div"); - Assert.True(await div.IsVisibleAsync()); - Assert.False(await div.IsHiddenAsync()); - Assert.True(await Page.IsVisibleAsync("div")); - Assert.False(await Page.IsHiddenAsync("div")); - var span = await Page.QuerySelectorAsync("span"); - Assert.False(await span.IsVisibleAsync()); - Assert.True(await span.IsHiddenAsync()); - Assert.False(await Page.IsVisibleAsync("span")); - Assert.True(await Page.IsHiddenAsync("span")); - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "isEnabled and isDisabled should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task IsEnabledAndIsDisabledShouldWork() - { - await Page.SetContentAsync(@" - - -
div
"); - var div = await Page.QuerySelectorAsync("div"); - Assert.True(await div.IsEnabledAsync()); - Assert.False(await div.IsDisabledAsync()); - Assert.True(await Page.IsEnabledAsync("div")); - Assert.False(await Page.IsDisabledAsync("div")); - var button1 = await Page.QuerySelectorAsync(":text('button1')"); - Assert.False(await button1.IsEnabledAsync()); - Assert.True(await button1.IsDisabledAsync()); - Assert.False(await Page.IsEnabledAsync(":text('button1')")); - Assert.True(await Page.IsDisabledAsync(":text('button1')")); - var button2 = await Page.QuerySelectorAsync(":text('button2')"); - Assert.True(await button2.IsEnabledAsync()); - Assert.False(await button2.IsDisabledAsync()); - Assert.True(await Page.IsEnabledAsync(":text('button2')")); - Assert.False(await Page.IsDisabledAsync(":text('button2')")); - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "isEditable should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task IsEditableShouldWork() - { - await Page.SetContentAsync(@""); - await Page.EvalOnSelectorAsync("textarea", "t => t.readOnly = true"); - var input1 = await Page.QuerySelectorAsync("#input1"); - Assert.False(await input1.IsEditableAsync()); - Assert.False(await Page.IsEditableAsync("#input1")); - var input2 = await Page.QuerySelectorAsync("#input2"); - Assert.True(await input2.IsEditableAsync()); - Assert.True(await Page.IsEditableAsync("#input2")); - var textarea = await Page.QuerySelectorAsync("textarea"); - Assert.False(await textarea.IsEditableAsync()); - Assert.False(await Page.IsEditableAsync("textarea")); - } - - [PlaywrightTest("elementhandle-convenience.spec.ts", "isChecked should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task IsCheckedShouldWork() - { - await Page.SetContentAsync(@"
Not a checkbox
"); - var handle = await Page.QuerySelectorAsync("input"); - Assert.True(await handle.IsCheckedAsync()); - Assert.True(await Page.IsCheckedAsync("input")); - await handle.EvaluateAsync("input => input.checked = false"); - Assert.False(await handle.IsCheckedAsync()); - Assert.False(await Page.IsCheckedAsync("input")); - var exception = await Assert.ThrowsAnyAsync(() => Page.IsCheckedAsync("div")); - Assert.Contains("Not a checkbox or radio button", exception.Message); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///elementhandle-convenience.spec.ts + public class ElementHandleConvenienceTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("elementhandle-convenience.spec.ts", "should have a nice preview")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHaveANicePreview() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/dom.html"); + var outer = await Page.QuerySelectorAsync("#outer"); + var inner = await Page.QuerySelectorAsync("#inner"); + var check = await Page.QuerySelectorAsync("#check"); + var text = await inner.EvaluateHandleAsync("e => e.firstChild"); + await Page.EvaluateAsync("() => 1"); // Give them a chance to calculate the preview. + Assert.That(outer.ToString(), Is.EqualTo("JSHandle@
")); + Assert.That(inner.ToString(), Is.EqualTo("JSHandle@
Text,↵more text
")); + Assert.That(text.ToString(), Is.EqualTo("JSHandle@#text=Text,↵more text")); + Assert.That(check.ToString(), Is.EqualTo("JSHandle@")); + } + + [PlaywrightTest("elementhandle-convenience.spec.ts", "getAttribute should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task GetAttributeShouldWork() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/dom.html"); + var handle = await Page.QuerySelectorAsync("#outer"); + + Assert.That(await handle.GetAttributeAsync("name"), Is.EqualTo("value")); + Assert.That(await Page.GetAttributeAsync("#outer", "name"), Is.EqualTo("value")); + } + + [PlaywrightTest("elementhandle-convenience.spec.ts", "innerHTML should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task InnerHTMLShouldWork() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/dom.html"); + var handle = await Page.QuerySelectorAsync("#outer"); + + Assert.That(await handle.InnerHTMLAsync(), Is.EqualTo("
Text,\nmore text
")); + Assert.That(await Page.InnerHTMLAsync("#outer"), Is.EqualTo("
Text,\nmore text
")); + } + + [PlaywrightTest("elementhandle-convenience.spec.ts", "innerText should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task InnerTextShouldWork() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/dom.html"); + var handle = await Page.QuerySelectorAsync("#inner"); + + Assert.That(await handle.InnerTextAsync(), Is.EqualTo("Text, more text")); + Assert.That(await Page.InnerTextAsync("#inner"), Is.EqualTo("Text, more text")); + } + + [PlaywrightTest("elementhandle-convenience.spec.ts", "'innerText should throw")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task InnerTextShouldThrow() + { + await Page.SetContentAsync("text"); + var exception1 = Assert.CatchAsync(() => Page.InnerTextAsync("svg")); + Assert.That(exception1.Message, Does.Contain("Not an HTMLElement")); + + var handle = await Page.QuerySelectorAsync("svg"); + var exception2 = Assert.CatchAsync(() => handle.InnerTextAsync()); + Assert.That(exception1.Message, Does.Contain("Not an HTMLElement")); + } + + [PlaywrightTest("elementhandle-convenience.spec.ts", "textContent should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task TextContentShouldWork() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/dom.html"); + var handle = await Page.QuerySelectorAsync("#outer"); + + Assert.That(await handle.TextContentAsync(), Is.EqualTo("Text,\nmore text")); + Assert.That(await Page.TextContentAsync("#outer"), Is.EqualTo("Text,\nmore text")); + } + + [PlaywrightTest("elementhandle-convenience.spec.ts", "Page.dispatchEvent(click)", "textContent should be atomic")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task TextContentShouldBeAtomic() + { + const string createDummySelector = @"({ + create(root, target) { }, + query(root, selector) { + const result = root.querySelector(selector); + if (result) + Promise.resolve().then(() => result.textContent = 'modified'); + return result; + }, + queryAll(root, selector) { + const result = Array.from(root.querySelectorAll(selector)); + for (const e of result) + Promise.resolve().then(() => e.textContent = 'modified'); + return result; + } + })"; + + await TestUtils.RegisterEngineAsync(Playwright, "textContent", createDummySelector); + await Page.SetContentAsync("
Hello
"); + string tc = await Page.TextContentAsync("textContent=div"); + Assert.That(tc, Is.EqualTo("Hello")); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('div').textContent"), Is.EqualTo("modified")); + } + + [PlaywrightTest("elementhandle-convenience.spec.ts", "Page.dispatchEvent(click)", "innerText should be atomic")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task InnerTextShouldBeAtomic() + { + const string createDummySelector = @"({ + create(root, target) { }, + query(root, selector) { + const result = root.querySelector(selector); + if (result) + Promise.resolve().then(() => result.textContent = 'modified'); + return result; + }, + queryAll(root, selector) { + const result = Array.from(root.querySelectorAll(selector)); + for (const e of result) + Promise.resolve().then(() => e.textContent = 'modified'); + return result; + } + })"; + + await TestUtils.RegisterEngineAsync(Playwright, "innerText", createDummySelector); + await Page.SetContentAsync("
Hello
"); + string tc = await Page.InnerTextAsync("innerText=div"); + Assert.That(tc, Is.EqualTo("Hello")); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('div').textContent"), Is.EqualTo("modified")); + } + + [PlaywrightTest("elementhandle-convenience.spec.ts", "Page.dispatchEvent(click)", "innerHTML should be atomic")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task InnerHtmlShouldBeAtomic() + { + const string createDummySelector = @"({ + create(root, target) { }, + query(root, selector) { + const result = root.querySelector(selector); + if (result) + Promise.resolve().then(() => result.textContent = 'modified'); + return result; + }, + queryAll(root, selector) { + const result = Array.from(root.querySelectorAll(selector)); + for (const e of result) + Promise.resolve().then(() => e.textContent = 'modified'); + return result; + } + })"; + + await TestUtils.RegisterEngineAsync(Playwright, "innerHtml", createDummySelector); + await Page.SetContentAsync("
Hello
"); + string tc = await Page.InnerHTMLAsync("innerHtml=div"); + Assert.That(tc, Is.EqualTo("Hello")); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('div').textContent"), Is.EqualTo("modified")); + } + + [PlaywrightTest("elementhandle-convenience.spec.ts", "Page.dispatchEvent(click)", "getAttribute should be atomic")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task GetAttributeShouldBeAtomic() + { + const string createDummySelector = @"({ + create(root, target) { }, + query(root, selector) { + const result = root.querySelector(selector); + if (result) + Promise.resolve().then(() => result.setAttribute('foo', 'modified')); + return result; + }, + queryAll(root, selector) { + const result = Array.from(root.querySelectorAll(selector)); + for (const e of result) + Promise.resolve().then(() => e.setAttribute('foo', 'modified')); + return result; + } + })"; + + await TestUtils.RegisterEngineAsync(Playwright, "getAttribute", createDummySelector); + await Page.SetContentAsync("
"); + string tc = await Page.GetAttributeAsync("getAttribute=div", "foo"); + Assert.That(tc, Is.EqualTo("Hello")); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('div').getAttribute('foo')"), Is.EqualTo("modified")); + } + + [PlaywrightTest("elementhandle-convenience.spec.ts", "isVisible and isHidden should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task IsVisibleAndIsHiddenShouldWork() + { + await Page.SetContentAsync("
Hi
"); + var div = await Page.QuerySelectorAsync("div"); + Assert.That(await div.IsVisibleAsync(), Is.True); + Assert.That(await div.IsHiddenAsync(), Is.False); + Assert.That(await Page.IsVisibleAsync("div"), Is.True); + Assert.That(await Page.IsHiddenAsync("div"), Is.False); + var span = await Page.QuerySelectorAsync("span"); + Assert.That(await span.IsVisibleAsync(), Is.False); + Assert.That(await span.IsHiddenAsync(), Is.True); + Assert.That(await Page.IsVisibleAsync("span"), Is.False); + Assert.That(await Page.IsHiddenAsync("span"), Is.True); + } + + [PlaywrightTest("elementhandle-convenience.spec.ts", "isEnabled and isDisabled should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task IsEnabledAndIsDisabledShouldWork() + { + await Page.SetContentAsync(@" + + +
div
"); + var div = await Page.QuerySelectorAsync("div"); + Assert.That(await div.IsEnabledAsync(), Is.True); + Assert.That(await div.IsDisabledAsync(), Is.False); + Assert.That(await Page.IsEnabledAsync("div"), Is.True); + Assert.That(await Page.IsDisabledAsync("div"), Is.False); + var button1 = await Page.QuerySelectorAsync(":text('button1')"); + Assert.That(await button1.IsEnabledAsync(), Is.False); + Assert.That(await button1.IsDisabledAsync(), Is.True); + Assert.That(await Page.IsEnabledAsync(":text('button1')"), Is.False); + Assert.That(await Page.IsDisabledAsync(":text('button1')"), Is.True); + var button2 = await Page.QuerySelectorAsync(":text('button2')"); + Assert.That(await button2.IsEnabledAsync(), Is.True); + Assert.That(await button2.IsDisabledAsync(), Is.False); + Assert.That(await Page.IsEnabledAsync(":text('button2')"), Is.True); + Assert.That(await Page.IsDisabledAsync(":text('button2')"), Is.False); + } + + [PlaywrightTest("elementhandle-convenience.spec.ts", "isEditable should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task IsEditableShouldWork() + { + await Page.SetContentAsync(@""); + await Page.EvalOnSelectorAsync("textarea", "t => t.readOnly = true"); + var input1 = await Page.QuerySelectorAsync("#input1"); + Assert.That(await input1.IsEditableAsync(), Is.False); + Assert.That(await Page.IsEditableAsync("#input1"), Is.False); + var input2 = await Page.QuerySelectorAsync("#input2"); + Assert.That(await input2.IsEditableAsync(), Is.True); + Assert.That(await Page.IsEditableAsync("#input2"), Is.True); + var textarea = await Page.QuerySelectorAsync("textarea"); + Assert.That(await textarea.IsEditableAsync(), Is.False); + Assert.That(await Page.IsEditableAsync("textarea"), Is.False); + } + + [PlaywrightTest("elementhandle-convenience.spec.ts", "isChecked should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task IsCheckedShouldWork() + { + await Page.SetContentAsync(@"
Not a checkbox
"); + var handle = await Page.QuerySelectorAsync("input"); + Assert.That(await handle.IsCheckedAsync(), Is.True); + Assert.That(await Page.IsCheckedAsync("input"), Is.True); + await handle.EvaluateAsync("input => input.checked = false"); + Assert.That(await handle.IsCheckedAsync(), Is.False); + Assert.That(await Page.IsCheckedAsync("input"), Is.False); + var exception = Assert.CatchAsync(() => Page.IsCheckedAsync("div")); + Assert.That(exception.Message, Does.Contain("Not a checkbox or radio button")); + } + } +} diff --git a/src/Playwright.Tests/ElementHandleEvalOnSelectorTests.cs b/src/PlaywrightSharp.Tests/ElementHandleEvalOnSelectorTests.cs similarity index 72% rename from src/Playwright.Tests/ElementHandleEvalOnSelectorTests.cs rename to src/PlaywrightSharp.Tests/ElementHandleEvalOnSelectorTests.cs index fccc84f35a..791daf65cb 100644 --- a/src/Playwright.Tests/ElementHandleEvalOnSelectorTests.cs +++ b/src/PlaywrightSharp.Tests/ElementHandleEvalOnSelectorTests.cs @@ -1,81 +1,74 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ElementHandleEvalOnSelectorTests : PlaywrightSharpPageBaseTest - { - /// - public ElementHandleEvalOnSelectorTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("elementhandle-eval-on-selector.spec.ts", "should work for all")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForAll() - { - await Page.SetContentAsync("
100
10
"); - var tweet = await Page.QuerySelectorAsync(".tweet"); - string[] content = await tweet.EvalOnSelectorAllAsync(".like", "nodes => nodes.map(n => n.innerText)"); - Assert.Equal(new[] { "100", "10" }, content); - } - - [PlaywrightTest("elementhandle-eval-on-selector.spec.ts", "should retrieve content from subtree for all")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRetrieveContentFromSubtreeForAll() - { - string htmlContent = "
not-a-child-div
a1-child-div
a2-child-div
"; - await Page.SetContentAsync(htmlContent); - var elementHandle = await Page.QuerySelectorAsync("#myId"); - string[] content = await elementHandle.EvalOnSelectorAllAsync(".a", "nodes => nodes.map(n => n.innerText)"); - Assert.Equal(new[] { "a1-child-div", "a2-child-div" }, content); - } - - [PlaywrightTest("elementhandle-eval-on-selector.spec.ts", "should not throw in case of missing selector for all")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotThrowInCaseOfMissingSelectorForAll() - { - string htmlContent = "
not-a-child-div
"; - await Page.SetContentAsync(htmlContent); - var elementHandle = await Page.QuerySelectorAsync("#myId"); - int nodesLength = await elementHandle.EvalOnSelectorAllAsync(".a", "nodes => nodes.length"); - Assert.Equal(0, nodesLength); - } - - [PlaywrightTest("elementhandle-eval-on-selector.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.SetContentAsync("
100
10
"); - var tweet = await Page.QuerySelectorAsync(".tweet"); - string content = await tweet.EvalOnSelectorAsync(".like", "node => node.innerText"); - Assert.Equal("100", content); - } - - [PlaywrightTest("elementhandle-eval-on-selector.spec.ts", "should retrieve content from subtree")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRetrieveContentFromSubtree() - { - string htmlContent = "
not-a-child-div
a-child-div
"; - await Page.SetContentAsync(htmlContent); - var elementHandle = await Page.QuerySelectorAsync("#myId"); - string content = await elementHandle.EvalOnSelectorAsync(".a", "node => node.innerText"); - Assert.Equal("a-child-div", content); - } - - [PlaywrightTest("elementhandle-eval-on-selector.spec.ts", "should throw in case of missing selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowInCaseOfMissingSelector() - { - string htmlContent = "
not-a-child-div
"; - await Page.SetContentAsync(htmlContent); - var elementHandle = await Page.QuerySelectorAsync("#myId"); - var exception = await Assert.ThrowsAsync(() => elementHandle.EvalOnSelectorAsync(".a", "node => node.innerText")); - Assert.Contains("failed to find element matching selector \".a\"", exception.Message); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class ElementHandleEvalOnSelectorTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("elementhandle-eval-on-selector.spec.ts", "should work for all")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForAll() + { + await Page.SetContentAsync("
100
10
"); + var tweet = await Page.QuerySelectorAsync(".tweet"); + string[] content = await tweet.EvalOnSelectorAllAsync(".like", "nodes => nodes.map(n => n.innerText)"); + Assert.That(content, Is.EqualTo(new[] { "100", "10" })); + } + + [PlaywrightTest("elementhandle-eval-on-selector.spec.ts", "should retrieve content from subtree for all")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRetrieveContentFromSubtreeForAll() + { + string htmlContent = "
not-a-child-div
a1-child-div
a2-child-div
"; + await Page.SetContentAsync(htmlContent); + var elementHandle = await Page.QuerySelectorAsync("#myId"); + string[] content = await elementHandle.EvalOnSelectorAllAsync(".a", "nodes => nodes.map(n => n.innerText)"); + Assert.That(content, Is.EqualTo(new[] { "a1-child-div", "a2-child-div" })); + } + + [PlaywrightTest("elementhandle-eval-on-selector.spec.ts", "should not throw in case of missing selector for all")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotThrowInCaseOfMissingSelectorForAll() + { + string htmlContent = "
not-a-child-div
"; + await Page.SetContentAsync(htmlContent); + var elementHandle = await Page.QuerySelectorAsync("#myId"); + int nodesLength = await elementHandle.EvalOnSelectorAllAsync(".a", "nodes => nodes.length"); + Assert.That(nodesLength, Is.EqualTo(0)); + } + + [PlaywrightTest("elementhandle-eval-on-selector.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.SetContentAsync("
100
10
"); + var tweet = await Page.QuerySelectorAsync(".tweet"); + string content = await tweet.EvalOnSelectorAsync(".like", "node => node.innerText"); + Assert.That(content, Is.EqualTo("100")); + } + + [PlaywrightTest("elementhandle-eval-on-selector.spec.ts", "should retrieve content from subtree")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRetrieveContentFromSubtree() + { + string htmlContent = "
not-a-child-div
a-child-div
"; + await Page.SetContentAsync(htmlContent); + var elementHandle = await Page.QuerySelectorAsync("#myId"); + string content = await elementHandle.EvalOnSelectorAsync(".a", "node => node.innerText"); + Assert.That(content, Is.EqualTo("a-child-div")); + } + + [PlaywrightTest("elementhandle-eval-on-selector.spec.ts", "should throw in case of missing selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowInCaseOfMissingSelector() + { + string htmlContent = "
not-a-child-div
"; + await Page.SetContentAsync(htmlContent); + var elementHandle = await Page.QuerySelectorAsync("#myId"); + var exception = Assert.ThrowsAsync(() => elementHandle.EvalOnSelectorAsync(".a", "node => node.innerText")); + Assert.That(exception.Message, Does.Contain("failed to find element matching selector \".a\"")); + } + } +} diff --git a/src/Playwright.Tests/ElementHandleMiscTests.cs b/src/PlaywrightSharp.Tests/ElementHandleMiscTests.cs similarity index 62% rename from src/Playwright.Tests/ElementHandleMiscTests.cs rename to src/PlaywrightSharp.Tests/ElementHandleMiscTests.cs index 3e302a224e..90b812c9d6 100644 --- a/src/Playwright.Tests/ElementHandleMiscTests.cs +++ b/src/PlaywrightSharp.Tests/ElementHandleMiscTests.cs @@ -1,103 +1,96 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ElementHandleMiscTests : PlaywrightSharpPageBaseTest - { - /// - public ElementHandleMiscTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("elementhandle-misc.spec.ts", "should hover")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHover() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); - var button = await Page.QuerySelectorAsync("#button-6"); - await button.HoverAsync(); - Assert.Equal("button-6", await Page.EvaluateAsync("() => document.querySelector('button:hover').id")); - } - - [PlaywrightTest("elementhandle-misc.spec.ts", "should hover when Node is removed")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHoverWhenNodeIsRemoved() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); - await Page.EvaluateAsync("() => delete window['Node']"); - var button = await Page.QuerySelectorAsync("#button-6"); - await button.HoverAsync(); - Assert.Equal("button-6", await Page.EvaluateAsync("() => document.querySelector('button:hover').id")); - } - - [PlaywrightTest("elementhandle-misc.spec.ts", "should fill input")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFillInput() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - var handle = await Page.QuerySelectorAsync("input"); - await handle.FillAsync("some value"); - Assert.Equal("some value", await Page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("elementhandle-misc.spec.ts", "should fill input when Node is removed")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFillInputWhenNodeIsRemoved() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.EvaluateAsync("() => delete window['Node']"); - var handle = await Page.QuerySelectorAsync("input"); - await handle.FillAsync("some value"); - Assert.Equal("some value", await Page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("elementhandle-misc.spec.ts", "should check the box")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCheckTheBox() - { - await Page.SetContentAsync(""); - var input = await Page.QuerySelectorAsync("input"); - await input.CheckAsync(); - Assert.True(await Page.EvaluateAsync("() => checkbox.checked")); - } - - [PlaywrightTest("elementhandle-misc.spec.ts", "should uncheck the box")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldUncheckTheBox() - { - await Page.SetContentAsync(""); - var input = await Page.QuerySelectorAsync("input"); - await input.UncheckAsync(); - Assert.False(await Page.EvaluateAsync("() => checkbox.checked")); - } - - [PlaywrightTest("elementhandle-misc.spec.ts", "should focus a button")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFocusAButton() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - var button = await Page.QuerySelectorAsync("button"); - - Assert.False(await button.EvaluateAsync("button => document.activeElement === button")); - await button.FocusAsync(); - Assert.True(await button.EvaluateAsync("button => document.activeElement === button")); - } - - [PlaywrightTest("elementhandle-misc.spec.ts", "should select single option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectSingleOption() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - var select = await Page.QuerySelectorAsync("select"); - await select.SelectOptionAsync("blue"); - - Assert.Equal(new[] { "blue" }, await Page.EvaluateAsync("() => result.onInput")); - Assert.Equal(new[] { "blue" }, await Page.EvaluateAsync("() => result.onChange")); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class ElementHandleMiscTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("elementhandle-misc.spec.ts", "should hover")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHover() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); + var button = await Page.QuerySelectorAsync("#button-6"); + await button.HoverAsync(); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('button:hover').id"), Is.EqualTo("button-6")); + } + + [PlaywrightTest("elementhandle-misc.spec.ts", "should hover when Node is removed")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHoverWhenNodeIsRemoved() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); + await Page.EvaluateAsync("() => delete window['Node']"); + var button = await Page.QuerySelectorAsync("#button-6"); + await button.HoverAsync(); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('button:hover').id"), Is.EqualTo("button-6")); + } + + [PlaywrightTest("elementhandle-misc.spec.ts", "should fill input")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFillInput() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + var handle = await Page.QuerySelectorAsync("input"); + await handle.FillAsync("some value"); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("some value")); + } + + [PlaywrightTest("elementhandle-misc.spec.ts", "should fill input when Node is removed")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFillInputWhenNodeIsRemoved() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.EvaluateAsync("() => delete window['Node']"); + var handle = await Page.QuerySelectorAsync("input"); + await handle.FillAsync("some value"); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("some value")); + } + + [PlaywrightTest("elementhandle-misc.spec.ts", "should check the box")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCheckTheBox() + { + await Page.SetContentAsync(""); + var input = await Page.QuerySelectorAsync("input"); + await input.CheckAsync(); + Assert.That(await Page.EvaluateAsync("() => checkbox.checked"), Is.True); + } + + [PlaywrightTest("elementhandle-misc.spec.ts", "should uncheck the box")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldUncheckTheBox() + { + await Page.SetContentAsync(""); + var input = await Page.QuerySelectorAsync("input"); + await input.UncheckAsync(); + Assert.That(await Page.EvaluateAsync("() => checkbox.checked"), Is.False); + } + + [PlaywrightTest("elementhandle-misc.spec.ts", "should focus a button")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFocusAButton() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + var button = await Page.QuerySelectorAsync("button"); + + Assert.That(await button.EvaluateAsync("button => document.activeElement === button"), Is.False); + await button.FocusAsync(); + Assert.That(await button.EvaluateAsync("button => document.activeElement === button"), Is.True); + } + + [PlaywrightTest("elementhandle-misc.spec.ts", "should select single option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSelectSingleOption() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); + var select = await Page.QuerySelectorAsync("select"); + await select.SelectOptionAsync("blue"); + + Assert.That(await Page.EvaluateAsync("() => result.onInput"), Is.EqualTo(new[] { "blue" })); + Assert.That(await Page.EvaluateAsync("() => result.onChange"), Is.EqualTo(new[] { "blue" })); + } + } +} diff --git a/src/Playwright.Tests/ElementHandleOwnerFrameTests.cs b/src/PlaywrightSharp.Tests/ElementHandleOwnerFrameTests.cs similarity index 74% rename from src/Playwright.Tests/ElementHandleOwnerFrameTests.cs rename to src/PlaywrightSharp.Tests/ElementHandleOwnerFrameTests.cs index cb1950ffd5..2e6a13528d 100644 --- a/src/Playwright.Tests/ElementHandleOwnerFrameTests.cs +++ b/src/PlaywrightSharp.Tests/ElementHandleOwnerFrameTests.cs @@ -1,116 +1,109 @@ -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ElementHandleOwnerFrameTests : PlaywrightSharpPageBaseTest - { - /// - public ElementHandleOwnerFrameTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - var frame = Page.Frames.ElementAt(1); - var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document.body"); - Assert.Equal(frame, await elementHandle.OwnerFrameAsync()); - } - - [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work for cross-process iframes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForCrossProcessIframes() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.CrossProcessUrl + "/empty.html"); - var frame = Page.Frames.ElementAt(1); - var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document.body"); - Assert.Equal(frame, await elementHandle.OwnerFrameAsync()); - } - - [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work for document")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForDocument() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - var frame = Page.Frames.ElementAt(1); - var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document"); - Assert.Equal(frame, await elementHandle.OwnerFrameAsync()); - } - - [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work for iframe elements")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForIframeElements() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - var frame = Page.MainFrame; - var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document.querySelector('#frame1')"); - Assert.Equal(frame, await elementHandle.OwnerFrameAsync()); - } - - [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work for cross-frame evaluations")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForCrossFrameEvaluations() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - var frame = Page.MainFrame; - var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document.querySelector('#frame1').contentWindow.document.body"); - Assert.Equal(frame.ChildFrames.First(), await elementHandle.OwnerFrameAsync()); - } - - [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work for detached elements")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForDetachedElements() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var divHandle = (IElementHandle)await Page.EvaluateHandleAsync(@"() => { - var div = document.createElement('div'); - document.body.appendChild(div); - return div; - }"); - Assert.Equal(Page.MainFrame, await divHandle.OwnerFrameAsync()); - await Page.EvaluateAsync(@"() => { - var div = document.querySelector('div'); - document.body.removeChild(div); - }"); - Assert.Equal(Page.MainFrame, await divHandle.OwnerFrameAsync()); - } - - [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work for adopted elements")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWorkForAdoptedElements() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup); - await TaskUtils.WhenAll( - popupTask, - Page.EvaluateAsync("url => window.__popup = window.open(url)", TestConstants.EmptyPage)); - var popup = await popupTask; - var divHandle = (IElementHandle)await Page.EvaluateHandleAsync(@"() => { - var div = document.createElement('div'); - document.body.appendChild(div); - return div; - }"); - Assert.Equal(Page.MainFrame, await divHandle.OwnerFrameAsync()); - await popup.WaitForLoadStateAsync(LoadState.DOMContentLoaded); - await Page.EvaluateAsync(@"() => { - var div = document.querySelector('div'); - window.__popup.document.body.appendChild(div); - }"); - Assert.Same(popup.MainFrame, await divHandle.OwnerFrameAsync()); - } - } -} +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class ElementHandleOwnerFrameTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + var frame = Page.Frames.ElementAt(1); + var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document.body"); + Assert.That(await elementHandle.OwnerFrameAsync(), Is.EqualTo(frame)); + } + + [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work for cross-process iframes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForCrossProcessIframes() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.CrossProcessUrl + "/empty.html"); + var frame = Page.Frames.ElementAt(1); + var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document.body"); + Assert.That(await elementHandle.OwnerFrameAsync(), Is.EqualTo(frame)); + } + + [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work for document")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForDocument() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + var frame = Page.Frames.ElementAt(1); + var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document"); + Assert.That(await elementHandle.OwnerFrameAsync(), Is.EqualTo(frame)); + } + + [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work for iframe elements")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForIframeElements() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + var frame = Page.MainFrame; + var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document.querySelector('#frame1')"); + Assert.That(await elementHandle.OwnerFrameAsync(), Is.EqualTo(frame)); + } + + [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work for cross-frame evaluations")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForCrossFrameEvaluations() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + var frame = Page.MainFrame; + var elementHandle = (IElementHandle)await frame.EvaluateHandleAsync("() => document.querySelector('#frame1').contentWindow.document.body"); + Assert.That(await elementHandle.OwnerFrameAsync(), Is.EqualTo(frame.ChildFrames.First())); + } + + [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work for detached elements")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForDetachedElements() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var divHandle = (IElementHandle)await Page.EvaluateHandleAsync(@"() => { + var div = document.createElement('div'); + document.body.appendChild(div); + return div; + }"); + Assert.That(await divHandle.OwnerFrameAsync(), Is.EqualTo(Page.MainFrame)); + await Page.EvaluateAsync(@"() => { + var div = document.querySelector('div'); + document.body.removeChild(div); + }"); + Assert.That(await divHandle.OwnerFrameAsync(), Is.EqualTo(Page.MainFrame)); + } + + [PlaywrightTest("elementhandle-owner-frame.spec.ts", "should work for adopted elements")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWorkForAdoptedElements() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup); + await TaskUtils.WhenAll( + popupTask, + Page.EvaluateAsync("url => window.__popup = window.open(url)", TestConstants.EmptyPage)); + var popup = await popupTask; + var divHandle = (IElementHandle)await Page.EvaluateHandleAsync(@"() => { + var div = document.createElement('div'); + document.body.appendChild(div); + return div; + }"); + Assert.That(await divHandle.OwnerFrameAsync(), Is.EqualTo(Page.MainFrame)); + await popup.WaitForLoadStateAsync(LoadState.DOMContentLoaded); + await Page.EvaluateAsync(@"() => { + var div = document.querySelector('div'); + window.__popup.document.body.appendChild(div); + }"); + Assert.That(await divHandle.OwnerFrameAsync(), Is.SameAs(popup.MainFrame)); + } + } +} diff --git a/src/Playwright.Tests/ElementHandleQuerySelectorTests.cs b/src/PlaywrightSharp.Tests/ElementHandleQuerySelectorTests.cs similarity index 76% rename from src/Playwright.Tests/ElementHandleQuerySelectorTests.cs rename to src/PlaywrightSharp.Tests/ElementHandleQuerySelectorTests.cs index ab376671f8..e2f4362a7f 100644 --- a/src/Playwright.Tests/ElementHandleQuerySelectorTests.cs +++ b/src/PlaywrightSharp.Tests/ElementHandleQuerySelectorTests.cs @@ -1,118 +1,111 @@ -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ElementHandleQuerySelectorTests : PlaywrightSharpPageBaseTest - { - /// - public ElementHandleQuerySelectorTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("elementhandle-query-selector.spec.ts", "should query existing element")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldQueryExistingElement() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/playground.html"); - await Page.SetContentAsync("
A
"); - var html = await Page.QuerySelectorAsync("html"); - var second = await html.QuerySelectorAsync(".second"); - var inner = await second.QuerySelectorAsync(".inner"); - string content = await Page.EvaluateAsync("e => e.textContent", inner); - Assert.Equal("A", content); - } - - [PlaywrightTest("elementhandle-query-selector.spec.ts", "should return null for non-existing element")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnNullForNonExistingElement() - { - await Page.SetContentAsync("
B
"); - var html = await Page.QuerySelectorAsync("html"); - var second = await html.QuerySelectorAsync(".third"); - Assert.Null(second); - } - - [PlaywrightTest("elementhandle-query-selector.spec.ts", "should work for adopted elements")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForAdoptedElements() - { - await Page.GoToAsync(TestConstants.EmptyPage); - - var (popup, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.Popup), - Page.EvaluateAsync("url => window.__popup = window.open(url)", TestConstants.EmptyPage)); - - var divHandle = await Page.EvaluateHandleAsync(@"() => { - const div = document.createElement('div'); - document.body.appendChild(div); - const span = document.createElement('span'); - span.textContent = 'hello'; - div.appendChild(span); - return div; - }") as IElementHandle; - - Assert.NotNull(divHandle); - Assert.Equal("hello", await divHandle.EvalOnSelectorAsync("span", "e => e.textContent")); - - await popup.WaitForLoadStateAsync(LoadState.DOMContentLoaded); - await Page.EvaluateAsync(@"() => { - const div = document.querySelector('div'); - window.__popup.document.body.appendChild(div); - }"); - - Assert.NotNull(await divHandle.QuerySelectorAsync("span")); - Assert.Equal("hello", await divHandle.EvalOnSelectorAsync("span", "e => e.textContent")); - } - - [PlaywrightTest("elementhandle-query-selector.spec.ts", "should query existing elements")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldQueryExistingElements() - { - await Page.SetContentAsync("
A

B
"); - var html = await Page.QuerySelectorAsync("html"); - var elements = await html.QuerySelectorAllAsync("div"); - Assert.Equal(2, elements.Count()); - var tasks = elements.Select(element => Page.EvaluateAsync("e => e.textContent", element)); - Assert.Equal(new[] { "A", "B" }, await TaskUtils.WhenAll(tasks)); - } - - [PlaywrightTest("elementhandle-query-selector.spec.ts", "should return empty array for non-existing elements")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnEmptyArrayForNonExistingElements() - { - await Page.SetContentAsync("A
B"); - var html = await Page.QuerySelectorAsync("html"); - var elements = await html.QuerySelectorAllAsync("div"); - Assert.Empty(elements); - } - - [PlaywrightTest("elementhandle-query-selector.spec.ts", "xpath should query existing element")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task XPathShouldQueryExistingElement() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/playground.html"); - await Page.SetContentAsync("
A
"); - var html = await Page.QuerySelectorAsync("html"); - var second = await html.QuerySelectorAllAsync("xpath=./body/div[contains(@class, 'second')]"); - var inner = await second.First().QuerySelectorAllAsync("xpath=./div[contains(@class, 'inner')]"); - string content = await Page.EvaluateAsync("e => e.textContent", inner.First()); - Assert.Equal("A", content); - } - - [PlaywrightTest("elementhandle-query-selector.spec.ts", "xpath should return null for non-existing element")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task XPathShouldReturnNullForNonExistingElement() - { - await Page.SetContentAsync("
B
"); - var html = await Page.QuerySelectorAsync("html"); - var second = await html.QuerySelectorAllAsync("xpath=/div[contains(@class, 'third')]"); - Assert.Empty(second); - } - } -} +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class ElementHandleQuerySelectorTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("elementhandle-query-selector.spec.ts", "should query existing element")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldQueryExistingElement() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/playground.html"); + await Page.SetContentAsync("
A
"); + var html = await Page.QuerySelectorAsync("html"); + var second = await html.QuerySelectorAsync(".second"); + var inner = await second.QuerySelectorAsync(".inner"); + string content = await Page.EvaluateAsync("e => e.textContent", inner); + Assert.That(content, Is.EqualTo("A")); + } + + [PlaywrightTest("elementhandle-query-selector.spec.ts", "should return null for non-existing element")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnNullForNonExistingElement() + { + await Page.SetContentAsync("
B
"); + var html = await Page.QuerySelectorAsync("html"); + var second = await html.QuerySelectorAsync(".third"); + Assert.That(second, Is.Null); + } + + [PlaywrightTest("elementhandle-query-selector.spec.ts", "should work for adopted elements")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForAdoptedElements() + { + await Page.GoToAsync(TestConstants.EmptyPage); + + var (popup, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.Popup), + Page.EvaluateAsync("url => window.__popup = window.open(url)", TestConstants.EmptyPage)); + + var divHandle = await Page.EvaluateHandleAsync(@"() => { + const div = document.createElement('div'); + document.body.appendChild(div); + const span = document.createElement('span'); + span.textContent = 'hello'; + div.appendChild(span); + return div; + }") as IElementHandle; + + Assert.That(divHandle, Is.Not.Null); + Assert.That(await divHandle.EvalOnSelectorAsync("span", "e => e.textContent"), Is.EqualTo("hello")); + + await popup.WaitForLoadStateAsync(LoadState.DOMContentLoaded); + await Page.EvaluateAsync(@"() => { + const div = document.querySelector('div'); + window.__popup.document.body.appendChild(div); + }"); + + Assert.That(await divHandle.QuerySelectorAsync("span"), Is.Not.Null); + Assert.That(await divHandle.EvalOnSelectorAsync("span", "e => e.textContent"), Is.EqualTo("hello")); + } + + [PlaywrightTest("elementhandle-query-selector.spec.ts", "should query existing elements")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldQueryExistingElements() + { + await Page.SetContentAsync("
A

B
"); + var html = await Page.QuerySelectorAsync("html"); + var elements = await html.QuerySelectorAllAsync("div"); + Assert.That(elements.Count(), Is.EqualTo(2)); + var tasks = elements.Select(element => Page.EvaluateAsync("e => e.textContent", element)); + Assert.That(await TaskUtils.WhenAll(tasks), Is.EqualTo(new[] { "A", "B" })); + } + + [PlaywrightTest("elementhandle-query-selector.spec.ts", "should return empty array for non-existing elements")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnEmptyArrayForNonExistingElements() + { + await Page.SetContentAsync("A
B"); + var html = await Page.QuerySelectorAsync("html"); + var elements = await html.QuerySelectorAllAsync("div"); + Assert.That(elements, Is.Empty); + } + + [PlaywrightTest("elementhandle-query-selector.spec.ts", "xpath should query existing element")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task XPathShouldQueryExistingElement() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/playground.html"); + await Page.SetContentAsync("
A
"); + var html = await Page.QuerySelectorAsync("html"); + var second = await html.QuerySelectorAllAsync("xpath=./body/div[contains(@class, 'second')]"); + var inner = await second.First().QuerySelectorAllAsync("xpath=./div[contains(@class, 'inner')]"); + string content = await Page.EvaluateAsync("e => e.textContent", inner.First()); + Assert.That(content, Is.EqualTo("A")); + } + + [PlaywrightTest("elementhandle-query-selector.spec.ts", "xpath should return null for non-existing element")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task XPathShouldReturnNullForNonExistingElement() + { + await Page.SetContentAsync("
B
"); + var html = await Page.QuerySelectorAsync("html"); + var second = await html.QuerySelectorAllAsync("xpath=/div[contains(@class, 'third')]"); + Assert.That(second, Is.Empty); + } + } +} diff --git a/src/Playwright.Tests/ElementHandleScreenshotTests.cs b/src/PlaywrightSharp.Tests/ElementHandleScreenshotTests.cs similarity index 78% rename from src/Playwright.Tests/ElementHandleScreenshotTests.cs rename to src/PlaywrightSharp.Tests/ElementHandleScreenshotTests.cs index e2ec00331b..40a16169e1 100644 --- a/src/Playwright.Tests/ElementHandleScreenshotTests.cs +++ b/src/PlaywrightSharp.Tests/ElementHandleScreenshotTests.cs @@ -1,437 +1,429 @@ -using System; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Microsoft.Playwright.Tests.Helpers; -using SixLabors.ImageSharp; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///elementhandle-screenshot.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ElementHandleScreenshotTests : PlaywrightSharpPageBaseTest - { - /// - public ElementHandleScreenshotTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - await Page.EvaluateAsync("window.scrollBy(50, 100)"); - var elementHandle = await Page.QuerySelectorAsync(".box:nth-of-type(3)"); - byte[] screenshot = await elementHandle.ScreenshotAsync(); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-element-bounding-box.png", screenshot)); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should take into account padding and border")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTakeIntoAccountPaddingAndBorder() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.SetContentAsync(@" -
oooo
- -
"); - var elementHandle = await Page.QuerySelectorAsync("div#d"); - byte[] screenshot = await elementHandle.ScreenshotAsync(); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-element-padding-border.png", screenshot)); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should capture full element when larger than viewport in parallel")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCaptureFullElementWhenLargerThanViewportInParallel() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.SetContentAsync(@" -
oooo
- -
-
-
- "); - var elementHandles = await Page.QuerySelectorAllAsync("div.to-screenshot"); - var screenshotTasks = elementHandles.Select(e => e.ScreenshotAsync()).ToArray(); - await TaskUtils.WhenAll(screenshotTasks); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-element-larger-than-viewport.png", screenshotTasks.ElementAt(2).Result)); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should capture full element when larger than viewport")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCaptureFullElementWhenLargerThanViewport() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.SetContentAsync(@" -
oooo
- -
-
-
"); - - var elementHandle = await Page.QuerySelectorAsync("div.to-screenshot"); - byte[] screenshot = await elementHandle.ScreenshotAsync(); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-element-larger-than-viewport.png", screenshot)); - await TestUtils.VerifyViewportAsync(Page, 500, 500); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should scroll element into view")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldScrollElementIntoView() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.SetContentAsync(@" -
oooo
- -
-
"); - var elementHandle = await Page.QuerySelectorAsync("div.to-screenshot"); - byte[] screenshot = await elementHandle.ScreenshotAsync(); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-element-scrolled-into-view.png", screenshot)); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should scroll 15000px into view")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldScroll15000pxIntoView() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.SetContentAsync(@" -
oooo
- -
-
"); - var elementHandle = await Page.QuerySelectorAsync("div.to-screenshot"); - byte[] screenshot = await elementHandle.ScreenshotAsync(); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-element-scrolled-into-view.png", screenshot)); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should work with a rotated element")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithARotatedElement() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.SetContentAsync(@" -
 
- "); - var elementHandle = await Page.QuerySelectorAsync("div"); - byte[] screenshot = await elementHandle.ScreenshotAsync(); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-element-rotate.png", screenshot)); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should fail to screenshot a detached element")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailToScreenshotADetachedElement() - { - await Page.SetContentAsync("

remove this

"); - var elementHandle = await Page.QuerySelectorAsync("h1"); - await Page.EvaluateAsync("element => element.remove()", elementHandle); - - var exception = await Assert.ThrowsAsync(() => elementHandle.ScreenshotAsync()); - Assert.Contains("Element is not attached to the DOM", exception.Message); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should timeout waiting for visible")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTimeoutWaitingForVisible() - { - await Page.SetContentAsync(@"
"); - var elementHandle = await Page.QuerySelectorAsync("div"); - var exception = await Assert.ThrowsAsync(() => elementHandle.ScreenshotAsync(timeout: 3000)); - Assert.Contains("Timeout 3000ms exceeded", exception.Message); - Assert.Contains("element is not visible", exception.Message); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should wait for visible")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForVisible() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - await Page.EvaluateAsync("() => window.scrollBy(50, 100)"); - var elementHandle = await Page.QuerySelectorAsync(".box:nth-of-type(3)"); - await elementHandle.EvaluateAsync("e => e.style.visibility = 'hidden'"); - var task = elementHandle.ScreenshotAsync(); - - for (int i = 0; i < 10; i++) - { - await Page.EvaluateAsync("() => new Promise(f => requestAnimationFrame(f))"); - } - Assert.False(task.IsCompleted); - await elementHandle.EvaluateAsync("e => e.style.visibility = 'visible'"); - - byte[] screenshot = await task; - Assert.True(ScreenshotHelper.PixelMatch("screenshot-element-bounding-box.png", screenshot)); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should work for an element with fractional dimensions")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForAnElementWithFractionalDimensions() - { - await Page.SetContentAsync("
"); - var elementHandle = await Page.QuerySelectorAsync("div"); - byte[] screenshot = await elementHandle.ScreenshotAsync(); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-element-fractional.png", screenshot)); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should work with a mobile viewport")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWorkWithAMobileViewport() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 320, - Height = 480, - }, - IsMobile = true, - }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - await page.EvaluateAsync("() => window.scrollBy(50, 100)"); - var elementHandle = await page.QuerySelectorAsync(".box:nth-of-type(3)"); - byte[] screenshot = await elementHandle.ScreenshotAsync(); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-element-mobile.png", screenshot)); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should work with device scale factor")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWorkWithDeviceScaleFactor() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 320, - Height = 480, - }, - DeviceScaleFactor = 2, - }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - await page.EvaluateAsync("() => window.scrollBy(50, 100)"); - var elementHandle = await page.QuerySelectorAsync(".box:nth-of-type(3)"); - byte[] screenshot = await elementHandle.ScreenshotAsync(); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-element-mobile-dsf.png", screenshot)); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should work for an element with an offset")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForAnElementWithAnOffset() - { - await Page.SetContentAsync("
"); - var elementHandle = await Page.QuerySelectorAsync("div"); - byte[] screenshot = await elementHandle.ScreenshotAsync(); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-element-fractional-offset.png", screenshot)); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should take screenshots when default viewport is null")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTakeScreenshotsWhenDefaultViewportIsNull() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = ViewportSize.NoViewport - }); - var page = await context.NewPageAsync(); - await page.SetContentAsync("
"); - var windowSize = await page.EvaluateAsync("() => ({ width: window.innerWidth * window.devicePixelRatio, height: window.innerHeight * window.devicePixelRatio })"); - var sizeBefore = await page.EvaluateAsync("() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight })"); - - byte[] screenshot = await page.ScreenshotAsync(); - Assert.NotNull(screenshot); - Assert.NotEmpty(screenshot); - var decoded = Image.Load(screenshot); - Assert.Equal(windowSize.Width, decoded.Width); - Assert.Equal(windowSize.Height, decoded.Height); - - var sizeAfter = await page.EvaluateAsync("() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight })"); - Assert.Equal(sizeBefore, sizeAfter); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should take fullPage screenshots when default viewport is null")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTakeFullPageScreenshotsWhenDefaultViewportIsNull() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = ViewportSize.NoViewport - }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - var sizeBefore = await page.EvaluateAsync("() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight })"); - - byte[] screenshot = await page.ScreenshotAsync(fullPage: true); - Assert.NotNull(screenshot); - Assert.NotEmpty(screenshot); - - var sizeAfter = await page.EvaluateAsync("() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight })"); - Assert.Equal(sizeBefore, sizeAfter); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should restore default viewport after fullPage screenshot")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRestoreDefaultViewportAfterFullPageScreenshot() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize { Width = 456, Height = 789 }, - }); - var page = await context.NewPageAsync(); - await TestUtils.VerifyViewportAsync(page, 456, 789); - byte[] screenshot = await page.ScreenshotAsync(fullPage: true); - Assert.NotNull(screenshot); - Assert.NotEmpty(screenshot); - - await TestUtils.VerifyViewportAsync(page, 456, 789); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should restore viewport after page screenshot and exception")] - [Fact(Skip = "Skip USES_HOOKS")] - public void ShouldRestoreViewportAfterPageScreenshotAndException() - { - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should restore viewport after page screenshot and timeout")] - [Fact(Skip = "Skip USES_HOOKS")] - public void ShouldRestoreViewportAfterPageScreenshotAndTimeout() - { - } - - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should take element screenshot when default viewport is null and restore back")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTakeElementScreenshotWhenDefaultViewportIsNullAndRestoreBack() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = ViewportSize.NoViewport, - }); - var page = await context.NewPageAsync(); - - await Page.SetContentAsync(@" -
oooo
- -
-
-
"); - - var sizeBefore = await page.EvaluateAsync("() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight })"); - var elementHandle = await page.QuerySelectorAsync("div.to-screenshot"); - byte[] screenshot = await page.ScreenshotAsync(); - Assert.NotNull(screenshot); - Assert.NotEmpty(screenshot); - - var sizeAfter = await page.EvaluateAsync("() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight })"); - Assert.Equal(sizeBefore, sizeAfter); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should restore viewport after element screenshot and exception")] - [Fact(Skip = "Skip USES_HOOKS")] - public void ShouldRestoreViewportAfterElementScreenshotAndException() - { - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "should take screenshot of disabled button")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTakeScreenshotOfDisabledButton() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.SetContentAsync(""); - var button = await Page.QuerySelectorAsync("button"); - byte[] screenshot = await button.ScreenshotAsync(); - Assert.NotNull(screenshot); - Assert.NotEmpty(screenshot); - } - - [PlaywrightTest("elementhandle-screenshot.spec.ts", "path option should create subdirectories")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PathOptionShouldCreateSubdirectories() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - await Page.EvaluateAsync("() => window.scrollBy(50, 100)"); - var elementHandle = await Page.QuerySelectorAsync(".box:nth-of-type(3)"); - using var tmpDir = new TempDirectory(); - string outputPath = Path.Combine(tmpDir.Path, "these", "are", "directories", "screenshot.png"); - await elementHandle.ScreenshotAsync(outputPath); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-element-bounding-box.png", outputPath)); - } - } -} +using System; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; +using PlaywrightSharp.Tests.Helpers; +using SixLabors.ImageSharp; + +namespace PlaywrightSharp.Tests +{ + ///elementhandle-screenshot.spec.ts + public class ElementHandleScreenshotTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + await Page.EvaluateAsync("window.scrollBy(50, 100)"); + var elementHandle = await Page.QuerySelectorAsync(".box:nth-of-type(3)"); + byte[] screenshot = await elementHandle.ScreenshotAsync(); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-element-bounding-box.png", screenshot), Is.True); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should take into account padding and border")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTakeIntoAccountPaddingAndBorder() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.SetContentAsync(@" +
oooo
+ +
"); + var elementHandle = await Page.QuerySelectorAsync("div#d"); + byte[] screenshot = await elementHandle.ScreenshotAsync(); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-element-padding-border.png", screenshot), Is.True); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should capture full element when larger than viewport in parallel")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCaptureFullElementWhenLargerThanViewportInParallel() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.SetContentAsync(@" +
oooo
+ +
+
+
+ "); + var elementHandles = await Page.QuerySelectorAllAsync("div.to-screenshot"); + var screenshotTasks = elementHandles.Select(e => e.ScreenshotAsync()).ToArray(); + await TaskUtils.WhenAll(screenshotTasks); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-element-larger-than-viewport.png", screenshotTasks.ElementAt(2).Result), Is.True); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should capture full element when larger than viewport")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCaptureFullElementWhenLargerThanViewport() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.SetContentAsync(@" +
oooo
+ +
+
+
"); + + var elementHandle = await Page.QuerySelectorAsync("div.to-screenshot"); + byte[] screenshot = await elementHandle.ScreenshotAsync(); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-element-larger-than-viewport.png", screenshot), Is.True); + await TestUtils.VerifyViewportAsync(Page, 500, 500); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should scroll element into view")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldScrollElementIntoView() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.SetContentAsync(@" +
oooo
+ +
+
"); + var elementHandle = await Page.QuerySelectorAsync("div.to-screenshot"); + byte[] screenshot = await elementHandle.ScreenshotAsync(); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-element-scrolled-into-view.png", screenshot), Is.True); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should scroll 15000px into view")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldScroll15000pxIntoView() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.SetContentAsync(@" +
oooo
+ +
+
"); + var elementHandle = await Page.QuerySelectorAsync("div.to-screenshot"); + byte[] screenshot = await elementHandle.ScreenshotAsync(); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-element-scrolled-into-view.png", screenshot), Is.True); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should work with a rotated element")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithARotatedElement() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.SetContentAsync(@" +
 
+ "); + var elementHandle = await Page.QuerySelectorAsync("div"); + byte[] screenshot = await elementHandle.ScreenshotAsync(); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-element-rotate.png", screenshot), Is.True); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should fail to screenshot a detached element")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailToScreenshotADetachedElement() + { + await Page.SetContentAsync("

remove this

"); + var elementHandle = await Page.QuerySelectorAsync("h1"); + await Page.EvaluateAsync("element => element.remove()", elementHandle); + + var exception = Assert.ThrowsAsync(() => elementHandle.ScreenshotAsync()); + Assert.That(exception.Message, Does.Contain("Element is not attached to the DOM")); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should timeout waiting for visible")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTimeoutWaitingForVisible() + { + await Page.SetContentAsync(@"
"); + var elementHandle = await Page.QuerySelectorAsync("div"); + var exception = Assert.ThrowsAsync(() => elementHandle.ScreenshotAsync(timeout: 3000)); + Assert.That(exception.Message, Does.Contain("Timeout 3000ms exceeded")); + Assert.That(exception.Message, Does.Contain("element is not visible")); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should wait for visible")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForVisible() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + await Page.EvaluateAsync("() => window.scrollBy(50, 100)"); + var elementHandle = await Page.QuerySelectorAsync(".box:nth-of-type(3)"); + await elementHandle.EvaluateAsync("e => e.style.visibility = 'hidden'"); + var task = elementHandle.ScreenshotAsync(); + + for (int i = 0; i < 10; i++) + { + await Page.EvaluateAsync("() => new Promise(f => requestAnimationFrame(f))"); + } + Assert.That(task.IsCompleted, Is.False); + await elementHandle.EvaluateAsync("e => e.style.visibility = 'visible'"); + + byte[] screenshot = await task; + Assert.That(ScreenshotHelper.PixelMatch("screenshot-element-bounding-box.png", screenshot), Is.True); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should work for an element with fractional dimensions")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForAnElementWithFractionalDimensions() + { + await Page.SetContentAsync("
"); + var elementHandle = await Page.QuerySelectorAsync("div"); + byte[] screenshot = await elementHandle.ScreenshotAsync(); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-element-fractional.png", screenshot), Is.True); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should work with a mobile viewport")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWorkWithAMobileViewport() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 320, + Height = 480, + }, + IsMobile = true, + }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + await page.EvaluateAsync("() => window.scrollBy(50, 100)"); + var elementHandle = await page.QuerySelectorAsync(".box:nth-of-type(3)"); + byte[] screenshot = await elementHandle.ScreenshotAsync(); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-element-mobile.png", screenshot), Is.True); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should work with device scale factor")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWorkWithDeviceScaleFactor() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 320, + Height = 480, + }, + DeviceScaleFactor = 2, + }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + await page.EvaluateAsync("() => window.scrollBy(50, 100)"); + var elementHandle = await page.QuerySelectorAsync(".box:nth-of-type(3)"); + byte[] screenshot = await elementHandle.ScreenshotAsync(); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-element-mobile-dsf.png", screenshot), Is.True); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should work for an element with an offset")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForAnElementWithAnOffset() + { + await Page.SetContentAsync("
"); + var elementHandle = await Page.QuerySelectorAsync("div"); + byte[] screenshot = await elementHandle.ScreenshotAsync(); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-element-fractional-offset.png", screenshot), Is.True); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should take screenshots when default viewport is null")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTakeScreenshotsWhenDefaultViewportIsNull() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = ViewportSize.NoViewport + }); + var page = await context.NewPageAsync(); + await page.SetContentAsync("
"); + var windowSize = await page.EvaluateAsync("() => ({ width: window.innerWidth * window.devicePixelRatio, height: window.innerHeight * window.devicePixelRatio })"); + var sizeBefore = await page.EvaluateAsync("() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight })"); + + byte[] screenshot = await page.ScreenshotAsync(); + Assert.That(screenshot, Is.Not.Null); + Assert.That(screenshot, Is.Not.Empty); + var decoded = Image.Load(screenshot); + Assert.That(decoded.Width, Is.EqualTo(windowSize.Width)); + Assert.That(decoded.Height, Is.EqualTo(windowSize.Height)); + + var sizeAfter = await page.EvaluateAsync("() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight })"); + Assert.That(sizeAfter, Is.EqualTo(sizeBefore)); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should take fullPage screenshots when default viewport is null")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTakeFullPageScreenshotsWhenDefaultViewportIsNull() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = ViewportSize.NoViewport + }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + var sizeBefore = await page.EvaluateAsync("() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight })"); + + byte[] screenshot = await page.ScreenshotAsync(fullPage: true); + Assert.That(screenshot, Is.Not.Null); + Assert.That(screenshot, Is.Not.Empty); + + var sizeAfter = await page.EvaluateAsync("() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight })"); + Assert.That(sizeAfter, Is.EqualTo(sizeBefore)); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should restore default viewport after fullPage screenshot")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRestoreDefaultViewportAfterFullPageScreenshot() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize { Width = 456, Height = 789 }, + }); + var page = await context.NewPageAsync(); + await TestUtils.VerifyViewportAsync(page, 456, 789); + byte[] screenshot = await page.ScreenshotAsync(fullPage: true); + Assert.That(screenshot, Is.Not.Null); + Assert.That(screenshot, Is.Not.Empty); + + await TestUtils.VerifyViewportAsync(page, 456, 789); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should restore viewport after page screenshot and exception")] + [Test, Ignore("Skip USES_HOOKS")] + public void ShouldRestoreViewportAfterPageScreenshotAndException() + { + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should restore viewport after page screenshot and timeout")] + [Test, Ignore("Skip USES_HOOKS")] + public void ShouldRestoreViewportAfterPageScreenshotAndTimeout() + { + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should take element screenshot when default viewport is null and restore back")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTakeElementScreenshotWhenDefaultViewportIsNullAndRestoreBack() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = ViewportSize.NoViewport, + }); + var page = await context.NewPageAsync(); + + await Page.SetContentAsync(@" +
oooo
+ +
+
+
"); + + var sizeBefore = await page.EvaluateAsync("() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight })"); + var elementHandle = await page.QuerySelectorAsync("div.to-screenshot"); + byte[] screenshot = await page.ScreenshotAsync(); + Assert.That(screenshot, Is.Not.Null); + Assert.That(screenshot, Is.Not.Empty); + + var sizeAfter = await page.EvaluateAsync("() => ({ width: document.body.offsetWidth, height: document.body.offsetHeight })"); + Assert.That(sizeAfter, Is.EqualTo(sizeBefore)); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should restore viewport after element screenshot and exception")] + [Test, Ignore("Skip USES_HOOKS")] + public void ShouldRestoreViewportAfterElementScreenshotAndException() + { + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "should take screenshot of disabled button")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTakeScreenshotOfDisabledButton() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.SetContentAsync(""); + var button = await Page.QuerySelectorAsync("button"); + byte[] screenshot = await button.ScreenshotAsync(); + Assert.That(screenshot, Is.Not.Null); + Assert.That(screenshot, Is.Not.Empty); + } + + [PlaywrightTest("elementhandle-screenshot.spec.ts", "path option should create subdirectories")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PathOptionShouldCreateSubdirectories() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + await Page.EvaluateAsync("() => window.scrollBy(50, 100)"); + var elementHandle = await Page.QuerySelectorAsync(".box:nth-of-type(3)"); + using var tmpDir = new TempDirectory(); + string outputPath = Path.Combine(tmpDir.Path, "these", "are", "directories", "screenshot.png"); + await elementHandle.ScreenshotAsync(outputPath); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-element-bounding-box.png", outputPath), Is.True); + } + } +} diff --git a/src/Playwright.Tests/ElementHandleScrollIntoViewTests.cs b/src/PlaywrightSharp.Tests/ElementHandleScrollIntoViewTests.cs similarity index 74% rename from src/Playwright.Tests/ElementHandleScrollIntoViewTests.cs rename to src/PlaywrightSharp.Tests/ElementHandleScrollIntoViewTests.cs index 6c05d6eaf1..636c0072b4 100644 --- a/src/Playwright.Tests/ElementHandleScrollIntoViewTests.cs +++ b/src/PlaywrightSharp.Tests/ElementHandleScrollIntoViewTests.cs @@ -1,110 +1,103 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ElementHandleScrollIntoViewTests : PlaywrightSharpPageBaseTest - { - /// - public ElementHandleScrollIntoViewTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/offscreenbuttons.html"); - for (int i = 0; i < 11; ++i) - { - var button = await Page.QuerySelectorAsync("#btn" + i); - double before = await button.EvaluateAsync(@"button => { - return button.getBoundingClientRect().right - window.innerWidth; - }"); - Assert.Equal(10 * i, before); - await button.ScrollIntoViewIfNeededAsync(); - double after = await button.EvaluateAsync(@"button => { - return button.getBoundingClientRect().right - window.innerWidth; - }"); - Assert.True(after <= 0); - await Page.EvaluateAsync("() => window.scrollTo(0, 0)"); - } - } - - [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should throw for detached element")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowForDetachedElement() - { - await Page.SetContentAsync("
Hello
"); - var div = await Page.QuerySelectorAsync("div"); - await div.EvaluateAsync("div => div.remove()"); - var exception = await Assert.ThrowsAnyAsync(() => div.ScrollIntoViewIfNeededAsync()); - Assert.Contains("Element is not attached to the DOM", exception.Message); - } - - [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should wait for display:none to become visible")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForDisplayNoneToBecomeVisible() - { - await Page.SetContentAsync("
Hello
"); - await TestWaitingAsync(Page, "div => div.style.display = 'block'"); - } - - [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should wait for display:contents to become visible")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForDisplayContentsToBecomeVisible() - { - await Page.SetContentAsync("
Hello
"); - await TestWaitingAsync(Page, "div => div.style.display = 'block'"); - } - - [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should wait for visibility:hidden to become visible")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForVisibilityHiddenToBecomeVisible() - { - await Page.SetContentAsync("
Hello
"); - await TestWaitingAsync(Page, "div => div.style.visibility = 'visible'"); - } - - [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should wait for zero-sized element to become visible")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForZeroSiedElementToBecomeVisible() - { - await Page.SetContentAsync("
Hello
"); - await TestWaitingAsync(Page, "div => div.style.height = '100px'"); - } - - [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should wait for nested display:none to become visible")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForNestedDisplayNoneToBecomeVisible() - { - await Page.SetContentAsync("
Hello
"); - await TestWaitingAsync(Page, "div => div.parentElement.style.display = 'block'"); - } - - [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should timeout waiting for visible")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTimeoutWaitingForVisible() - { - await Page.SetContentAsync("
Hello
"); - var div = await Page.QuerySelectorAsync("div"); - var exception = await Assert.ThrowsAnyAsync(() => div.ScrollIntoViewIfNeededAsync(3000)); - Assert.Contains("element is not visible", exception.Message); - } - - private async Task TestWaitingAsync(IPage page, string after) - { - var div = await page.QuerySelectorAsync("div"); - var task = div.ScrollIntoViewIfNeededAsync(); - await page.EvaluateAsync("() => new Promise(f => setTimeout(f, 1000))"); - Assert.False(task.IsCompleted); - await div.EvaluateAsync(after); - await task; - } - } -} +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class ElementHandleScrollIntoViewTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/offscreenbuttons.html"); + for (int i = 0; i < 11; ++i) + { + var button = await Page.QuerySelectorAsync("#btn" + i); + double before = await button.EvaluateAsync(@"button => { + return button.getBoundingClientRect().right - window.innerWidth; + }"); + Assert.That(before, Is.EqualTo(10 * i)); + await button.ScrollIntoViewIfNeededAsync(); + double after = await button.EvaluateAsync(@"button => { + return button.getBoundingClientRect().right - window.innerWidth; + }"); + Assert.That(after <= 0, Is.True); + await Page.EvaluateAsync("() => window.scrollTo(0, 0)"); + } + } + + [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should throw for detached element")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowForDetachedElement() + { + await Page.SetContentAsync("
Hello
"); + var div = await Page.QuerySelectorAsync("div"); + await div.EvaluateAsync("div => div.remove()"); + var exception = Assert.CatchAsync(() => div.ScrollIntoViewIfNeededAsync()); + Assert.That(exception.Message, Does.Contain("Element is not attached to the DOM")); + } + + [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should wait for display:none to become visible")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForDisplayNoneToBecomeVisible() + { + await Page.SetContentAsync("
Hello
"); + await TestWaitingAsync(Page, "div => div.style.display = 'block'"); + } + + [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should wait for display:contents to become visible")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForDisplayContentsToBecomeVisible() + { + await Page.SetContentAsync("
Hello
"); + await TestWaitingAsync(Page, "div => div.style.display = 'block'"); + } + + [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should wait for visibility:hidden to become visible")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForVisibilityHiddenToBecomeVisible() + { + await Page.SetContentAsync("
Hello
"); + await TestWaitingAsync(Page, "div => div.style.visibility = 'visible'"); + } + + [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should wait for zero-sized element to become visible")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForZeroSiedElementToBecomeVisible() + { + await Page.SetContentAsync("
Hello
"); + await TestWaitingAsync(Page, "div => div.style.height = '100px'"); + } + + [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should wait for nested display:none to become visible")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForNestedDisplayNoneToBecomeVisible() + { + await Page.SetContentAsync("
Hello
"); + await TestWaitingAsync(Page, "div => div.parentElement.style.display = 'block'"); + } + + [PlaywrightTest("elementhandle-scroll-into-view.spec.ts", "should timeout waiting for visible")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTimeoutWaitingForVisible() + { + await Page.SetContentAsync("
Hello
"); + var div = await Page.QuerySelectorAsync("div"); + var exception = Assert.CatchAsync(() => div.ScrollIntoViewIfNeededAsync(3000)); + Assert.That(exception.Message, Does.Contain("element is not visible")); + } + + private async Task TestWaitingAsync(IPage page, string after) + { + var div = await page.QuerySelectorAsync("div"); + var task = div.ScrollIntoViewIfNeededAsync(); + await page.EvaluateAsync("() => new Promise(f => setTimeout(f, 1000))"); + Assert.That(task.IsCompleted, Is.False); + await div.EvaluateAsync(after); + await task; + } + } +} diff --git a/src/Playwright.Tests/ElementHandleSelectTextTests.cs b/src/PlaywrightSharp.Tests/ElementHandleSelectTextTests.cs similarity index 63% rename from src/Playwright.Tests/ElementHandleSelectTextTests.cs rename to src/PlaywrightSharp.Tests/ElementHandleSelectTextTests.cs index e7c395c387..42967e8331 100644 --- a/src/Playwright.Tests/ElementHandleSelectTextTests.cs +++ b/src/PlaywrightSharp.Tests/ElementHandleSelectTextTests.cs @@ -1,98 +1,91 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ElementHandleSelectTextTests : PlaywrightSharpPageBaseTest - { - /// - public ElementHandleSelectTextTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("elementhandle-select-text.spec.ts", "should select textarea")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectTextarea() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - var textarea = await Page.QuerySelectorAsync("textarea"); - await textarea.EvaluateAsync("textarea => textarea.value = 'some value'"); - await textarea.SelectTextAsync(); - - if (TestConstants.IsFirefox) - { - Assert.Equal(0, await textarea.EvaluateAsync("el => el.selectionStart")); - Assert.Equal(10, await textarea.EvaluateAsync("el => el.selectionEnd")); - } - else - { - Assert.Equal("some value", await Page.EvaluateAsync("() => window.getSelection().toString()")); - } - } - - [PlaywrightTest("elementhandle-select-text.spec.ts", "should select input")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectInput() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - var input = await Page.QuerySelectorAsync("input"); - await input.EvaluateAsync("input => input.value = 'some value'"); - await input.SelectTextAsync(); - - if (TestConstants.IsFirefox) - { - Assert.Equal(0, await input.EvaluateAsync("el => el.selectionStart")); - Assert.Equal(10, await input.EvaluateAsync("el => el.selectionEnd")); - } - else - { - Assert.Equal("some value", await Page.EvaluateAsync("() => window.getSelection().toString()")); - } - } - - [PlaywrightTest("elementhandle-select-text.spec.ts", "should select plain div")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectPlainDiv() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - var div = await Page.QuerySelectorAsync("div.plain"); - await div.EvaluateAsync("input => input.value = 'some value'"); - await div.SelectTextAsync(); - - Assert.Equal("Plain div", await Page.EvaluateAsync("() => window.getSelection().toString()")); - } - - [PlaywrightTest("elementhandle-select-text.spec.ts", "should timeout waiting for invisible element")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTimeoutWaitingForInvisibleElement() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - var textarea = await Page.QuerySelectorAsync("textarea"); - await textarea.EvaluateAsync("e => e.style.display = 'none'"); - - var exception = await Assert.ThrowsAnyAsync(() => textarea.SelectTextAsync(3000)); - Assert.Contains("element is not visible", exception.Message); - } - - [PlaywrightTest("elementhandle-select-text.spec.ts", "should wait for visible")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForVisible() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - var textarea = await Page.QuerySelectorAsync("textarea"); - await textarea.EvaluateAsync("textarea => textarea.value = 'some value'"); - await textarea.EvaluateAsync("e => e.style.display = 'none'"); - - var task = textarea.SelectTextAsync(3000); - await Page.EvaluateAsync("() => new Promise(f => setTimeout(f, 1000))"); - Assert.False(task.IsCompleted); - await textarea.EvaluateAsync("e => e.style.display = 'block'"); - await task; - } - } -} +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class ElementHandleSelectTextTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("elementhandle-select-text.spec.ts", "should select textarea")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSelectTextarea() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + var textarea = await Page.QuerySelectorAsync("textarea"); + await textarea.EvaluateAsync("textarea => textarea.value = 'some value'"); + await textarea.SelectTextAsync(); + + if (TestConstants.IsFirefox) + { + Assert.That(await textarea.EvaluateAsync("el => el.selectionStart"), Is.EqualTo(0)); + Assert.That(await textarea.EvaluateAsync("el => el.selectionEnd"), Is.EqualTo(10)); + } + else + { + Assert.That(await Page.EvaluateAsync("() => window.getSelection().toString()"), Is.EqualTo("some value")); + } + } + + [PlaywrightTest("elementhandle-select-text.spec.ts", "should select input")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSelectInput() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + var input = await Page.QuerySelectorAsync("input"); + await input.EvaluateAsync("input => input.value = 'some value'"); + await input.SelectTextAsync(); + + if (TestConstants.IsFirefox) + { + Assert.That(await input.EvaluateAsync("el => el.selectionStart"), Is.EqualTo(0)); + Assert.That(await input.EvaluateAsync("el => el.selectionEnd"), Is.EqualTo(10)); + } + else + { + Assert.That(await Page.EvaluateAsync("() => window.getSelection().toString()"), Is.EqualTo("some value")); + } + } + + [PlaywrightTest("elementhandle-select-text.spec.ts", "should select plain div")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSelectPlainDiv() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + var div = await Page.QuerySelectorAsync("div.plain"); + await div.EvaluateAsync("input => input.value = 'some value'"); + await div.SelectTextAsync(); + + Assert.That(await Page.EvaluateAsync("() => window.getSelection().toString()"), Is.EqualTo("Plain div")); + } + + [PlaywrightTest("elementhandle-select-text.spec.ts", "should timeout waiting for invisible element")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTimeoutWaitingForInvisibleElement() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + var textarea = await Page.QuerySelectorAsync("textarea"); + await textarea.EvaluateAsync("e => e.style.display = 'none'"); + + var exception = Assert.CatchAsync(() => textarea.SelectTextAsync(3000)); + Assert.That(exception.Message, Does.Contain("element is not visible")); + } + + [PlaywrightTest("elementhandle-select-text.spec.ts", "should wait for visible")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForVisible() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + var textarea = await Page.QuerySelectorAsync("textarea"); + await textarea.EvaluateAsync("textarea => textarea.value = 'some value'"); + await textarea.EvaluateAsync("e => e.style.display = 'none'"); + + var task = textarea.SelectTextAsync(3000); + await Page.EvaluateAsync("() => new Promise(f => setTimeout(f, 1000))"); + Assert.That(task.IsCompleted, Is.False); + await textarea.EvaluateAsync("e => e.style.display = 'block'"); + await task; + } + } +} diff --git a/src/Playwright.Tests/ElementHandleWaitForElementStateTests.cs b/src/PlaywrightSharp.Tests/ElementHandleWaitForElementStateTests.cs similarity index 76% rename from src/Playwright.Tests/ElementHandleWaitForElementStateTests.cs rename to src/PlaywrightSharp.Tests/ElementHandleWaitForElementStateTests.cs index 04b97a3a65..5528ff2a75 100644 --- a/src/Playwright.Tests/ElementHandleWaitForElementStateTests.cs +++ b/src/PlaywrightSharp.Tests/ElementHandleWaitForElementStateTests.cs @@ -1,163 +1,156 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///elementhandle-wait-for-element-state.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ElementHandleWaitForElementStateTests : PlaywrightSharpPageBaseTest - { - /// - public ElementHandleWaitForElementStateTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for visible")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForVisible() - { - await Page.SetContentAsync("
content
"); - var div = await Page.QuerySelectorAsync("div"); - var task = div.WaitForElementStateAsync(ElementState.Visible); - await GiveItAChanceToResolve(Page); - Assert.False(task.IsCompleted); - await div.EvaluateAsync("div => div.style.display = 'block'"); - await task; - } - - [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for already visible")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForAlreadyVisible() - { - await Page.SetContentAsync("
content
"); - var div = await Page.QuerySelectorAsync("div"); - await div.WaitForElementStateAsync(ElementState.Visible); - } - - [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should timeout waiting for visible")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTimeoutWaitingForVisible() - { - await Page.SetContentAsync("
content
"); - var div = await Page.QuerySelectorAsync("div"); - var exception = await Assert.ThrowsAnyAsync(() => div.WaitForElementStateAsync(ElementState.Visible, 1000)); - Assert.Contains("Timeout 1000ms exceeded", exception.Message); - } - - [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should throw waiting for visible when detached")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowWaitingForVisibleWhenDetached() - { - await Page.SetContentAsync("
content
"); - var div = await Page.QuerySelectorAsync("div"); - var task = div.WaitForElementStateAsync(ElementState.Visible); - await div.EvaluateAsync("div => div.remove()"); - var exception = await Assert.ThrowsAnyAsync(() => task); - Assert.Contains("Element is not attached to the DOM", exception.Message); - } - - [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for hidden")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForHidden() - { - await Page.SetContentAsync("
content
"); - var div = await Page.QuerySelectorAsync("div"); - var task = div.WaitForElementStateAsync(ElementState.Hidden); - await GiveItAChanceToResolve(Page); - Assert.False(task.IsCompleted); - await div.EvaluateAsync("div => div.style.display = 'none'"); - await task; - } - - [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for already hidden")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForAlreadyHidden() - { - await Page.SetContentAsync("
"); - var div = await Page.QuerySelectorAsync("div"); - await div.WaitForElementStateAsync(ElementState.Hidden); - } - - [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should throw waiting for hidden when detached")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowWaitingForHiddenWhenDetached() - { - await Page.SetContentAsync("
content
"); - var div = await Page.QuerySelectorAsync("div"); - var task = div.WaitForElementStateAsync(ElementState.Hidden); - await GiveItAChanceToResolve(Page); - Assert.False(task.IsCompleted); - await div.EvaluateAsync("div => div.remove()"); - await task; - } - - [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for enabled button")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForEnabledButton() - { - await Page.SetContentAsync(""); - var span = await Page.QuerySelectorAsync("text=Target"); - var task = span.WaitForElementStateAsync(ElementState.Enabled); - await GiveItAChanceToResolve(Page); - Assert.False(task.IsCompleted); - await span.EvaluateAsync("span => span.parentElement.disabled = false"); - await task; - } - - [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should throw waiting for enabled when detached")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowWaitingForEnabledWhenDetached() - { - await Page.SetContentAsync(""); - var button = await Page.QuerySelectorAsync("button"); - var task = button.WaitForElementStateAsync(ElementState.Enabled); - await button.EvaluateAsync("button => button.remove()"); - var exception = await Assert.ThrowsAnyAsync(() => task); - Assert.Contains("Element is not attached to the DOM", exception.Message); - } - - [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for disabled button")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForDisabledButton() - { - await Page.SetContentAsync(""); - var span = await Page.QuerySelectorAsync("text=Target"); - var task = span.WaitForElementStateAsync(ElementState.Disabled); - await GiveItAChanceToResolve(Page); - Assert.False(task.IsCompleted); - await span.EvaluateAsync("span => span.parentElement.disabled = true"); - await task; - } - - [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for stable position")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWaitForStablePosition() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - var button = await Page.QuerySelectorAsync("button"); - await Page.EvalOnSelectorAsync("button", @"button => { - button.style.transition = 'margin 10000ms linear 0s'; - button.style.marginLeft = '20000px'; - }"); - - var task = button.WaitForElementStateAsync(ElementState.Stable); - await GiveItAChanceToResolve(Page); - Assert.False(task.IsCompleted); - await button.EvaluateAsync("button => button.style.transition = ''"); - await task; - } - - private async Task GiveItAChanceToResolve(IPage page) - { - for (int i = 0; i < 5; i++) - { - await page.EvaluateAsync("() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f)))"); - } - } - } -} +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///elementhandle-wait-for-element-state.spec.ts + public class ElementHandleWaitForElementStateTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for visible")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForVisible() + { + await Page.SetContentAsync("
content
"); + var div = await Page.QuerySelectorAsync("div"); + var task = div.WaitForElementStateAsync(ElementState.Visible); + await GiveItAChanceToResolve(Page); + Assert.That(task.IsCompleted, Is.False); + await div.EvaluateAsync("div => div.style.display = 'block'"); + await task; + } + + [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for already visible")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForAlreadyVisible() + { + await Page.SetContentAsync("
content
"); + var div = await Page.QuerySelectorAsync("div"); + await div.WaitForElementStateAsync(ElementState.Visible); + } + + [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should timeout waiting for visible")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTimeoutWaitingForVisible() + { + await Page.SetContentAsync("
content
"); + var div = await Page.QuerySelectorAsync("div"); + var exception = Assert.CatchAsync(() => div.WaitForElementStateAsync(ElementState.Visible, 1000)); + Assert.That(exception.Message, Does.Contain("Timeout 1000ms exceeded")); + } + + [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should throw waiting for visible when detached")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowWaitingForVisibleWhenDetached() + { + await Page.SetContentAsync("
content
"); + var div = await Page.QuerySelectorAsync("div"); + var task = div.WaitForElementStateAsync(ElementState.Visible); + await div.EvaluateAsync("div => div.remove()"); + var exception = Assert.CatchAsync(() => task); + Assert.That(exception.Message, Does.Contain("Element is not attached to the DOM")); + } + + [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for hidden")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForHidden() + { + await Page.SetContentAsync("
content
"); + var div = await Page.QuerySelectorAsync("div"); + var task = div.WaitForElementStateAsync(ElementState.Hidden); + await GiveItAChanceToResolve(Page); + Assert.That(task.IsCompleted, Is.False); + await div.EvaluateAsync("div => div.style.display = 'none'"); + await task; + } + + [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for already hidden")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForAlreadyHidden() + { + await Page.SetContentAsync("
"); + var div = await Page.QuerySelectorAsync("div"); + await div.WaitForElementStateAsync(ElementState.Hidden); + } + + [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should throw waiting for hidden when detached")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowWaitingForHiddenWhenDetached() + { + await Page.SetContentAsync("
content
"); + var div = await Page.QuerySelectorAsync("div"); + var task = div.WaitForElementStateAsync(ElementState.Hidden); + await GiveItAChanceToResolve(Page); + Assert.That(task.IsCompleted, Is.False); + await div.EvaluateAsync("div => div.remove()"); + await task; + } + + [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for enabled button")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForEnabledButton() + { + await Page.SetContentAsync(""); + var span = await Page.QuerySelectorAsync("text=Target"); + var task = span.WaitForElementStateAsync(ElementState.Enabled); + await GiveItAChanceToResolve(Page); + Assert.That(task.IsCompleted, Is.False); + await span.EvaluateAsync("span => span.parentElement.disabled = false"); + await task; + } + + [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should throw waiting for enabled when detached")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowWaitingForEnabledWhenDetached() + { + await Page.SetContentAsync(""); + var button = await Page.QuerySelectorAsync("button"); + var task = button.WaitForElementStateAsync(ElementState.Enabled); + await button.EvaluateAsync("button => button.remove()"); + var exception = Assert.CatchAsync(() => task); + Assert.That(exception.Message, Does.Contain("Element is not attached to the DOM")); + } + + [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for disabled button")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForDisabledButton() + { + await Page.SetContentAsync(""); + var span = await Page.QuerySelectorAsync("text=Target"); + var task = span.WaitForElementStateAsync(ElementState.Disabled); + await GiveItAChanceToResolve(Page); + Assert.That(task.IsCompleted, Is.False); + await span.EvaluateAsync("span => span.parentElement.disabled = true"); + await task; + } + + [PlaywrightTest("elementhandle-wait-for-element-state.spec.ts", "should wait for stable position")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWaitForStablePosition() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + var button = await Page.QuerySelectorAsync("button"); + await Page.EvalOnSelectorAsync("button", @"button => { + button.style.transition = 'margin 10000ms linear 0s'; + button.style.marginLeft = '20000px'; + }"); + + var task = button.WaitForElementStateAsync(ElementState.Stable); + await GiveItAChanceToResolve(Page); + Assert.That(task.IsCompleted, Is.False); + await button.EvaluateAsync("button => button.style.transition = ''"); + await task; + } + + private async Task GiveItAChanceToResolve(IPage page) + { + for (int i = 0; i < 5; i++) + { + await page.EvaluateAsync("() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f)))"); + } + } + } +} diff --git a/src/Playwright.Tests/EmulationFocusTests.cs b/src/PlaywrightSharp.Tests/EmulationFocusTests.cs similarity index 72% rename from src/Playwright.Tests/EmulationFocusTests.cs rename to src/PlaywrightSharp.Tests/EmulationFocusTests.cs index 1d24af0def..03e9bcc8b5 100644 --- a/src/Playwright.Tests/EmulationFocusTests.cs +++ b/src/PlaywrightSharp.Tests/EmulationFocusTests.cs @@ -1,192 +1,185 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class EmulationFocusTests : PlaywrightSharpPageBaseTest - { - /// - public EmulationFocusTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("emulation-focus.spec.ts", "should think that it is focused by default")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThinkThatItIsFocusedByDefault() - { - Assert.True(await Page.EvaluateAsync("document.hasFocus()")); - } - - [PlaywrightTest("emulation-focus.spec.ts", "should think that all pages are focused")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThinkThatAllPagesAreFocused() - { - var page2 = await Page.Context.NewPageAsync(); - Assert.True(await Page.EvaluateAsync("document.hasFocus()")); - Assert.True(await page2.EvaluateAsync("document.hasFocus()")); - } - - [PlaywrightTest("emulation-focus.spec.ts", "should focus popups by default")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFocusPopupsByDefault() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup); - - await TaskUtils.WhenAll( - popupTask, - Page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); - - var popup = popupTask.Result; - - Assert.True(await Page.EvaluateAsync("document.hasFocus()")); - Assert.True(await popup.EvaluateAsync("document.hasFocus()")); - } - - [PlaywrightTest("emulation-focus.spec.ts", "should provide target for keyboard events")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldProvideTargetForKeyboardEvents() - { - var page2 = await Page.Context.NewPageAsync(); - - await TaskUtils.WhenAll( - Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"), - page2.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html")); - - await TaskUtils.WhenAll( - Page.FocusAsync("input"), - page2.FocusAsync("input")); - - string text = "first"; - string text2 = "second"; - - await TaskUtils.WhenAll( - Page.Keyboard.TypeAsync(text), - page2.Keyboard.TypeAsync(text2)); - - var results = await TaskUtils.WhenAll( - Page.EvaluateAsync("result"), - page2.EvaluateAsync("result")); - - Assert.Equal(text, results.Item1); - Assert.Equal(text2, results.Item2); - } - - [PlaywrightTest("emulation-focus.spec.ts", "should not affect mouse event target page")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotAffectMouseEventTargetPage() - { - var page2 = await Page.Context.NewPageAsync(); - string clickCounter = @"function clickCounter() { - document.onclick = () => window.clickCount = (window.clickCount || 0) + 1; - }"; - - await TaskUtils.WhenAll( - Page.EvaluateAsync(clickCounter), - page2.EvaluateAsync(clickCounter), - Page.FocusAsync("body"), - page2.FocusAsync("body")); - - await TaskUtils.WhenAll( - Page.Mouse.ClickAsync(1, 1), - page2.Mouse.ClickAsync(1, 1)); - - var counters = await TaskUtils.WhenAll( - Page.EvaluateAsync("window.clickCount"), - page2.EvaluateAsync("window.clickCount")); - - Assert.Equal(1, counters.Item1); - Assert.Equal(1, counters.Item2); - } - - [PlaywrightTest("emulation-focus.spec.ts", "should change document.activeElement")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldChangeDocumentActiveElement() - { - var page2 = await Page.Context.NewPageAsync(); - - await TaskUtils.WhenAll( - Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"), - page2.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html")); - - await TaskUtils.WhenAll( - Page.FocusAsync("input"), - page2.FocusAsync("textArea")); - - var results = await TaskUtils.WhenAll( - Page.EvaluateAsync("document.activeElement.tagName"), - page2.EvaluateAsync("document.activeElement.tagName")); - - Assert.Equal("INPUT", results.Item1); - Assert.Equal("TEXTAREA", results.Item2); - } - - [PlaywrightTest("emulation-focus.spec.ts", "should not affect screenshots")] - [Fact(Skip = "We need screenshot features first")] - public void ShouldNotAffectScreenshots() - { - } - - [PlaywrightTest("emulation-focus.spec.ts", "should change focused iframe")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldChangeFocusedIframe() - { - await Page.GoToAsync(TestConstants.EmptyPage); - - var (frame1, frame2) = await TaskUtils.WhenAll( - FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.ServerUrl + "/input/textarea.html"), - FrameUtils.AttachFrameAsync(Page, "frame2", TestConstants.ServerUrl + "/input/textarea.html")); - - string logger = @"function logger() { - self._events = []; - const element = document.querySelector('input'); - element.onfocus = element.onblur = (e) => self._events.push(e.type); - }"; - - await TaskUtils.WhenAll( - frame1.EvaluateAsync(logger), - frame2.EvaluateAsync(logger)); - - var focused = await TaskUtils.WhenAll( - frame1.EvaluateAsync("document.hasFocus()"), - frame2.EvaluateAsync("document.hasFocus()")); - - Assert.False(focused.Item1); - Assert.False(focused.Item2); - - await frame1.FocusAsync("input"); - var events = await TaskUtils.WhenAll( - frame1.EvaluateAsync("self._events"), - frame2.EvaluateAsync("self._events")); - - Assert.Equal(new[] { "focus" }, events.Item1); - Assert.Empty(events.Item2); - - focused = await TaskUtils.WhenAll( - frame1.EvaluateAsync("document.hasFocus()"), - frame2.EvaluateAsync("document.hasFocus()")); - - Assert.True(focused.Item1); - Assert.False(focused.Item2); - - await frame2.FocusAsync("input"); - events = await TaskUtils.WhenAll( - frame1.EvaluateAsync("self._events"), - frame2.EvaluateAsync("self._events")); - - Assert.Equal(new[] { "focus", "blur" }, events.Item1); - Assert.Equal(new[] { "focus" }, events.Item2); - - focused = await TaskUtils.WhenAll( - frame1.EvaluateAsync("document.hasFocus()"), - frame2.EvaluateAsync("document.hasFocus()")); - - Assert.False(focused.Item1); - Assert.True(focused.Item2); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class EmulationFocusTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("emulation-focus.spec.ts", "should think that it is focused by default")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThinkThatItIsFocusedByDefault() + { + Assert.That(await Page.EvaluateAsync("document.hasFocus()"), Is.True); + } + + [PlaywrightTest("emulation-focus.spec.ts", "should think that all pages are focused")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThinkThatAllPagesAreFocused() + { + var page2 = await Page.Context.NewPageAsync(); + Assert.That(await Page.EvaluateAsync("document.hasFocus()"), Is.True); + Assert.That(await page2.EvaluateAsync("document.hasFocus()"), Is.True); + } + + [PlaywrightTest("emulation-focus.spec.ts", "should focus popups by default")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFocusPopupsByDefault() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup); + + await TaskUtils.WhenAll( + popupTask, + Page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); + + var popup = popupTask.Result; + + Assert.That(await Page.EvaluateAsync("document.hasFocus()"), Is.True); + Assert.That(await popup.EvaluateAsync("document.hasFocus()"), Is.True); + } + + [PlaywrightTest("emulation-focus.spec.ts", "should provide target for keyboard events")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldProvideTargetForKeyboardEvents() + { + var page2 = await Page.Context.NewPageAsync(); + + await TaskUtils.WhenAll( + Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"), + page2.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html")); + + await TaskUtils.WhenAll( + Page.FocusAsync("input"), + page2.FocusAsync("input")); + + string text = "first"; + string text2 = "second"; + + await TaskUtils.WhenAll( + Page.Keyboard.TypeAsync(text), + page2.Keyboard.TypeAsync(text2)); + + var results = await TaskUtils.WhenAll( + Page.EvaluateAsync("result"), + page2.EvaluateAsync("result")); + + Assert.That(results.Item1, Is.EqualTo(text)); + Assert.That(results.Item2, Is.EqualTo(text2)); + } + + [PlaywrightTest("emulation-focus.spec.ts", "should not affect mouse event target page")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotAffectMouseEventTargetPage() + { + var page2 = await Page.Context.NewPageAsync(); + string clickCounter = @"function clickCounter() { + document.onclick = () => window.clickCount = (window.clickCount || 0) + 1; + }"; + + await TaskUtils.WhenAll( + Page.EvaluateAsync(clickCounter), + page2.EvaluateAsync(clickCounter), + Page.FocusAsync("body"), + page2.FocusAsync("body")); + + await TaskUtils.WhenAll( + Page.Mouse.ClickAsync(1, 1), + page2.Mouse.ClickAsync(1, 1)); + + var counters = await TaskUtils.WhenAll( + Page.EvaluateAsync("window.clickCount"), + page2.EvaluateAsync("window.clickCount")); + + Assert.That(counters.Item1, Is.EqualTo(1)); + Assert.That(counters.Item2, Is.EqualTo(1)); + } + + [PlaywrightTest("emulation-focus.spec.ts", "should change document.activeElement")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldChangeDocumentActiveElement() + { + var page2 = await Page.Context.NewPageAsync(); + + await TaskUtils.WhenAll( + Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"), + page2.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html")); + + await TaskUtils.WhenAll( + Page.FocusAsync("input"), + page2.FocusAsync("textArea")); + + var results = await TaskUtils.WhenAll( + Page.EvaluateAsync("document.activeElement.tagName"), + page2.EvaluateAsync("document.activeElement.tagName")); + + Assert.That(results.Item1, Is.EqualTo("INPUT")); + Assert.That(results.Item2, Is.EqualTo("TEXTAREA")); + } + + [PlaywrightTest("emulation-focus.spec.ts", "should not affect screenshots")] + [Test, Ignore("We need screenshot features first")] + public void ShouldNotAffectScreenshots() + { + } + + [PlaywrightTest("emulation-focus.spec.ts", "should change focused iframe")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldChangeFocusedIframe() + { + await Page.GoToAsync(TestConstants.EmptyPage); + + var (frame1, frame2) = await TaskUtils.WhenAll( + FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.ServerUrl + "/input/textarea.html"), + FrameUtils.AttachFrameAsync(Page, "frame2", TestConstants.ServerUrl + "/input/textarea.html")); + + string logger = @"function logger() { + self._events = []; + const element = document.querySelector('input'); + element.onfocus = element.onblur = (e) => self._events.push(e.type); + }"; + + await TaskUtils.WhenAll( + frame1.EvaluateAsync(logger), + frame2.EvaluateAsync(logger)); + + var focused = await TaskUtils.WhenAll( + frame1.EvaluateAsync("document.hasFocus()"), + frame2.EvaluateAsync("document.hasFocus()")); + + Assert.That(focused.Item1, Is.False); + Assert.That(focused.Item2, Is.False); + + await frame1.FocusAsync("input"); + var events = await TaskUtils.WhenAll( + frame1.EvaluateAsync("self._events"), + frame2.EvaluateAsync("self._events")); + + Assert.That(events.Item1, Is.EqualTo(new[] { "focus" })); + Assert.That(events.Item2, Is.Empty); + + focused = await TaskUtils.WhenAll( + frame1.EvaluateAsync("document.hasFocus()"), + frame2.EvaluateAsync("document.hasFocus()")); + + Assert.That(focused.Item1, Is.True); + Assert.That(focused.Item2, Is.False); + + await frame2.FocusAsync("input"); + events = await TaskUtils.WhenAll( + frame1.EvaluateAsync("self._events"), + frame2.EvaluateAsync("self._events")); + + Assert.That(events.Item1, Is.EqualTo(new[] { "focus", "blur" })); + Assert.That(events.Item2, Is.EqualTo(new[] { "focus" })); + + focused = await TaskUtils.WhenAll( + frame1.EvaluateAsync("document.hasFocus()"), + frame2.EvaluateAsync("document.hasFocus()")); + + Assert.That(focused.Item1, Is.False); + Assert.That(focused.Item2, Is.True); + } + } +} diff --git a/src/Playwright.Tests/EvalOnSelectorAllTests.cs b/src/PlaywrightSharp.Tests/EvalOnSelectorAllTests.cs similarity index 60% rename from src/Playwright.Tests/EvalOnSelectorAllTests.cs rename to src/PlaywrightSharp.Tests/EvalOnSelectorAllTests.cs index 0821e3881c..629efc6993 100644 --- a/src/Playwright.Tests/EvalOnSelectorAllTests.cs +++ b/src/PlaywrightSharp.Tests/EvalOnSelectorAllTests.cs @@ -1,91 +1,84 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class EvalOnSelectorAllTests : PlaywrightSharpPageBaseTest - { - /// - public EvalOnSelectorAllTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("eval-on-selector-all.spec.ts", "should work with css selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithCssSelector() - { - await Page.SetContentAsync("
hello
beautiful
world!
"); - int divsCount = await Page.EvalOnSelectorAllAsync("css=div", "divs => divs.length"); - Assert.Equal(3, divsCount); - } - - [PlaywrightTest("eval-on-selector-all.spec.ts", "should work with text selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithTextSelector() - { - await Page.SetContentAsync("
hello
beautiful
beautiful
world!
"); - int divsCount = await Page.EvalOnSelectorAllAsync("text=beautiful", "divs => divs.length"); - Assert.Equal(2, divsCount); - } - - [PlaywrightTest("eval-on-selector-all.spec.ts", "should work with xpath selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithXpathSelector() - { - await Page.SetContentAsync("
hello
beautiful
world!
"); - int divsCount = await Page.EvalOnSelectorAllAsync("xpath=/html/body/div", "divs => divs.length"); - Assert.Equal(3, divsCount); - } - - [PlaywrightTest("eval-on-selector-all.spec.ts", "should auto-detect css selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAutoDetectCssSelector() - { - await Page.SetContentAsync("
hello
beautiful
world!
"); - int divsCount = await Page.EvalOnSelectorAllAsync("div", "divs => divs.length"); - Assert.Equal(3, divsCount); - } - - [PlaywrightTest("eval-on-selector-all.spec.ts", "should support >> syntax")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportDoubleGreaterThanSyntax() - { - await Page.SetContentAsync("
hello
beautiful
world!
Not this one"); - int spansCount = await Page.EvalOnSelectorAllAsync("css=div >> css=span", "spans => spans.length"); - Assert.Equal(3, spansCount); - } - - [PlaywrightTest("eval-on-selector-all.spec.ts", "should should support * capture")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportStarCapture() - { - await Page.SetContentAsync("
a
b
"); - Assert.Equal(1, await Page.EvalOnSelectorAllAsync("*css=div >> \"b\"", "divs => divs.length")); - Assert.Equal(1, await Page.EvalOnSelectorAllAsync("section >> *css=div >> \"b\"", "divs => divs.length")); - Assert.Equal(4, await Page.EvalOnSelectorAllAsync("section >> *", "divs => divs.length")); - - await Page.SetContentAsync("
aa
"); - Assert.Equal(1, await Page.EvalOnSelectorAllAsync("*css=div >> \"a\"", "divs => divs.length")); - Assert.Equal(1, await Page.EvalOnSelectorAllAsync("section >> *css=div >> \"a\"", "divs => divs.length")); - - await Page.SetContentAsync("
a
a
a
"); - Assert.Equal(3, await Page.EvalOnSelectorAllAsync("*css=div >> \"a\"", "divs => divs.length")); - Assert.Equal(1, await Page.EvalOnSelectorAllAsync("section >> *css=div >> \"a\"", "divs => divs.length")); - } - - [PlaywrightTest("eval-on-selector-all.spec.ts", "should support * capture when multiple paths match")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportStarCaptureWhenMultiplePathsMatch() - { - await Page.SetContentAsync("
"); - Assert.Equal(2, await Page.EvalOnSelectorAllAsync("*css=div >> span", "els => els.length")); - - await Page.SetContentAsync("
"); - Assert.Equal(2, await Page.EvalOnSelectorAllAsync("*css=div >> span", "els => els.length")); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class EvalOnSelectorAllTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("eval-on-selector-all.spec.ts", "should work with css selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithCssSelector() + { + await Page.SetContentAsync("
hello
beautiful
world!
"); + int divsCount = await Page.EvalOnSelectorAllAsync("css=div", "divs => divs.length"); + Assert.That(divsCount, Is.EqualTo(3)); + } + + [PlaywrightTest("eval-on-selector-all.spec.ts", "should work with text selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithTextSelector() + { + await Page.SetContentAsync("
hello
beautiful
beautiful
world!
"); + int divsCount = await Page.EvalOnSelectorAllAsync("text=beautiful", "divs => divs.length"); + Assert.That(divsCount, Is.EqualTo(2)); + } + + [PlaywrightTest("eval-on-selector-all.spec.ts", "should work with xpath selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithXpathSelector() + { + await Page.SetContentAsync("
hello
beautiful
world!
"); + int divsCount = await Page.EvalOnSelectorAllAsync("xpath=/html/body/div", "divs => divs.length"); + Assert.That(divsCount, Is.EqualTo(3)); + } + + [PlaywrightTest("eval-on-selector-all.spec.ts", "should auto-detect css selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAutoDetectCssSelector() + { + await Page.SetContentAsync("
hello
beautiful
world!
"); + int divsCount = await Page.EvalOnSelectorAllAsync("div", "divs => divs.length"); + Assert.That(divsCount, Is.EqualTo(3)); + } + + [PlaywrightTest("eval-on-selector-all.spec.ts", "should support >> syntax")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportDoubleGreaterThanSyntax() + { + await Page.SetContentAsync("
hello
beautiful
world!
Not this one"); + int spansCount = await Page.EvalOnSelectorAllAsync("css=div >> css=span", "spans => spans.length"); + Assert.That(spansCount, Is.EqualTo(3)); + } + + [PlaywrightTest("eval-on-selector-all.spec.ts", "should should support * capture")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportStarCapture() + { + await Page.SetContentAsync("
a
b
"); + Assert.That(await Page.EvalOnSelectorAllAsync("*css=div >> \"b\"", "divs => divs.length"), Is.EqualTo(1)); + Assert.That(await Page.EvalOnSelectorAllAsync("section >> *css=div >> \"b\"", "divs => divs.length"), Is.EqualTo(1)); + Assert.That(await Page.EvalOnSelectorAllAsync("section >> *", "divs => divs.length"), Is.EqualTo(4)); + + await Page.SetContentAsync("
aa
"); + Assert.That(await Page.EvalOnSelectorAllAsync("*css=div >> \"a\"", "divs => divs.length"), Is.EqualTo(1)); + Assert.That(await Page.EvalOnSelectorAllAsync("section >> *css=div >> \"a\"", "divs => divs.length"), Is.EqualTo(1)); + + await Page.SetContentAsync("
a
a
a
"); + Assert.That(await Page.EvalOnSelectorAllAsync("*css=div >> \"a\"", "divs => divs.length"), Is.EqualTo(3)); + Assert.That(await Page.EvalOnSelectorAllAsync("section >> *css=div >> \"a\"", "divs => divs.length"), Is.EqualTo(1)); + } + + [PlaywrightTest("eval-on-selector-all.spec.ts", "should support * capture when multiple paths match")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportStarCaptureWhenMultiplePathsMatch() + { + await Page.SetContentAsync("
"); + Assert.That(await Page.EvalOnSelectorAllAsync("*css=div >> span", "els => els.length"), Is.EqualTo(2)); + + await Page.SetContentAsync("
"); + Assert.That(await Page.EvalOnSelectorAllAsync("*css=div >> span", "els => els.length"), Is.EqualTo(2)); + } + } +} diff --git a/src/Playwright.Tests/EvalOnSelectorTests.cs b/src/PlaywrightSharp.Tests/EvalOnSelectorTests.cs similarity index 53% rename from src/Playwright.Tests/EvalOnSelectorTests.cs rename to src/PlaywrightSharp.Tests/EvalOnSelectorTests.cs index 0e8c4a9a67..ec7b8dcc7c 100644 --- a/src/Playwright.Tests/EvalOnSelectorTests.cs +++ b/src/PlaywrightSharp.Tests/EvalOnSelectorTests.cs @@ -1,263 +1,256 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class EvalOnSelectorTests : PlaywrightSharpPageBaseTest - { - /// - public EvalOnSelectorTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should work with css selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithCssSelector() - { - await Page.SetContentAsync("
43543
"); - string idAttribute = await Page.EvalOnSelectorAsync("css=section", "e => e.id"); - Assert.Equal("testAttribute", idAttribute); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should work with id selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithIdSelector() - { - await Page.SetContentAsync("
43543
"); - string idAttribute = await Page.EvalOnSelectorAsync("id=testAttribute", "e => e.id"); - Assert.Equal("testAttribute", idAttribute); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should work with data-test selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithDataTestSelector() - { - await Page.SetContentAsync("
43543
"); - string idAttribute = await Page.EvalOnSelectorAsync("data-test=foo", "e => e.id"); - Assert.Equal("testAttribute", idAttribute); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should work with data-testid selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithDataTestidSelector() - { - await Page.SetContentAsync("
43543
"); - string idAttribute = await Page.EvalOnSelectorAsync("data-testid=foo", "e => e.id"); - Assert.Equal("testAttribute", idAttribute); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should work with data-test-id selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithDataTestIdSelector() - { - await Page.SetContentAsync("
43543
"); - string idAttribute = await Page.EvalOnSelectorAsync("data-test-id=foo", "e => e.id"); - Assert.Equal("testAttribute", idAttribute); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should work with text selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithTextSelector() - { - await Page.SetContentAsync("
43543
"); - string idAttribute = await Page.EvalOnSelectorAsync("text=\"43543\"", "e => e.id"); - Assert.Equal("testAttribute", idAttribute); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should work with xpath selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithXpathSelector() - { - await Page.SetContentAsync("
43543
"); - string idAttribute = await Page.EvalOnSelectorAsync("xpath=/html/body/section", "e => e.id"); - Assert.Equal("testAttribute", idAttribute); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should work with text selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithTextSelector2() - { - await Page.SetContentAsync("
43543
"); - string idAttribute = await Page.EvalOnSelectorAsync("text=43543", "e => e.id"); - Assert.Equal("testAttribute", idAttribute); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should auto-detect css selector")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAutoDetectCssSelector() - { - await Page.SetContentAsync("
43543
"); - string idAttribute = await Page.EvalOnSelectorAsync("section", "e => e.id"); - Assert.Equal("testAttribute", idAttribute); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should auto-detect nested selectors")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAutoDetectNestedSelectors() - { - await Page.SetContentAsync("
43543Hello
"); - string idAttribute = await Page.EvalOnSelectorAsync("div[foo=bar] > section >> \"Hello\" >> div", "e => e.id"); - Assert.Equal("target", idAttribute); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should auto-detect css selector with attributes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAutoDetectCssSelectorWithAttributes() - { - await Page.SetContentAsync("
43543
"); - string idAttribute = await Page.EvalOnSelectorAsync("section[id=\"testAttribute\"]", "e => e.id"); - Assert.Equal("testAttribute", idAttribute); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should accept arguments")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptArguments() - { - await Page.SetContentAsync("
hello
"); - string text = await Page.EvalOnSelectorAsync("section", "(e, suffix) => e.textContent + suffix", " world!"); - Assert.Equal("hello world!", text); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should accept ElementHandles as arguments")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptElementHandlesAsArguments() - { - await Page.SetContentAsync("
hello
world
"); - var divHandle = await Page.QuerySelectorAsync("div"); - string text = await Page.EvalOnSelectorAsync("section", "(e, div) => e.textContent + div.textContent", divHandle); - Assert.Equal("hello world", text); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should throw error if no element is found")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowErrorIfNoElementIsFound() - { - var exception = await Assert.ThrowsAsync(() - => Page.EvalOnSelectorAsync("section", "e => e.id")); - Assert.Contains("failed to find element matching selector \"section\"", exception.Message); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should support >> syntax")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportDoubleGreaterThanSyntax() - { - await Page.SetContentAsync("
hello
"); - string text = await Page.EvalOnSelectorAsync("css=section >> css=div", "(e, suffix) => e.textContent + suffix", " world!"); - Assert.Equal("hello world!", text); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should support >> syntax with different engines")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportDoubleGreaterThanSyntaxWithDifferentEngines() - { - await Page.SetContentAsync("
hello
"); - string text = await Page.EvalOnSelectorAsync("xpath=/html/body/section >> css=div >> text=\"hello\"", "(e, suffix) => e.textContent + suffix", " world!"); - Assert.Equal("hello world!", text); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should support spaces with >> syntax")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportSpacesWithDoubleGreaterThanSyntax() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/deep-shadow.html"); - string text = await Page.EvalOnSelectorAsync(" css = div >>css=div>>css = span ", "e => e.textContent"); - Assert.Equal("Hello from root2", text); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should not stop at first failure with >> syntax")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotStopAtFirstFailureWithDoubleGraterThanSyntax() - { - await Page.SetContentAsync("
Next
"); - string text = await Page.EvalOnSelectorAsync("button >> \"Next\"", "(e) => e.outerHTML"); - Assert.Equal("", text); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should support * capture")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportStarCapture() - { - await Page.SetContentAsync("
a
b
"); - Assert.Equal("
b
", await Page.EvalOnSelectorAsync("*css=div >> \"b\"", "(e) => e.outerHTML")); - Assert.Equal("
b
", await Page.EvalOnSelectorAsync("section >> *css=div >> \"b\"", "(e) => e.outerHTML")); - Assert.Equal("b", await Page.EvalOnSelectorAsync("css=div >> *text=\"b\"", "(e) => e.outerHTML")); - Assert.NotNull(await Page.QuerySelectorAsync("*")); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should throw on multiple * captures")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowOnMultipleStarCaptures() - { - var exception = await Assert.ThrowsAnyAsync(() => Page.EvalOnSelectorAsync("*css=div >> *css=span", "(e) => e.outerHTML")); - Assert.Equal("Only one of the selectors can capture using * modifier", exception.Message); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should throw on malformed * capture")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowOnMalformedStarCapture() - { - var exception = await Assert.ThrowsAnyAsync(() => Page.EvalOnSelectorAsync("*=div", "(e) => e.outerHTML")); - Assert.Equal("Unknown engine \"\" while parsing selector *=div", exception.Message); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should work with spaces in css attributes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithSpacesInCssAttributes() - { - await Page.SetContentAsync("
"); - Assert.NotNull(await Page.WaitForSelectorAsync("[placeholder = \"Select date\"]")); - Assert.NotNull(await Page.WaitForSelectorAsync("[placeholder = 'Select date']")); - Assert.NotNull(await Page.WaitForSelectorAsync("input[placeholder = \"Select date\"]")); - Assert.NotNull(await Page.WaitForSelectorAsync("input[placeholder = 'Select date']")); - Assert.NotNull(await Page.QuerySelectorAsync("[placeholder = \"Select date\"]")); - Assert.NotNull(await Page.QuerySelectorAsync("[placeholder = 'Select date']")); - Assert.NotNull(await Page.QuerySelectorAsync("input[placeholder = \"Select date\"]")); - Assert.NotNull(await Page.QuerySelectorAsync("input[placeholder = 'Select date']")); - Assert.Equal("", await Page.EvalOnSelectorAsync("[placeholder = \"Select date\"]", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("[placeholder = 'Select date']", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("input[placeholder = \"Select date\"]", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("input[placeholder = 'Select date']", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("css =[placeholder = \"Select date\"]", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("css =[placeholder = 'Select date']", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("css = input[placeholder = \"Select date\"]", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("css = input[placeholder = 'Select date']", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div >> [placeholder = \"Select date\"]", "e => e.outerHTML")); - Assert.Equal("", await Page.EvalOnSelectorAsync("div >> [placeholder = 'Select date']", "e => e.outerHTML")); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should work with quotes in css attributes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWihQuotesInCssAttributes() - { - await Page.SetContentAsync("
"); - Assert.NotNull(await Page.QuerySelectorAsync("[placeholder = \"Select\\\"date\"]")); - Assert.NotNull(await Page.QuerySelectorAsync("[placeholder = 'Select\"date']")); - - await Page.SetContentAsync("
"); - Assert.NotNull(await Page.QuerySelectorAsync("[placeholder = \"Select \\\" date\"]")); - Assert.NotNull(await Page.QuerySelectorAsync("[placeholder = 'Select \" date']")); - - await Page.SetContentAsync("
"); - Assert.NotNull(await Page.QuerySelectorAsync("[placeholder = \"Select'date\"]")); - Assert.NotNull(await Page.QuerySelectorAsync("[placeholder = 'Select\\'date']")); - - await Page.SetContentAsync("
"); - Assert.NotNull(await Page.QuerySelectorAsync("[placeholder = \"Select ' date\"]")); - Assert.NotNull(await Page.QuerySelectorAsync("[placeholder = 'Select \\' date']")); - } - - [PlaywrightTest("eval-on-selector.spec.ts", "should work with quotes in css attributes when missing")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWihQuotesInCssAttributesWhenMissing() - { - var inputTask = Page.WaitForSelectorAsync("[placeholder = \"Select\\\"date\"]"); - Assert.Null(await Page.QuerySelectorAsync("[placeholder = \"Select\\\"date\"]")); - await Page.SetContentAsync("
"); - await inputTask; - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class EvalOnSelectorTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("eval-on-selector.spec.ts", "should work with css selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithCssSelector() + { + await Page.SetContentAsync("
43543
"); + string idAttribute = await Page.EvalOnSelectorAsync("css=section", "e => e.id"); + Assert.That(idAttribute, Is.EqualTo("testAttribute")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should work with id selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithIdSelector() + { + await Page.SetContentAsync("
43543
"); + string idAttribute = await Page.EvalOnSelectorAsync("id=testAttribute", "e => e.id"); + Assert.That(idAttribute, Is.EqualTo("testAttribute")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should work with data-test selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithDataTestSelector() + { + await Page.SetContentAsync("
43543
"); + string idAttribute = await Page.EvalOnSelectorAsync("data-test=foo", "e => e.id"); + Assert.That(idAttribute, Is.EqualTo("testAttribute")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should work with data-testid selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithDataTestidSelector() + { + await Page.SetContentAsync("
43543
"); + string idAttribute = await Page.EvalOnSelectorAsync("data-testid=foo", "e => e.id"); + Assert.That(idAttribute, Is.EqualTo("testAttribute")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should work with data-test-id selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithDataTestIdSelector() + { + await Page.SetContentAsync("
43543
"); + string idAttribute = await Page.EvalOnSelectorAsync("data-test-id=foo", "e => e.id"); + Assert.That(idAttribute, Is.EqualTo("testAttribute")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should work with text selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithTextSelector() + { + await Page.SetContentAsync("
43543
"); + string idAttribute = await Page.EvalOnSelectorAsync("text=\"43543\"", "e => e.id"); + Assert.That(idAttribute, Is.EqualTo("testAttribute")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should work with xpath selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithXpathSelector() + { + await Page.SetContentAsync("
43543
"); + string idAttribute = await Page.EvalOnSelectorAsync("xpath=/html/body/section", "e => e.id"); + Assert.That(idAttribute, Is.EqualTo("testAttribute")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should work with text selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithTextSelector2() + { + await Page.SetContentAsync("
43543
"); + string idAttribute = await Page.EvalOnSelectorAsync("text=43543", "e => e.id"); + Assert.That(idAttribute, Is.EqualTo("testAttribute")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should auto-detect css selector")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAutoDetectCssSelector() + { + await Page.SetContentAsync("
43543
"); + string idAttribute = await Page.EvalOnSelectorAsync("section", "e => e.id"); + Assert.That(idAttribute, Is.EqualTo("testAttribute")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should auto-detect nested selectors")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAutoDetectNestedSelectors() + { + await Page.SetContentAsync("
43543Hello
"); + string idAttribute = await Page.EvalOnSelectorAsync("div[foo=bar] > section >> \"Hello\" >> div", "e => e.id"); + Assert.That(idAttribute, Is.EqualTo("target")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should auto-detect css selector with attributes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAutoDetectCssSelectorWithAttributes() + { + await Page.SetContentAsync("
43543
"); + string idAttribute = await Page.EvalOnSelectorAsync("section[id=\"testAttribute\"]", "e => e.id"); + Assert.That(idAttribute, Is.EqualTo("testAttribute")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should accept arguments")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptArguments() + { + await Page.SetContentAsync("
hello
"); + string text = await Page.EvalOnSelectorAsync("section", "(e, suffix) => e.textContent + suffix", " world!"); + Assert.That(text, Is.EqualTo("hello world!")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should accept ElementHandles as arguments")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptElementHandlesAsArguments() + { + await Page.SetContentAsync("
hello
world
"); + var divHandle = await Page.QuerySelectorAsync("div"); + string text = await Page.EvalOnSelectorAsync("section", "(e, div) => e.textContent + div.textContent", divHandle); + Assert.That(text, Is.EqualTo("hello world")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should throw error if no element is found")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowErrorIfNoElementIsFound() + { + var exception = Assert.ThrowsAsync(() + => Page.EvalOnSelectorAsync("section", "e => e.id")); + Assert.That(exception.Message, Does.Contain("failed to find element matching selector \"section\"")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should support >> syntax")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportDoubleGreaterThanSyntax() + { + await Page.SetContentAsync("
hello
"); + string text = await Page.EvalOnSelectorAsync("css=section >> css=div", "(e, suffix) => e.textContent + suffix", " world!"); + Assert.That(text, Is.EqualTo("hello world!")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should support >> syntax with different engines")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportDoubleGreaterThanSyntaxWithDifferentEngines() + { + await Page.SetContentAsync("
hello
"); + string text = await Page.EvalOnSelectorAsync("xpath=/html/body/section >> css=div >> text=\"hello\"", "(e, suffix) => e.textContent + suffix", " world!"); + Assert.That(text, Is.EqualTo("hello world!")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should support spaces with >> syntax")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportSpacesWithDoubleGreaterThanSyntax() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/deep-shadow.html"); + string text = await Page.EvalOnSelectorAsync(" css = div >>css=div>>css = span ", "e => e.textContent"); + Assert.That(text, Is.EqualTo("Hello from root2")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should not stop at first failure with >> syntax")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotStopAtFirstFailureWithDoubleGraterThanSyntax() + { + await Page.SetContentAsync("
Next
"); + string text = await Page.EvalOnSelectorAsync("button >> \"Next\"", "(e) => e.outerHTML"); + Assert.That(text, Is.EqualTo("")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should support * capture")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportStarCapture() + { + await Page.SetContentAsync("
a
b
"); + Assert.That(await Page.EvalOnSelectorAsync("*css=div >> \"b\"", "(e) => e.outerHTML"), Is.EqualTo("
b
")); + Assert.That(await Page.EvalOnSelectorAsync("section >> *css=div >> \"b\"", "(e) => e.outerHTML"), Is.EqualTo("
b
")); + Assert.That(await Page.EvalOnSelectorAsync("css=div >> *text=\"b\"", "(e) => e.outerHTML"), Is.EqualTo("b")); + Assert.That(await Page.QuerySelectorAsync("*"), Is.Not.Null); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should throw on multiple * captures")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowOnMultipleStarCaptures() + { + var exception = Assert.CatchAsync(() => Page.EvalOnSelectorAsync("*css=div >> *css=span", "(e) => e.outerHTML")); + Assert.That(exception.Message, Is.EqualTo("Only one of the selectors can capture using * modifier")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should throw on malformed * capture")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowOnMalformedStarCapture() + { + var exception = Assert.CatchAsync(() => Page.EvalOnSelectorAsync("*=div", "(e) => e.outerHTML")); + Assert.That(exception.Message, Is.EqualTo("Unknown engine \"\" while parsing selector *=div")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should work with spaces in css attributes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithSpacesInCssAttributes() + { + await Page.SetContentAsync("
"); + Assert.That(await Page.WaitForSelectorAsync("[placeholder = \"Select date\"]"), Is.Not.Null); + Assert.That(await Page.WaitForSelectorAsync("[placeholder = 'Select date']"), Is.Not.Null); + Assert.That(await Page.WaitForSelectorAsync("input[placeholder = \"Select date\"]"), Is.Not.Null); + Assert.That(await Page.WaitForSelectorAsync("input[placeholder = 'Select date']"), Is.Not.Null); + Assert.That(await Page.QuerySelectorAsync("[placeholder = \"Select date\"]"), Is.Not.Null); + Assert.That(await Page.QuerySelectorAsync("[placeholder = 'Select date']"), Is.Not.Null); + Assert.That(await Page.QuerySelectorAsync("input[placeholder = \"Select date\"]"), Is.Not.Null); + Assert.That(await Page.QuerySelectorAsync("input[placeholder = 'Select date']"), Is.Not.Null); + Assert.That(await Page.EvalOnSelectorAsync("[placeholder = \"Select date\"]", "e => e.outerHTML"), Is.EqualTo("")); + Assert.That(await Page.EvalOnSelectorAsync("[placeholder = 'Select date']", "e => e.outerHTML"), Is.EqualTo("")); + Assert.That(await Page.EvalOnSelectorAsync("input[placeholder = \"Select date\"]", "e => e.outerHTML"), Is.EqualTo("")); + Assert.That(await Page.EvalOnSelectorAsync("input[placeholder = 'Select date']", "e => e.outerHTML"), Is.EqualTo("")); + Assert.That(await Page.EvalOnSelectorAsync("css =[placeholder = \"Select date\"]", "e => e.outerHTML"), Is.EqualTo("")); + Assert.That(await Page.EvalOnSelectorAsync("css =[placeholder = 'Select date']", "e => e.outerHTML"), Is.EqualTo("")); + Assert.That(await Page.EvalOnSelectorAsync("css = input[placeholder = \"Select date\"]", "e => e.outerHTML"), Is.EqualTo("")); + Assert.That(await Page.EvalOnSelectorAsync("css = input[placeholder = 'Select date']", "e => e.outerHTML"), Is.EqualTo("")); + Assert.That(await Page.EvalOnSelectorAsync("div >> [placeholder = \"Select date\"]", "e => e.outerHTML"), Is.EqualTo("")); + Assert.That(await Page.EvalOnSelectorAsync("div >> [placeholder = 'Select date']", "e => e.outerHTML"), Is.EqualTo("")); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should work with quotes in css attributes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWihQuotesInCssAttributes() + { + await Page.SetContentAsync("
"); + Assert.That(await Page.QuerySelectorAsync("[placeholder = \"Select\\\"date\"]"), Is.Not.Null); + Assert.That(await Page.QuerySelectorAsync("[placeholder = 'Select\"date']"), Is.Not.Null); + + await Page.SetContentAsync("
"); + Assert.That(await Page.QuerySelectorAsync("[placeholder = \"Select \\\" date\"]"), Is.Not.Null); + Assert.That(await Page.QuerySelectorAsync("[placeholder = 'Select \" date']"), Is.Not.Null); + + await Page.SetContentAsync("
"); + Assert.That(await Page.QuerySelectorAsync("[placeholder = \"Select'date\"]"), Is.Not.Null); + Assert.That(await Page.QuerySelectorAsync("[placeholder = 'Select\\'date']"), Is.Not.Null); + + await Page.SetContentAsync("
"); + Assert.That(await Page.QuerySelectorAsync("[placeholder = \"Select ' date\"]"), Is.Not.Null); + Assert.That(await Page.QuerySelectorAsync("[placeholder = 'Select \\' date']"), Is.Not.Null); + } + + [PlaywrightTest("eval-on-selector.spec.ts", "should work with quotes in css attributes when missing")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWihQuotesInCssAttributesWhenMissing() + { + var inputTask = Page.WaitForSelectorAsync("[placeholder = \"Select\\\"date\"]"); + Assert.That(await Page.QuerySelectorAsync("[placeholder = \"Select\\\"date\"]"), Is.Null); + await Page.SetContentAsync("
"); + await inputTask; + } + } +} diff --git a/src/Playwright.Tests/Firefox/LauncherTests.cs b/src/PlaywrightSharp.Tests/Firefox/LauncherTests.cs similarity index 60% rename from src/Playwright.Tests/Firefox/LauncherTests.cs rename to src/PlaywrightSharp.Tests/Firefox/LauncherTests.cs index db88d8f93e..1f7faf5b38 100644 --- a/src/Playwright.Tests/Firefox/LauncherTests.cs +++ b/src/PlaywrightSharp.Tests/Firefox/LauncherTests.cs @@ -1,39 +1,32 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests.Firefox -{ - ///firefox/launcher.spec.ts - ///launcher - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class LauncherTests : PlaywrightSharpBaseTest - { - /// - public LauncherTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("firefox/launcher.spec.ts", "should pass firefox user preferences")] - [SkipBrowserAndPlatformFact(skipChromium: true, skipWebkit: true)] - public async Task ShouldPassFirefoxUserPreferences() - { - var firefoxUserPrefs = new Dictionary - { - ["network.proxy.type"] = 1, - ["network.proxy.http"] = "127.0.0.1", - ["network.proxy.http_port"] = 333, - }; - - await using var browser = await BrowserType.LaunchAsync(firefoxUserPrefs: firefoxUserPrefs); - var page = await browser.NewPageAsync(); - var exception = await Assert.ThrowsAnyAsync(() => page.GoToAsync("http://example.com")); - - Assert.Contains("NS_ERROR_PROXY_CONNECTION_REFUSED", exception.Message); - } - } -} +using System.Collections.Generic; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests.Firefox +{ + ///firefox/launcher.spec.ts + ///launcher + public class LauncherTests : PlaywrightSharpBaseTest + { + [PlaywrightTest("firefox/launcher.spec.ts", "should pass firefox user preferences")] + [SkipBrowserAndPlatformFact(skipChromium: true, skipWebkit: true)] + public async Task ShouldPassFirefoxUserPreferences() + { + var firefoxUserPrefs = new Dictionary + { + ["network.proxy.type"] = 1, + ["network.proxy.http"] = "127.0.0.1", + ["network.proxy.http_port"] = 333, + }; + + await using var browser = await BrowserType.LaunchAsync(firefoxUserPrefs: firefoxUserPrefs); + var page = await browser.NewPageAsync(); + var exception = Assert.CatchAsync(() => page.GoToAsync("http://example.com")); + + Assert.That(exception.Message, Does.Contain("NS_ERROR_PROXY_CONNECTION_REFUSED")); + } + } +} diff --git a/src/Playwright.Tests/FixturesTests.cs b/src/PlaywrightSharp.Tests/FixturesTests.cs similarity index 65% rename from src/Playwright.Tests/FixturesTests.cs rename to src/PlaywrightSharp.Tests/FixturesTests.cs index 72eb820547..bdc42415f3 100644 --- a/src/Playwright.Tests/FixturesTests.cs +++ b/src/PlaywrightSharp.Tests/FixturesTests.cs @@ -1,54 +1,47 @@ -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///fixtures.spec.ts - ///Fixtures - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class FixturesTests : PlaywrightSharpBaseTest - { - /// - public FixturesTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("fixtures.spec.ts", "should close the browser when the node process closes")] - [Fact(Skip = "We don't need to test process handling")] - public void ShouldCloseTheBrowserWhenTheNodeProcessCloses() { } - - [PlaywrightTest("fixtures.spec.ts", "fixtures", "should report browser close signal")] - [Fact(Skip = "We don't need to test signals")] - public void ShouldReportBrowserCloseSignal() { } - - [PlaywrightTest("fixtures.spec.ts", "fixtures", "should report browser close signal 2")] - [Fact(Skip = "We don't need to test signals")] - public void ShouldReportBrowserCloseSignal2() { } - - [PlaywrightTest("fixtures.spec.ts", "fixtures", "should close the browser on SIGINT")] - [Fact(Skip = "We don't need to test signals")] - public void ShouldCloseTheBrowserOnSIGINT() { } - - [PlaywrightTest("fixtures.spec.ts", "fixtures", "should close the browser on SIGTERM")] - [Fact(Skip = "We don't need to test signals")] - public void ShouldCloseTheBrowserOnSIGTERM() { } - - [PlaywrightTest("fixtures.spec.ts", "fixtures", "should close the browser on SIGHUP")] - [Fact(Skip = "We don't need to test signals")] - public void ShouldCloseTheBrowserOnSIGHUP() { } - - [PlaywrightTest("fixtures.spec.ts", "fixtures", "should close the browser on double SIGINT")] - [Fact(Skip = "We don't need to test signals")] - public void ShouldCloseTheBrowserOnDoubleSIGINT() { } - - [PlaywrightTest("fixtures.spec.ts", "fixtures", "should close the browser on SIGINT + SIGERM")] - [Fact(Skip = "We don't need to test signals")] - public void ShouldCloseTheBrowserOnSIGINTAndSIGTERM() { } - - [PlaywrightTest("fixtures.spec.ts", "should report browser close signal")] - [Fact(Skip = "We don't need to test stacktrace")] - public void CallerFilePath() { } - } -} +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///fixtures.spec.ts + ///Fixtures + public class FixturesTests : PlaywrightSharpBaseTest + { + [PlaywrightTest("fixtures.spec.ts", "should close the browser when the node process closes")] + [Test, Ignore("We don't need to test process handling")] + public void ShouldCloseTheBrowserWhenTheNodeProcessCloses() { } + + [PlaywrightTest("fixtures.spec.ts", "fixtures", "should report browser close signal")] + [Test, Ignore("We don't need to test signals")] + public void ShouldReportBrowserCloseSignal() { } + + [PlaywrightTest("fixtures.spec.ts", "fixtures", "should report browser close signal 2")] + [Test, Ignore("We don't need to test signals")] + public void ShouldReportBrowserCloseSignal2() { } + + [PlaywrightTest("fixtures.spec.ts", "fixtures", "should close the browser on SIGINT")] + [Test, Ignore("We don't need to test signals")] + public void ShouldCloseTheBrowserOnSIGINT() { } + + [PlaywrightTest("fixtures.spec.ts", "fixtures", "should close the browser on SIGTERM")] + [Test, Ignore("We don't need to test signals")] + public void ShouldCloseTheBrowserOnSIGTERM() { } + + [PlaywrightTest("fixtures.spec.ts", "fixtures", "should close the browser on SIGHUP")] + [Test, Ignore("We don't need to test signals")] + public void ShouldCloseTheBrowserOnSIGHUP() { } + + [PlaywrightTest("fixtures.spec.ts", "fixtures", "should close the browser on double SIGINT")] + [Test, Ignore("We don't need to test signals")] + public void ShouldCloseTheBrowserOnDoubleSIGINT() { } + + [PlaywrightTest("fixtures.spec.ts", "fixtures", "should close the browser on SIGINT + SIGERM")] + [Test, Ignore("We don't need to test signals")] + public void ShouldCloseTheBrowserOnSIGINTAndSIGTERM() { } + + [PlaywrightTest("fixtures.spec.ts", "should report browser close signal")] + [Test, Ignore("We don't need to test stacktrace")] + public void CallerFilePath() { } + } +} diff --git a/src/Playwright.Tests/FrameEvaluateTests.cs b/src/PlaywrightSharp.Tests/FrameEvaluateTests.cs similarity index 63% rename from src/Playwright.Tests/FrameEvaluateTests.cs rename to src/PlaywrightSharp.Tests/FrameEvaluateTests.cs index 28c4b47362..66cd337c99 100644 --- a/src/Playwright.Tests/FrameEvaluateTests.cs +++ b/src/PlaywrightSharp.Tests/FrameEvaluateTests.cs @@ -1,186 +1,179 @@ -using System.Dynamic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class FrameEvaluateTests : PlaywrightSharpPageBaseTest - { - /// - public FrameEvaluateTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("frame-evaluate.spec.ts", "should have different execution contexts")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHaveDifferentExecutionContexts() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - Assert.Equal(2, Page.Frames.Count); - await Page.Frames.First().EvaluateAsync("() => window.FOO = 'foo'"); - await Page.Frames.ElementAt(1).EvaluateAsync("() => window.FOO = 'bar'"); - Assert.Equal("foo", await Page.Frames.First().EvaluateAsync("() => window.FOO")); - Assert.Equal("bar", await Page.Frames.ElementAt(1).EvaluateAsync("() => window.FOO")); - } - - [PlaywrightTest("frame-evaluate.spec.ts", "should have correct execution contexts")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHaveCorrectExecutionContexts() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); - Assert.Equal(2, Page.Frames.Count); - Assert.Empty(await Page.Frames.First().EvaluateAsync("() => document.body.textContent.trim()")); - Assert.Equal("Hi, I'm frame", await Page.Frames.ElementAt(1).EvaluateAsync("() => document.body.textContent.trim()")); - } - - [PlaywrightTest("frame-evaluate.spec.ts", "should dispose context on navigation")] - [Fact(Skip = "Ignore USES_HOOKS")] - public void ShouldDisposeContextOnNavigation() - { - } - - [PlaywrightTest("frame-evaluate.spec.ts", "should dispose context on cross-origin navigation")] - [Fact(Skip = "Ignore USES_HOOKS")] - public void ShouldDisposeContextOnCrossOriginNavigation() - { - } - - [PlaywrightTest("frame-evaluate.spec.ts", "should execute after cross-site navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldExecuteAfterCrossSiteNavigation() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var mainFrame = Page.MainFrame; - Assert.Contains("localhost", await mainFrame.EvaluateAsync("() => window.location.href")); - await Page.GoToAsync(TestConstants.CrossProcessUrl + "/empty.html"); - Assert.Contains("127", await mainFrame.EvaluateAsync("() => window.location.href")); - } - - [PlaywrightTest("frame-evaluate.spec.ts", "should allow cross-frame js handles")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAllowCrossFrameJsHandles() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); - var handle = await Page.EvaluateHandleAsync(@"() => { - const iframe = document.querySelector('iframe'); - const foo = { bar: 'baz' }; - iframe.contentWindow.__foo = foo; - return foo; - }"); - var childFrame = Page.MainFrame.ChildFrames.First(); - dynamic childResult = await childFrame.EvaluateAsync("() => window.__foo"); - Assert.Equal("baz", childResult.bar); - var exception = await Assert.ThrowsAnyAsync(() => childFrame.EvaluateAsync("foo => foo.bar", handle)); - Assert.Equal("JSHandles can be evaluated only in the context they were created!", exception.Message); - } - - [PlaywrightTest("frame-evaluate.spec.ts", "should allow cross-frame element handles")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAllowCrossFrameElementHandles() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); - var bodyHandle = await Page.MainFrame.ChildFrames.First().QuerySelectorAsync("body"); - string result = await Page.EvaluateAsync("body => body.innerHTML", bodyHandle); - Assert.Equal("
Hi, I\'m frame
", result.Trim()); - } - - [PlaywrightTest("frame-evaluate.spec.ts", "should not allow cross-frame element handles when frames do not script each other")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotAllowCrossFrameElementHandlesWhenFramesDoNotScriptEachOther() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var frame = await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.CrossProcessUrl + "/empty.html"); - var bodyHandle = await frame.QuerySelectorAsync("body"); - var exception = await Assert.ThrowsAsync(() => Page.EvaluateAsync("body => body.innerHTML", bodyHandle)); - Assert.Contains("Unable to adopt element handle from a different document", exception.Message); - } - - [PlaywrightTest("frame-evaluate.spec.ts", "should throw for detached frames")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowForDetachedFrames() - { - var frame1 = await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - await FrameUtils.DetachFrameAsync(Page, "frame1"); - var exception = await Assert.ThrowsAsync(() => frame1.EvaluateAsync("() => 7 * 8")); - Assert.Contains("Execution Context is not available in detached frame", exception.Message); - } - - [PlaywrightTest("frame-evaluate.spec.ts", "should be isolated between frames")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeIsolatedBetweenFrames() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - Assert.Equal(2, Page.Frames.Count); - var frames = Page.Frames; - Assert.NotSame(frames.First(), frames.ElementAt(1)); - - await TaskUtils.WhenAll( - frames.First().EvaluateAsync("() => window.a = 1"), - frames.ElementAt(1).EvaluateAsync("() => window.a = 2") - ); - - var (result1, result2) = await TaskUtils.WhenAll( - frames.First().EvaluateAsync("() => window.a"), - frames.ElementAt(1).EvaluateAsync("() => window.a") - ); - Assert.Equal(1, result1); - Assert.Equal(2, result2); - } - - [PlaywrightTest("frame-evaluate.spec.ts", "should work in iframes that failed initial navigation")] - [SkipBrowserAndPlatformFact(skipChromium: true, skipFirefox: true)] - public async Task ShouldWorkIniframesThatFailedInitialNavigation() - { - await Page.SetContentAsync( - @" - ", - waitUntil: WaitUntilState.DOMContentLoaded); - - await Page.EvaluateAsync(@"() => { - const iframe = document.querySelector('iframe'); - const div = iframe.contentDocument.createElement('div'); - iframe.contentDocument.body.appendChild(div); - }"); - - Assert.Equal("about:blank", Page.Frames.ElementAt(1).Url); - Assert.Equal("about:blank", await Page.Frames.ElementAt(1).EvaluateAsync("() => window.location.href")); - Assert.NotNull(await Page.Frames.ElementAt(1).QuerySelectorAsync("DIV")); - } - - [PlaywrightTest("frame-evaluate.spec.ts", "should work in iframes that failed initial navigation")] - [SkipBrowserAndPlatformFact(skipChromium: true, skipFirefox: true)] - public async Task ShouldWorkInIframesThatInterruptedInitialJavascriptUrlNavigation() - { - await Page.GoToAsync(TestConstants.EmptyPage); - - await Page.EvaluateAsync(@"() => { - const iframe = document.createElement('iframe'); - iframe.src = 'javascript:""""'; - document.body.appendChild(iframe); - iframe.contentDocument.open(); - iframe.contentDocument.write('
hello
'); - iframe.contentDocument.close(); - }"); - - Assert.Equal(TestConstants.EmptyPage, await Page.Frames.ElementAt(1).EvaluateAsync("() => window.location.href")); - Assert.NotNull(await Page.Frames.ElementAt(1).QuerySelectorAsync("DIV")); - } - - [PlaywrightTest("frame-evaluate.spec.ts", "evaluateHandle should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task EvaluateHandleShouldWork() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var windowHandle = await Page.MainFrame.EvaluateHandleAsync("() => window"); - Assert.NotNull(windowHandle); - } - } -} +using System.Dynamic; +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class FrameEvaluateTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("frame-evaluate.spec.ts", "should have different execution contexts")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHaveDifferentExecutionContexts() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + Assert.That(Page.Frames.Count, Is.EqualTo(2)); + await Page.Frames.First().EvaluateAsync("() => window.FOO = 'foo'"); + await Page.Frames.ElementAt(1).EvaluateAsync("() => window.FOO = 'bar'"); + Assert.That(await Page.Frames.First().EvaluateAsync("() => window.FOO"), Is.EqualTo("foo")); + Assert.That(await Page.Frames.ElementAt(1).EvaluateAsync("() => window.FOO"), Is.EqualTo("bar")); + } + + [PlaywrightTest("frame-evaluate.spec.ts", "should have correct execution contexts")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHaveCorrectExecutionContexts() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); + Assert.That(Page.Frames.Count, Is.EqualTo(2)); + Assert.That(await Page.Frames.First().EvaluateAsync("() => document.body.textContent.trim()"), Is.Empty); + Assert.That(await Page.Frames.ElementAt(1).EvaluateAsync("() => document.body.textContent.trim()"), Is.EqualTo("Hi, I'm frame")); + } + + [PlaywrightTest("frame-evaluate.spec.ts", "should dispose context on navigation")] + [Test, Ignore("Ignore USES_HOOKS")] + public void ShouldDisposeContextOnNavigation() + { + } + + [PlaywrightTest("frame-evaluate.spec.ts", "should dispose context on cross-origin navigation")] + [Test, Ignore("Ignore USES_HOOKS")] + public void ShouldDisposeContextOnCrossOriginNavigation() + { + } + + [PlaywrightTest("frame-evaluate.spec.ts", "should execute after cross-site navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldExecuteAfterCrossSiteNavigation() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var mainFrame = Page.MainFrame; + Assert.That(await mainFrame.EvaluateAsync("() => window.location.href"), Does.Contain("localhost")); + await Page.GoToAsync(TestConstants.CrossProcessUrl + "/empty.html"); + Assert.That(await mainFrame.EvaluateAsync("() => window.location.href"), Does.Contain("127")); + } + + [PlaywrightTest("frame-evaluate.spec.ts", "should allow cross-frame js handles")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAllowCrossFrameJsHandles() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); + var handle = await Page.EvaluateHandleAsync(@"() => { + const iframe = document.querySelector('iframe'); + const foo = { bar: 'baz' }; + iframe.contentWindow.__foo = foo; + return foo; + }"); + var childFrame = Page.MainFrame.ChildFrames.First(); + dynamic childResult = await childFrame.EvaluateAsync("() => window.__foo"); + Assert.That(childResult.bar, Is.EqualTo("baz")); + var exception = Assert.CatchAsync(() => childFrame.EvaluateAsync("foo => foo.bar", handle)); + Assert.That(exception.Message, Is.EqualTo("JSHandles can be evaluated only in the context they were created!")); + } + + [PlaywrightTest("frame-evaluate.spec.ts", "should allow cross-frame element handles")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAllowCrossFrameElementHandles() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); + var bodyHandle = await Page.MainFrame.ChildFrames.First().QuerySelectorAsync("body"); + string result = await Page.EvaluateAsync("body => body.innerHTML", bodyHandle); + Assert.That(result.Trim(), Is.EqualTo("
Hi, I\'m frame
")); + } + + [PlaywrightTest("frame-evaluate.spec.ts", "should not allow cross-frame element handles when frames do not script each other")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotAllowCrossFrameElementHandlesWhenFramesDoNotScriptEachOther() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var frame = await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.CrossProcessUrl + "/empty.html"); + var bodyHandle = await frame.QuerySelectorAsync("body"); + var exception = Assert.ThrowsAsync(() => Page.EvaluateAsync("body => body.innerHTML", bodyHandle)); + Assert.That(exception.Message, Does.Contain("Unable to adopt element handle from a different document")); + } + + [PlaywrightTest("frame-evaluate.spec.ts", "should throw for detached frames")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowForDetachedFrames() + { + var frame1 = await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + await FrameUtils.DetachFrameAsync(Page, "frame1"); + var exception = Assert.ThrowsAsync(() => frame1.EvaluateAsync("() => 7 * 8")); + Assert.That(exception.Message, Does.Contain("Execution Context is not available in detached frame")); + } + + [PlaywrightTest("frame-evaluate.spec.ts", "should be isolated between frames")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeIsolatedBetweenFrames() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + Assert.That(Page.Frames.Count, Is.EqualTo(2)); + var frames = Page.Frames; + Assert.That(frames.ElementAt(1), Is.Not.SameAs(frames.First())); + + await TaskUtils.WhenAll( + frames.First().EvaluateAsync("() => window.a = 1"), + frames.ElementAt(1).EvaluateAsync("() => window.a = 2") + ); + + var (result1, result2) = await TaskUtils.WhenAll( + frames.First().EvaluateAsync("() => window.a"), + frames.ElementAt(1).EvaluateAsync("() => window.a") + ); + Assert.That(result1, Is.EqualTo(1)); + Assert.That(result2, Is.EqualTo(2)); + } + + [PlaywrightTest("frame-evaluate.spec.ts", "should work in iframes that failed initial navigation")] + [SkipBrowserAndPlatformFact(skipChromium: true, skipFirefox: true)] + public async Task ShouldWorkIniframesThatFailedInitialNavigation() + { + await Page.SetContentAsync( + @" + ", + waitUntil: WaitUntilState.DOMContentLoaded); + + await Page.EvaluateAsync(@"() => { + const iframe = document.querySelector('iframe'); + const div = iframe.contentDocument.createElement('div'); + iframe.contentDocument.body.appendChild(div); + }"); + + Assert.That(Page.Frames.ElementAt(1).Url, Is.EqualTo("about:blank")); + Assert.That(await Page.Frames.ElementAt(1).EvaluateAsync("() => window.location.href"), Is.EqualTo("about:blank")); + Assert.That(await Page.Frames.ElementAt(1).QuerySelectorAsync("DIV"), Is.Not.Null); + } + + [PlaywrightTest("frame-evaluate.spec.ts", "should work in iframes that failed initial navigation")] + [SkipBrowserAndPlatformFact(skipChromium: true, skipFirefox: true)] + public async Task ShouldWorkInIframesThatInterruptedInitialJavascriptUrlNavigation() + { + await Page.GoToAsync(TestConstants.EmptyPage); + + await Page.EvaluateAsync(@"() => { + const iframe = document.createElement('iframe'); + iframe.src = 'javascript:""""'; + document.body.appendChild(iframe); + iframe.contentDocument.open(); + iframe.contentDocument.write('
hello
'); + iframe.contentDocument.close(); + }"); + + Assert.That(await Page.Frames.ElementAt(1).EvaluateAsync("() => window.location.href"), Is.EqualTo(TestConstants.EmptyPage)); + Assert.That(await Page.Frames.ElementAt(1).QuerySelectorAsync("DIV"), Is.Not.Null); + } + + [PlaywrightTest("frame-evaluate.spec.ts", "evaluateHandle should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task EvaluateHandleShouldWork() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var windowHandle = await Page.MainFrame.EvaluateHandleAsync("() => window"); + Assert.That(windowHandle, Is.Not.Null); + } + } +} diff --git a/src/Playwright.Tests/FrameFrameElementTests.cs b/src/PlaywrightSharp.Tests/FrameFrameElementTests.cs similarity index 62% rename from src/Playwright.Tests/FrameFrameElementTests.cs rename to src/PlaywrightSharp.Tests/FrameFrameElementTests.cs index 3d44b39e73..cbfe10a9d9 100644 --- a/src/Playwright.Tests/FrameFrameElementTests.cs +++ b/src/PlaywrightSharp.Tests/FrameFrameElementTests.cs @@ -1,64 +1,57 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class FrameFrameElementTests : PlaywrightSharpPageBaseTest - { - /// - public FrameFrameElementTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("frame-frame-element.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var frame1 = await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - var frame2 = await FrameUtils.AttachFrameAsync(Page, "frame2", TestConstants.EmptyPage); - var frame3 = await FrameUtils.AttachFrameAsync(Page, "frame3", TestConstants.EmptyPage); - - var frame1handle1 = await Page.QuerySelectorAsync("#frame1"); - var frame1handle2 = await frame1.FrameElementAsync(); - var frame3handle1 = await Page.QuerySelectorAsync("#frame3"); - var frame3handle2 = await frame3.FrameElementAsync(); - - Assert.True(await frame1handle1.EvaluateAsync("(a, b) => a === b", frame1handle2)); - Assert.True(await frame3handle1.EvaluateAsync("(a, b) => a === b", frame3handle2)); - Assert.False(await frame1handle1.EvaluateAsync("(a, b) => a === b", frame3handle2)); - - var windowHandle = await Page.MainFrame.EvaluateHandleAsync("() => window"); - Assert.NotNull(windowHandle); - } - - [PlaywrightTest("frame-frame-element.spec.ts", "should work with contentFrame")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithContentFrame() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var frame = await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - var handle = await frame.FrameElementAsync(); - var contentFrame = await handle.ContentFrameAsync(); - - Assert.Same(contentFrame, frame); - } - - [PlaywrightTest("frame-frame-element.spec.ts", "should throw when detached")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowWhenDetached() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var frame1 = await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - await Page.EvalOnSelectorAsync("#frame1", "e => e.remove()"); - - var exception = await Assert.ThrowsAnyAsync(() => frame1.FrameElementAsync()); - - Assert.Equal("Frame has been detached.", exception.Message); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class FrameFrameElementTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("frame-frame-element.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var frame1 = await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + var frame2 = await FrameUtils.AttachFrameAsync(Page, "frame2", TestConstants.EmptyPage); + var frame3 = await FrameUtils.AttachFrameAsync(Page, "frame3", TestConstants.EmptyPage); + + var frame1handle1 = await Page.QuerySelectorAsync("#frame1"); + var frame1handle2 = await frame1.FrameElementAsync(); + var frame3handle1 = await Page.QuerySelectorAsync("#frame3"); + var frame3handle2 = await frame3.FrameElementAsync(); + + Assert.That(await frame1handle1.EvaluateAsync("(a, b) => a === b", frame1handle2), Is.True); + Assert.That(await frame3handle1.EvaluateAsync("(a, b) => a === b", frame3handle2), Is.True); + Assert.That(await frame1handle1.EvaluateAsync("(a, b) => a === b", frame3handle2), Is.False); + + var windowHandle = await Page.MainFrame.EvaluateHandleAsync("() => window"); + Assert.That(windowHandle, Is.Not.Null); + } + + [PlaywrightTest("frame-frame-element.spec.ts", "should work with contentFrame")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithContentFrame() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var frame = await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + var handle = await frame.FrameElementAsync(); + var contentFrame = await handle.ContentFrameAsync(); + + Assert.That(frame, Is.SameAs(contentFrame)); + } + + [PlaywrightTest("frame-frame-element.spec.ts", "should throw when detached")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowWhenDetached() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var frame1 = await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + await Page.EvalOnSelectorAsync("#frame1", "e => e.remove()"); + + var exception = Assert.CatchAsync(() => frame1.FrameElementAsync()); + + Assert.That(exception.Message, Is.EqualTo("Frame has been detached.")); + } + } +} diff --git a/src/Playwright.Tests/FrameGoToTests.cs b/src/PlaywrightSharp.Tests/FrameGoToTests.cs similarity index 71% rename from src/Playwright.Tests/FrameGoToTests.cs rename to src/PlaywrightSharp.Tests/FrameGoToTests.cs index 1ca58499fe..86eb8323f5 100644 --- a/src/Playwright.Tests/FrameGoToTests.cs +++ b/src/PlaywrightSharp.Tests/FrameGoToTests.cs @@ -1,112 +1,105 @@ -using System; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class FrameGoToTests : PlaywrightSharpPageBaseTest - { - /// - public FrameGoToTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("frame-goto.spec.ts", "should navigate subframes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNavigateSubFrames() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); - Assert.Single(Page.Frames.Where(f => f.Url.Contains("/frames/one-frame.html"))); - Assert.Single(Page.Frames.Where(f => f.Url.Contains("/frames/frame.html"))); - var childFrame = Page.FirstChildFrame(); - var response = await childFrame.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Same(response.Frame, childFrame); - } - - [PlaywrightTest("frame-goto.spec.ts", "should reject when frame detaches")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRejectWhenFrameDetaches() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); - Server.SetRoute("/empty.html", _ => Task.Delay(10000)); - var waitForRequestTask = Server.WaitForRequest("/empty.html"); - var navigationTask = Page.FirstChildFrame().GoToAsync(TestConstants.EmptyPage); - await waitForRequestTask; - await Page.EvalOnSelectorAsync("iframe", "frame => frame.remove()"); - var exception = await Assert.ThrowsAsync(async () => await navigationTask); - Assert.Contains("frame was detached", exception.Message); - } - - [PlaywrightTest("frame-goto.spec.ts", "should continue after client redirect")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldContinueAfterClientRedirect() - { - Server.SetRoute("/frames/script.js", _ => Task.Delay(10000)); - string url = TestConstants.ServerUrl + "/frames/child-redirect.html"; - var exception = await Assert.ThrowsAnyAsync(() => Page.GoToAsync(url, WaitUntilState.NetworkIdle, 5000)); - - Assert.Contains("Timeout 5000ms", exception.Message); - Assert.Contains($"navigating to \"{url}\", waiting until \"networkidle\"", exception.Message); - } - - [PlaywrightTest("frame-goto.spec.ts", "should return matching responses")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnMatchingResponses() - { - await Page.GoToAsync(TestConstants.EmptyPage); - // Attach three frames. - var matchingData = new MatchingResponseData[] - { - new MatchingResponseData{ FrameTask = FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage)}, - new MatchingResponseData{ FrameTask = FrameUtils.AttachFrameAsync(Page, "frame2", TestConstants.EmptyPage)}, - new MatchingResponseData{ FrameTask = FrameUtils.AttachFrameAsync(Page, "frame3", TestConstants.EmptyPage)} - }; - - await TaskUtils.WhenAll(matchingData.Select(m => m.FrameTask)); - - // Navigate all frames to the same URL. - var requestHandler = new RequestDelegate(async (context) => - { - if (int.TryParse(context.Request.Query["index"], out int index)) - { - await context.Response.WriteAsync(await matchingData[index].ServerResponseTcs.Task); - } - }); - - Server.SetRoute("/one-style.html?index=0", requestHandler); - Server.SetRoute("/one-style.html?index=1", requestHandler); - Server.SetRoute("/one-style.html?index=2", requestHandler); - - for (int i = 0; i < 3; ++i) - { - var waitRequestTask = Server.WaitForRequest("/one-style.html"); - matchingData[i].NavigationTask = matchingData[i].FrameTask.Result.GoToAsync($"{TestConstants.ServerUrl}/one-style.html?index={i}"); - await waitRequestTask; - } - // Respond from server out-of-order. - string[] serverResponseTexts = new string[] { "AAA", "BBB", "CCC" }; - for (int i = 0; i < 3; ++i) - { - matchingData[i].ServerResponseTcs.TrySetResult(serverResponseTexts[i]); - var response = await matchingData[i].NavigationTask; - Assert.Same(matchingData[i].FrameTask.Result, response.Frame); - Assert.Equal(serverResponseTexts[i], await response.GetTextAsync()); - } - } - - class MatchingResponseData - { - public Task"); - }); - await using var context = await Browser.NewContextAsync(new BrowserContextOptions { IgnoreHTTPSErrors = true }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.HttpsPrefix + "/mixedcontent.html", WaitUntilState.DOMContentLoaded); - Assert.Equal(2, page.Frames.Count); - Assert.Equal(3, await page.MainFrame.EvaluateAsync("1 + 2")); - Assert.Equal(5, await page.FirstChildFrame().EvaluateAsync("2 + 3")); - } - - [PlaywrightTest("ignorehttpserrors.spec.ts", "should work with WebSocket")] - // [Fact(Timeout = TestConstants.DefaultTestTimeout)] - [Fact(Skip = "Fix me #1058")] - public async Task ShouldWorkWithWebSocket() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions { IgnoreHTTPSErrors = true }); - var page = await context.NewPageAsync(); - string value = await page.EvaluateAsync(@"endpoint => { - let cb; - const result = new Promise(f => cb = f); - const ws = new WebSocket(endpoint); - ws.addEventListener('message', data => { ws.close(); cb(data.data); }); - ws.addEventListener('error', error => cb('Error')); - return result; - }", TestConstants.HttpsPrefix.Replace("https", "wss") + "/ws"); - - Assert.Equal("incoming", value); - } - - [PlaywrightTest("ignorehttpserrors.spec.ts", "should fail with WebSocket if not ignored")] - // [Fact(Timeout = TestConstants.DefaultTestTimeout)] - [Fact(Skip = "Fix me #1058")] - public async Task ShouldFailWithWebSocketIfNotIgnored() - { - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - string value = await page.EvaluateAsync(@"endpoint => { - let cb; - const result = new Promise(f => cb = f); - const ws = new WebSocket(endpoint); - ws.addEventListener('message', data => { ws.close(); cb(data.data); }); - ws.addEventListener('error', error => cb('Error')); - return result; - }", TestConstants.HttpsPrefix.Replace("https", "wss") + "/ws"); - - Assert.Equal("Error", value); - } - } -} +using System.Net; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Connections.Features; +using Microsoft.AspNetCore.Http; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///ignorehttpserrors.spec.ts + ///ignoreHTTPSErrors + public class IgnoreHttpsErrorsTests : PlaywrightSharpBrowserBaseTest + { + [PlaywrightTest("ignorehttpserrors.spec.ts", "should work")] + // [Test, Timeout(TestConstants.DefaultTestTimeout)] + [Test, Ignore("Fix me #1058")] + public async Task ShouldWork() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions { IgnoreHTTPSErrors = true }); + var page = await context.NewPageAsync(); + var requestTask = HttpsServer.WaitForRequest( + "/empty.html", + request => request.HttpContext.Features.Get().Protocol); + var responseTask = page.GoToAsync(TestConstants.HttpsPrefix + "/empty.html"); + + await TaskUtils.WhenAll( + requestTask, + responseTask); + + var response = responseTask.Result; + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [PlaywrightTest("ignorehttpserrors.spec.ts", "should isolate contexts")] + /// [Test, Timeout(TestConstants.DefaultTestTimeout)] + [Test, Ignore("Fix me #1058")] + public async Task ShouldIsolateContexts() + { + await using (var context = await Browser.NewContextAsync(new BrowserContextOptions { IgnoreHTTPSErrors = true })) + { + var page = await context.NewPageAsync(); + var response = await page.GoToAsync(TestConstants.HttpsPrefix + "/empty.html"); + + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + await using (var context = await Browser.NewContextAsync()) + { + var page = await context.NewPageAsync(); + Assert.CatchAsync(() => page.GoToAsync(TestConstants.HttpsPrefix + "/empty.html")); + } + } + + [PlaywrightTest("ignorehttpserrors.spec.ts", "should work with mixed content")] + // [Test, Timeout(TestConstants.DefaultTestTimeout)] + [Test, Ignore("Fix me #1058")] + public async Task ShouldWorkWithMixedContent() + { + HttpsServer.SetRoute("/mixedcontent.html", async (context) => + { + await context.Response.WriteAsync($""); + }); + await using var context = await Browser.NewContextAsync(new BrowserContextOptions { IgnoreHTTPSErrors = true }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.HttpsPrefix + "/mixedcontent.html", WaitUntilState.DOMContentLoaded); + Assert.That(page.Frames.Count, Is.EqualTo(2)); + Assert.That(await page.MainFrame.EvaluateAsync("1 + 2"), Is.EqualTo(3)); + Assert.That(await page.FirstChildFrame().EvaluateAsync("2 + 3"), Is.EqualTo(5)); + } + + [PlaywrightTest("ignorehttpserrors.spec.ts", "should work with WebSocket")] + // [Test, Timeout(TestConstants.DefaultTestTimeout)] + [Test, Ignore("Fix me #1058")] + public async Task ShouldWorkWithWebSocket() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions { IgnoreHTTPSErrors = true }); + var page = await context.NewPageAsync(); + string value = await page.EvaluateAsync(@"endpoint => { + let cb; + const result = new Promise(f => cb = f); + const ws = new WebSocket(endpoint); + ws.addEventListener('message', data => { ws.close(); cb(data.data); }); + ws.addEventListener('error', error => cb('Error')); + return result; + }", TestConstants.HttpsPrefix.Replace("https", "wss") + "/ws"); + + Assert.That(value, Is.EqualTo("incoming")); + } + + [PlaywrightTest("ignorehttpserrors.spec.ts", "should fail with WebSocket if not ignored")] + // [Test, Timeout(TestConstants.DefaultTestTimeout)] + [Test, Ignore("Fix me #1058")] + public async Task ShouldFailWithWebSocketIfNotIgnored() + { + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + string value = await page.EvaluateAsync(@"endpoint => { + let cb; + const result = new Promise(f => cb = f); + const ws = new WebSocket(endpoint); + ws.addEventListener('message', data => { ws.close(); cb(data.data); }); + ws.addEventListener('error', error => cb('Error')); + return result; + }", TestConstants.HttpsPrefix.Replace("https", "wss") + "/ws"); + + Assert.That(value, Is.EqualTo("Error")); + } + } +} diff --git a/src/PlaywrightSharp.Tests/InterceptionTests.cs b/src/PlaywrightSharp.Tests/InterceptionTests.cs new file mode 100644 index 0000000000..55fb6ca723 --- /dev/null +++ b/src/PlaywrightSharp.Tests/InterceptionTests.cs @@ -0,0 +1,103 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class GlobTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("interception.spec.ts", "should work with glob")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public void ShouldWorkWithGlob() + { + Assert.That("https://localhost:8080/foo.js", Does.Match(StringExtensions.GlobToRegex("**/*.js"))); + Assert.That("https://localhost:8080/foo.js", Does.Not.Match(StringExtensions.GlobToRegex("**/*.css"))); + Assert.That("https://localhost:8080/foo.js", Does.Not.Match(StringExtensions.GlobToRegex("*.js"))); + Assert.That("https://localhost:8080/foo.js", Does.Match(StringExtensions.GlobToRegex("https://**/*.js"))); + Assert.That("http://localhost:8080/simple/path.js", Does.Match(StringExtensions.GlobToRegex("http://localhost:8080/simple/path.js"))); + Assert.That("http://localhost:8080/Simple/path.js", Does.Match(StringExtensions.GlobToRegex("http://localhost:8080/?imple/path.js"))); + Assert.That("https://localhost:8080/a.js", Does.Match(StringExtensions.GlobToRegex("**/{a,b}.js"))); + Assert.That("https://localhost:8080/b.js", Does.Match(StringExtensions.GlobToRegex("**/{a,b}.js"))); + Assert.That("https://localhost:8080/c.js", Does.Not.Match(StringExtensions.GlobToRegex("**/{a,b}.js"))); + + Assert.That("https://localhost:8080/c.jpg", Does.Match(StringExtensions.GlobToRegex("**/*.{png,jpg,jpeg}"))); + Assert.That("https://localhost:8080/c.jpeg", Does.Match(StringExtensions.GlobToRegex("**/*.{png,jpg,jpeg}"))); + Assert.That("https://localhost:8080/c.png", Does.Match(StringExtensions.GlobToRegex("**/*.{png,jpg,jpeg}"))); + Assert.That("https://localhost:8080/c.css", Does.Not.Match(StringExtensions.GlobToRegex("**/*.{png,jpg,jpeg}"))); + } + + [PlaywrightTest("interception.spec.ts", "should work with ignoreHTTPSErrors")] + // [Test, Timeout(TestConstants.DefaultTestTimeout)] + [Test, Ignore("Fix me #1058")] + public async Task ShouldWorkWitIgnoreHTTPSErrors() + { + await using var browser = await BrowserType.LaunchDefaultAsync(); + var context = await browser.NewContextAsync(new BrowserContextOptions + { + IgnoreHTTPSErrors = true + }); + + var page = await context.NewPageAsync(); + + await page.RouteAsync("**/*", (route) => route.ResumeAsync()); + var response = await page.GoToAsync(TestConstants.HttpsPrefix + "/empty.html"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [PlaywrightTest("interception.spec.ts", "should work with navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithNavigation() + { + var requests = new Dictionary(); + await Page.RouteAsync("**/*", (route) => + { + requests.Add(route.Request.Url.Split('/').Last(), route.Request); + route.ResumeAsync(); + }); + + Server.SetRedirect("/rrredirect", "/frames/one-frame.html"); + await Page.GoToAsync(TestConstants.ServerUrl + "/rrredirect"); + Assert.That(requests["rrredirect"].IsNavigationRequest, Is.True); + Assert.That(requests["frame.html"].IsNavigationRequest, Is.True); + Assert.That(requests["script.js"].IsNavigationRequest, Is.False); + Assert.That(requests["style.css"].IsNavigationRequest, Is.False); + } + + [PlaywrightTest("interception.spec.ts", "should work with regular expression passed from a different context")] + [Test, Ignore("We don't need to test Regex contexts")] + public void ShouldWorkWithRegularExpressionPassedFromADifferentContext() + { + } + + [PlaywrightTest("interception.spec.ts", "should intercept after a service worker")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldInterceptAfterAServiceWorker() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/serviceworkers/fetchdummy/sw.html"); + await Page.EvaluateAsync("() => window.activationPromise"); + + string swResponse = await Page.EvaluateAsync("() => fetchDummy('foo')"); + Assert.That(swResponse, Is.EqualTo("responseFromServiceWorker:foo")); + + await Page.RouteAsync("**/foo", (route) => + { + int slash = route.Request.Url.LastIndexOf("/"); + string name = route.Request.Url.Substring(slash + 1); + + route.FulfillAsync(HttpStatusCode.OK, "responseFromInterception:" + name, contentType: "text/css"); + }); + + string swResponse2 = await Page.EvaluateAsync("() => fetchDummy('foo')"); + Assert.That(swResponse2, Is.EqualTo("responseFromServiceWorker:foo")); + + string nonInterceptedResponse = await Page.EvaluateAsync("() => fetchDummy('passthrough')"); + Assert.That(nonInterceptedResponse, Is.EqualTo("FAILURE: Not Found")); + } + } +} diff --git a/src/Playwright.Tests/Internals/FlexibleStringEnumConverterTests.cs b/src/PlaywrightSharp.Tests/Internals/FlexibleStringEnumConverterTests.cs similarity index 65% rename from src/Playwright.Tests/Internals/FlexibleStringEnumConverterTests.cs rename to src/PlaywrightSharp.Tests/Internals/FlexibleStringEnumConverterTests.cs index 1f30509ac7..a1ddcb927c 100644 --- a/src/Playwright.Tests/Internals/FlexibleStringEnumConverterTests.cs +++ b/src/PlaywrightSharp.Tests/Internals/FlexibleStringEnumConverterTests.cs @@ -1,52 +1,52 @@ -using System; -using System.Runtime.Serialization; -using System.Text.Json; -using Microsoft.Playwright.Helpers; -using Xunit; - -namespace Microsoft.Playwright.Tests.Internals -{ - /// - /// FlexibleStringEnumConverterTests - /// - public class FlexibleStringEnumConverterTests - { - private readonly JsonSerializerOptions _options = new JsonSerializerOptions - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - Converters = - { - new FlexibleStringEnumConverter(TestEnum.Default) - }, - }; - - private enum TestEnum - { - Default, - Document, - [EnumMember(Value = "usingenummember")] - StyleSheet, - } - - /// - /// Should work with the enum name. - /// - [Fact] - public void ShouldWorkWithName() - => Assert.Equal(TestEnum.Document, JsonSerializer.Deserialize("\"document\"", _options)); - - /// - /// Should work with the EnumMember value. - /// - [Fact] - public void ShouldWorkWithEnumMemberName() - => Assert.Equal(TestEnum.StyleSheet, JsonSerializer.Deserialize("\"usingenummember\"", _options)); - - /// - /// Should fallback to the default value. - /// - [Fact] - public void ShouldFallback() - => Assert.Equal(TestEnum.Default, JsonSerializer.Deserialize("\"foobar\"", _options)); - } -} +using System; +using System.Runtime.Serialization; +using System.Text.Json; +using NUnit.Framework; +using PlaywrightSharp.Helpers; + +namespace PlaywrightSharp.Tests.Internals +{ + /// + /// FlexibleStringEnumConverterTests + /// + public class FlexibleStringEnumConverterTests + { + private readonly JsonSerializerOptions _options = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + Converters = + { + new FlexibleStringEnumConverter(TestEnum.Default) + }, + }; + + private enum TestEnum + { + Default, + Document, + [EnumMember(Value = "usingenummember")] + StyleSheet, + } + + /// + /// Should work with the enum name. + /// + [Test] + public void ShouldWorkWithName() + => Assert.That(JsonSerializer.Deserialize("\"document\"", _options), Is.EqualTo(TestEnum.Document)); + + /// + /// Should work with the EnumMember value. + /// + [Test] + public void ShouldWorkWithEnumMemberName() + => Assert.That(JsonSerializer.Deserialize("\"usingenummember\"", _options), Is.EqualTo(TestEnum.StyleSheet)); + + /// + /// Should fallback to the default value. + /// + [Test] + public void ShouldFallback() + => Assert.That(JsonSerializer.Deserialize("\"foobar\"", _options), Is.EqualTo(TestEnum.Default)); + } +} diff --git a/src/Playwright.Tests/Issues/Issue983.cs b/src/PlaywrightSharp.Tests/Issues/Issue983.cs similarity index 55% rename from src/Playwright.Tests/Issues/Issue983.cs rename to src/PlaywrightSharp.Tests/Issues/Issue983.cs index faa8b70025..012f892b16 100644 --- a/src/Playwright.Tests/Issues/Issue983.cs +++ b/src/PlaywrightSharp.Tests/Issues/Issue983.cs @@ -1,34 +1,27 @@ -using System; -using System.Collections.Generic; -using System.Dynamic; -using System.Threading.Tasks; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests.Issues -{ - /// - /// See https://github.com/microsoft/playwright-sharp/issues/983. - /// - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class Issue983 : PlaywrightSharpPageBaseTest - { - /// - public Issue983(ITestOutputHelper output) : base(output) - { - } - - /// - /// See https://github.com/microsoft/playwright-sharp/issues/983. - /// - [Fact(Skip = "Getting navigation timeouts on CI")] - public async Task ShouldWork() - { - await Page.GoToAsync("https://github.com"); - string title = await Page.TitleAsync(); - Assert.Contains("GitHub", title); - } - } -} +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests.Issues +{ + /// + /// See https://github.com/microsoft/playwright-sharp/issues/983. + /// + public class Issue983 : PlaywrightSharpPageBaseTest + { + /// + /// See https://github.com/microsoft/playwright-sharp/issues/983. + /// + [Test, Ignore("Getting navigation timeouts on CI")] + public async Task ShouldWork() + { + await Page.GoToAsync("https://github.com"); + string title = await Page.TitleAsync(); + Assert.That(title, Does.Contain("GitHub")); + } + } +} diff --git a/src/Playwright.Tests/JSHandleAsElementTests.cs b/src/PlaywrightSharp.Tests/JSHandleAsElementTests.cs similarity index 64% rename from src/Playwright.Tests/JSHandleAsElementTests.cs rename to src/PlaywrightSharp.Tests/JSHandleAsElementTests.cs index 6bc24819ea..d7c5a50f29 100644 --- a/src/Playwright.Tests/JSHandleAsElementTests.cs +++ b/src/PlaywrightSharp.Tests/JSHandleAsElementTests.cs @@ -1,57 +1,50 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class JSHandleAsElementTests : PlaywrightSharpPageBaseTest - { - /// - public JSHandleAsElementTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("jshandle-as-element.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - var aHandle = await Page.EvaluateHandleAsync("() => document.body"); - var element = aHandle as IElementHandle; - Assert.NotNull(element); - } - - [PlaywrightTest("jshandle-as-element.spec.ts", "should return null for non-elements")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnNullForNonElements() - { - var aHandle = await Page.EvaluateHandleAsync("() => 2"); - var element = aHandle as IElementHandle; - Assert.Null(element); - } - - [PlaywrightTest("jshandle-as-element.spec.ts", "should return ElementHandle for TextNodes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnElementHandleForTextNodes() - { - await Page.SetContentAsync("
ee!
"); - var aHandle = await Page.EvaluateHandleAsync("() => document.querySelector('div').firstChild"); - var element = aHandle as IElementHandle; - Assert.NotNull(element); - Assert.True(await Page.EvaluateAsync("e => e.nodeType === HTMLElement.TEXT_NODE", element)); - } - - [PlaywrightTest("jshandle-as-element.spec.ts", "should work with nullified Node")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithNullifiedNode() - { - await Page.SetContentAsync("
test
"); - await Page.EvaluateAsync("() => delete Node"); - var handle = await Page.EvaluateHandleAsync("() => document.querySelector('section')"); - var element = handle as IElementHandle; - Assert.NotNull(element); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class JSHandleAsElementTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("jshandle-as-element.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + var aHandle = await Page.EvaluateHandleAsync("() => document.body"); + var element = aHandle as IElementHandle; + Assert.That(element, Is.Not.Null); + } + + [PlaywrightTest("jshandle-as-element.spec.ts", "should return null for non-elements")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnNullForNonElements() + { + var aHandle = await Page.EvaluateHandleAsync("() => 2"); + var element = aHandle as IElementHandle; + Assert.That(element, Is.Null); + } + + [PlaywrightTest("jshandle-as-element.spec.ts", "should return ElementHandle for TextNodes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnElementHandleForTextNodes() + { + await Page.SetContentAsync("
ee!
"); + var aHandle = await Page.EvaluateHandleAsync("() => document.querySelector('div').firstChild"); + var element = aHandle as IElementHandle; + Assert.That(element, Is.Not.Null); + Assert.That(await Page.EvaluateAsync("e => e.nodeType === HTMLElement.TEXT_NODE", element), Is.True); + } + + [PlaywrightTest("jshandle-as-element.spec.ts", "should work with nullified Node")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithNullifiedNode() + { + await Page.SetContentAsync("
test
"); + await Page.EvaluateAsync("() => delete Node"); + var handle = await Page.EvaluateHandleAsync("() => document.querySelector('section')"); + var element = handle as IElementHandle; + Assert.That(element, Is.Not.Null); + } + } +} diff --git a/src/Playwright.Tests/JSHandleJsonValueTests.cs b/src/PlaywrightSharp.Tests/JSHandleJsonValueTests.cs similarity index 54% rename from src/Playwright.Tests/JSHandleJsonValueTests.cs rename to src/PlaywrightSharp.Tests/JSHandleJsonValueTests.cs index 69dacbef5e..90c34c685c 100644 --- a/src/Playwright.Tests/JSHandleJsonValueTests.cs +++ b/src/PlaywrightSharp.Tests/JSHandleJsonValueTests.cs @@ -1,46 +1,39 @@ -using System; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class JSHandleJsonValueTests : PlaywrightSharpPageBaseTest - { - /// - public JSHandleJsonValueTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("jshandle-json-value.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - var aHandle = await Page.EvaluateHandleAsync("() => ({ foo: 'bar'})"); - var json = await aHandle.JsonValueAsync(); - Assert.Equal("bar", json.GetProperty("foo").GetString()); - } - - [PlaywrightTest("jshandle-json-value.spec.ts", "should work with dates")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithDates() - { - var dateHandle = await Page.EvaluateHandleAsync("() => new Date('2017-09-26T00:00:00.000Z')"); - var json = await dateHandle.JsonValueAsync(); - Assert.Equal(2017, json.Year); - } - - [PlaywrightTest("jshandle-json-value.spec.ts", "should throw for circular objects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowForCircularObjects() - { - var windowHandle = await Page.EvaluateHandleAsync("window"); - var exception = await Assert.ThrowsAnyAsync(() => windowHandle.JsonValueAsync()); - Assert.Contains("Argument is a circular structure", exception.Message); - } - } -} +using System; +using System.Text.Json; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class JSHandleJsonValueTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("jshandle-json-value.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + var aHandle = await Page.EvaluateHandleAsync("() => ({ foo: 'bar'})"); + var json = await aHandle.JsonValueAsync(); + Assert.That(json.GetProperty("foo").GetString(), Is.EqualTo("bar")); + } + + [PlaywrightTest("jshandle-json-value.spec.ts", "should work with dates")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithDates() + { + var dateHandle = await Page.EvaluateHandleAsync("() => new Date('2017-09-26T00:00:00.000Z')"); + var json = await dateHandle.JsonValueAsync(); + Assert.That(json.Year, Is.EqualTo(2017)); + } + + [PlaywrightTest("jshandle-json-value.spec.ts", "should throw for circular objects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowForCircularObjects() + { + var windowHandle = await Page.EvaluateHandleAsync("window"); + var exception = Assert.CatchAsync(() => windowHandle.JsonValueAsync()); + Assert.That(exception.Message, Does.Contain("Argument is a circular structure")); + } + } +} diff --git a/src/Playwright.Tests/JSHandlePropertiesTests.cs b/src/PlaywrightSharp.Tests/JSHandlePropertiesTests.cs similarity index 64% rename from src/Playwright.Tests/JSHandlePropertiesTests.cs rename to src/PlaywrightSharp.Tests/JSHandlePropertiesTests.cs index eed73ef1d0..02311c2ffe 100644 --- a/src/Playwright.Tests/JSHandlePropertiesTests.cs +++ b/src/PlaywrightSharp.Tests/JSHandlePropertiesTests.cs @@ -1,115 +1,108 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class JSHandlePropertiesTests : PlaywrightSharpPageBaseTest - { - /// - public JSHandlePropertiesTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("jshandle-properties.spec.ts", "getProperties should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task GetPropertiesShouldWork() - { - var aHandle = await Page.EvaluateHandleAsync(@"() => ({ - foo: 'bar' - })"); - var properties = await aHandle.GetPropertiesAsync(); - Assert.True(properties.TryGetValue("foo", out var foo)); - Assert.Equal("bar", await foo.JsonValueAsync()); - } - - [PlaywrightTest("jshandle-properties.spec.ts", "should return empty map for non-objects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnEmptyMapForNonObjects() - { - var aHandle = await Page.EvaluateHandleAsync("() => 123"); - var properties = await aHandle.GetPropertiesAsync(); - Assert.Empty(properties); - } - - [PlaywrightTest("jshandle-properties.spec.ts", "should return even non-own properties")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnEvenNonOwnProperties() - { - var aHandle = await Page.EvaluateHandleAsync(@"() => { - class A - { - constructor() - { - this.a = '1'; - } - } - class B extends A - { - constructor() { - super(); - this.b = '2'; - } - } - return new B(); - }"); - var properties = await aHandle.GetPropertiesAsync(); - Assert.Equal("1", await properties["a"].JsonValueAsync()); - Assert.Equal("2", await properties["b"].JsonValueAsync()); - } - - [PlaywrightTest("jshandle-properties.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - var aHandle = await Page.EvaluateHandleAsync(@"() => ({ - one: 1, - two: 2, - three: 3 - })"); - var twoHandle = await aHandle.GetPropertyAsync("two"); - Assert.Equal(2, await twoHandle.JsonValueAsync()); - } - - [PlaywrightTest("jshandle-properties.spec.ts", "should work with undefined, null, and empty")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithUndefinedNullAndEmpty() - { - var aHandle = await Page.EvaluateHandleAsync(@"() => ({ - undefined: undefined, - null: null, - })"); - var undefinedHandle = await aHandle.GetPropertyAsync("undefined"); - Assert.Null(await undefinedHandle.JsonValueAsync()); - var nullHandle = await aHandle.GetPropertyAsync("null"); - Assert.Null(await nullHandle.JsonValueAsync()); - var emptyHandle = await aHandle.GetPropertyAsync("emptyHandle"); - Assert.Null(await emptyHandle.JsonValueAsync()); - } - - [PlaywrightTest("jshandle-properties.spec.ts", "should work with unserializable values")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithUnserializableValues() - { - var aHandle = await Page.EvaluateHandleAsync(@"() => ({ - infinity: Infinity, - nInfinity: -Infinity, - nan: NaN, - nzero: -0 - })"); - - var infinityHandle = await aHandle.GetPropertyAsync("infinity"); - Assert.Equal(double.PositiveInfinity, await infinityHandle.JsonValueAsync()); - var ninfinityHandle = await aHandle.GetPropertyAsync("nInfinity"); - Assert.Equal(double.NegativeInfinity, await ninfinityHandle.JsonValueAsync()); - var nanHandle = await aHandle.GetPropertyAsync("nan"); - Assert.Equal(double.NaN, await nanHandle.JsonValueAsync()); - var nzeroHandle = await aHandle.GetPropertyAsync("nzero"); - Assert.True((await nzeroHandle.JsonValueAsync()).IsNegativeZero()); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class JSHandlePropertiesTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("jshandle-properties.spec.ts", "getProperties should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task GetPropertiesShouldWork() + { + var aHandle = await Page.EvaluateHandleAsync(@"() => ({ + foo: 'bar' + })"); + var properties = await aHandle.GetPropertiesAsync(); + Assert.That(properties.TryGetValue("foo", out var foo), Is.True); + Assert.That(await foo.JsonValueAsync(), Is.EqualTo("bar")); + } + + [PlaywrightTest("jshandle-properties.spec.ts", "should return empty map for non-objects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnEmptyMapForNonObjects() + { + var aHandle = await Page.EvaluateHandleAsync("() => 123"); + var properties = await aHandle.GetPropertiesAsync(); + Assert.That(properties, Is.Empty); + } + + [PlaywrightTest("jshandle-properties.spec.ts", "should return even non-own properties")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnEvenNonOwnProperties() + { + var aHandle = await Page.EvaluateHandleAsync(@"() => { + class A + { + constructor() + { + this.a = '1'; + } + } + class B extends A + { + constructor() { + super(); + this.b = '2'; + } + } + return new B(); + }"); + var properties = await aHandle.GetPropertiesAsync(); + Assert.That(await properties["a"].JsonValueAsync(), Is.EqualTo("1")); + Assert.That(await properties["b"].JsonValueAsync(), Is.EqualTo("2")); + } + + [PlaywrightTest("jshandle-properties.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + var aHandle = await Page.EvaluateHandleAsync(@"() => ({ + one: 1, + two: 2, + three: 3 + })"); + var twoHandle = await aHandle.GetPropertyAsync("two"); + Assert.That(await twoHandle.JsonValueAsync(), Is.EqualTo(2)); + } + + [PlaywrightTest("jshandle-properties.spec.ts", "should work with undefined, null, and empty")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithUndefinedNullAndEmpty() + { + var aHandle = await Page.EvaluateHandleAsync(@"() => ({ + undefined: undefined, + null: null, + })"); + var undefinedHandle = await aHandle.GetPropertyAsync("undefined"); + Assert.That(await undefinedHandle.JsonValueAsync(), Is.Null); + var nullHandle = await aHandle.GetPropertyAsync("null"); + Assert.That(await nullHandle.JsonValueAsync(), Is.Null); + var emptyHandle = await aHandle.GetPropertyAsync("emptyHandle"); + Assert.That(await emptyHandle.JsonValueAsync(), Is.Null); + } + + [PlaywrightTest("jshandle-properties.spec.ts", "should work with unserializable values")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithUnserializableValues() + { + var aHandle = await Page.EvaluateHandleAsync(@"() => ({ + infinity: Infinity, + nInfinity: -Infinity, + nan: NaN, + nzero: -0 + })"); + + var infinityHandle = await aHandle.GetPropertyAsync("infinity"); + Assert.That(await infinityHandle.JsonValueAsync(), Is.EqualTo(double.PositiveInfinity)); + var ninfinityHandle = await aHandle.GetPropertyAsync("nInfinity"); + Assert.That(await ninfinityHandle.JsonValueAsync(), Is.EqualTo(double.NegativeInfinity)); + var nanHandle = await aHandle.GetPropertyAsync("nan"); + Assert.That(await nanHandle.JsonValueAsync(), Is.EqualTo(double.NaN)); + var nzeroHandle = await aHandle.GetPropertyAsync("nzero"); + Assert.That((await nzeroHandle.JsonValueAsync()).IsNegativeZero(), Is.True); + } + } +} diff --git a/src/PlaywrightSharp.Tests/JSHandleToStringTests.cs b/src/PlaywrightSharp.Tests/JSHandleToStringTests.cs new file mode 100644 index 0000000000..1f915efdd2 --- /dev/null +++ b/src/PlaywrightSharp.Tests/JSHandleToStringTests.cs @@ -0,0 +1,63 @@ +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class JSHandleToStringTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("jshandle-to-string.spec.ts", "should work for primitives")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForPrimitives() + { + var numberHandle = await Page.EvaluateHandleAsync("() => 2"); + Assert.That(numberHandle.ToString(), Is.EqualTo("JSHandle@2")); + var stringHandle = await Page.EvaluateHandleAsync("() => 'a'"); + Assert.That(stringHandle.ToString(), Is.EqualTo("JSHandle@a")); + } + + [PlaywrightTest("jshandle-to-string.spec.ts", "should work for complicated objects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForComplicatedObjects() + { + var aHandle = await Page.EvaluateHandleAsync("() => window"); + Assert.That(aHandle.ToString(), Is.EqualTo("JSHandle@object")); + } + + [PlaywrightTest("jshandle-to-string.spec.ts", "should work for promises")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForPromises() + { + // wrap the promise in an object, otherwise we will await. + var wrapperHandle = await Page.EvaluateHandleAsync("() => ({ b: Promise.resolve(123)})"); + var bHandle = await wrapperHandle.GetPropertyAsync("b"); + Assert.That(bHandle.ToString(), Is.EqualTo("JSHandle@promise")); + } + + [PlaywrightTest("jshandle-to-string.spec.ts", "should work with different subtypes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithDifferentSubtypes() + { + Assert.That((await Page.EvaluateHandleAsync("(function(){})")).ToString(), Is.EqualTo("JSHandle@function")); + Assert.That((await Page.EvaluateHandleAsync("12")).ToString(), Is.EqualTo("JSHandle@12")); + Assert.That((await Page.EvaluateHandleAsync("true")).ToString(), Is.EqualTo("JSHandle@true")); + Assert.That((await Page.EvaluateHandleAsync("undefined")).ToString(), Is.EqualTo("JSHandle@undefined")); + Assert.That((await Page.EvaluateHandleAsync("\"foo\"")).ToString(), Is.EqualTo("JSHandle@foo")); + Assert.That((await Page.EvaluateHandleAsync("Symbol()")).ToString(), Is.EqualTo("JSHandle@symbol")); + Assert.That((await Page.EvaluateHandleAsync("new Map()")).ToString(), Is.EqualTo("JSHandle@map")); + Assert.That((await Page.EvaluateHandleAsync("new Set()")).ToString(), Is.EqualTo("JSHandle@set")); + Assert.That((await Page.EvaluateHandleAsync("[]")).ToString(), Is.EqualTo("JSHandle@array")); + Assert.That((await Page.EvaluateHandleAsync("null")).ToString(), Is.EqualTo("JSHandle@null")); + Assert.That((await Page.EvaluateHandleAsync("/foo/")).ToString(), Is.EqualTo("JSHandle@regexp")); + // We get the preview faster than in node. + Assert.That(new[] { "JSHandle@node", "JSHandle@" }, Does.Contain((await Page.EvaluateHandleAsync("document.body")).ToString())); + Assert.That((await Page.EvaluateHandleAsync("new Date()")).ToString(), Is.EqualTo("JSHandle@date")); + Assert.That((await Page.EvaluateHandleAsync("new WeakMap()")).ToString(), Is.EqualTo("JSHandle@weakmap")); + Assert.That((await Page.EvaluateHandleAsync("new WeakSet()")).ToString(), Is.EqualTo("JSHandle@weakset")); + Assert.That((await Page.EvaluateHandleAsync("new Error()")).ToString(), Is.EqualTo("JSHandle@error")); + Assert.That((await Page.EvaluateHandleAsync("new Int32Array()")).ToString(), Is.EqualTo(TestConstants.IsWebKit ? "JSHandle@array" : "JSHandle@typedarray")); + Assert.That((await Page.EvaluateHandleAsync("new Proxy({}, {})")).ToString(), Is.EqualTo("JSHandle@proxy")); + } + } +} diff --git a/src/PlaywrightSharp.Tests/LauncherTests.cs b/src/PlaywrightSharp.Tests/LauncherTests.cs new file mode 100644 index 0000000000..7ff4cddb57 --- /dev/null +++ b/src/PlaywrightSharp.Tests/LauncherTests.cs @@ -0,0 +1,17 @@ +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class LauncherTests : PlaywrightSharpBaseTest + { + [PlaywrightTest("launcher.spec.ts", "should require top-level Errors")] + [Test, Ignore("We don't need this test. Leaving for tracking purposes")] + public void ShouldRequireTopLevelErrors() { } + + [PlaywrightTest("launcher.spec.ts", "should require top-level DeviceDescriptors")] + [Test, Ignore("We don't need this test. Leaving for tracking purposes")] + public void ShouldRequireTopLevelDeviceDescriptors() { } + } +} diff --git a/src/PlaywrightSharp.Tests/LoggerTests.cs b/src/PlaywrightSharp.Tests/LoggerTests.cs new file mode 100644 index 0000000000..8ade0a6647 --- /dev/null +++ b/src/PlaywrightSharp.Tests/LoggerTests.cs @@ -0,0 +1,22 @@ +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class LoggerTests : PlaywrightSharpBaseTest + { + [PlaywrightTest("logger.spec.ts", "should log")] + [Test, Ignore("We don't test CHANNEL")] + public void ShouldLog() + { + } + + [PlaywrightTest("logger.spec.ts", "should log context-level")] + [Test, Ignore("We don't test CHANNEL")] + public void ShouldLogContextLevel() + { + } + + } +} diff --git a/src/Playwright.Tests/NetworkPostDataTests.cs b/src/PlaywrightSharp.Tests/NetworkPostDataTests.cs similarity index 78% rename from src/Playwright.Tests/NetworkPostDataTests.cs rename to src/PlaywrightSharp.Tests/NetworkPostDataTests.cs index 8a43eed369..5b1756f5c8 100644 --- a/src/Playwright.Tests/NetworkPostDataTests.cs +++ b/src/PlaywrightSharp.Tests/NetworkPostDataTests.cs @@ -1,120 +1,110 @@ -using System.Text.Encodings.Web; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - - -namespace Microsoft.Playwright.Tests -{ - /// network-post-data.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public sealed class NetworkPostDataTests : PlaywrightSharpPageBaseTest - { - - /// - public NetworkPostDataTests(ITestOutputHelper output) : - base(output) - { - } - - /// network-post-data.spec.ts - /// should return correct postData buffer for utf-8 body - [Fact(Timeout = Microsoft.Playwright.Playwright.DefaultTimeout)] - public async Task ShouldReturnCorrectPostdataBufferForUtf8Body() - { - await Page.GoToAsync(TestConstants.EmptyPage); - string value = "baẞ"; - - var task = Page.WaitForEventAsync(PageEvent.Request, (r) => true); - var actualTask = Page.EvaluateAsync(@$"() => {{ - const request = new Request('{TestConstants.ServerUrl + "/title.html"}', {{ - method: 'POST', - body: JSON.stringify('{value}'), - }}); - request.headers.set('content-type', 'application/json;charset=UTF-8'); - return fetch(request); - }}"); - - Task.WaitAll(task, actualTask); - - string expectedJsonValue = JsonSerializer.Serialize(value, new JsonSerializerOptions - { - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, - WriteIndented = true - }); - - var request = task.Result; - Assert.Equal(expectedJsonValue, request.PostData); - Assert.Equal(value, request.GetPayloadAsJson().RootElement.GetString()); - } - - /// network-post-data.spec.ts - /// should return post data w/o content-type - [Fact(Timeout = Microsoft.Playwright.Playwright.DefaultTimeout)] - public async Task ShouldReturnPostDataWOContentType() - { - await Page.GoToAsync(TestConstants.EmptyPage); - - var task = Page.WaitForEventAsync(PageEvent.Request, (r) => true); - var actualTask = Page.EvaluateAsync(@"(url) => { - const request = new Request(url, { - method: 'POST', - body: JSON.stringify({ value: 42 }), - }); - request.headers.set('content-type', ''); - return fetch(request); - }", TestConstants.ServerUrl + "/title.html"); - - Task.WaitAll(task, actualTask); - - var request = task.Result; - Assert.Equal(42, request.GetPayloadAsJson().RootElement.GetProperty("value").GetInt32()); - } - - /// network-post-data.spec.ts - /// should throw on invalid JSON in post data - [Fact(Timeout = Microsoft.Playwright.Playwright.DefaultTimeout)] - public async Task ShouldThrowOnInvalidJSONInPostData() - { - await Page.GoToAsync(TestConstants.EmptyPage); - - var task = Page.WaitForEventAsync(PageEvent.Request, (r) => true); - var actualTask = Page.EvaluateAsync(@"(url) => { - const request = new Request(url, { - method: 'POST', - body: '', - }); - return fetch(request); - }", TestConstants.ServerUrl + "/title.html"); - - Task.WaitAll(task, actualTask); - - var request = task.Result; - Assert.ThrowsAny(() => request.GetPayloadAsJson()); - } - - /// network-post-data.spec.ts - /// should return post data for PUT requests - [Fact(Timeout = Microsoft.Playwright.Playwright.DefaultTimeout)] - public async Task ShouldReturnPostDataForPUTRequests() - { - await Page.GoToAsync(TestConstants.EmptyPage); - - var task = Page.WaitForEventAsync(PageEvent.Request, (r) => true); - var actualTask = Page.EvaluateAsync(@"(url) => { - const request = new Request(url, { - method: 'PUT', - body: JSON.stringify({ value: 42 }), - }); - return fetch(request); - }", TestConstants.ServerUrl + "/title.html"); - - Task.WaitAll(task, actualTask); - - var request = task.Result; - Assert.Equal(42, request.GetPayloadAsJson().RootElement.GetProperty("value").GetInt32()); - } - } -} +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + /// network-post-data.spec.ts + public sealed class NetworkPostDataTests : PlaywrightSharpPageBaseTest + { + /// network-post-data.spec.ts + /// should return correct postData buffer for utf-8 body + [Test, Timeout(PlaywrightSharp.Playwright.DefaultTimeout)] + public async Task ShouldReturnCorrectPostdataBufferForUtf8Body() + { + await Page.GoToAsync(TestConstants.EmptyPage); + string value = "ba\u00DF"; + + var task = Page.WaitForEventAsync(PageEvent.Request, (r) => true); + var actualTask = Page.EvaluateAsync(@$"() => {{ + const request = new Request('{TestConstants.ServerUrl + "/title.html"}', {{ + method: 'POST', + body: JSON.stringify('{value}'), + }}); + request.headers.set('content-type', 'application/json;charset=UTF-8'); + return fetch(request); + }}"); + + Task.WaitAll(task, actualTask); + + string expectedJsonValue = JsonSerializer.Serialize(value, new JsonSerializerOptions + { + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + WriteIndented = true + }); + + var request = task.Result; + Assert.That(request.PostData, Is.EqualTo(expectedJsonValue)); + Assert.That(request.GetPayloadAsJson().RootElement.GetString(), Is.EqualTo(value)); + } + + /// network-post-data.spec.ts + /// should return post data w/o content-type + [Test, Timeout(PlaywrightSharp.Playwright.DefaultTimeout)] + public async Task ShouldReturnPostDataWOContentType() + { + await Page.GoToAsync(TestConstants.EmptyPage); + + var task = Page.WaitForEventAsync(PageEvent.Request, (r) => true); + var actualTask = Page.EvaluateAsync(@"(url) => { + const request = new Request(url, { + method: 'POST', + body: JSON.stringify({ value: 42 }), + }); + request.headers.set('content-type', ''); + return fetch(request); + }", TestConstants.ServerUrl + "/title.html"); + + Task.WaitAll(task, actualTask); + + var request = task.Result; + Assert.That(request.GetPayloadAsJson().RootElement.GetProperty("value").GetInt32(), Is.EqualTo(42)); + } + + /// network-post-data.spec.ts + /// should throw on invalid JSON in post data + [Test, Timeout(PlaywrightSharp.Playwright.DefaultTimeout)] + public async Task ShouldThrowOnInvalidJSONInPostData() + { + await Page.GoToAsync(TestConstants.EmptyPage); + + var task = Page.WaitForEventAsync(PageEvent.Request, (r) => true); + var actualTask = Page.EvaluateAsync(@"(url) => { + const request = new Request(url, { + method: 'POST', + body: '', + }); + return fetch(request); + }", TestConstants.ServerUrl + "/title.html"); + + Task.WaitAll(task, actualTask); + + var request = task.Result; + Assert.Throws(() => request.GetPayloadAsJson()); + } + + /// network-post-data.spec.ts + /// should return post data for PUT requests + [Test, Timeout(PlaywrightSharp.Playwright.DefaultTimeout)] + public async Task ShouldReturnPostDataForPUTRequests() + { + await Page.GoToAsync(TestConstants.EmptyPage); + + var task = Page.WaitForEventAsync(PageEvent.Request, (r) => true); + var actualTask = Page.EvaluateAsync(@"(url) => { + const request = new Request(url, { + method: 'PUT', + body: JSON.stringify({ value: 42 }), + }); + return fetch(request); + }", TestConstants.ServerUrl + "/title.html"); + + Task.WaitAll(task, actualTask); + + var request = task.Result; + Assert.That(request.GetPayloadAsJson().RootElement.GetProperty("value").GetInt32(), Is.EqualTo(42)); + } + } +} diff --git a/src/Playwright.Tests/PageAccessibilityContentEditableTests.cs b/src/PlaywrightSharp.Tests/PageAccessibilityContentEditableTests.cs similarity index 78% rename from src/Playwright.Tests/PageAccessibilityContentEditableTests.cs rename to src/PlaywrightSharp.Tests/PageAccessibilityContentEditableTests.cs index f4dbf3bf4e..d3a192056f 100644 --- a/src/Playwright.Tests/PageAccessibilityContentEditableTests.cs +++ b/src/PlaywrightSharp.Tests/PageAccessibilityContentEditableTests.cs @@ -1,150 +1,139 @@ -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageAccessibilityContentEditableTests : PlaywrightSharpPageBaseTest - { - /// - public PageAccessibilityContentEditableTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-accessibility.spec.ts", "contenteditable", "plain text field with role should not have children")] - [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] - public async Task PlainTextFieldWithRoleShouldNotHaveChildren() - { - await Page.SetContentAsync("
Edit this image:my fake image
"); - var snapshot = (await Page.Accessibility.SnapshotAsync()); - Assert.Equal( - new AccessibilitySnapshotResult - { - Role = "textbox", - Name = "", - Value = "Edit this image:" - }, - snapshot.Children.First()); - } - - [PlaywrightTest("page-accessibility.spec.ts", "contenteditable", "plain text field without role should not have content")] - [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] - public async Task PlainTextFieldWithoutRoleShouldNotHaveContent() - { - await Page.SetContentAsync( - "
Edit this image:my fake image
"); - var snapshot = (await Page.Accessibility.SnapshotAsync()); - Assert.Equal("generic", snapshot.Children.First().Role); - Assert.Equal(string.Empty, snapshot.Children.First().Name); - } - - [PlaywrightTest("page-accessibility.spec.ts", "contenteditable", "plain text field with tabindex and without role should not have content")] - [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] - public async Task PlainTextFieldWithTabindexAndWithoutRoleShouldNotHaveContent() - { - await Page.SetContentAsync("
Edit this image:my fake image
"); - var node = (await Page.Accessibility.SnapshotAsync()).Children.First(); - Assert.Equal("generic", node.Role); - Assert.Empty(node.Name); - } - - [PlaywrightTest("page-accessibility.spec.ts", "contenteditable", "non editable textbox with role and tabIndex and label should not have children")] - [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] - public async Task NonEditableTextboxWithRoleAndTabIndexAndLabelShouldNotHaveChildren() - { - await Page.SetContentAsync(@" -
- this is the inner content - yo -
"); - - AccessibilitySnapshotResult node = null; - - if (TestConstants.IsFirefox) - { - node = new AccessibilitySnapshotResult - { - Role = "textbox", - Name = "my favorite textbox", - Value = "this is the inner content yo" - }; - } - else if (TestConstants.IsChromium) - { - node = new AccessibilitySnapshotResult - { - Role = "textbox", - Name = "my favorite textbox", - Value = "this is the inner content " - }; - } - else - { - node = new AccessibilitySnapshotResult - { - Role = "textbox", - Name = "my favorite textbox", - Value = "this is the inner content " - }; - } - Assert.Equal(node, (await Page.Accessibility.SnapshotAsync()).Children.First()); - } - - [PlaywrightTest("page-accessibility.spec.ts", "contenteditable", "checkbox with and tabIndex and label should not have children")] - [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] - public async Task CheckboxWithAndTabIndexAndLabelShouldNotHaveChildren() - { - await Page.SetContentAsync(@" -
- this is the inner content - yo -
"); - Assert.Equal( - new AccessibilitySnapshotResult - { - Role = "checkbox", - Name = "my favorite checkbox", - Checked = MixedState.On - }, - (await Page.Accessibility.SnapshotAsync()).Children.First()); - } - - [PlaywrightTest("page-accessibility.spec.ts", "contenteditable", "checkbox without label should not have children")] - [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] - public async Task CheckboxWithoutLabelShouldNotHaveChildren() - { - await Page.SetContentAsync(@" -
- this is the inner content - yo -
"); - - AccessibilitySnapshotResult node; - if (TestConstants.IsFirefox) - { - node = new AccessibilitySnapshotResult - { - Role = "checkbox", - Name = "this is the inner content yo", - Checked = MixedState.On, - }; - } - else - { - node = new AccessibilitySnapshotResult - { - Role = "checkbox", - Name = "this is the inner content yo", - Checked = MixedState.On, - }; - } - - Assert.Equal(node, (await Page.Accessibility.SnapshotAsync()).Children.First()); - } - } -} +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageAccessibilityContentEditableTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-accessibility.spec.ts", "contenteditable", "plain text field with role should not have children")] + [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] + public async Task PlainTextFieldWithRoleShouldNotHaveChildren() + { + await Page.SetContentAsync("
Edit this image:my fake image
"); + var snapshot = (await Page.Accessibility.SnapshotAsync()); + Assert.That(snapshot.Children.First(), Is.EqualTo(new AccessibilitySnapshotResult + { + Role = "textbox", + Name = "", + Value = "Edit this image:" + })); + } + + [PlaywrightTest("page-accessibility.spec.ts", "contenteditable", "plain text field without role should not have content")] + [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] + public async Task PlainTextFieldWithoutRoleShouldNotHaveContent() + { + await Page.SetContentAsync( + "
Edit this image:my fake image
"); + var snapshot = (await Page.Accessibility.SnapshotAsync()); + Assert.That(snapshot.Children.First().Role, Is.EqualTo("generic")); + Assert.That(snapshot.Children.First().Name, Is.EqualTo(string.Empty)); + } + + [PlaywrightTest("page-accessibility.spec.ts", "contenteditable", "plain text field with tabindex and without role should not have content")] + [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] + public async Task PlainTextFieldWithTabindexAndWithoutRoleShouldNotHaveContent() + { + await Page.SetContentAsync("
Edit this image:my fake image
"); + var node = (await Page.Accessibility.SnapshotAsync()).Children.First(); + Assert.That(node.Role, Is.EqualTo("generic")); + Assert.That(node.Name, Is.Empty); + } + + [PlaywrightTest("page-accessibility.spec.ts", "contenteditable", "non editable textbox with role and tabIndex and label should not have children")] + [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] + public async Task NonEditableTextboxWithRoleAndTabIndexAndLabelShouldNotHaveChildren() + { + await Page.SetContentAsync(@" +
+ this is the inner content + yo +
"); + + AccessibilitySnapshotResult node = null; + + if (TestConstants.IsFirefox) + { + node = new AccessibilitySnapshotResult + { + Role = "textbox", + Name = "my favorite textbox", + Value = "this is the inner content yo" + }; + } + else if (TestConstants.IsChromium) + { + node = new AccessibilitySnapshotResult + { + Role = "textbox", + Name = "my favorite textbox", + Value = "this is the inner content " + }; + } + else + { + node = new AccessibilitySnapshotResult + { + Role = "textbox", + Name = "my favorite textbox", + Value = "this is the inner content " + }; + } + Assert.That((await Page.Accessibility.SnapshotAsync()).Children.First(), Is.EqualTo(node)); + } + + [PlaywrightTest("page-accessibility.spec.ts", "contenteditable", "checkbox with and tabIndex and label should not have children")] + [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] + public async Task CheckboxWithAndTabIndexAndLabelShouldNotHaveChildren() + { + await Page.SetContentAsync(@" +
+ this is the inner content + yo +
"); + Assert.That((await Page.Accessibility.SnapshotAsync()).Children.First(), Is.EqualTo(new AccessibilitySnapshotResult + { + Role = "checkbox", + Name = "my favorite checkbox", + Checked = MixedState.On + })); + } + + [PlaywrightTest("page-accessibility.spec.ts", "contenteditable", "checkbox without label should not have children")] + [SkipBrowserAndPlatformFact(skipWebkit: true, skipFirefox: true)] + public async Task CheckboxWithoutLabelShouldNotHaveChildren() + { + await Page.SetContentAsync(@" +
+ this is the inner content + yo +
"); + + AccessibilitySnapshotResult node; + if (TestConstants.IsFirefox) + { + node = new AccessibilitySnapshotResult + { + Role = "checkbox", + Name = "this is the inner content yo", + Checked = MixedState.On, + }; + } + else + { + node = new AccessibilitySnapshotResult + { + Role = "checkbox", + Name = "this is the inner content yo", + Checked = MixedState.On, + }; + } + + Assert.That((await Page.Accessibility.SnapshotAsync()).Children.First(), Is.EqualTo(node)); + } + } +} diff --git a/src/Playwright.Tests/PageAccessibilityTests.cs b/src/PlaywrightSharp.Tests/PageAccessibilityTests.cs similarity index 84% rename from src/Playwright.Tests/PageAccessibilityTests.cs rename to src/PlaywrightSharp.Tests/PageAccessibilityTests.cs index 33e653d196..fbabff1fb9 100644 --- a/src/Playwright.Tests/PageAccessibilityTests.cs +++ b/src/PlaywrightSharp.Tests/PageAccessibilityTests.cs @@ -1,536 +1,523 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using KellermanSoftware.CompareNetObjects; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageAccessibilityTests : PlaywrightSharpPageBaseTest - { - /// - public PageAccessibilityTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-accessibility.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.SetContentAsync(@" - - Accessibility Test - - -

Inputs

- - - - - - - - - "); - - AccessibilitySnapshotResult nodeToCheck; - - if (TestConstants.IsFirefox) - { - nodeToCheck = new AccessibilitySnapshotResult - { - Role = "document", - Name = "Accessibility Test", - Children = new AccessibilitySnapshotResult[] - { - new AccessibilitySnapshotResult - { - Role = "heading", - Name = "Inputs", - Level = 1 - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = "Empty input", - Focused = true - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = "readonly input", - Readonly = true - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = "disabled input", - Disabled= true - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = "Input with whitespace", - Value= " " - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = string.Empty, - Value= "value only" - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = string.Empty, - Value= "and a value" - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = string.Empty, - Value= "and a value", - Description= "This is a description!"} - }.ToList() - }; - } - else if (TestConstants.IsChromium) - { - nodeToCheck = new AccessibilitySnapshotResult - { - Role = "WebArea", - Name = "Accessibility Test", - Children = new AccessibilitySnapshotResult[] - { - new AccessibilitySnapshotResult - { - Role = "heading", - Name = "Inputs", - Level = 1 - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = "Empty input", - Focused = true - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = "readonly input", - Readonly = true - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = "disabled input", - Disabled= true - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = "Input with whitespace", - Value= " " - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = "", - Value= "value only" - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = "placeholder", - Value= "and a value" - }, - new AccessibilitySnapshotResult{ - Role = "textbox", - Name = "placeholder", - Value= "and a value", - Description= "This is a description!"} - }.ToList() - }; - } - else - { - nodeToCheck = new AccessibilitySnapshotResult - { - Role = "WebArea", - Name = "Accessibility Test", - Children = new AccessibilitySnapshotResult[] - { - new AccessibilitySnapshotResult - { - Role = "heading", - Name = "Inputs", - Level = 1 - }, - new AccessibilitySnapshotResult { - Role = "textbox", - Name = "Empty input", - Focused = true - }, - new AccessibilitySnapshotResult { - Role = "textbox", - Name = "readonly input", - Readonly = true - }, - new AccessibilitySnapshotResult { - Role = "textbox", - Name = "disabled input", - Disabled = true - }, - new AccessibilitySnapshotResult { - Role = "textbox", - Name = "Input with whitespace", - Value = " " - }, - new AccessibilitySnapshotResult { - Role = "textbox", - Name = "", - Value = "value only" - }, - new AccessibilitySnapshotResult { - Role = "textbox", - Name = "placeholder", - Value = "and a value" - }, - new AccessibilitySnapshotResult { - Role = "textbox", - Name = "This is a description!", - Value = "and a value" } - }.ToList() - }; - } - - var snapshot = (await Page.Accessibility.SnapshotAsync()); - - CompareLogic compareLogic = new CompareLogic(); - var result = compareLogic.Compare(nodeToCheck, snapshot); - Assert.True(result.AreEqual, result.DifferencesString); - } - - [PlaywrightTest("page-accessibility.spec.ts", "should work with regular text")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithRegularRext() - { - await Page.SetContentAsync("
Hello World
"); - var snapshot = (await Page.Accessibility.SnapshotAsync()); - Assert.Equal(new AccessibilitySnapshotResult - { - Role = TestConstants.IsFirefox ? "text leaf" : "text", - Name = "Hello World", - }, snapshot.Children.First()); - } - - [PlaywrightTest("page-accessibility.spec.ts", "roledescription")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task RoleDescription() - { - await Page.SetContentAsync("
Hi
"); - var snapshot = (await Page.Accessibility.SnapshotAsync()); - Assert.Equal("foo", snapshot.Children.First().Roledescription); - } - - [PlaywrightTest("page-accessibility.spec.ts", "orientation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task Orientation() - { - await Page.SetContentAsync("11"); - var snapshot = (await Page.Accessibility.SnapshotAsync()); - Assert.Equal("vertical", snapshot.Children.First().Orientation); - } - - [PlaywrightTest("page-accessibility.spec.ts", "autocomplete")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task Autocomplete() - { - await Page.SetContentAsync("
hi
"); - var snapshot = (await Page.Accessibility.SnapshotAsync()); - Assert.Equal("list", snapshot.Children.First().Autocomplete); - } - - [PlaywrightTest("page-accessibility.spec.ts", "multiselectable")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task Multiselectable() - { - await Page.SetContentAsync("
hey
"); - var snapshot = (await Page.Accessibility.SnapshotAsync()); - Assert.True(snapshot.Children.First().Multiselectable); - } - - [PlaywrightTest("page-accessibility.spec.ts", "keyshortcuts")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task KeyShortcuts() - { - await Page.SetContentAsync("
hey
"); - var snapshot = (await Page.Accessibility.SnapshotAsync()); - Assert.Equal("foo", snapshot.Children.First().Keyshortcuts); - } - - [PlaywrightTest("page-accessibility.spec.ts", "filtering children of leaf nodes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task FilteringChildrenOfLeafNodes() - { - await Page.SetContentAsync(@" -
-
Tab1
-
Tab2
-
- "); - var snapshot = (await Page.Accessibility.SnapshotAsync()); - Assert.Equal( - new AccessibilitySnapshotResult - { - Role = TestConstants.IsFirefox ? "document" : "WebArea", - Name = "", - Children = new[] - { - new AccessibilitySnapshotResult - { - Role = "tab", - Name = "Tab1", - Selected = true - }, - new AccessibilitySnapshotResult - { - Role = "tab", - Name = "Tab2", - } - } - }, - snapshot); - } - - [PlaywrightTest("page-accessibility.spec.ts", "rich text editable fields should have children")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task RichTextEditableFieldsShouldHaveChildren() - { - await Page.SetContentAsync(@" -
- Edit this image: my fake image -
"); - - AccessibilitySnapshotResult node; - - if (TestConstants.IsFirefox) - { - node = new AccessibilitySnapshotResult - { - Role = "section", - Name = "", - Children = new AccessibilitySnapshotResult[] - { - new AccessibilitySnapshotResult - { - Role = "text leaf", - Name = "Edit this image: " - }, - new AccessibilitySnapshotResult - { - Role = "text", - Name = "my fake image" - } - } - }; - } - else - { - node = new AccessibilitySnapshotResult - { - Role = "generic", - Name = "", - Value = "Edit this image: ", - Children = new AccessibilitySnapshotResult[] - { - new AccessibilitySnapshotResult - { - Role = "text", - Name = "Edit this image:" - }, - new AccessibilitySnapshotResult - { - Role = "img", - Name = "my fake image" - } - } - }; - } - - var snapshot = (await Page.Accessibility.SnapshotAsync()); - Assert.Equal(node, snapshot.Children.First()); - } - - [PlaywrightTest("page-accessibility.spec.ts", "rich text editable fields with role should have children")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task RichTextEditableFieldsWithRoleShouldHaveChildren() - { - await Page.SetContentAsync(@" -
- Edit this image: my fake image -
"); - - AccessibilitySnapshotResult node; - - if (TestConstants.IsFirefox) - { - node = new AccessibilitySnapshotResult - { - Role = "textbox", - Name = "", - Value = "Edit this image: my fake image", - Children = new AccessibilitySnapshotResult[] - { - new AccessibilitySnapshotResult - { - Role = "text", - Name = "my fake image" - } - } - }; - } - else - { - node = new AccessibilitySnapshotResult - { - Role = "textbox", - Name = "", - Value = "Edit this image: ", - Children = new AccessibilitySnapshotResult[] - { - new AccessibilitySnapshotResult - { - Role = "text", - Name = "Edit this image:" - }, - new AccessibilitySnapshotResult - { - Role = "img", - Name = "my fake image" - } - } - }; - } - - Assert.Equal(node, (await Page.Accessibility.SnapshotAsync()).Children.First()); - } - - [PlaywrightTest("page-accessibility.spec.ts", "should work a button")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkAButton() - { - await Page.SetContentAsync(""); - var button = await Page.QuerySelectorAsync("button"); - - Assert.Equal( - new AccessibilitySnapshotResult - { - Role = "button", - Name = "My Button" - }, - (await Page.Accessibility.SnapshotAsync(root: button))); - } - - [PlaywrightTest("page-accessibility.spec.ts", "should work an input")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkAnInput() - { - await Page.SetContentAsync(""); - var input = await Page.QuerySelectorAsync("input"); - - Assert.Equal( - new AccessibilitySnapshotResult - { - Role = "textbox", - Name = "My Input", - Value = "My Value" - }, - (await Page.Accessibility.SnapshotAsync(root: input))); - } - - [PlaywrightTest("page-accessibility.spec.ts", "should work on a menu")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkOnAMenu() - { - await Page.SetContentAsync(@" -
-
First Item
-
Second Item
-
Third Item
-
- "); - var menu = await Page.QuerySelectorAsync("div[role=\"menu\"]"); - - var nodeToCheck = new AccessibilitySnapshotResult - { - Role = "menu", - Name = "My Menu", - Children = new AccessibilitySnapshotResult[] - { - new AccessibilitySnapshotResult - { - Role = "menuitem", - Name = "First Item" - }, - new AccessibilitySnapshotResult - { - Role = "menuitem", - Name = "Second Item" - }, - new AccessibilitySnapshotResult - { - Role = "menuitem", - Name = "Third Item" - } - }.ToList(), - Orientation = TestConstants.IsWebKit ? "vertical" : null - }; - - CompareLogic compareLogic = new CompareLogic(); - var result = compareLogic.Compare(nodeToCheck, (await Page.Accessibility.SnapshotAsync(root: menu))); - Assert.True(result.AreEqual, result.DifferencesString); - } - - [PlaywrightTest("page-accessibility.spec.ts", "should return null when the element is no longer in DOM")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnNullWhenTheElementIsNoLongerInDOM() - { - await Page.SetContentAsync(""); - var button = await Page.QuerySelectorAsync("button"); - await Page.EvalOnSelectorAsync("button", "button => button.remove()"); - - Assert.Null(await Page.Accessibility.SnapshotAsync(root: button)); - } - - [PlaywrightTest("page-accessibility.spec.ts", "should show uninteresting nodes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReportUninterestingNodes() - { - await Page.SetContentAsync(@" -
-
- hello -
- world -
-
-
- "); - - var root = await Page.QuerySelectorAsync("#root"); - var snapshot = (await Page.Accessibility.SnapshotAsync(false, root)); - Assert.Equal("textbox", snapshot.Role); - Assert.Contains("hello", snapshot.Value.ToString()); - Assert.Contains("world", snapshot.Value.ToString()); - Assert.NotEmpty(snapshot.Children); - Func findFocusedNode = root => - { - var nodes = new System.Collections.Generic.Stack(new[] { root }); - while (nodes.Count > 0) - { - var node = nodes.Pop(); - if (node.Focused) return node; - foreach (var innerNode in node.Children) - { - nodes.Push(innerNode); - } - } - - return null; - }; - } - } -} +using System; +using System.Linq; +using System.Threading.Tasks; +using KellermanSoftware.CompareNetObjects; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageAccessibilityTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-accessibility.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.SetContentAsync(@" + + Accessibility Test + + +

Inputs

+ + + + + + + + + "); + + AccessibilitySnapshotResult nodeToCheck; + + if (TestConstants.IsFirefox) + { + nodeToCheck = new AccessibilitySnapshotResult + { + Role = "document", + Name = "Accessibility Test", + Children = new AccessibilitySnapshotResult[] + { + new AccessibilitySnapshotResult + { + Role = "heading", + Name = "Inputs", + Level = 1 + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = "Empty input", + Focused = true + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = "readonly input", + Readonly = true + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = "disabled input", + Disabled= true + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = "Input with whitespace", + Value= " " + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = string.Empty, + Value= "value only" + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = string.Empty, + Value= "and a value" + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = string.Empty, + Value= "and a value", + Description= "This is a description!"} + }.ToList() + }; + } + else if (TestConstants.IsChromium) + { + nodeToCheck = new AccessibilitySnapshotResult + { + Role = "WebArea", + Name = "Accessibility Test", + Children = new AccessibilitySnapshotResult[] + { + new AccessibilitySnapshotResult + { + Role = "heading", + Name = "Inputs", + Level = 1 + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = "Empty input", + Focused = true + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = "readonly input", + Readonly = true + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = "disabled input", + Disabled= true + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = "Input with whitespace", + Value= " " + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = "", + Value= "value only" + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = "placeholder", + Value= "and a value" + }, + new AccessibilitySnapshotResult{ + Role = "textbox", + Name = "placeholder", + Value= "and a value", + Description= "This is a description!"} + }.ToList() + }; + } + else + { + nodeToCheck = new AccessibilitySnapshotResult + { + Role = "WebArea", + Name = "Accessibility Test", + Children = new AccessibilitySnapshotResult[] + { + new AccessibilitySnapshotResult + { + Role = "heading", + Name = "Inputs", + Level = 1 + }, + new AccessibilitySnapshotResult { + Role = "textbox", + Name = "Empty input", + Focused = true + }, + new AccessibilitySnapshotResult { + Role = "textbox", + Name = "readonly input", + Readonly = true + }, + new AccessibilitySnapshotResult { + Role = "textbox", + Name = "disabled input", + Disabled = true + }, + new AccessibilitySnapshotResult { + Role = "textbox", + Name = "Input with whitespace", + Value = " " + }, + new AccessibilitySnapshotResult { + Role = "textbox", + Name = "", + Value = "value only" + }, + new AccessibilitySnapshotResult { + Role = "textbox", + Name = "placeholder", + Value = "and a value" + }, + new AccessibilitySnapshotResult { + Role = "textbox", + Name = "This is a description!", + Value = "and a value" } + }.ToList() + }; + } + + var snapshot = (await Page.Accessibility.SnapshotAsync()); + + CompareLogic compareLogic = new CompareLogic(); + var result = compareLogic.Compare(nodeToCheck, snapshot); + Assert.That(result.AreEqual, Is.True, result.DifferencesString); + } + + [PlaywrightTest("page-accessibility.spec.ts", "should work with regular text")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithRegularRext() + { + await Page.SetContentAsync("
Hello World
"); + var snapshot = (await Page.Accessibility.SnapshotAsync()); + Assert.That(snapshot.Children.First(), Is.EqualTo(new AccessibilitySnapshotResult + { + Role = TestConstants.IsFirefox ? "text leaf" : "text", + Name = "Hello World", + })); + } + + [PlaywrightTest("page-accessibility.spec.ts", "roledescription")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task RoleDescription() + { + await Page.SetContentAsync("
Hi
"); + var snapshot = (await Page.Accessibility.SnapshotAsync()); + Assert.That(snapshot.Children.First().Roledescription, Is.EqualTo("foo")); + } + + [PlaywrightTest("page-accessibility.spec.ts", "orientation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task Orientation() + { + await Page.SetContentAsync("11"); + var snapshot = (await Page.Accessibility.SnapshotAsync()); + Assert.That(snapshot.Children.First().Orientation, Is.EqualTo("vertical")); + } + + [PlaywrightTest("page-accessibility.spec.ts", "autocomplete")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task Autocomplete() + { + await Page.SetContentAsync("
hi
"); + var snapshot = (await Page.Accessibility.SnapshotAsync()); + Assert.That(snapshot.Children.First().Autocomplete, Is.EqualTo("list")); + } + + [PlaywrightTest("page-accessibility.spec.ts", "multiselectable")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task Multiselectable() + { + await Page.SetContentAsync("
hey
"); + var snapshot = (await Page.Accessibility.SnapshotAsync()); + Assert.That(snapshot.Children.First().Multiselectable, Is.True); + } + + [PlaywrightTest("page-accessibility.spec.ts", "keyshortcuts")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task KeyShortcuts() + { + await Page.SetContentAsync("
hey
"); + var snapshot = (await Page.Accessibility.SnapshotAsync()); + Assert.That(snapshot.Children.First().Keyshortcuts, Is.EqualTo("foo")); + } + + [PlaywrightTest("page-accessibility.spec.ts", "filtering children of leaf nodes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task FilteringChildrenOfLeafNodes() + { + await Page.SetContentAsync(@" +
+
Tab1
+
Tab2
+
+ "); + var snapshot = (await Page.Accessibility.SnapshotAsync()); + Assert.That(snapshot, Is.EqualTo(new AccessibilitySnapshotResult + { + Role = TestConstants.IsFirefox ? "document" : "WebArea", + Name = "", + Children = new[] + { + new AccessibilitySnapshotResult + { + Role = "tab", + Name = "Tab1", + Selected = true + }, + new AccessibilitySnapshotResult + { + Role = "tab", + Name = "Tab2", + } + } + })); + } + + [PlaywrightTest("page-accessibility.spec.ts", "rich text editable fields should have children")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task RichTextEditableFieldsShouldHaveChildren() + { + await Page.SetContentAsync(@" +
+ Edit this image: my fake image +
"); + + AccessibilitySnapshotResult node; + + if (TestConstants.IsFirefox) + { + node = new AccessibilitySnapshotResult + { + Role = "section", + Name = "", + Children = new AccessibilitySnapshotResult[] + { + new AccessibilitySnapshotResult + { + Role = "text leaf", + Name = "Edit this image: " + }, + new AccessibilitySnapshotResult + { + Role = "text", + Name = "my fake image" + } + } + }; + } + else + { + node = new AccessibilitySnapshotResult + { + Role = "generic", + Name = "", + Value = "Edit this image: ", + Children = new AccessibilitySnapshotResult[] + { + new AccessibilitySnapshotResult + { + Role = "text", + Name = "Edit this image:" + }, + new AccessibilitySnapshotResult + { + Role = "img", + Name = "my fake image" + } + } + }; + } + + var snapshot = (await Page.Accessibility.SnapshotAsync()); + Assert.That(snapshot.Children.First(), Is.EqualTo(node)); + } + + [PlaywrightTest("page-accessibility.spec.ts", "rich text editable fields with role should have children")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task RichTextEditableFieldsWithRoleShouldHaveChildren() + { + await Page.SetContentAsync(@" +
+ Edit this image: my fake image +
"); + + AccessibilitySnapshotResult node; + + if (TestConstants.IsFirefox) + { + node = new AccessibilitySnapshotResult + { + Role = "textbox", + Name = "", + Value = "Edit this image: my fake image", + Children = new AccessibilitySnapshotResult[] + { + new AccessibilitySnapshotResult + { + Role = "text", + Name = "my fake image" + } + } + }; + } + else + { + node = new AccessibilitySnapshotResult + { + Role = "textbox", + Name = "", + Value = "Edit this image: ", + Children = new AccessibilitySnapshotResult[] + { + new AccessibilitySnapshotResult + { + Role = "text", + Name = "Edit this image:" + }, + new AccessibilitySnapshotResult + { + Role = "img", + Name = "my fake image" + } + } + }; + } + + Assert.That((await Page.Accessibility.SnapshotAsync()).Children.First(), Is.EqualTo(node)); + } + + [PlaywrightTest("page-accessibility.spec.ts", "should work a button")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkAButton() + { + await Page.SetContentAsync(""); + var button = await Page.QuerySelectorAsync("button"); + + Assert.That((await Page.Accessibility.SnapshotAsync(root: button)), Is.EqualTo(new AccessibilitySnapshotResult + { + Role = "button", + Name = "My Button" + })); + } + + [PlaywrightTest("page-accessibility.spec.ts", "should work an input")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkAnInput() + { + await Page.SetContentAsync(""); + var input = await Page.QuerySelectorAsync("input"); + + Assert.That((await Page.Accessibility.SnapshotAsync(root: input)), Is.EqualTo(new AccessibilitySnapshotResult + { + Role = "textbox", + Name = "My Input", + Value = "My Value" + })); + } + + [PlaywrightTest("page-accessibility.spec.ts", "should work on a menu")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkOnAMenu() + { + await Page.SetContentAsync(@" +
+
First Item
+
Second Item
+
Third Item
+
+ "); + var menu = await Page.QuerySelectorAsync("div[role=\"menu\"]"); + + var nodeToCheck = new AccessibilitySnapshotResult + { + Role = "menu", + Name = "My Menu", + Children = new AccessibilitySnapshotResult[] + { + new AccessibilitySnapshotResult + { + Role = "menuitem", + Name = "First Item" + }, + new AccessibilitySnapshotResult + { + Role = "menuitem", + Name = "Second Item" + }, + new AccessibilitySnapshotResult + { + Role = "menuitem", + Name = "Third Item" + } + }.ToList(), + Orientation = TestConstants.IsWebKit ? "vertical" : null + }; + + CompareLogic compareLogic = new CompareLogic(); + var result = compareLogic.Compare(nodeToCheck, (await Page.Accessibility.SnapshotAsync(root: menu))); + Assert.That(result.AreEqual, Is.True, result.DifferencesString); + } + + [PlaywrightTest("page-accessibility.spec.ts", "should return null when the element is no longer in DOM")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnNullWhenTheElementIsNoLongerInDOM() + { + await Page.SetContentAsync(""); + var button = await Page.QuerySelectorAsync("button"); + await Page.EvalOnSelectorAsync("button", "button => button.remove()"); + + Assert.That(await Page.Accessibility.SnapshotAsync(root: button), Is.Null); + } + + [PlaywrightTest("page-accessibility.spec.ts", "should show uninteresting nodes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReportUninterestingNodes() + { + await Page.SetContentAsync(@" +
+
+ hello +
+ world +
+
+
+ "); + + var root = await Page.QuerySelectorAsync("#root"); + var snapshot = (await Page.Accessibility.SnapshotAsync(false, root)); + Assert.That(snapshot.Role, Is.EqualTo("textbox")); + Assert.That(snapshot.Value.ToString(), Does.Contain("hello")); + Assert.That(snapshot.Value.ToString(), Does.Contain("world")); + Assert.That(snapshot.Children, Is.Not.Empty); + Func findFocusedNode = root => + { + var nodes = new System.Collections.Generic.Stack(new[] { root }); + while (nodes.Count > 0) + { + var node = nodes.Pop(); + if (node.Focused) return node; + foreach (var innerNode in node.Children) + { + nodes.Push(innerNode); + } + } + + return null; + }; + } + } +} diff --git a/src/Playwright.Tests/PageAddInitScriptTests.cs b/src/PlaywrightSharp.Tests/PageAddInitScriptTests.cs similarity index 70% rename from src/Playwright.Tests/PageAddInitScriptTests.cs rename to src/PlaywrightSharp.Tests/PageAddInitScriptTests.cs index f011233f4b..fae8c5d22f 100644 --- a/src/Playwright.Tests/PageAddInitScriptTests.cs +++ b/src/PlaywrightSharp.Tests/PageAddInitScriptTests.cs @@ -1,157 +1,152 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///evaluation.spec.ts - ///Page.evaluateOnNewDocument - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageAddInitScriptTests : PlaywrightSharpPageBaseTest - { - /// - public PageAddInitScriptTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-add-init-script.spec.ts", "should evaluate before anything else on the page")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEvaluateBeforeAnythingElseOnThePage() - { - await Page.AddInitScriptAsync(@"function(){ - window.injected = 123; - }"); - await Page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); - Assert.Equal(123, await Page.EvaluateAsync("() => window.result")); - } - - [PlaywrightTest("page-add-init-script.spec.ts", "should work with a path")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithAPath() - { - await Page.AddInitScriptAsync(scriptPath: TestUtils.GetWebServerFile("injectedfile.js")); - - await Page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); - Assert.Equal(123, await Page.EvaluateAsync("() => window.result")); - } - - [PlaywrightTest("page-add-init-script.spec.ts", "should work with a path")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithContents() - { - await Page.AddInitScriptAsync(script: @"function(){ - window.injected = 123; - }"); - await Page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); - Assert.Equal(123, await Page.EvaluateAsync("() => window.result")); - } - - [PlaywrightTest("page-add-init-script.spec.ts", "should throw without path and content")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public Task ShouldThrowWithoutPathAndContent() - => Assert.ThrowsAnyAsync(() => Page.AddInitScriptAsync()); - - [PlaywrightTest("page-add-init-script.spec.ts", "should work with browser context scripts")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithBrowserContextScripts() - { - await using var context = await Browser.NewContextAsync(); - await context.AddInitScriptAsync(@"function(){ - window.temp = 123; - }"); - - var page = await context.NewPageAsync(); - await page.AddInitScriptAsync(script: @"function(){ - window.injected = window.temp; - }"); - await page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); - Assert.Equal(123, await page.EvaluateAsync("() => window.result")); - } - - [PlaywrightTest("page-add-init-script.spec.ts", "should work with browser context scripts with path")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithBrowserContextScriptsWithPath() - { - await using var context = await Browser.NewContextAsync(); - await context.AddInitScriptAsync(scriptPath: TestUtils.GetWebServerFile("injectedfile.js")); - - var page = await context.NewPageAsync(); - - await page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); - Assert.Equal(123, await page.EvaluateAsync("() => window.result")); - } - - [PlaywrightTest("page-add-init-script.spec.ts", "should work with browser context scripts for already created pages")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithBrowserContextScriptsForAlreadyCreatedPages() - { - await using var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - - await context.AddInitScriptAsync(@"function(){ - window.temp = 123; - }"); - - await page.AddInitScriptAsync(script: @"function(){ - window.injected = window.temp; - }"); - - await page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); - Assert.Equal(123, await page.EvaluateAsync("() => window.result")); - } - - [PlaywrightTest("page-add-init-script.spec.ts", "should support multiple scripts")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportMultipleScripts() - { - await Page.AddInitScriptAsync(@"function(){ - window.script1 = 1; - }"); - await Page.AddInitScriptAsync(@"function(){ - window.script2 = 2; - }"); - await Page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); - Assert.Equal(1, await Page.EvaluateAsync("() => window.script1")); - Assert.Equal(2, await Page.EvaluateAsync("() => window.script2")); - } - - [PlaywrightTest("page-add-init-script.spec.ts", "should work with CSP")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithCSP() - { - Server.SetCSP("/empty.html", "script-src " + TestConstants.ServerUrl); - await Page.AddInitScriptAsync(@"function(){ - window.injected = 123; - }"); - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(123, await Page.EvaluateAsync("() => window.injected")); - - // Make sure CSP works. - try - { - await Page.AddScriptTagAsync(content: "window.e = 10;"); - } - catch - { - //Silent exception - } - - Assert.Null(await Page.EvaluateAsync("() => window.e")); - } - - [PlaywrightTest("page-add-init-script.spec.ts", "should work after a cross origin navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkAfterACrossOriginNavigation() - { - await Page.GoToAsync(TestConstants.CrossProcessUrl); - await Page.AddInitScriptAsync(@"function(){ - window.injected = 123; - }"); - await Page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); - Assert.Equal(123, await Page.EvaluateAsync("() => window.result")); - } - } -} +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///evaluation.spec.ts + ///Page.evaluateOnNewDocument + public class PageAddInitScriptTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-add-init-script.spec.ts", "should evaluate before anything else on the page")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEvaluateBeforeAnythingElseOnThePage() + { + await Page.AddInitScriptAsync(@"function(){ + window.injected = 123; + }"); + await Page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); + Assert.That(await Page.EvaluateAsync("() => window.result"), Is.EqualTo(123)); + } + + [PlaywrightTest("page-add-init-script.spec.ts", "should work with a path")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithAPath() + { + await Page.AddInitScriptAsync(scriptPath: TestUtils.GetWebServerFile("injectedfile.js")); + + await Page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); + Assert.That(await Page.EvaluateAsync("() => window.result"), Is.EqualTo(123)); + } + + [PlaywrightTest("page-add-init-script.spec.ts", "should work with a path")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithContents() + { + await Page.AddInitScriptAsync(script: @"function(){ + window.injected = 123; + }"); + await Page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); + Assert.That(await Page.EvaluateAsync("() => window.result"), Is.EqualTo(123)); + } + + [PlaywrightTest("page-add-init-script.spec.ts", "should throw without path and content")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public void ShouldThrowWithoutPathAndContent() + { + Assert.CatchAsync(() => Page.AddInitScriptAsync()); + } + + [PlaywrightTest("page-add-init-script.spec.ts", "should work with browser context scripts")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithBrowserContextScripts() + { + await using var context = await Browser.NewContextAsync(); + await context.AddInitScriptAsync(@"function(){ + window.temp = 123; + }"); + + var page = await context.NewPageAsync(); + await page.AddInitScriptAsync(script: @"function(){ + window.injected = window.temp; + }"); + await page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); + Assert.That(await page.EvaluateAsync("() => window.result"), Is.EqualTo(123)); + } + + [PlaywrightTest("page-add-init-script.spec.ts", "should work with browser context scripts with path")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithBrowserContextScriptsWithPath() + { + await using var context = await Browser.NewContextAsync(); + await context.AddInitScriptAsync(scriptPath: TestUtils.GetWebServerFile("injectedfile.js")); + + var page = await context.NewPageAsync(); + + await page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); + Assert.That(await page.EvaluateAsync("() => window.result"), Is.EqualTo(123)); + } + + [PlaywrightTest("page-add-init-script.spec.ts", "should work with browser context scripts for already created pages")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithBrowserContextScriptsForAlreadyCreatedPages() + { + await using var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + + await context.AddInitScriptAsync(@"function(){ + window.temp = 123; + }"); + + await page.AddInitScriptAsync(script: @"function(){ + window.injected = window.temp; + }"); + + await page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); + Assert.That(await page.EvaluateAsync("() => window.result"), Is.EqualTo(123)); + } + + [PlaywrightTest("page-add-init-script.spec.ts", "should support multiple scripts")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportMultipleScripts() + { + await Page.AddInitScriptAsync(@"function(){ + window.script1 = 1; + }"); + await Page.AddInitScriptAsync(@"function(){ + window.script2 = 2; + }"); + await Page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); + Assert.That(await Page.EvaluateAsync("() => window.script1"), Is.EqualTo(1)); + Assert.That(await Page.EvaluateAsync("() => window.script2"), Is.EqualTo(2)); + } + + [PlaywrightTest("page-add-init-script.spec.ts", "should work with CSP")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithCSP() + { + Server.SetCSP("/empty.html", "script-src " + TestConstants.ServerUrl); + await Page.AddInitScriptAsync(@"function(){ + window.injected = 123; + }"); + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await Page.EvaluateAsync("() => window.injected"), Is.EqualTo(123)); + + // Make sure CSP works. + try + { + await Page.AddScriptTagAsync(content: "window.e = 10;"); + } + catch + { + //Silent exception + } + + Assert.That(await Page.EvaluateAsync("() => window.e"), Is.Null); + } + + [PlaywrightTest("page-add-init-script.spec.ts", "should work after a cross origin navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkAfterACrossOriginNavigation() + { + await Page.GoToAsync(TestConstants.CrossProcessUrl); + await Page.AddInitScriptAsync(@"function(){ + window.injected = 123; + }"); + await Page.GoToAsync(TestConstants.ServerUrl + "/tamperable.html"); + Assert.That(await Page.EvaluateAsync("() => window.result"), Is.EqualTo(123)); + } + } +} diff --git a/src/Playwright.Tests/PageAddScriptTagTests.cs b/src/PlaywrightSharp.Tests/PageAddScriptTagTests.cs similarity index 67% rename from src/Playwright.Tests/PageAddScriptTagTests.cs rename to src/PlaywrightSharp.Tests/PageAddScriptTagTests.cs index e538b9de37..8053cc87b6 100644 --- a/src/Playwright.Tests/PageAddScriptTagTests.cs +++ b/src/PlaywrightSharp.Tests/PageAddScriptTagTests.cs @@ -1,129 +1,122 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageAddScriptTagTests : PlaywrightSharpPageBaseTest - { - /// - public PageAddScriptTagTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-add-script-tag.spec.ts", "should throw an error if no options are provided")] - [Fact(Skip = "Not relevant for C#, js specific")] - public void ShouldThrowAnErrorIfNoOptionsAreProvided() - { - } - - [PlaywrightTest("page-add-script-tag.spec.ts", "should work with a url")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithAUrl() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var scriptHandle = await Page.AddScriptTagAsync(url: "/injectedfile.js"); - Assert.NotNull(scriptHandle); - Assert.Equal(42, await Page.EvaluateAsync("() => __injected")); - } - - [PlaywrightTest("page-add-script-tag.spec.ts", "should work with a url and type=module")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithAUrlAndTypeModule() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.AddScriptTagAsync(url: "/es6/es6import.js", type: "module"); - Assert.Equal(42, await Page.EvaluateAsync("() => __es6injected")); - } - - [PlaywrightTest("page-add-script-tag.spec.ts", "should work with a path and type=module")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithAPathAndTypeModule() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.AddScriptTagAsync(path: TestUtils.GetWebServerFile("es6/es6pathimport.js"), type: "module"); - await Page.WaitForFunctionAsync("window.__es6injected"); - Assert.Equal(42, await Page.EvaluateAsync("() => __es6injected")); - } - - [PlaywrightTest("page-add-script-tag.spec.ts", "should work with a content and type=module")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithAContentAndTypeModule() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.AddScriptTagAsync(content: "import num from '/es6/es6module.js'; window.__es6injected = num;", type: "module"); - await Page.WaitForFunctionAsync("window.__es6injected"); - Assert.Equal(42, await Page.EvaluateAsync("() => __es6injected")); - } - - [PlaywrightTest("page-add-script-tag.spec.ts", "should throw an error if loading from url fail")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowAnErrorIfLoadingFromUrlFail() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Assert.ThrowsAsync(() => Page.AddScriptTagAsync(url: "/nonexistfile.js")); - } - - [PlaywrightTest("page-add-script-tag.spec.ts", "should work with a path")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithAPath() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var scriptHandle = await Page.AddScriptTagAsync(path: TestUtils.GetWebServerFile("injectedfile.js")); - Assert.NotNull(scriptHandle); - Assert.Equal(42, await Page.EvaluateAsync("() => __injected")); - } - - [PlaywrightTest("page-add-script-tag.spec.ts", "should include sourceURL when path is provided")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task ShouldIncludeSourceURLWhenPathIsProvided() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.AddScriptTagAsync(path: TestUtils.GetWebServerFile("injectedfile.js")); - string result = await Page.EvaluateAsync("() => __injectedError.stack"); - Assert.Contains(TestUtils.GetWebServerFile("injectedfile.js"), result); - } - - [PlaywrightTest("page-add-script-tag.spec.ts", "should work with content")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithContent() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var scriptHandle = await Page.AddScriptTagAsync(content: "window.__injected = 35;"); - Assert.NotNull(scriptHandle); - Assert.Equal(35, await Page.EvaluateAsync("() => __injected")); - } - - [PlaywrightTest("page-add-script-tag.spec.ts", "should throw when added with content to the CSP page")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldThrowWhenAddedWithContentToTheCSPPage() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); - await Assert.ThrowsAsync(() => - Page.AddScriptTagAsync(content: "window.__injected = 35;")); - } - - [PlaywrightTest("page-add-script-tag.spec.ts", "should throw when added with URL to the CSP page")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowWhenAddedWithURLToTheCSPPage() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); - await Assert.ThrowsAsync(() => - Page.AddScriptTagAsync(url: TestConstants.CrossProcessUrl + "/injectedfile.js")); - } - - [PlaywrightTest("page-add-script-tag.spec.ts", "should throw a nice error when the request fails")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowANiceErrorWhenTheEequestFails() - { - await Page.GoToAsync(TestConstants.EmptyPage); - string url = TestConstants.ServerUrl + "/this_does_not_exists.js"; - var exception = await Assert.ThrowsAsync(() => Page.AddScriptTagAsync(url)); - Assert.Contains(url, exception.Message); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageAddScriptTagTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-add-script-tag.spec.ts", "should throw an error if no options are provided")] + [Test, Ignore("Not relevant for C#, js specific")] + public void ShouldThrowAnErrorIfNoOptionsAreProvided() + { + } + + [PlaywrightTest("page-add-script-tag.spec.ts", "should work with a url")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithAUrl() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var scriptHandle = await Page.AddScriptTagAsync(url: "/injectedfile.js"); + Assert.That(scriptHandle, Is.Not.Null); + Assert.That(await Page.EvaluateAsync("() => __injected"), Is.EqualTo(42)); + } + + [PlaywrightTest("page-add-script-tag.spec.ts", "should work with a url and type=module")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithAUrlAndTypeModule() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.AddScriptTagAsync(url: "/es6/es6import.js", type: "module"); + Assert.That(await Page.EvaluateAsync("() => __es6injected"), Is.EqualTo(42)); + } + + [PlaywrightTest("page-add-script-tag.spec.ts", "should work with a path and type=module")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithAPathAndTypeModule() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.AddScriptTagAsync(path: TestUtils.GetWebServerFile("es6/es6pathimport.js"), type: "module"); + await Page.WaitForFunctionAsync("window.__es6injected"); + Assert.That(await Page.EvaluateAsync("() => __es6injected"), Is.EqualTo(42)); + } + + [PlaywrightTest("page-add-script-tag.spec.ts", "should work with a content and type=module")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithAContentAndTypeModule() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.AddScriptTagAsync(content: "import num from '/es6/es6module.js'; window.__es6injected = num;", type: "module"); + await Page.WaitForFunctionAsync("window.__es6injected"); + Assert.That(await Page.EvaluateAsync("() => __es6injected"), Is.EqualTo(42)); + } + + [PlaywrightTest("page-add-script-tag.spec.ts", "should throw an error if loading from url fail")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowAnErrorIfLoadingFromUrlFail() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.ThrowsAsync(() => Page.AddScriptTagAsync(url: "/nonexistfile.js")); + } + + [PlaywrightTest("page-add-script-tag.spec.ts", "should work with a path")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithAPath() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var scriptHandle = await Page.AddScriptTagAsync(path: TestUtils.GetWebServerFile("injectedfile.js")); + Assert.That(scriptHandle, Is.Not.Null); + Assert.That(await Page.EvaluateAsync("() => __injected"), Is.EqualTo(42)); + } + + [PlaywrightTest("page-add-script-tag.spec.ts", "should include sourceURL when path is provided")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task ShouldIncludeSourceURLWhenPathIsProvided() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.AddScriptTagAsync(path: TestUtils.GetWebServerFile("injectedfile.js")); + string result = await Page.EvaluateAsync("() => __injectedError.stack"); + Assert.That(result, Does.Contain(TestUtils.GetWebServerFile("injectedfile.js"))); + } + + [PlaywrightTest("page-add-script-tag.spec.ts", "should work with content")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithContent() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var scriptHandle = await Page.AddScriptTagAsync(content: "window.__injected = 35;"); + Assert.That(scriptHandle, Is.Not.Null); + Assert.That(await Page.EvaluateAsync("() => __injected"), Is.EqualTo(35)); + } + + [PlaywrightTest("page-add-script-tag.spec.ts", "should throw when added with content to the CSP page")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldThrowWhenAddedWithContentToTheCSPPage() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); + Assert.ThrowsAsync(() => + Page.AddScriptTagAsync(content: "window.__injected = 35;")); + } + + [PlaywrightTest("page-add-script-tag.spec.ts", "should throw when added with URL to the CSP page")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowWhenAddedWithURLToTheCSPPage() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); + Assert.ThrowsAsync(() => + Page.AddScriptTagAsync(url: TestConstants.CrossProcessUrl + "/injectedfile.js")); + } + + [PlaywrightTest("page-add-script-tag.spec.ts", "should throw a nice error when the request fails")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowANiceErrorWhenTheEequestFails() + { + await Page.GoToAsync(TestConstants.EmptyPage); + string url = TestConstants.ServerUrl + "/this_does_not_exists.js"; + var exception = Assert.ThrowsAsync(() => Page.AddScriptTagAsync(url)); + Assert.That(exception.Message, Does.Contain(url)); + } + } +} diff --git a/src/Playwright.Tests/PageAddStyleTagTests.cs b/src/PlaywrightSharp.Tests/PageAddStyleTagTests.cs similarity index 61% rename from src/Playwright.Tests/PageAddStyleTagTests.cs rename to src/PlaywrightSharp.Tests/PageAddStyleTagTests.cs index 9901975f1c..c7310c08f6 100644 --- a/src/Playwright.Tests/PageAddStyleTagTests.cs +++ b/src/PlaywrightSharp.Tests/PageAddStyleTagTests.cs @@ -1,91 +1,84 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageAddStyleTagTests : PlaywrightSharpPageBaseTest - { - /// - public PageAddStyleTagTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-add-style-tag.spec.ts", "should throw an error if no options are provided")] - [Fact(Skip = "Not relevant for C#, js specific")] - public void ShouldThrowAnErrorIfNoOptionsAreProvided() - { - } - - [PlaywrightTest("page-add-style-tag.spec.ts", "should work with a url")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithAUrl() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var styleHandle = await Page.AddStyleTagAsync(url: "/injectedstyle.css"); - Assert.NotNull(styleHandle); - Assert.Equal("rgb(255, 0, 0)", await Page.EvaluateAsync("window.getComputedStyle(document.querySelector('body')).getPropertyValue('background-color')")); - } - - [PlaywrightTest("page-add-style-tag.spec.ts", "should throw an error if loading from url fail")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowAnErrorIfLoadingFromUrlFail() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Assert.ThrowsAsync(() => - Page.AddStyleTagAsync(url: "/nonexistfile.js")); - } - - [PlaywrightTest("page-add-style-tag.spec.ts", "should work with a path")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithAPath() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var styleHandle = await Page.AddStyleTagAsync(path: TestUtils.GetWebServerFile("injectedstyle.css")); - Assert.NotNull(styleHandle); - Assert.Equal("rgb(255, 0, 0)", await Page.EvaluateAsync("window.getComputedStyle(document.querySelector('body')).getPropertyValue('background-color')")); - } - - [PlaywrightTest("page-add-style-tag.spec.ts", "should include sourceURL when path is provided")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldIncludeSourceURLWhenPathIsProvided() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.AddStyleTagAsync(path: TestUtils.GetWebServerFile("injectedstyle.css")); - var styleHandle = await Page.QuerySelectorAsync("style"); - string styleContent = await Page.EvaluateAsync("style => style.innerHTML", styleHandle); - Assert.Contains(TestUtils.GetWebServerFile("injectedstyle.css"), styleContent); - } - - [PlaywrightTest("page-add-style-tag.spec.ts", "should work with content")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithContent() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var styleHandle = await Page.AddStyleTagAsync(content: "body { background-color: green; }"); - Assert.NotNull(styleHandle); - Assert.Equal("rgb(0, 128, 0)", await Page.EvaluateAsync("window.getComputedStyle(document.querySelector('body')).getPropertyValue('background-color')")); - } - - [PlaywrightTest("page-add-style-tag.spec.ts", "should throw when added with content to the CSP page")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowWhenAddedWithContentToTheCSPPage() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); - await Assert.ThrowsAsync(() => - Page.AddStyleTagAsync(content: "body { background-color: green; }")); - } - - [PlaywrightTest("page-add-style-tag.spec.ts", "should throw when added with URL to the CSP page")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowWhenAddedWithURLToTheCSPPage() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); - await Assert.ThrowsAsync(() => - Page.AddStyleTagAsync(url: TestConstants.CrossProcessUrl + "/injectedstyle.css")); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageAddStyleTagTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-add-style-tag.spec.ts", "should throw an error if no options are provided")] + [Test, Ignore("Not relevant for C#, js specific")] + public void ShouldThrowAnErrorIfNoOptionsAreProvided() + { + } + + [PlaywrightTest("page-add-style-tag.spec.ts", "should work with a url")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithAUrl() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var styleHandle = await Page.AddStyleTagAsync(url: "/injectedstyle.css"); + Assert.That(styleHandle, Is.Not.Null); + Assert.That(await Page.EvaluateAsync("window.getComputedStyle(document.querySelector('body')).getPropertyValue('background-color')"), Is.EqualTo("rgb(255, 0, 0)")); + } + + [PlaywrightTest("page-add-style-tag.spec.ts", "should throw an error if loading from url fail")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowAnErrorIfLoadingFromUrlFail() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.ThrowsAsync(() => + Page.AddStyleTagAsync(url: "/nonexistfile.js")); + } + + [PlaywrightTest("page-add-style-tag.spec.ts", "should work with a path")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithAPath() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var styleHandle = await Page.AddStyleTagAsync(path: TestUtils.GetWebServerFile("injectedstyle.css")); + Assert.That(styleHandle, Is.Not.Null); + Assert.That(await Page.EvaluateAsync("window.getComputedStyle(document.querySelector('body')).getPropertyValue('background-color')"), Is.EqualTo("rgb(255, 0, 0)")); + } + + [PlaywrightTest("page-add-style-tag.spec.ts", "should include sourceURL when path is provided")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldIncludeSourceURLWhenPathIsProvided() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.AddStyleTagAsync(path: TestUtils.GetWebServerFile("injectedstyle.css")); + var styleHandle = await Page.QuerySelectorAsync("style"); + string styleContent = await Page.EvaluateAsync("style => style.innerHTML", styleHandle); + Assert.That(styleContent, Does.Contain(TestUtils.GetWebServerFile("injectedstyle.css"))); + } + + [PlaywrightTest("page-add-style-tag.spec.ts", "should work with content")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithContent() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var styleHandle = await Page.AddStyleTagAsync(content: "body { background-color: green; }"); + Assert.That(styleHandle, Is.Not.Null); + Assert.That(await Page.EvaluateAsync("window.getComputedStyle(document.querySelector('body')).getPropertyValue('background-color')"), Is.EqualTo("rgb(0, 128, 0)")); + } + + [PlaywrightTest("page-add-style-tag.spec.ts", "should throw when added with content to the CSP page")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowWhenAddedWithContentToTheCSPPage() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); + Assert.ThrowsAsync(() => + Page.AddStyleTagAsync(content: "body { background-color: green; }")); + } + + [PlaywrightTest("page-add-style-tag.spec.ts", "should throw when added with URL to the CSP page")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowWhenAddedWithURLToTheCSPPage() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/csp.html"); + Assert.ThrowsAsync(() => + Page.AddStyleTagAsync(url: TestConstants.CrossProcessUrl + "/injectedstyle.css")); + } + } +} diff --git a/src/Playwright.Tests/PageAutoWaitingBasicTests.cs b/src/PlaywrightSharp.Tests/PageAutoWaitingBasicTests.cs similarity index 82% rename from src/Playwright.Tests/PageAutoWaitingBasicTests.cs rename to src/PlaywrightSharp.Tests/PageAutoWaitingBasicTests.cs index cefbd145e4..97bce3713d 100644 --- a/src/Playwright.Tests/PageAutoWaitingBasicTests.cs +++ b/src/PlaywrightSharp.Tests/PageAutoWaitingBasicTests.cs @@ -1,263 +1,256 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageAutoWaitingBasicTests : PlaywrightSharpPageBaseTest - { - /// - public PageAutoWaitingBasicTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await navigation when clicking anchor")] - [Fact(Skip = "Flacky")] - public async Task ShouldAwaitNavigationWhenClickingAnchor() - { - var messages = new List(); - Server.SetRoute("/empty.html", context => - { - messages.Add("route"); - context.Response.ContentType = "text/html"; - return context.Response.WriteAsync(""); - }); - - await Page.SetContentAsync($"empty.html"); - await TaskUtils.WhenAll( - Page.ClickAsync("a").ContinueWith(_ => messages.Add("click")), - Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); - - Assert.Equal("route|navigated|click", string.Join("|", messages)); - } - - [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await cross-process navigation when clicking anchor")] - [Fact(Skip = "Flacky")] - public async Task ShouldAwaitCrossProcessNavigationWhenClickingAnchor() - { - var messages = new List(); - Server.SetRoute("/empty.html", context => - { - messages.Add("route"); - context.Response.ContentType = "text/html"; - return context.Response.WriteAsync(""); - }); - - await Page.SetContentAsync($"empty.html"); - await TaskUtils.WhenAll( - Page.ClickAsync("a").ContinueWith(_ => messages.Add("click")), - Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); - - Assert.Equal("route|navigated|click", string.Join("|", messages)); - } - - [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await form-get on click")] - [Fact(Skip = "Flacky")] - public async Task ShouldAwaitFormGetOnClick() - { - var messages = new List(); - Server.SetRoute("/empty.html?foo=bar", context => - { - messages.Add("route"); - context.Response.ContentType = "text/html"; - return context.Response.WriteAsync(""); - }); - - await Page.SetContentAsync($@" -
- - -
"); - - await TaskUtils.WhenAll( - Page.ClickAsync("input[type=submit]").ContinueWith(_ => messages.Add("click")), - Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); - - Assert.Equal("route|navigated|click", string.Join("|", messages)); - } - - [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await form-post on click")] - [Fact(Skip = "Flacky")] - public async Task ShouldAwaitFormPostOnClick() - { - var messages = new List(); - Server.SetRoute("/empty.html", context => - { - messages.Add("route"); - context.Response.ContentType = "text/html"; - return context.Response.WriteAsync(""); - }); - - await Page.SetContentAsync($@" -
- - -
"); - - await TaskUtils.WhenAll( - Page.ClickAsync("input[type=submit]").ContinueWith(_ => messages.Add("click")), - Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); - - Assert.Equal("route|navigated|click", string.Join("|", messages)); - } - - [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await navigation when assigning location")] - [Fact(Skip = "Flacky")] - public async Task ShouldAwaitNavigationWhenAssigningLocation() - { - var messages = new List(); - Server.SetRoute("/empty.html", context => - { - messages.Add("route"); - context.Response.ContentType = "text/html"; - return context.Response.WriteAsync(""); - }); - - await TaskUtils.WhenAll( - Page.EvaluateAsync($"window.location.href = '{TestConstants.EmptyPage}'").ContinueWith(_ => messages.Add("evaluate")), - Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); - - Assert.Equal("route|navigated|evaluate", string.Join("|", messages)); - } - - [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await navigation when assigning location twice")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAwaitNavigationWhenAssigningLocationTwice() - { - var messages = new List(); - Server.SetRoute("/empty.html?cancel", context => - { - return context.Response.WriteAsync("done"); - }); - - Server.SetRoute("/empty.html?override", context => - { - messages.Add("routeoverride"); - return context.Response.WriteAsync("done"); - }); - - await Page.EvaluateAsync($@" - window.location.href = '{TestConstants.EmptyPage}?cancel'; - window.location.href = '{TestConstants.EmptyPage}?override';"); - messages.Add("evaluate"); - - Assert.Equal("routeoverride|evaluate", string.Join("|", messages)); - } - - [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await navigation when evaluating reload")] - [Fact(Skip = "Flacky")] - public async Task ShouldAwaitNavigationWhenEvaluatingReload() - { - var messages = new List(); - await Page.GoToAsync(TestConstants.EmptyPage); - Server.SetRoute("/empty.html", context => - { - messages.Add("route"); - context.Response.ContentType = "text/html"; - return context.Response.WriteAsync(""); - }); - - await TaskUtils.WhenAll( - Page.EvaluateAsync($"window.location.reload();").ContinueWith(_ => messages.Add("evaluate")), - Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); - - Assert.Equal("route|navigated|evaluate", string.Join("|", messages)); - } - - [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await navigating specified target")] - [Fact(Skip = "Flacky")] - public async Task ShouldAwaitNavigatingSpecifiedTarget() - { - var messages = new List(); - Server.SetRoute("/empty.html", context => - { - messages.Add("route"); - context.Response.ContentType = "text/html"; - return context.Response.WriteAsync(""); - }); - - await Page.SetContentAsync($@" - empty.html - "); - - var frame = Page.Frame("target"); - - await TaskUtils.WhenAll( - Page.ClickAsync("a").ContinueWith(_ => messages.Add("click")), - Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); - - Assert.Equal(TestConstants.EmptyPage, frame.Url); - Assert.Equal("route|navigated|click", string.Join("|", messages)); - } - - [PlaywrightTest("page-autowaiting-basic.spec.ts", "should work with noWaitAfter: true")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithNoWaitAfterTrue() - { - var messages = new List(); - Server.SetRoute("/empty.html", _ => Task.CompletedTask); - - await Page.SetContentAsync($@"empty.html"); - await Page.ClickAsync("a", noWaitAfter: true); - } - - [PlaywrightTest("page-autowaiting-basic.spec.ts", "should work with waitForLoadState(load)")] - [Fact(Skip = "Flacky")] - public async Task ShouldWorkWithWaitForLoadStateLoad() - { - var messages = new List(); - Server.SetRoute("/empty.html", context => - { - messages.Add("route"); - context.Response.ContentType = "text/html"; - return context.Response.WriteAsync(""); - }); - - await Page.SetContentAsync($"empty.html"); - var clickLoaded = new TaskCompletionSource(); - - await TaskUtils.WhenAll( - Page.ClickAsync("a").ContinueWith(_ => Page.WaitForLoadStateAsync(LoadState.Load).ContinueWith(_ => - { - messages.Add("clickload"); - clickLoaded.TrySetResult(true); - })), - clickLoaded.Task, - Page.WaitForNavigationAsync(WaitUntilState.DOMContentLoaded).ContinueWith(_ => messages.Add("domcontentloaded"))); - - Assert.Equal("route|domcontentloaded|clickload", string.Join("|", messages)); - } - - [PlaywrightTest("page-autowaiting-basic.spec.ts", "should work with goto following click")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithGotoFollowingClick() - { - var messages = new List(); - Server.SetRoute("/empty.html", context => - { - messages.Add("route"); - context.Response.ContentType = "text/html"; - return context.Response.WriteAsync("You are logged in"); - }); - - await Page.SetContentAsync($@" -
- - -
"); - - await Page.FillAsync("input[type=text]", "admin"); - await Page.ClickAsync("input[type=submit]"); - await Page.GoToAsync(TestConstants.EmptyPage); - } - - [PlaywrightTest("page-autowaiting-basic.spec.ts", "should report navigation in the log when clicking anchor")] - [Fact(Skip = "We ignore USES_HOOKS")] - public void ShouldReportNavigationInTheLogWhenClickingAnchor() { } - } -} +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageAutoWaitingBasicTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await navigation when clicking anchor")] + [Test, Ignore("Flacky")] + public async Task ShouldAwaitNavigationWhenClickingAnchor() + { + var messages = new List(); + Server.SetRoute("/empty.html", context => + { + messages.Add("route"); + context.Response.ContentType = "text/html"; + return context.Response.WriteAsync(""); + }); + + await Page.SetContentAsync($"empty.html"); + await TaskUtils.WhenAll( + Page.ClickAsync("a").ContinueWith(_ => messages.Add("click")), + Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); + + Assert.That(string.Join("|", messages), Is.EqualTo("route|navigated|click")); + } + + [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await cross-process navigation when clicking anchor")] + [Test, Ignore("Flacky")] + public async Task ShouldAwaitCrossProcessNavigationWhenClickingAnchor() + { + var messages = new List(); + Server.SetRoute("/empty.html", context => + { + messages.Add("route"); + context.Response.ContentType = "text/html"; + return context.Response.WriteAsync(""); + }); + + await Page.SetContentAsync($"empty.html"); + await TaskUtils.WhenAll( + Page.ClickAsync("a").ContinueWith(_ => messages.Add("click")), + Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); + + Assert.That(string.Join("|", messages), Is.EqualTo("route|navigated|click")); + } + + [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await form-get on click")] + [Test, Ignore("Flacky")] + public async Task ShouldAwaitFormGetOnClick() + { + var messages = new List(); + Server.SetRoute("/empty.html?foo=bar", context => + { + messages.Add("route"); + context.Response.ContentType = "text/html"; + return context.Response.WriteAsync(""); + }); + + await Page.SetContentAsync($@" +
+ + +
"); + + await TaskUtils.WhenAll( + Page.ClickAsync("input[type=submit]").ContinueWith(_ => messages.Add("click")), + Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); + + Assert.That(string.Join("|", messages), Is.EqualTo("route|navigated|click")); + } + + [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await form-post on click")] + [Test, Ignore("Flacky")] + public async Task ShouldAwaitFormPostOnClick() + { + var messages = new List(); + Server.SetRoute("/empty.html", context => + { + messages.Add("route"); + context.Response.ContentType = "text/html"; + return context.Response.WriteAsync(""); + }); + + await Page.SetContentAsync($@" +
+ + +
"); + + await TaskUtils.WhenAll( + Page.ClickAsync("input[type=submit]").ContinueWith(_ => messages.Add("click")), + Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); + + Assert.That(string.Join("|", messages), Is.EqualTo("route|navigated|click")); + } + + [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await navigation when assigning location")] + [Test, Ignore("Flacky")] + public async Task ShouldAwaitNavigationWhenAssigningLocation() + { + var messages = new List(); + Server.SetRoute("/empty.html", context => + { + messages.Add("route"); + context.Response.ContentType = "text/html"; + return context.Response.WriteAsync(""); + }); + + await TaskUtils.WhenAll( + Page.EvaluateAsync($"window.location.href = '{TestConstants.EmptyPage}'").ContinueWith(_ => messages.Add("evaluate")), + Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); + + Assert.That(string.Join("|", messages), Is.EqualTo("route|navigated|evaluate")); + } + + [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await navigation when assigning location twice")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAwaitNavigationWhenAssigningLocationTwice() + { + var messages = new List(); + Server.SetRoute("/empty.html?cancel", context => + { + return context.Response.WriteAsync("done"); + }); + + Server.SetRoute("/empty.html?override", context => + { + messages.Add("routeoverride"); + return context.Response.WriteAsync("done"); + }); + + await Page.EvaluateAsync($@" + window.location.href = '{TestConstants.EmptyPage}?cancel'; + window.location.href = '{TestConstants.EmptyPage}?override';"); + messages.Add("evaluate"); + + Assert.That(string.Join("|", messages), Is.EqualTo("routeoverride|evaluate")); + } + + [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await navigation when evaluating reload")] + [Test, Ignore("Flacky")] + public async Task ShouldAwaitNavigationWhenEvaluatingReload() + { + var messages = new List(); + await Page.GoToAsync(TestConstants.EmptyPage); + Server.SetRoute("/empty.html", context => + { + messages.Add("route"); + context.Response.ContentType = "text/html"; + return context.Response.WriteAsync(""); + }); + + await TaskUtils.WhenAll( + Page.EvaluateAsync($"window.location.reload();").ContinueWith(_ => messages.Add("evaluate")), + Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); + + Assert.That(string.Join("|", messages), Is.EqualTo("route|navigated|evaluate")); + } + + [PlaywrightTest("page-autowaiting-basic.spec.ts", "should await navigating specified target")] + [Test, Ignore("Flacky")] + public async Task ShouldAwaitNavigatingSpecifiedTarget() + { + var messages = new List(); + Server.SetRoute("/empty.html", context => + { + messages.Add("route"); + context.Response.ContentType = "text/html"; + return context.Response.WriteAsync(""); + }); + + await Page.SetContentAsync($@" + empty.html + "); + + var frame = Page.Frame("target"); + + await TaskUtils.WhenAll( + Page.ClickAsync("a").ContinueWith(_ => messages.Add("click")), + Page.WaitForEventAsync(PageEvent.FrameNavigated).ContinueWith(_ => messages.Add("navigated"))); + + Assert.That(frame.Url, Is.EqualTo(TestConstants.EmptyPage)); + Assert.That(string.Join("|", messages), Is.EqualTo("route|navigated|click")); + } + + [PlaywrightTest("page-autowaiting-basic.spec.ts", "should work with noWaitAfter: true")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithNoWaitAfterTrue() + { + var messages = new List(); + Server.SetRoute("/empty.html", _ => Task.CompletedTask); + + await Page.SetContentAsync($@"empty.html"); + await Page.ClickAsync("a", noWaitAfter: true); + } + + [PlaywrightTest("page-autowaiting-basic.spec.ts", "should work with waitForLoadState(load)")] + [Test, Ignore("Flacky")] + public async Task ShouldWorkWithWaitForLoadStateLoad() + { + var messages = new List(); + Server.SetRoute("/empty.html", context => + { + messages.Add("route"); + context.Response.ContentType = "text/html"; + return context.Response.WriteAsync(""); + }); + + await Page.SetContentAsync($"empty.html"); + var clickLoaded = new TaskCompletionSource(); + + await TaskUtils.WhenAll( + Page.ClickAsync("a").ContinueWith(_ => Page.WaitForLoadStateAsync(LoadState.Load).ContinueWith(_ => + { + messages.Add("clickload"); + clickLoaded.TrySetResult(true); + })), + clickLoaded.Task, + Page.WaitForNavigationAsync(WaitUntilState.DOMContentLoaded).ContinueWith(_ => messages.Add("domcontentloaded"))); + + Assert.That(string.Join("|", messages), Is.EqualTo("route|domcontentloaded|clickload")); + } + + [PlaywrightTest("page-autowaiting-basic.spec.ts", "should work with goto following click")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithGotoFollowingClick() + { + var messages = new List(); + Server.SetRoute("/empty.html", context => + { + messages.Add("route"); + context.Response.ContentType = "text/html"; + return context.Response.WriteAsync("You are logged in"); + }); + + await Page.SetContentAsync($@" +
+ + +
"); + + await Page.FillAsync("input[type=text]", "admin"); + await Page.ClickAsync("input[type=submit]"); + await Page.GoToAsync(TestConstants.EmptyPage); + } + + [PlaywrightTest("page-autowaiting-basic.spec.ts", "should report navigation in the log when clicking anchor")] + [Test, Ignore("We ignore USES_HOOKS")] + public void ShouldReportNavigationInTheLogWhenClickingAnchor() { } + } +} diff --git a/src/Playwright.Tests/PageAutoWaitingNotHangTests.cs b/src/PlaywrightSharp.Tests/PageAutoWaitingNotHangTests.cs similarity index 79% rename from src/Playwright.Tests/PageAutoWaitingNotHangTests.cs rename to src/PlaywrightSharp.Tests/PageAutoWaitingNotHangTests.cs index 75da22d7e5..fe6042e157 100644 --- a/src/Playwright.Tests/PageAutoWaitingNotHangTests.cs +++ b/src/PlaywrightSharp.Tests/PageAutoWaitingNotHangTests.cs @@ -1,93 +1,86 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageAutoWaitingNotHangTests : PlaywrightSharpPageBaseTest - { - /// - public PageAutoWaitingNotHangTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "clicking on links which do not commit navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ClickingOnLinksWhichDoNotCommitNavigation() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync($"fooobar"); - await Page.ClickAsync("a"); - } - - [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "calling window.stop async")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task CallingWindowStopAsync() - { - Server.SetRoute("/empty.html", _ => Task.CompletedTask); - - await Page.EvaluateAsync($@"(url) => {{ - window.location.href = url; - setTimeout(() => window.stop(), 100); - }}", TestConstants.EmptyPage); - } - - [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "calling window.stop")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task CallingWindowStop() - { - Server.SetRoute("/empty.html", _ => Task.CompletedTask); - - await Page.EvaluateAsync($@"(url) => {{ - window.location.href = url; - window.stop(); - }}", TestConstants.EmptyPage); - } - - [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "assigning location to about:blank")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task AssigningLocationToAboutBlank() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.EvaluateAsync("window.location.href = 'about:blank';"); - } - - [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "assigning location to about:blank after non-about:blank")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task AssigningLocationToAboutBlankAfterNonAboutBlank() - { - Server.SetRoute("/empty.html", _ => Task.CompletedTask); - - await Page.EvaluateAsync($@"(url) => {{ - window.location.href = '{TestConstants.EmptyPage}'; - window.location.href = 'about:blank'; - }}", TestConstants.EmptyPage); - } - - [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "calling window.open and window.close")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task CallingWindowOpenAndWindowClose() - { - await Page.GoToAsync(TestConstants.EmptyPage); - - await Page.EvaluateAsync($@"(url) => {{ - const popup = window.open(window.location.href); - popup.close(); - }}", TestConstants.EmptyPage); - } - - [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "opening a popup")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task OpeningAPopup() - { - await Page.GoToAsync(TestConstants.EmptyPage); - - await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.Popup), - Page.EvaluateAsync("() => window._popup = window.open(window.location.href)")); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageAutoWaitingNotHangTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "clicking on links which do not commit navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ClickingOnLinksWhichDoNotCommitNavigation() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.SetContentAsync($"fooobar"); + await Page.ClickAsync("a"); + } + + [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "calling window.stop async")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task CallingWindowStopAsync() + { + Server.SetRoute("/empty.html", _ => Task.CompletedTask); + + await Page.EvaluateAsync($@"(url) => {{ + window.location.href = url; + setTimeout(() => window.stop(), 100); + }}", TestConstants.EmptyPage); + } + + [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "calling window.stop")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task CallingWindowStop() + { + Server.SetRoute("/empty.html", _ => Task.CompletedTask); + + await Page.EvaluateAsync($@"(url) => {{ + window.location.href = url; + window.stop(); + }}", TestConstants.EmptyPage); + } + + [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "assigning location to about:blank")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task AssigningLocationToAboutBlank() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.EvaluateAsync("window.location.href = 'about:blank';"); + } + + [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "assigning location to about:blank after non-about:blank")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task AssigningLocationToAboutBlankAfterNonAboutBlank() + { + Server.SetRoute("/empty.html", _ => Task.CompletedTask); + + await Page.EvaluateAsync($@"(url) => {{ + window.location.href = '{TestConstants.EmptyPage}'; + window.location.href = 'about:blank'; + }}", TestConstants.EmptyPage); + } + + [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "calling window.open and window.close")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task CallingWindowOpenAndWindowClose() + { + await Page.GoToAsync(TestConstants.EmptyPage); + + await Page.EvaluateAsync($@"(url) => {{ + const popup = window.open(window.location.href); + popup.close(); + }}", TestConstants.EmptyPage); + } + + [PlaywrightTest("page-autowaiting-no-hang.spec.ts", "opening a popup")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task OpeningAPopup() + { + await Page.GoToAsync(TestConstants.EmptyPage); + + await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.Popup), + Page.EvaluateAsync("() => window._popup = window.open(window.location.href)")); + } + } +} diff --git a/src/Playwright.Tests/PageBasicTests.cs b/src/PlaywrightSharp.Tests/PageBasicTests.cs similarity index 64% rename from src/Playwright.Tests/PageBasicTests.cs rename to src/PlaywrightSharp.Tests/PageBasicTests.cs index 5a8cb734f1..3f1980afac 100644 --- a/src/Playwright.Tests/PageBasicTests.cs +++ b/src/PlaywrightSharp.Tests/PageBasicTests.cs @@ -1,272 +1,266 @@ -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageBasicTests : PlaywrightSharpPageBaseTest - { - /// - public PageBasicTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-basic.spec.ts", "should reject all promises when page is closed")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRejectAllPromisesWhenPageIsClosed() - { - var newPage = await Context.NewPageAsync(); - var exception = await Assert.ThrowsAsync(() => TaskUtils.WhenAll( - newPage.EvaluateAsync("() => new Promise(r => { })"), - newPage.CloseAsync() - )); - Assert.Contains("Protocol error", Assert.IsType(exception).Message); - } - - [PlaywrightTest("page-basic.spec.ts", "async stacks should work")] - [Fact(Skip = "We don't need to test this in .NET")] - public async Task AsyncStacksShouldWork() - { - Server.SetRoute("/empty.html", context => - { - context.Abort(); // is this right? - return Task.CompletedTask; - }); - var exception = await Assert.ThrowsAsync(() => Page.GoToAsync(TestConstants.EmptyPage)); - Assert.Contains(nameof(PageBasicTests), exception.StackTrace); - } - - [PlaywrightTest("page-basic.spec.ts", "Page.press should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PagePressShouldWork() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.PressAsync("textarea", "a"); - Assert.Equal("a", await Page.EvaluateAsync("() => document.querySelector('textarea').value")); - } - - [PlaywrightTest("page-basic.spec.ts", "Frame.press should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task FramePressShouldWork() - { - await Page.SetContentAsync($""); - var frame = Page.Frames.Single(f => f.Name == "inner"); - await frame.PressAsync("textarea", "a"); - Assert.Equal("a", await frame.EvaluateAsync("() => document.querySelector('textarea').value")); - } - - [PlaywrightTest("page-basic.spec.ts", "page.frame should respect name")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnTheCorrectBrowserInstance() - { - await Page.SetContentAsync(""); - Assert.Null(Page.Frames.FirstOrDefault(f => f.Name == "bogus")); - var frame = Page.Frames.FirstOrDefault(f => f.Name == "target"); - Assert.Same(Page.MainFrame.ChildFrames.First(), frame); - } - - [PlaywrightTest("page-basic.spec.ts", "page.frame should respect url")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRespectUrl() - { - await Page.SetContentAsync($""); - Assert.Null(Page.Frames.FirstOrDefault(f => f.Name == "bogus")); - var frame = Page.Frames.FirstOrDefault(f => f.Url.Contains("empty")); - Assert.Same(Page.MainFrame.ChildFrames.First(), frame); - } - - [PlaywrightTest("page-basic.spec.ts", "should provide access to the opener page")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldProvideAccessToTheOpenerPage() - { - var (popupEvent, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.Popup), - Page.EvaluateAsync("() => window.open('about:blank')") - ); - var opener = await popupEvent.OpenerAsync(); - Assert.Equal(Page, opener); - } - - [PlaywrightTest("page-basic.spec.ts", "should return null if parent page has been closed")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnNullIfParentPageHasBeenClosed() - { - var (popupEvent, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.Popup), - Page.EvaluateAsync("() => window.open('about:blank')") - ); - await Page.CloseAsync(); - var opener = await popupEvent.OpenerAsync(); - Assert.Null(opener); - } - - [PlaywrightTest("page-basic.spec.ts", "should return the page title")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnThePageTitle() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/title.html"); - Assert.Equal("Woof-Woof", await Page.TitleAsync()); - } - - [PlaywrightTest("page-basic.spec.ts", "page.url should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PageUrlShouldWork() - { - Assert.Equal("about:blank", Page.Url); - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(TestConstants.EmptyPage, Page.Url); - } - - [PlaywrightTest("page-basic.spec.ts", "should include hashes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldIncludeHashes() - { - await Page.GoToAsync(TestConstants.EmptyPage + "#hash"); - Assert.Equal(TestConstants.EmptyPage + "#hash", Page.Url); - await Page.EvaluateAsync("() => window.location.hash = 'dynamic'"); - Assert.Equal(TestConstants.EmptyPage + "#dynamic", Page.Url); - } - - [PlaywrightTest("page-basic.spec.ts", "should fail with error upon disconnect")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWithErrorUponDisconnect() - { - var task = Page.WaitForEventAsync(PageEvent.Download); - await Page.CloseAsync(); - var exception = await Assert.ThrowsAnyAsync(() => task); - Assert.Contains("Page closed", exception.Message); - } - - [PlaywrightTest("page-basic.spec.ts", "should have sane user agent")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHaveASaneUserAgent() - { - string userAgent = await Page.EvaluateAsync("() => navigator.userAgent"); - var regex = new Regex("[()]"); - string[] parts = Regex.Split(userAgent, "[()]").Select(t => t.Trim()).ToArray(); - - Assert.Equal("Mozilla/5.0", parts[0]); - - if (TestConstants.IsFirefox) - { - string[] engineBrowser = parts[2].Split(' '); - Assert.StartsWith("Gecko", engineBrowser[0]); - Assert.StartsWith("Firefox", engineBrowser[1]); - } - else - { - Assert.StartsWith("AppleWebKit/", parts[2]); - Assert.Equal("KHTML, like Gecko", parts[3]); - string[] engineBrowser = parts[4].Split(' '); - Assert.StartsWith("Safari/", engineBrowser[1]); - - if (TestConstants.IsChromium) - { - Assert.Contains("Chrome/", engineBrowser[0]); - } - else - { - Assert.StartsWith("Version", engineBrowser[0]); - } - } - } - - [PlaywrightTest("page-basic.spec.ts", "should work with window.close")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithWindowClose() - { - var newPageTask = Page.WaitForEventAsync(PageEvent.Popup); - await Page.EvaluateAsync("() => window['newPage'] = window.open('about:blank')"); - var newPage = await newPageTask; - var closedTsc = new TaskCompletionSource(); - newPage.Close += (_, _) => closedTsc.SetResult(true); - await Page.EvaluateAsync("() => window['newPage'].close()"); - await closedTsc.Task; - } - - [PlaywrightTest("page-basic.spec.ts", "should work with page.close")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithPageClose() - { - var newPage = await Context.NewPageAsync(); - var closedTsc = new TaskCompletionSource(); - newPage.Close += (_, _) => closedTsc.SetResult(true); - await newPage.CloseAsync(); - await closedTsc.Task; - } - - [PlaywrightTest("page-basic.spec.ts", "should fire load when expected")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFireLoadWhenExpected() - { - await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.Load), - Page.GoToAsync("about:blank") - ); - } - - [PlaywrightTest("page-basic.spec.ts", "should fire domcontentloaded when expected")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFireDOMcontentloadedWhenExpected() - { - var task = Page.GoToAsync("about:blank"); - await Page.WaitForEventAsync(PageEvent.DOMContentLoaded); - await task; - } - - [PlaywrightTest("page-basic.spec.ts", "should set the page close state")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSetThePageCloseState() - { - var newPage = await Context.NewPageAsync(); - Assert.False(newPage.IsClosed); - await newPage.CloseAsync(); - Assert.True(newPage.IsClosed); - } - - [PlaywrightTest("page-basic.spec.ts", "should terminate network waiters")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTerminateNetworkWaiters() - { - var newPage = await Context.NewPageAsync(); - var exception = await Assert.ThrowsAsync(() => TaskUtils.WhenAll( - newPage.WaitForRequestAsync(TestConstants.EmptyPage), - newPage.WaitForResponseAsync(TestConstants.EmptyPage), - newPage.CloseAsync() - )); - for (int i = 0; i < 2; i++) - { - string message = exception.Message; - Assert.Contains("Page closed", message); - Assert.DoesNotContain("Timeout", message); - } - } - - [PlaywrightTest("page-basic.spec.ts", "should be callable twice")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeCallableTwice() - { - var newPage = await Context.NewPageAsync(); - await TaskUtils.WhenAll( - newPage.CloseAsync(), - newPage.CloseAsync()); - - await newPage.CloseAsync(); - } - - [PlaywrightTest("page-basic.spec.ts", "should not be visible in context.pages")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotBeVisibleInContextPages() - { - var newPage = await Context.NewPageAsync(); - Assert.Contains(newPage, Context.Pages); - await newPage.CloseAsync(); - Assert.DoesNotContain(newPage, Context.Pages); - } - } -} +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageBasicTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-basic.spec.ts", "should reject all promises when page is closed")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRejectAllPromisesWhenPageIsClosed() + { + var newPage = await Context.NewPageAsync(); + var exception = Assert.ThrowsAsync(() => TaskUtils.WhenAll( + newPage.EvaluateAsync("() => new Promise(r => { })"), + newPage.CloseAsync() + )); + Assert.That(exception, Is.InstanceOf()); + Assert.That(exception.Message, Does.Contain("Protocol error")); + } + + [PlaywrightTest("page-basic.spec.ts", "async stacks should work")] + [Test, Ignore("We don't need to test this in .NET")] + public async Task AsyncStacksShouldWork() + { + Server.SetRoute("/empty.html", context => + { + context.Abort(); // is this right? + return Task.CompletedTask; + }); + var exception = Assert.ThrowsAsync(() => Page.GoToAsync(TestConstants.EmptyPage)); + Assert.That(exception.StackTrace, Does.Contain(nameof(PageBasicTests))); + } + + [PlaywrightTest("page-basic.spec.ts", "Page.press should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PagePressShouldWork() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.PressAsync("textarea", "a"); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('textarea').value"), Is.EqualTo("a")); + } + + [PlaywrightTest("page-basic.spec.ts", "Frame.press should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task FramePressShouldWork() + { + await Page.SetContentAsync($""); + var frame = Page.Frames.Single(f => f.Name == "inner"); + await frame.PressAsync("textarea", "a"); + Assert.That(await frame.EvaluateAsync("() => document.querySelector('textarea').value"), Is.EqualTo("a")); + } + + [PlaywrightTest("page-basic.spec.ts", "page.frame should respect name")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnTheCorrectBrowserInstance() + { + await Page.SetContentAsync(""); + Assert.That(Page.Frames.FirstOrDefault(f => f.Name == "bogus"), Is.Null); + var frame = Page.Frames.FirstOrDefault(f => f.Name == "target"); + Assert.That(frame, Is.SameAs(Page.MainFrame.ChildFrames.First())); + } + + [PlaywrightTest("page-basic.spec.ts", "page.frame should respect url")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRespectUrl() + { + await Page.SetContentAsync($""); + Assert.That(Page.Frames.FirstOrDefault(f => f.Name == "bogus"), Is.Null); + var frame = Page.Frames.FirstOrDefault(f => f.Url.Contains("empty")); + Assert.That(frame, Is.SameAs(Page.MainFrame.ChildFrames.First())); + } + + [PlaywrightTest("page-basic.spec.ts", "should provide access to the opener page")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldProvideAccessToTheOpenerPage() + { + var (popupEvent, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.Popup), + Page.EvaluateAsync("() => window.open('about:blank')") + ); + var opener = await popupEvent.OpenerAsync(); + Assert.That(opener, Is.EqualTo(Page)); + } + + [PlaywrightTest("page-basic.spec.ts", "should return null if parent page has been closed")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnNullIfParentPageHasBeenClosed() + { + var (popupEvent, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.Popup), + Page.EvaluateAsync("() => window.open('about:blank')") + ); + await Page.CloseAsync(); + var opener = await popupEvent.OpenerAsync(); + Assert.That(opener, Is.Null); + } + + [PlaywrightTest("page-basic.spec.ts", "should return the page title")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnThePageTitle() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/title.html"); + Assert.That(await Page.TitleAsync(), Is.EqualTo("Woof-Woof")); + } + + [PlaywrightTest("page-basic.spec.ts", "page.url should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PageUrlShouldWork() + { + Assert.That(Page.Url, Is.EqualTo("about:blank")); + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(Page.Url, Is.EqualTo(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-basic.spec.ts", "should include hashes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldIncludeHashes() + { + await Page.GoToAsync(TestConstants.EmptyPage + "#hash"); + Assert.That(Page.Url, Is.EqualTo(TestConstants.EmptyPage + "#hash")); + await Page.EvaluateAsync("() => window.location.hash = 'dynamic'"); + Assert.That(Page.Url, Is.EqualTo(TestConstants.EmptyPage + "#dynamic")); + } + + [PlaywrightTest("page-basic.spec.ts", "should fail with error upon disconnect")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWithErrorUponDisconnect() + { + var task = Page.WaitForEventAsync(PageEvent.Download); + await Page.CloseAsync(); + var exception = Assert.CatchAsync(() => task); + Assert.That(exception.Message, Does.Contain("Page closed")); + } + + [PlaywrightTest("page-basic.spec.ts", "should have sane user agent")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHaveASaneUserAgent() + { + string userAgent = await Page.EvaluateAsync("() => navigator.userAgent"); + var regex = new Regex("[()]"); + string[] parts = Regex.Split(userAgent, "[()]").Select(t => t.Trim()).ToArray(); + + Assert.That(parts[0], Is.EqualTo("Mozilla/5.0")); + + if (TestConstants.IsFirefox) + { + string[] engineBrowser = parts[2].Split(' '); + Assert.That(engineBrowser[0], Does.StartWith("Gecko")); + Assert.That(engineBrowser[1], Does.StartWith("Firefox")); + } + else + { + Assert.That(parts[2], Does.StartWith("AppleWebKit/")); + Assert.That(parts[3], Is.EqualTo("KHTML, like Gecko")); + string[] engineBrowser = parts[4].Split(' '); + Assert.That(engineBrowser[1], Does.StartWith("Safari/")); + + if (TestConstants.IsChromium) + { + Assert.That(engineBrowser[0], Does.Contain("Chrome/")); + } + else + { + Assert.That(engineBrowser[0], Does.StartWith("Version")); + } + } + } + + [PlaywrightTest("page-basic.spec.ts", "should work with window.close")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithWindowClose() + { + var newPageTask = Page.WaitForEventAsync(PageEvent.Popup); + await Page.EvaluateAsync("() => window['newPage'] = window.open('about:blank')"); + var newPage = await newPageTask; + var closedTsc = new TaskCompletionSource(); + newPage.Close += (_, _) => closedTsc.SetResult(true); + await Page.EvaluateAsync("() => window['newPage'].close()"); + await closedTsc.Task; + } + + [PlaywrightTest("page-basic.spec.ts", "should work with page.close")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithPageClose() + { + var newPage = await Context.NewPageAsync(); + var closedTsc = new TaskCompletionSource(); + newPage.Close += (_, _) => closedTsc.SetResult(true); + await newPage.CloseAsync(); + await closedTsc.Task; + } + + [PlaywrightTest("page-basic.spec.ts", "should fire load when expected")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFireLoadWhenExpected() + { + await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.Load), + Page.GoToAsync("about:blank") + ); + } + + [PlaywrightTest("page-basic.spec.ts", "should fire domcontentloaded when expected")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFireDOMcontentloadedWhenExpected() + { + var task = Page.GoToAsync("about:blank"); + await Page.WaitForEventAsync(PageEvent.DOMContentLoaded); + await task; + } + + [PlaywrightTest("page-basic.spec.ts", "should set the page close state")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSetThePageCloseState() + { + var newPage = await Context.NewPageAsync(); + Assert.That(newPage.IsClosed, Is.False); + await newPage.CloseAsync(); + Assert.That(newPage.IsClosed, Is.True); + } + + [PlaywrightTest("page-basic.spec.ts", "should terminate network waiters")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTerminateNetworkWaiters() + { + var newPage = await Context.NewPageAsync(); + var exception = Assert.ThrowsAsync(() => TaskUtils.WhenAll( + newPage.WaitForRequestAsync(TestConstants.EmptyPage), + newPage.WaitForResponseAsync(TestConstants.EmptyPage), + newPage.CloseAsync() + )); + for (int i = 0; i < 2; i++) + { + string message = exception.Message; + Assert.That(message, Does.Contain("Page closed")); + Assert.That(message, Does.Not.Contain("Timeout")); + } + } + + [PlaywrightTest("page-basic.spec.ts", "should be callable twice")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeCallableTwice() + { + var newPage = await Context.NewPageAsync(); + await TaskUtils.WhenAll( + newPage.CloseAsync(), + newPage.CloseAsync()); + + await newPage.CloseAsync(); + } + + [PlaywrightTest("page-basic.spec.ts", "should not be visible in context.pages")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotBeVisibleInContextPages() + { + var newPage = await Context.NewPageAsync(); + Assert.That(Context.Pages, Does.Contain(newPage)); + await newPage.CloseAsync(); + Assert.That(Context.Pages, Does.Not.Contain(newPage)); + } + } +} diff --git a/src/Playwright.Tests/PageCheckTests.cs b/src/PlaywrightSharp.Tests/PageCheckTests.cs similarity index 65% rename from src/Playwright.Tests/PageCheckTests.cs rename to src/PlaywrightSharp.Tests/PageCheckTests.cs index e44dbd03f2..8417c2110f 100644 --- a/src/Playwright.Tests/PageCheckTests.cs +++ b/src/PlaywrightSharp.Tests/PageCheckTests.cs @@ -1,96 +1,89 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageCheckTests : PlaywrightSharpPageBaseTest - { - /// - public PageCheckTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-check.spec.ts", "should check the box")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCheckTheBox() - { - await Page.SetContentAsync(""); - await Page.CheckAsync("input"); - Assert.True(await Page.EvaluateAsync("checkbox.checked")); - } - - [PlaywrightTest("page-check.spec.ts", "should not check the checked box")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotCheckTheCheckedBox() - { - await Page.SetContentAsync(""); - await Page.CheckAsync("input"); - Assert.True(await Page.EvaluateAsync("checkbox.checked")); - } - - [PlaywrightTest("page-check.spec.ts", "should uncheck the box")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldUncheckTheBox() - { - await Page.SetContentAsync(""); - await Page.UncheckAsync("input"); - Assert.False(await Page.EvaluateAsync("checkbox.checked")); - } - - [PlaywrightTest("page-check.spec.ts", "should check the box by label")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCheckTheBoxByLabel() - { - await Page.SetContentAsync(""); - await Page.CheckAsync("label"); - Assert.True(await Page.EvaluateAsync("checkbox.checked")); - } - - [PlaywrightTest("page-check.spec.ts", "should check the box outside label")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCheckTheBoxOutsideLabel() - { - await Page.SetContentAsync("
"); - await Page.CheckAsync("label"); - Assert.True(await Page.EvaluateAsync("checkbox.checked")); - } - - [PlaywrightTest("page-check.spec.ts", "should check the box inside label w/o id")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCheckTheBoxInsideLabelWoId() - { - await Page.SetContentAsync(""); - await Page.CheckAsync("label"); - Assert.True(await Page.EvaluateAsync("checkbox.checked")); - } - - [PlaywrightTest("page-check.spec.ts", "should check radio")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCheckRadio() - { - await Page.SetContentAsync(@" - one - two - three"); - await Page.CheckAsync("#two"); - Assert.True(await Page.EvaluateAsync("two.checked")); - } - - [PlaywrightTest("page-check.spec.ts", "should check the box by aria role")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCheckTheBoxByAriaRole() - { - await Page.SetContentAsync(@" - - "); - await Page.CheckAsync("div"); - Assert.Equal("true", await Page.EvaluateAsync("checkbox.getAttribute('aria-checked')")); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageCheckTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-check.spec.ts", "should check the box")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCheckTheBox() + { + await Page.SetContentAsync(""); + await Page.CheckAsync("input"); + Assert.That(await Page.EvaluateAsync("checkbox.checked"), Is.True); + } + + [PlaywrightTest("page-check.spec.ts", "should not check the checked box")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotCheckTheCheckedBox() + { + await Page.SetContentAsync(""); + await Page.CheckAsync("input"); + Assert.That(await Page.EvaluateAsync("checkbox.checked"), Is.True); + } + + [PlaywrightTest("page-check.spec.ts", "should uncheck the box")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldUncheckTheBox() + { + await Page.SetContentAsync(""); + await Page.UncheckAsync("input"); + Assert.That(await Page.EvaluateAsync("checkbox.checked"), Is.False); + } + + [PlaywrightTest("page-check.spec.ts", "should check the box by label")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCheckTheBoxByLabel() + { + await Page.SetContentAsync(""); + await Page.CheckAsync("label"); + Assert.That(await Page.EvaluateAsync("checkbox.checked"), Is.True); + } + + [PlaywrightTest("page-check.spec.ts", "should check the box outside label")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCheckTheBoxOutsideLabel() + { + await Page.SetContentAsync("
"); + await Page.CheckAsync("label"); + Assert.That(await Page.EvaluateAsync("checkbox.checked"), Is.True); + } + + [PlaywrightTest("page-check.spec.ts", "should check the box inside label w/o id")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCheckTheBoxInsideLabelWoId() + { + await Page.SetContentAsync(""); + await Page.CheckAsync("label"); + Assert.That(await Page.EvaluateAsync("checkbox.checked"), Is.True); + } + + [PlaywrightTest("page-check.spec.ts", "should check radio")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCheckRadio() + { + await Page.SetContentAsync(@" + one + two + three"); + await Page.CheckAsync("#two"); + Assert.That(await Page.EvaluateAsync("two.checked"), Is.True); + } + + [PlaywrightTest("page-check.spec.ts", "should check the box by aria role")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCheckTheBoxByAriaRole() + { + await Page.SetContentAsync(@" + + "); + await Page.CheckAsync("div"); + Assert.That(await Page.EvaluateAsync("checkbox.getAttribute('aria-checked')"), Is.EqualTo("true")); + } + } +} diff --git a/src/Playwright.Tests/PageClickReactTests.cs b/src/PlaywrightSharp.Tests/PageClickReactTests.cs similarity index 68% rename from src/Playwright.Tests/PageClickReactTests.cs rename to src/PlaywrightSharp.Tests/PageClickReactTests.cs index 0d5a40709e..dc84826680 100644 --- a/src/Playwright.Tests/PageClickReactTests.cs +++ b/src/PlaywrightSharp.Tests/PageClickReactTests.cs @@ -1,88 +1,81 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageClickReactTests : PlaywrightSharpPageBaseTest - { - /// - public PageClickReactTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-click-react.spec.ts", "should retarget when element is recycled during hit testing")] - [Fact(Skip = " Skip USES_HOOKS")] - public void ShouldRetargetWhenElementIsRecycledDuringHitTesting() - { - } - - [PlaywrightTest("page-click-react.spec.ts", "should report that selector does not match anymore")] - [Fact(Skip = " Skip USES_HOOKS")] - public void ShouldReportThatSelectorDoesNotMatchAnymore() - { - } - - [PlaywrightTest("page-click-react.spec.ts", "should retarget when element is recycled before enabled check")] - [Fact(Skip = " Skip USES_HOOKS")] - public void ShouldRetargetWhenElementIsRecycledBeforeEnabledCheck() - { - } - - [PlaywrightTest("page-click-react.spec.ts", "should not retarget the handle when element is recycled")] - [Fact(Skip = " Skip USES_HOOKS")] - public void ShouldNotRetargetTheHandleWhenElementIsRecycled() - { - } - - [PlaywrightTest("page-click-react.spec.ts", "should timeout when click opens alert")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTimeoutWhenClickOpensAlert() - { - var dialogTask = Page.WaitForEventAsync(PageEvent.Dialog); - - await Page.SetContentAsync("
Click me
"); - - var exception = await Assert.ThrowsAsync(() => Page.ClickAsync("div", timeout: 3000)); - Assert.Contains("Timeout 3000ms exceeded", exception.Message); - var dialog = await dialogTask; - await dialog.DismissAsync(); - } - - [PlaywrightTest("page-click-react.spec.ts", "should not retarget when element changes on hover")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotRetargetWhenElementChangesOnHover() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/react.html"); - await Page.EvaluateAsync(@"() => { - renderComponent(e('div', {}, [e(MyButton, { name: 'button1', renameOnHover: true }), e(MyButton, { name: 'button2' })] )); - }"); - - await Page.ClickAsync("text=button1"); - Assert.True(await Page.EvaluateAsync("window.button1")); - Assert.Null(await Page.EvaluateAsync("window.button2")); - } - - [PlaywrightTest("page-click-react.spec.ts", "should not retarget when element is recycled on hover")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotRetargetWhenElementIsRecycledOnHover() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/react.html"); - await Page.EvaluateAsync(@"() => { - function shuffle() { - renderComponent(e('div', {}, [e(MyButton, { name: 'button2' }), e(MyButton, { name: 'button1' })] )); - } - renderComponent(e('div', {}, [e(MyButton, { name: 'button1', onHover: shuffle }), e(MyButton, { name: 'button2' })] )); - }"); - - await Page.ClickAsync("text=button1"); - Assert.Null(await Page.EvaluateAsync("window.button1")); - Assert.True(await Page.EvaluateAsync("window.button2")); - } - - } -} +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageClickReactTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-click-react.spec.ts", "should retarget when element is recycled during hit testing")] + [Test, Ignore(" Skip USES_HOOKS")] + public void ShouldRetargetWhenElementIsRecycledDuringHitTesting() + { + } + + [PlaywrightTest("page-click-react.spec.ts", "should report that selector does not match anymore")] + [Test, Ignore(" Skip USES_HOOKS")] + public void ShouldReportThatSelectorDoesNotMatchAnymore() + { + } + + [PlaywrightTest("page-click-react.spec.ts", "should retarget when element is recycled before enabled check")] + [Test, Ignore(" Skip USES_HOOKS")] + public void ShouldRetargetWhenElementIsRecycledBeforeEnabledCheck() + { + } + + [PlaywrightTest("page-click-react.spec.ts", "should not retarget the handle when element is recycled")] + [Test, Ignore(" Skip USES_HOOKS")] + public void ShouldNotRetargetTheHandleWhenElementIsRecycled() + { + } + + [PlaywrightTest("page-click-react.spec.ts", "should timeout when click opens alert")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTimeoutWhenClickOpensAlert() + { + var dialogTask = Page.WaitForEventAsync(PageEvent.Dialog); + + await Page.SetContentAsync("
Click me
"); + + var exception = Assert.ThrowsAsync(() => Page.ClickAsync("div", timeout: 3000)); + Assert.That(exception.Message, Does.Contain("Timeout 3000ms exceeded")); + var dialog = await dialogTask; + await dialog.DismissAsync(); + } + + [PlaywrightTest("page-click-react.spec.ts", "should not retarget when element changes on hover")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotRetargetWhenElementChangesOnHover() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/react.html"); + await Page.EvaluateAsync(@"() => { + renderComponent(e('div', {}, [e(MyButton, { name: 'button1', renameOnHover: true }), e(MyButton, { name: 'button2' })] )); + }"); + + await Page.ClickAsync("text=button1"); + Assert.That(await Page.EvaluateAsync("window.button1"), Is.True); + Assert.That(await Page.EvaluateAsync("window.button2"), Is.Null); + } + + [PlaywrightTest("page-click-react.spec.ts", "should not retarget when element is recycled on hover")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotRetargetWhenElementIsRecycledOnHover() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/react.html"); + await Page.EvaluateAsync(@"() => { + function shuffle() { + renderComponent(e('div', {}, [e(MyButton, { name: 'button2' }), e(MyButton, { name: 'button1' })] )); + } + renderComponent(e('div', {}, [e(MyButton, { name: 'button1', onHover: shuffle }), e(MyButton, { name: 'button2' })] )); + }"); + + await Page.ClickAsync("text=button1"); + Assert.That(await Page.EvaluateAsync("window.button1"), Is.Null); + Assert.That(await Page.EvaluateAsync("window.button2"), Is.True); + } + + } +} diff --git a/src/Playwright.Tests/PageClickTests.cs b/src/PlaywrightSharp.Tests/PageClickTests.cs similarity index 70% rename from src/Playwright.Tests/PageClickTests.cs rename to src/PlaywrightSharp.Tests/PageClickTests.cs index ca9655235a..58dc3a712a 100644 --- a/src/Playwright.Tests/PageClickTests.cs +++ b/src/PlaywrightSharp.Tests/PageClickTests.cs @@ -1,918 +1,911 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageClickTests : PlaywrightSharpPageBaseTest - { - /// - public PageClickTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-click.spec.ts", "should click the button")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickTheButton() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.ClickAsync("button"); - Assert.Equal("Clicked", await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-click.spec.ts", "should click svg")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickSvg() - { - await Page.SetContentAsync($@" - - - - "); - await Page.ClickAsync("circle"); - Assert.Equal(42, await Page.EvaluateAsync("() => window.__CLICKED")); - } - - [PlaywrightTest("page-click.spec.ts", "should click svg")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickTheButtonIfWindowNodeIsRemoved() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvaluateAsync("delete window.Node"); - await Page.ClickAsync("button"); - Assert.Equal("Clicked", await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-click.spec.ts", "should click on a span with an inline element inside")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickOnASpanWithAnInlineElementInside() - { - await Page.SetContentAsync($@" - - - "); - await Page.ClickAsync("span"); - Assert.Equal(42, await Page.EvaluateAsync("() => window.CLICKED")); - } - - [PlaywrightTest("page-click.spec.ts", "should not throw UnhandledPromiseRejection when page closes")] - [Fact(Skip = "We don't need to test this race condition")] - public void ShouldGracefullyFailWhenPageCloses() - { - } - - [PlaywrightTest("page-click.spec.ts", "should click the button after navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickTheButtonAfterNavigation() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.ClickAsync("button"); - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.ClickAsync("button"); - Assert.Equal("Clicked", await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-click.spec.ts", "should click the button after a cross origin navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickTheButtonAfterACrossOriginNavigation() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.ClickAsync("button"); - await Page.GoToAsync(TestConstants.CrossProcessHttpPrefix + "/input/button.html"); - await Page.ClickAsync("button"); - Assert.Equal("Clicked", await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-click.spec.ts", "should click with disabled javascript")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickWithDisabledJavascript() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions { JavaScriptEnabled = false }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/wrappedlink.html"); - await TaskUtils.WhenAll( - page.ClickAsync("a"), - page.WaitForNavigationAsync() - ); - Assert.Equal(TestConstants.ServerUrl + "/wrappedlink.html#clicked", page.Url); - } - - [PlaywrightTest("page-click.spec.ts", "should click when one of inline box children is outside of viewport")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickWhenOneOfInlineBoxChildrenIsOutsideOfViewport() - { - await Page.SetContentAsync($@" - - woofdoggo - "); - - await Page.ClickAsync("span"); - Assert.Equal(42, await Page.EvaluateAsync("() => window.CLICKED")); - } - - [PlaywrightTest("page-click.spec.ts", "should select the text by triple clicking")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectTheTextByTripleClicking() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - const string text = "This is the text that we are going to try to select. Let's see how it goes."; - await Page.FillAsync("textarea", text); - await Page.ClickAsync("textarea", clickCount: 3); - Assert.Equal(text, await Page.EvaluateAsync(@"() => { - const textarea = document.querySelector('textarea'); - return textarea.value.substring(textarea.selectionStart, textarea.selectionEnd); - }")); - } - - [PlaywrightTest("page-click.spec.ts", "should click offscreen buttons")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickOffscreenButtons() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/offscreenbuttons.html"); - var messages = new List(); - Page.Console += (_, e) => messages.Add(e.Text); - - for (int i = 0; i < 11; ++i) - { - // We might have scrolled to click a button - reset to (0, 0). - await Page.EvaluateAsync("() => window.scrollTo(0, 0)"); - await Page.ClickAsync($"#btn{i}"); - } - Assert.Equal(new List - { - "button #0 clicked", - "button #1 clicked", - "button #2 clicked", - "button #3 clicked", - "button #4 clicked", - "button #5 clicked", - "button #6 clicked", - "button #7 clicked", - "button #8 clicked", - "button #9 clicked", - "button #10 clicked" - }, messages); - } - - [PlaywrightTest("page-click.spec.ts", "should waitFor visible when already visible")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForVisibleWhenAlreadyVisible() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.ClickAsync("button"); - Assert.Equal("Clicked", await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-click.spec.ts", "should not wait with force")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotWaitWithForce() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvalOnSelectorAsync("button", "b => b.style.display = 'none'"); - - var exception = await Assert.ThrowsAsync(() - => Page.ClickAsync("button", force: true)); - - Assert.Contains("Element is not visible", exception.Message); - Assert.Equal("Was not clicked", await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-click.spec.ts", "should waitFor display:none to be gone")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForDisplayNoneToBeGone() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvalOnSelectorAsync("button", "b => b.style.display = 'none'"); - var clickTask = Page.ClickAsync("button", timeout: 0); - - await GiveItAChanceToClick(Page); - - Assert.False(clickTask.IsCompleted); - Assert.Equal("Was not clicked", await Page.EvaluateAsync("result")); - - await Page.EvalOnSelectorAsync("button", "b => b.style.display = 'block'"); - await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); - - Assert.Equal("Clicked", await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-click.spec.ts", "should waitFor visibility:hidden to be gone")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForVisibilityhiddenToBeGone() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvalOnSelectorAsync("button", "b => b.style.visibility = 'hidden'"); - var clickTask = Page.ClickAsync("button", timeout: 0); - - await GiveItAChanceToClick(Page); - - Assert.False(clickTask.IsCompleted); - Assert.Equal("Was not clicked", await Page.EvaluateAsync("result")); - - await Page.EvalOnSelectorAsync("button", "b => b.style.visibility = 'visible'"); - await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); - - Assert.Equal("Clicked", await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-click.spec.ts", "should waitFor visible when parent is hidden")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForVisibleWhenParentIsHidden() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvalOnSelectorAsync("button", "b => b.parentElement.style.display = 'none'"); - var clickTask = Page.ClickAsync("button", timeout: 0); - - await GiveItAChanceToClick(Page); - - Assert.False(clickTask.IsCompleted); - Assert.Equal("Was not clicked", await Page.EvaluateAsync("result")); - - await Page.EvalOnSelectorAsync("button", "b => b.parentElement.style.display = 'block'"); - await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); - - Assert.Equal("Clicked", await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-click.spec.ts", "should click wrapped links")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickWrappedLinks() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/wrappedlink.html"); - await Page.ClickAsync("a"); - Assert.True(await Page.EvaluateAsync("window.__clicked")); - } - - [PlaywrightTest("page-click.spec.ts", "should click on checkbox input and toggle")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickOnCheckboxInputAndToggle() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/checkbox.html"); - Assert.Null(await Page.EvaluateAsync("result.check")); - await Page.ClickAsync("input#agree"); - Assert.True(await Page.EvaluateAsync("result.check")); - Assert.Equal(new[] { - "mouseover", - "mouseenter", - "mousemove", - "mousedown", - "mouseup", - "click", - "input", - "change" - }, await Page.EvaluateAsync("result.events")); - await Page.ClickAsync("input#agree"); - Assert.False(await Page.EvaluateAsync("result.check")); - } - - [PlaywrightTest("page-click.spec.ts", "should click on checkbox label and toggle")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickOnCheckboxLabelAndToggle() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/checkbox.html"); - Assert.Null(await Page.EvaluateAsync("result.check")); - await Page.ClickAsync("label[for=\"agree\"]"); - Assert.True(await Page.EvaluateAsync("result.check")); - Assert.Equal(new[] { - "click", - "input", - "change" - }, await Page.EvaluateAsync("result.events")); - await Page.ClickAsync("label[for=\"agree\"]"); - Assert.False(await Page.EvaluateAsync("result.check")); - } - - [PlaywrightTest("page-click.spec.ts", "should not hang with touch-enabled viewports")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotHangWithTouchEnabledViewports() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = TestConstants.iPhone6.Viewport, - HasTouch = TestConstants.iPhone6.HasTouch, - }); - - var page = await context.NewPageAsync(); - await page.Mouse.DownAsync(); - await page.Mouse.MoveAsync(100, 10); - await page.Mouse.UpAsync(); - } - - [PlaywrightTest("page-click.spec.ts", "should scroll and click the button")] - [Fact(Skip = "Flacky")] - public async Task ShouldScrollAndClickTheButton() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); - await Page.ClickAsync("#button-5"); - Assert.Equal("clicked", await Page.EvaluateAsync("document.querySelector(\"#button-5\").textContent")); - await Page.ClickAsync("#button-80"); - Assert.Equal("clicked", await Page.EvaluateAsync("document.querySelector(\"#button-80\").textContent")); - } - - [PlaywrightTest("page-click.spec.ts", "should double click the button")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDoubleClickTheButton() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvaluateAsync(@"{ - window.double = false; - const button = document.querySelector('button'); - button.addEventListener('dblclick', event => { - window.double = true; - }); - }"); - var button = await Page.QuerySelectorAsync("button"); - await button.DblClickAsync(); - Assert.True(await Page.EvaluateAsync("double")); - Assert.Equal("Clicked", await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-click.spec.ts", "should click a partially obscured button")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickAPartiallyObscuredButton() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvaluateAsync(@"{ - const button = document.querySelector('button'); - button.textContent = 'Some really long text that will go offscreen'; - - button.style.position = 'absolute'; - button.style.left = '368px'; - }"); - await Page.ClickAsync("button"); - Assert.Equal("Clicked", await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-click.spec.ts", "should click a rotated button")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickARotatedButton() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/rotatedButton.html"); - await Page.ClickAsync("button"); - Assert.Equal("Clicked", await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-click.spec.ts", "should fire contextmenu event on right click")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFireContextmenuEventOnRightClick() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); - await Page.ClickAsync("#button-8", button: MouseButton.Right); - Assert.Equal("context menu", await Page.EvaluateAsync("document.querySelector('#button-8').textContent")); - } - - [PlaywrightTest("page-click.spec.ts", "should click links which cause navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickLinksWhichCauseNavigation() - { - await Page.SetContentAsync($"empty.html"); - // This await should not hang. - await Page.ClickAsync("a"); - } - - [PlaywrightTest("page-click.spec.ts", "should click the button inside an iframe")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickTheButtonInsideAnIframe() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync("
spacer
"); - await FrameUtils.AttachFrameAsync(Page, "button-test", TestConstants.ServerUrl + "/input/button.html"); - var frame = Page.FirstChildFrame(); - var button = await frame.QuerySelectorAsync("button"); - await button.ClickAsync(); - Assert.Equal("Clicked", await frame.EvaluateAsync("window.result")); - } - - [PlaywrightTest("page-click.spec.ts", "should click the button with fixed position inside an iframe")] - [SkipBrowserAndPlatformFact(skipChromium: true, skipWebkit: true)] - public async Task ShouldClickTheButtonWithFixedPositionInsideAnIframe() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetViewportSizeAsync(500, 500); - await Page.SetContentAsync("
spacer
"); - await FrameUtils.AttachFrameAsync(Page, "button-test", TestConstants.ServerUrl + "/input/button.html"); - var frame = Page.FirstChildFrame(); - await frame.EvalOnSelectorAsync("button", "button => button.style.setProperty('position', 'fixed')"); - await frame.ClickAsync("button"); - Assert.Equal("Clicked", await frame.EvaluateAsync("window.result")); - } - - [PlaywrightTest("page-click.spec.ts", "should click the button with deviceScaleFactor set")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickTheButtonWithDeviceScaleFactorSet() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 400, - Height = 400, - }, - DeviceScaleFactor = 5, - }); - - var page = await context.NewPageAsync(); - Assert.Equal(5, await page.EvaluateAsync("window.devicePixelRatio")); - await page.SetContentAsync("
spacer
"); - await FrameUtils.AttachFrameAsync(page, "button-test", TestConstants.ServerUrl + "/input/button.html"); - var frame = page.FirstChildFrame(); - var button = await frame.QuerySelectorAsync("button"); - await button.ClickAsync(); - Assert.Equal("Clicked", await frame.EvaluateAsync("window.result")); - } - - [PlaywrightTest("page-click.spec.ts", "should click the button with px border with relative point")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickTheButtonWithPxBorderWithRelativePoint() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvalOnSelectorAsync("button", "button => button.style.borderWidth = '8px'"); - await Page.ClickAsync("button", position: new Position { X = 20, Y = 10 }); - Assert.Equal("Clicked", await Page.EvaluateAsync("window.result")); - // Safari reports border-relative offsetX/offsetY. - Assert.Equal(TestConstants.IsWebKit ? 20 + 8 : 20, await Page.EvaluateAsync("offsetX")); - Assert.Equal(TestConstants.IsWebKit ? 10 + 8 : 10, await Page.EvaluateAsync("offsetY")); - } - - [PlaywrightTest("page-click.spec.ts", "should click the button with em border with offset")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickTheButtonWithEmBorderWithOffset() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvalOnSelectorAsync("button", "button => button.style.borderWidth = '2em'"); - await Page.EvalOnSelectorAsync("button", "button => button.style.fontSize = '12px'"); - await Page.ClickAsync("button", position: new Position { X = 20, Y = 10 }); - Assert.Equal("Clicked", await Page.EvaluateAsync("window.result")); - // Safari reports border-relative offsetX/offsetY. - Assert.Equal(TestConstants.IsWebKit ? 12 * 2 + 20 : 20, await Page.EvaluateAsync("offsetX")); - Assert.Equal(TestConstants.IsWebKit ? 12 * 2 + 10 : 10, await Page.EvaluateAsync("offsetY")); - } - - [PlaywrightTest("page-click.spec.ts", "should click a very large button with offset")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickAVeryLargeButtonWithOffset() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvalOnSelectorAsync("button", "button => button.style.borderWidth = '8px'"); - await Page.EvalOnSelectorAsync("button", "button => button.style.height = button.style.width = '2000px'"); - await Page.ClickAsync("button", position: new Position { X = 1900, Y = 1910 }); - Assert.Equal("Clicked", await Page.EvaluateAsync("window.result")); - // Safari reports border-relative offsetX/offsetY. - Assert.Equal(TestConstants.IsWebKit ? 1900 + 8 : 1900, await Page.EvaluateAsync("offsetX")); - Assert.Equal(TestConstants.IsWebKit ? 1910 + 8 : 1910, await Page.EvaluateAsync("offsetY")); - } - - [PlaywrightTest("page-click.spec.ts", "should click a button in scrolling container with offset")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickAButtonInScrollingContainerWithOffset() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvalOnSelectorAsync("button", @"button => { - const container = document.createElement('div'); - container.style.overflow = 'auto'; - container.style.width = '200px'; - container.style.height = '200px'; - button.parentElement.insertBefore(container, button); - container.appendChild(button); - button.style.height = '2000px'; - button.style.width = '2000px'; - button.style.borderWidth = '8px'; - }"); - - await Page.ClickAsync("button", position: new Position { X = 1900, Y = 1910 }); - Assert.Equal("Clicked", await Page.EvaluateAsync("window.result")); - // Safari reports border-relative offsetX/offsetY. - Assert.Equal(TestConstants.IsWebKit ? 1900 + 8 : 1900, await Page.EvaluateAsync("offsetX")); - Assert.Equal(TestConstants.IsWebKit ? 1910 + 8 : 1910, await Page.EvaluateAsync("offsetY")); - } - - [PlaywrightTest("page-click.spec.ts", "should click the button with offset with page scale")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldClickTheButtonWithOffsetWithPageScale() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 400, - Height = 400, - }, - IsMobile = true, - }); - - var page = await context.NewPageAsync(); - - await page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await page.EvalOnSelectorAsync("button", @"button => { - button.style.borderWidth = '8px'; - document.body.style.margin = '0'; - }"); - - await page.ClickAsync("button", position: new Position { X = 20, Y = 10 }); - Assert.Equal("Clicked", await page.EvaluateAsync("window.result")); - - var point = TestConstants.Product switch - { - TestConstants.ChromiumProduct => new Point(27, 18), - TestConstants.WebkitProduct => new Point(29, 19), - _ => new Point(28, 18), - }; - - Assert.Equal(point.X, Convert.ToInt32(await page.EvaluateAsync("pageX"))); - Assert.Equal(point.Y, Convert.ToInt32(await page.EvaluateAsync("pageY"))); - } - - [PlaywrightTest("page-click.spec.ts", "should wait for stable position")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForStablePosition() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvalOnSelectorAsync("button", @"button => { - button.style.transition = 'margin 500ms linear 0s'; - button.style.marginLeft = '200px'; - button.style.borderWidth = '0'; - button.style.width = '200px'; - button.style.height = '20px'; - // Set display to 'block'- otherwise Firefox layouts with non-even - // values on Linux. - button.style.display = 'block'; - document.body.style.margin = '0'; - }"); - - await Page.ClickAsync("button"); - Assert.Equal("Clicked", await Page.EvaluateAsync("window.result")); - Assert.Equal(300, await Page.EvaluateAsync("pageX")); - Assert.Equal(10, await Page.EvaluateAsync("pageY")); - } - - [PlaywrightTest("page-click.spec.ts", "should wait for becoming hit target")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForBecomingHitTarget() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvalOnSelectorAsync("button", @"button => { - button.style.borderWidth = '0'; - button.style.width = '200px'; - button.style.height = '20px'; - document.body.style.margin = '0'; - document.body.style.position = 'relative'; - const flyOver = document.createElement('div'); - flyOver.className = 'flyover'; - flyOver.style.position = 'absolute'; - flyOver.style.width = '400px'; - flyOver.style.height = '20px'; - flyOver.style.left = '-200px'; - flyOver.style.top = '0'; - flyOver.style.background = 'red'; - document.body.appendChild(flyOver); - }"); - - var clickTask = Page.ClickAsync("button"); - Assert.False(clickTask.IsCompleted); - - await Page.EvalOnSelectorAsync(".flyover", "flyOver => flyOver.style.left = '0'"); - await GiveItAChanceToClick(Page); - Assert.False(clickTask.IsCompleted); - - await Page.EvalOnSelectorAsync(".flyover", "flyOver => flyOver.style.left = '200px'"); - await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); - Assert.Equal("Clicked", await Page.EvaluateAsync("window.result")); - } - - [PlaywrightTest("page-click.spec.ts", "should fail when obscured and not waiting for hit target")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWhenObscuredAndNotWaitingForHitTarget() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - var button = await Page.QuerySelectorAsync("button"); - await Page.EvalOnSelectorAsync("button", @"button => { - document.body.style.position = 'relative'; - const blocker = document.createElement('div'); - blocker.style.position = 'absolute'; - blocker.style.width = '400px'; - blocker.style.height = '20px'; - blocker.style.left = '0'; - blocker.style.top = '0'; - document.body.appendChild(blocker); - }"); - - await button.ClickAsync(force: true); - Assert.Equal("Was not clicked", await Page.EvaluateAsync("window.result")); - } - - [PlaywrightTest("page-click.spec.ts", "should wait for button to be enabled")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForButtonToBeEnabled() - { - await Page.SetContentAsync(""); - var clickTask = Page.ClickAsync("text=Click target"); - await GiveItAChanceToClick(Page); - Assert.Null(await Page.EvaluateAsync("window.__CLICKED")); - Assert.False(clickTask.IsCompleted); - await Page.EvaluateAsync("() => document.querySelector('button').removeAttribute('disabled')"); - await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); - Assert.True(await Page.EvaluateAsync("window.__CLICKED")); - } - - [PlaywrightTest("page-click.spec.ts", "should wait for input to be enabled")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForInputToBeEnabled() - { - await Page.SetContentAsync(""); - var clickTask = Page.ClickAsync("input"); - await GiveItAChanceToClick(Page); - Assert.Null(await Page.EvaluateAsync("window.__CLICKED")); - Assert.False(clickTask.IsCompleted); - await Page.EvaluateAsync("() => document.querySelector('input').removeAttribute('disabled')"); - await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); - Assert.True(await Page.EvaluateAsync("window.__CLICKED")); - } - - [PlaywrightTest("page-click.spec.ts", "should wait for select to be enabled")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForSelectToBeEnabled() - { - await Page.SetContentAsync(""); - var clickTask = Page.ClickAsync("select"); - await GiveItAChanceToClick(Page); - Assert.Null(await Page.EvaluateAsync("window.__CLICKED")); - Assert.False(clickTask.IsCompleted); - await Page.EvaluateAsync("() => document.querySelector('select').removeAttribute('disabled')"); - await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); - Assert.True(await Page.EvaluateAsync("window.__CLICKED")); - } - - [PlaywrightTest("page-click.spec.ts", "should click disabled div")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickDisabledDiv() - { - await Page.SetContentAsync("
Click target
"); - await Page.ClickAsync("text=Click target"); - Assert.True(await Page.EvaluateAsync("window.__CLICKED")); - } - - [PlaywrightTest("page-click.spec.ts", "should climb dom for inner label with pointer-events:none")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClimbDomForInnerLabelWithPointerEventsNone() - { - await Page.SetContentAsync(""); - await Page.ClickAsync("text=Click target"); - Assert.True(await Page.EvaluateAsync("window.__CLICKED")); - } - - [PlaywrightTest("page-click.spec.ts", "should climb up to [role=button]")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClimbUpToRoleButton() - { - await Page.SetContentAsync("
Click target
"); - await Page.ClickAsync("text=Click target"); - Assert.True(await Page.EvaluateAsync("window.__CLICKED")); - } - - [PlaywrightTest("page-click.spec.ts", "should wait for BUTTON to be clickable when it has pointer-events:none")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForButtonToBeClickableWhenItHasPointerEventsNone() - { - await Page.SetContentAsync(""); - var clickTask = Page.ClickAsync("text=Click target"); - await GiveItAChanceToClick(Page); - Assert.Null(await Page.EvaluateAsync("window.__CLICKED")); - Assert.False(clickTask.IsCompleted); - await Page.EvaluateAsync("() => document.querySelector('button').style.removeProperty('pointer-events')"); - await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); - Assert.True(await Page.EvaluateAsync("window.__CLICKED")); - } - - [PlaywrightTest("page-click.spec.ts", "should wait for LABEL to be clickable when it has pointer-events:none")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForLabelToBeClickableWhenItHasPointerEventsNone() - { - await Page.SetContentAsync(""); - var clickTask = Page.ClickAsync("text=Click target"); - - for (int i = 0; i < 5; ++i) - { - Assert.Null(await Page.EvaluateAsync("window.__CLICKED")); - } - - Assert.False(clickTask.IsCompleted); - await Page.EvaluateAsync("() => document.querySelector('label').style.removeProperty('pointer-events')"); - await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); - Assert.True(await Page.EvaluateAsync("window.__CLICKED")); - } - - [PlaywrightTest("page-click.spec.ts", "should update modifiers correctly")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldUpdateModifiersCorrectly() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.ClickAsync("button", modifiers: new[] { KeyboardModifier.Shift }); - Assert.True(await Page.EvaluateAsync("shiftKey")); - await Page.ClickAsync("button", modifiers: Array.Empty()); - Assert.False(await Page.EvaluateAsync("shiftKey")); - - await Page.Keyboard.DownAsync("Shift"); - - await Page.ClickAsync("button", modifiers: Array.Empty()); - Assert.False(await Page.EvaluateAsync("shiftKey")); - - await Page.ClickAsync("button"); - Assert.True(await Page.EvaluateAsync("shiftKey")); - - await Page.Keyboard.UpAsync("Shift"); - - await Page.ClickAsync("button"); - Assert.False(await Page.EvaluateAsync("shiftKey")); - } - - [PlaywrightTest("page-click.spec.ts", "should click an offscreen element when scroll-behavior is smooth")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickAnOffscreenElementWhenScrollBehaviorIsSmooth() - { - await Page.SetContentAsync(@$" -
- -
"); - - await Page.ClickAsync("button"); - Assert.True(await Page.EvaluateAsync("window.clicked")); - } - - [PlaywrightTest("page-click.spec.ts", "should report nice error when element is detached and force-clicked")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReportNiceErrorWhenElementIsDetachedAndForceClicked() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/animating-button.html"); - await Page.EvaluateAsync("() => addButton()"); - var handle = await Page.QuerySelectorAsync("button"); - await Page.EvaluateAsync("() => stopButton(true)"); - var clickTask = handle.ClickAsync(force: true); - var exception = await Assert.ThrowsAsync(() => clickTask); - Assert.Null(await Page.EvaluateAsync("window.clicked")); - Assert.Contains("Element is not attached to the DOM", exception.Message); - } - - [PlaywrightTest("page-click.spec.ts", "should fail when element detaches after animation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWhenElementDetachesAfterAnimation() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/animating-button.html"); - await Page.EvaluateAsync("() => addButton()"); - var handle = await Page.QuerySelectorAsync("button"); - var clickTask = handle.ClickAsync(); - await Page.EvaluateAsync("() => stopButton(true)"); - var exception = await Assert.ThrowsAsync(() => clickTask); - Assert.Null(await Page.EvaluateAsync("window.clicked")); - Assert.Contains("Element is not attached to the DOM", exception.Message); - } - - [PlaywrightTest("page-click.spec.ts", "should retry when element detaches after animation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRetryWhenElementDetachesAfterAnimation() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/animating-button.html"); - await Page.EvaluateAsync("() => addButton()"); - var clickTask = Page.ClickAsync("button"); - Assert.False(clickTask.IsCompleted); - Assert.Null(await Page.EvaluateAsync("window.clicked")); - await Page.EvaluateAsync("() => stopButton(true)"); - await Page.EvaluateAsync("() => addButton()"); - Assert.False(clickTask.IsCompleted); - Assert.Null(await Page.EvaluateAsync("window.clicked")); - await Page.EvaluateAsync("() => stopButton(true)"); - await Page.EvaluateAsync("() => addButton()"); - Assert.False(clickTask.IsCompleted); - Assert.Null(await Page.EvaluateAsync("window.clicked")); - await Page.EvaluateAsync("() => stopButton(false)"); - await clickTask; - Assert.True(await Page.EvaluateAsync("window.clicked")); - } - - [PlaywrightTest("page-click.spec.ts", "should retry when element is animating from outside the viewport")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRetryWhenElementIsAnimatingFromOutsideTheViewport() - { - await Page.SetContentAsync($@" - -
- -
"); - - var handle = await Page.QuerySelectorAsync("button"); - var clickTask = handle.ClickAsync(); - await handle.EvaluateAsync("button => button.className = 'animated'"); - await clickTask; - Assert.True(await Page.EvaluateAsync("window.clicked")); - } - - [PlaywrightTest("page-click.spec.ts", "should retry when element is animating from outside the viewport with force")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRetryWhenElementIsAnimatingFromOutsideTheViewportWithForce() - { - await Page.SetContentAsync($@" - -
- -
"); - - var handle = await Page.QuerySelectorAsync("button"); - var clickTask = handle.ClickAsync(force: true); - await handle.EvaluateAsync("button => button.className = 'animated'"); - var exception = await Assert.ThrowsAsync(() => clickTask); - Assert.Null(await Page.EvaluateAsync("window.clicked")); - Assert.Contains("Element is outside of the viewport", exception.Message); - } - - [PlaywrightTest("page-click.spec.ts", "should dispatch microtasks in order")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDispatchMicrotasksInOrder() - { - await Page.SetContentAsync($@" - - "); - - await Page.ClickAsync("button"); - Assert.Equal(1, await Page.EvaluateAsync("window.result")); - } - - [PlaywrightTest("page-click.spec.ts", "should click the button when window.innerWidth is corrupted")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClickTheButtonWhenWindowInnerWidthIsCorrupted() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.EvaluateAsync(@"() => window.innerWith = 0"); - - await Page.ClickAsync("button"); - Assert.Equal("Clicked", await Page.EvaluateAsync("result")); - } - - private async Task GiveItAChanceToClick(IPage page) - { - for (int i = 0; i < 5; i++) - { - await page.EvaluateAsync("() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f)))"); - } - } - } -} +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageClickTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-click.spec.ts", "should click the button")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickTheButton() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.ClickAsync("button"); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should click svg")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickSvg() + { + await Page.SetContentAsync($@" + + + + "); + await Page.ClickAsync("circle"); + Assert.That(await Page.EvaluateAsync("() => window.__CLICKED"), Is.EqualTo(42)); + } + + [PlaywrightTest("page-click.spec.ts", "should click svg")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickTheButtonIfWindowNodeIsRemoved() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvaluateAsync("delete window.Node"); + await Page.ClickAsync("button"); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should click on a span with an inline element inside")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickOnASpanWithAnInlineElementInside() + { + await Page.SetContentAsync($@" + + + "); + await Page.ClickAsync("span"); + Assert.That(await Page.EvaluateAsync("() => window.CLICKED"), Is.EqualTo(42)); + } + + [PlaywrightTest("page-click.spec.ts", "should not throw UnhandledPromiseRejection when page closes")] + [Test, Ignore("We don't need to test this race condition")] + public void ShouldGracefullyFailWhenPageCloses() + { + } + + [PlaywrightTest("page-click.spec.ts", "should click the button after navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickTheButtonAfterNavigation() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.ClickAsync("button"); + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.ClickAsync("button"); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should click the button after a cross origin navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickTheButtonAfterACrossOriginNavigation() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.ClickAsync("button"); + await Page.GoToAsync(TestConstants.CrossProcessHttpPrefix + "/input/button.html"); + await Page.ClickAsync("button"); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should click with disabled javascript")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickWithDisabledJavascript() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions { JavaScriptEnabled = false }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/wrappedlink.html"); + await TaskUtils.WhenAll( + page.ClickAsync("a"), + page.WaitForNavigationAsync() + ); + Assert.That(page.Url, Is.EqualTo(TestConstants.ServerUrl + "/wrappedlink.html#clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should click when one of inline box children is outside of viewport")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickWhenOneOfInlineBoxChildrenIsOutsideOfViewport() + { + await Page.SetContentAsync($@" + + woofdoggo + "); + + await Page.ClickAsync("span"); + Assert.That(await Page.EvaluateAsync("() => window.CLICKED"), Is.EqualTo(42)); + } + + [PlaywrightTest("page-click.spec.ts", "should select the text by triple clicking")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSelectTheTextByTripleClicking() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + const string text = "This is the text that we are going to try to select. Let's see how it goes."; + await Page.FillAsync("textarea", text); + await Page.ClickAsync("textarea", clickCount: 3); + Assert.That(await Page.EvaluateAsync(@"() => { + const textarea = document.querySelector('textarea'); + return textarea.value.substring(textarea.selectionStart, textarea.selectionEnd); + }"), Is.EqualTo(text)); + } + + [PlaywrightTest("page-click.spec.ts", "should click offscreen buttons")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickOffscreenButtons() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/offscreenbuttons.html"); + var messages = new List(); + Page.Console += (_, e) => messages.Add(e.Text); + + for (int i = 0; i < 11; ++i) + { + // We might have scrolled to click a button - reset to (0, 0). + await Page.EvaluateAsync("() => window.scrollTo(0, 0)"); + await Page.ClickAsync($"#btn{i}"); + } + Assert.That(messages, Is.EqualTo(new List + { + "button #0 clicked", + "button #1 clicked", + "button #2 clicked", + "button #3 clicked", + "button #4 clicked", + "button #5 clicked", + "button #6 clicked", + "button #7 clicked", + "button #8 clicked", + "button #9 clicked", + "button #10 clicked" + })); + } + + [PlaywrightTest("page-click.spec.ts", "should waitFor visible when already visible")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForVisibleWhenAlreadyVisible() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.ClickAsync("button"); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should not wait with force")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotWaitWithForce() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvalOnSelectorAsync("button", "b => b.style.display = 'none'"); + + var exception = Assert.ThrowsAsync(() + => Page.ClickAsync("button", force: true)); + + Assert.That(exception.Message, Does.Contain("Element is not visible")); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Was not clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should waitFor display:none to be gone")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForDisplayNoneToBeGone() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvalOnSelectorAsync("button", "b => b.style.display = 'none'"); + var clickTask = Page.ClickAsync("button", timeout: 0); + + await GiveItAChanceToClick(Page); + + Assert.That(clickTask.IsCompleted, Is.False); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Was not clicked")); + + await Page.EvalOnSelectorAsync("button", "b => b.style.display = 'block'"); + await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); + + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should waitFor visibility:hidden to be gone")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForVisibilityhiddenToBeGone() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvalOnSelectorAsync("button", "b => b.style.visibility = 'hidden'"); + var clickTask = Page.ClickAsync("button", timeout: 0); + + await GiveItAChanceToClick(Page); + + Assert.That(clickTask.IsCompleted, Is.False); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Was not clicked")); + + await Page.EvalOnSelectorAsync("button", "b => b.style.visibility = 'visible'"); + await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); + + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should waitFor visible when parent is hidden")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForVisibleWhenParentIsHidden() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvalOnSelectorAsync("button", "b => b.parentElement.style.display = 'none'"); + var clickTask = Page.ClickAsync("button", timeout: 0); + + await GiveItAChanceToClick(Page); + + Assert.That(clickTask.IsCompleted, Is.False); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Was not clicked")); + + await Page.EvalOnSelectorAsync("button", "b => b.parentElement.style.display = 'block'"); + await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); + + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should click wrapped links")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickWrappedLinks() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/wrappedlink.html"); + await Page.ClickAsync("a"); + Assert.That(await Page.EvaluateAsync("window.__clicked"), Is.True); + } + + [PlaywrightTest("page-click.spec.ts", "should click on checkbox input and toggle")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickOnCheckboxInputAndToggle() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/checkbox.html"); + Assert.That(await Page.EvaluateAsync("result.check"), Is.Null); + await Page.ClickAsync("input#agree"); + Assert.That(await Page.EvaluateAsync("result.check"), Is.True); + Assert.That(await Page.EvaluateAsync("result.events"), Is.EqualTo(new[] { + "mouseover", + "mouseenter", + "mousemove", + "mousedown", + "mouseup", + "click", + "input", + "change" + })); + await Page.ClickAsync("input#agree"); + Assert.That(await Page.EvaluateAsync("result.check"), Is.False); + } + + [PlaywrightTest("page-click.spec.ts", "should click on checkbox label and toggle")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickOnCheckboxLabelAndToggle() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/checkbox.html"); + Assert.That(await Page.EvaluateAsync("result.check"), Is.Null); + await Page.ClickAsync("label[for=\"agree\"]"); + Assert.That(await Page.EvaluateAsync("result.check"), Is.True); + Assert.That(await Page.EvaluateAsync("result.events"), Is.EqualTo(new[] { + "click", + "input", + "change" + })); + await Page.ClickAsync("label[for=\"agree\"]"); + Assert.That(await Page.EvaluateAsync("result.check"), Is.False); + } + + [PlaywrightTest("page-click.spec.ts", "should not hang with touch-enabled viewports")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotHangWithTouchEnabledViewports() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = TestConstants.iPhone6.Viewport, + HasTouch = TestConstants.iPhone6.HasTouch, + }); + + var page = await context.NewPageAsync(); + await page.Mouse.DownAsync(); + await page.Mouse.MoveAsync(100, 10); + await page.Mouse.UpAsync(); + } + + [PlaywrightTest("page-click.spec.ts", "should scroll and click the button")] + [Test, Ignore("Flacky")] + public async Task ShouldScrollAndClickTheButton() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); + await Page.ClickAsync("#button-5"); + Assert.That(await Page.EvaluateAsync("document.querySelector(\"#button-5\").textContent"), Is.EqualTo("clicked")); + await Page.ClickAsync("#button-80"); + Assert.That(await Page.EvaluateAsync("document.querySelector(\"#button-80\").textContent"), Is.EqualTo("clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should double click the button")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDoubleClickTheButton() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvaluateAsync(@"{ + window.double = false; + const button = document.querySelector('button'); + button.addEventListener('dblclick', event => { + window.double = true; + }); + }"); + var button = await Page.QuerySelectorAsync("button"); + await button.DblClickAsync(); + Assert.That(await Page.EvaluateAsync("double"), Is.True); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should click a partially obscured button")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickAPartiallyObscuredButton() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvaluateAsync(@"{ + const button = document.querySelector('button'); + button.textContent = 'Some really long text that will go offscreen'; + + button.style.position = 'absolute'; + button.style.left = '368px'; + }"); + await Page.ClickAsync("button"); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should click a rotated button")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickARotatedButton() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/rotatedButton.html"); + await Page.ClickAsync("button"); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should fire contextmenu event on right click")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFireContextmenuEventOnRightClick() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); + await Page.ClickAsync("#button-8", button: MouseButton.Right); + Assert.That(await Page.EvaluateAsync("document.querySelector('#button-8').textContent"), Is.EqualTo("context menu")); + } + + [PlaywrightTest("page-click.spec.ts", "should click links which cause navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickLinksWhichCauseNavigation() + { + await Page.SetContentAsync($"empty.html"); + // This await should not hang. + await Page.ClickAsync("a"); + } + + [PlaywrightTest("page-click.spec.ts", "should click the button inside an iframe")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickTheButtonInsideAnIframe() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.SetContentAsync("
spacer
"); + await FrameUtils.AttachFrameAsync(Page, "button-test", TestConstants.ServerUrl + "/input/button.html"); + var frame = Page.FirstChildFrame(); + var button = await frame.QuerySelectorAsync("button"); + await button.ClickAsync(); + Assert.That(await frame.EvaluateAsync("window.result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should click the button with fixed position inside an iframe")] + [SkipBrowserAndPlatformFact(skipChromium: true, skipWebkit: true)] + public async Task ShouldClickTheButtonWithFixedPositionInsideAnIframe() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.SetViewportSizeAsync(500, 500); + await Page.SetContentAsync("
spacer
"); + await FrameUtils.AttachFrameAsync(Page, "button-test", TestConstants.ServerUrl + "/input/button.html"); + var frame = Page.FirstChildFrame(); + await frame.EvalOnSelectorAsync("button", "button => button.style.setProperty('position', 'fixed')"); + await frame.ClickAsync("button"); + Assert.That(await frame.EvaluateAsync("window.result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should click the button with deviceScaleFactor set")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickTheButtonWithDeviceScaleFactorSet() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 400, + Height = 400, + }, + DeviceScaleFactor = 5, + }); + + var page = await context.NewPageAsync(); + Assert.That(await page.EvaluateAsync("window.devicePixelRatio"), Is.EqualTo(5)); + await page.SetContentAsync("
spacer
"); + await FrameUtils.AttachFrameAsync(page, "button-test", TestConstants.ServerUrl + "/input/button.html"); + var frame = page.FirstChildFrame(); + var button = await frame.QuerySelectorAsync("button"); + await button.ClickAsync(); + Assert.That(await frame.EvaluateAsync("window.result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should click the button with px border with relative point")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickTheButtonWithPxBorderWithRelativePoint() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvalOnSelectorAsync("button", "button => button.style.borderWidth = '8px'"); + await Page.ClickAsync("button", position: new Position { X = 20, Y = 10 }); + Assert.That(await Page.EvaluateAsync("window.result"), Is.EqualTo("Clicked")); + // Safari reports border-relative offsetX/offsetY. + Assert.That(await Page.EvaluateAsync("offsetX"), Is.EqualTo(TestConstants.IsWebKit ? 20 + 8 : 20)); + Assert.That(await Page.EvaluateAsync("offsetY"), Is.EqualTo(TestConstants.IsWebKit ? 10 + 8 : 10)); + } + + [PlaywrightTest("page-click.spec.ts", "should click the button with em border with offset")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickTheButtonWithEmBorderWithOffset() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvalOnSelectorAsync("button", "button => button.style.borderWidth = '2em'"); + await Page.EvalOnSelectorAsync("button", "button => button.style.fontSize = '12px'"); + await Page.ClickAsync("button", position: new Position { X = 20, Y = 10 }); + Assert.That(await Page.EvaluateAsync("window.result"), Is.EqualTo("Clicked")); + // Safari reports border-relative offsetX/offsetY. + Assert.That(await Page.EvaluateAsync("offsetX"), Is.EqualTo(TestConstants.IsWebKit ? 12 * 2 + 20 : 20)); + Assert.That(await Page.EvaluateAsync("offsetY"), Is.EqualTo(TestConstants.IsWebKit ? 12 * 2 + 10 : 10)); + } + + [PlaywrightTest("page-click.spec.ts", "should click a very large button with offset")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickAVeryLargeButtonWithOffset() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvalOnSelectorAsync("button", "button => button.style.borderWidth = '8px'"); + await Page.EvalOnSelectorAsync("button", "button => button.style.height = button.style.width = '2000px'"); + await Page.ClickAsync("button", position: new Position { X = 1900, Y = 1910 }); + Assert.That(await Page.EvaluateAsync("window.result"), Is.EqualTo("Clicked")); + // Safari reports border-relative offsetX/offsetY. + Assert.That(await Page.EvaluateAsync("offsetX"), Is.EqualTo(TestConstants.IsWebKit ? 1900 + 8 : 1900)); + Assert.That(await Page.EvaluateAsync("offsetY"), Is.EqualTo(TestConstants.IsWebKit ? 1910 + 8 : 1910)); + } + + [PlaywrightTest("page-click.spec.ts", "should click a button in scrolling container with offset")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickAButtonInScrollingContainerWithOffset() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvalOnSelectorAsync("button", @"button => { + const container = document.createElement('div'); + container.style.overflow = 'auto'; + container.style.width = '200px'; + container.style.height = '200px'; + button.parentElement.insertBefore(container, button); + container.appendChild(button); + button.style.height = '2000px'; + button.style.width = '2000px'; + button.style.borderWidth = '8px'; + }"); + + await Page.ClickAsync("button", position: new Position { X = 1900, Y = 1910 }); + Assert.That(await Page.EvaluateAsync("window.result"), Is.EqualTo("Clicked")); + // Safari reports border-relative offsetX/offsetY. + Assert.That(await Page.EvaluateAsync("offsetX"), Is.EqualTo(TestConstants.IsWebKit ? 1900 + 8 : 1900)); + Assert.That(await Page.EvaluateAsync("offsetY"), Is.EqualTo(TestConstants.IsWebKit ? 1910 + 8 : 1910)); + } + + [PlaywrightTest("page-click.spec.ts", "should click the button with offset with page scale")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldClickTheButtonWithOffsetWithPageScale() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 400, + Height = 400, + }, + IsMobile = true, + }); + + var page = await context.NewPageAsync(); + + await page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await page.EvalOnSelectorAsync("button", @"button => { + button.style.borderWidth = '8px'; + document.body.style.margin = '0'; + }"); + + await page.ClickAsync("button", position: new Position { X = 20, Y = 10 }); + Assert.That(await page.EvaluateAsync("window.result"), Is.EqualTo("Clicked")); + + var point = TestConstants.Product switch + { + TestConstants.ChromiumProduct => new Point(27, 18), + TestConstants.WebkitProduct => new Point(29, 19), + _ => new Point(28, 18), + }; + + Assert.That(Convert.ToInt32(await page.EvaluateAsync("pageX")), Is.EqualTo(point.X)); + Assert.That(Convert.ToInt32(await page.EvaluateAsync("pageY")), Is.EqualTo(point.Y)); + } + + [PlaywrightTest("page-click.spec.ts", "should wait for stable position")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForStablePosition() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvalOnSelectorAsync("button", @"button => { + button.style.transition = 'margin 500ms linear 0s'; + button.style.marginLeft = '200px'; + button.style.borderWidth = '0'; + button.style.width = '200px'; + button.style.height = '20px'; + // Set display to 'block'- otherwise Firefox layouts with non-even + // values on Linux. + button.style.display = 'block'; + document.body.style.margin = '0'; + }"); + + await Page.ClickAsync("button"); + Assert.That(await Page.EvaluateAsync("window.result"), Is.EqualTo("Clicked")); + Assert.That(await Page.EvaluateAsync("pageX"), Is.EqualTo(300)); + Assert.That(await Page.EvaluateAsync("pageY"), Is.EqualTo(10)); + } + + [PlaywrightTest("page-click.spec.ts", "should wait for becoming hit target")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForBecomingHitTarget() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvalOnSelectorAsync("button", @"button => { + button.style.borderWidth = '0'; + button.style.width = '200px'; + button.style.height = '20px'; + document.body.style.margin = '0'; + document.body.style.position = 'relative'; + const flyOver = document.createElement('div'); + flyOver.className = 'flyover'; + flyOver.style.position = 'absolute'; + flyOver.style.width = '400px'; + flyOver.style.height = '20px'; + flyOver.style.left = '-200px'; + flyOver.style.top = '0'; + flyOver.style.background = 'red'; + document.body.appendChild(flyOver); + }"); + + var clickTask = Page.ClickAsync("button"); + Assert.That(clickTask.IsCompleted, Is.False); + + await Page.EvalOnSelectorAsync(".flyover", "flyOver => flyOver.style.left = '0'"); + await GiveItAChanceToClick(Page); + Assert.That(clickTask.IsCompleted, Is.False); + + await Page.EvalOnSelectorAsync(".flyover", "flyOver => flyOver.style.left = '200px'"); + await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); + Assert.That(await Page.EvaluateAsync("window.result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should fail when obscured and not waiting for hit target")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWhenObscuredAndNotWaitingForHitTarget() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + var button = await Page.QuerySelectorAsync("button"); + await Page.EvalOnSelectorAsync("button", @"button => { + document.body.style.position = 'relative'; + const blocker = document.createElement('div'); + blocker.style.position = 'absolute'; + blocker.style.width = '400px'; + blocker.style.height = '20px'; + blocker.style.left = '0'; + blocker.style.top = '0'; + document.body.appendChild(blocker); + }"); + + await button.ClickAsync(force: true); + Assert.That(await Page.EvaluateAsync("window.result"), Is.EqualTo("Was not clicked")); + } + + [PlaywrightTest("page-click.spec.ts", "should wait for button to be enabled")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForButtonToBeEnabled() + { + await Page.SetContentAsync(""); + var clickTask = Page.ClickAsync("text=Click target"); + await GiveItAChanceToClick(Page); + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.Null); + Assert.That(clickTask.IsCompleted, Is.False); + await Page.EvaluateAsync("() => document.querySelector('button').removeAttribute('disabled')"); + await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.True); + } + + [PlaywrightTest("page-click.spec.ts", "should wait for input to be enabled")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForInputToBeEnabled() + { + await Page.SetContentAsync(""); + var clickTask = Page.ClickAsync("input"); + await GiveItAChanceToClick(Page); + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.Null); + Assert.That(clickTask.IsCompleted, Is.False); + await Page.EvaluateAsync("() => document.querySelector('input').removeAttribute('disabled')"); + await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.True); + } + + [PlaywrightTest("page-click.spec.ts", "should wait for select to be enabled")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForSelectToBeEnabled() + { + await Page.SetContentAsync(""); + var clickTask = Page.ClickAsync("select"); + await GiveItAChanceToClick(Page); + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.Null); + Assert.That(clickTask.IsCompleted, Is.False); + await Page.EvaluateAsync("() => document.querySelector('select').removeAttribute('disabled')"); + await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.True); + } + + [PlaywrightTest("page-click.spec.ts", "should click disabled div")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickDisabledDiv() + { + await Page.SetContentAsync("
Click target
"); + await Page.ClickAsync("text=Click target"); + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.True); + } + + [PlaywrightTest("page-click.spec.ts", "should climb dom for inner label with pointer-events:none")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClimbDomForInnerLabelWithPointerEventsNone() + { + await Page.SetContentAsync(""); + await Page.ClickAsync("text=Click target"); + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.True); + } + + [PlaywrightTest("page-click.spec.ts", "should climb up to [role=button]")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClimbUpToRoleButton() + { + await Page.SetContentAsync("
Click target
"); + await Page.ClickAsync("text=Click target"); + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.True); + } + + [PlaywrightTest("page-click.spec.ts", "should wait for BUTTON to be clickable when it has pointer-events:none")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForButtonToBeClickableWhenItHasPointerEventsNone() + { + await Page.SetContentAsync(""); + var clickTask = Page.ClickAsync("text=Click target"); + await GiveItAChanceToClick(Page); + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.Null); + Assert.That(clickTask.IsCompleted, Is.False); + await Page.EvaluateAsync("() => document.querySelector('button').style.removeProperty('pointer-events')"); + await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.True); + } + + [PlaywrightTest("page-click.spec.ts", "should wait for LABEL to be clickable when it has pointer-events:none")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForLabelToBeClickableWhenItHasPointerEventsNone() + { + await Page.SetContentAsync(""); + var clickTask = Page.ClickAsync("text=Click target"); + + for (int i = 0; i < 5; ++i) + { + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.Null); + } + + Assert.That(clickTask.IsCompleted, Is.False); + await Page.EvaluateAsync("() => document.querySelector('label').style.removeProperty('pointer-events')"); + await clickTask.WithTimeout(TestConstants.DefaultTaskTimeout); + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.True); + } + + [PlaywrightTest("page-click.spec.ts", "should update modifiers correctly")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldUpdateModifiersCorrectly() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.ClickAsync("button", modifiers: new[] { KeyboardModifier.Shift }); + Assert.That(await Page.EvaluateAsync("shiftKey"), Is.True); + await Page.ClickAsync("button", modifiers: Array.Empty()); + Assert.That(await Page.EvaluateAsync("shiftKey"), Is.False); + + await Page.Keyboard.DownAsync("Shift"); + + await Page.ClickAsync("button", modifiers: Array.Empty()); + Assert.That(await Page.EvaluateAsync("shiftKey"), Is.False); + + await Page.ClickAsync("button"); + Assert.That(await Page.EvaluateAsync("shiftKey"), Is.True); + + await Page.Keyboard.UpAsync("Shift"); + + await Page.ClickAsync("button"); + Assert.That(await Page.EvaluateAsync("shiftKey"), Is.False); + } + + [PlaywrightTest("page-click.spec.ts", "should click an offscreen element when scroll-behavior is smooth")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickAnOffscreenElementWhenScrollBehaviorIsSmooth() + { + await Page.SetContentAsync(@$" +
+ +
"); + + await Page.ClickAsync("button"); + Assert.That(await Page.EvaluateAsync("window.clicked"), Is.True); + } + + [PlaywrightTest("page-click.spec.ts", "should report nice error when element is detached and force-clicked")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReportNiceErrorWhenElementIsDetachedAndForceClicked() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/animating-button.html"); + await Page.EvaluateAsync("() => addButton()"); + var handle = await Page.QuerySelectorAsync("button"); + await Page.EvaluateAsync("() => stopButton(true)"); + var clickTask = handle.ClickAsync(force: true); + var exception = Assert.ThrowsAsync(() => clickTask); + Assert.That(await Page.EvaluateAsync("window.clicked"), Is.Null); + Assert.That(exception.Message, Does.Contain("Element is not attached to the DOM")); + } + + [PlaywrightTest("page-click.spec.ts", "should fail when element detaches after animation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWhenElementDetachesAfterAnimation() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/animating-button.html"); + await Page.EvaluateAsync("() => addButton()"); + var handle = await Page.QuerySelectorAsync("button"); + var clickTask = handle.ClickAsync(); + await Page.EvaluateAsync("() => stopButton(true)"); + var exception = Assert.ThrowsAsync(() => clickTask); + Assert.That(await Page.EvaluateAsync("window.clicked"), Is.Null); + Assert.That(exception.Message, Does.Contain("Element is not attached to the DOM")); + } + + [PlaywrightTest("page-click.spec.ts", "should retry when element detaches after animation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRetryWhenElementDetachesAfterAnimation() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/animating-button.html"); + await Page.EvaluateAsync("() => addButton()"); + var clickTask = Page.ClickAsync("button"); + Assert.That(clickTask.IsCompleted, Is.False); + Assert.That(await Page.EvaluateAsync("window.clicked"), Is.Null); + await Page.EvaluateAsync("() => stopButton(true)"); + await Page.EvaluateAsync("() => addButton()"); + Assert.That(clickTask.IsCompleted, Is.False); + Assert.That(await Page.EvaluateAsync("window.clicked"), Is.Null); + await Page.EvaluateAsync("() => stopButton(true)"); + await Page.EvaluateAsync("() => addButton()"); + Assert.That(clickTask.IsCompleted, Is.False); + Assert.That(await Page.EvaluateAsync("window.clicked"), Is.Null); + await Page.EvaluateAsync("() => stopButton(false)"); + await clickTask; + Assert.That(await Page.EvaluateAsync("window.clicked"), Is.True); + } + + [PlaywrightTest("page-click.spec.ts", "should retry when element is animating from outside the viewport")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRetryWhenElementIsAnimatingFromOutsideTheViewport() + { + await Page.SetContentAsync($@" + +
+ +
"); + + var handle = await Page.QuerySelectorAsync("button"); + var clickTask = handle.ClickAsync(); + await handle.EvaluateAsync("button => button.className = 'animated'"); + await clickTask; + Assert.That(await Page.EvaluateAsync("window.clicked"), Is.True); + } + + [PlaywrightTest("page-click.spec.ts", "should retry when element is animating from outside the viewport with force")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRetryWhenElementIsAnimatingFromOutsideTheViewportWithForce() + { + await Page.SetContentAsync($@" + +
+ +
"); + + var handle = await Page.QuerySelectorAsync("button"); + var clickTask = handle.ClickAsync(force: true); + await handle.EvaluateAsync("button => button.className = 'animated'"); + var exception = Assert.ThrowsAsync(() => clickTask); + Assert.That(await Page.EvaluateAsync("window.clicked"), Is.Null); + Assert.That(exception.Message, Does.Contain("Element is outside of the viewport")); + } + + [PlaywrightTest("page-click.spec.ts", "should dispatch microtasks in order")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDispatchMicrotasksInOrder() + { + await Page.SetContentAsync($@" + + "); + + await Page.ClickAsync("button"); + Assert.That(await Page.EvaluateAsync("window.result"), Is.EqualTo(1)); + } + + [PlaywrightTest("page-click.spec.ts", "should click the button when window.innerWidth is corrupted")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClickTheButtonWhenWindowInnerWidthIsCorrupted() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvaluateAsync(@"() => window.innerWith = 0"); + + await Page.ClickAsync("button"); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo("Clicked")); + } + + private async Task GiveItAChanceToClick(IPage page) + { + for (int i = 0; i < 5; i++) + { + await page.EvaluateAsync("() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f)))"); + } + } + } +} diff --git a/src/PlaywrightSharp.Tests/PageClickTimeout1Tests.cs b/src/PlaywrightSharp.Tests/PageClickTimeout1Tests.cs new file mode 100644 index 0000000000..65ad13492d --- /dev/null +++ b/src/PlaywrightSharp.Tests/PageClickTimeout1Tests.cs @@ -0,0 +1,31 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageClickTimeout1Tests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-click-timeout-1.spec.ts", "should avoid side effects after timeout")] + [Test, Ignore("Ignore USES_HOOKS")] + public void ShouldAvoidSideEffectsAfterTimeout() + { + } + + [PlaywrightTest("page-click-timeout-1.spec.ts", "should timeout waiting for button to be enabled")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTimeoutWaitingForButtonToBeEnabled() + { + await Page.SetContentAsync(""); + var clickTask = Page.ClickAsync("text=Click target", timeout: 3000); + Assert.That(await Page.EvaluateAsync("window.__CLICKED"), Is.Null); + + var exception = Assert.ThrowsAsync(() => clickTask); + + Assert.That(exception.Message, Does.Contain("Timeout 3000ms exceeded")); + Assert.That(exception.Message, Does.Contain("element is not enabled - waiting")); + } + } +} diff --git a/src/PlaywrightSharp.Tests/PageClickTimeout2Tests.cs b/src/PlaywrightSharp.Tests/PageClickTimeout2Tests.cs new file mode 100644 index 0000000000..faeb0fa888 --- /dev/null +++ b/src/PlaywrightSharp.Tests/PageClickTimeout2Tests.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageClickTimeout2Tests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-click-timeout-2.spec.ts", "should timeout waiting for display:none to be gone")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTimeoutWaitingForDisplayNoneToBeGone() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvalOnSelectorAsync("button", "b => b.style.display = 'none'"); + var exception = Assert.ThrowsAsync(() + => Page.ClickAsync("button", timeout: 5000)); + + Assert.That(exception.Message, Does.Contain("Timeout 5000ms exceeded")); + Assert.That(exception.Message, Does.Contain("waiting for element to be visible, enabled and stable")); + Assert.That(exception.Message, Does.Contain("element is not visible - waiting")); + } + + [PlaywrightTest("page-click-timeout-2.spec.ts", "should timeout waiting for visbility:hidden to be gone")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTimeoutWaitingForVisbilityHiddenToBeGone() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvalOnSelectorAsync("button", "b => b.style.visibility = 'hidden'"); + var clickTask = Page.ClickAsync("button", timeout: 5000); + var exception = Assert.ThrowsAsync(() + => Page.ClickAsync("button", timeout: 5000)); + + Assert.That(exception.Message, Does.Contain("Timeout 5000ms exceeded")); + Assert.That(exception.Message, Does.Contain("waiting for element to be visible, enabled and stable")); + Assert.That(exception.Message, Does.Contain("element is not visible - waiting")); + } + + } +} diff --git a/src/Playwright.Tests/PageClickTimeout3Tests.cs b/src/PlaywrightSharp.Tests/PageClickTimeout3Tests.cs similarity index 69% rename from src/Playwright.Tests/PageClickTimeout3Tests.cs rename to src/PlaywrightSharp.Tests/PageClickTimeout3Tests.cs index 41555596bd..853e2c7970 100644 --- a/src/Playwright.Tests/PageClickTimeout3Tests.cs +++ b/src/PlaywrightSharp.Tests/PageClickTimeout3Tests.cs @@ -1,58 +1,51 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageClickTimeout3Tests : PlaywrightSharpPageBaseTest - { - /// - public PageClickTimeout3Tests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-click-timeout-3.spec.ts", "should fail when element jumps during hit testing")] - [Fact(Skip = " Skip USES_HOOKS")] - public void ShouldFailWhenElementJumpsDuringHitTesting() - { - } - - [PlaywrightTest("page-click-timeout-3.spec.ts", "should timeout waiting for hit target")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTimeoutWaitingForHitTarget() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - var button = await Page.QuerySelectorAsync("button"); - - await Page.EvalOnSelectorAsync("button", @"button => { - button.style.borderWidth = '0'; - button.style.width = '200px'; - button.style.height = '20px'; - document.body.style.margin = '0'; - document.body.style.position = 'relative'; - const flyOver = document.createElement('div'); - flyOver.className = 'flyover'; - flyOver.style.position = 'absolute'; - flyOver.style.width = '400px'; - flyOver.style.height = '20px'; - flyOver.style.left = '-200px'; - flyOver.style.top = '0'; - flyOver.style.background = 'red'; - document.body.appendChild(flyOver); - }"); - - var exception = await Assert.ThrowsAsync(() - => button.ClickAsync(timeout: 5000)); - - Assert.Contains("Timeout 5000ms exceeded.", exception.Message); - } - } -} +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageClickTimeout3Tests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-click-timeout-3.spec.ts", "should fail when element jumps during hit testing")] + [Test, Ignore(" Skip USES_HOOKS")] + public void ShouldFailWhenElementJumpsDuringHitTesting() + { + } + + [PlaywrightTest("page-click-timeout-3.spec.ts", "should timeout waiting for hit target")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTimeoutWaitingForHitTarget() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + var button = await Page.QuerySelectorAsync("button"); + + await Page.EvalOnSelectorAsync("button", @"button => { + button.style.borderWidth = '0'; + button.style.width = '200px'; + button.style.height = '20px'; + document.body.style.margin = '0'; + document.body.style.position = 'relative'; + const flyOver = document.createElement('div'); + flyOver.className = 'flyover'; + flyOver.style.position = 'absolute'; + flyOver.style.width = '400px'; + flyOver.style.height = '20px'; + flyOver.style.left = '-200px'; + flyOver.style.top = '0'; + flyOver.style.background = 'red'; + document.body.appendChild(flyOver); + }"); + + var exception = Assert.ThrowsAsync(() + => button.ClickAsync(timeout: 5000)); + + Assert.That(exception.Message, Does.Contain("Timeout 5000ms exceeded.")); + } + } +} diff --git a/src/PlaywrightSharp.Tests/PageClickTimeout4Tests.cs b/src/PlaywrightSharp.Tests/PageClickTimeout4Tests.cs new file mode 100644 index 0000000000..68eef1a26c --- /dev/null +++ b/src/PlaywrightSharp.Tests/PageClickTimeout4Tests.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageClickTimeout4Tests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-click-timeout-4.spec.ts", "should timeout waiting for stable position")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTimeoutWaitingForStablePosition() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.EvalOnSelectorAsync("button", @"button => { + button.style.transition = 'margin 5s linear 0s'; + button.style.marginLeft = '200px'; + }"); + + var exception = Assert.ThrowsAsync(() + => Page.ClickAsync("button", timeout: 3000)); + + Assert.That(exception.Message, Does.Contain("Timeout 3000ms exceeded")); + Assert.That(exception.Message, Does.Contain("waiting for element to be visible, enabled and stable")); + Assert.That(exception.Message, Does.Contain("element is not stable - waiting")); + } + } +} diff --git a/src/PlaywrightSharp.Tests/PageCloseTests.cs b/src/PlaywrightSharp.Tests/PageCloseTests.cs new file mode 100644 index 0000000000..6e9be254ab --- /dev/null +++ b/src/PlaywrightSharp.Tests/PageCloseTests.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageCloseTests : PlaywrightSharpPageBaseTest + { + } +} diff --git a/src/Playwright.Tests/PageDialogTests.cs b/src/PlaywrightSharp.Tests/PageDialogTests.cs similarity index 69% rename from src/Playwright.Tests/PageDialogTests.cs rename to src/PlaywrightSharp.Tests/PageDialogTests.cs index 493444de52..708fe1d916 100644 --- a/src/Playwright.Tests/PageDialogTests.cs +++ b/src/PlaywrightSharp.Tests/PageDialogTests.cs @@ -1,116 +1,109 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageDialogTests : PlaywrightSharpPageBaseTest - { - /// - public PageDialogTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-dialog.spec.ts", "should fire")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFire() - { - Page.Dialog += async (_, e) => - { - Assert.Equal(DialogType.Alert, e.Type); - Assert.Equal(string.Empty, e.DefaultValue); - Assert.Equal("yo", e.Message); - - await e.AcceptAsync(); - }; - - await Page.EvaluateAsync("alert('yo');"); - } - - [PlaywrightTest("page-dialog.spec.ts", "should allow accepting prompts")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAllowAcceptingPrompts() - { - Page.Dialog += async (_, e) => - { - Assert.Equal(DialogType.Prompt, e.Type); - Assert.Equal("yes.", e.DefaultValue); - Assert.Equal("question?", e.Message); - - await e.AcceptAsync("answer!"); - }; - - string result = await Page.EvaluateAsync("prompt('question?', 'yes.')"); - Assert.Equal("answer!", result); - } - - [PlaywrightTest("page-dialog.spec.ts", "should dismiss the prompt")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDismissThePrompt() - { - Page.Dialog += async (_, e) => - { - await e.DismissAsync(); - }; - - string result = await Page.EvaluateAsync("prompt('question?')"); - Assert.Null(result); - } - - [PlaywrightTest("page-dialog.spec.ts", "should accept the confirm prompt")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptTheConfirmPrompts() - { - Page.Dialog += async (_, e) => - { - await e.AcceptAsync(); - }; - - bool result = await Page.EvaluateAsync("confirm('boolean?')"); - Assert.True(result); - } - - [PlaywrightTest("page-dialog.spec.ts", "should dismiss the confirm prompt")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDismissTheConfirmPrompt() - { - Page.Dialog += async (_, e) => - { - await e.DismissAsync(); - }; - - bool result = await Page.EvaluateAsync("prompt('boolean?')"); - Assert.False(result); - } - - [PlaywrightTest("page-dialog.spec.ts", "should log prompt actions")] - [Fact(Skip = "FAIL CHANNEL")] - public async Task ShouldLogPromptActions() - { - Page.Dialog += async (_, e) => - { - await e.DismissAsync(); - }; - - bool result = await Page.EvaluateAsync("prompt('boolean?')"); - Assert.False(result); - } - - [PlaywrightTest("page-dialog.spec.ts", "should be able to close context with open alert")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task ShouldBeAbleToCloseContextWithOpenAlert() - { - var context = await Browser.NewContextAsync(); - var page = await context.NewPageAsync(); - var alertTask = page.WaitForEventAsync(PageEvent.Dialog); - - await page.EvaluateAsync("() => setTimeout(() => alert('hello'), 0)"); - await alertTask; - await context.CloseAsync(); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageDialogTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-dialog.spec.ts", "should fire")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFire() + { + Page.Dialog += async (_, e) => + { + Assert.That(e.Type, Is.EqualTo(DialogType.Alert)); + Assert.That(e.DefaultValue, Is.EqualTo(string.Empty)); + Assert.That(e.Message, Is.EqualTo("yo")); + + await e.AcceptAsync(); + }; + + await Page.EvaluateAsync("alert('yo');"); + } + + [PlaywrightTest("page-dialog.spec.ts", "should allow accepting prompts")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAllowAcceptingPrompts() + { + Page.Dialog += async (_, e) => + { + Assert.That(e.Type, Is.EqualTo(DialogType.Prompt)); + Assert.That(e.DefaultValue, Is.EqualTo("yes.")); + Assert.That(e.Message, Is.EqualTo("question?")); + + await e.AcceptAsync("answer!"); + }; + + string result = await Page.EvaluateAsync("prompt('question?', 'yes.')"); + Assert.That(result, Is.EqualTo("answer!")); + } + + [PlaywrightTest("page-dialog.spec.ts", "should dismiss the prompt")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDismissThePrompt() + { + Page.Dialog += async (_, e) => + { + await e.DismissAsync(); + }; + + string result = await Page.EvaluateAsync("prompt('question?')"); + Assert.That(result, Is.Null); + } + + [PlaywrightTest("page-dialog.spec.ts", "should accept the confirm prompt")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptTheConfirmPrompts() + { + Page.Dialog += async (_, e) => + { + await e.AcceptAsync(); + }; + + bool result = await Page.EvaluateAsync("confirm('boolean?')"); + Assert.That(result, Is.True); + } + + [PlaywrightTest("page-dialog.spec.ts", "should dismiss the confirm prompt")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDismissTheConfirmPrompt() + { + Page.Dialog += async (_, e) => + { + await e.DismissAsync(); + }; + + bool result = await Page.EvaluateAsync("prompt('boolean?')"); + Assert.That(result, Is.False); + } + + [PlaywrightTest("page-dialog.spec.ts", "should log prompt actions")] + [Test, Ignore("FAIL CHANNEL")] + public async Task ShouldLogPromptActions() + { + Page.Dialog += async (_, e) => + { + await e.DismissAsync(); + }; + + bool result = await Page.EvaluateAsync("prompt('boolean?')"); + Assert.That(result, Is.False); + } + + [PlaywrightTest("page-dialog.spec.ts", "should be able to close context with open alert")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task ShouldBeAbleToCloseContextWithOpenAlert() + { + var context = await Browser.NewContextAsync(); + var page = await context.NewPageAsync(); + var alertTask = page.WaitForEventAsync(PageEvent.Dialog); + + await page.EvaluateAsync("() => setTimeout(() => alert('hello'), 0)"); + await alertTask; + await context.CloseAsync(); + } + } +} diff --git a/src/Playwright.Tests/PageDispatchEventTests.cs b/src/PlaywrightSharp.Tests/PageDispatchEventTests.cs similarity index 76% rename from src/Playwright.Tests/PageDispatchEventTests.cs rename to src/PlaywrightSharp.Tests/PageDispatchEventTests.cs index 3b664904d8..0678237954 100644 --- a/src/Playwright.Tests/PageDispatchEventTests.cs +++ b/src/PlaywrightSharp.Tests/PageDispatchEventTests.cs @@ -1,203 +1,196 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///dispatchevent.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageDispatchEventTests : PlaywrightSharpPageBaseTest - { - /// - public PageDispatchEventTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click event")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDispatchClickEvent() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.DispatchEventAsync("button", "click"); - Assert.Equal("Clicked", await Page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click event properties")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDispatchClickEventProperties() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.DispatchEventAsync("button", "click"); - Assert.True(await Page.EvaluateAsync("() => bubbles")); - Assert.True(await Page.EvaluateAsync("() => cancelable")); - Assert.True(await Page.EvaluateAsync("() => composed")); - } - - [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click svg")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDispatchClickSvg() - { - await Page.SetContentAsync(@" - - - "); - - await Page.DispatchEventAsync("circle", "click"); - Assert.Equal(42, await Page.EvaluateAsync("() => window.__CLICKED")); - } - - [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click on a span with an inline element inside")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDispatchClickOnASpanWithAnInlineElementInside() - { - await Page.SetContentAsync(@" - - "); - - await Page.DispatchEventAsync("span", "click"); - Assert.Equal(42, await Page.EvaluateAsync("() => window.CLICKED")); - } - - [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click after navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDispatchClickAfterNavigation() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.DispatchEventAsync("button", "click"); - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.DispatchEventAsync("button", "click"); - Assert.Equal("Clicked", await Page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click after a cross origin navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDispatchClickAfterACrossOriginNavigation() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - await Page.DispatchEventAsync("button", "click"); - await Page.GoToAsync(TestConstants.CrossProcessHttpPrefix + "/input/button.html"); - await Page.DispatchEventAsync("button", "click"); - Assert.Equal("Clicked", await Page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("page-dispatchevent.spec.ts", "should not fail when element is blocked on hover")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotFailWhenElementIsBlockedOnHover() - { - await Page.SetContentAsync(@" - - - -
-
"); - - await Page.DispatchEventAsync("button", "click"); - Assert.True(await Page.EvaluateAsync("() => window.clicked")); - } - - [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click when node is added in shadow dom")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDispatchClickWhenNodeIsAddedInShadowDom() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var watchdog = Page.DispatchEventAsync("span", "click"); - - await Page.EvaluateAsync(@"() => { - const div = document.createElement('div'); - div.attachShadow({mode: 'open'}); - document.body.appendChild(div); - }"); - await Page.EvaluateAsync("() => new Promise(f => setTimeout(f, 100))"); - - await Page.EvaluateAsync(@"() => { - const span = document.createElement('span'); - span.textContent = 'Hello from shadow'; - span.addEventListener('click', () => window.clicked = true); - document.querySelector('div').shadowRoot.appendChild(span); - }"); - - await watchdog; - Assert.True(await Page.EvaluateAsync("() => window.clicked")); - } - - [PlaywrightTest("page-dispatchevent.spec.ts", "should be atomic")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAtomic() - { - const string createDummySelector = @"({ - create(root, target) {}, - query(root, selector) { - const result = root.querySelector(selector); - if (result) - Promise.resolve().then(() => result.onclick = ''); - return result; - }, - queryAll(root, selector) { - const result = Array.from(root.querySelectorAll(selector)); - for (const e of result) - Promise.resolve().then(() => e.onclick = null); - return result; - } - })"; - - await TestUtils.RegisterEngineAsync(Playwright, "page-dispatchevent", createDummySelector); - await Page.SetContentAsync("
Hello
"); - await Page.DispatchEventAsync("page-dispatchevent=div", "click"); - Assert.True(await Page.EvaluateAsync("() => window['_clicked']")); - } - - [PlaywrightTest("page-dispatchevent.spec.ts", "Page.dispatchEvent(drag)", "should dispatch drag drop events")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task ShouldDispatchDragDropEvents() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/drag-n-drop.html"); - var dataTransfer = await Page.EvaluateHandleAsync("() => new DataTransfer()"); - await Page.DispatchEventAsync("#source", "dragstart", new { dataTransfer }); - await Page.DispatchEventAsync("#target", "drop", new { dataTransfer }); - - var source = await Page.QuerySelectorAsync("#source"); - var target = await Page.QuerySelectorAsync("#target"); - Assert.True(await Page.EvaluateAsync(@"() => { - return source.parentElement === target; - }", new { source, target })); - } - - [PlaywrightTest("page-dispatchevent.spec.ts", "Page.dispatchEvent(drag)", "should dispatch drag drop events")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task ElementHandleShouldDispatchDragDropEvents() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/drag-n-drop.html"); - var dataTransfer = await Page.EvaluateHandleAsync("() => new DataTransfer()"); - var source = await Page.QuerySelectorAsync("#source"); - await source.DispatchEventAsync("dragstart", new { dataTransfer }); - var target = await Page.QuerySelectorAsync("#target"); - await target.DispatchEventAsync("drop", new { dataTransfer }); - - Assert.True(await Page.EvaluateAsync(@"() => { - return source.parentElement === target; - }", new { source, target })); - } - - [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click event")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ElementHandleShouldDispatchClickEvent() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); - var button = await Page.QuerySelectorAsync("button"); - await button.DispatchEventAsync("click"); - Assert.Equal("Clicked", await Page.EvaluateAsync("() => result")); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///dispatchevent.spec.ts + public class PageDispatchEventTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click event")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDispatchClickEvent() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.DispatchEventAsync("button", "click"); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click event properties")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDispatchClickEventProperties() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.DispatchEventAsync("button", "click"); + Assert.That(await Page.EvaluateAsync("() => bubbles"), Is.True); + Assert.That(await Page.EvaluateAsync("() => cancelable"), Is.True); + Assert.That(await Page.EvaluateAsync("() => composed"), Is.True); + } + + [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click svg")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDispatchClickSvg() + { + await Page.SetContentAsync(@" + + + "); + + await Page.DispatchEventAsync("circle", "click"); + Assert.That(await Page.EvaluateAsync("() => window.__CLICKED"), Is.EqualTo(42)); + } + + [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click on a span with an inline element inside")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDispatchClickOnASpanWithAnInlineElementInside() + { + await Page.SetContentAsync(@" + + "); + + await Page.DispatchEventAsync("span", "click"); + Assert.That(await Page.EvaluateAsync("() => window.CLICKED"), Is.EqualTo(42)); + } + + [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click after navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDispatchClickAfterNavigation() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.DispatchEventAsync("button", "click"); + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.DispatchEventAsync("button", "click"); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click after a cross origin navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDispatchClickAfterACrossOriginNavigation() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + await Page.DispatchEventAsync("button", "click"); + await Page.GoToAsync(TestConstants.CrossProcessHttpPrefix + "/input/button.html"); + await Page.DispatchEventAsync("button", "click"); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("Clicked")); + } + + [PlaywrightTest("page-dispatchevent.spec.ts", "should not fail when element is blocked on hover")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotFailWhenElementIsBlockedOnHover() + { + await Page.SetContentAsync(@" + + + +
+
"); + + await Page.DispatchEventAsync("button", "click"); + Assert.That(await Page.EvaluateAsync("() => window.clicked"), Is.True); + } + + [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click when node is added in shadow dom")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDispatchClickWhenNodeIsAddedInShadowDom() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var watchdog = Page.DispatchEventAsync("span", "click"); + + await Page.EvaluateAsync(@"() => { + const div = document.createElement('div'); + div.attachShadow({mode: 'open'}); + document.body.appendChild(div); + }"); + await Page.EvaluateAsync("() => new Promise(f => setTimeout(f, 100))"); + + await Page.EvaluateAsync(@"() => { + const span = document.createElement('span'); + span.textContent = 'Hello from shadow'; + span.addEventListener('click', () => window.clicked = true); + document.querySelector('div').shadowRoot.appendChild(span); + }"); + + await watchdog; + Assert.That(await Page.EvaluateAsync("() => window.clicked"), Is.True); + } + + [PlaywrightTest("page-dispatchevent.spec.ts", "should be atomic")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAtomic() + { + const string createDummySelector = @"({ + create(root, target) {}, + query(root, selector) { + const result = root.querySelector(selector); + if (result) + Promise.resolve().then(() => result.onclick = ''); + return result; + }, + queryAll(root, selector) { + const result = Array.from(root.querySelectorAll(selector)); + for (const e of result) + Promise.resolve().then(() => e.onclick = null); + return result; + } + })"; + + await TestUtils.RegisterEngineAsync(Playwright, "page-dispatchevent", createDummySelector); + await Page.SetContentAsync("
Hello
"); + await Page.DispatchEventAsync("page-dispatchevent=div", "click"); + Assert.That(await Page.EvaluateAsync("() => window['_clicked']"), Is.True); + } + + [PlaywrightTest("page-dispatchevent.spec.ts", "Page.dispatchEvent(drag)", "should dispatch drag drop events")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task ShouldDispatchDragDropEvents() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/drag-n-drop.html"); + var dataTransfer = await Page.EvaluateHandleAsync("() => new DataTransfer()"); + await Page.DispatchEventAsync("#source", "dragstart", new { dataTransfer }); + await Page.DispatchEventAsync("#target", "drop", new { dataTransfer }); + + var source = await Page.QuerySelectorAsync("#source"); + var target = await Page.QuerySelectorAsync("#target"); + Assert.That(await Page.EvaluateAsync(@"() => { + return source.parentElement === target; + }", new { source, target }), Is.True); + } + + [PlaywrightTest("page-dispatchevent.spec.ts", "Page.dispatchEvent(drag)", "should dispatch drag drop events")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task ElementHandleShouldDispatchDragDropEvents() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/drag-n-drop.html"); + var dataTransfer = await Page.EvaluateHandleAsync("() => new DataTransfer()"); + var source = await Page.QuerySelectorAsync("#source"); + await source.DispatchEventAsync("dragstart", new { dataTransfer }); + var target = await Page.QuerySelectorAsync("#target"); + await target.DispatchEventAsync("drop", new { dataTransfer }); + + Assert.That(await Page.EvaluateAsync(@"() => { + return source.parentElement === target; + }", new { source, target }), Is.True); + } + + [PlaywrightTest("page-dispatchevent.spec.ts", "should dispatch click event")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ElementHandleShouldDispatchClickEvent() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/button.html"); + var button = await Page.QuerySelectorAsync("button"); + await button.DispatchEventAsync("click"); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("Clicked")); + } + } +} diff --git a/src/Playwright.Tests/PageDragTests.cs b/src/PlaywrightSharp.Tests/PageDragTests.cs similarity index 54% rename from src/Playwright.Tests/PageDragTests.cs rename to src/PlaywrightSharp.Tests/PageDragTests.cs index be179b3239..f5f8698ee9 100644 --- a/src/Playwright.Tests/PageDragTests.cs +++ b/src/PlaywrightSharp.Tests/PageDragTests.cs @@ -1,30 +1,23 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageDragTests : PlaywrightSharpPageBaseTest - { - /// - public PageDragTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-drag.spec.ts", "should work")] - [Fact(Skip = "Skipped in Playwright")] - public async Task ShouldWork() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/drag-n-drop.html"); - await Page.HoverAsync("#source"); - await Page.Mouse.DownAsync(); - await Page.HoverAsync("#target"); - await Page.Mouse.UpAsync(); - - Assert.True(await Page.EvalOnSelectorAsync("#target", "target => target.contains(document.querySelector('#source'))")); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageDragTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-drag.spec.ts", "should work")] + [Test, Ignore("Skipped in Playwright")] + public async Task ShouldWork() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/drag-n-drop.html"); + await Page.HoverAsync("#source"); + await Page.Mouse.DownAsync(); + await Page.HoverAsync("#target"); + await Page.Mouse.UpAsync(); + + Assert.That(await Page.EvalOnSelectorAsync("#target", "target => target.contains(document.querySelector('#source'))"), Is.True); + } + } +} diff --git a/src/Playwright.Tests/PageEmulateMediaTests.cs b/src/PlaywrightSharp.Tests/PageEmulateMediaTests.cs similarity index 52% rename from src/Playwright.Tests/PageEmulateMediaTests.cs rename to src/PlaywrightSharp.Tests/PageEmulateMediaTests.cs index 2362702769..4a8c825cab 100644 --- a/src/Playwright.Tests/PageEmulateMediaTests.cs +++ b/src/PlaywrightSharp.Tests/PageEmulateMediaTests.cs @@ -1,150 +1,143 @@ -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageEmulateMediaTests : PlaywrightSharpPageBaseTest - { - /// - public PageEmulateMediaTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-emulate-media.spec.ts", "should emulate scheme work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEmulateSchemeWork() - { - await Page.EmulateMediaAsync(ColorScheme.Light); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches")); - - await Page.EmulateMediaAsync(ColorScheme.Dark); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches")); - } - - [PlaywrightTest("page-emulate-media.spec.ts", "should default to light")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDefaultToLight() - { - Assert.True(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches")); - - await Page.EmulateMediaAsync(ColorScheme.Dark); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches")); - - await Page.EmulateMediaAsync(colorScheme: ColorScheme.Undefined); - Assert.True(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches")); - Assert.False(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches")); - } - - [PlaywrightTest("page-emulate-media.spec.ts", "should throw in case of bad media argument")] - [Fact(Skip = "We don't need this test. Leaving for tracking purposes")] - public void ShouldThrowInCaseOfBadMediaArgument() { } - - [PlaywrightTest("page-emulate-media.spec.ts", "should work during navigation")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWorkDuringNavigation() - { - await Page.EmulateMediaAsync(ColorScheme.Light); - var navigated = Page.GoToAsync(TestConstants.EmptyPage); - - for (int i = 0; i < 9; i++) - { - await Page.EmulateMediaAsync(i % 2 == 0 ? ColorScheme.Dark : ColorScheme.Light); - await Task.Delay(1); - } - await navigated; - - Assert.True(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches")); - } - - [PlaywrightTest("page-emulate-media.spec.ts", "should work in popup")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkInPopup() - { - await using (var context = await Browser.NewContextAsync(new BrowserContextOptions - { - ColorScheme = ColorScheme.Dark, - })) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - var popupTask = page.WaitForEventAsync(PageEvent.Popup); - - await TaskUtils.WhenAll( - popupTask, - page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); - - var popup = popupTask.Result; - - Assert.True(await popup.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches")); - Assert.False(await popup.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches")); - } - - await using (var context = await Browser.NewContextAsync(new BrowserContextOptions - { - ColorScheme = ColorScheme.Light, - })) - { - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - var popupTask = page.WaitForEventAsync(PageEvent.Popup); - - await TaskUtils.WhenAll( - popupTask, - page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); - - var popup = popupTask.Result; - - Assert.False(await popup.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches")); - Assert.True(await popup.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches")); - } - } - - [PlaywrightTest("page-emulate-media.spec.ts", "should work in cross-process iframe")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkInCrossProcessIframe() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - ColorScheme = ColorScheme.Dark, - }); - - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(page, "frame1", TestConstants.CrossProcessHttpPrefix + "/empty.html"); - var frame = page.Frames.ElementAt(1); - - Assert.True(await frame.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches")); - } - - [PlaywrightTest("page-emulate-media.spec.ts", "should emulate type")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEmulateType() - { - Assert.True(await Page.EvaluateAsync("matchMedia('screen').matches")); - Assert.False(await Page.EvaluateAsync("matchMedia('print').matches")); - await Page.EmulateMediaAsync(Media.Print); - Assert.False(await Page.EvaluateAsync("matchMedia('screen').matches")); - Assert.True(await Page.EvaluateAsync("matchMedia('print').matches")); - await Page.EmulateMediaAsync(); - Assert.False(await Page.EvaluateAsync("matchMedia('screen').matches")); - Assert.True(await Page.EvaluateAsync("matchMedia('print').matches")); - await Page.EmulateMediaAsync(Media.Undefined); - Assert.True(await Page.EvaluateAsync("matchMedia('screen').matches")); - Assert.False(await Page.EvaluateAsync("matchMedia('print').matches")); - } - - [PlaywrightTest("page-emulate-media.spec.ts", "should throw in case of bad colorScheme argument")] - [Fact(Skip = "We don't need this test. Leaving for tracking purposes")] - public void ShouldThrowInCaseOfBadColorSchemeArgument() { } - } -} +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageEmulateMediaTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-emulate-media.spec.ts", "should emulate scheme work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEmulateSchemeWork() + { + await Page.EmulateMediaAsync(ColorScheme.Light); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches"), Is.False); + + await Page.EmulateMediaAsync(ColorScheme.Dark); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches"), Is.False); + } + + [PlaywrightTest("page-emulate-media.spec.ts", "should default to light")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDefaultToLight() + { + Assert.That(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches"), Is.False); + + await Page.EmulateMediaAsync(ColorScheme.Dark); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches"), Is.False); + + await Page.EmulateMediaAsync(colorScheme: ColorScheme.Undefined); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches"), Is.False); + } + + [PlaywrightTest("page-emulate-media.spec.ts", "should throw in case of bad media argument")] + [Test, Ignore("We don't need this test. Leaving for tracking purposes")] + public void ShouldThrowInCaseOfBadMediaArgument() { } + + [PlaywrightTest("page-emulate-media.spec.ts", "should work during navigation")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWorkDuringNavigation() + { + await Page.EmulateMediaAsync(ColorScheme.Light); + var navigated = Page.GoToAsync(TestConstants.EmptyPage); + + for (int i = 0; i < 9; i++) + { + await Page.EmulateMediaAsync(i % 2 == 0 ? ColorScheme.Dark : ColorScheme.Light); + await Task.Delay(1); + } + await navigated; + + Assert.That(await Page.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches"), Is.True); + } + + [PlaywrightTest("page-emulate-media.spec.ts", "should work in popup")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkInPopup() + { + await using (var context = await Browser.NewContextAsync(new BrowserContextOptions + { + ColorScheme = ColorScheme.Dark, + })) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + var popupTask = page.WaitForEventAsync(PageEvent.Popup); + + await TaskUtils.WhenAll( + popupTask, + page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); + + var popup = popupTask.Result; + + Assert.That(await popup.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches"), Is.True); + Assert.That(await popup.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches"), Is.False); + } + + await using (var context = await Browser.NewContextAsync(new BrowserContextOptions + { + ColorScheme = ColorScheme.Light, + })) + { + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + var popupTask = page.WaitForEventAsync(PageEvent.Popup); + + await TaskUtils.WhenAll( + popupTask, + page.EvaluateAsync("url => window.open(url)", TestConstants.EmptyPage)); + + var popup = popupTask.Result; + + Assert.That(await popup.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches"), Is.False); + Assert.That(await popup.EvaluateAsync("() => matchMedia('(prefers-color-scheme: light)').matches"), Is.True); + } + } + + [PlaywrightTest("page-emulate-media.spec.ts", "should work in cross-process iframe")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkInCrossProcessIframe() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + ColorScheme = ColorScheme.Dark, + }); + + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(page, "frame1", TestConstants.CrossProcessHttpPrefix + "/empty.html"); + var frame = page.Frames.ElementAt(1); + + Assert.That(await frame.EvaluateAsync("() => matchMedia('(prefers-color-scheme: dark)').matches"), Is.True); + } + + [PlaywrightTest("page-emulate-media.spec.ts", "should emulate type")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEmulateType() + { + Assert.That(await Page.EvaluateAsync("matchMedia('screen').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("matchMedia('print').matches"), Is.False); + await Page.EmulateMediaAsync(Media.Print); + Assert.That(await Page.EvaluateAsync("matchMedia('screen').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("matchMedia('print').matches"), Is.True); + await Page.EmulateMediaAsync(); + Assert.That(await Page.EvaluateAsync("matchMedia('screen').matches"), Is.False); + Assert.That(await Page.EvaluateAsync("matchMedia('print').matches"), Is.True); + await Page.EmulateMediaAsync(Media.Undefined); + Assert.That(await Page.EvaluateAsync("matchMedia('screen').matches"), Is.True); + Assert.That(await Page.EvaluateAsync("matchMedia('print').matches"), Is.False); + } + + [PlaywrightTest("page-emulate-media.spec.ts", "should throw in case of bad colorScheme argument")] + [Test, Ignore("We don't need this test. Leaving for tracking purposes")] + public void ShouldThrowInCaseOfBadColorSchemeArgument() { } + } +} diff --git a/src/Playwright.Tests/PageEvaluateHandleTests.cs b/src/PlaywrightSharp.Tests/PageEvaluateHandleTests.cs similarity index 64% rename from src/Playwright.Tests/PageEvaluateHandleTests.cs rename to src/PlaywrightSharp.Tests/PageEvaluateHandleTests.cs index 05a93e5140..098ba9ea59 100644 --- a/src/Playwright.Tests/PageEvaluateHandleTests.cs +++ b/src/PlaywrightSharp.Tests/PageEvaluateHandleTests.cs @@ -1,167 +1,160 @@ -using System; -using System.Dynamic; -using System.Linq; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageEvaluateHandleTests : PlaywrightSharpPageBaseTest - { - /// - public PageEvaluateHandleTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-evaluate-handle.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - var windowHandle = await Page.EvaluateHandleAsync("() => window"); - Assert.NotNull(windowHandle); - } - - [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept object handle as an argument")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptObjectHandleAsAnArgument() - { - var navigatorHandle = await Page.EvaluateHandleAsync("() => navigator"); - string text = await Page.EvaluateAsync("e => e.userAgent", navigatorHandle); - Assert.Contains("Mozilla", text); - } - - [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept object handle to primitive types")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptObjectHandleToPrimitiveTypes() - { - var aHandle = await Page.EvaluateHandleAsync("() => 5"); - bool isFive = await Page.EvaluateAsync("e => Object.is (e, 5)", aHandle); - Assert.True(isFive); - } - - [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept nested handle")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptNestedHandle() - { - var foo = await Page.EvaluateHandleAsync("() => ({x: 1, y: 'foo'})"); - dynamic result = await Page.EvaluateAsync("({ foo }) => foo", new { foo }); - - Assert.Equal(1, result.x); - Assert.Equal("foo", result.y); - } - - [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept nested window handle")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptNestedWindowHandle() - { - var foo = await Page.EvaluateHandleAsync("() => window"); - Assert.True(await Page.EvaluateAsync("({ foo }) => foo === window", new { foo })); - } - - [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept multiple nested handles")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptMultipleNestedHandles() - { - var foo = await Page.EvaluateHandleAsync("() => ({ x: 1, y: 'foo' })"); - var bar = await Page.EvaluateHandleAsync("() => 5"); - var baz = await Page.EvaluateHandleAsync("() => ['baz']"); - - string result = await Page.EvaluateAsync( - "x => JSON.stringify(x)", - new - { - a1 = new { foo }, - a2 = new - { - bar, - arr = new[] { new { baz } }, - }, - }); - - var json = JsonDocument.Parse(result).RootElement; - - Assert.Equal(1, json.GetProperty("a1").GetProperty("foo").GetProperty("x").GetInt32()); - Assert.Equal("foo", json.GetProperty("a1").GetProperty("foo").GetProperty("y").ToString()); - Assert.Equal(5, json.GetProperty("a2").GetProperty("bar").GetInt32()); - Assert.Equal("baz", json.GetProperty("a2").GetProperty("arr").EnumerateArray().First().GetProperty("baz").EnumerateArray().First().ToString()); - } - - [PlaywrightTest("page-evaluate-handle.spec.ts", "should throw for circular objects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowForCircularObjects() - { - dynamic a = new ExpandoObject(); - a.a = 1; - a.y = a; - - var exception = await Assert.ThrowsAnyAsync(() => Page.EvaluateAsync("x => x", a)); - Assert.Equal("Argument is a circular structure", exception.Message); - } - - [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept same nested object multiple times")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptSameNestedObjectMultipleTimes() - { - dynamic foo = new { x = 1 }; - string result = await Page.EvaluateAsync( - "x => JSON.stringify(x)", - new - { - foo, - bar = new[] { foo }, - baz = new { foo }, - }); - - var json = JsonDocument.Parse(result).RootElement; - - Assert.Equal(1, json.GetProperty("foo").GetProperty("x").GetInt32()); - Assert.Equal(1, json.GetProperty("bar").EnumerateArray().First().GetProperty("x").GetInt32()); - Assert.Equal(1, json.GetProperty("baz").GetProperty("foo").GetProperty("x").GetInt32()); - } - - [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept object handle to unserializable value")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptObjectHandleToUnserializableValue() - { - var aHandle = await Page.EvaluateHandleAsync("() => Infinity"); - Assert.True(await Page.EvaluateAsync("e => Object.is(e, Infinity)", aHandle)); - } - - [PlaywrightTest("page-evaluate-handle.spec.ts", "should pass configurable args")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldPassConfigurableArgs() - { - JsonElement result = await Page.EvaluateAsync( - @"arg =>{ - if (arg.foo !== 42) - throw new Error('Not a 42'); - arg.foo = 17; - if (arg.foo !== 17) - throw new Error('Not 17'); - delete arg.foo; - if (arg.foo === 17) - throw new Error('Still 17'); - return arg; - }", - new { foo = 42 }); - - Assert.Equal("{}", result.ToString()); - } - - [PlaywrightTest("page-evaluate-handle.spec.ts", "should work with primitives")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithPrimitives() - { - var aHandle = await Page.EvaluateHandleAsync(@"() => { - window.FOO = 123; - return window; - }"); - Assert.Equal(123, await Page.EvaluateAsync("e => e.FOO", aHandle)); - } - } -} +using System; +using System.Dynamic; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageEvaluateHandleTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-evaluate-handle.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + var windowHandle = await Page.EvaluateHandleAsync("() => window"); + Assert.That(windowHandle, Is.Not.Null); + } + + [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept object handle as an argument")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptObjectHandleAsAnArgument() + { + var navigatorHandle = await Page.EvaluateHandleAsync("() => navigator"); + string text = await Page.EvaluateAsync("e => e.userAgent", navigatorHandle); + Assert.That(text, Does.Contain("Mozilla")); + } + + [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept object handle to primitive types")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptObjectHandleToPrimitiveTypes() + { + var aHandle = await Page.EvaluateHandleAsync("() => 5"); + bool isFive = await Page.EvaluateAsync("e => Object.is (e, 5)", aHandle); + Assert.That(isFive, Is.True); + } + + [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept nested handle")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptNestedHandle() + { + var foo = await Page.EvaluateHandleAsync("() => ({x: 1, y: 'foo'})"); + dynamic result = await Page.EvaluateAsync("({ foo }) => foo", new { foo }); + + Assert.That(result.x, Is.EqualTo(1)); + Assert.That(result.y, Is.EqualTo("foo")); + } + + [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept nested window handle")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptNestedWindowHandle() + { + var foo = await Page.EvaluateHandleAsync("() => window"); + Assert.That(await Page.EvaluateAsync("({ foo }) => foo === window", new { foo }), Is.True); + } + + [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept multiple nested handles")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptMultipleNestedHandles() + { + var foo = await Page.EvaluateHandleAsync("() => ({ x: 1, y: 'foo' })"); + var bar = await Page.EvaluateHandleAsync("() => 5"); + var baz = await Page.EvaluateHandleAsync("() => ['baz']"); + + string result = await Page.EvaluateAsync( + "x => JSON.stringify(x)", + new + { + a1 = new { foo }, + a2 = new + { + bar, + arr = new[] { new { baz } }, + }, + }); + + var json = JsonDocument.Parse(result).RootElement; + + Assert.That(json.GetProperty("a1").GetProperty("foo").GetProperty("x").GetInt32(), Is.EqualTo(1)); + Assert.That(json.GetProperty("a1").GetProperty("foo").GetProperty("y").ToString(), Is.EqualTo("foo")); + Assert.That(json.GetProperty("a2").GetProperty("bar").GetInt32(), Is.EqualTo(5)); + Assert.That(json.GetProperty("a2").GetProperty("arr").EnumerateArray().First().GetProperty("baz").EnumerateArray().First().ToString(), Is.EqualTo("baz")); + } + + [PlaywrightTest("page-evaluate-handle.spec.ts", "should throw for circular objects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowForCircularObjects() + { + dynamic a = new ExpandoObject(); + a.a = 1; + a.y = a; + + var exception = Assert.CatchAsync(() => Page.EvaluateAsync("x => x", a)); + Assert.That(exception.Message, Is.EqualTo("Argument is a circular structure")); + } + + [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept same nested object multiple times")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptSameNestedObjectMultipleTimes() + { + dynamic foo = new { x = 1 }; + string result = await Page.EvaluateAsync( + "x => JSON.stringify(x)", + new + { + foo, + bar = new[] { foo }, + baz = new { foo }, + }); + + var json = JsonDocument.Parse(result).RootElement; + + Assert.That(json.GetProperty("foo").GetProperty("x").GetInt32(), Is.EqualTo(1)); + Assert.That(json.GetProperty("bar").EnumerateArray().First().GetProperty("x").GetInt32(), Is.EqualTo(1)); + Assert.That(json.GetProperty("baz").GetProperty("foo").GetProperty("x").GetInt32(), Is.EqualTo(1)); + } + + [PlaywrightTest("page-evaluate-handle.spec.ts", "should accept object handle to unserializable value")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptObjectHandleToUnserializableValue() + { + var aHandle = await Page.EvaluateHandleAsync("() => Infinity"); + Assert.That(await Page.EvaluateAsync("e => Object.is(e, Infinity)", aHandle), Is.True); + } + + [PlaywrightTest("page-evaluate-handle.spec.ts", "should pass configurable args")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldPassConfigurableArgs() + { + JsonElement result = await Page.EvaluateAsync( + @"arg =>{ + if (arg.foo !== 42) + throw new Error('Not a 42'); + arg.foo = 17; + if (arg.foo !== 17) + throw new Error('Not 17'); + delete arg.foo; + if (arg.foo === 17) + throw new Error('Still 17'); + return arg; + }", + new { foo = 42 }); + + Assert.That(result.ToString(), Is.EqualTo("{}")); + } + + [PlaywrightTest("page-evaluate-handle.spec.ts", "should work with primitives")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithPrimitives() + { + var aHandle = await Page.EvaluateHandleAsync(@"() => { + window.FOO = 123; + return window; + }"); + Assert.That(await Page.EvaluateAsync("e => e.FOO", aHandle), Is.EqualTo(123)); + } + } +} diff --git a/src/Playwright.Tests/PageEvaluateTests.cs b/src/PlaywrightSharp.Tests/PageEvaluateTests.cs similarity index 65% rename from src/Playwright.Tests/PageEvaluateTests.cs rename to src/PlaywrightSharp.Tests/PageEvaluateTests.cs index 954b120458..a9a5457121 100644 --- a/src/Playwright.Tests/PageEvaluateTests.cs +++ b/src/PlaywrightSharp.Tests/PageEvaluateTests.cs @@ -1,704 +1,698 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Dynamic; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageEvaluateTests : PlaywrightSharpPageBaseTest - { - /// - public PageEvaluateTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-evaluate.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - int result = await Page.EvaluateAsync("() => 7 * 3"); - Assert.Equal(21, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should transfer NaN")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTransferNaN() - { - double result = await Page.EvaluateAsync("a => a", double.NaN); - Assert.Equal(double.NaN, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should transfer -0")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTransferNegative0() - { - double result = await Page.EvaluateAsync("a => a", -0d); - Assert.True(result.IsNegativeZero()); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should transfer Infinity")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTransferInfinity() - { - double result = await Page.EvaluateAsync("a => a", double.PositiveInfinity); - Assert.Equal(double.PositiveInfinity, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should transfer -Infinity")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTransferNegativeInfinity() - { - double result = await Page.EvaluateAsync("a => a", double.NegativeInfinity); - Assert.Equal(double.NegativeInfinity, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should roundtrip unserializable values")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRoundtripUnserializableValues() - { - dynamic value = new - { - infinity = double.PositiveInfinity, - nInfinity = double.NegativeInfinity, - nZero = -0d, - nan = double.NaN, - }; - - dynamic result = await Page.EvaluateAsync("value => value", value); - Assert.Equal(value.infinity, result.infinity); - Assert.Equal(value.nInfinity, result.nInfinity); - Assert.Equal(value.nZero, result.nZero); - Assert.Equal(value.nan, result.nan); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should roundtrip promise to value")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRoundtripPromiseToValue() - { - object result = await Page.EvaluateAsync("value => Promise.resolve(value)", null); - Assert.Null(result); - - double infitinity = await Page.EvaluateAsync("value => Promise.resolve(value)", double.PositiveInfinity); - Assert.Equal(double.PositiveInfinity, infitinity); - - double ninfitinity = await Page.EvaluateAsync("value => Promise.resolve(value)", double.NegativeInfinity); - Assert.Equal(double.NegativeInfinity, ninfitinity); - - double nzero = await Page.EvaluateAsync("value => Promise.resolve(value)", -0d); - Assert.Equal(-0, nzero); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should roundtrip promise to unserializable values")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRoundtripPromiseToUnserializableValues() - { - dynamic value = new - { - infinity = double.PositiveInfinity, - nInfinity = double.NegativeInfinity, - nZero = -0d, - nan = double.NaN, - }; - - dynamic result = await Page.EvaluateAsync("value => Promise.resolve(value)", value); - Assert.Equal(value.infinity, result.infinity); - Assert.Equal(value.nInfinity, result.nInfinity); - Assert.Equal(value.nZero, result.nZero); - Assert.Equal(value.nan, result.nan); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should transfer arrays")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTransferArrays() - { - int[] result = await Page.EvaluateAsync("a => a", new[] { 1, 2, 3 }); - Assert.Equal(new[] { 1, 2, 3 }, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should transfer arrays as arrays, not objects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTransferArraysAsArraysNotObjects() - { - bool result = await Page.EvaluateAsync("a => Array.isArray(a)", new[] { 1, 2, 3 }); - Assert.True(result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should transfer maps as empty objects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTransferMapsAsEmptyObjects() - { - dynamic result = await Page.EvaluateAsync("a => a.x.constructor.name + ' ' + JSON.stringify(a.x), {x: new Map([[1, 2]])}"); - Assert.Empty(TypeDescriptor.GetProperties(result)); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should modify global environment")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldModifyGlobalEnvironment() - { - await Page.EvaluateAsync("() => window.globalVar = 123"); - Assert.Equal(123, await Page.EvaluateAsync("globalVar")); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should evaluate in the page context")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEvaluateInThePageContext() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/global-var.html"); - Assert.Equal(123, await Page.EvaluateAsync("globalVar")); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should return undefined for objects with symbols")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnUndefinedForObjectsWithSymbols() - { - Assert.Equal(new object[] { null }, await Page.EvaluateAsync("() => [Symbol('foo4')]")); - Assert.Equal("{}", (await Page.EvaluateAsync(@"() => { - var a = { }; - a[Symbol('foo4')] = 42; - return a; - }")).ToJson()); - dynamic element = await Page.EvaluateAsync(@"() => { - return { foo: [{ a: Symbol('foo4') }] }; - }"); - - Assert.Null(element.foo[0].a); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should work with function shorthands")] - [Fact(Skip = "Not relevant for C#, js specific")] - public void ShouldWorkWithFunctionShorthands() - { - } - - [PlaywrightTest("page-evaluate.spec.ts", "should work with unicode chars")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithUnicodeChars() - { - int result = await Page.EvaluateAsync("a => a['中文字符']", new Dictionary { ["中文字符"] = 42 }); - Assert.Equal(42, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should throw when evaluation triggers reload")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowWhenEvaluationTriggersReload() - { - var exception = await Assert.ThrowsAsync(() => Page.EvaluateAsync(@"() => { - location.reload(); - return new Promise(() => { }); - }")); - Assert.Contains("navigation", exception.Message); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should await promise")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAwaitPromise() - { - int result = await Page.EvaluateAsync("() => Promise.resolve(8 * 7)"); - Assert.Equal(56, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should work right after framenavigated")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkRightAfterFrameNavigated() - { - Task frameEvaluation = null; - Page.FrameNavigated += (_, e) => - { - frameEvaluation = e.EvaluateAsync("() => 6 * 7"); - }; - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(42, await frameEvaluation); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should work right after a cross-origin navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkRightAfterACrossOriginNavigation() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Task frameEvaluation = null; - Page.FrameNavigated += (_, e) => - { - frameEvaluation = e.EvaluateAsync("() => 6 * 7"); - }; - await Page.GoToAsync(TestConstants.CrossProcessUrl + "/empty.html"); - Assert.Equal(42, await frameEvaluation); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should work from-inside an exposed function")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkFromInsideAnExposedFunction() - { - // Setup inpage callback, which calls Page.evaluate - await Page.ExposeFunctionAsync("callController", async (int a, int b) => await Page.EvaluateAsync("({a, b}) => a * b", new { a, b })); - int result = await Page.EvaluateAsync(@"async function() { - return await callController(9, 3); - }"); - Assert.Equal(27, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should reject promise with exception")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRejectPromiseWithException() - { - var exception = await Assert.ThrowsAsync(() => Page.EvaluateAsync("() => not_existing_object.property")); - Assert.Contains("not_existing_object", exception.Message); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should support thrown strings as error messages")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportThrownStringsAsErrorMessages() - { - var exception = await Assert.ThrowsAsync(() => Page.EvaluateAsync("() => { throw 'qwerty'; }")); - Assert.Contains("qwerty", exception.Message); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should support thrown numbers as error messages")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportThrownNumbersAsErrorMessages() - { - var exception = await Assert.ThrowsAsync(() => Page.EvaluateAsync("() => { throw 100500; }")); - Assert.Contains("100500", exception.Message); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should return complex objects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnComplexObjects() - { - var obj = new { foo = "bar!" }; - var result = await Page.EvaluateAsync("a => a", obj); - Assert.Equal("bar!", result.GetProperty("foo").GetString()); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should return NaN")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnNaN() - { - double result = await Page.EvaluateAsync("() => NaN"); - Assert.Equal(double.NaN, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should return -0")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnNegative0() - => Assert.True((await Page.EvaluateAsync("() => -0")).IsNegativeZero()); - - [PlaywrightTest("page-evaluate.spec.ts", "should return Infinity")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnInfinity() - { - double result = await Page.EvaluateAsync("() => Infinity"); - Assert.Equal(double.PositiveInfinity, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should return -Infinity")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnNegativeInfinity() - { - double result = await Page.EvaluateAsync("() => -Infinity"); - Assert.Equal(double.NegativeInfinity, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should work with overwritten Promise")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithOverwrittenPromise() - { - await Page.EvaluateAsync(@"const originalPromise = window.Promise; - class Promise2 { - static all(...arg) { - return wrap(originalPromise.all(...arg)); - } - static race(...arg) { - return wrap(originalPromise.race(...arg)); - } - static resolve(...arg) { - return wrap(originalPromise.resolve(...arg)); - } - constructor(f, r) { - this._promise = new originalPromise(f, r); - } - then(f, r) { - return wrap(this._promise.then(f, r)); - } - catch(f) { - return wrap(this._promise.catch(f)); - } - finally(f) { - return wrap(this._promise.finally(f)); - } - }; - const wrap = p => { - const result = new Promise2(() => {}, () => {}); - result._promise = p; - return result; - }; - window.Promise = Promise2; - window.__Promise2 = Promise2;"); - - Assert.True(await Page.EvaluateAsync(@"() => { - const p = Promise.all([Promise.race([]), new Promise(() => {}).then(() => {})]); - return p instanceof window.__Promise2; - }")); - Assert.Equal(42, await Page.EvaluateAsync("() => Promise.resolve(42)")); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should throw when passed more than one parameter")] - [Fact(Skip = "Not relevant for C#, js specific")] - public void ShouldThrowWhenPassedMoreThanOneParameter() - { - } - - [PlaywrightTest("page-evaluate.spec.ts", @"should accept ""undefined"" as one of multiple parameters")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptUndefinedAsOneOfMultipleParameters() - { - //C# will send nulls - bool result = await Page.EvaluateAsync(@"({a, b}) => { - console.log(a); - console.log(b); - return Object.is (a, null) && Object.is (b, 'foo') - }", new { a = (object)null, b = "foo" }); - Assert.True(result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should properly serialize undefined arguments")] - [Fact(Skip = "Not relevant for C#, js specific")] - public void ShouldProperlySerializeUndefinedArguments() - { - } - - [PlaywrightTest("page-evaluate.spec.ts", "should properly serialize undefined fields")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldProperlySerializeUndefinedFields() - { - dynamic result = await Page.EvaluateAsync("() => ({a: undefined})"); - Assert.Null(result.a); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should properly serialize null arguments")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldProperlySerializeNullArguments() - => Assert.Null(await Page.EvaluateAsync("x => x", null)); - - [PlaywrightTest("page-evaluate.spec.ts", "should properly serialize null fields")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldProperlySerializeNullFields() - { - dynamic result = await Page.EvaluateAsync("() => ({ a: null})"); - Assert.Null(result.a); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should return undefined for non-serializable objects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnUndefinedForNonSerializableObjects() - => Assert.Null(await Page.EvaluateAsync("() => window")); - - [PlaywrightTest("page-evaluate.spec.ts", "should fail for circular object")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailForCircularObject() - { - object result = await Page.EvaluateAsync(@"() => { - var a = { }; - var b = { a }; - a.b = b; - return a; - }"); - Assert.Null(result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should be able to throw a tricky error")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToThrowATrickyError() - { - var windowHandle = await Page.EvaluateHandleAsync("() => window"); - var exceptionText = await Assert.ThrowsAnyAsync(() => windowHandle.JsonValueAsync()); - var error = await Assert.ThrowsAnyAsync(() => Page.EvaluateAsync(@"errorText => { - throw new Error(errorText); - }", exceptionText.Message)); - Assert.Contains(exceptionText.Message, error.Message); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should accept a string")] - [Fact(Skip = "Not relevant for C#, js specific")] - public void ShouldAcceptAString() - { - } - - [PlaywrightTest("page-evaluate.spec.ts", "should accept a string with semi colons")] - [Fact(Skip = "Not relevant for C#, js specific")] - public void ShouldAcceptAStringWithSemiColons() - { - } - - [PlaywrightTest("page-evaluate.spec.ts", "should accept a string with comments")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptAStringWithComments() - { - int result = await Page.EvaluateAsync("2 + 5;\n// do some math!"); - Assert.Equal(7, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should accept element handle as an argument")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptElementHandleAsAnArgument() - { - await Page.SetContentAsync("
42
"); - var element = await Page.QuerySelectorAsync("section"); - string text = await Page.EvaluateAsync("e => e.textContent", element); - Assert.Equal("42", text); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should throw if underlying element was disposed")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowIfUnderlyingElementWasDisposed() - { - await Page.SetContentAsync("
39
"); - var element = await Page.QuerySelectorAsync("section"); - Assert.NotNull(element); - await element.DisposeAsync(); - - var exception = await Assert.ThrowsAnyAsync(() => Page.EvaluateAsync("e => e.textContent", element)); - Assert.Contains("JSHandle is disposed", exception.Message); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should simulate a user gesture")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSimulateAUserGesture() - { - bool result = await Page.EvaluateAsync(@"() => { - document.body.appendChild(document.createTextNode('test')); - document.execCommand('selectAll'); - return document.execCommand('copy'); - }"); - Assert.True(result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should throw a nice error after a navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowANiceErrorAfterANavigation() - { - var exceptionTask = Assert.ThrowsAsync(() => Page.EvaluateAsync("() => new Promise(f => window.__resolve = f)")); - await TaskUtils.WhenAll( - Page.WaitForNavigationAsync(), - Page.EvaluateAsync(@"() => { - window.location.reload(); - setTimeout(() => window.__resolve(42), 1000); - }") - ); - var exception = await exceptionTask; - Assert.Contains("navigation", exception.Message); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should not throw an error when evaluation does a navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotThrowAnErrorWhenEvaluationDoesANavigation() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); - int[] result = await Page.EvaluateAsync(@"() => { - window.location = '/empty.html'; - return [42]; - }"); - Assert.Equal(new[] { 42 }, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should not throw an error when evaluation does a synchronous navigation and returns an object")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task ShouldNotThrowAnErrorWhenEvaluationDoesASynchronousNavigationAndReturnsAnObject() - { - var result = await Page.EvaluateAsync(@"() => { - window.location.reload(); - return {a: 42}; - }"); - Assert.Equal(42, result.GetProperty("a").GetInt32()); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should not throw an error when evaluation does a synchronous navigation and returns an undefined")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task ShouldNotThrowAnErrorWhenEvaluationDoesASynchronousNavigationAndReturnsUndefined() - { - var result = await Page.EvaluateAsync(@"() => { - window.location.reload(); - return undefined; - }"); - Assert.Null(result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should transfer 100Mb of data from page to node.js")] - [Fact(Skip = "SKIP WIRE")] - public async Task ShouldTransfer100MbOfDataFromPageToNodeJs() - { - string a = await Page.EvaluateAsync("() => Array(100 * 1024 * 1024 + 1).join('a')"); - Assert.Equal(100 * 1024 * 1024, a.Length); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should throw error with detailed information on exception inside promise ")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowErrorWithDetailedInformationOnExceptionInsidePromise() - { - var exception = await Assert.ThrowsAsync(() => Page.EvaluateAsync(@"() => new Promise(() => { - throw new Error('Error in promise'); - })")); - Assert.Contains("Error in promise", exception.Message); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should work even when JSON is set to null")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkEvenWhenJSONIsSetToNull() - { - await Page.EvaluateAsync("() => { window.JSON.stringify = null; window.JSON = null; }"); - var result = await Page.EvaluateAsync("() => ({ abc: 123})"); - Assert.Equal(123, result.GetProperty("abc").GetInt32()); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should await promise from popup")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldAwaitPromiseFromPopup() - { - await Page.GoToAsync(TestConstants.EmptyPage); - - int result = await Page.EvaluateAsync(@"() => { - const win = window.open('about:blank'); - return new win.Promise(f => f(42)); - }"); - Assert.Equal(42, result); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should work with new Function() and CSP")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithNewFunctionAndCSP() - { - Server.SetCSP("/empty.html", "script-src" + TestConstants.ServerUrl); - await Page.GoToAsync(TestConstants.EmptyPage); - - Assert.True(await Page.EvaluateAsync("() => new Function('return true')()")); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should work with non-strict expressions")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithNonStrictExpressions() - { - Assert.Equal(3.14m, await Page.EvaluateAsync(@"() => { - y = 3.14; - return y; - }")); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should respect use strict expression")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRespectUseStrictExpression() - { - var exception = await Assert.ThrowsAsync(() => Page.EvaluateAsync(@"() => { - ""use strict""; - variableY = 3.14; - return variableY; - }")); - Assert.Contains("variableY", exception.Message); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should not leak utility script")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotLeakUtilityScript() - { - Assert.True(await Page.EvaluateAsync(@"() => this === window")); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should not leak handles")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotLeakHandles() - { - var exception = await Assert.ThrowsAsync(() => Page.EvaluateAsync(@"() => handles.length")); - Assert.Contains("handles", exception.Message); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should work with CSP")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithCSP() - { - Server.SetCSP("/empty.html", "script-src 'self'"); - await Page.GoToAsync(TestConstants.EmptyPage); - - Assert.Equal(4, await Page.EvaluateAsync("() => 2 + 2")); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should evaluate exception")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEvaluateException() - { - string exception = await Page.EvaluateAsync(@"() => { - return (function functionOnStack() { - return new Error('error message'); - })(); - }"); - Assert.Contains("Error: error message", exception); - Assert.Contains("functionOnStack", exception); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should evaluate exception")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEvaluateException2() - { - string exception = await Page.EvaluateAsync(@"() => new Error('error message')"); - Assert.Contains("Error: error message", exception); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should evaluate date")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEvaluateDate() - { - dynamic result = await Page.EvaluateAsync(@"() => ({ date: new Date('2020-05-27T01:31:38.506Z') })"); - Assert.Equal(new DateTime(2020, 05, 27, 1, 31, 38, 506), result.date); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should roundtrip date")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRoundtripDate() - { - var date = new DateTime(2020, 05, 27, 1, 31, 38, 506, DateTimeKind.Utc); - var result = await Page.EvaluateAsync(@"date => date", date); - Assert.Equal(date, result); - } - - [Fact(Skip = "The driver doesn't support this yet")] - public async Task ShouldTreatEcma2020AsFunctions() - => Assert.Equal("dario", await Page.EvaluateAsync( - @"() => { - const person = { name: 'dario' }; - return person?.name; - }")); - - [PlaywrightTest("page-evaluate.spec.ts", "should roundtrip regex")] - [Fact(Skip = "Regex is not native as in javascript")] - public void ShouldRoundtripRegex() - { - } - - [PlaywrightTest("page-evaluate.spec.ts", "should jsonValue() date")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldJsonValueDate() - { - var resultHandle = await Page.EvaluateHandleAsync(@"() => ({ date: new Date('2020-05-27T01:31:38.506Z') })"); - dynamic result = await resultHandle.JsonValueAsync(); - Assert.Equal(new DateTime(2020, 05, 27, 1, 31, 38, 506), result.date); - } - - [PlaywrightTest("page-evaluate.spec.ts", "should not use toJSON when evaluating")] - [Fact(Skip = "Skip for now")] - public void ShouldNotUseToJSONWhenEvaluating() - { - } - - [PlaywrightTest("page-evaluate.spec.ts", "should not use toJSON in jsonValue")] - [Fact(Skip = "Skip for now")] - public void ShouldNotUseToJSONInJsonValue() - { - } - } -} +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Dynamic; +using System.Text.Json; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageEvaluateTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-evaluate.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + int result = await Page.EvaluateAsync("() => 7 * 3"); + Assert.That(result, Is.EqualTo(21)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should transfer NaN")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTransferNaN() + { + double result = await Page.EvaluateAsync("a => a", double.NaN); + Assert.That(result, Is.EqualTo(double.NaN)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should transfer -0")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTransferNegative0() + { + double result = await Page.EvaluateAsync("a => a", -0d); + Assert.That(result.IsNegativeZero(), Is.True); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should transfer Infinity")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTransferInfinity() + { + double result = await Page.EvaluateAsync("a => a", double.PositiveInfinity); + Assert.That(result, Is.EqualTo(double.PositiveInfinity)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should transfer -Infinity")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTransferNegativeInfinity() + { + double result = await Page.EvaluateAsync("a => a", double.NegativeInfinity); + Assert.That(result, Is.EqualTo(double.NegativeInfinity)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should roundtrip unserializable values")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRoundtripUnserializableValues() + { + dynamic value = new + { + infinity = double.PositiveInfinity, + nInfinity = double.NegativeInfinity, + nZero = -0d, + nan = double.NaN, + }; + + dynamic result = await Page.EvaluateAsync("value => value", value); + Assert.That(result.infinity, Is.EqualTo(value.infinity)); + Assert.That(result.nInfinity, Is.EqualTo(value.nInfinity)); + Assert.That(result.nZero, Is.EqualTo(value.nZero)); + Assert.That(result.nan, Is.EqualTo(value.nan)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should roundtrip promise to value")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRoundtripPromiseToValue() + { + object result = await Page.EvaluateAsync("value => Promise.resolve(value)", null); + Assert.That(result, Is.Null); + + double infitinity = await Page.EvaluateAsync("value => Promise.resolve(value)", double.PositiveInfinity); + Assert.That(infitinity, Is.EqualTo(double.PositiveInfinity)); + + double ninfitinity = await Page.EvaluateAsync("value => Promise.resolve(value)", double.NegativeInfinity); + Assert.That(ninfitinity, Is.EqualTo(double.NegativeInfinity)); + + double nzero = await Page.EvaluateAsync("value => Promise.resolve(value)", -0d); + Assert.That(nzero, Is.EqualTo(-0)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should roundtrip promise to unserializable values")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRoundtripPromiseToUnserializableValues() + { + dynamic value = new + { + infinity = double.PositiveInfinity, + nInfinity = double.NegativeInfinity, + nZero = -0d, + nan = double.NaN, + }; + + dynamic result = await Page.EvaluateAsync("value => Promise.resolve(value)", value); + Assert.That(result.infinity, Is.EqualTo(value.infinity)); + Assert.That(result.nInfinity, Is.EqualTo(value.nInfinity)); + Assert.That(result.nZero, Is.EqualTo(value.nZero)); + Assert.That(result.nan, Is.EqualTo(value.nan)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should transfer arrays")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTransferArrays() + { + int[] result = await Page.EvaluateAsync("a => a", new[] { 1, 2, 3 }); + Assert.That(result, Is.EqualTo(new[] { 1, 2, 3 })); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should transfer arrays as arrays, not objects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTransferArraysAsArraysNotObjects() + { + bool result = await Page.EvaluateAsync("a => Array.isArray(a)", new[] { 1, 2, 3 }); + Assert.That(result, Is.True); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should transfer maps as empty objects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTransferMapsAsEmptyObjects() + { + dynamic result = await Page.EvaluateAsync("a => a.x.constructor.name + ' ' + JSON.stringify(a.x), {x: new Map([[1, 2]])}"); + Assert.That(TypeDescriptor.GetProperties(result), Is.Empty); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should modify global environment")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldModifyGlobalEnvironment() + { + await Page.EvaluateAsync("() => window.globalVar = 123"); + Assert.That(await Page.EvaluateAsync("globalVar"), Is.EqualTo(123)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should evaluate in the page context")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEvaluateInThePageContext() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/global-var.html"); + Assert.That(await Page.EvaluateAsync("globalVar"), Is.EqualTo(123)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should return undefined for objects with symbols")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnUndefinedForObjectsWithSymbols() + { + Assert.That(await Page.EvaluateAsync("() => [Symbol('foo4')]"), Is.EqualTo(new object[] { null })); + Assert.That((await Page.EvaluateAsync(@"() => { + var a = { }; + a[Symbol('foo4')] = 42; + return a; + }")).ToJson(), Is.EqualTo("{}")); + dynamic element = await Page.EvaluateAsync(@"() => { + return { foo: [{ a: Symbol('foo4') }] }; + }"); + + Assert.That(element.foo[0].a, Is.Null); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should work with function shorthands")] + [Test, Ignore("Not relevant for C#, js specific")] + public void ShouldWorkWithFunctionShorthands() + { + } + + [PlaywrightTest("page-evaluate.spec.ts", "should work with unicode chars")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithUnicodeChars() + { + int result = await Page.EvaluateAsync("a => a['中文字符']", new Dictionary { ["中文字符"] = 42 }); + Assert.That(result, Is.EqualTo(42)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should throw when evaluation triggers reload")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowWhenEvaluationTriggersReload() + { + var exception = Assert.ThrowsAsync(() => Page.EvaluateAsync(@"() => { + location.reload(); + return new Promise(() => { }); + }")); + Assert.That(exception.Message, Does.Contain("navigation")); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should await promise")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAwaitPromise() + { + int result = await Page.EvaluateAsync("() => Promise.resolve(8 * 7)"); + Assert.That(result, Is.EqualTo(56)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should work right after framenavigated")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkRightAfterFrameNavigated() + { + Task frameEvaluation = null; + Page.FrameNavigated += (_, e) => + { + frameEvaluation = e.EvaluateAsync("() => 6 * 7"); + }; + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await frameEvaluation, Is.EqualTo(42)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should work right after a cross-origin navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkRightAfterACrossOriginNavigation() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Task frameEvaluation = null; + Page.FrameNavigated += (_, e) => + { + frameEvaluation = e.EvaluateAsync("() => 6 * 7"); + }; + await Page.GoToAsync(TestConstants.CrossProcessUrl + "/empty.html"); + Assert.That(await frameEvaluation, Is.EqualTo(42)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should work from-inside an exposed function")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkFromInsideAnExposedFunction() + { + // Setup inpage callback, which calls Page.evaluate + await Page.ExposeFunctionAsync("callController", async (int a, int b) => await Page.EvaluateAsync("({a, b}) => a * b", new { a, b })); + int result = await Page.EvaluateAsync(@"async function() { + return await callController(9, 3); + }"); + Assert.That(result, Is.EqualTo(27)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should reject promise with exception")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRejectPromiseWithException() + { + var exception = Assert.ThrowsAsync(() => Page.EvaluateAsync("() => not_existing_object.property")); + Assert.That(exception.Message, Does.Contain("not_existing_object")); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should support thrown strings as error messages")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportThrownStringsAsErrorMessages() + { + var exception = Assert.ThrowsAsync(() => Page.EvaluateAsync("() => { throw 'qwerty'; }")); + Assert.That(exception.Message, Does.Contain("qwerty")); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should support thrown numbers as error messages")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportThrownNumbersAsErrorMessages() + { + var exception = Assert.ThrowsAsync(() => Page.EvaluateAsync("() => { throw 100500; }")); + Assert.That(exception.Message, Does.Contain("100500")); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should return complex objects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnComplexObjects() + { + var obj = new { foo = "bar!" }; + var result = await Page.EvaluateAsync("a => a", obj); + Assert.That(result.GetProperty("foo").GetString(), Is.EqualTo("bar!")); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should return NaN")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnNaN() + { + double result = await Page.EvaluateAsync("() => NaN"); + Assert.That(result, Is.EqualTo(double.NaN)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should return -0")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnNegative0() + => Assert.That((await Page.EvaluateAsync("() => -0")).IsNegativeZero(), Is.True); + + [PlaywrightTest("page-evaluate.spec.ts", "should return Infinity")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnInfinity() + { + double result = await Page.EvaluateAsync("() => Infinity"); + Assert.That(result, Is.EqualTo(double.PositiveInfinity)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should return -Infinity")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnNegativeInfinity() + { + double result = await Page.EvaluateAsync("() => -Infinity"); + Assert.That(result, Is.EqualTo(double.NegativeInfinity)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should work with overwritten Promise")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithOverwrittenPromise() + { + await Page.EvaluateAsync(@"const originalPromise = window.Promise; + class Promise2 { + static all(...arg) { + return wrap(originalPromise.all(...arg)); + } + static race(...arg) { + return wrap(originalPromise.race(...arg)); + } + static resolve(...arg) { + return wrap(originalPromise.resolve(...arg)); + } + constructor(f, r) { + this._promise = new originalPromise(f, r); + } + then(f, r) { + return wrap(this._promise.then(f, r)); + } + catch(f) { + return wrap(this._promise.catch(f)); + } + finally(f) { + return wrap(this._promise.finally(f)); + } + }; + const wrap = p => { + const result = new Promise2(() => {}, () => {}); + result._promise = p; + return result; + }; + window.Promise = Promise2; + window.__Promise2 = Promise2;"); + + Assert.That(await Page.EvaluateAsync(@"() => { + const p = Promise.all([Promise.race([]), new Promise(() => {}).then(() => {})]); + return p instanceof window.__Promise2; + }"), Is.True); + Assert.That(await Page.EvaluateAsync("() => Promise.resolve(42)"), Is.EqualTo(42)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should throw when passed more than one parameter")] + [Test, Ignore("Not relevant for C#, js specific")] + public void ShouldThrowWhenPassedMoreThanOneParameter() + { + } + + [PlaywrightTest("page-evaluate.spec.ts", @"should accept ""undefined"" as one of multiple parameters")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptUndefinedAsOneOfMultipleParameters() + { + //C# will send nulls + bool result = await Page.EvaluateAsync(@"({a, b}) => { + console.log(a); + console.log(b); + return Object.is (a, null) && Object.is (b, 'foo') + }", new { a = (object)null, b = "foo" }); + Assert.That(result, Is.True); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should properly serialize undefined arguments")] + [Test, Ignore("Not relevant for C#, js specific")] + public void ShouldProperlySerializeUndefinedArguments() + { + } + + [PlaywrightTest("page-evaluate.spec.ts", "should properly serialize undefined fields")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldProperlySerializeUndefinedFields() + { + dynamic result = await Page.EvaluateAsync("() => ({a: undefined})"); + Assert.That(result.a, Is.Null); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should properly serialize null arguments")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldProperlySerializeNullArguments() + => Assert.That(await Page.EvaluateAsync("x => x", null), Is.Null); + + [PlaywrightTest("page-evaluate.spec.ts", "should properly serialize null fields")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldProperlySerializeNullFields() + { + dynamic result = await Page.EvaluateAsync("() => ({ a: null})"); + Assert.That(result.a, Is.Null); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should return undefined for non-serializable objects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnUndefinedForNonSerializableObjects() + => Assert.That(await Page.EvaluateAsync("() => window"), Is.Null); + + [PlaywrightTest("page-evaluate.spec.ts", "should fail for circular object")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailForCircularObject() + { + object result = await Page.EvaluateAsync(@"() => { + var a = { }; + var b = { a }; + a.b = b; + return a; + }"); + Assert.That(result, Is.Null); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should be able to throw a tricky error")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToThrowATrickyError() + { + var windowHandle = await Page.EvaluateHandleAsync("() => window"); + var exceptionText = Assert.CatchAsync(() => windowHandle.JsonValueAsync()); + var error = Assert.CatchAsync(() => Page.EvaluateAsync(@"errorText => { + throw new Error(errorText); + }", exceptionText.Message)); + Assert.That(error.Message, Does.Contain(exceptionText.Message)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should accept a string")] + [Test, Ignore("Not relevant for C#, js specific")] + public void ShouldAcceptAString() + { + } + + [PlaywrightTest("page-evaluate.spec.ts", "should accept a string with semi colons")] + [Test, Ignore("Not relevant for C#, js specific")] + public void ShouldAcceptAStringWithSemiColons() + { + } + + [PlaywrightTest("page-evaluate.spec.ts", "should accept a string with comments")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptAStringWithComments() + { + int result = await Page.EvaluateAsync("2 + 5;\n// do some math!"); + Assert.That(result, Is.EqualTo(7)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should accept element handle as an argument")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptElementHandleAsAnArgument() + { + await Page.SetContentAsync("
42
"); + var element = await Page.QuerySelectorAsync("section"); + string text = await Page.EvaluateAsync("e => e.textContent", element); + Assert.That(text, Is.EqualTo("42")); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should throw if underlying element was disposed")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowIfUnderlyingElementWasDisposed() + { + await Page.SetContentAsync("
39
"); + var element = await Page.QuerySelectorAsync("section"); + Assert.That(element, Is.Not.Null); + await element.DisposeAsync(); + + var exception = Assert.CatchAsync(() => Page.EvaluateAsync("e => e.textContent", element)); + Assert.That(exception.Message, Does.Contain("JSHandle is disposed")); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should simulate a user gesture")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSimulateAUserGesture() + { + bool result = await Page.EvaluateAsync(@"() => { + document.body.appendChild(document.createTextNode('test')); + document.execCommand('selectAll'); + return document.execCommand('copy'); + }"); + Assert.That(result, Is.True); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should throw a nice error after a navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowANiceErrorAfterANavigation() + { + var evaluateTask = Page.EvaluateAsync("() => new Promise(f => window.__resolve = f)"); + await TaskUtils.WhenAll( + Page.WaitForNavigationAsync(), + Page.EvaluateAsync(@"() => { + window.location.reload(); + setTimeout(() => window.__resolve(42), 1000); + }") + ); + var exception = Assert.CatchAsync(() => evaluateTask); + Assert.That(exception.Message, Does.Contain("navigation")); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should not throw an error when evaluation does a navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotThrowAnErrorWhenEvaluationDoesANavigation() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); + int[] result = await Page.EvaluateAsync(@"() => { + window.location = '/empty.html'; + return [42]; + }"); + Assert.That(result, Is.EqualTo(new[] { 42 })); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should not throw an error when evaluation does a synchronous navigation and returns an object")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task ShouldNotThrowAnErrorWhenEvaluationDoesASynchronousNavigationAndReturnsAnObject() + { + var result = await Page.EvaluateAsync(@"() => { + window.location.reload(); + return {a: 42}; + }"); + Assert.That(result.GetProperty("a").GetInt32(), Is.EqualTo(42)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should not throw an error when evaluation does a synchronous navigation and returns an undefined")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task ShouldNotThrowAnErrorWhenEvaluationDoesASynchronousNavigationAndReturnsUndefined() + { + var result = await Page.EvaluateAsync(@"() => { + window.location.reload(); + return undefined; + }"); + Assert.That(result, Is.Null); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should transfer 100Mb of data from page to node.js")] + [Test, Ignore("SKIP WIRE")] + public async Task ShouldTransfer100MbOfDataFromPageToNodeJs() + { + string a = await Page.EvaluateAsync("() => Array(100 * 1024 * 1024 + 1).join('a')"); + Assert.That(a.Length, Is.EqualTo(100 * 1024 * 1024)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should throw error with detailed information on exception inside promise ")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowErrorWithDetailedInformationOnExceptionInsidePromise() + { + var exception = Assert.ThrowsAsync(() => Page.EvaluateAsync(@"() => new Promise(() => { + throw new Error('Error in promise'); + })")); + Assert.That(exception.Message, Does.Contain("Error in promise")); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should work even when JSON is set to null")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkEvenWhenJSONIsSetToNull() + { + await Page.EvaluateAsync("() => { window.JSON.stringify = null; window.JSON = null; }"); + var result = await Page.EvaluateAsync("() => ({ abc: 123})"); + Assert.That(result.GetProperty("abc").GetInt32(), Is.EqualTo(123)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should await promise from popup")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldAwaitPromiseFromPopup() + { + await Page.GoToAsync(TestConstants.EmptyPage); + + int result = await Page.EvaluateAsync(@"() => { + const win = window.open('about:blank'); + return new win.Promise(f => f(42)); + }"); + Assert.That(result, Is.EqualTo(42)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should work with new Function() and CSP")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithNewFunctionAndCSP() + { + Server.SetCSP("/empty.html", "script-src" + TestConstants.ServerUrl); + await Page.GoToAsync(TestConstants.EmptyPage); + + Assert.That(await Page.EvaluateAsync("() => new Function('return true')()"), Is.True); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should work with non-strict expressions")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithNonStrictExpressions() + { + Assert.That(await Page.EvaluateAsync(@"() => { + y = 3.14; + return y; + }"), Is.EqualTo(3.14m)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should respect use strict expression")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRespectUseStrictExpression() + { + var exception = Assert.ThrowsAsync(() => Page.EvaluateAsync(@"() => { + ""use strict""; + variableY = 3.14; + return variableY; + }")); + Assert.That(exception.Message, Does.Contain("variableY")); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should not leak utility script")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotLeakUtilityScript() + { + Assert.That(await Page.EvaluateAsync(@"() => this === window"), Is.True); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should not leak handles")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotLeakHandles() + { + var exception = Assert.ThrowsAsync(() => Page.EvaluateAsync(@"() => handles.length")); + Assert.That(exception.Message, Does.Contain("handles")); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should work with CSP")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithCSP() + { + Server.SetCSP("/empty.html", "script-src 'self'"); + await Page.GoToAsync(TestConstants.EmptyPage); + + Assert.That(await Page.EvaluateAsync("() => 2 + 2"), Is.EqualTo(4)); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should evaluate exception")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEvaluateException() + { + string exception = await Page.EvaluateAsync(@"() => { + return (function functionOnStack() { + return new Error('error message'); + })(); + }"); + Assert.That(exception, Does.Contain("Error: error message")); + Assert.That(exception, Does.Contain("functionOnStack")); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should evaluate exception")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEvaluateException2() + { + string exception = await Page.EvaluateAsync(@"() => new Error('error message')"); + Assert.That(exception, Does.Contain("Error: error message")); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should evaluate date")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEvaluateDate() + { + dynamic result = await Page.EvaluateAsync(@"() => ({ date: new Date('2020-05-27T01:31:38.506Z') })"); + Assert.That(result.date, Is.EqualTo(new DateTime(2020, 05, 27, 1, 31, 38, 506))); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should roundtrip date")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRoundtripDate() + { + var date = new DateTime(2020, 05, 27, 1, 31, 38, 506, DateTimeKind.Utc); + var result = await Page.EvaluateAsync(@"date => date", date); + Assert.That(result, Is.EqualTo(date)); + } + + [Test, Ignore("The driver doesn't support this yet")] + public async Task ShouldTreatEcma2020AsFunctions() + => Assert.That(await Page.EvaluateAsync( + @"() => { + const person = { name: 'dario' }; + return person?.name; + }"), Is.EqualTo("dario")); + + [PlaywrightTest("page-evaluate.spec.ts", "should roundtrip regex")] + [Test, Ignore("Regex is not native as in javascript")] + public void ShouldRoundtripRegex() + { + } + + [PlaywrightTest("page-evaluate.spec.ts", "should jsonValue() date")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldJsonValueDate() + { + var resultHandle = await Page.EvaluateHandleAsync(@"() => ({ date: new Date('2020-05-27T01:31:38.506Z') })"); + dynamic result = await resultHandle.JsonValueAsync(); + Assert.That(result.date, Is.EqualTo(new DateTime(2020, 05, 27, 1, 31, 38, 506))); + } + + [PlaywrightTest("page-evaluate.spec.ts", "should not use toJSON when evaluating")] + [Test, Ignore("Skip for now")] + public void ShouldNotUseToJSONWhenEvaluating() + { + } + + [PlaywrightTest("page-evaluate.spec.ts", "should not use toJSON in jsonValue")] + [Test, Ignore("Skip for now")] + public void ShouldNotUseToJSONInJsonValue() + { + } + + } +} diff --git a/src/Playwright.Tests/PageEventConsoleTests.cs b/src/PlaywrightSharp.Tests/PageEventConsoleTests.cs similarity index 72% rename from src/Playwright.Tests/PageEventConsoleTests.cs rename to src/PlaywrightSharp.Tests/PageEventConsoleTests.cs index 57bf75a424..1040cc3110 100644 --- a/src/Playwright.Tests/PageEventConsoleTests.cs +++ b/src/PlaywrightSharp.Tests/PageEventConsoleTests.cs @@ -1,154 +1,147 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageEventConsoleTests : PlaywrightSharpPageBaseTest - { - /// - public PageEventConsoleTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-event-console.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - IConsoleMessage message = null; - void EventHandler(object sender, IConsoleMessage e) - { - message = e; - Page.Console -= EventHandler; - } - Page.Console += EventHandler; - await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.Console), - Page.EvaluateAsync("() => console.log('hello', 5, { foo: 'bar'})")); - - Assert.Equal("hello 5 JSHandle@object", message.Text); - Assert.Equal("log", message.Type); - Assert.Equal("hello", await message.Args.ElementAt(0).JsonValueAsync()); - Assert.Equal(5, await message.Args.ElementAt(1).JsonValueAsync()); - Assert.Equal("bar", (await message.Args.ElementAt(2).JsonValueAsync()).GetProperty("foo").GetString()); - } - - [PlaywrightTest("page-event-console.spec.ts", "should emit same log twice")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEmitSameLogTwice() - { - var messages = new List(); - - Page.Console += (_, e) => messages.Add(e.Text); - await Page.EvaluateAsync("() => { for (let i = 0; i < 2; ++i ) console.log('hello'); } "); - - Assert.Equal(new[] { "hello", "hello" }, messages.ToArray()); - } - - [PlaywrightTest("page-event-console.spec.ts", "should work for different console API calls")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForDifferentConsoleAPICalls() - { - var messages = new List(); - Page.Console += (_, e) => messages.Add(e); - // All console events will be reported before `Page.evaluate` is finished. - await Page.EvaluateAsync(@"() => { - // A pair of time/timeEnd generates only one Console API call. - console.time('calling console.time'); - console.timeEnd('calling console.time'); - console.trace('calling console.trace'); - console.dir('calling console.dir'); - console.warn('calling console.warn'); - console.error('calling console.error'); - console.log(Promise.resolve('should not wait until resolved!')); - }"); - Assert.Equal(new[] { "timeEnd", "trace", "dir", "warning", "error", "log" }, messages.Select(msg => msg.Type)); - Assert.Contains("calling console.time", messages[0].Text); - Assert.Equal(new[] - { - "calling console.trace", - "calling console.dir", - "calling console.warn", - "calling console.error", - "JSHandle@promise" - }, messages.Skip(1).Select(msg => msg.Text)); - } - - [PlaywrightTest("page-event-console.spec.ts", "should not fail for window object")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotFailForWindowObject() - { - IConsoleMessage message = null; - void EventHandler(object sender, IConsoleMessage e) - { - message = e; - Page.Console -= EventHandler; - } - Page.Console += EventHandler; - await TaskUtils.WhenAll( - Page.EvaluateAsync("() => console.error(window)"), - Page.WaitForEventAsync(PageEvent.Console) - ); - Assert.Equal("JSHandle@object", message.Text); - } - - [PlaywrightTest("page-event-console.spec.ts", "should trigger correct Log")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTriggerCorrectLog() - { - await Page.GoToAsync("about:blank"); - var (messageEvent, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.Console), - Page.EvaluateAsync("async url => fetch(url).catch (e => { })", TestConstants.EmptyPage) - ); - Assert.Contains("Access-Control-Allow-Origin", messageEvent.Text); - Assert.Equal("error", messageEvent.Type); - } - - [PlaywrightTest("page-event-console.spec.ts", "should have location for console API calls")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHaveLocationForConsoleAPICalls() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var (messageEvent, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.Console), - Page.GoToAsync(TestConstants.ServerUrl + "/consolelog.html") - ); - Assert.Equal("yellow", messageEvent.Text); - Assert.Equal("log", messageEvent.Type); - string location = messageEvent.Location; - } - - [PlaywrightTest("page-event-console.spec.ts", "should not throw when there are console messages in detached iframes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotThrowWhenThereAreConsoleMessagesInDetachedIframes() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var (popup, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.Popup), - Page.EvaluateAsync(@"async () => - { - // 1. Create a popup that Playwright is not connected to. - const win = window.open(''); - window._popup = win; - if (window.document.readyState !== 'complete') - await new Promise(f => window.addEventListener('load', f)); - // 2. In this popup, create an iframe that console.logs a message. - win.document.body.innerHTML = ``; - const frame = win.document.querySelector('iframe'); - if (!frame.contentDocument || frame.contentDocument.readyState !== 'complete') - await new Promise(f => frame.addEventListener('load', f)); - // 3. After that, remove the iframe. - frame.remove(); - }")); - // 4. Connect to the popup and make sure it doesn't throw. - Assert.Equal(2, await popup.EvaluateAsync("1 + 1")); - } - } -} +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageEventConsoleTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-event-console.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + IConsoleMessage message = null; + void EventHandler(object sender, IConsoleMessage e) + { + message = e; + Page.Console -= EventHandler; + } + Page.Console += EventHandler; + await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.Console), + Page.EvaluateAsync("() => console.log('hello', 5, { foo: 'bar'})")); + + Assert.That(message.Text, Is.EqualTo("hello 5 JSHandle@object")); + Assert.That(message.Type, Is.EqualTo("log")); + Assert.That(await message.Args.ElementAt(0).JsonValueAsync(), Is.EqualTo("hello")); + Assert.That(await message.Args.ElementAt(1).JsonValueAsync(), Is.EqualTo(5)); + Assert.That((await message.Args.ElementAt(2).JsonValueAsync()).GetProperty("foo").GetString(), Is.EqualTo("bar")); + } + + [PlaywrightTest("page-event-console.spec.ts", "should emit same log twice")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEmitSameLogTwice() + { + var messages = new List(); + + Page.Console += (_, e) => messages.Add(e.Text); + await Page.EvaluateAsync("() => { for (let i = 0; i < 2; ++i ) console.log('hello'); } "); + + Assert.That(messages.ToArray(), Is.EqualTo(new[] { "hello", "hello" })); + } + + [PlaywrightTest("page-event-console.spec.ts", "should work for different console API calls")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForDifferentConsoleAPICalls() + { + var messages = new List(); + Page.Console += (_, e) => messages.Add(e); + // All console events will be reported before `Page.evaluate` is finished. + await Page.EvaluateAsync(@"() => { + // A pair of time/timeEnd generates only one Console API call. + console.time('calling console.time'); + console.timeEnd('calling console.time'); + console.trace('calling console.trace'); + console.dir('calling console.dir'); + console.warn('calling console.warn'); + console.error('calling console.error'); + console.log(Promise.resolve('should not wait until resolved!')); + }"); + Assert.That(messages.Select(msg => msg.Type), Is.EqualTo(new[] { "timeEnd", "trace", "dir", "warning", "error", "log" })); + Assert.That(messages[0].Text, Does.Contain("calling console.time")); + Assert.That(messages.Skip(1).Select(msg => msg.Text), Is.EqualTo(new[] + { + "calling console.trace", + "calling console.dir", + "calling console.warn", + "calling console.error", + "JSHandle@promise" + })); + } + + [PlaywrightTest("page-event-console.spec.ts", "should not fail for window object")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotFailForWindowObject() + { + IConsoleMessage message = null; + void EventHandler(object sender, IConsoleMessage e) + { + message = e; + Page.Console -= EventHandler; + } + Page.Console += EventHandler; + await TaskUtils.WhenAll( + Page.EvaluateAsync("() => console.error(window)"), + Page.WaitForEventAsync(PageEvent.Console) + ); + Assert.That(message.Text, Is.EqualTo("JSHandle@object")); + } + + [PlaywrightTest("page-event-console.spec.ts", "should trigger correct Log")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTriggerCorrectLog() + { + await Page.GoToAsync("about:blank"); + var (messageEvent, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.Console), + Page.EvaluateAsync("async url => fetch(url).catch (e => { })", TestConstants.EmptyPage) + ); + Assert.That(messageEvent.Text, Does.Contain("Access-Control-Allow-Origin")); + Assert.That(messageEvent.Type, Is.EqualTo("error")); + } + + [PlaywrightTest("page-event-console.spec.ts", "should have location for console API calls")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHaveLocationForConsoleAPICalls() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var (messageEvent, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.Console), + Page.GoToAsync(TestConstants.ServerUrl + "/consolelog.html") + ); + Assert.That(messageEvent.Text, Is.EqualTo("yellow")); + Assert.That(messageEvent.Type, Is.EqualTo("log")); + string location = messageEvent.Location; + } + + [PlaywrightTest("page-event-console.spec.ts", "should not throw when there are console messages in detached iframes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotThrowWhenThereAreConsoleMessagesInDetachedIframes() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var (popup, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.Popup), + Page.EvaluateAsync(@"async () => + { + // 1. Create a popup that Playwright is not connected to. + const win = window.open(''); + window._popup = win; + if (window.document.readyState !== 'complete') + await new Promise(f => window.addEventListener('load', f)); + // 2. In this popup, create an iframe that console.logs a message. + win.document.body.innerHTML = ``; + const frame = win.document.querySelector('iframe'); + if (!frame.contentDocument || frame.contentDocument.readyState !== 'complete') + await new Promise(f => frame.addEventListener('load', f)); + // 3. After that, remove the iframe. + frame.remove(); + }")); + // 4. Connect to the popup and make sure it doesn't throw. + Assert.That(await popup.EvaluateAsync("1 + 1"), Is.EqualTo(2)); + } + } +} diff --git a/src/Playwright.Tests/PageEventCrashTests.cs b/src/PlaywrightSharp.Tests/PageEventCrashTests.cs similarity index 76% rename from src/Playwright.Tests/PageEventCrashTests.cs rename to src/PlaywrightSharp.Tests/PageEventCrashTests.cs index bdd2fcf550..f851b9d1a3 100644 --- a/src/Playwright.Tests/PageEventCrashTests.cs +++ b/src/PlaywrightSharp.Tests/PageEventCrashTests.cs @@ -1,94 +1,87 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageEventCrashTests : PlaywrightSharpPageBaseTest - { - /// - public PageEventCrashTests(ITestOutputHelper output) : base(output) - { - } - - // We skip all browser because crash uses internals. - [PlaywrightTest("page-event-crash.spec.ts", "should emit crash event when page crashes")] - [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] - public async Task ShouldEmitCrashEventWhenPageCrashes() - { - await Page.SetContentAsync("
This page should crash
"); - var crashTask = Page.WaitForEventAsync(PageEvent.Crash); - await CrashAsync(Page); - await crashTask.WithTimeout(TestConstants.DefaultTaskTimeout); - } - - // We skip all browser because crash uses internals. - [PlaywrightTest("page-event-crash.spec.ts", "should throw on any action after page crashes")] - [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] - public async Task ShouldThrowOnAnyActionAfterPageCrashes() - { - await Page.SetContentAsync("
This page should crash
"); - var crashTask = Page.WaitForEventAsync(PageEvent.Crash); - await CrashAsync(Page); - await crashTask.WithTimeout(TestConstants.DefaultTaskTimeout); - var exception = await Assert.ThrowsAnyAsync(() => Page.EvaluateAsync("() => {}")); - Assert.Contains("crash", exception.Message); - } - - // We skip all browser because crash uses internals. - [PlaywrightTest("page-event-crash.spec.ts", "should cancel waitForEvent when page crashes")] - [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] - public async Task ShouldCancelWaitForEventWhenPageCrashes() - { - await Page.SetContentAsync("
This page should crash
"); - var responseTask = Page.WaitForEventAsync(PageEvent.Response); - await CrashAsync(Page); - var exception = await Assert.ThrowsAnyAsync(() => responseTask.WithTimeout(TestConstants.DefaultTaskTimeout)); - Assert.Contains("Page crashed", exception.Message); - } - - // We skip all browser because crash uses internals. - [PlaywrightTest("page-event-crash.spec.ts", "should cancel navigation when page crashes")] - [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] - public async Task ShouldCancelNavigationWhenPageCrashes() - { - await Page.SetContentAsync("
This page should crash
"); - Server.SetRoute("/one-style.css", _ => Task.Delay(2000)); - var task = Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); - await Page.WaitForNavigationAsync(WaitUntilState.DOMContentLoaded); - - await CrashAsync(Page); - var exception = await Assert.ThrowsAnyAsync(() => task); - Assert.Contains("Navigation failed because page crashed", exception.Message); - } - - // We skip all browser because crash uses internals. - [PlaywrightTest("page-event-crash.spec.ts", "should be able to close context when page crashes")] - [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] - public async Task ShouldBeAbleToCloseContextWhenPageCrashes() - { - await Page.SetContentAsync("
This page should crash
"); - var crashTask = Page.WaitForEventAsync(PageEvent.Crash); - await CrashAsync(Page); - await crashTask.WithTimeout(TestConstants.DefaultTaskTimeout); - await Page.Context.CloseAsync(); - } - - private async Task CrashAsync(IPage page) - { - try - { - await page.GoToAsync("chrome://crash"); - } - catch - { - } - } - } -} +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageEventCrashTests : PlaywrightSharpPageBaseTest + { + // We skip all browser because crash uses internals. + [PlaywrightTest("page-event-crash.spec.ts", "should emit crash event when page crashes")] + [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] + public async Task ShouldEmitCrashEventWhenPageCrashes() + { + await Page.SetContentAsync("
This page should crash
"); + var crashTask = Page.WaitForEventAsync(PageEvent.Crash); + await CrashAsync(Page); + await crashTask.WithTimeout(TestConstants.DefaultTaskTimeout); + } + + // We skip all browser because crash uses internals. + [PlaywrightTest("page-event-crash.spec.ts", "should throw on any action after page crashes")] + [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] + public async Task ShouldThrowOnAnyActionAfterPageCrashes() + { + await Page.SetContentAsync("
This page should crash
"); + var crashTask = Page.WaitForEventAsync(PageEvent.Crash); + await CrashAsync(Page); + await crashTask.WithTimeout(TestConstants.DefaultTaskTimeout); + var exception = Assert.CatchAsync(() => Page.EvaluateAsync("() => {}")); + Assert.That(exception.Message, Does.Contain("crash")); + } + + // We skip all browser because crash uses internals. + [PlaywrightTest("page-event-crash.spec.ts", "should cancel waitForEvent when page crashes")] + [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] + public async Task ShouldCancelWaitForEventWhenPageCrashes() + { + await Page.SetContentAsync("
This page should crash
"); + var responseTask = Page.WaitForEventAsync(PageEvent.Response); + await CrashAsync(Page); + var exception = Assert.CatchAsync(() => responseTask.WithTimeout(TestConstants.DefaultTaskTimeout)); + Assert.That(exception.Message, Does.Contain("Page crashed")); + } + + // We skip all browser because crash uses internals. + [PlaywrightTest("page-event-crash.spec.ts", "should cancel navigation when page crashes")] + [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] + public async Task ShouldCancelNavigationWhenPageCrashes() + { + await Page.SetContentAsync("
This page should crash
"); + Server.SetRoute("/one-style.css", _ => Task.Delay(2000)); + var task = Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); + await Page.WaitForNavigationAsync(WaitUntilState.DOMContentLoaded); + + await CrashAsync(Page); + var exception = Assert.CatchAsync(() => task); + Assert.That(exception.Message, Does.Contain("Navigation failed because page crashed")); + } + + // We skip all browser because crash uses internals. + [PlaywrightTest("page-event-crash.spec.ts", "should be able to close context when page crashes")] + [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] + public async Task ShouldBeAbleToCloseContextWhenPageCrashes() + { + await Page.SetContentAsync("
This page should crash
"); + var crashTask = Page.WaitForEventAsync(PageEvent.Crash); + await CrashAsync(Page); + await crashTask.WithTimeout(TestConstants.DefaultTaskTimeout); + await Page.Context.CloseAsync(); + } + + private async Task CrashAsync(IPage page) + { + try + { + await page.GoToAsync("chrome://crash"); + } + catch + { + } + } + } +} diff --git a/src/Playwright.Tests/PageEventNetworkTests.cs b/src/PlaywrightSharp.Tests/PageEventNetworkTests.cs similarity index 56% rename from src/Playwright.Tests/PageEventNetworkTests.cs rename to src/PlaywrightSharp.Tests/PageEventNetworkTests.cs index ac0bf2a138..cad2cbacd2 100644 --- a/src/Playwright.Tests/PageEventNetworkTests.cs +++ b/src/PlaywrightSharp.Tests/PageEventNetworkTests.cs @@ -1,141 +1,134 @@ -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.Playwright.Contracts.Constants; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Microsoft.Playwright.Tests.TestServer; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageEventNetworkTests : PlaywrightSharpPageBaseTest - { - /// - public PageEventNetworkTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-event-network.spec.ts", "Page.Events.Request")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PageEventsRequest() - { - var requests = new List(); - Page.Request += (_, e) => requests.Add(e); - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Single(requests); - Assert.Equal(TestConstants.EmptyPage, requests[0].Url); - Assert.Equal(ResourceTypes.Document, requests[0].ResourceType, true); - Assert.Equal(HttpMethod.Get.Method, requests[0].Method); - Assert.NotNull(await requests[0].GetResponseAsync()); - Assert.Equal(Page.MainFrame, requests[0].Frame); - Assert.Equal(TestConstants.EmptyPage, requests[0].Frame.Url); - } - - [PlaywrightTest("page-event-network.spec.ts", "Page.Events.Response")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PageEventsResponse() - { - var responses = new List(); - Page.Response += (_, e) => responses.Add(e); - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Single(responses); - Assert.Equal(TestConstants.EmptyPage, responses[0].Url); - Assert.Equal(HttpStatusCode.OK, responses[0].StatusCode); - Assert.True(responses[0].Ok); - Assert.NotNull(responses[0].Request); - } - - [PlaywrightTest("page-event-network.spec.ts", "Page.Events.RequestFailed")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PageEventsRequestFailed() - { - int port = TestConstants.Port + 100; - var disposableServer = new SimpleServer(port, TestUtils.FindParentDirectory("Playwright.Tests.TestServer"), false); - await disposableServer.StartAsync(); - - disposableServer.SetRoute("/one-style.css", async _ => - { - await disposableServer.StopAsync(); - }); - var failedRequests = new List(); - - Page.RequestFailed += (_, e) => failedRequests.Add(e); - - await Page.GoToAsync($"http://localhost:{port}/one-style.html"); - - Assert.Single(failedRequests); - Assert.Contains("one-style.css", failedRequests[0].Url); - Assert.Null(await failedRequests[0].GetResponseAsync()); - Assert.Equal(ResourceTypes.Stylesheet, failedRequests[0].ResourceType, true); - - string error = string.Empty; - - //We just need to test that we had a failure. - Assert.NotNull(failedRequests[0].Failure); - Assert.NotNull(failedRequests[0].Frame); - } - - [PlaywrightTest("page-event-network.spec.ts", "Page.Events.RequestFinished")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PageEventsRequestFinished() - { - var (_, response) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.RequestFinished), - Page.GoToAsync(TestConstants.EmptyPage)); - - var request = response.Request; - Assert.Equal(TestConstants.EmptyPage, request.Url); - Assert.NotNull(await request.GetResponseAsync()); - Assert.Equal(HttpMethod.Get.Method, request.Method); - Assert.Equal(Page.MainFrame, request.Frame); - Assert.Equal(TestConstants.EmptyPage, request.Frame.Url); - } - - [PlaywrightTest("page-event-network.spec.ts", "should fire events in proper order")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFireEventsInProperOrder() - { - var events = new List(); - Page.Request += (_, _) => events.Add("request"); - Page.Response += (_, _) => events.Add("response"); - var response = await Page.GoToAsync(TestConstants.EmptyPage); - await response.GetFinishedAsync(); - events.Add("requestfinished"); - Assert.Equal(new[] { "request", "response", "requestfinished" }, events); - } - - [PlaywrightTest("page-event-network.spec.ts", "should support redirects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportRedirects() - { - var events = new List(); - Page.Request += (_, e) => events.Add($"{e.Method} {e.Url}"); - Page.Response += (_, e) => events.Add($"{(int)e.Status} {e.Url}"); - Page.RequestFinished += (_, e) => events.Add($"DONE {e.Url}"); - Page.RequestFailed += (_, e) => events.Add($"FAIL {e.Url}"); - Server.SetRedirect("/foo.html", "/empty.html"); - const string FOO_URL = TestConstants.ServerUrl + "/foo.html"; - var response = await Page.GoToAsync(FOO_URL); - await response.GetFinishedAsync(); - Assert.Equal(new[] { - $"GET {FOO_URL}", - $"302 {FOO_URL}", - $"DONE {FOO_URL}", - $"GET {TestConstants.EmptyPage}", - $"200 {TestConstants.EmptyPage}", - $"DONE {TestConstants.EmptyPage}" - }, events); - - // Check redirect chain - var redirectedFrom = response.Request.RedirectedFrom; - - Assert.Contains("/foo.html", redirectedFrom.Url); - Assert.NotNull(redirectedFrom.RedirectedTo); - Assert.Equal(response.Request, redirectedFrom.RedirectedTo); - } - } -} +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Contracts.Constants; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; +using PlaywrightSharp.TestServer; + +namespace PlaywrightSharp.Tests +{ + public class PageEventNetworkTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-event-network.spec.ts", "Page.Events.Request")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PageEventsRequest() + { + var requests = new List(); + Page.Request += (_, e) => requests.Add(e); + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(requests, Has.Exactly(1).Items); + Assert.That(requests[0].Url, Is.EqualTo(TestConstants.EmptyPage)); + Assert.That(requests[0].ResourceType, Is.EqualTo(ResourceTypes.Document).IgnoreCase); + Assert.That(requests[0].Method, Is.EqualTo(HttpMethod.Get.Method)); + Assert.That(await requests[0].GetResponseAsync(), Is.Not.Null); + Assert.That(requests[0].Frame, Is.EqualTo(Page.MainFrame)); + Assert.That(requests[0].Frame.Url, Is.EqualTo(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-event-network.spec.ts", "Page.Events.Response")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PageEventsResponse() + { + var responses = new List(); + Page.Response += (_, e) => responses.Add(e); + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(responses, Has.Exactly(1).Items); + Assert.That(responses[0].Url, Is.EqualTo(TestConstants.EmptyPage)); + Assert.That(responses[0].StatusCode, Is.EqualTo(HttpStatusCode.OK)); + Assert.That(responses[0].Ok, Is.True); + Assert.That(responses[0].Request, Is.Not.Null); + } + + [PlaywrightTest("page-event-network.spec.ts", "Page.Events.RequestFailed")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PageEventsRequestFailed() + { + int port = TestConstants.Port + 100; + var disposableServer = new SimpleServer(port, TestUtils.FindParentDirectory("Playwright.Tests.TestServer"), false); + await disposableServer.StartAsync(); + + disposableServer.SetRoute("/one-style.css", async _ => + { + await disposableServer.StopAsync(); + }); + var failedRequests = new List(); + + Page.RequestFailed += (_, e) => failedRequests.Add(e); + + await Page.GoToAsync($"http://localhost:{port}/one-style.html"); + + Assert.That(failedRequests, Has.Exactly(1).Items); + Assert.That(failedRequests[0].Url, Does.Contain("one-style.css")); + Assert.That(await failedRequests[0].GetResponseAsync(), Is.Null); + Assert.That(failedRequests[0].ResourceType, Is.EqualTo(ResourceTypes.Stylesheet).IgnoreCase); + + string error = string.Empty; + + //We just need to test that we had a failure. + Assert.That(failedRequests[0].Failure, Is.Not.Null); + Assert.That(failedRequests[0].Frame, Is.Not.Null); + } + + [PlaywrightTest("page-event-network.spec.ts", "Page.Events.RequestFinished")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PageEventsRequestFinished() + { + var (_, response) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.RequestFinished), + Page.GoToAsync(TestConstants.EmptyPage)); + + var request = response.Request; + Assert.That(request.Url, Is.EqualTo(TestConstants.EmptyPage)); + Assert.That(await request.GetResponseAsync(), Is.Not.Null); + Assert.That(request.Method, Is.EqualTo(HttpMethod.Get.Method)); + Assert.That(request.Frame, Is.EqualTo(Page.MainFrame)); + Assert.That(request.Frame.Url, Is.EqualTo(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-event-network.spec.ts", "should fire events in proper order")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFireEventsInProperOrder() + { + var events = new List(); + Page.Request += (_, _) => events.Add("request"); + Page.Response += (_, _) => events.Add("response"); + var response = await Page.GoToAsync(TestConstants.EmptyPage); + await response.GetFinishedAsync(); + events.Add("requestfinished"); + Assert.That(events, Is.EqualTo(new[] { "request", "response", "requestfinished" })); + } + + [PlaywrightTest("page-event-network.spec.ts", "should support redirects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportRedirects() + { + var events = new List(); + Page.Request += (_, e) => events.Add($"{e.Method} {e.Url}"); + Page.Response += (_, e) => events.Add($"{(int)e.Status} {e.Url}"); + Page.RequestFinished += (_, e) => events.Add($"DONE {e.Url}"); + Page.RequestFailed += (_, e) => events.Add($"FAIL {e.Url}"); + Server.SetRedirect("/foo.html", "/empty.html"); + const string FOO_URL = TestConstants.ServerUrl + "/foo.html"; + var response = await Page.GoToAsync(FOO_URL); + await response.GetFinishedAsync(); + Assert.That(events, Is.EqualTo(new[] { + $"GET {FOO_URL}", + $"302 {FOO_URL}", + $"DONE {FOO_URL}", + $"GET {TestConstants.EmptyPage}", + $"200 {TestConstants.EmptyPage}", + $"DONE {TestConstants.EmptyPage}" + })); + + // Check redirect chain + var redirectedFrom = response.Request.RedirectedFrom; + + Assert.That(redirectedFrom.Url, Does.Contain("/foo.html")); + Assert.That(redirectedFrom.RedirectedTo, Is.Not.Null); + Assert.That(redirectedFrom.RedirectedTo, Is.EqualTo(response.Request)); + } + } +} diff --git a/src/Playwright.Tests/PageEventPageErrorTests.cs b/src/PlaywrightSharp.Tests/PageEventPageErrorTests.cs similarity index 72% rename from src/Playwright.Tests/PageEventPageErrorTests.cs rename to src/PlaywrightSharp.Tests/PageEventPageErrorTests.cs index 1e5ee0b5e2..bdd25e9597 100644 --- a/src/Playwright.Tests/PageEventPageErrorTests.cs +++ b/src/PlaywrightSharp.Tests/PageEventPageErrorTests.cs @@ -1,95 +1,88 @@ -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageEventPageErrorTests : PlaywrightSharpPageBaseTest - { - /// - public PageEventPageErrorTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-event-pageerror.spec.ts", "should fire")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFire() - { - var (error, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.PageError), - Page.GoToAsync(TestConstants.ServerUrl + "/error.html") - ); - - Assert.Contains("Error", error); - Assert.Contains("Fancy error!", error); - string stack = await Page.EvaluateAsync("() => window.e.stack"); - - if (TestConstants.IsWebKit) - { - stack = stack.Replace("14:25", "15:19"); - } - - Assert.Contains(stack, error); - } - - [PlaywrightTest("page-event-pageerror.spec.ts", "should contain sourceURL")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task ShouldContainSourceURL() - { - var (error, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.PageError), - Page.GoToAsync(TestConstants.ServerUrl + "/error.html")); - - Assert.Contains("myscript.js", error); - } - - [PlaywrightTest("page-event-pageerror.spec.ts", "should handle odd values")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldHandleOddValues() - { - object[][] cases = new object[][] - { - new []{ null, "null"}, - //[undefined], "undefined" Not undefined here - new object[]{ 0, "0"}, - new []{ "", "" }, - }; - - foreach (object[] kv in cases) - { - var (error, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.PageError), - Page.EvaluateAsync("value => setTimeout(() => { throw value; }, 0)", kv[0])); - - Assert.Contains(TestConstants.IsFirefox ? "uncaught exception: " + kv[1].ToString() : kv[1].ToString(), error); - } - } - - [PlaywrightTest("page-event-pageerror.spec.ts", "should handle object")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldHandleObject() - { - var (error, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.PageError), - Page.EvaluateAsync("value => setTimeout(() => { throw {}; }, 0)", 0)); - - Assert.Contains(TestConstants.IsChromium ? "Object" : "[object Object]", error); - } - - [PlaywrightTest("page-event-pageerror.spec.ts", "should handle window")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldHandleWindow() - { - var (error, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.PageError), - Page.EvaluateAsync("value => setTimeout(() => { throw window ; }, 0)", 0)); - - Assert.Contains(TestConstants.IsChromium ? "Window" : "[object Window]", error); - } - } -} +using System.Text.Json; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageEventPageErrorTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-event-pageerror.spec.ts", "should fire")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFire() + { + var (error, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.PageError), + Page.GoToAsync(TestConstants.ServerUrl + "/error.html") + ); + + Assert.That(error, Does.Contain("Error")); + Assert.That(error, Does.Contain("Fancy error!")); + string stack = await Page.EvaluateAsync("() => window.e.stack"); + + if (TestConstants.IsWebKit) + { + stack = stack.Replace("14:25", "15:19"); + } + + Assert.That(error, Does.Contain(stack)); + } + + [PlaywrightTest("page-event-pageerror.spec.ts", "should contain sourceURL")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task ShouldContainSourceURL() + { + var (error, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.PageError), + Page.GoToAsync(TestConstants.ServerUrl + "/error.html")); + + Assert.That(error, Does.Contain("myscript.js")); + } + + [PlaywrightTest("page-event-pageerror.spec.ts", "should handle odd values")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldHandleOddValues() + { + object[][] cases = new object[][] + { + new []{ null, "null"}, + //[undefined], "undefined" Not undefined here + new object[]{ 0, "0"}, + new []{ "", "" }, + }; + + foreach (object[] kv in cases) + { + var (error, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.PageError), + Page.EvaluateAsync("value => setTimeout(() => { throw value; }, 0)", kv[0])); + + Assert.That(error, Does.Contain(TestConstants.IsFirefox ? "uncaught exception: " + kv[1].ToString() : kv[1].ToString())); + } + } + + [PlaywrightTest("page-event-pageerror.spec.ts", "should handle object")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldHandleObject() + { + var (error, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.PageError), + Page.EvaluateAsync("value => setTimeout(() => { throw {}; }, 0)", 0)); + + Assert.That(error, Does.Contain(TestConstants.IsChromium ? "Object" : "[object Object]")); + } + + [PlaywrightTest("page-event-pageerror.spec.ts", "should handle window")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldHandleWindow() + { + var (error, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.PageError), + Page.EvaluateAsync("value => setTimeout(() => { throw window ; }, 0)", 0)); + + Assert.That(error, Does.Contain(TestConstants.IsChromium ? "Window" : "[object Window]")); + } + } +} diff --git a/src/Playwright.Tests/PageEventPopupTests.cs b/src/PlaywrightSharp.Tests/PageEventPopupTests.cs similarity index 74% rename from src/Playwright.Tests/PageEventPopupTests.cs rename to src/PlaywrightSharp.Tests/PageEventPopupTests.cs index c88cab3d92..3c9161679c 100644 --- a/src/Playwright.Tests/PageEventPopupTests.cs +++ b/src/PlaywrightSharp.Tests/PageEventPopupTests.cs @@ -1,246 +1,239 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageEventPopupTests : PlaywrightSharpPageBaseTest - { - /// - public PageEventPopupTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-event-popup.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - var popupTask = Page.WaitForEventAsync(PageEvent.Popup); - await TaskUtils.WhenAll( - popupTask, - Page.EvaluateAsync("() => window.open('about:blank')") - ); - var popup = popupTask.Result; - Assert.False(await Page.EvaluateAsync("() => !!window.opener")); - Assert.True(await popup.EvaluateAsync("() => !!window.opener")); - } - - [PlaywrightTest("page-event-popup.spec.ts", "should work with window features")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithWindowFeatures() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup); - await TaskUtils.WhenAll( - popupTask, - Page.EvaluateAsync("() => window.open('about:blank', 'Title', 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=780,height=200,top=0,left=0')") - ); - var popup = popupTask.Result; - Assert.False(await Page.EvaluateAsync("() => !!window.opener")); - Assert.True(await popup.EvaluateAsync("() => !!window.opener")); - } - - [PlaywrightTest("page-event-popup.spec.ts", "should emit for immediately closed popups")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEmitForImmediatelyClosedPopups() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup); - await TaskUtils.WhenAll( - popupTask, - Page.EvaluateAsync(@"() => { - const win = window.open('about:blank'); - win.close(); - }") - ); - Assert.NotNull(popupTask.Result); - } - - [PlaywrightTest("page-event-popup.spec.ts", "should emit for immediately closed popups")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEmitForImmediatelyClosedPopupsWithLocation() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup); - await TaskUtils.WhenAll( - popupTask, - Page.EvaluateAsync(@"() => { - const win = window.open(window.location.href); - win.close(); - }") - ); - Assert.NotNull(popupTask.Result); - } - - [PlaywrightTest("page-event-popup.spec.ts", "should be able to capture alert")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToCaptureAlert() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup); - var evaluateTask = Page.EvaluateAsync(@"() => { - const win = window.open(''); - win.alert('hello'); - }"); - - var popup = await popupTask; - var dialog = await popup.WaitForEventAsync(PageEvent.Dialog); - - Assert.Equal("hello", dialog.Message); - await dialog.DismissAsync(); - await evaluateTask; - } - - [PlaywrightTest("page-event-popup.spec.ts", "should work with empty url")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithEmptyUrl() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup); - await TaskUtils.WhenAll( - popupTask, - Page.EvaluateAsync("() => window.open('')") - ); - var popup = popupTask.Result; - Assert.False(await Page.EvaluateAsync("() => !!window.opener")); - Assert.True(await popup.EvaluateAsync("() => !!window.opener")); - } - - [PlaywrightTest("page-event-popup.spec.ts", "should work with noopener and no url")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithNoopenerAndNoUrl() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup); - await TaskUtils.WhenAll( - popupTask, - Page.EvaluateAsync("() => window.open(undefined, null, 'noopener')") - ); - var popup = popupTask.Result; - Assert.Equal("about:blank", popup.Url.Split('#')[0]); - Assert.False(await Page.EvaluateAsync("() => !!window.opener")); - Assert.False(await popup.EvaluateAsync("() => !!window.opener")); - } - - [PlaywrightTest("page-event-popup.spec.ts", "should work with noopener and about:blank")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithNoopenerAndAboutBlank() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup); - await TaskUtils.WhenAll( - popupTask, - Page.EvaluateAsync("() => window.open('about:blank', null, 'noopener')") - ); - var popup = popupTask.Result; - Assert.False(await Page.EvaluateAsync("() => !!window.opener")); - Assert.False(await popup.EvaluateAsync("() => !!window.opener")); - } - - [PlaywrightTest("page-event-popup.spec.ts", "should work with noopener and url")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithNoopenerAndUrl() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup); - await TaskUtils.WhenAll( - popupTask, - Page.EvaluateAsync("url => window.open(url, null, 'noopener')", TestConstants.EmptyPage) - ); - var popup = popupTask.Result; - Assert.False(await Page.EvaluateAsync("() => !!window.opener")); - Assert.False(await popup.EvaluateAsync("() => !!window.opener")); - } - - [PlaywrightTest("page-event-popup.spec.ts", "should work with clicking target=_blank")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWorkWithClickingTargetBlank() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync("yo"); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup).ContinueWith(async task => - { - var popup = task.Result; - await popup.WaitForLoadStateAsync(); - return popup; - }); - await TaskUtils.WhenAll( - popupTask, - Page.ClickAsync("a") - ); - - var popup = await popupTask.Result; - Assert.False(await Page.EvaluateAsync("() => !!window.opener")); - Assert.True(await popup.EvaluateAsync("() => !!window.opener")); - } - - [PlaywrightTest("page-event-popup.spec.ts", "should work with fake-clicking target=_blank and rel=noopener")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWorkWithFakeClickingTargetBlankAndRelNoopener() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync("yo"); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup).ContinueWith(async task => - { - var popup = task.Result; - await popup.WaitForLoadStateAsync(); - return popup; - }); - await TaskUtils.WhenAll( - popupTask, - Page.EvalOnSelectorAsync("a", "a => a.click()") - ); - var popup = await popupTask.Result; - Assert.False(await Page.EvaluateAsync("() => !!window.opener")); - Assert.False(await popup.EvaluateAsync("() => !!window.opener")); - } - - [PlaywrightTest("page-event-popup.spec.ts", "should work with clicking target=_blank and rel=noopener")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWorkWithClickingTargetBlankAndRelNoopener() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync("yo"); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup).ContinueWith(async task => - { - var popup = task.Result; - await popup.WaitForLoadStateAsync(); - return popup; - }); - await TaskUtils.WhenAll( - popupTask, - Page.ClickAsync("a") - ); - var popup = await popupTask.Result; - Assert.False(await Page.EvaluateAsync("() => !!window.opener")); - Assert.False(await popup.EvaluateAsync("() => !!window.opener")); - } - - [PlaywrightTest("page-event-popup.spec.ts", "should not treat navigations as new popups")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldNotTreatNavigationsAsNewPopups() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync("yo"); - var popupTask = Page.WaitForEventAsync(PageEvent.Popup).ContinueWith(async task => - { - var popup = task.Result; - await popup.WaitForLoadStateAsync(); - return popup; - }); - await TaskUtils.WhenAll( - popupTask, - Page.ClickAsync("a") - ); - var popup = await popupTask.Result; - bool badSecondPopup = false; - Page.Popup += (_, _) => badSecondPopup = true; - await popup.GoToAsync(TestConstants.CrossProcessUrl + "/empty.html"); - Assert.False(badSecondPopup); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageEventPopupTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-event-popup.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + var popupTask = Page.WaitForEventAsync(PageEvent.Popup); + await TaskUtils.WhenAll( + popupTask, + Page.EvaluateAsync("() => window.open('about:blank')") + ); + var popup = popupTask.Result; + Assert.That(await Page.EvaluateAsync("() => !!window.opener"), Is.False); + Assert.That(await popup.EvaluateAsync("() => !!window.opener"), Is.True); + } + + [PlaywrightTest("page-event-popup.spec.ts", "should work with window features")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithWindowFeatures() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup); + await TaskUtils.WhenAll( + popupTask, + Page.EvaluateAsync("() => window.open('about:blank', 'Title', 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=780,height=200,top=0,left=0')") + ); + var popup = popupTask.Result; + Assert.That(await Page.EvaluateAsync("() => !!window.opener"), Is.False); + Assert.That(await popup.EvaluateAsync("() => !!window.opener"), Is.True); + } + + [PlaywrightTest("page-event-popup.spec.ts", "should emit for immediately closed popups")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEmitForImmediatelyClosedPopups() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup); + await TaskUtils.WhenAll( + popupTask, + Page.EvaluateAsync(@"() => { + const win = window.open('about:blank'); + win.close(); + }") + ); + Assert.That(popupTask.Result, Is.Not.Null); + } + + [PlaywrightTest("page-event-popup.spec.ts", "should emit for immediately closed popups")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEmitForImmediatelyClosedPopupsWithLocation() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup); + await TaskUtils.WhenAll( + popupTask, + Page.EvaluateAsync(@"() => { + const win = window.open(window.location.href); + win.close(); + }") + ); + Assert.That(popupTask.Result, Is.Not.Null); + } + + [PlaywrightTest("page-event-popup.spec.ts", "should be able to capture alert")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToCaptureAlert() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup); + var evaluateTask = Page.EvaluateAsync(@"() => { + const win = window.open(''); + win.alert('hello'); + }"); + + var popup = await popupTask; + var dialog = await popup.WaitForEventAsync(PageEvent.Dialog); + + Assert.That(dialog.Message, Is.EqualTo("hello")); + await dialog.DismissAsync(); + await evaluateTask; + } + + [PlaywrightTest("page-event-popup.spec.ts", "should work with empty url")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithEmptyUrl() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup); + await TaskUtils.WhenAll( + popupTask, + Page.EvaluateAsync("() => window.open('')") + ); + var popup = popupTask.Result; + Assert.That(await Page.EvaluateAsync("() => !!window.opener"), Is.False); + Assert.That(await popup.EvaluateAsync("() => !!window.opener"), Is.True); + } + + [PlaywrightTest("page-event-popup.spec.ts", "should work with noopener and no url")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithNoopenerAndNoUrl() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup); + await TaskUtils.WhenAll( + popupTask, + Page.EvaluateAsync("() => window.open(undefined, null, 'noopener')") + ); + var popup = popupTask.Result; + Assert.That(popup.Url.Split('#')[0], Is.EqualTo("about:blank")); + Assert.That(await Page.EvaluateAsync("() => !!window.opener"), Is.False); + Assert.That(await popup.EvaluateAsync("() => !!window.opener"), Is.False); + } + + [PlaywrightTest("page-event-popup.spec.ts", "should work with noopener and about:blank")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithNoopenerAndAboutBlank() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup); + await TaskUtils.WhenAll( + popupTask, + Page.EvaluateAsync("() => window.open('about:blank', null, 'noopener')") + ); + var popup = popupTask.Result; + Assert.That(await Page.EvaluateAsync("() => !!window.opener"), Is.False); + Assert.That(await popup.EvaluateAsync("() => !!window.opener"), Is.False); + } + + [PlaywrightTest("page-event-popup.spec.ts", "should work with noopener and url")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithNoopenerAndUrl() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup); + await TaskUtils.WhenAll( + popupTask, + Page.EvaluateAsync("url => window.open(url, null, 'noopener')", TestConstants.EmptyPage) + ); + var popup = popupTask.Result; + Assert.That(await Page.EvaluateAsync("() => !!window.opener"), Is.False); + Assert.That(await popup.EvaluateAsync("() => !!window.opener"), Is.False); + } + + [PlaywrightTest("page-event-popup.spec.ts", "should work with clicking target=_blank")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWorkWithClickingTargetBlank() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.SetContentAsync("yo"); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup).ContinueWith(async task => + { + var popup = task.Result; + await popup.WaitForLoadStateAsync(); + return popup; + }); + await TaskUtils.WhenAll( + popupTask, + Page.ClickAsync("a") + ); + + var popup = await popupTask.Result; + Assert.That(await Page.EvaluateAsync("() => !!window.opener"), Is.False); + Assert.That(await popup.EvaluateAsync("() => !!window.opener"), Is.True); + } + + [PlaywrightTest("page-event-popup.spec.ts", "should work with fake-clicking target=_blank and rel=noopener")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWorkWithFakeClickingTargetBlankAndRelNoopener() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.SetContentAsync("yo"); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup).ContinueWith(async task => + { + var popup = task.Result; + await popup.WaitForLoadStateAsync(); + return popup; + }); + await TaskUtils.WhenAll( + popupTask, + Page.EvalOnSelectorAsync("a", "a => a.click()") + ); + var popup = await popupTask.Result; + Assert.That(await Page.EvaluateAsync("() => !!window.opener"), Is.False); + Assert.That(await popup.EvaluateAsync("() => !!window.opener"), Is.False); + } + + [PlaywrightTest("page-event-popup.spec.ts", "should work with clicking target=_blank and rel=noopener")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWorkWithClickingTargetBlankAndRelNoopener() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.SetContentAsync("yo"); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup).ContinueWith(async task => + { + var popup = task.Result; + await popup.WaitForLoadStateAsync(); + return popup; + }); + await TaskUtils.WhenAll( + popupTask, + Page.ClickAsync("a") + ); + var popup = await popupTask.Result; + Assert.That(await Page.EvaluateAsync("() => !!window.opener"), Is.False); + Assert.That(await popup.EvaluateAsync("() => !!window.opener"), Is.False); + } + + [PlaywrightTest("page-event-popup.spec.ts", "should not treat navigations as new popups")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldNotTreatNavigationsAsNewPopups() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.SetContentAsync("yo"); + var popupTask = Page.WaitForEventAsync(PageEvent.Popup).ContinueWith(async task => + { + var popup = task.Result; + await popup.WaitForLoadStateAsync(); + return popup; + }); + await TaskUtils.WhenAll( + popupTask, + Page.ClickAsync("a") + ); + var popup = await popupTask.Result; + bool badSecondPopup = false; + Page.Popup += (_, _) => badSecondPopup = true; + await popup.GoToAsync(TestConstants.CrossProcessUrl + "/empty.html"); + Assert.That(badSecondPopup, Is.False); + } + } +} diff --git a/src/Playwright.Tests/PageEventRequestTests.cs b/src/PlaywrightSharp.Tests/PageEventRequestTests.cs similarity index 64% rename from src/Playwright.Tests/PageEventRequestTests.cs rename to src/PlaywrightSharp.Tests/PageEventRequestTests.cs index 56289687ce..9cf827e80f 100644 --- a/src/Playwright.Tests/PageEventRequestTests.cs +++ b/src/PlaywrightSharp.Tests/PageEventRequestTests.cs @@ -1,68 +1,61 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageEventRequestTests : PlaywrightSharpPageBaseTest - { - /// - public PageEventRequestTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-event-request.spec.ts", "should fire for navigation requests")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFireForNavigationRequests() - { - var requests = new List(); - Page.Request += (_, e) => requests.Add(e); - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Single(requests); - } - - [PlaywrightTest("page-event-request.spec.ts", "should fire for iframes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFireForIframes() - { - var requests = new List(); - Page.Request += (_, e) => requests.Add(e); - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - Assert.Equal(2, requests.Count); - } - - [PlaywrightTest("page-event-request.spec.ts", "should fire for fetches")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFireForFetches() - { - var requests = new List(); - Page.Request += (_, e) => requests.Add(e); - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.EvaluateAsync("fetch('/empty.html')"); - Assert.Equal(2, requests.Count); - } - - [PlaywrightTest("page-event-request.spec.ts", "should report requests and responses handled by service worker")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReportRequestsAndResponsesHandledByServiceWorker() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/serviceworkers/fetchdummy/sw.html"); - await Page.EvaluateAsync("() => window.activationPromise"); - - var (request, swResponse) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.Request), - Page.EvaluateAsync("() => fetchDummy('foo')")); - - Assert.Equal("responseFromServiceWorker:foo", swResponse); - Assert.Equal(TestConstants.ServerUrl + "/serviceworkers/fetchdummy/foo", request.Url); - var response = await request.GetResponseAsync(); - Assert.Equal(TestConstants.ServerUrl + "/serviceworkers/fetchdummy/foo", response.Url); - Assert.Equal("responseFromServiceWorker:foo", await response.GetTextAsync()); - } - } -} +using System.Collections.Generic; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageEventRequestTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-event-request.spec.ts", "should fire for navigation requests")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFireForNavigationRequests() + { + var requests = new List(); + Page.Request += (_, e) => requests.Add(e); + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(requests, Has.Exactly(1).Items); + } + + [PlaywrightTest("page-event-request.spec.ts", "should fire for iframes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFireForIframes() + { + var requests = new List(); + Page.Request += (_, e) => requests.Add(e); + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + Assert.That(requests.Count, Is.EqualTo(2)); + } + + [PlaywrightTest("page-event-request.spec.ts", "should fire for fetches")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFireForFetches() + { + var requests = new List(); + Page.Request += (_, e) => requests.Add(e); + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.EvaluateAsync("fetch('/empty.html')"); + Assert.That(requests.Count, Is.EqualTo(2)); + } + + [PlaywrightTest("page-event-request.spec.ts", "should report requests and responses handled by service worker")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReportRequestsAndResponsesHandledByServiceWorker() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/serviceworkers/fetchdummy/sw.html"); + await Page.EvaluateAsync("() => window.activationPromise"); + + var (request, swResponse) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.Request), + Page.EvaluateAsync("() => fetchDummy('foo')")); + + Assert.That(swResponse, Is.EqualTo("responseFromServiceWorker:foo")); + Assert.That(request.Url, Is.EqualTo(TestConstants.ServerUrl + "/serviceworkers/fetchdummy/foo")); + var response = await request.GetResponseAsync(); + Assert.That(response.Url, Is.EqualTo(TestConstants.ServerUrl + "/serviceworkers/fetchdummy/foo")); + Assert.That(await response.GetTextAsync(), Is.EqualTo("responseFromServiceWorker:foo")); + } + } +} diff --git a/src/Playwright.Tests/PageExposeFunctionTests.cs b/src/PlaywrightSharp.Tests/PageExposeFunctionTests.cs similarity index 75% rename from src/Playwright.Tests/PageExposeFunctionTests.cs rename to src/PlaywrightSharp.Tests/PageExposeFunctionTests.cs index 26ba861dae..d9330849bd 100644 --- a/src/Playwright.Tests/PageExposeFunctionTests.cs +++ b/src/PlaywrightSharp.Tests/PageExposeFunctionTests.cs @@ -1,247 +1,240 @@ -using System.Linq; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///page-expose-function.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageExposeFunctionTests : PlaywrightSharpPageBaseTest - { - /// - public PageExposeFunctionTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-expose-function.spec.ts", "exposeBinding should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ExposeBindingShouldWork() - { - BindingSource bindingSource = null; - - await Page.ExposeBindingAsync("add", (BindingSource source, int a, int b) => - { - bindingSource = source; - return a + b; - }); - - int result = await Page.EvaluateAsync("async function () { return add(5, 6); }"); - - Assert.Same(Context, bindingSource.Context); - Assert.Same(Page, bindingSource.Page); - Assert.Same(Page.MainFrame, bindingSource.Frame); - Assert.Equal(11, result); - } - - [PlaywrightTest("page-expose-function.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.ExposeFunctionAsync("compute", (int a, int b) => a * b); - int result = await Page.EvaluateAsync(@"async function() { - return await compute(9, 4); - }"); - Assert.Equal(36, result); - } - - [PlaywrightTest("page-expose-function.spec.ts", "should work with handles and complex objects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithHandlesAndComplexObjects() - { - var fooHandle = await Page.EvaluateHandleAsync(@"() => { - window['fooValue'] = { bar: 2 }; - return window['fooValue']; - }"); - - await Page.ExposeFunctionAsync("handle", () => new[] { new { foo = fooHandle } }); - - Assert.True(await Page.EvaluateAsync(@"async function() { - const value = await window['handle'](); - const [{ foo }] = value; - return foo === window['fooValue']; - }")); - } - - [PlaywrightTest("page-expose-function.spec.ts", "should throw exception in page context")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowExceptionInPageContext() - { - await Page.ExposeFunctionAsync("woof", () => - { - throw new PlaywrightSharpException("WOOF WOOF"); - }); - var result = await Page.EvaluateAsync(@"async () => { - try - { - await woof(); - } - catch (e) - { - return { message: e.message, stack: e.stack}; - } - }"); - Assert.Equal("WOOF WOOF", result.GetProperty("message").GetString()); - Assert.Contains(nameof(PageExposeFunctionTests), result.GetProperty("stack").GetString()); - } - - [PlaywrightTest("page-expose-function.spec.ts", @"should support throwing ""null""")] - [Fact(Skip = "Not relevant for C#, js specific")] - public void ShouldSupportThrowingNull() - { - } - - [PlaywrightTest("page-expose-function.spec.ts", "should be callable from-inside addInitScript")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeCallableFromInsideAddInitScript() - { - bool called = false; - await Page.ExposeFunctionAsync("woof", () => - { - called = true; - }); - await Page.AddInitScriptAsync("() => woof()"); - await Page.ReloadAsync(); - Assert.True(called); - } - - [PlaywrightTest("page-expose-function.spec.ts", "should survive navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSurviveNavigation() - { - await Page.ExposeFunctionAsync("compute", (int a, int b) => a * b); - await Page.GoToAsync(TestConstants.EmptyPage); - int result = await Page.EvaluateAsync(@"async function() { - return await compute(9, 4); - }"); - Assert.Equal(36, result); - } - - [PlaywrightTest("page-expose-function.spec.ts", "should await returned promise")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAwaitReturnedPromise() - { - await Page.ExposeFunctionAsync("compute", (int a, int b) => Task.FromResult(a * b)); - int result = await Page.EvaluateAsync(@"async function() { - return await compute(3, 5); - }"); - Assert.Equal(15, result); - } - - [PlaywrightTest("page-expose-function.spec.ts", "should work on frames")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkOnFrames() - { - await Page.ExposeFunctionAsync("compute", (int a, int b) => Task.FromResult(a * b)); - await Page.GoToAsync(TestConstants.ServerUrl + "/frames/nested-frames.html"); - var frame = Page.Frames.ElementAt(1); - int result = await frame.EvaluateAsync(@"async function() { - return await compute(3, 5); - }"); - Assert.Equal(15, result); - } - - [PlaywrightTest("page-expose-function.spec.ts", "should work on frames before navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkOnFramesBeforeNavigation() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/frames/nested-frames.html"); - await Page.ExposeFunctionAsync("compute", (int a, int b) => Task.FromResult(a * b)); - var frame = Page.Frames.ElementAt(1); - int result = await frame.EvaluateAsync(@"async function() { - return await compute(3, 5); - }"); - Assert.Equal(15, result); - } - - [PlaywrightTest("page-expose-function.spec.ts", "should work after cross origin navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkAfterCrossOriginNavigation() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.ExposeFunctionAsync("compute", (int a, int b) => a * b); - await Page.GoToAsync(TestConstants.CrossProcessUrl + "/empty.html"); - int result = await Page.EvaluateAsync(@"async function() { - return await compute(9, 4); - }"); - Assert.Equal(36, result); - } - - [PlaywrightTest("page-expose-function.spec.ts", "should work with complex objects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithComplexObjects() - { - await Page.ExposeFunctionAsync("complexObject", (ComplexObject a, ComplexObject b) => - { - return new ComplexObject { x = a.x + b.x }; - }); - var result = await Page.EvaluateAsync("async () => complexObject({ x: 5}, { x: 2})"); - Assert.Equal(7, result.x); - } - - [PlaywrightTest("page-expose-function.spec.ts", "exposeBindingHandle should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ExposeBindingHandleShouldWork() - { - IJSHandle target = null; - await Page.ExposeBindingAsync( - "logme", - (_, t) => - { - target = t; - return 17; - }); - - int result = await Page.EvaluateAsync(@"async function() { - return window['logme']({ foo: 42 }); - }"); - - Assert.Equal(42, await target.EvaluateAsync("x => x.foo")); - Assert.Equal(17, result); - } - - [PlaywrightTest("page-expose-function.spec.ts", "exposeBindingHandle should not throw during navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ExposeBindingHandleShouldNotThrowDuringNavigation() - { - IJSHandle target = null; - await Page.ExposeBindingAsync( - "logme", - (_, t) => - { - target = t; - return 17; - }); - - await TaskUtils.WhenAll( - Page.WaitForNavigationAsync(WaitUntilState.Load), - Page.EvaluateAsync(@"async url => { - window['logme']({ foo: 42 }); - window.location.href = url; - }", TestConstants.ServerUrl + "/one-style.html")); - } - - [PlaywrightTest("browsercontext-expose-function.spec.ts", "should throw for duplicate registrations")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowForDuplicateRegistrations() - { - await Page.ExposeFunctionAsync("foo", () => { }); - var exception = await Assert.ThrowsAnyAsync(() => Page.ExposeFunctionAsync("foo", () => { })); - Assert.Equal("Function \"foo\" has been already registered", exception.Message); - } - - [PlaywrightTest("page-expose-function.spec.ts", "exposeBindingHandle should throw for multiple arguments")] - [Fact(Skip = "Not relevant for C#, js specific")] - public void ExposeBindingHandleShouldThrowForMultipleArguments() - { - } - - internal class ComplexObject - { - public int x { get; set; } - } - } -} +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///page-expose-function.spec.ts + public class PageExposeFunctionTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-expose-function.spec.ts", "exposeBinding should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ExposeBindingShouldWork() + { + BindingSource bindingSource = null; + + await Page.ExposeBindingAsync("add", (BindingSource source, int a, int b) => + { + bindingSource = source; + return a + b; + }); + + int result = await Page.EvaluateAsync("async function () { return add(5, 6); }"); + + Assert.That(bindingSource.Context, Is.SameAs(Context)); + Assert.That(bindingSource.Page, Is.SameAs(Page)); + Assert.That(bindingSource.Frame, Is.SameAs(Page.MainFrame)); + Assert.That(result, Is.EqualTo(11)); + } + + [PlaywrightTest("page-expose-function.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.ExposeFunctionAsync("compute", (int a, int b) => a * b); + int result = await Page.EvaluateAsync(@"async function() { + return await compute(9, 4); + }"); + Assert.That(result, Is.EqualTo(36)); + } + + [PlaywrightTest("page-expose-function.spec.ts", "should work with handles and complex objects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithHandlesAndComplexObjects() + { + var fooHandle = await Page.EvaluateHandleAsync(@"() => { + window['fooValue'] = { bar: 2 }; + return window['fooValue']; + }"); + + await Page.ExposeFunctionAsync("handle", () => new[] { new { foo = fooHandle } }); + + Assert.That(await Page.EvaluateAsync(@"async function() { + const value = await window['handle'](); + const [{ foo }] = value; + return foo === window['fooValue']; + }"), Is.True); + } + + [PlaywrightTest("page-expose-function.spec.ts", "should throw exception in page context")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowExceptionInPageContext() + { + await Page.ExposeFunctionAsync("woof", () => + { + throw new PlaywrightSharpException("WOOF WOOF"); + }); + var result = await Page.EvaluateAsync(@"async () => { + try + { + await woof(); + } + catch (e) + { + return { message: e.message, stack: e.stack}; + } + }"); + Assert.That(result.GetProperty("message").GetString(), Is.EqualTo("WOOF WOOF")); + Assert.That(result.GetProperty("stack").GetString(), Does.Contain(nameof(PageExposeFunctionTests))); + } + + [PlaywrightTest("page-expose-function.spec.ts", @"should support throwing ""null""")] + [Test, Ignore("Not relevant for C#, js specific")] + public void ShouldSupportThrowingNull() + { + } + + [PlaywrightTest("page-expose-function.spec.ts", "should be callable from-inside addInitScript")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeCallableFromInsideAddInitScript() + { + bool called = false; + await Page.ExposeFunctionAsync("woof", () => + { + called = true; + }); + await Page.AddInitScriptAsync("() => woof()"); + await Page.ReloadAsync(); + Assert.That(called, Is.True); + } + + [PlaywrightTest("page-expose-function.spec.ts", "should survive navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSurviveNavigation() + { + await Page.ExposeFunctionAsync("compute", (int a, int b) => a * b); + await Page.GoToAsync(TestConstants.EmptyPage); + int result = await Page.EvaluateAsync(@"async function() { + return await compute(9, 4); + }"); + Assert.That(result, Is.EqualTo(36)); + } + + [PlaywrightTest("page-expose-function.spec.ts", "should await returned promise")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAwaitReturnedPromise() + { + await Page.ExposeFunctionAsync("compute", (int a, int b) => Task.FromResult(a * b)); + int result = await Page.EvaluateAsync(@"async function() { + return await compute(3, 5); + }"); + Assert.That(result, Is.EqualTo(15)); + } + + [PlaywrightTest("page-expose-function.spec.ts", "should work on frames")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkOnFrames() + { + await Page.ExposeFunctionAsync("compute", (int a, int b) => Task.FromResult(a * b)); + await Page.GoToAsync(TestConstants.ServerUrl + "/frames/nested-frames.html"); + var frame = Page.Frames.ElementAt(1); + int result = await frame.EvaluateAsync(@"async function() { + return await compute(3, 5); + }"); + Assert.That(result, Is.EqualTo(15)); + } + + [PlaywrightTest("page-expose-function.spec.ts", "should work on frames before navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkOnFramesBeforeNavigation() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/frames/nested-frames.html"); + await Page.ExposeFunctionAsync("compute", (int a, int b) => Task.FromResult(a * b)); + var frame = Page.Frames.ElementAt(1); + int result = await frame.EvaluateAsync(@"async function() { + return await compute(3, 5); + }"); + Assert.That(result, Is.EqualTo(15)); + } + + [PlaywrightTest("page-expose-function.spec.ts", "should work after cross origin navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkAfterCrossOriginNavigation() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.ExposeFunctionAsync("compute", (int a, int b) => a * b); + await Page.GoToAsync(TestConstants.CrossProcessUrl + "/empty.html"); + int result = await Page.EvaluateAsync(@"async function() { + return await compute(9, 4); + }"); + Assert.That(result, Is.EqualTo(36)); + } + + [PlaywrightTest("page-expose-function.spec.ts", "should work with complex objects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithComplexObjects() + { + await Page.ExposeFunctionAsync("complexObject", (ComplexObject a, ComplexObject b) => + { + return new ComplexObject { x = a.x + b.x }; + }); + var result = await Page.EvaluateAsync("async () => complexObject({ x: 5}, { x: 2})"); + Assert.That(result.x, Is.EqualTo(7)); + } + + [PlaywrightTest("page-expose-function.spec.ts", "exposeBindingHandle should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ExposeBindingHandleShouldWork() + { + IJSHandle target = null; + await Page.ExposeBindingAsync( + "logme", + (_, t) => + { + target = t; + return 17; + }); + + int result = await Page.EvaluateAsync(@"async function() { + return window['logme']({ foo: 42 }); + }"); + + Assert.That(await target.EvaluateAsync("x => x.foo"), Is.EqualTo(42)); + Assert.That(result, Is.EqualTo(17)); + } + + [PlaywrightTest("page-expose-function.spec.ts", "exposeBindingHandle should not throw during navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ExposeBindingHandleShouldNotThrowDuringNavigation() + { + IJSHandle target = null; + await Page.ExposeBindingAsync( + "logme", + (_, t) => + { + target = t; + return 17; + }); + + await TaskUtils.WhenAll( + Page.WaitForNavigationAsync(WaitUntilState.Load), + Page.EvaluateAsync(@"async url => { + window['logme']({ foo: 42 }); + window.location.href = url; + }", TestConstants.ServerUrl + "/one-style.html")); + } + + [PlaywrightTest("browsercontext-expose-function.spec.ts", "should throw for duplicate registrations")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowForDuplicateRegistrations() + { + await Page.ExposeFunctionAsync("foo", () => { }); + var exception = Assert.CatchAsync(() => Page.ExposeFunctionAsync("foo", () => { })); + Assert.That(exception.Message, Is.EqualTo("Function \"foo\" has been already registered")); + } + + [PlaywrightTest("page-expose-function.spec.ts", "exposeBindingHandle should throw for multiple arguments")] + [Test, Ignore("Not relevant for C#, js specific")] + public void ExposeBindingHandleShouldThrowForMultipleArguments() + { + } + + internal class ComplexObject + { + public int x { get; set; } + } + } +} diff --git a/src/Playwright.Tests/PageExtensions.cs b/src/PlaywrightSharp.Tests/PageExtensions.cs similarity index 83% rename from src/Playwright.Tests/PageExtensions.cs rename to src/PlaywrightSharp.Tests/PageExtensions.cs index 5b29a2af88..ebc070281d 100644 --- a/src/Playwright.Tests/PageExtensions.cs +++ b/src/PlaywrightSharp.Tests/PageExtensions.cs @@ -1,9 +1,9 @@ -using System.Linq; - -namespace Microsoft.Playwright.Tests -{ - internal static class PageExtensions - { - public static IFrame FirstChildFrame(this IPage page) => page.Frames.FirstOrDefault(f => f.ParentFrame == page.MainFrame); - } -} +using System.Linq; + +namespace PlaywrightSharp.Tests +{ + internal static class PageExtensions + { + public static IFrame FirstChildFrame(this IPage page) => page.Frames.FirstOrDefault(f => f.ParentFrame == page.MainFrame); + } +} diff --git a/src/Playwright.Tests/PageFillTests.cs b/src/PlaywrightSharp.Tests/PageFillTests.cs similarity index 64% rename from src/Playwright.Tests/PageFillTests.cs rename to src/PlaywrightSharp.Tests/PageFillTests.cs index ba8cb72e16..04b714ae38 100644 --- a/src/Playwright.Tests/PageFillTests.cs +++ b/src/PlaywrightSharp.Tests/PageFillTests.cs @@ -1,308 +1,301 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageFillTests : PlaywrightSharpPageBaseTest - { - /// - public PageFillTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-fill.spec.ts", "should fill textarea")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFillTextarea() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.FillAsync("textarea", "some value"); - Assert.Equal("some value", await Page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("page-fill.spec.ts", "should fill input")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFillInput() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.FillAsync("input", "some value"); - Assert.Equal("some value", await Page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("page-fill.spec.ts", "should throw on unsupported inputs")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowOnUnsupportedInputs() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - foreach (string type in new[] { "button", "checkbox", "file", "image", "radio", "range", "reset", "submit" }) - { - await Page.EvalOnSelectorAsync("input", "(input, type) => input.setAttribute('type', type)", type); - var exception = await Assert.ThrowsAsync(() => Page.FillAsync("input", string.Empty)); - Assert.Contains($"input of type \"{type}\" cannot be filled", exception.Message); - } - } - - [PlaywrightTest("page-fill.spec.ts", "should fill different input types")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFillDifferentInputTypes() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - foreach (string type in new[] { "password", "search", "tel", "text", "url" }) - { - await Page.EvalOnSelectorAsync("input", "(input, type) => input.setAttribute('type', type)", type); - await Page.FillAsync("input", "text " + type); - Assert.Equal("text " + type, await Page.EvaluateAsync("() => result")); - } - } - - [PlaywrightTest("page-fill.spec.ts", "should fill date input after clicking")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFillDateInputAfterClicking() - { - await Page.SetContentAsync(""); - await Page.ClickAsync("input"); - await Page.FillAsync("input", "2020-03-02"); - Assert.Equal("2020-03-02", await Page.EvalOnSelectorAsync("input", "input => input.value")); - } - - [PlaywrightTest("page-fill.spec.ts", "should throw on incorrect date")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task ShouldThrowOnIncorrectDate() - { - await Page.SetContentAsync(""); - await Page.ClickAsync("input"); - var exception = await Assert.ThrowsAnyAsync(() => Page.FillAsync("input", "2020-13-02")); - Assert.Contains("Malformed value", exception.Message); - } - - [PlaywrightTest("page-fill.spec.ts", "should fill time input after clicking")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFillTimeInputAfterClicking() - { - await Page.SetContentAsync(""); - await Page.ClickAsync("input"); - await Page.FillAsync("input", "13:15"); - Assert.Equal("13:15", await Page.EvalOnSelectorAsync("input", "input => input.value")); - } - - [PlaywrightTest("page-fill.spec.ts", "should throw on incorrect time")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task ShouldThrowOnIncorrectTime() - { - await Page.SetContentAsync(""); - await Page.ClickAsync("input"); - var exception = await Assert.ThrowsAnyAsync(() => Page.FillAsync("input", "25:05")); - Assert.Contains("Malformed value", exception.Message); - } - - [PlaywrightTest("page-fill.spec.ts", "should fill datetime-local input")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFillDatetimeLocalInput() - { - await Page.SetContentAsync(""); - await Page.ClickAsync("input"); - await Page.FillAsync("input", "2020-03-02T05:15"); - Assert.Equal("2020-03-02T05:15", await Page.EvalOnSelectorAsync("input", "input => input.value")); - } - - [PlaywrightTest("page-fill.spec.ts", "should throw on incorrect datetime-local")] - [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] - public async Task ShouldThrowOnIncorrectDateTimeLocal() - { - await Page.SetContentAsync(""); - await Page.ClickAsync("input"); - var exception = await Assert.ThrowsAnyAsync(() => Page.FillAsync("input", "abc")); - Assert.Contains("Malformed value", exception.Message); - } - - [PlaywrightTest("page-fill.spec.ts", "should fill contenteditable")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFillContenteditable() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.FillAsync("div[contenteditable]", "some value"); - Assert.Equal("some value", await Page.EvalOnSelectorAsync("div[contenteditable]", "div => div.textContent")); - } - - [PlaywrightTest("page-fill.spec.ts", "should fill elements with existing value and selection")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFillElementsWithExistingValueAndSelection() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - - await Page.EvalOnSelectorAsync("input", "input => input.value = 'value one'"); - await Page.FillAsync("input", "another value"); - Assert.Equal("another value", await Page.EvaluateAsync("() => result")); - - await Page.EvalOnSelectorAsync("input", @"input => { - input.selectionStart = 1; - input.selectionEnd = 2; - }"); - await Page.FillAsync("input", "maybe this one"); - Assert.Equal("maybe this one", await Page.EvaluateAsync("() => result")); - - await Page.EvalOnSelectorAsync("div[contenteditable]", @"div => { - div.innerHTML = 'some text some more text and even more text'; - var range = document.createRange(); - range.selectNodeContents(div.querySelector('span')); - var selection = window.getSelection(); - selection.removeAllRanges(); - selection.addRange(range); - }"); - await Page.FillAsync("div[contenteditable]", "replace with this"); - Assert.Equal("replace with this", await Page.EvalOnSelectorAsync("div[contenteditable]", "div => div.textContent")); - } - - [PlaywrightTest("page-fill.spec.ts", "should throw when element is not an <input>, <textarea> or [contenteditable]")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowWhenElementIsNotAnInputOrTextareaOrContenteditable() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - var exception = await Assert.ThrowsAsync(() => Page.FillAsync("body", string.Empty)); - Assert.Contains("Element is not an ", exception.Message); - } - - [PlaywrightTest("page-fill.spec.ts", "should throw if passed a non-string value")] - [Fact(Skip = "Not relevant for C#, js specific")] - public void ShouldThrowIfPassedANonStringValue() - { - } - - [PlaywrightTest("page-fill.spec.ts", "should retry on disabled element")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRetryOnDisabledElement() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.EvalOnSelectorAsync("input", "i => i.disabled = true"); - - var task = Page.FillAsync("input", "some value"); - await GiveItAChanceToFillAsync(Page); - Assert.False(task.IsCompleted); - Assert.Empty(await Page.EvaluateAsync("() => result")); - - await Page.EvalOnSelectorAsync("input", "i => i.disabled = false"); - await task; - Assert.Equal("some value", await Page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("page-fill.spec.ts", "should retry on readonly element")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRetryOnReadonlyElement() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.EvalOnSelectorAsync("textarea", "i => i.readOnly = true"); - var task = Page.FillAsync("textarea", "some value"); - await GiveItAChanceToFillAsync(Page); - Assert.False(task.IsCompleted); - Assert.Empty(await Page.EvaluateAsync("() => result")); - - await Page.EvalOnSelectorAsync("textarea", "i => i.readOnly = false"); - await task; - Assert.Equal("some value", await Page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("page-fill.spec.ts", "should retry on invisible element")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRetryOnInvisibleElement() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.EvalOnSelectorAsync("input", "i => i.style.display = 'none'"); - - var task = Page.FillAsync("input", "some value"); - await GiveItAChanceToFillAsync(Page); - Assert.False(task.IsCompleted); - Assert.Empty(await Page.EvaluateAsync("() => result")); - - await Page.EvalOnSelectorAsync("input", "i => i.style.display = 'inline'"); - await task; - Assert.Equal("some value", await Page.EvaluateAsync("() => result")); - } - - [PlaywrightTest("page-fill.spec.ts", "should be able to fill the body")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToFillTheBody() - { - await Page.SetContentAsync(""); - await Page.FillAsync("body", "some value"); - Assert.Equal("some value", await Page.EvaluateAsync("() => document.body.textContent")); - } - - [PlaywrightTest("page-fill.spec.ts", "should fill fixed position input")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFillFixedPositionInput() - { - await Page.SetContentAsync(""); - await Page.FillAsync("input", "some value"); - Assert.Equal("some value", await Page.EvalOnSelectorAsync("input", "i => i.value")); - } - - [PlaywrightTest("page-fill.spec.ts", "should be able to fill when focus is in the wrong frame")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToFillWhenFocusIsInTheWrongFrame() - { - await Page.SetContentAsync("
"); - await Page.FocusAsync("iframe"); - await Page.FillAsync("div", "some value"); - Assert.Equal("some value", await Page.EvalOnSelectorAsync("div", "d => d.textContent")); - } - - [PlaywrightTest("page-fill.spec.ts", "should be able to fill the input[type=number]")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToFillTheInputTypeNumber() - { - await Page.SetContentAsync(""); - await Page.FillAsync("input", "42"); - Assert.Equal("42", await Page.EvaluateAsync("() => input.value")); - } - - [PlaywrightTest("page-fill.spec.ts", "should be able to fill exponent into the input[type=number]")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToFillTheInputExponentIntoTypeNumber() - { - await Page.SetContentAsync(""); - await Page.FillAsync("input", "-10e5"); - Assert.Equal("-10e5", await Page.EvaluateAsync("() => input.value")); - } - - [PlaywrightTest("page-fill.spec.ts", "should be able to fill the input[type=number] with empty string")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToFillTheInputTypeNumberWithEmptyString() - { - await Page.SetContentAsync(""); - await Page.FillAsync("input", ""); - Assert.Empty(await Page.EvaluateAsync("() => input.value")); - } - - [PlaywrightTest("page-fill.spec.ts", "should not be able to fill text into the input[type=number]")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotBeAbleToFillTextIntoTheInputTypeNumber() - { - await Page.SetContentAsync(""); - var exception = await Assert.ThrowsAnyAsync(() => Page.FillAsync("input", "abc")); - Assert.Contains("Cannot type text into input[type=number]", exception.Message); - } - - [PlaywrightTest("page-fill.spec.ts", "should be able to clear")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToClear() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.FillAsync("input", "some value"); - Assert.Equal("some value", await Page.EvaluateAsync("() => result")); - await Page.FillAsync("input", ""); - Assert.Empty(await Page.EvaluateAsync("() => result")); - } - - private async Task GiveItAChanceToFillAsync(IPage page) - { - for (int i = 0; i < 5; i++) - { - await page.EvaluateAsync("() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f)))"); - } - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageFillTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-fill.spec.ts", "should fill textarea")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFillTextarea() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.FillAsync("textarea", "some value"); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("some value")); + } + + [PlaywrightTest("page-fill.spec.ts", "should fill input")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFillInput() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.FillAsync("input", "some value"); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("some value")); + } + + [PlaywrightTest("page-fill.spec.ts", "should throw on unsupported inputs")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowOnUnsupportedInputs() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + foreach (string type in new[] { "button", "checkbox", "file", "image", "radio", "range", "reset", "submit" }) + { + await Page.EvalOnSelectorAsync("input", "(input, type) => input.setAttribute('type', type)", type); + var exception = Assert.ThrowsAsync(() => Page.FillAsync("input", string.Empty)); + Assert.That(exception.Message, Does.Contain($"input of type \"{type}\" cannot be filled")); + } + } + + [PlaywrightTest("page-fill.spec.ts", "should fill different input types")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFillDifferentInputTypes() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + foreach (string type in new[] { "password", "search", "tel", "text", "url" }) + { + await Page.EvalOnSelectorAsync("input", "(input, type) => input.setAttribute('type', type)", type); + await Page.FillAsync("input", "text " + type); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("text " + type)); + } + } + + [PlaywrightTest("page-fill.spec.ts", "should fill date input after clicking")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFillDateInputAfterClicking() + { + await Page.SetContentAsync(""); + await Page.ClickAsync("input"); + await Page.FillAsync("input", "2020-03-02"); + Assert.That(await Page.EvalOnSelectorAsync("input", "input => input.value"), Is.EqualTo("2020-03-02")); + } + + [PlaywrightTest("page-fill.spec.ts", "should throw on incorrect date")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task ShouldThrowOnIncorrectDate() + { + await Page.SetContentAsync(""); + await Page.ClickAsync("input"); + var exception = Assert.CatchAsync(() => Page.FillAsync("input", "2020-13-02")); + Assert.That(exception.Message, Does.Contain("Malformed value")); + } + + [PlaywrightTest("page-fill.spec.ts", "should fill time input after clicking")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFillTimeInputAfterClicking() + { + await Page.SetContentAsync(""); + await Page.ClickAsync("input"); + await Page.FillAsync("input", "13:15"); + Assert.That(await Page.EvalOnSelectorAsync("input", "input => input.value"), Is.EqualTo("13:15")); + } + + [PlaywrightTest("page-fill.spec.ts", "should throw on incorrect time")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task ShouldThrowOnIncorrectTime() + { + await Page.SetContentAsync(""); + await Page.ClickAsync("input"); + var exception = Assert.CatchAsync(() => Page.FillAsync("input", "25:05")); + Assert.That(exception.Message, Does.Contain("Malformed value")); + } + + [PlaywrightTest("page-fill.spec.ts", "should fill datetime-local input")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFillDatetimeLocalInput() + { + await Page.SetContentAsync(""); + await Page.ClickAsync("input"); + await Page.FillAsync("input", "2020-03-02T05:15"); + Assert.That(await Page.EvalOnSelectorAsync("input", "input => input.value"), Is.EqualTo("2020-03-02T05:15")); + } + + [PlaywrightTest("page-fill.spec.ts", "should throw on incorrect datetime-local")] + [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] + public async Task ShouldThrowOnIncorrectDateTimeLocal() + { + await Page.SetContentAsync(""); + await Page.ClickAsync("input"); + var exception = Assert.CatchAsync(() => Page.FillAsync("input", "abc")); + Assert.That(exception.Message, Does.Contain("Malformed value")); + } + + [PlaywrightTest("page-fill.spec.ts", "should fill contenteditable")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFillContenteditable() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.FillAsync("div[contenteditable]", "some value"); + Assert.That(await Page.EvalOnSelectorAsync("div[contenteditable]", "div => div.textContent"), Is.EqualTo("some value")); + } + + [PlaywrightTest("page-fill.spec.ts", "should fill elements with existing value and selection")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFillElementsWithExistingValueAndSelection() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + + await Page.EvalOnSelectorAsync("input", "input => input.value = 'value one'"); + await Page.FillAsync("input", "another value"); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("another value")); + + await Page.EvalOnSelectorAsync("input", @"input => { + input.selectionStart = 1; + input.selectionEnd = 2; + }"); + await Page.FillAsync("input", "maybe this one"); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("maybe this one")); + + await Page.EvalOnSelectorAsync("div[contenteditable]", @"div => { + div.innerHTML = 'some text some more text and even more text'; + var range = document.createRange(); + range.selectNodeContents(div.querySelector('span')); + var selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange(range); + }"); + await Page.FillAsync("div[contenteditable]", "replace with this"); + Assert.That(await Page.EvalOnSelectorAsync("div[contenteditable]", "div => div.textContent"), Is.EqualTo("replace with this")); + } + + [PlaywrightTest("page-fill.spec.ts", "should throw when element is not an <input>, <textarea> or [contenteditable]")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowWhenElementIsNotAnInputOrTextareaOrContenteditable() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + var exception = Assert.ThrowsAsync(() => Page.FillAsync("body", string.Empty)); + Assert.That(exception.Message, Does.Contain("Element is not an ")); + } + + [PlaywrightTest("page-fill.spec.ts", "should throw if passed a non-string value")] + [Test, Ignore("Not relevant for C#, js specific")] + public void ShouldThrowIfPassedANonStringValue() + { + } + + [PlaywrightTest("page-fill.spec.ts", "should retry on disabled element")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRetryOnDisabledElement() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.EvalOnSelectorAsync("input", "i => i.disabled = true"); + + var task = Page.FillAsync("input", "some value"); + await GiveItAChanceToFillAsync(Page); + Assert.That(task.IsCompleted, Is.False); + Assert.That(await Page.EvaluateAsync("() => result"), Is.Empty); + + await Page.EvalOnSelectorAsync("input", "i => i.disabled = false"); + await task; + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("some value")); + } + + [PlaywrightTest("page-fill.spec.ts", "should retry on readonly element")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRetryOnReadonlyElement() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.EvalOnSelectorAsync("textarea", "i => i.readOnly = true"); + var task = Page.FillAsync("textarea", "some value"); + await GiveItAChanceToFillAsync(Page); + Assert.That(task.IsCompleted, Is.False); + Assert.That(await Page.EvaluateAsync("() => result"), Is.Empty); + + await Page.EvalOnSelectorAsync("textarea", "i => i.readOnly = false"); + await task; + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("some value")); + } + + [PlaywrightTest("page-fill.spec.ts", "should retry on invisible element")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRetryOnInvisibleElement() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.EvalOnSelectorAsync("input", "i => i.style.display = 'none'"); + + var task = Page.FillAsync("input", "some value"); + await GiveItAChanceToFillAsync(Page); + Assert.That(task.IsCompleted, Is.False); + Assert.That(await Page.EvaluateAsync("() => result"), Is.Empty); + + await Page.EvalOnSelectorAsync("input", "i => i.style.display = 'inline'"); + await task; + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("some value")); + } + + [PlaywrightTest("page-fill.spec.ts", "should be able to fill the body")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToFillTheBody() + { + await Page.SetContentAsync(""); + await Page.FillAsync("body", "some value"); + Assert.That(await Page.EvaluateAsync("() => document.body.textContent"), Is.EqualTo("some value")); + } + + [PlaywrightTest("page-fill.spec.ts", "should fill fixed position input")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFillFixedPositionInput() + { + await Page.SetContentAsync(""); + await Page.FillAsync("input", "some value"); + Assert.That(await Page.EvalOnSelectorAsync("input", "i => i.value"), Is.EqualTo("some value")); + } + + [PlaywrightTest("page-fill.spec.ts", "should be able to fill when focus is in the wrong frame")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToFillWhenFocusIsInTheWrongFrame() + { + await Page.SetContentAsync("
"); + await Page.FocusAsync("iframe"); + await Page.FillAsync("div", "some value"); + Assert.That(await Page.EvalOnSelectorAsync("div", "d => d.textContent"), Is.EqualTo("some value")); + } + + [PlaywrightTest("page-fill.spec.ts", "should be able to fill the input[type=number]")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToFillTheInputTypeNumber() + { + await Page.SetContentAsync(""); + await Page.FillAsync("input", "42"); + Assert.That(await Page.EvaluateAsync("() => input.value"), Is.EqualTo("42")); + } + + [PlaywrightTest("page-fill.spec.ts", "should be able to fill exponent into the input[type=number]")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToFillTheInputExponentIntoTypeNumber() + { + await Page.SetContentAsync(""); + await Page.FillAsync("input", "-10e5"); + Assert.That(await Page.EvaluateAsync("() => input.value"), Is.EqualTo("-10e5")); + } + + [PlaywrightTest("page-fill.spec.ts", "should be able to fill the input[type=number] with empty string")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToFillTheInputTypeNumberWithEmptyString() + { + await Page.SetContentAsync(""); + await Page.FillAsync("input", ""); + Assert.That(await Page.EvaluateAsync("() => input.value"), Is.Empty); + } + + [PlaywrightTest("page-fill.spec.ts", "should not be able to fill text into the input[type=number]")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotBeAbleToFillTextIntoTheInputTypeNumber() + { + await Page.SetContentAsync(""); + var exception = Assert.CatchAsync(() => Page.FillAsync("input", "abc")); + Assert.That(exception.Message, Does.Contain("Cannot type text into input[type=number]")); + } + + [PlaywrightTest("page-fill.spec.ts", "should be able to clear")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToClear() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.FillAsync("input", "some value"); + Assert.That(await Page.EvaluateAsync("() => result"), Is.EqualTo("some value")); + await Page.FillAsync("input", ""); + Assert.That(await Page.EvaluateAsync("() => result"), Is.Empty); + } + + private async Task GiveItAChanceToFillAsync(IPage page) + { + for (int i = 0; i < 5; i++) + { + await page.EvaluateAsync("() => new Promise(f => requestAnimationFrame(() => requestAnimationFrame(f)))"); + } + } + } +} diff --git a/src/Playwright.Tests/PageFocusTests.cs b/src/PlaywrightSharp.Tests/PageFocusTests.cs similarity index 66% rename from src/Playwright.Tests/PageFocusTests.cs rename to src/PlaywrightSharp.Tests/PageFocusTests.cs index 65070eed52..cb90c19b4a 100644 --- a/src/Playwright.Tests/PageFocusTests.cs +++ b/src/PlaywrightSharp.Tests/PageFocusTests.cs @@ -1,77 +1,70 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageFocusTests : PlaywrightSharpPageBaseTest - { - /// - public PageFocusTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-focus.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.SetContentAsync("
"); - Assert.Equal("BODY", await Page.EvaluateAsync("() => document.activeElement.nodeName")); - await Page.FocusAsync("#d1"); - Assert.Equal("d1", await Page.EvaluateAsync("() => document.activeElement.id")); - } - - [PlaywrightTest("page-focus.spec.ts", "should emit focus event")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEmitFocusEvent() - { - await Page.SetContentAsync("
"); - bool focused = false; - await Page.ExposeFunctionAsync("focusEvent", () => focused = true); - await Page.EvaluateAsync("() => d1.addEventListener('focus', focusEvent)"); - await Page.FocusAsync("#d1"); - Assert.True(focused); - } - - [PlaywrightTest("page-focus.spec.ts", "should emit blur event")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEmitBlurEvent() - { - await Page.SetContentAsync("
DIV1
DIV2
"); - await Page.FocusAsync("#d1"); - bool focused = false; - bool blurred = false; - await Page.ExposeFunctionAsync("focusEvent", () => focused = true); - await Page.ExposeFunctionAsync("blurEvent", () => blurred = true); - await Page.EvaluateAsync("() => d1.addEventListener('blur', blurEvent)"); - await Page.EvaluateAsync("() => d2.addEventListener('focus', focusEvent)"); - await Page.FocusAsync("#d2"); - Assert.True(focused); - Assert.True(blurred); - } - - [PlaywrightTest("page-focus.spec.ts", "should traverse focus")] - [SkipBrowserAndPlatformFact(skipWebkit: true, skipWindows: true, skipOSX: true)] - public async Task ShouldTraverseFocus() - { - await Page.SetContentAsync(""); - bool focused = false; - await Page.ExposeFunctionAsync("focusEvent", () => focused = true); - await Page.EvaluateAsync("() => i2.addEventListener('focus', focusEvent)"); - - await Page.FocusAsync("#i1"); - await Page.Keyboard.TypeAsync("First"); - await Page.Keyboard.PressAsync("Tab"); - await Page.Keyboard.TypeAsync("Last"); - - Assert.True(focused); - - Assert.Equal("First", await Page.EvalOnSelectorAsync("#i1", "e => e.value")); - Assert.Equal("Last", await Page.EvalOnSelectorAsync("#i2", "e => e.value")); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageFocusTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-focus.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.SetContentAsync("
"); + Assert.That(await Page.EvaluateAsync("() => document.activeElement.nodeName"), Is.EqualTo("BODY")); + await Page.FocusAsync("#d1"); + Assert.That(await Page.EvaluateAsync("() => document.activeElement.id"), Is.EqualTo("d1")); + } + + [PlaywrightTest("page-focus.spec.ts", "should emit focus event")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEmitFocusEvent() + { + await Page.SetContentAsync("
"); + bool focused = false; + await Page.ExposeFunctionAsync("focusEvent", () => focused = true); + await Page.EvaluateAsync("() => d1.addEventListener('focus', focusEvent)"); + await Page.FocusAsync("#d1"); + Assert.That(focused, Is.True); + } + + [PlaywrightTest("page-focus.spec.ts", "should emit blur event")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEmitBlurEvent() + { + await Page.SetContentAsync("
DIV1
DIV2
"); + await Page.FocusAsync("#d1"); + bool focused = false; + bool blurred = false; + await Page.ExposeFunctionAsync("focusEvent", () => focused = true); + await Page.ExposeFunctionAsync("blurEvent", () => blurred = true); + await Page.EvaluateAsync("() => d1.addEventListener('blur', blurEvent)"); + await Page.EvaluateAsync("() => d2.addEventListener('focus', focusEvent)"); + await Page.FocusAsync("#d2"); + Assert.That(focused, Is.True); + Assert.That(blurred, Is.True); + } + + [PlaywrightTest("page-focus.spec.ts", "should traverse focus")] + [SkipBrowserAndPlatformFact(skipWebkit: true, skipWindows: true, skipOSX: true)] + public async Task ShouldTraverseFocus() + { + await Page.SetContentAsync(""); + bool focused = false; + await Page.ExposeFunctionAsync("focusEvent", () => focused = true); + await Page.EvaluateAsync("() => i2.addEventListener('focus', focusEvent)"); + + await Page.FocusAsync("#i1"); + await Page.Keyboard.TypeAsync("First"); + await Page.Keyboard.PressAsync("Tab"); + await Page.Keyboard.TypeAsync("Last"); + + Assert.That(focused, Is.True); + + Assert.That(await Page.EvalOnSelectorAsync("#i1", "e => e.value"), Is.EqualTo("First")); + Assert.That(await Page.EvalOnSelectorAsync("#i2", "e => e.value"), Is.EqualTo("Last")); + } + } +} diff --git a/src/Playwright.Tests/PageGoToTests.cs b/src/PlaywrightSharp.Tests/PageGoToTests.cs similarity index 61% rename from src/Playwright.Tests/PageGoToTests.cs rename to src/PlaywrightSharp.Tests/PageGoToTests.cs index d04aab4f28..581104d95e 100644 --- a/src/Playwright.Tests/PageGoToTests.cs +++ b/src/PlaywrightSharp.Tests/PageGoToTests.cs @@ -1,604 +1,598 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class GoToTests : PlaywrightSharpPageBaseTest - { - /// - public GoToTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-goto.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(TestConstants.EmptyPage, Page.Url); - } - - [PlaywrightTest("page-goto.spec.ts", "should work with file URL")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithFileURL() - { - string fileurl = new Uri(TestUtils.GetWebServerFile(Path.Combine("frames", "two-frames.html"))).AbsoluteUri; - await Page.GoToAsync(fileurl); - Assert.Equal(fileurl.ToLower(), Page.Url.ToLower()); - Assert.Equal(3, Page.Frames.Count); - } - - [PlaywrightTest("page-goto.spec.ts", "should use http for no protocol")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldUseHttpForNoProtocol() - { - await Page.GoToAsync(TestConstants.EmptyPage.Replace("http://", string.Empty)); - Assert.Equal(TestConstants.EmptyPage, Page.Url); - } - - [PlaywrightTest("page-goto.spec.ts", "should work cross-process")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkCrossProcess() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(TestConstants.EmptyPage, Page.Url); - - string url = TestConstants.CrossProcessHttpPrefix + "/empty.html"; - IFrame requestFrame = null; - Page.Request += (_, e) => - { - if (e.Url == url) - { - requestFrame = e.Frame; - } - }; - - var response = await Page.GoToAsync(url); - Assert.Equal(url, Page.Url); - Assert.Same(Page.MainFrame, response.Frame); - Assert.Same(Page.MainFrame, requestFrame); - Assert.Equal(url, response.Url); - } - - [PlaywrightTest("page-goto.spec.ts", "should capture iframe navigation request")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCaptureIframeNavigationRequest() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(TestConstants.EmptyPage, Page.Url); - - IFrame requestFrame = null; - Page.Request += (_, e) => - { - if (e.Url == TestConstants.ServerUrl + "/frames/frame.html") - { - requestFrame = e.Frame; - } - }; - - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); - Assert.Equal(TestConstants.ServerUrl + "/frames/one-frame.html", Page.Url); - Assert.Same(Page.MainFrame, response.Frame); - Assert.Equal(TestConstants.ServerUrl + "/frames/one-frame.html", response.Url); - - Assert.Equal(2, Page.Frames.Count); - Assert.Same(Page.FirstChildFrame(), requestFrame); - } - - [PlaywrightTest("page-goto.spec.ts", "should capture cross-process iframe navigation request")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldCaptureCrossProcessIframeNavigationRequest() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(TestConstants.EmptyPage, Page.Url); - - IFrame requestFrame = null; - Page.Request += (_, e) => - { - if (e.Url == TestConstants.CrossProcessHttpPrefix + "/frames/frame.html") - { - requestFrame = e.Frame; - } - }; - - var response = await Page.GoToAsync(TestConstants.CrossProcessHttpPrefix + "/frames/one-frame.html"); - Assert.Equal(TestConstants.CrossProcessHttpPrefix + "/frames/one-frame.html", Page.Url); - Assert.Same(Page.MainFrame, response.Frame); - Assert.Equal(TestConstants.CrossProcessHttpPrefix + "/frames/one-frame.html", response.Url); - - Assert.Equal(2, Page.Frames.Count); - Assert.Same(Page.FirstChildFrame(), requestFrame); - } - - [PlaywrightTest("page-goto.spec.ts", "should work with anchor navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithAnchorNavigation() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(TestConstants.EmptyPage, Page.Url); - await Page.GoToAsync($"{TestConstants.EmptyPage}#foo"); - Assert.Equal($"{TestConstants.EmptyPage}#foo", Page.Url); - await Page.GoToAsync($"{TestConstants.EmptyPage}#bar"); - Assert.Equal($"{TestConstants.EmptyPage}#bar", Page.Url); - } - - [PlaywrightTest("page-goto.spec.ts", "should work with redirects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithRedirects() - { - Server.SetRedirect("/redirect/1.html", "/redirect/2.html"); - Server.SetRedirect("/redirect/2.html", "/empty.html"); - - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/redirect/1.html"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - await Page.GoToAsync(TestConstants.EmptyPage); - } - - [PlaywrightTest("page-goto.spec.ts", "should navigate to about:blank")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNavigateToAboutBlank() - { - var response = await Page.GoToAsync(TestConstants.AboutBlank); - Assert.Null(response); - } - - [PlaywrightTest("page-goto.spec.ts", "should return response when page changes its URL after load")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnResponseWhenPageChangesItsURLAfterLoad() - { - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/historyapi.html"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - - [PlaywrightTest("page-goto.spec.ts", "should work with subframes return 204")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithSubframesReturn204() - { - Server.SetRoute("/frames/frame.html", context => - { - context.Response.StatusCode = 204; - return Task.CompletedTask; - }); - await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); - } - - [PlaywrightTest("page-goto.spec.ts", "should work with subframes return 204")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWhenServerReturns204() - { - Server.SetRoute("/empty.html", context => - { - context.Response.StatusCode = 204; - return Task.CompletedTask; - }); - var exception = await Assert.ThrowsAnyAsync( - () => Page.GoToAsync(TestConstants.EmptyPage)); - - if (TestConstants.IsChromium) - { - Assert.Contains("net::ERR_ABORTED", exception.Message); - } - else if (TestConstants.IsFirefox) - { - Assert.Contains("NS_BINDING_ABORTED", exception.Message); - } - else - { - Assert.Contains("Aborted: 204 No Content", exception.Message); - } - } - - [PlaywrightTest("page-goto.spec.ts", "should navigate to empty page with domcontentloaded")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNavigateToEmptyPageWithDOMContentLoaded() - { - var response = await Page.GoToAsync(TestConstants.EmptyPage, WaitUntilState.DOMContentLoaded); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - - [PlaywrightTest("page-goto.spec.ts", "should work when page calls history API in beforeunload")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWhenPageCallsHistoryAPIInBeforeunload() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.EvaluateAsync(@"() => - { - window.addEventListener('beforeunload', () => history.replaceState(null, 'initial', window.location.href), false); - }"); - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - - [PlaywrightTest("page-goto.spec.ts", "should fail when navigating to bad url")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWhenNavigatingToBadUrl() - { - var exception = await Assert.ThrowsAnyAsync(async () => await Page.GoToAsync("asdfasdf")); - if (TestConstants.IsChromium || TestConstants.IsWebKit) - { - Assert.Contains("Cannot navigate to invalid URL", exception.Message); - } - else - { - Assert.Contains("Invalid url", exception.Message); - } - } - - [PlaywrightTest("page-goto.spec.ts", "should fail when navigating to bad SSL")] - // [Fact(Timeout = TestConstants.DefaultTestTimeout)] - [Fact(Skip = "Fix me #1058")] - public async Task ShouldFailWhenNavigatingToBadSSL() - { - Page.Request += (_, e) => Assert.NotNull(e); - Page.RequestFinished += (_, e) => Assert.NotNull(e); - Page.RequestFailed += (_, e) => Assert.NotNull(e); - - var exception = await Assert.ThrowsAnyAsync(async () => await Page.GoToAsync(TestConstants.HttpsPrefix + "/empty.html")); - TestUtils.AssertSSLError(exception.Message); - } - - [PlaywrightTest("page-goto.spec.ts", "should fail when navigating to bad SSL after redirects")] - // [Fact(Timeout = TestConstants.DefaultTestTimeout)] - [Fact(Skip = "Fix me #1058")] - public async Task ShouldFailWhenNavigatingToBadSSLAfterRedirects() - { - Server.SetRedirect("/redirect/1.html", "/redirect/2.html"); - Server.SetRedirect("/redirect/2.html", "/empty.html"); - var exception = await Assert.ThrowsAnyAsync(async () => await Page.GoToAsync(TestConstants.HttpsPrefix + "/redirect/1.html")); - TestUtils.AssertSSLError(exception.Message); - } - - [PlaywrightTest("page-goto.spec.ts", "should not crash when navigating to bad SSL after a cross origin navigation")] - // [Fact(Timeout = TestConstants.DefaultTestTimeout)] - [Fact(Skip = "Fix me #1058")] - public async Task ShouldNotCrashWhenNavigatingToBadSSLAfterACrossOriginNavigation() - { - await Page.GoToAsync(TestConstants.CrossProcessHttpPrefix + "/empty.html"); - await Page.GoToAsync(TestConstants.HttpsPrefix + "/empty.html").ContinueWith(_ => { }); - } - - [PlaywrightTest("page-goto.spec.ts", "should throw if networkidle0 is passed as an option")] - [Fact(Skip = "We don't need this test")] - public void ShouldThrowIfNetworkIdle0IsPassedAsAnOption() - { } - - [PlaywrightTest("page-goto.spec.ts", "should throw if networkidle2 is passed as an option")] - [Fact(Skip = "We don't need this test")] - public void ShouldThrowIfNetworkIdle2IsPassedAsAnOption() - { } - - [PlaywrightTest("page-goto.spec.ts", "should throw if networkidle is passed as an option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWhenMainResourcesFailedToLoad() - { - var exception = await Assert.ThrowsAnyAsync(async () => await Page.GoToAsync("http://localhost:44123/non-existing-url")); - - if (TestConstants.IsChromium) - { - Assert.Contains("net::ERR_CONNECTION_REFUSED", exception.Message); - } - else if (TestConstants.IsWebKit && TestConstants.IsWindows) - { - Assert.Contains("Couldn't connect to server", exception.Message); - } - else if (TestConstants.IsWebKit) - { - Assert.Contains("Could not connect", exception.Message); - } - else - { - Assert.Contains("NS_ERROR_CONNECTION_REFUSED", exception.Message); - } - } - - [PlaywrightTest("page-goto.spec.ts", "should fail when exceeding maximum navigation timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWhenExceedingMaximumNavigationTimeout() - { - Server.SetRoute("/empty.html", _ => Task.Delay(-1)); - var exception = await Assert.ThrowsAsync(async () - => await Page.GoToAsync(TestConstants.EmptyPage, timeout: 1)); - Assert.Contains("Timeout 1ms exceeded", exception.Message); - Assert.Contains(TestConstants.EmptyPage, exception.Message); - } - - [PlaywrightTest("page-goto.spec.ts", "should fail when exceeding maximum navigation timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWhenExceedingDefaultMaximumNavigationTimeout() - { - Server.SetRoute("/empty.html", _ => Task.Delay(-1)); - Page.Context.DefaultNavigationTimeout = 2; - Page.DefaultNavigationTimeout = 1; - var exception = await Assert.ThrowsAsync(async () => await Page.GoToAsync(TestConstants.EmptyPage)); - Assert.Contains("Timeout 1ms exceeded", exception.Message); - Assert.Contains(TestConstants.EmptyPage, exception.Message); - } - - [PlaywrightTest("page-goto.spec.ts", "should fail when exceeding browser context navigation timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWhenExceedingBrowserContextNavigationTimeout() - { - Server.SetRoute("/empty.html", _ => Task.Delay(-1)); - Page.Context.DefaultNavigationTimeout = 2; - var exception = await Assert.ThrowsAsync(async () => await Page.GoToAsync(TestConstants.EmptyPage)); - Assert.Contains("Timeout 2ms exceeded", exception.Message); - Assert.Contains(TestConstants.EmptyPage, exception.Message); - } - - [PlaywrightTest("page-goto.spec.ts", "should fail when exceeding default maximum timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWhenExceedingDefaultMaximumTimeout() - { - Server.SetRoute("/empty.html", _ => Task.Delay(-1)); - Page.Context.DefaultTimeout = 2; - Page.DefaultTimeout = 1; - var exception = await Assert.ThrowsAsync(async () => await Page.GoToAsync(TestConstants.EmptyPage)); - Assert.Contains("Timeout 1ms exceeded", exception.Message); - Assert.Contains(TestConstants.EmptyPage, exception.Message); - } - - [PlaywrightTest("page-goto.spec.ts", "should fail when exceeding browser context timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWhenExceedingBrowserContextTimeout() - { - Server.SetRoute("/empty.html", _ => Task.Delay(-1)); - Page.Context.DefaultTimeout = 2; - var exception = await Assert.ThrowsAsync(async () => await Page.GoToAsync(TestConstants.EmptyPage)); - Assert.Contains("Timeout 2ms exceeded", exception.Message); - Assert.Contains(TestConstants.EmptyPage, exception.Message); - } - - [PlaywrightTest("page-goto.spec.ts", "should prioritize default navigation timeout over default timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldPrioritizeDefaultNavigationTimeoutOverDefaultTimeout() - { - // Hang for request to the empty.html - Server.SetRoute("/empty.html", _ => Task.Delay(-1)); - Page.DefaultTimeout = 0; - Page.DefaultNavigationTimeout = 1; - var exception = await Assert.ThrowsAnyAsync(async () => await Page.GoToAsync(TestConstants.EmptyPage)); - Assert.Contains("Timeout 1ms exceeded", exception.Message); - Assert.Contains(TestConstants.EmptyPage, exception.Message); - } - - [PlaywrightTest("page-goto.spec.ts", "should disable timeout when its set to 0")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDisableTimeoutWhenItsSetTo0() - { - bool loaded = false; - void OnLoad(object sender, IPage e) - { - loaded = true; - Page.Load -= OnLoad; - } - Page.Load += OnLoad; - - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html", WaitUntilState.Load, 0); - Assert.True(loaded); - } - - [PlaywrightTest("page-goto.spec.ts", "should fail when replaced by another navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWhenReplacedByAnotherNavigation() - { - Task anotherTask = null; - - // Hang for request to the empty.html - Server.SetRoute("/empty.html", _ => - { - anotherTask = Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); - return Task.Delay(-1); - }); - - var exception = await Assert.ThrowsAnyAsync(async () => await Page.GoToAsync(TestConstants.EmptyPage)); - await anotherTask; - - if (TestConstants.IsChromium) - { - Assert.Contains("net::ERR_ABORTED", exception.Message); - } - else if (TestConstants.IsWebKit) - { - Assert.Contains("cancelled", exception.Message); - } - else - { - Assert.Contains("NS_BINDING_ABORTED", exception.Message); - } - } - - [PlaywrightTest("page-goto.spec.ts", "should work when navigating to valid url")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWhenNavigatingToValidUrl() - { - var response = await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - - [PlaywrightTest("page-goto.spec.ts", "should work when navigating to data url")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWhenNavigatingToDataUrl() - { - var response = await Page.GoToAsync("data:text/html,hello"); - Assert.Null(response); - } - - [PlaywrightTest("page-goto.spec.ts", "should work when navigating to 404")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWhenNavigatingTo404() - { - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/not-found"); - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [PlaywrightTest("page-goto.spec.ts", "should return last response in redirect chain")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnLastResponseInRedirectChain() - { - Server.SetRedirect("/redirect/1.html", "/redirect/2.html"); - Server.SetRedirect("/redirect/2.html", "/redirect/3.html"); - Server.SetRedirect("/redirect/3.html", TestConstants.EmptyPage); - - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/redirect/1.html"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(TestConstants.EmptyPage, response.Url); - } - - [PlaywrightTest("page-goto.spec.ts", "should not leak listeners during navigation")] - [Fact(Skip = "We don't need this test")] - public void ShouldNotLeakListenersDuringNavigation() - { } - - [PlaywrightTest("page-goto.spec.ts", "should not leak listeners during bad navigation")] - [Fact(Skip = "We don't need this test")] - public void ShouldNotLeakListenersDuringBadNavigation() - { } - - [PlaywrightTest("page-goto.spec.ts", "should not leak listeners during navigation of 11 pages")] - [Fact(Skip = "We don't need this test")] - public void ShouldNotLeakListenersDuringNavigationOf11Pages() - { } - - [PlaywrightTest("page-goto.spec.ts", "should navigate to dataURL and not fire dataURL requests")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNavigateToDataURLAndNotFireDataURLRequests() - { - var requests = new List(); - Page.Request += (_, e) => requests.Add(e); - - string dataUrl = "data:text/html,
yo
"; - var response = await Page.GoToAsync(dataUrl); - Assert.Null(response); - Assert.Empty(requests); - } - - [PlaywrightTest("page-goto.spec.ts", "should navigate to URL with hash and fire requests without hash")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNavigateToURLWithHashAndFireRequestsWithoutHash() - { - var requests = new List(); - Page.Request += (_, e) => requests.Add(e); - - var response = await Page.GoToAsync(TestConstants.EmptyPage + "#hash"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(TestConstants.EmptyPage, response.Url); - Assert.Single(requests); - Assert.Equal(TestConstants.EmptyPage, requests[0].Url); - } - - [PlaywrightTest("page-goto.spec.ts", "should work with self requesting page")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithSelfRequestingPage() - { - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/self-request.html"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Contains("self-request.html", response.Url); - } - - [PlaywrightTest("page-goto.spec.ts", "should fail when navigating and show the url at the error message")] - // [Fact(Timeout = TestConstants.DefaultTestTimeout)] - [Fact(Skip = "Fix me #1058")] - public async Task ShouldFailWhenNavigatingAndShowTheUrlAtTheErrorMessage() - { - const string url = TestConstants.HttpsPrefix + "/redirect/1.html"; - var exception = await Assert.ThrowsAnyAsync(async () => await Page.GoToAsync(url)); - Assert.Contains(url, exception.Message); - } - - [PlaywrightTest("page-goto.spec.ts", "should be able to navigate to a page controlled by service worker")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToNavigateToAPageControlledByServiceWorker() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/serviceworkers/fetch/sw.html"); - await Page.EvaluateAsync("() => window.activationPromise"); - await Page.GoToAsync(TestConstants.ServerUrl + "/serviceworkers/fetch/sw.html"); - } - - [PlaywrightTest("page-goto.spec.ts", "should send referer")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSendReferer() - { - string referer1 = null; - string referer2 = null; - - await TaskUtils.WhenAll( - Server.WaitForRequest("/grid.html", r => referer1 = r.Headers["Referer"]), - Server.WaitForRequest("/digits/1.png", r => referer2 = r.Headers["Referer"]), - Page.GoToAsync(TestConstants.ServerUrl + "/grid.html", referer: "http://google.com/") - ); - - Assert.Equal("http://google.com/", referer1); - // Make sure subresources do not inherit referer. - Assert.Equal(TestConstants.ServerUrl + "/grid.html", referer2); - Assert.Equal(TestConstants.ServerUrl + "/grid.html", Page.Url); - } - - [PlaywrightTest("page-goto.spec.ts", "should reject referer option when setExtraHTTPHeaders provides referer")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRejectRefererOptionWhenSetExtraHTTPHeadersProvidesReferer() - { - await Page.SetExtraHttpHeadersAsync(new Dictionary - { - ["referer"] = "http://microsoft.com/" - }); - - var exception = await Assert.ThrowsAsync(async () => - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html", referer: "http://google.com/")); - - Assert.Contains("\"referer\" is already specified as extra HTTP header", exception.Message); - Assert.Contains(TestConstants.ServerUrl + "/grid.html", exception.Message); - } - - [PlaywrightTest("page-goto.spec.ts", "should override referrer-policy")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldOverrideReferrerPolicy() - { - Server.Subscribe("/grid.html", context => - { - context.Response.Headers["Referrer-Policy"] = "no-referrer"; - }); - - string referer1 = null; - string referer2 = null; - - var reqTask1 = Server.WaitForRequest("/grid.html", r => referer1 = r.Headers["Referer"]); - var reqTask2 = Server.WaitForRequest("/digits/1.png", r => referer2 = r.Headers["Referer"]); - await TaskUtils.WhenAll( - reqTask1, - reqTask2, - Page.GoToAsync(TestConstants.ServerUrl + "/grid.html", referer: "http://microsoft.com/")); - - Assert.Equal("http://microsoft.com/", referer1); - // Make sure subresources do not inherit referer. - Assert.Null(referer2); - Assert.Equal(TestConstants.ServerUrl + "/grid.html", Page.Url); - } - - [PlaywrightTest("page-goto.spec.ts", "should fail when canceled by another navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWhenCanceledByAnotherNavigation() - { - Server.SetRoute("/one-style.html", _ => Task.Delay(10_000)); - var request = Server.WaitForRequest("/one-style.html"); - var failed = Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html", TestConstants.IsFirefox ? WaitUntilState.NetworkIdle : WaitUntilState.Load); - await request; - await Page.GoToAsync(TestConstants.EmptyPage); - - await Assert.ThrowsAnyAsync(async () => await failed); - } - - [PlaywrightTest("page-goto.spec.ts", "extraHTTPHeaders should be pushed to provisional page")] - [Fact(Skip = "Skipped in Playwright")] - public void ExtraHTTPHeadersShouldBePushedToProvisionalPage() - { - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class GoToTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-goto.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(Page.Url, Is.EqualTo(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-goto.spec.ts", "should work with file URL")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithFileURL() + { + string fileurl = new Uri(TestUtils.GetWebServerFile(Path.Combine("frames", "two-frames.html"))).AbsoluteUri; + await Page.GoToAsync(fileurl); + Assert.That(Page.Url.ToLower(), Is.EqualTo(fileurl.ToLower())); + Assert.That(Page.Frames.Count, Is.EqualTo(3)); + } + + [PlaywrightTest("page-goto.spec.ts", "should use http for no protocol")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldUseHttpForNoProtocol() + { + await Page.GoToAsync(TestConstants.EmptyPage.Replace("http://", string.Empty)); + Assert.That(Page.Url, Is.EqualTo(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-goto.spec.ts", "should work cross-process")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkCrossProcess() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(Page.Url, Is.EqualTo(TestConstants.EmptyPage)); + + string url = TestConstants.CrossProcessHttpPrefix + "/empty.html"; + IFrame requestFrame = null; + Page.Request += (_, e) => + { + if (e.Url == url) + { + requestFrame = e.Frame; + } + }; + + var response = await Page.GoToAsync(url); + Assert.That(Page.Url, Is.EqualTo(url)); + Assert.That(response.Frame, Is.SameAs(Page.MainFrame)); + Assert.That(requestFrame, Is.SameAs(Page.MainFrame)); + Assert.That(response.Url, Is.EqualTo(url)); + } + + [PlaywrightTest("page-goto.spec.ts", "should capture iframe navigation request")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCaptureIframeNavigationRequest() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(Page.Url, Is.EqualTo(TestConstants.EmptyPage)); + + IFrame requestFrame = null; + Page.Request += (_, e) => + { + if (e.Url == TestConstants.ServerUrl + "/frames/frame.html") + { + requestFrame = e.Frame; + } + }; + + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); + Assert.That(Page.Url, Is.EqualTo(TestConstants.ServerUrl + "/frames/one-frame.html")); + Assert.That(response.Frame, Is.SameAs(Page.MainFrame)); + Assert.That(response.Url, Is.EqualTo(TestConstants.ServerUrl + "/frames/one-frame.html")); + + Assert.That(Page.Frames.Count, Is.EqualTo(2)); + Assert.That(requestFrame, Is.SameAs(Page.FirstChildFrame())); + } + + [PlaywrightTest("page-goto.spec.ts", "should capture cross-process iframe navigation request")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldCaptureCrossProcessIframeNavigationRequest() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(Page.Url, Is.EqualTo(TestConstants.EmptyPage)); + + IFrame requestFrame = null; + Page.Request += (_, e) => + { + if (e.Url == TestConstants.CrossProcessHttpPrefix + "/frames/frame.html") + { + requestFrame = e.Frame; + } + }; + + var response = await Page.GoToAsync(TestConstants.CrossProcessHttpPrefix + "/frames/one-frame.html"); + Assert.That(Page.Url, Is.EqualTo(TestConstants.CrossProcessHttpPrefix + "/frames/one-frame.html")); + Assert.That(response.Frame, Is.SameAs(Page.MainFrame)); + Assert.That(response.Url, Is.EqualTo(TestConstants.CrossProcessHttpPrefix + "/frames/one-frame.html")); + + Assert.That(Page.Frames.Count, Is.EqualTo(2)); + Assert.That(requestFrame, Is.SameAs(Page.FirstChildFrame())); + } + + [PlaywrightTest("page-goto.spec.ts", "should work with anchor navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithAnchorNavigation() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(Page.Url, Is.EqualTo(TestConstants.EmptyPage)); + await Page.GoToAsync($"{TestConstants.EmptyPage}#foo"); + Assert.That(Page.Url, Is.EqualTo($"{TestConstants.EmptyPage}#foo")); + await Page.GoToAsync($"{TestConstants.EmptyPage}#bar"); + Assert.That(Page.Url, Is.EqualTo($"{TestConstants.EmptyPage}#bar")); + } + + [PlaywrightTest("page-goto.spec.ts", "should work with redirects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithRedirects() + { + Server.SetRedirect("/redirect/1.html", "/redirect/2.html"); + Server.SetRedirect("/redirect/2.html", "/empty.html"); + + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/redirect/1.html"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + await Page.GoToAsync(TestConstants.EmptyPage); + } + + [PlaywrightTest("page-goto.spec.ts", "should navigate to about:blank")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNavigateToAboutBlank() + { + var response = await Page.GoToAsync(TestConstants.AboutBlank); + Assert.That(response, Is.Null); + } + + [PlaywrightTest("page-goto.spec.ts", "should return response when page changes its URL after load")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnResponseWhenPageChangesItsURLAfterLoad() + { + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/historyapi.html"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [PlaywrightTest("page-goto.spec.ts", "should work with subframes return 204")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithSubframesReturn204() + { + Server.SetRoute("/frames/frame.html", context => + { + context.Response.StatusCode = 204; + return Task.CompletedTask; + }); + await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); + } + + [PlaywrightTest("page-goto.spec.ts", "should work with subframes return 204")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWhenServerReturns204() + { + Server.SetRoute("/empty.html", context => + { + context.Response.StatusCode = 204; + return Task.CompletedTask; + }); + var exception = Assert.CatchAsync( + () => Page.GoToAsync(TestConstants.EmptyPage)); + + if (TestConstants.IsChromium) + { + Assert.That(exception.Message, Does.Contain("net::ERR_ABORTED")); + } + else if (TestConstants.IsFirefox) + { + Assert.That(exception.Message, Does.Contain("NS_BINDING_ABORTED")); + } + else + { + Assert.That(exception.Message, Does.Contain("Aborted: 204 No Content")); + } + } + + [PlaywrightTest("page-goto.spec.ts", "should navigate to empty page with domcontentloaded")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNavigateToEmptyPageWithDOMContentLoaded() + { + var response = await Page.GoToAsync(TestConstants.EmptyPage, WaitUntilState.DOMContentLoaded); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [PlaywrightTest("page-goto.spec.ts", "should work when page calls history API in beforeunload")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWhenPageCallsHistoryAPIInBeforeunload() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.EvaluateAsync(@"() => + { + window.addEventListener('beforeunload', () => history.replaceState(null, 'initial', window.location.href), false); + }"); + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [PlaywrightTest("page-goto.spec.ts", "should fail when navigating to bad url")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWhenNavigatingToBadUrl() + { + var exception = Assert.CatchAsync(async () => await Page.GoToAsync("asdfasdf")); + if (TestConstants.IsChromium || TestConstants.IsWebKit) + { + Assert.That(exception.Message, Does.Contain("Cannot navigate to invalid URL")); + } + else + { + Assert.That(exception.Message, Does.Contain("Invalid url")); + } + } + + [PlaywrightTest("page-goto.spec.ts", "should fail when navigating to bad SSL")] + // [Test, Timeout(TestConstants.DefaultTestTimeout)] + [Test, Ignore("Fix me #1058")] + public async Task ShouldFailWhenNavigatingToBadSSL() + { + Page.Request += (_, e) => Assert.That(e, Is.Not.Null); + Page.RequestFinished += (_, e) => Assert.That(e, Is.Not.Null); + Page.RequestFailed += (_, e) => Assert.That(e, Is.Not.Null); + + var exception = Assert.CatchAsync(async () => await Page.GoToAsync(TestConstants.HttpsPrefix + "/empty.html")); + TestUtils.AssertSSLError(exception.Message); + } + + [PlaywrightTest("page-goto.spec.ts", "should fail when navigating to bad SSL after redirects")] + // [Test, Timeout(TestConstants.DefaultTestTimeout)] + [Test, Ignore("Fix me #1058")] + public async Task ShouldFailWhenNavigatingToBadSSLAfterRedirects() + { + Server.SetRedirect("/redirect/1.html", "/redirect/2.html"); + Server.SetRedirect("/redirect/2.html", "/empty.html"); + var exception = Assert.CatchAsync(async () => await Page.GoToAsync(TestConstants.HttpsPrefix + "/redirect/1.html")); + TestUtils.AssertSSLError(exception.Message); + } + + [PlaywrightTest("page-goto.spec.ts", "should not crash when navigating to bad SSL after a cross origin navigation")] + // [Test, Timeout(TestConstants.DefaultTestTimeout)] + [Test, Ignore("Fix me #1058")] + public async Task ShouldNotCrashWhenNavigatingToBadSSLAfterACrossOriginNavigation() + { + await Page.GoToAsync(TestConstants.CrossProcessHttpPrefix + "/empty.html"); + await Page.GoToAsync(TestConstants.HttpsPrefix + "/empty.html").ContinueWith(_ => { }); + } + + [PlaywrightTest("page-goto.spec.ts", "should throw if networkidle0 is passed as an option")] + [Test, Ignore("We don't need this test")] + public void ShouldThrowIfNetworkIdle0IsPassedAsAnOption() + { + } + [PlaywrightTest("page-goto.spec.ts", "should throw if networkidle2 is passed as an option")] + [Test, Ignore("We don't need this test")] + public void ShouldThrowIfNetworkIdle2IsPassedAsAnOption() + { + } + [PlaywrightTest("page-goto.spec.ts", "should throw if networkidle is passed as an option")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWhenMainResourcesFailedToLoad() + { + var exception = Assert.CatchAsync(async () => await Page.GoToAsync("http://localhost:44123/non-existing-url")); + + if (TestConstants.IsChromium) + { + Assert.That(exception.Message, Does.Contain("net::ERR_CONNECTION_REFUSED")); + } + else if (TestConstants.IsWebKit && TestConstants.IsWindows) + { + Assert.That(exception.Message, Does.Contain("Couldn't connect to server")); + } + else if (TestConstants.IsWebKit) + { + Assert.That(exception.Message, Does.Contain("Could not connect")); + } + else + { + Assert.That(exception.Message, Does.Contain("NS_ERROR_CONNECTION_REFUSED")); + } + } + + [PlaywrightTest("page-goto.spec.ts", "should fail when exceeding maximum navigation timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWhenExceedingMaximumNavigationTimeout() + { + Server.SetRoute("/empty.html", _ => Task.Delay(-1)); + var exception = Assert.ThrowsAsync(async () + => await Page.GoToAsync(TestConstants.EmptyPage, timeout: 1)); + Assert.That(exception.Message, Does.Contain("Timeout 1ms exceeded")); + Assert.That(exception.Message, Does.Contain(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-goto.spec.ts", "should fail when exceeding maximum navigation timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWhenExceedingDefaultMaximumNavigationTimeout() + { + Server.SetRoute("/empty.html", _ => Task.Delay(-1)); + Page.Context.DefaultNavigationTimeout = 2; + Page.DefaultNavigationTimeout = 1; + var exception = Assert.ThrowsAsync(async () => await Page.GoToAsync(TestConstants.EmptyPage)); + Assert.That(exception.Message, Does.Contain("Timeout 1ms exceeded")); + Assert.That(exception.Message, Does.Contain(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-goto.spec.ts", "should fail when exceeding browser context navigation timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWhenExceedingBrowserContextNavigationTimeout() + { + Server.SetRoute("/empty.html", _ => Task.Delay(-1)); + Page.Context.DefaultNavigationTimeout = 2; + var exception = Assert.ThrowsAsync(async () => await Page.GoToAsync(TestConstants.EmptyPage)); + Assert.That(exception.Message, Does.Contain("Timeout 2ms exceeded")); + Assert.That(exception.Message, Does.Contain(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-goto.spec.ts", "should fail when exceeding default maximum timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWhenExceedingDefaultMaximumTimeout() + { + Server.SetRoute("/empty.html", _ => Task.Delay(-1)); + Page.Context.DefaultTimeout = 2; + Page.DefaultTimeout = 1; + var exception = Assert.ThrowsAsync(async () => await Page.GoToAsync(TestConstants.EmptyPage)); + Assert.That(exception.Message, Does.Contain("Timeout 1ms exceeded")); + Assert.That(exception.Message, Does.Contain(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-goto.spec.ts", "should fail when exceeding browser context timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWhenExceedingBrowserContextTimeout() + { + Server.SetRoute("/empty.html", _ => Task.Delay(-1)); + Page.Context.DefaultTimeout = 2; + var exception = Assert.ThrowsAsync(async () => await Page.GoToAsync(TestConstants.EmptyPage)); + Assert.That(exception.Message, Does.Contain("Timeout 2ms exceeded")); + Assert.That(exception.Message, Does.Contain(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-goto.spec.ts", "should prioritize default navigation timeout over default timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldPrioritizeDefaultNavigationTimeoutOverDefaultTimeout() + { + // Hang for request to the empty.html + Server.SetRoute("/empty.html", _ => Task.Delay(-1)); + Page.DefaultTimeout = 0; + Page.DefaultNavigationTimeout = 1; + var exception = Assert.CatchAsync(async () => await Page.GoToAsync(TestConstants.EmptyPage)); + Assert.That(exception.Message, Does.Contain("Timeout 1ms exceeded")); + Assert.That(exception.Message, Does.Contain(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-goto.spec.ts", "should disable timeout when its set to 0")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDisableTimeoutWhenItsSetTo0() + { + bool loaded = false; + void OnLoad(object sender, IPage e) + { + loaded = true; + Page.Load -= OnLoad; + } + Page.Load += OnLoad; + + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html", WaitUntilState.Load, 0); + Assert.That(loaded, Is.True); + } + + [PlaywrightTest("page-goto.spec.ts", "should fail when replaced by another navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWhenReplacedByAnotherNavigation() + { + Task anotherTask = null; + + // Hang for request to the empty.html + Server.SetRoute("/empty.html", _ => + { + anotherTask = Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); + return Task.Delay(-1); + }); + + var exception = Assert.CatchAsync(async () => await Page.GoToAsync(TestConstants.EmptyPage)); + await anotherTask; + + if (TestConstants.IsChromium) + { + Assert.That(exception.Message, Does.Contain("net::ERR_ABORTED")); + } + else if (TestConstants.IsWebKit) + { + Assert.That(exception.Message, Does.Contain("cancelled")); + } + else + { + Assert.That(exception.Message, Does.Contain("NS_BINDING_ABORTED")); + } + } + + [PlaywrightTest("page-goto.spec.ts", "should work when navigating to valid url")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWhenNavigatingToValidUrl() + { + var response = await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [PlaywrightTest("page-goto.spec.ts", "should work when navigating to data url")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWhenNavigatingToDataUrl() + { + var response = await Page.GoToAsync("data:text/html,hello"); + Assert.That(response, Is.Null); + } + + [PlaywrightTest("page-goto.spec.ts", "should work when navigating to 404")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWhenNavigatingTo404() + { + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/not-found"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NotFound)); + } + + [PlaywrightTest("page-goto.spec.ts", "should return last response in redirect chain")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnLastResponseInRedirectChain() + { + Server.SetRedirect("/redirect/1.html", "/redirect/2.html"); + Server.SetRedirect("/redirect/2.html", "/redirect/3.html"); + Server.SetRedirect("/redirect/3.html", TestConstants.EmptyPage); + + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/redirect/1.html"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + Assert.That(response.Url, Is.EqualTo(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-goto.spec.ts", "should not leak listeners during navigation")] + [Test, Ignore("We don't need this test")] + public void ShouldNotLeakListenersDuringNavigation() + { + } + [PlaywrightTest("page-goto.spec.ts", "should not leak listeners during bad navigation")] + [Test, Ignore("We don't need this test")] + public void ShouldNotLeakListenersDuringBadNavigation() + { + } + [PlaywrightTest("page-goto.spec.ts", "should not leak listeners during navigation of 11 pages")] + [Test, Ignore("We don't need this test")] + public void ShouldNotLeakListenersDuringNavigationOf11Pages() + { + } + [PlaywrightTest("page-goto.spec.ts", "should navigate to dataURL and not fire dataURL requests")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNavigateToDataURLAndNotFireDataURLRequests() + { + var requests = new List(); + Page.Request += (_, e) => requests.Add(e); + + string dataUrl = "data:text/html,
yo
"; + var response = await Page.GoToAsync(dataUrl); + Assert.That(response, Is.Null); + Assert.That(requests, Is.Empty); + } + + [PlaywrightTest("page-goto.spec.ts", "should navigate to URL with hash and fire requests without hash")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNavigateToURLWithHashAndFireRequestsWithoutHash() + { + var requests = new List(); + Page.Request += (_, e) => requests.Add(e); + + var response = await Page.GoToAsync(TestConstants.EmptyPage + "#hash"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + Assert.That(response.Url, Is.EqualTo(TestConstants.EmptyPage)); + Assert.That(requests, Has.Exactly(1).Items); + Assert.That(requests[0].Url, Is.EqualTo(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-goto.spec.ts", "should work with self requesting page")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithSelfRequestingPage() + { + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/self-request.html"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + Assert.That(response.Url, Does.Contain("self-request.html")); + } + + [PlaywrightTest("page-goto.spec.ts", "should fail when navigating and show the url at the error message")] + // [Test, Timeout(TestConstants.DefaultTestTimeout)] + [Test, Ignore("Fix me #1058")] + public async Task ShouldFailWhenNavigatingAndShowTheUrlAtTheErrorMessage() + { + const string url = TestConstants.HttpsPrefix + "/redirect/1.html"; + var exception = Assert.CatchAsync(async () => await Page.GoToAsync(url)); + Assert.That(exception.Message, Does.Contain(url)); + } + + [PlaywrightTest("page-goto.spec.ts", "should be able to navigate to a page controlled by service worker")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToNavigateToAPageControlledByServiceWorker() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/serviceworkers/fetch/sw.html"); + await Page.EvaluateAsync("() => window.activationPromise"); + await Page.GoToAsync(TestConstants.ServerUrl + "/serviceworkers/fetch/sw.html"); + } + + [PlaywrightTest("page-goto.spec.ts", "should send referer")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSendReferer() + { + string referer1 = null; + string referer2 = null; + + await TaskUtils.WhenAll( + Server.WaitForRequest("/grid.html", r => referer1 = r.Headers["Referer"]), + Server.WaitForRequest("/digits/1.png", r => referer2 = r.Headers["Referer"]), + Page.GoToAsync(TestConstants.ServerUrl + "/grid.html", referer: "http://google.com/") + ); + + Assert.That(referer1, Is.EqualTo("http://google.com/")); + // Make sure subresources do not inherit referer. + Assert.That(referer2, Is.EqualTo(TestConstants.ServerUrl + "/grid.html")); + Assert.That(Page.Url, Is.EqualTo(TestConstants.ServerUrl + "/grid.html")); + } + + [PlaywrightTest("page-goto.spec.ts", "should reject referer option when setExtraHTTPHeaders provides referer")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRejectRefererOptionWhenSetExtraHTTPHeadersProvidesReferer() + { + await Page.SetExtraHttpHeadersAsync(new Dictionary + { + ["referer"] = "http://microsoft.com/" + }); + + var exception = Assert.ThrowsAsync(async () => + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html", referer: "http://google.com/")); + + Assert.That(exception.Message, Does.Contain("\"referer\" is already specified as extra HTTP header")); + Assert.That(exception.Message, Does.Contain(TestConstants.ServerUrl + "/grid.html")); + } + + [PlaywrightTest("page-goto.spec.ts", "should override referrer-policy")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldOverrideReferrerPolicy() + { + Server.Subscribe("/grid.html", context => + { + context.Response.Headers["Referrer-Policy"] = "no-referrer"; + }); + + string referer1 = null; + string referer2 = null; + + var reqTask1 = Server.WaitForRequest("/grid.html", r => referer1 = r.Headers["Referer"]); + var reqTask2 = Server.WaitForRequest("/digits/1.png", r => referer2 = r.Headers["Referer"]); + await TaskUtils.WhenAll( + reqTask1, + reqTask2, + Page.GoToAsync(TestConstants.ServerUrl + "/grid.html", referer: "http://microsoft.com/")); + + Assert.That(referer1, Is.EqualTo("http://microsoft.com/")); + // Make sure subresources do not inherit referer. + Assert.That(referer2, Is.Null); + Assert.That(Page.Url, Is.EqualTo(TestConstants.ServerUrl + "/grid.html")); + } + + [PlaywrightTest("page-goto.spec.ts", "should fail when canceled by another navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWhenCanceledByAnotherNavigation() + { + Server.SetRoute("/one-style.html", _ => Task.Delay(10_000)); + var request = Server.WaitForRequest("/one-style.html"); + var failed = Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html", TestConstants.IsFirefox ? WaitUntilState.NetworkIdle : WaitUntilState.Load); + await request; + await Page.GoToAsync(TestConstants.EmptyPage); + + Assert.CatchAsync(async () => await failed); + } + + [PlaywrightTest("page-goto.spec.ts", "extraHTTPHeaders should be pushed to provisional page")] + [Test, Ignore("Skipped in Playwright")] + public void ExtraHTTPHeadersShouldBePushedToProvisionalPage() + { + } + + } +} diff --git a/src/Playwright.Tests/PageHistoryTests.cs b/src/PlaywrightSharp.Tests/PageHistoryTests.cs similarity index 56% rename from src/Playwright.Tests/PageHistoryTests.cs rename to src/PlaywrightSharp.Tests/PageHistoryTests.cs index 6b2a7d3219..a6b676f215 100644 --- a/src/Playwright.Tests/PageHistoryTests.cs +++ b/src/PlaywrightSharp.Tests/PageHistoryTests.cs @@ -1,72 +1,64 @@ -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageHistoryTests : PlaywrightSharpPageBaseTest - { - /// - public PageHistoryTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-history.spec.ts", "page.goBack should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PageGobackShouldWork() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - - var response = await Page.GoBackAsync(); - Assert.True(response.Ok); - Assert.Contains(TestConstants.EmptyPage, response.Url); - - response = await Page.GoForwardAsync(); - Assert.True(response.Ok); - Assert.Contains("/grid.html", response.Url); - - response = await Page.GoForwardAsync(); - Assert.Null(response); - } - - [PlaywrightTest("page-history.spec.ts", "page.goBack should work with HistoryAPI")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PageGoBackShouldWorkWithHistoryAPI() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.EvaluateAsync(@" - history.pushState({ }, '', '/first.html'); - history.pushState({ }, '', '/second.html'); - "); - Assert.Equal(TestConstants.ServerUrl + "/second.html", Page.Url); - - await Page.GoBackAsync(); - Assert.Equal(TestConstants.ServerUrl + "/first.html", Page.Url); - await Page.GoBackAsync(); - Assert.Equal(TestConstants.EmptyPage, Page.Url); - await Page.GoForwardAsync(); - Assert.Equal(TestConstants.ServerUrl + "/first.html", Page.Url); - } - - [PlaywrightTest("page-history.spec.ts", "should work for file urls")] - [Fact(Skip = "We need screenshots for this")] - public void ShouldWorkForFileUrls() - { - } - - - [PlaywrightTest("page-history.spec.ts", "page.reload should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PageReloadShouldWork() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.EvaluateAsync("() => window._foo = 10"); - await Page.ReloadAsync(); - Assert.Null(await Page.EvaluateAsync("() => window._foo")); - } - } -} +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageHistoryTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-history.spec.ts", "page.goBack should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PageGobackShouldWork() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + + var response = await Page.GoBackAsync(); + Assert.That(response.Ok, Is.True); + Assert.That(response.Url, Does.Contain(TestConstants.EmptyPage)); + + response = await Page.GoForwardAsync(); + Assert.That(response.Ok, Is.True); + Assert.That(response.Url, Does.Contain("/grid.html")); + + response = await Page.GoForwardAsync(); + Assert.That(response, Is.Null); + } + + [PlaywrightTest("page-history.spec.ts", "page.goBack should work with HistoryAPI")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PageGoBackShouldWorkWithHistoryAPI() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.EvaluateAsync(@" + history.pushState({ }, '', '/first.html'); + history.pushState({ }, '', '/second.html'); + "); + Assert.That(Page.Url, Is.EqualTo(TestConstants.ServerUrl + "/second.html")); + + await Page.GoBackAsync(); + Assert.That(Page.Url, Is.EqualTo(TestConstants.ServerUrl + "/first.html")); + await Page.GoBackAsync(); + Assert.That(Page.Url, Is.EqualTo(TestConstants.EmptyPage)); + await Page.GoForwardAsync(); + Assert.That(Page.Url, Is.EqualTo(TestConstants.ServerUrl + "/first.html")); + } + + [PlaywrightTest("page-history.spec.ts", "should work for file urls")] + [Test, Ignore("We need screenshots for this")] + public void ShouldWorkForFileUrls() + { + } + + [PlaywrightTest("page-history.spec.ts", "page.reload should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PageReloadShouldWork() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.EvaluateAsync("() => window._foo = 10"); + await Page.ReloadAsync(); + Assert.That(await Page.EvaluateAsync("() => window._foo"), Is.Null); + } + } +} diff --git a/src/Playwright.Tests/PageKeyboardTests.cs b/src/PlaywrightSharp.Tests/PageKeyboardTests.cs similarity index 68% rename from src/Playwright.Tests/PageKeyboardTests.cs rename to src/PlaywrightSharp.Tests/PageKeyboardTests.cs index 5295ca72fb..6c43e1ca7e 100644 --- a/src/Playwright.Tests/PageKeyboardTests.cs +++ b/src/PlaywrightSharp.Tests/PageKeyboardTests.cs @@ -1,581 +1,564 @@ -using System; -using System.Collections.Generic; -using System.Dynamic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageKeyboardTests : PlaywrightSharpPageBaseTest - { - /// - public PageKeyboardTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-keyboard.spec.ts", "should type into a textarea")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTypeIntoATextarea() - { - await Page.EvaluateAsync(@"() => { - var textarea = document.createElement('textarea'); - document.body.appendChild(textarea); - textarea.focus(); - }"); - string text = "Hello world. I am the text that was typed!"; - await Page.Keyboard.TypeAsync(text); - Assert.Equal(text, await Page.EvaluateAsync("() => document.querySelector('textarea').value")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should press the metaKey")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldPressTheMetaKey1() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/empty.html"); - await Page.EvaluateAsync(@"() => { - window.keyPromise = new Promise(resolve => document.addEventListener('keydown', event => resolve(event.key))); - }"); - await Page.Keyboard.PressAsync("Meta"); - Assert.Equal(TestConstants.IsFirefox && !TestConstants.IsMacOSX ? "OS" : "Meta", await Page.EvaluateAsync("keyPromise")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should move with the arrow keys")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldMoveWithTheArrowKeys() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.TypeAsync("textarea", "Hello World!"); - Assert.Equal("Hello World!", await Page.EvaluateAsync("() => document.querySelector('textarea').value")); - for (int i = 0; i < "World!".Length; i++) - { - _ = Page.Keyboard.PressAsync("ArrowLeft"); - } - await Page.Keyboard.TypeAsync("inserted "); - Assert.Equal("Hello inserted World!", await Page.EvaluateAsync("() => document.querySelector('textarea').value")); - _ = Page.Keyboard.DownAsync("Shift"); - for (int i = 0; i < "inserted ".Length; i++) - { - _ = Page.Keyboard.PressAsync("ArrowLeft"); - } - _ = Page.Keyboard.UpAsync("Shift"); - await Page.Keyboard.PressAsync("Backspace"); - Assert.Equal("Hello World!", await Page.EvaluateAsync("() => document.querySelector('textarea').value")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should send a character with ElementHandle.press")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSendACharacterWithElementHandlePress() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - var textarea = await Page.QuerySelectorAsync("textarea"); - await textarea.PressAsync("a"); - Assert.Equal("a", await Page.EvaluateAsync("() => document.querySelector('textarea').value")); - - await Page.EvaluateAsync("() => window.addEventListener('keydown', e => e.preventDefault(), true)"); - - await textarea.PressAsync("b"); - Assert.Equal("a", await Page.EvaluateAsync("() => document.querySelector('textarea').value")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should send a character with sendCharacter")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSendACharacterWithSendCharacter() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.FocusAsync("textarea"); - await Page.Keyboard.InsertTextAsync("嗨"); - Assert.Equal("嗨", await Page.EvaluateAsync("() => document.querySelector('textarea').value")); - await Page.EvaluateAsync("() => window.addEventListener('keydown', e => e.preventDefault(), true)"); - await Page.Keyboard.InsertTextAsync("a"); - Assert.Equal("嗨a", await Page.EvaluateAsync("() => document.querySelector('textarea').value")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "insertText should only emit input event")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task InsertTextShouldOnlyEmitInputEvent() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.FocusAsync("textarea"); - - var events = await Page.EvaluateHandleAsync(@"() => { - const events = []; - document.addEventListener('keydown', e => events.push(e.type)); - document.addEventListener('keyup', e => events.push(e.type)); - document.addEventListener('keypress', e => events.push(e.type)); - document.addEventListener('input', e => events.push(e.type)); - return events; - }"); - - await Page.Keyboard.InsertTextAsync("hello world"); - Assert.Equal(new[] { "input" }, await events.JsonValueAsync()); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should report shiftKey")] - [SkipBrowserAndPlatformFact(skipFirefox: true, skipOSX: true)] - public async Task ShouldReportShiftKey() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); - var keyboard = Page.Keyboard; - var codeForKey = new Dictionary { ["Shift"] = 16, ["Alt"] = 18, ["Control"] = 17 }; - foreach (string modifierKey in codeForKey.Keys) - { - int modifierValue = codeForKey[modifierKey]; - await keyboard.DownAsync(modifierKey); - Assert.Equal($"Keydown: {modifierKey} {modifierKey}Left {modifierValue} [{modifierKey}]", await Page.EvaluateAsync("() => getResult()")); - await keyboard.DownAsync("!"); - // Shift+! will generate a keypress - if (modifierKey == "Shift") - { - Assert.Equal($"Keydown: ! Digit1 49 [{modifierKey}]\nKeypress: ! Digit1 33 33 [{modifierKey}]", await Page.EvaluateAsync("() => getResult()")); - } - else - { - Assert.Equal($"Keydown: ! Digit1 49 [{modifierKey}]", await Page.EvaluateAsync("() => getResult()")); - } - - await keyboard.UpAsync("!"); - Assert.Equal($"Keyup: ! Digit1 49 [{modifierKey}]", await Page.EvaluateAsync("() => getResult()")); - await keyboard.UpAsync(modifierKey); - Assert.Equal($"Keyup: {modifierKey} {modifierKey}Left {modifierValue} []", await Page.EvaluateAsync("() => getResult()")); - } - } - - [PlaywrightTest("page-keyboard.spec.ts", "should report multiple modifiers")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReportMultipleModifiers() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); - var keyboard = Page.Keyboard; - await keyboard.DownAsync("Control"); - Assert.Equal("Keydown: Control ControlLeft 17 [Control]", await Page.EvaluateAsync("() => getResult()")); - await keyboard.DownAsync("Alt"); - Assert.Equal("Keydown: Alt AltLeft 18 [Alt Control]", await Page.EvaluateAsync("() => getResult()")); - await keyboard.DownAsync(";"); - Assert.Equal("Keydown: ; Semicolon 186 [Alt Control]", await Page.EvaluateAsync("() => getResult()")); - await keyboard.UpAsync(";"); - Assert.Equal("Keyup: ; Semicolon 186 [Alt Control]", await Page.EvaluateAsync("() => getResult()")); - await keyboard.UpAsync("Control"); - Assert.Equal("Keyup: Control ControlLeft 17 [Alt]", await Page.EvaluateAsync("() => getResult()")); - await keyboard.UpAsync("Alt"); - Assert.Equal("Keyup: Alt AltLeft 18 []", await Page.EvaluateAsync("() => getResult()")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should send proper codes while typing")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSendProperCodesWhileTyping() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); - await Page.Keyboard.TypeAsync("!"); - Assert.Equal(string.Join("\n", - "Keydown: ! Digit1 49 []", - "Keypress: ! Digit1 33 33 []", - "Keyup: ! Digit1 49 []"), await Page.EvaluateAsync("() => getResult()")); - await Page.Keyboard.TypeAsync("^"); - Assert.Equal(string.Join("\n", - "Keydown: ^ Digit6 54 []", - "Keypress: ^ Digit6 94 94 []", - "Keyup: ^ Digit6 54 []"), await Page.EvaluateAsync("() => getResult()")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should send proper codes while typing with shift")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSendProperCodesWhileTypingWithShift() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); - var keyboard = Page.Keyboard; - await keyboard.DownAsync("Shift"); - await Page.Keyboard.TypeAsync("~"); - Assert.Equal(string.Join("\n", - "Keydown: Shift ShiftLeft 16 [Shift]", - "Keydown: ~ Backquote 192 [Shift]", // 192 is ` keyCode - "Keypress: ~ Backquote 126 126 [Shift]", // 126 is ~ charCode - "Keyup: ~ Backquote 192 [Shift]"), await Page.EvaluateAsync("() => getResult()")); - await keyboard.UpAsync("Shift"); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should not type canceled events")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotTypeCanceledEvents() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.FocusAsync("textarea"); - await Page.EvaluateAsync(@"() =>{ - window.addEventListener('keydown', event => { - event.stopPropagation(); - event.stopImmediatePropagation(); - if (event.key === 'l') - event.preventDefault(); - if (event.key === 'o') - event.preventDefault(); - }, false); - }"); - await Page.Keyboard.TypeAsync("Hello World!"); - Assert.Equal("He Wrd!", await Page.EvaluateAsync("() => textarea.value")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should press plus")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldPressPlus() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); - await Page.Keyboard.PressAsync("+"); - Assert.Equal( - string.Join( - "\n", - new[] - { - "Keydown: + Equal 187 []", // 192 is ` keyCode - "Keypress: + Equal 43 43 []", // 126 is ~ charCode - "Keyup: + Equal 187 []" - }), - await Page.EvaluateAsync("() => getResult()")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should press shift plus")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldPressShiftPlus() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); - await Page.Keyboard.PressAsync("Shift++"); - Assert.Equal( - string.Join( - "\n", - new[] - { - "Keydown: Shift ShiftLeft 16 [Shift]", - "Keydown: + Equal 187 [Shift]", // 192 is ` keyCode - "Keypress: + Equal 43 43 [Shift]", // 126 is ~ charCode - "Keyup: + Equal 187 [Shift]", - "Keyup: Shift ShiftLeft 16 []" - }), - await Page.EvaluateAsync("() => getResult()")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should support plus-separated modifiers")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportPlusSeparatedModifiers() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); - await Page.Keyboard.PressAsync("Shift+~"); - Assert.Equal( - string.Join( - "\n", - new[] - { - "Keydown: Shift ShiftLeft 16 [Shift]", - "Keydown: ~ Backquote 192 [Shift]", // 192 is ` keyCode - "Keypress: ~ Backquote 126 126 [Shift]", // 126 is ~ charCode - "Keyup: ~ Backquote 192 [Shift]", - "Keyup: Shift ShiftLeft 16 []" - }), - await Page.EvaluateAsync("() => getResult()")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should support multiple plus-separated modifiers")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportMultiplePlusSeparatedModifiers() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); - await Page.Keyboard.PressAsync("Control+Shift+~"); - Assert.Equal( - string.Join( - "\n", - new[] - { - "Keydown: Control ControlLeft 17 [Control]", - "Keydown: Shift ShiftLeft 16 [Control Shift]", - "Keydown: ~ Backquote 192 [Control Shift]", // 192 is ` keyCode - "Keyup: ~ Backquote 192 [Control Shift]", - "Keyup: Shift ShiftLeft 16 [Control]", - "Keyup: Control ControlLeft 17 []" - }), - await Page.EvaluateAsync("() => getResult()")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should shift raw codes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldShiftRawCodes() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); - await Page.Keyboard.PressAsync("Shift+Digit3"); - Assert.Equal( - string.Join( - "\n", - new[] - { - "Keydown: Shift ShiftLeft 16 [Shift]", - "Keydown: # Digit3 51 [Shift]", // 51 is # keyCode - "Keypress: # Digit3 35 35 [Shift]", // 35 is # charCode - "Keyup: # Digit3 51 [Shift]", - "Keyup: Shift ShiftLeft 16 []" - }), - await Page.EvaluateAsync("() => getResult()")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should specify repeat property")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSpecifyRepeatProperty() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.FocusAsync("textarea"); - var lastEvent = await CaptureLastKeydownAsync(Page); - await Page.EvaluateAsync("() => document.querySelector('textarea').addEventListener('keydown', e => window.lastEvent = e, true)"); - await Page.Keyboard.DownAsync("a"); - Assert.False(await lastEvent.EvaluateAsync("e => e.repeat")); - await Page.Keyboard.PressAsync("a"); - Assert.True(await lastEvent.EvaluateAsync("e => e.repeat")); - - await Page.Keyboard.DownAsync("b"); - Assert.False(await lastEvent.EvaluateAsync("e => e.repeat")); - await Page.Keyboard.DownAsync("b"); - Assert.True(await lastEvent.EvaluateAsync("e => e.repeat")); - - await Page.Keyboard.UpAsync("a"); - await Page.Keyboard.DownAsync("a"); - Assert.False(await lastEvent.EvaluateAsync("e => e.repeat")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should type all kinds of characters")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTypeAllKindsOfCharacters() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.FocusAsync("textarea"); - string text = "This text goes onto two lines.\nThis character is 嗨."; - await Page.Keyboard.TypeAsync(text); - Assert.Equal(text, await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should specify location")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSpecifyLocation() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - var lastEventHandle = await CaptureLastKeydownAsync(Page); - var textarea = await Page.QuerySelectorAsync("textarea"); - - await textarea.PressAsync("Digit5"); - Assert.Equal(0, await lastEventHandle.EvaluateAsync("e => e.location")); - - await textarea.PressAsync("ControlLeft"); - Assert.Equal(1, await lastEventHandle.EvaluateAsync("e => e.location")); - - await textarea.PressAsync("ControlRight"); - Assert.Equal(2, await lastEventHandle.EvaluateAsync("e => e.location")); - - await textarea.PressAsync("NumpadSubtract"); - Assert.Equal(3, await lastEventHandle.EvaluateAsync("e => e.location")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should press Enter")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldPressEnter() - { - await Page.SetContentAsync(""); - await Page.FocusAsync("textarea"); - var lastEventHandle = await CaptureLastKeydownAsync(Page); - - await TestEnterKeyAsync("Enter", "Enter", "Enter"); - await TestEnterKeyAsync("NumpadEnter", "Enter", "NumpadEnter"); - await TestEnterKeyAsync("\n", "Enter", "Enter"); - await TestEnterKeyAsync("\r", "Enter", "Enter"); - - async Task TestEnterKeyAsync(string key, string expectedKey, string expectedCode) - { - await Page.Keyboard.PressAsync(key); - dynamic lastEvent = await lastEventHandle.JsonValueAsync(); - Assert.Equal(expectedKey, lastEvent.key); - Assert.Equal(expectedCode, lastEvent.code); - - string value = await Page.EvalOnSelectorAsync("textarea", "t => t.value"); - Assert.Equal("\n", value); - await Page.EvalOnSelectorAsync("textarea", "t => t.value = ''"); - } - } - - [PlaywrightTest("page-keyboard.spec.ts", "should throw on unknown keys")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowOnUnknownKeys() - { - var exception = await Assert.ThrowsAsync(() => Page.Keyboard.PressAsync("NotARealKey")); - Assert.Equal("Unknown key: \"NotARealKey\"", exception.Message); - - exception = await Assert.ThrowsAsync(() => Page.Keyboard.PressAsync("ё")); - Assert.Equal("Unknown key: \"ё\"", exception.Message); - - exception = await Assert.ThrowsAsync(() => Page.Keyboard.PressAsync("😊")); - Assert.Equal("Unknown key: \"😊\"", exception.Message); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should type emoji")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTypeEmoji() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.TypeAsync("textarea", "👹 Tokyo street Japan 🇯🇵"); - Assert.Equal("👹 Tokyo street Japan 🇯🇵", await Page.EvalOnSelectorAsync("textarea", "textarea => textarea.value")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should type emoji into an iframe")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTypeEmojiIntoAnIframe() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await FrameUtils.AttachFrameAsync(Page, "emoji-test", TestConstants.ServerUrl + "/input/textarea.html"); - var frame = Page.Frames.ElementAt(1); - var textarea = await frame.QuerySelectorAsync("textarea"); - await textarea.TypeAsync("👹 Tokyo street Japan 🇯🇵"); - Assert.Equal("👹 Tokyo street Japan 🇯🇵", await frame.EvalOnSelectorAsync("textarea", "textarea => textarea.value")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should handle selectAll")] - [SkipBrowserAndPlatformFact(skipOSX: true, skipChromium: true)] - public async Task ShouldHandleSelectAll() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - var textarea = await Page.QuerySelectorAsync("textarea"); - await textarea.TypeAsync("some text"); - string modifier = TestConstants.IsMacOSX ? "Meta" : "Control"; - await Page.Keyboard.DownAsync(modifier); - await Page.Keyboard.PressAsync("a"); - await Page.Keyboard.UpAsync(modifier); - await Page.Keyboard.PressAsync("Backspace"); - Assert.Empty(await Page.EvalOnSelectorAsync("textarea", "textarea => textarea.value")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should be able to prevent selectAll")] - [SkipBrowserAndPlatformFact(skipOSX: true, skipChromium: true)] - public async Task ShouldBeAbleToPreventSelectAll() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - var textarea = await Page.QuerySelectorAsync("textarea"); - await textarea.TypeAsync("some text"); - await Page.EvalOnSelectorAsync("textarea", @"textarea => { - textarea.addEventListener('keydown', event => { - if (event.key === 'a' && (event.metaKey || event.ctrlKey)) - event.preventDefault(); - }, false); - }"); - string modifier = TestConstants.IsMacOSX ? "Meta" : "Control"; - await Page.Keyboard.DownAsync(modifier); - await Page.Keyboard.PressAsync("a"); - await Page.Keyboard.UpAsync(modifier); - await Page.Keyboard.PressAsync("Backspace"); - Assert.Equal("some tex", await Page.EvalOnSelectorAsync("textarea", "textarea => textarea.value")); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should press the meta key")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldPressTheMetaKey2() - { - var lastEventHandle = await CaptureLastKeydownAsync(Page); - await Page.Keyboard.PressAsync("Meta"); - dynamic result = await lastEventHandle.JsonValueAsync(); - string key = result.key; - string code = result.code; - bool metaKey = result.metaKey; - - if (TestConstants.IsFirefox && !TestConstants.IsMacOSX) - { - Assert.Equal("OS", key); - } - else - { - Assert.Equal("Meta", key); - } - - if (TestConstants.IsFirefox) - { - Assert.Equal("OSLeft", code); - } - else - { - Assert.Equal("MetaLeft", code); - } - - if (TestConstants.IsFirefox && !TestConstants.IsMacOSX) - { - Assert.False(metaKey); - } - else - { - Assert.True(metaKey); - } - } - - [PlaywrightTest("page-keyboard.spec.ts", "should work after a cross origin navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkAfterACrossOriginNavigation() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/empty.html"); - await Page.GoToAsync(TestConstants.CrossProcessUrl + "/empty.html"); - var lastEventHandle = await CaptureLastKeydownAsync(Page); - await Page.Keyboard.PressAsync("a"); - dynamic result = await lastEventHandle.JsonValueAsync(); - Assert.Equal("a", result.key); - } - - [PlaywrightTest("page-keyboard.spec.ts", "should expose keyIdentifier in webkit")] - [SkipBrowserAndPlatformFact(skipChromium: true, skipFirefox: true)] - public async Task ShouldExposeKeyIdentifierInWebkit() - { - var lastEventHandle = await CaptureLastKeydownAsync(Page); - var keyMap = new Dictionary - { - ["ArrowUp"] = "Up", - ["ArrowDown"] = "Down", - ["ArrowLeft"] = "Left", - ["ArrowRight"] = "Right", - ["Backspace"] = "U+0008", - ["Tab"] = "U+0009", - ["Delete"] = "U+007F", - ["a"] = "U+0041", - ["b"] = "U+0042", - ["F12"] = "F12", - }; - - foreach (var kv in keyMap) - { - await Page.Keyboard.PressAsync(kv.Key); - Assert.Equal(kv.Value, await lastEventHandle.EvaluateAsync("e => e.keyIdentifier")); - } - } - - [PlaywrightTest("page-keyboard.spec.ts", "should scroll with PageDown")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldScrollWithPageDown() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); - await Page.ClickAsync("body"); - await Page.Keyboard.PressAsync("PageDown"); - await Page.WaitForFunctionAsync("() => scrollY > 0"); - } - - private Task CaptureLastKeydownAsync(IPage page) - => page.EvaluateHandleAsync(@"() => { - const lastEvent = { - repeat: false, - location: -1, - code: '', - key: '', - metaKey: false, - keyIdentifier: 'unsupported' - }; - document.addEventListener('keydown', e => { - lastEvent.repeat = e.repeat; - lastEvent.location = e.location; - lastEvent.key = e.key; - lastEvent.code = e.code; - lastEvent.metaKey = e.metaKey; - lastEvent.keyIdentifier = 'keyIdentifier' in e && e.keyIdentifier; - }, true); - return lastEvent; - }"); - } -} +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageKeyboardTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-keyboard.spec.ts", "should type into a textarea")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTypeIntoATextarea() + { + await Page.EvaluateAsync(@"() => { + var textarea = document.createElement('textarea'); + document.body.appendChild(textarea); + textarea.focus(); + }"); + string text = "Hello world. I am the text that was typed!"; + await Page.Keyboard.TypeAsync(text); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('textarea').value"), Is.EqualTo(text)); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should press the metaKey")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldPressTheMetaKey1() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/empty.html"); + await Page.EvaluateAsync(@"() => { + window.keyPromise = new Promise(resolve => document.addEventListener('keydown', event => resolve(event.key))); + }"); + await Page.Keyboard.PressAsync("Meta"); + Assert.That(await Page.EvaluateAsync("keyPromise"), Is.EqualTo(TestConstants.IsFirefox && !TestConstants.IsMacOSX ? "OS" : "Meta")); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should move with the arrow keys")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldMoveWithTheArrowKeys() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.TypeAsync("textarea", "Hello World!"); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('textarea').value"), Is.EqualTo("Hello World!")); + for (int i = 0; i < "World!".Length; i++) + { + _ = Page.Keyboard.PressAsync("ArrowLeft"); + } + await Page.Keyboard.TypeAsync("inserted "); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('textarea').value"), Is.EqualTo("Hello inserted World!")); + _ = Page.Keyboard.DownAsync("Shift"); + for (int i = 0; i < "inserted ".Length; i++) + { + _ = Page.Keyboard.PressAsync("ArrowLeft"); + } + _ = Page.Keyboard.UpAsync("Shift"); + await Page.Keyboard.PressAsync("Backspace"); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('textarea').value"), Is.EqualTo("Hello World!")); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should send a character with ElementHandle.press")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSendACharacterWithElementHandlePress() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + var textarea = await Page.QuerySelectorAsync("textarea"); + await textarea.PressAsync("a"); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('textarea').value"), Is.EqualTo("a")); + + await Page.EvaluateAsync("() => window.addEventListener('keydown', e => e.preventDefault(), true)"); + + await textarea.PressAsync("b"); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('textarea').value"), Is.EqualTo("a")); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should send a character with sendCharacter")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSendACharacterWithSendCharacter() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.FocusAsync("textarea"); + await Page.Keyboard.InsertTextAsync("嗨"); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('textarea').value"), Is.EqualTo("嗨")); + await Page.EvaluateAsync("() => window.addEventListener('keydown', e => e.preventDefault(), true)"); + await Page.Keyboard.InsertTextAsync("a"); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('textarea').value"), Is.EqualTo("嗨a")); + } + + [PlaywrightTest("page-keyboard.spec.ts", "insertText should only emit input event")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task InsertTextShouldOnlyEmitInputEvent() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.FocusAsync("textarea"); + + var events = await Page.EvaluateHandleAsync(@"() => { + const events = []; + document.addEventListener('keydown', e => events.push(e.type)); + document.addEventListener('keyup', e => events.push(e.type)); + document.addEventListener('keypress', e => events.push(e.type)); + document.addEventListener('input', e => events.push(e.type)); + return events; + }"); + + await Page.Keyboard.InsertTextAsync("hello world"); + Assert.That(await events.JsonValueAsync(), Is.EqualTo(new[] { "input" })); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should report shiftKey")] + [SkipBrowserAndPlatformFact(skipFirefox: true, skipOSX: true)] + public async Task ShouldReportShiftKey() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); + var keyboard = Page.Keyboard; + var codeForKey = new Dictionary { ["Shift"] = 16, ["Alt"] = 18, ["Control"] = 17 }; + foreach (string modifierKey in codeForKey.Keys) + { + int modifierValue = codeForKey[modifierKey]; + await keyboard.DownAsync(modifierKey); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo($"Keydown: {modifierKey} {modifierKey}Left {modifierValue} [{modifierKey}]")); + await keyboard.DownAsync("!"); + // Shift+! will generate a keypress + if (modifierKey == "Shift") + { + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo($"Keydown: ! Digit1 49 [{modifierKey}]\nKeypress: ! Digit1 33 33 [{modifierKey}]")); + } + else + { + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo($"Keydown: ! Digit1 49 [{modifierKey}]")); + } + + await keyboard.UpAsync("!"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo($"Keyup: ! Digit1 49 [{modifierKey}]")); + await keyboard.UpAsync(modifierKey); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo($"Keyup: {modifierKey} {modifierKey}Left {modifierValue} []")); + } + } + + [PlaywrightTest("page-keyboard.spec.ts", "should report multiple modifiers")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReportMultipleModifiers() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); + var keyboard = Page.Keyboard; + await keyboard.DownAsync("Control"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo("Keydown: Control ControlLeft 17 [Control]")); + await keyboard.DownAsync("Alt"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo("Keydown: Alt AltLeft 18 [Alt Control]")); + await keyboard.DownAsync(";"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo("Keydown: ; Semicolon 186 [Alt Control]")); + await keyboard.UpAsync(";"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo("Keyup: ; Semicolon 186 [Alt Control]")); + await keyboard.UpAsync("Control"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo("Keyup: Control ControlLeft 17 [Alt]")); + await keyboard.UpAsync("Alt"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo("Keyup: Alt AltLeft 18 []")); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should send proper codes while typing")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSendProperCodesWhileTyping() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); + await Page.Keyboard.TypeAsync("!"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo(string.Join("\n", + "Keydown: ! Digit1 49 []", + "Keypress: ! Digit1 33 33 []", + "Keyup: ! Digit1 49 []"))); + await Page.Keyboard.TypeAsync("^"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo(string.Join("\n", + "Keydown: ^ Digit6 54 []", + "Keypress: ^ Digit6 94 94 []", + "Keyup: ^ Digit6 54 []"))); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should send proper codes while typing with shift")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSendProperCodesWhileTypingWithShift() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); + var keyboard = Page.Keyboard; + await keyboard.DownAsync("Shift"); + await Page.Keyboard.TypeAsync("~"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo(string.Join("\n", + "Keydown: Shift ShiftLeft 16 [Shift]", + "Keydown: ~ Backquote 192 [Shift]", // 192 is ` keyCode + "Keypress: ~ Backquote 126 126 [Shift]", // 126 is ~ charCode + "Keyup: ~ Backquote 192 [Shift]"))); + await keyboard.UpAsync("Shift"); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should not type canceled events")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotTypeCanceledEvents() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.FocusAsync("textarea"); + await Page.EvaluateAsync(@"() =>{ + window.addEventListener('keydown', event => { + event.stopPropagation(); + event.stopImmediatePropagation(); + if (event.key === 'l') + event.preventDefault(); + if (event.key === 'o') + event.preventDefault(); + }, false); + }"); + await Page.Keyboard.TypeAsync("Hello World!"); + Assert.That(await Page.EvaluateAsync("() => textarea.value"), Is.EqualTo("He Wrd!")); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should press plus")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldPressPlus() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); + await Page.Keyboard.PressAsync("+"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo(string.Join( + "\n", + new[] + { + "Keydown: + Equal 187 []", // 192 is ` keyCode + "Keypress: + Equal 43 43 []", // 126 is ~ charCode + "Keyup: + Equal 187 []" + }))); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should press shift plus")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldPressShiftPlus() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); + await Page.Keyboard.PressAsync("Shift++"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo(string.Join( + "\n", + new[] + { + "Keydown: Shift ShiftLeft 16 [Shift]", + "Keydown: + Equal 187 [Shift]", // 192 is ` keyCode + "Keypress: + Equal 43 43 [Shift]", // 126 is ~ charCode + "Keyup: + Equal 187 [Shift]", + "Keyup: Shift ShiftLeft 16 []" + }))); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should support plus-separated modifiers")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportPlusSeparatedModifiers() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); + await Page.Keyboard.PressAsync("Shift+~"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo(string.Join( + "\n", + new[] + { + "Keydown: Shift ShiftLeft 16 [Shift]", + "Keydown: ~ Backquote 192 [Shift]", // 192 is ` keyCode + "Keypress: ~ Backquote 126 126 [Shift]", // 126 is ~ charCode + "Keyup: ~ Backquote 192 [Shift]", + "Keyup: Shift ShiftLeft 16 []" + }))); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should support multiple plus-separated modifiers")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportMultiplePlusSeparatedModifiers() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); + await Page.Keyboard.PressAsync("Control+Shift+~"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo(string.Join( + "\n", + new[] + { + "Keydown: Control ControlLeft 17 [Control]", + "Keydown: Shift ShiftLeft 16 [Control Shift]", + "Keydown: ~ Backquote 192 [Control Shift]", // 192 is ` keyCode + "Keyup: ~ Backquote 192 [Control Shift]", + "Keyup: Shift ShiftLeft 16 [Control]", + "Keyup: Control ControlLeft 17 []" + }))); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should shift raw codes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldShiftRawCodes() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/keyboard.html"); + await Page.Keyboard.PressAsync("Shift+Digit3"); + Assert.That(await Page.EvaluateAsync("() => getResult()"), Is.EqualTo(string.Join( + "\n", + new[] + { + "Keydown: Shift ShiftLeft 16 [Shift]", + "Keydown: # Digit3 51 [Shift]", // 51 is # keyCode + "Keypress: # Digit3 35 35 [Shift]", // 35 is # charCode + "Keyup: # Digit3 51 [Shift]", + "Keyup: Shift ShiftLeft 16 []" + }))); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should specify repeat property")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSpecifyRepeatProperty() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.FocusAsync("textarea"); + var lastEvent = await CaptureLastKeydownAsync(Page); + await Page.EvaluateAsync("() => document.querySelector('textarea').addEventListener('keydown', e => window.lastEvent = e, true)"); + await Page.Keyboard.DownAsync("a"); + Assert.That(await lastEvent.EvaluateAsync("e => e.repeat"), Is.False); + await Page.Keyboard.PressAsync("a"); + Assert.That(await lastEvent.EvaluateAsync("e => e.repeat"), Is.True); + + await Page.Keyboard.DownAsync("b"); + Assert.That(await lastEvent.EvaluateAsync("e => e.repeat"), Is.False); + await Page.Keyboard.DownAsync("b"); + Assert.That(await lastEvent.EvaluateAsync("e => e.repeat"), Is.True); + + await Page.Keyboard.UpAsync("a"); + await Page.Keyboard.DownAsync("a"); + Assert.That(await lastEvent.EvaluateAsync("e => e.repeat"), Is.False); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should type all kinds of characters")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTypeAllKindsOfCharacters() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.FocusAsync("textarea"); + string text = "This text goes onto two lines.\nThis character is 嗨."; + await Page.Keyboard.TypeAsync(text); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo(text)); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should specify location")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSpecifyLocation() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + var lastEventHandle = await CaptureLastKeydownAsync(Page); + var textarea = await Page.QuerySelectorAsync("textarea"); + + await textarea.PressAsync("Digit5"); + Assert.That(await lastEventHandle.EvaluateAsync("e => e.location"), Is.EqualTo(0)); + + await textarea.PressAsync("ControlLeft"); + Assert.That(await lastEventHandle.EvaluateAsync("e => e.location"), Is.EqualTo(1)); + + await textarea.PressAsync("ControlRight"); + Assert.That(await lastEventHandle.EvaluateAsync("e => e.location"), Is.EqualTo(2)); + + await textarea.PressAsync("NumpadSubtract"); + Assert.That(await lastEventHandle.EvaluateAsync("e => e.location"), Is.EqualTo(3)); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should press Enter")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldPressEnter() + { + await Page.SetContentAsync(""); + await Page.FocusAsync("textarea"); + var lastEventHandle = await CaptureLastKeydownAsync(Page); + + await TestEnterKeyAsync("Enter", "Enter", "Enter"); + await TestEnterKeyAsync("NumpadEnter", "Enter", "NumpadEnter"); + await TestEnterKeyAsync("\n", "Enter", "Enter"); + await TestEnterKeyAsync("\r", "Enter", "Enter"); + + async Task TestEnterKeyAsync(string key, string expectedKey, string expectedCode) + { + await Page.Keyboard.PressAsync(key); + dynamic lastEvent = await lastEventHandle.JsonValueAsync(); + Assert.That(lastEvent.key, Is.EqualTo(expectedKey)); + Assert.That(lastEvent.code, Is.EqualTo(expectedCode)); + + string value = await Page.EvalOnSelectorAsync("textarea", "t => t.value"); + Assert.That(value, Is.EqualTo("\n")); + await Page.EvalOnSelectorAsync("textarea", "t => t.value = ''"); + } + } + + [PlaywrightTest("page-keyboard.spec.ts", "should throw on unknown keys")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowOnUnknownKeys() + { + var exception = Assert.ThrowsAsync(() => Page.Keyboard.PressAsync("NotARealKey")); + Assert.That(exception.Message, Is.EqualTo("Unknown key: \"NotARealKey\"")); + + exception = Assert.ThrowsAsync(() => Page.Keyboard.PressAsync("ё")); + Assert.That(exception.Message, Is.EqualTo("Unknown key: \"ё\"")); + + exception = Assert.ThrowsAsync(() => Page.Keyboard.PressAsync("😊")); + Assert.That(exception.Message, Is.EqualTo("Unknown key: \"😊\"")); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should type emoji")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTypeEmoji() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.TypeAsync("textarea", "👹 Tokyo street Japan 🇯🇵"); + Assert.That(await Page.EvalOnSelectorAsync("textarea", "textarea => textarea.value"), Is.EqualTo("👹 Tokyo street Japan 🇯🇵")); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should type emoji into an iframe")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTypeEmojiIntoAnIframe() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await FrameUtils.AttachFrameAsync(Page, "emoji-test", TestConstants.ServerUrl + "/input/textarea.html"); + var frame = Page.Frames.ElementAt(1); + var textarea = await frame.QuerySelectorAsync("textarea"); + await textarea.TypeAsync("👹 Tokyo street Japan 🇯🇵"); + Assert.That(await frame.EvalOnSelectorAsync("textarea", "textarea => textarea.value"), Is.EqualTo("👹 Tokyo street Japan 🇯🇵")); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should handle selectAll")] + [SkipBrowserAndPlatformFact(skipOSX: true, skipChromium: true)] + public async Task ShouldHandleSelectAll() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + var textarea = await Page.QuerySelectorAsync("textarea"); + await textarea.TypeAsync("some text"); + string modifier = TestConstants.IsMacOSX ? "Meta" : "Control"; + await Page.Keyboard.DownAsync(modifier); + await Page.Keyboard.PressAsync("a"); + await Page.Keyboard.UpAsync(modifier); + await Page.Keyboard.PressAsync("Backspace"); + Assert.That(await Page.EvalOnSelectorAsync("textarea", "textarea => textarea.value"), Is.Empty); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should be able to prevent selectAll")] + [SkipBrowserAndPlatformFact(skipOSX: true, skipChromium: true)] + public async Task ShouldBeAbleToPreventSelectAll() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + var textarea = await Page.QuerySelectorAsync("textarea"); + await textarea.TypeAsync("some text"); + await Page.EvalOnSelectorAsync("textarea", @"textarea => { + textarea.addEventListener('keydown', event => { + if (event.key === 'a' && (event.metaKey || event.ctrlKey)) + event.preventDefault(); + }, false); + }"); + string modifier = TestConstants.IsMacOSX ? "Meta" : "Control"; + await Page.Keyboard.DownAsync(modifier); + await Page.Keyboard.PressAsync("a"); + await Page.Keyboard.UpAsync(modifier); + await Page.Keyboard.PressAsync("Backspace"); + Assert.That(await Page.EvalOnSelectorAsync("textarea", "textarea => textarea.value"), Is.EqualTo("some tex")); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should press the meta key")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldPressTheMetaKey2() + { + var lastEventHandle = await CaptureLastKeydownAsync(Page); + await Page.Keyboard.PressAsync("Meta"); + dynamic result = await lastEventHandle.JsonValueAsync(); + string key = result.key; + string code = result.code; + bool metaKey = result.metaKey; + + if (TestConstants.IsFirefox && !TestConstants.IsMacOSX) + { + Assert.That(key, Is.EqualTo("OS")); + } + else + { + Assert.That(key, Is.EqualTo("Meta")); + } + + if (TestConstants.IsFirefox) + { + Assert.That(code, Is.EqualTo("OSLeft")); + } + else + { + Assert.That(code, Is.EqualTo("MetaLeft")); + } + + if (TestConstants.IsFirefox && !TestConstants.IsMacOSX) + { + Assert.That(metaKey, Is.False); + } + else + { + Assert.That(metaKey, Is.True); + } + } + + [PlaywrightTest("page-keyboard.spec.ts", "should work after a cross origin navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkAfterACrossOriginNavigation() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/empty.html"); + await Page.GoToAsync(TestConstants.CrossProcessUrl + "/empty.html"); + var lastEventHandle = await CaptureLastKeydownAsync(Page); + await Page.Keyboard.PressAsync("a"); + dynamic result = await lastEventHandle.JsonValueAsync(); + Assert.That(result.key, Is.EqualTo("a")); + } + + [PlaywrightTest("page-keyboard.spec.ts", "should expose keyIdentifier in webkit")] + [SkipBrowserAndPlatformFact(skipChromium: true, skipFirefox: true)] + public async Task ShouldExposeKeyIdentifierInWebkit() + { + var lastEventHandle = await CaptureLastKeydownAsync(Page); + var keyMap = new Dictionary + { + ["ArrowUp"] = "Up", + ["ArrowDown"] = "Down", + ["ArrowLeft"] = "Left", + ["ArrowRight"] = "Right", + ["Backspace"] = "U+0008", + ["Tab"] = "U+0009", + ["Delete"] = "U+007F", + ["a"] = "U+0041", + ["b"] = "U+0042", + ["F12"] = "F12", + }; + + foreach (var kv in keyMap) + { + await Page.Keyboard.PressAsync(kv.Key); + Assert.That(await lastEventHandle.EvaluateAsync("e => e.keyIdentifier"), Is.EqualTo(kv.Value)); + } + } + + [PlaywrightTest("page-keyboard.spec.ts", "should scroll with PageDown")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldScrollWithPageDown() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); + await Page.ClickAsync("body"); + await Page.Keyboard.PressAsync("PageDown"); + await Page.WaitForFunctionAsync("() => scrollY > 0"); + } + + private Task CaptureLastKeydownAsync(IPage page) + => page.EvaluateHandleAsync(@"() => { + const lastEvent = { + repeat: false, + location: -1, + code: '', + key: '', + metaKey: false, + keyIdentifier: 'unsupported' + }; + document.addEventListener('keydown', e => { + lastEvent.repeat = e.repeat; + lastEvent.location = e.location; + lastEvent.key = e.key; + lastEvent.code = e.code; + lastEvent.metaKey = e.metaKey; + lastEvent.keyIdentifier = 'keyIdentifier' in e && e.keyIdentifier; + }, true); + return lastEvent; + }"); + } +} diff --git a/src/Playwright.Tests/PageMouseTests.cs b/src/PlaywrightSharp.Tests/PageMouseTests.cs similarity index 74% rename from src/Playwright.Tests/PageMouseTests.cs rename to src/PlaywrightSharp.Tests/PageMouseTests.cs index 782e258a3f..5763b4dfc2 100644 --- a/src/Playwright.Tests/PageMouseTests.cs +++ b/src/PlaywrightSharp.Tests/PageMouseTests.cs @@ -1,184 +1,175 @@ -using System.Collections.Generic; -using System.Text.Json; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageMouseTests : PlaywrightSharpPageBaseTest - { - /// - public PageMouseTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-mouse.spec.ts", "should click the document")] - [SkipBrowserAndPlatformFact(skipFirefox: true, skipWindows: true)] - public async Task ShouldClickTheDocument() - { - await Page.EvaluateAsync(@"() => { - window.clickPromise = new Promise(resolve => { - document.addEventListener('click', event => { - resolve({ - type: event.type, - detail: event.detail, - clientX: event.clientX, - clientY: event.clientY, - isTrusted: event.isTrusted, - button: event.button - }); - }); - }); - }"); - await Page.Mouse.ClickAsync(50, 60); - var clickEvent = await Page.EvaluateAsync("() => window.clickPromise"); - Assert.Equal("click", clickEvent.GetProperty("type").GetString()); - Assert.Equal(1, clickEvent.GetProperty("detail").GetInt32()); - Assert.Equal(50, clickEvent.GetProperty("clientX").GetInt32()); - Assert.Equal(60, clickEvent.GetProperty("clientY").GetInt32()); - Assert.True(clickEvent.GetProperty("isTrusted").GetBoolean()); - Assert.Equal(0, clickEvent.GetProperty("button").GetInt32()); - } - - [PlaywrightTest("page-mouse.spec.ts", "should select the text with mouse")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectTheTextWithMouse() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); - await Page.FocusAsync("textarea"); - const string text = "This is the text that we are going to try to select. Let\'s see how it goes."; - await Page.Keyboard.TypeAsync(text); - // Firefox needs an extra frame here after typing or it will fail to set the scrollTop - await Page.EvaluateAsync("() => new Promise(requestAnimationFrame)"); - await Page.EvaluateAsync("() => document.querySelector('textarea').scrollTop = 0"); - var dimensions = await Page.EvaluateAsync(@"function dimensions() { - const rect = document.querySelector('textarea').getBoundingClientRect(); - return { - x: rect.left, - y: rect.top, - width: rect.width, - height: rect.height - }; - }"); - int x = dimensions.GetProperty("x").GetInt32(); - int y = dimensions.GetProperty("y").GetInt32(); - await Page.Mouse.MoveAsync(x + 2, y + 2); - await Page.Mouse.DownAsync(); - await Page.Mouse.MoveAsync(200, 200); - await Page.Mouse.UpAsync(); - Assert.Equal(text, await Page.EvaluateAsync(@"() => { - const textarea = document.querySelector('textarea'); - return textarea.value.substring(textarea.selectionStart, textarea.selectionEnd); - }")); - } - - [PlaywrightTest("page-mouse.spec.ts", "should trigger hover state")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTriggerHoverState() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); - await Page.HoverAsync("#button-6"); - Assert.Equal("button-6", await Page.EvaluateAsync("() => document.querySelector('button:hover').id")); - await Page.HoverAsync("#button-2"); - Assert.Equal("button-2", await Page.EvaluateAsync("() => document.querySelector('button:hover').id")); - await Page.HoverAsync("#button-91"); - Assert.Equal("button-91", await Page.EvaluateAsync("() => document.querySelector('button:hover').id")); - } - - [PlaywrightTest("page-mouse.spec.ts", "should trigger hover state with removed window.Node")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTriggerHoverStateWithRemovedWindowNode() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); - await Page.EvaluateAsync("() => delete window.Node"); - await Page.HoverAsync("#button-6"); - Assert.Equal("button-6", await Page.EvaluateAsync("() => document.querySelector('button:hover').id")); - } - - [PlaywrightTest("page-mouse.spec.ts", "should set modifier keys on click")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSetModifierKeysOnClick() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); - await Page.EvaluateAsync("() => document.querySelector('#button-3').addEventListener('mousedown', e => window.lastEvent = e, true)"); - var modifiers = new Dictionary { ["Shift"] = "shiftKey", ["Control"] = "ctrlKey", ["Alt"] = "altKey", ["Meta"] = "metaKey" }; - // In Firefox, the Meta modifier only exists on Mac - if (TestConstants.IsFirefox && !TestConstants.IsMacOSX) - { - modifiers.Remove("Meta"); - } - - foreach (string key in modifiers.Keys) - { - string value = modifiers[key]; - await Page.Keyboard.DownAsync(key); - await Page.ClickAsync("#button-3"); - Assert.True(await Page.EvaluateAsync("mod => window.lastEvent[mod]", value)); - await Page.Keyboard.UpAsync(key); - } - await Page.ClickAsync("#button-3"); - foreach (string key in modifiers.Keys) - { - Assert.False(await Page.EvaluateAsync("mod => window.lastEvent[mod]", modifiers[key])); - } - } - - [PlaywrightTest("page-mouse.spec.ts", "should tween mouse movement")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTweenMouseMovement() - { - // The test becomes flaky on WebKit without next line. - if (TestConstants.IsWebKit) - { - await Page.EvaluateAsync("() => new Promise(requestAnimationFrame)"); - } - await Page.Mouse.MoveAsync(100, 100); - await Page.EvaluateAsync(@"() => { - window.result = []; - document.addEventListener('mousemove', event => { - window.result.push([event.clientX, event.clientY]); - }); - }"); - await Page.Mouse.MoveAsync(200, 300, steps: 5); - Assert.Equal( - new[] - { - new[] { 120, 140 }, - new[] { 140, 180 }, - new[] { 160, 220 }, - new[] { 180, 260 }, - new[] { 200, 300 } - }, - await Page.EvaluateAsync("result")); - } - - [PlaywrightTest("page-mouse.spec.ts", "should work with mobile viewports and cross process navigations")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWorkWithMobileViewportsAndCrossProcessNavigations() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize { Width = 360, Height = 640 }, - IsMobile = true, - }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.EmptyPage); - - await page.GoToAsync(TestConstants.CrossProcessHttpPrefix + "/mobile.html"); - await page.EvaluateAsync(@"() => { - document.addEventListener('click', event => { - window.result = { x: event.clientX, y: event.clientY }; - }); - }"); - await page.Mouse.ClickAsync(30, 40); - var result = await page.EvaluateAsync("result"); - Assert.Equal(30, result.GetProperty("x").GetInt32()); - Assert.Equal(40, result.GetProperty("y").GetInt32()); - } - } -} +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageMouseTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-mouse.spec.ts", "should click the document")] + [SkipBrowserAndPlatformFact(skipFirefox: true, skipWindows: true)] + public async Task ShouldClickTheDocument() + { + await Page.EvaluateAsync(@"() => { + window.clickPromise = new Promise(resolve => { + document.addEventListener('click', event => { + resolve({ + type: event.type, + detail: event.detail, + clientX: event.clientX, + clientY: event.clientY, + isTrusted: event.isTrusted, + button: event.button + }); + }); + }); + }"); + await Page.Mouse.ClickAsync(50, 60); + var clickEvent = await Page.EvaluateAsync("() => window.clickPromise"); + Assert.That(clickEvent.GetProperty("type").GetString(), Is.EqualTo("click")); + Assert.That(clickEvent.GetProperty("detail").GetInt32(), Is.EqualTo(1)); + Assert.That(clickEvent.GetProperty("clientX").GetInt32(), Is.EqualTo(50)); + Assert.That(clickEvent.GetProperty("clientY").GetInt32(), Is.EqualTo(60)); + Assert.That(clickEvent.GetProperty("isTrusted").GetBoolean(), Is.True); + Assert.That(clickEvent.GetProperty("button").GetInt32(), Is.EqualTo(0)); + } + + [PlaywrightTest("page-mouse.spec.ts", "should select the text with mouse")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSelectTheTextWithMouse() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/textarea.html"); + await Page.FocusAsync("textarea"); + const string text = "This is the text that we are going to try to select. Let\'s see how it goes."; + await Page.Keyboard.TypeAsync(text); + // Firefox needs an extra frame here after typing or it will fail to set the scrollTop + await Page.EvaluateAsync("() => new Promise(requestAnimationFrame)"); + await Page.EvaluateAsync("() => document.querySelector('textarea').scrollTop = 0"); + var dimensions = await Page.EvaluateAsync(@"function dimensions() { + const rect = document.querySelector('textarea').getBoundingClientRect(); + return { + x: rect.left, + y: rect.top, + width: rect.width, + height: rect.height + }; + }"); + int x = dimensions.GetProperty("x").GetInt32(); + int y = dimensions.GetProperty("y").GetInt32(); + await Page.Mouse.MoveAsync(x + 2, y + 2); + await Page.Mouse.DownAsync(); + await Page.Mouse.MoveAsync(200, 200); + await Page.Mouse.UpAsync(); + Assert.That(await Page.EvaluateAsync(@"() => { + const textarea = document.querySelector('textarea'); + return textarea.value.substring(textarea.selectionStart, textarea.selectionEnd); + }"), Is.EqualTo(text)); + } + + [PlaywrightTest("page-mouse.spec.ts", "should trigger hover state")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTriggerHoverState() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); + await Page.HoverAsync("#button-6"); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('button:hover').id"), Is.EqualTo("button-6")); + await Page.HoverAsync("#button-2"); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('button:hover').id"), Is.EqualTo("button-2")); + await Page.HoverAsync("#button-91"); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('button:hover').id"), Is.EqualTo("button-91")); + } + + [PlaywrightTest("page-mouse.spec.ts", "should trigger hover state with removed window.Node")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTriggerHoverStateWithRemovedWindowNode() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); + await Page.EvaluateAsync("() => delete window.Node"); + await Page.HoverAsync("#button-6"); + Assert.That(await Page.EvaluateAsync("() => document.querySelector('button:hover').id"), Is.EqualTo("button-6")); + } + + [PlaywrightTest("page-mouse.spec.ts", "should set modifier keys on click")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSetModifierKeysOnClick() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/scrollable.html"); + await Page.EvaluateAsync("() => document.querySelector('#button-3').addEventListener('mousedown', e => window.lastEvent = e, true)"); + var modifiers = new Dictionary { ["Shift"] = "shiftKey", ["Control"] = "ctrlKey", ["Alt"] = "altKey", ["Meta"] = "metaKey" }; + // In Firefox, the Meta modifier only exists on Mac + if (TestConstants.IsFirefox && !TestConstants.IsMacOSX) + { + modifiers.Remove("Meta"); + } + + foreach (string key in modifiers.Keys) + { + string value = modifiers[key]; + await Page.Keyboard.DownAsync(key); + await Page.ClickAsync("#button-3"); + Assert.That(await Page.EvaluateAsync("mod => window.lastEvent[mod]", value), Is.True); + await Page.Keyboard.UpAsync(key); + } + await Page.ClickAsync("#button-3"); + foreach (string key in modifiers.Keys) + { + Assert.That(await Page.EvaluateAsync("mod => window.lastEvent[mod]", modifiers[key]), Is.False); + } + } + + [PlaywrightTest("page-mouse.spec.ts", "should tween mouse movement")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTweenMouseMovement() + { + // The test becomes flaky on WebKit without next line. + if (TestConstants.IsWebKit) + { + await Page.EvaluateAsync("() => new Promise(requestAnimationFrame)"); + } + await Page.Mouse.MoveAsync(100, 100); + await Page.EvaluateAsync(@"() => { + window.result = []; + document.addEventListener('mousemove', event => { + window.result.push([event.clientX, event.clientY]); + }); + }"); + await Page.Mouse.MoveAsync(200, 300, steps: 5); + Assert.That(await Page.EvaluateAsync("result"), Is.EqualTo(new[] + { + new[] { 120, 140 }, + new[] { 140, 180 }, + new[] { 160, 220 }, + new[] { 180, 260 }, + new[] { 200, 300 } + })); + } + + [PlaywrightTest("page-mouse.spec.ts", "should work with mobile viewports and cross process navigations")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWorkWithMobileViewportsAndCrossProcessNavigations() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize { Width = 360, Height = 640 }, + IsMobile = true, + }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.EmptyPage); + + await page.GoToAsync(TestConstants.CrossProcessHttpPrefix + "/mobile.html"); + await page.EvaluateAsync(@"() => { + document.addEventListener('click', event => { + window.result = { x: event.clientX, y: event.clientY }; + }); + }"); + await page.Mouse.ClickAsync(30, 40); + var result = await page.EvaluateAsync("result"); + Assert.That(result.GetProperty("x").GetInt32(), Is.EqualTo(30)); + Assert.That(result.GetProperty("y").GetInt32(), Is.EqualTo(40)); + } + } +} diff --git a/src/Playwright.Tests/PageNavigationTests.cs b/src/PlaywrightSharp.Tests/PageNavigationTests.cs similarity index 69% rename from src/Playwright.Tests/PageNavigationTests.cs rename to src/PlaywrightSharp.Tests/PageNavigationTests.cs index 494508b95e..0681596635 100644 --- a/src/Playwright.Tests/PageNavigationTests.cs +++ b/src/PlaywrightSharp.Tests/PageNavigationTests.cs @@ -1,38 +1,31 @@ -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class ClickNavigationTests : PlaywrightSharpPageBaseTest - { - /// - public ClickNavigationTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-navigation.spec.ts", "should work with _blank target")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithBblankTarget() - { - Server.SetRoute("/empty.html", ctx => - ctx.Response.WriteAsync($"Click me")); - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.ClickAsync("\"Click me\""); - } - - [PlaywrightTest("page-navigation.spec.ts", "should work with cross-process _blank target")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithCrossProcessBlankTarget() - { - Server.SetRoute("/empty.html", ctx => - ctx.Response.WriteAsync($"Click me")); - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.ClickAsync("\"Click me\""); - } - } -} +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class ClickNavigationTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-navigation.spec.ts", "should work with _blank target")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithBblankTarget() + { + Server.SetRoute("/empty.html", ctx => + ctx.Response.WriteAsync($"Click me")); + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.ClickAsync("\"Click me\""); + } + + [PlaywrightTest("page-navigation.spec.ts", "should work with cross-process _blank target")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithCrossProcessBlankTarget() + { + Server.SetRoute("/empty.html", ctx => + ctx.Response.WriteAsync($"Click me")); + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.ClickAsync("\"Click me\""); + } + } +} diff --git a/src/Playwright.Tests/PageNetworkIdleTests.cs b/src/PlaywrightSharp.Tests/PageNetworkIdleTests.cs similarity index 86% rename from src/Playwright.Tests/PageNetworkIdleTests.cs rename to src/PlaywrightSharp.Tests/PageNetworkIdleTests.cs index 9415d2e3c8..1d00142fa6 100644 --- a/src/Playwright.Tests/PageNetworkIdleTests.cs +++ b/src/PlaywrightSharp.Tests/PageNetworkIdleTests.cs @@ -1,202 +1,195 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Net; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///page-network-idle.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageNetworkIdleTests : PlaywrightSharpPageBaseTest - { - /// - public PageNetworkIdleTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-network-idle.spec.ts", "should navigate to empty page with networkidle")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNavigateToEmptyPageWithNetworkIdle() - { - var response = await Page.GoToAsync(TestConstants.EmptyPage, WaitUntilState.NetworkIdle); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - - [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle to succeed navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public Task ShouldWaitForNetworkIdleToSucceedNavigation() - => NetworkIdleTestAsync(Page.MainFrame, () => Page.GoToAsync(TestConstants.ServerUrl + "/networkidle.html", WaitUntilState.NetworkIdle)); - - [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle to succeed navigation with request from previous navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForToSucceedNavigationWithRequestFromPreviousNavigation() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Server.SetRoute("/foo.js", _ => Task.CompletedTask); - await Page.SetContentAsync(""); - await NetworkIdleTestAsync(Page.MainFrame, () => Page.GoToAsync(TestConstants.ServerUrl + "/networkidle.html", WaitUntilState.NetworkIdle)); - } - - [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle in waitForNavigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public Task ShouldWaitForInWaitForNavigation() - => NetworkIdleTestAsync( - Page.MainFrame, - () => - { - var task = Page.WaitForNavigationAsync(WaitUntilState.NetworkIdle); - Page.GoToAsync(TestConstants.ServerUrl + "/networkidle.html"); - return task; - }); - - [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle in setContent")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForInSetContent() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await NetworkIdleTestAsync( - Page.MainFrame, - () => Page.SetContentAsync("", waitUntil: WaitUntilState.NetworkIdle), - true); - } - - [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle in setContent with request from previous navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForNetworkIdleInSetContentWithRequestFromPreviousNavigation() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Server.SetRoute("/foo.js", _ => Task.CompletedTask); - await Page.SetContentAsync(""); - await NetworkIdleTestAsync( - Page.MainFrame, - () => Page.SetContentAsync("", waitUntil: WaitUntilState.NetworkIdle), - true); - } - - [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle when navigating iframe")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForNetworkIdleWhenNavigatingIframe() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); - var frame = Page.FirstChildFrame(); - await NetworkIdleTestAsync( - frame, - () => frame.GoToAsync(TestConstants.ServerUrl + "/networkidle.html", WaitUntilState.NetworkIdle)); - } - - [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle in setContent from the child frame")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForInSetContentFromTheChildFrame() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await NetworkIdleTestAsync( - Page.MainFrame, - () => Page.SetContentAsync("", waitUntil: WaitUntilState.NetworkIdle), - true); - } - - [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle from the child frame")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public Task ShouldWaitForFromTheChildFrame() - => NetworkIdleTestAsync( - Page.MainFrame, - () => Page.GoToAsync(TestConstants.ServerUrl + "/networkidle-frame.html", WaitUntilState.NetworkIdle)); - - [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle from the popup")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitForNetworkIdleFromThePopup() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync(@" - - - - - - "); - - for (int i = 1; i < 6; i++) - { - var popup = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.Popup), - Page.ClickAsync("#box" + i)); - - await popup.WaitForLoadStateAsync(LoadState.NetworkIdle); - } - } - - private async Task NetworkIdleTestAsync(IFrame frame, Func action, bool isSetContent = false) - { - var lastResponseFinished = new Stopwatch(); - var responses = new ConcurrentDictionary>(); - var fetches = new Dictionary>(); - - async Task RequestDelegate(HttpContext context) - { - var taskCompletion = new TaskCompletionSource(); - responses[context.Request.Path] = taskCompletion; - fetches[context.Request.Path].TrySetResult(true); - await taskCompletion.Task; - lastResponseFinished.Restart(); - context.Response.StatusCode = 404; - await context.Response.WriteAsync("File not found"); - } - - fetches["/fetch-request-a.js"] = new TaskCompletionSource(); - Server.SetRoute("/fetch-request-a.js", RequestDelegate); - - var firstFetchResourceRequested = Server.WaitForRequest("/fetch-request-a.js"); - - fetches["/fetch-request-b.js"] = new TaskCompletionSource(); - Server.SetRoute("/fetch-request-b.js", RequestDelegate); - var secondFetchResourceRequested = Server.WaitForRequest("/fetch-request-b.js"); - - var waitForLoadTask = isSetContent ? Task.CompletedTask : frame.WaitForNavigationAsync(WaitUntilState.Load); - - var actionTask = action(); - - await waitForLoadTask; - Assert.False(actionTask.IsCompleted); - - await firstFetchResourceRequested.WithTimeout(TestConstants.DefaultTaskTimeout); - Assert.False(actionTask.IsCompleted); - - await fetches["/fetch-request-a.js"].Task.WithTimeout(TestConstants.DefaultTaskTimeout); - await frame.Page.EvaluateAsync("() => window['fetchSecond']()"); - - // Finishing first response should leave 2 requests alive and trigger networkidle2. - responses["/fetch-request-a.js"].TrySetResult(true); - - // Wait for the second round to be requested. - await secondFetchResourceRequested.WithTimeout(TestConstants.DefaultTaskTimeout); - Assert.False(actionTask.IsCompleted); - - await fetches["/fetch-request-b.js"].Task.WithTimeout(TestConstants.DefaultTaskTimeout); - responses["/fetch-request-b.js"].TrySetResult(true); - - IResponse navigationResponse = null; - if (!isSetContent) - { - navigationResponse = await (Task)actionTask; - } - else - { - await actionTask; - } - - lastResponseFinished.Stop(); - if (!isSetContent) - { - Assert.Equal(HttpStatusCode.OK, navigationResponse.StatusCode); - } - } - } -} +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///page-network-idle.spec.ts + public class PageNetworkIdleTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-network-idle.spec.ts", "should navigate to empty page with networkidle")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNavigateToEmptyPageWithNetworkIdle() + { + var response = await Page.GoToAsync(TestConstants.EmptyPage, WaitUntilState.NetworkIdle); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle to succeed navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public Task ShouldWaitForNetworkIdleToSucceedNavigation() + => NetworkIdleTestAsync(Page.MainFrame, () => Page.GoToAsync(TestConstants.ServerUrl + "/networkidle.html", WaitUntilState.NetworkIdle)); + + [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle to succeed navigation with request from previous navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForToSucceedNavigationWithRequestFromPreviousNavigation() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Server.SetRoute("/foo.js", _ => Task.CompletedTask); + await Page.SetContentAsync(""); + await NetworkIdleTestAsync(Page.MainFrame, () => Page.GoToAsync(TestConstants.ServerUrl + "/networkidle.html", WaitUntilState.NetworkIdle)); + } + + [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle in waitForNavigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public Task ShouldWaitForInWaitForNavigation() + => NetworkIdleTestAsync( + Page.MainFrame, + () => + { + var task = Page.WaitForNavigationAsync(WaitUntilState.NetworkIdle); + Page.GoToAsync(TestConstants.ServerUrl + "/networkidle.html"); + return task; + }); + + [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle in setContent")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForInSetContent() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await NetworkIdleTestAsync( + Page.MainFrame, + () => Page.SetContentAsync("", waitUntil: WaitUntilState.NetworkIdle), + true); + } + + [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle in setContent with request from previous navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForNetworkIdleInSetContentWithRequestFromPreviousNavigation() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Server.SetRoute("/foo.js", _ => Task.CompletedTask); + await Page.SetContentAsync(""); + await NetworkIdleTestAsync( + Page.MainFrame, + () => Page.SetContentAsync("", waitUntil: WaitUntilState.NetworkIdle), + true); + } + + [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle when navigating iframe")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForNetworkIdleWhenNavigatingIframe() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); + var frame = Page.FirstChildFrame(); + await NetworkIdleTestAsync( + frame, + () => frame.GoToAsync(TestConstants.ServerUrl + "/networkidle.html", WaitUntilState.NetworkIdle)); + } + + [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle in setContent from the child frame")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForInSetContentFromTheChildFrame() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await NetworkIdleTestAsync( + Page.MainFrame, + () => Page.SetContentAsync("", waitUntil: WaitUntilState.NetworkIdle), + true); + } + + [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle from the child frame")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public Task ShouldWaitForFromTheChildFrame() + => NetworkIdleTestAsync( + Page.MainFrame, + () => Page.GoToAsync(TestConstants.ServerUrl + "/networkidle-frame.html", WaitUntilState.NetworkIdle)); + + [PlaywrightTest("page-network-idle.spec.ts", "should wait for networkidle from the popup")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitForNetworkIdleFromThePopup() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.SetContentAsync(@" + + + + + + "); + + for (int i = 1; i < 6; i++) + { + var popup = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.Popup), + Page.ClickAsync("#box" + i)); + + await popup.WaitForLoadStateAsync(LoadState.NetworkIdle); + } + } + + private async Task NetworkIdleTestAsync(IFrame frame, Func action, bool isSetContent = false) + { + var lastResponseFinished = new Stopwatch(); + var responses = new ConcurrentDictionary>(); + var fetches = new Dictionary>(); + + async Task RequestDelegate(HttpContext context) + { + var taskCompletion = new TaskCompletionSource(); + responses[context.Request.Path] = taskCompletion; + fetches[context.Request.Path].TrySetResult(true); + await taskCompletion.Task; + lastResponseFinished.Restart(); + context.Response.StatusCode = 404; + await context.Response.WriteAsync("File not found"); + } + + fetches["/fetch-request-a.js"] = new TaskCompletionSource(); + Server.SetRoute("/fetch-request-a.js", RequestDelegate); + + var firstFetchResourceRequested = Server.WaitForRequest("/fetch-request-a.js"); + + fetches["/fetch-request-b.js"] = new TaskCompletionSource(); + Server.SetRoute("/fetch-request-b.js", RequestDelegate); + var secondFetchResourceRequested = Server.WaitForRequest("/fetch-request-b.js"); + + var waitForLoadTask = isSetContent ? Task.CompletedTask : frame.WaitForNavigationAsync(WaitUntilState.Load); + + var actionTask = action(); + + await waitForLoadTask; + Assert.That(actionTask.IsCompleted, Is.False); + + await firstFetchResourceRequested.WithTimeout(TestConstants.DefaultTaskTimeout); + Assert.That(actionTask.IsCompleted, Is.False); + + await fetches["/fetch-request-a.js"].Task.WithTimeout(TestConstants.DefaultTaskTimeout); + await frame.Page.EvaluateAsync("() => window['fetchSecond']()"); + + // Finishing first response should leave 2 requests alive and trigger networkidle2. + responses["/fetch-request-a.js"].TrySetResult(true); + + // Wait for the second round to be requested. + await secondFetchResourceRequested.WithTimeout(TestConstants.DefaultTaskTimeout); + Assert.That(actionTask.IsCompleted, Is.False); + + await fetches["/fetch-request-b.js"].Task.WithTimeout(TestConstants.DefaultTaskTimeout); + responses["/fetch-request-b.js"].TrySetResult(true); + + IResponse navigationResponse = null; + if (!isSetContent) + { + navigationResponse = await (Task)actionTask; + } + else + { + await actionTask; + } + + lastResponseFinished.Stop(); + if (!isSetContent) + { + Assert.That(navigationResponse.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + } + } +} diff --git a/src/Playwright.Tests/PageNetworkRequestTest.cs b/src/PlaywrightSharp.Tests/PageNetworkRequestTest.cs similarity index 69% rename from src/Playwright.Tests/PageNetworkRequestTest.cs rename to src/PlaywrightSharp.Tests/PageNetworkRequestTest.cs index daaf373435..51c2a0d567 100644 --- a/src/Playwright.Tests/PageNetworkRequestTest.cs +++ b/src/PlaywrightSharp.Tests/PageNetworkRequestTest.cs @@ -1,237 +1,229 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Playwright.Contracts.Constants; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///network-request.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageNetworkRequestTest : PlaywrightSharpPageBaseTest - { - /// - public PageNetworkRequestTest(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-network-request.spec.ts", "should work for main frame navigation request")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForMainFrameNavigationRequests() - { - var requests = new List(); - Page.Request += (_, e) => requests.Add(e); - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Single(requests); - Assert.Equal(Page.MainFrame, requests[0].Frame); - } - - [PlaywrightTest("page-network-request.spec.ts", "should work for subframe navigation request")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForSubframeNavigationRequest() - { - var requests = new List(); - Page.Request += (_, e) => requests.Add(e); - - await Page.GoToAsync(TestConstants.EmptyPage); - - await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); - Assert.Equal(2, requests.Count); - Assert.Equal(Page.FirstChildFrame(), requests[1].Frame); - } - - [PlaywrightTest("page-network-request.spec.ts", "should work for fetch requests")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForFetchRequests() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var requests = new List(); - Page.Request += (_, e) => requests.Add(e); - await Page.EvaluateAsync("fetch('/digits/1.png')"); - Assert.Single(requests.Where(r => !r.Url.Contains("favicon"))); - Assert.Equal(Page.MainFrame, requests[0].Frame); - } - - [PlaywrightTest("page-network-request.spec.ts", "should return headers")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnHeaders() - { - var response = await Page.GoToAsync(TestConstants.EmptyPage); - - string expected = TestConstants.Product switch - { - TestConstants.ChromiumProduct => "Chrome", - TestConstants.FirefoxProduct => "Firefox", - TestConstants.WebkitProduct => "WebKit", - _ => "None" - }; - - Assert.Contains(response.Request.GetHeaderValues("user-agent"), (f) => f.Contains(expected)); - } - - [PlaywrightTest("page-network-request.spec.ts", "Request.headers", "should get the same headers as the server")] - [Fact(Skip = "We don't need to test this")] - public void ShouldGetTheSameHeadersAsTheServer() - { - } - - [PlaywrightTest("page-network-request.spec.ts", "should return postData")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnPostData() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Server.SetRoute("/post", _ => Task.CompletedTask); - IRequest request = null; - Page.Request += (_, e) => request = e; - await Page.EvaluateHandleAsync("fetch('./post', { method: 'POST', body: JSON.stringify({ foo: 'bar'})})"); - Assert.NotNull(request); - Assert.Equal("{\"foo\":\"bar\"}", request.PostData); - } - - [PlaywrightTest("page-network-request.spec.ts", "should work with binary post data")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithBinaryPostData() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Server.SetRoute("/post", _ => Task.CompletedTask); - IRequest request = null; - Page.Request += (_, e) => request = e; - await Page.EvaluateHandleAsync("fetch('./post', { method: 'POST', body: new Uint8Array(Array.from(Array(256).keys())) })"); - Assert.NotNull(request); - byte[] data = request.PostDataBuffer; - Assert.Equal(256, data.Length); - - for (int index = 0; index < data.Length; index++) - { - Assert.Equal(index, data[index]); - } - } - - [PlaywrightTest("page-network-request.spec.ts", "should work with binary post data and interception")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithBinaryPostDataAndInterception() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Server.SetRoute("/post", _ => Task.CompletedTask); - await Page.RouteAsync("/post", (route) => route.ResumeAsync()); - IRequest request = null; - Page.Request += (_, e) => request = e; - await Page.EvaluateHandleAsync("fetch('./post', { method: 'POST', body: new Uint8Array(Array.from(Array(256).keys())) })"); - Assert.NotNull(request); - byte[] data = request.PostDataBuffer; - Assert.Equal(256, data.Length); - - for (int index = 0; index < data.Length; index++) - { - Assert.Equal(index, data[index]); - } - } - - [PlaywrightTest("page-network-request.spec.ts", "should be |undefined| when there is no post data")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeUndefinedWhenThereIsNoPostData() - { - var response = await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Null(response.Request.PostData); - } - - - [PlaywrightTest("page-network-request.spec.ts", "should parse the json post data")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldParseTheJsonPostData() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Server.SetRoute("/post", _ => Task.CompletedTask); - IRequest request = null; - Page.Request += (_, e) => request = e; - await Page.EvaluateHandleAsync("fetch('./post', { method: 'POST', body: JSON.stringify({ foo: 'bar'})})"); - Assert.NotNull(request); - Assert.Equal("bar", request.GetPayloadAsJson().RootElement.GetProperty("foo").ToString()); - } - - [PlaywrightTest("page-network-request.spec.ts", "should parse the data if content-type is application/x-www-form-urlencoded")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldParseTheDataIfContentTypeIsApplicationXWwwFormUrlencoded() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Server.SetRoute("/post", _ => Task.CompletedTask); - IRequest request = null; - Page.Request += (_, e) => request = e; - await Page.SetContentAsync("
"); - await Page.ClickAsync("input[type=submit]"); - - Assert.NotNull(request); - var element = request.GetPayloadAsJson().RootElement; - Assert.Equal("bar", element.GetProperty("foo").ToString()); - Assert.Equal("123", element.GetProperty("baz").ToString()); - } - - [PlaywrightTest("page-network-request.spec.ts", "should be |undefined| when there is no post data")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeUndefinedWhenThereIsNoPostData2() - { - var response = await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Null(response.Request.GetPayloadAsJson()); - } - - [PlaywrightTest("page-network-request.spec.ts", "should return event source")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnEventSource() - { - const string sseMessage = "{\"foo\": \"bar\"}"; - - Server.SetRoute("/sse", async ctx => - { - ctx.Response.Headers["content-type"] = "text/event-stream"; - ctx.Response.Headers["connection"] = "keep-alive"; - ctx.Response.Headers["cache-control"] = "no-cache"; - - await ctx.Response.Body.FlushAsync(); - await ctx.Response.WriteAsync($"data: {sseMessage}\r\r"); - await ctx.Response.Body.FlushAsync(); - }); - - await Page.GoToAsync(TestConstants.EmptyPage); - var requests = new List(); - Page.Request += (_, e) => requests.Add(e); - - Assert.Equal(sseMessage, await Page.EvaluateAsync(@"() => { - const eventSource = new EventSource('/sse'); - return new Promise(resolve => { - eventSource.onmessage = e => resolve(e.data); - }); - }")); - - Assert.Equal(ResourceTypes.EventSource, requests[0].ResourceType); - } - - [PlaywrightTest("page-network-request.spec.ts", "should return navigation bit")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnNavigationBit() - { - var requests = new Dictionary(); - Page.Request += (_, e) => requests[e.Url.Split('/').Last()] = e; - Server.SetRedirect("/rrredirect", "/frames/one-frame.html"); - await Page.GoToAsync(TestConstants.ServerUrl + "/rrredirect"); - Assert.True(requests["rrredirect"].IsNavigationRequest); - Assert.True(requests["one-frame.html"].IsNavigationRequest); - Assert.True(requests["frame.html"].IsNavigationRequest); - Assert.False(requests["script.js"].IsNavigationRequest); - Assert.False(requests["style.css"].IsNavigationRequest); - } - - [PlaywrightTest("page-network-request.spec.ts", "Request.isNavigationRequest", "should return navigation bit when navigating to image")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnNavigationBitWhenNavigatingToImage() - { - var requests = new List(); - Page.Request += (_, e) => requests.Add(e); - await Page.GoToAsync(TestConstants.ServerUrl + "/pptr.png"); - Assert.True(requests[0].IsNavigationRequest); - } - } -} +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using NUnit.Framework; +using PlaywrightSharp.Contracts.Constants; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///network-request.spec.ts + public class PageNetworkRequestTest : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-network-request.spec.ts", "should work for main frame navigation request")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForMainFrameNavigationRequests() + { + var requests = new List(); + Page.Request += (_, e) => requests.Add(e); + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(requests, Has.Exactly(1).Items); + Assert.That(requests[0].Frame, Is.EqualTo(Page.MainFrame)); + } + + [PlaywrightTest("page-network-request.spec.ts", "should work for subframe navigation request")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForSubframeNavigationRequest() + { + var requests = new List(); + Page.Request += (_, e) => requests.Add(e); + + await Page.GoToAsync(TestConstants.EmptyPage); + + await FrameUtils.AttachFrameAsync(Page, "frame1", TestConstants.EmptyPage); + Assert.That(requests.Count, Is.EqualTo(2)); + Assert.That(requests[1].Frame, Is.EqualTo(Page.FirstChildFrame())); + } + + [PlaywrightTest("page-network-request.spec.ts", "should work for fetch requests")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForFetchRequests() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var requests = new List(); + Page.Request += (_, e) => requests.Add(e); + await Page.EvaluateAsync("fetch('/digits/1.png')"); + Assert.That(requests.Where(r => !r.Url.Contains("favicon")), Has.Exactly(1).Items); + Assert.That(requests[0].Frame, Is.EqualTo(Page.MainFrame)); + } + + [PlaywrightTest("page-network-request.spec.ts", "should return headers")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnHeaders() + { + var response = await Page.GoToAsync(TestConstants.EmptyPage); + + string expected = TestConstants.Product switch + { + TestConstants.ChromiumProduct => "Chrome", + TestConstants.FirefoxProduct => "Firefox", + TestConstants.WebkitProduct => "WebKit", + _ => "None" + }; + + Assert.That(response.Request.GetHeaderValues("user-agent").Any(f => f.Contains(expected)), Is.True); + } + + [PlaywrightTest("page-network-request.spec.ts", "Request.headers", "should get the same headers as the server")] + [Test, Ignore("We don't need to test this")] + public void ShouldGetTheSameHeadersAsTheServer() + { + } + + [PlaywrightTest("page-network-request.spec.ts", "should return postData")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnPostData() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Server.SetRoute("/post", _ => Task.CompletedTask); + IRequest request = null; + Page.Request += (_, e) => request = e; + await Page.EvaluateHandleAsync("fetch('./post', { method: 'POST', body: JSON.stringify({ foo: 'bar'})})"); + Assert.That(request, Is.Not.Null); + Assert.That(request.PostData, Is.EqualTo("{\"foo\":\"bar\"}")); + } + + [PlaywrightTest("page-network-request.spec.ts", "should work with binary post data")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithBinaryPostData() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Server.SetRoute("/post", _ => Task.CompletedTask); + IRequest request = null; + Page.Request += (_, e) => request = e; + await Page.EvaluateHandleAsync("fetch('./post', { method: 'POST', body: new Uint8Array(Array.from(Array(256).keys())) })"); + Assert.That(request, Is.Not.Null); + byte[] data = request.PostDataBuffer; + Assert.That(data.Length, Is.EqualTo(256)); + + for (int index = 0; index < data.Length; index++) + { + Assert.That(data[index], Is.EqualTo(index)); + } + } + + [PlaywrightTest("page-network-request.spec.ts", "should work with binary post data and interception")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithBinaryPostDataAndInterception() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Server.SetRoute("/post", _ => Task.CompletedTask); + await Page.RouteAsync("/post", (route) => route.ResumeAsync()); + IRequest request = null; + Page.Request += (_, e) => request = e; + await Page.EvaluateHandleAsync("fetch('./post', { method: 'POST', body: new Uint8Array(Array.from(Array(256).keys())) })"); + Assert.That(request, Is.Not.Null); + byte[] data = request.PostDataBuffer; + Assert.That(data.Length, Is.EqualTo(256)); + + for (int index = 0; index < data.Length; index++) + { + Assert.That(data[index], Is.EqualTo(index)); + } + } + + [PlaywrightTest("page-network-request.spec.ts", "should be |undefined| when there is no post data")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeUndefinedWhenThereIsNoPostData() + { + var response = await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.Request.PostData, Is.Null); + } + + [PlaywrightTest("page-network-request.spec.ts", "should parse the json post data")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldParseTheJsonPostData() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Server.SetRoute("/post", _ => Task.CompletedTask); + IRequest request = null; + Page.Request += (_, e) => request = e; + await Page.EvaluateHandleAsync("fetch('./post', { method: 'POST', body: JSON.stringify({ foo: 'bar'})})"); + Assert.That(request, Is.Not.Null); + Assert.That(request.GetPayloadAsJson().RootElement.GetProperty("foo").ToString(), Is.EqualTo("bar")); + } + + [PlaywrightTest("page-network-request.spec.ts", "should parse the data if content-type is application/x-www-form-urlencoded")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldParseTheDataIfContentTypeIsApplicationXWwwFormUrlencoded() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Server.SetRoute("/post", _ => Task.CompletedTask); + IRequest request = null; + Page.Request += (_, e) => request = e; + await Page.SetContentAsync("
"); + await Page.ClickAsync("input[type=submit]"); + + Assert.That(request, Is.Not.Null); + var element = request.GetPayloadAsJson().RootElement; + Assert.That(element.GetProperty("foo").ToString(), Is.EqualTo("bar")); + Assert.That(element.GetProperty("baz").ToString(), Is.EqualTo("123")); + } + + [PlaywrightTest("page-network-request.spec.ts", "should be |undefined| when there is no post data")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeUndefinedWhenThereIsNoPostData2() + { + var response = await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.Request.GetPayloadAsJson(), Is.Null); + } + + [PlaywrightTest("page-network-request.spec.ts", "should return event source")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnEventSource() + { + const string sseMessage = "{\"foo\": \"bar\"}"; + + Server.SetRoute("/sse", async ctx => + { + ctx.Response.Headers["content-type"] = "text/event-stream"; + ctx.Response.Headers["connection"] = "keep-alive"; + ctx.Response.Headers["cache-control"] = "no-cache"; + + await ctx.Response.Body.FlushAsync(); + await ctx.Response.WriteAsync($"data: {sseMessage}\r\r"); + await ctx.Response.Body.FlushAsync(); + }); + + await Page.GoToAsync(TestConstants.EmptyPage); + var requests = new List(); + Page.Request += (_, e) => requests.Add(e); + + Assert.That(await Page.EvaluateAsync(@"() => { + const eventSource = new EventSource('/sse'); + return new Promise(resolve => { + eventSource.onmessage = e => resolve(e.data); + }); + }"), Is.EqualTo(sseMessage)); + + Assert.That(requests[0].ResourceType, Is.EqualTo(ResourceTypes.EventSource)); + } + + [PlaywrightTest("page-network-request.spec.ts", "should return navigation bit")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnNavigationBit() + { + var requests = new Dictionary(); + Page.Request += (_, e) => requests[e.Url.Split('/').Last()] = e; + Server.SetRedirect("/rrredirect", "/frames/one-frame.html"); + await Page.GoToAsync(TestConstants.ServerUrl + "/rrredirect"); + Assert.That(requests["rrredirect"].IsNavigationRequest, Is.True); + Assert.That(requests["one-frame.html"].IsNavigationRequest, Is.True); + Assert.That(requests["frame.html"].IsNavigationRequest, Is.True); + Assert.That(requests["script.js"].IsNavigationRequest, Is.False); + Assert.That(requests["style.css"].IsNavigationRequest, Is.False); + } + + [PlaywrightTest("page-network-request.spec.ts", "Request.isNavigationRequest", "should return navigation bit when navigating to image")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnNavigationBitWhenNavigatingToImage() + { + var requests = new List(); + Page.Request += (_, e) => requests.Add(e); + await Page.GoToAsync(TestConstants.ServerUrl + "/pptr.png"); + Assert.That(requests[0].IsNavigationRequest, Is.True); + } + } +} diff --git a/src/Playwright.Tests/PageNetworkResponseTests.cs b/src/PlaywrightSharp.Tests/PageNetworkResponseTests.cs similarity index 69% rename from src/Playwright.Tests/PageNetworkResponseTests.cs rename to src/PlaywrightSharp.Tests/PageNetworkResponseTests.cs index 1a7c219213..a7e47cd14d 100644 --- a/src/Playwright.Tests/PageNetworkResponseTests.cs +++ b/src/PlaywrightSharp.Tests/PageNetworkResponseTests.cs @@ -1,165 +1,158 @@ -using System.IO; -using System.Net; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageNetworkResponseTests : PlaywrightSharpPageBaseTest - { - /// - public PageNetworkResponseTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-network-response.spec.ts", "should return body")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnBody() - { - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/pptr.png"); - byte[] imageBuffer = File.ReadAllBytes(TestUtils.GetWebServerFile("pptr.png")); - Assert.Equal(imageBuffer, await response.GetBodyAsync()); - } - - [PlaywrightTest("page-network-response.spec.ts", "should return body with compression")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnBodyWithCompression() - { - Server.EnableGzip("/pptr.png"); - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/pptr.png"); - byte[] imageBuffer = File.ReadAllBytes(TestUtils.GetWebServerFile("pptr.png")); - Assert.Equal(imageBuffer, await response.GetBodyAsync()); - } - - [PlaywrightTest("page-network-response.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - Server.SetRoute("/empty.html", (context) => - { - context.Response.Headers["foo"] = "bar"; - return Task.CompletedTask; - }); - - var response = await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Contains("bar", response.GetHeaderValues("foo")); - } - - [PlaywrightTest("page-network-response.spec.ts", "should return json")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnJson() - { - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/simple.json"); - Assert.Equal("{\"foo\": \"bar\"}", (await response.GetJsonAsync()).RootElement.GetRawText()); - } - - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithGenerics() - { - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/simple.json"); - Assert.Equal("bar", (await response.GetJsonAsync()).Foo); - } - - [PlaywrightTest("page-network-response.spec.ts", "should return status text")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnStatusText() - { - Server.SetRoute("/cool", (context) => - { - context.Response.StatusCode = 200; - //There are some debates about this on these issues - //https://github.com/aspnet/HttpAbstractions/issues/395 - //https://github.com/aspnet/HttpAbstractions/issues/486 - //https://github.com/aspnet/HttpAbstractions/issues/794 - context.Features.Get().ReasonPhrase = "cool!"; - return Task.CompletedTask; - }); - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/cool"); - Assert.Equal("cool!", response.StatusText); - } - - [PlaywrightTest("page-network-response.spec.ts", "should return text")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnText() - { - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/simple.json"); - Assert.Equal("{\"foo\": \"bar\"}", (await response.GetTextAsync()).Trim()); - } - - [PlaywrightTest("page-network-response.spec.ts", "should return uncompressed text")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnUncompressedText() - { - Server.EnableGzip("/simple.json"); - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/simple.json"); - Assert.Equal("gzip", response.GetHeaderValue("content-encoding")); - Assert.Equal("{\"foo\": \"bar\"}", (await response.GetTextAsync()).Trim()); - } - - [PlaywrightTest("page-network-response.spec.ts", "should throw when requesting body of redirected response")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowWhenRequestingBodyOfRedirectedResponse() - { - Server.SetRedirect("/foo.html", "/empty.html"); - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/foo.html"); - var redirectedFrom = response.Request.RedirectedFrom; - Assert.NotNull(redirectedFrom); - var redirected = await redirectedFrom.GetResponseAsync(); - Assert.Equal(HttpStatusCode.Redirect, redirected.StatusCode); - - var exception = await Assert.ThrowsAsync(async () => await redirected.GetTextAsync()); - Assert.Contains("Response body is unavailable for redirect responses", exception.Message); - } - - [PlaywrightTest("page-network-response.spec.ts", "should wait until response completes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWaitUntilResponseCompletes() - { - await Page.GoToAsync(TestConstants.EmptyPage); - // Setup server to trap request. - var serverResponseCompletion = new TaskCompletionSource(); - HttpResponse serverResponse = null; - Server.SetRoute("/get", context => - { - serverResponse = context.Response; - context.Response.Headers["Content-Type"] = "text/plain; charset=utf-8"; - context.Response.WriteAsync("hello "); - return serverResponseCompletion.Task; - }); - - // Setup page to trap response. - bool requestFinished = false; - Page.RequestFinished += (_, e) => requestFinished = requestFinished || e.Url.Contains("/get"); - // send request and wait for server response - var (pageResponse, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.Response), - Page.EvaluateAsync("fetch('./get', { method: 'GET'})"), - Server.WaitForRequest("/get") - ); - - Assert.NotNull(serverResponse); - Assert.NotNull(pageResponse); - Assert.Equal(HttpStatusCode.OK, pageResponse.StatusCode); - Assert.False(requestFinished); - - var responseText = pageResponse.GetTextAsync(); - // Write part of the response and wait for it to be flushed. - await serverResponse.WriteAsync("wor"); - // Finish response. - await serverResponse.WriteAsync("ld!"); - serverResponseCompletion.SetResult(true); - Assert.Equal("hello world!", await responseText); - } - - class TestClass - { - public string Foo { get; set; } - } - } -} +using System.IO; +using System.Net; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageNetworkResponseTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-network-response.spec.ts", "should return body")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnBody() + { + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/pptr.png"); + byte[] imageBuffer = File.ReadAllBytes(TestUtils.GetWebServerFile("pptr.png")); + Assert.That(await response.GetBodyAsync(), Is.EqualTo(imageBuffer)); + } + + [PlaywrightTest("page-network-response.spec.ts", "should return body with compression")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnBodyWithCompression() + { + Server.EnableGzip("/pptr.png"); + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/pptr.png"); + byte[] imageBuffer = File.ReadAllBytes(TestUtils.GetWebServerFile("pptr.png")); + Assert.That(await response.GetBodyAsync(), Is.EqualTo(imageBuffer)); + } + + [PlaywrightTest("page-network-response.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + Server.SetRoute("/empty.html", (context) => + { + context.Response.Headers["foo"] = "bar"; + return Task.CompletedTask; + }); + + var response = await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.GetHeaderValues("foo"), Does.Contain("bar")); + } + + [PlaywrightTest("page-network-response.spec.ts", "should return json")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnJson() + { + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/simple.json"); + Assert.That((await response.GetJsonAsync()).RootElement.GetRawText(), Is.EqualTo("{\"foo\": \"bar\"}")); + } + + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithGenerics() + { + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/simple.json"); + Assert.That((await response.GetJsonAsync()).Foo, Is.EqualTo("bar")); + } + + [PlaywrightTest("page-network-response.spec.ts", "should return status text")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnStatusText() + { + Server.SetRoute("/cool", (context) => + { + context.Response.StatusCode = 200; + //There are some debates about this on these issues + //https://github.com/aspnet/HttpAbstractions/issues/395 + //https://github.com/aspnet/HttpAbstractions/issues/486 + //https://github.com/aspnet/HttpAbstractions/issues/794 + context.Features.Get().ReasonPhrase = "cool!"; + return Task.CompletedTask; + }); + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/cool"); + Assert.That(response.StatusText, Is.EqualTo("cool!")); + } + + [PlaywrightTest("page-network-response.spec.ts", "should return text")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnText() + { + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/simple.json"); + Assert.That((await response.GetTextAsync()).Trim(), Is.EqualTo("{\"foo\": \"bar\"}")); + } + + [PlaywrightTest("page-network-response.spec.ts", "should return uncompressed text")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnUncompressedText() + { + Server.EnableGzip("/simple.json"); + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/simple.json"); + Assert.That(response.GetHeaderValue("content-encoding"), Is.EqualTo("gzip")); + Assert.That((await response.GetTextAsync()).Trim(), Is.EqualTo("{\"foo\": \"bar\"}")); + } + + [PlaywrightTest("page-network-response.spec.ts", "should throw when requesting body of redirected response")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowWhenRequestingBodyOfRedirectedResponse() + { + Server.SetRedirect("/foo.html", "/empty.html"); + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/foo.html"); + var redirectedFrom = response.Request.RedirectedFrom; + Assert.That(redirectedFrom, Is.Not.Null); + var redirected = await redirectedFrom.GetResponseAsync(); + Assert.That(redirected.StatusCode, Is.EqualTo(HttpStatusCode.Redirect)); + + var exception = Assert.ThrowsAsync(async () => await redirected.GetTextAsync()); + Assert.That(exception.Message, Does.Contain("Response body is unavailable for redirect responses")); + } + + [PlaywrightTest("page-network-response.spec.ts", "should wait until response completes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWaitUntilResponseCompletes() + { + await Page.GoToAsync(TestConstants.EmptyPage); + // Setup server to trap request. + var serverResponseCompletion = new TaskCompletionSource(); + HttpResponse serverResponse = null; + Server.SetRoute("/get", context => + { + serverResponse = context.Response; + context.Response.Headers["Content-Type"] = "text/plain; charset=utf-8"; + context.Response.WriteAsync("hello "); + return serverResponseCompletion.Task; + }); + + // Setup page to trap response. + bool requestFinished = false; + Page.RequestFinished += (_, e) => requestFinished = requestFinished || e.Url.Contains("/get"); + // send request and wait for server response + var (pageResponse, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.Response), + Page.EvaluateAsync("fetch('./get', { method: 'GET'})"), + Server.WaitForRequest("/get") + ); + + Assert.That(serverResponse, Is.Not.Null); + Assert.That(pageResponse, Is.Not.Null); + Assert.That(pageResponse.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + Assert.That(requestFinished, Is.False); + + var responseText = pageResponse.GetTextAsync(); + // Write part of the response and wait for it to be flushed. + await serverResponse.WriteAsync("wor"); + // Finish response. + await serverResponse.WriteAsync("ld!"); + serverResponseCompletion.SetResult(true); + Assert.That(await responseText, Is.EqualTo("hello world!")); + } + + class TestClass + { + public string Foo { get; set; } + } + } +} diff --git a/src/Playwright.Tests/PageRequestContinueTests.cs b/src/PlaywrightSharp.Tests/PageRequestContinueTests.cs similarity index 76% rename from src/Playwright.Tests/PageRequestContinueTests.cs rename to src/PlaywrightSharp.Tests/PageRequestContinueTests.cs index a1066910af..b849e957c2 100644 --- a/src/Playwright.Tests/PageRequestContinueTests.cs +++ b/src/PlaywrightSharp.Tests/PageRequestContinueTests.cs @@ -1,81 +1,74 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageRequestContinueTests : PlaywrightSharpPageBaseTest - { - /// - public PageRequestContinueTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-request-continue.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); - await Page.GoToAsync(TestConstants.EmptyPage); - } - - [PlaywrightTest("page-request-continue.spec.ts", "should amend HTTP headers")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAmendHTTPHeaders() - { - await Page.RouteAsync("**/*", (route) => - { - var headers = new Dictionary(route.Request.Headers.ToDictionary(x => x.Key, x => x.Value)) { ["FOO"] = "bar" }; - route.ResumeAsync(headers: headers); - }); - await Page.GoToAsync(TestConstants.EmptyPage); - var requestTask = Server.WaitForRequest("/sleep.zzz", request => request.Headers["foo"]); - await TaskUtils.WhenAll( - requestTask, - Page.EvaluateAsync("() => fetch('/sleep.zzz')") - ); - Assert.Equal("bar", requestTask.Result); - } - - [PlaywrightTest("page-request-continue.spec.ts", "should amend method on main request")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAmendMethodOnMainRequest() - { - var methodTask = Server.WaitForRequest("/empty.html", r => r.Method); - await Page.RouteAsync("**/*", (route) => route.ResumeAsync(method: HttpMethod.Post.Method)); - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal("POST", await methodTask); - } - - [PlaywrightTest("page-request-continue.spec.ts", "should amend post data")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAmendPostData() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.RouteAsync("**/*", (route) => - { - route.ResumeAsync(postData: Encoding.UTF8.GetBytes("doggo")); - }); - var requestTask = Server.WaitForRequest("/sleep.zzz", request => - { - using StreamReader reader = new StreamReader(request.Body); - return reader.ReadToEndAsync().GetAwaiter().GetResult(); - }); - - await TaskUtils.WhenAll( - requestTask, - Page.EvaluateAsync("() => fetch('/sleep.zzz', { method: 'POST', body: 'birdy' })") - ); - Assert.Equal("doggo", requestTask.Result); - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageRequestContinueTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-request-continue.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); + await Page.GoToAsync(TestConstants.EmptyPage); + } + + [PlaywrightTest("page-request-continue.spec.ts", "should amend HTTP headers")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAmendHTTPHeaders() + { + await Page.RouteAsync("**/*", (route) => + { + var headers = new Dictionary(route.Request.Headers.ToDictionary(x => x.Key, x => x.Value)) { ["FOO"] = "bar" }; + route.ResumeAsync(headers: headers); + }); + await Page.GoToAsync(TestConstants.EmptyPage); + var requestTask = Server.WaitForRequest("/sleep.zzz", request => request.Headers["foo"]); + await TaskUtils.WhenAll( + requestTask, + Page.EvaluateAsync("() => fetch('/sleep.zzz')") + ); + Assert.That(requestTask.Result, Is.EqualTo("bar")); + } + + [PlaywrightTest("page-request-continue.spec.ts", "should amend method on main request")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAmendMethodOnMainRequest() + { + var methodTask = Server.WaitForRequest("/empty.html", r => r.Method); + await Page.RouteAsync("**/*", (route) => route.ResumeAsync(method: HttpMethod.Post.Method)); + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(await methodTask, Is.EqualTo("POST")); + } + + [PlaywrightTest("page-request-continue.spec.ts", "should amend post data")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAmendPostData() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.RouteAsync("**/*", (route) => + { + route.ResumeAsync(postData: Encoding.UTF8.GetBytes("doggo")); + }); + var requestTask = Server.WaitForRequest("/sleep.zzz", request => + { + using StreamReader reader = new StreamReader(request.Body); + return reader.ReadToEndAsync().GetAwaiter().GetResult(); + }); + + await TaskUtils.WhenAll( + requestTask, + Page.EvaluateAsync("() => fetch('/sleep.zzz', { method: 'POST', body: 'birdy' })") + ); + Assert.That(requestTask.Result, Is.EqualTo("doggo")); + } + } +} diff --git a/src/Playwright.Tests/PageRequestFulfillTests.cs b/src/PlaywrightSharp.Tests/PageRequestFulfillTests.cs similarity index 73% rename from src/Playwright.Tests/PageRequestFulfillTests.cs rename to src/PlaywrightSharp.Tests/PageRequestFulfillTests.cs index ebeb7e9cf7..4189fd546c 100644 --- a/src/Playwright.Tests/PageRequestFulfillTests.cs +++ b/src/PlaywrightSharp.Tests/PageRequestFulfillTests.cs @@ -1,199 +1,192 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Microsoft.Playwright.Tests.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class RequestFulfillTests : PlaywrightSharpPageBaseTest - { - /// - public RequestFulfillTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-request-fulfill.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.RouteAsync("**/*", (route) => - { - route.FulfillAsync( - status: HttpStatusCode.Created, - headers: new Dictionary - { - ["foo"] = "bar" - }, - contentType: "text/html", - body: "Yo, page!"); - }); - var response = await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(HttpStatusCode.Created, response.StatusCode); - Assert.Equal("bar", response.GetHeaderValue("foo")); - Assert.Equal("Yo, page!", await Page.EvaluateAsync("() => document.body.textContent")); - } - - /// - /// In Playwright this method is called ShouldWorkWithStatusCode422. - /// I found that status 422 is not available in all .NET runtime versions (see https://github.com/dotnet/core/blob/4c4642d548074b3fbfd425541a968aadd75fea99/release-notes/2.1/Preview/api-diff/preview2/2.1-preview2_System.Net.md) - /// As the goal here is testing HTTP codes that are not in Chromium (see https://cs.chromium.org/chromium/src/net/http/http_status_code_list.h?sq=package:chromium) we will use code 426: Upgrade Required - /// - [PlaywrightTest("page-request-fulfill.spec.ts", "should work with status code 422")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithStatusCode422() - { - await Page.RouteAsync("**/*", (route) => - { - route.FulfillAsync(HttpStatusCode.UpgradeRequired, "Yo, page!"); - }); - var response = await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(HttpStatusCode.UpgradeRequired, response.StatusCode); - Assert.Equal("Upgrade Required", response.StatusText); - Assert.Equal("Yo, page!", await Page.EvaluateAsync("() => document.body.textContent")); - } - - [PlaywrightTest("page-request-fulfill.spec.ts", "should allow mocking binary responses")] - [Fact(Skip = "We need screenshots for this")] - public async Task ShouldAllowMockingBinaryResponses() - { - await Page.RouteAsync("**/*", (route) => - { - byte[] imageBuffer = File.ReadAllBytes(TestUtils.GetWebServerFile("pptr.png")); - route.FulfillAsync( - contentType: "image/png", - bodyBytes: imageBuffer); - }); - await Page.EvaluateAsync(@"PREFIX => { - const img = document.createElement('img'); - img.src = PREFIX + '/does-not-exist.png'; - document.body.appendChild(img); - return new Promise(fulfill => img.onload = fulfill); - }", TestConstants.ServerUrl); - var img = await Page.QuerySelectorAsync("img"); - Assert.True(ScreenshotHelper.PixelMatch("mock-binary-response.png", await img.ScreenshotAsync())); - } - - [PlaywrightTest("page-request-fulfill.spec.ts", "should allow mocking svg with charset")] - [Fact(Skip = "We need screenshots for this")] - public void ShouldAllowMockingSvgWithCharset() - { - } - - [PlaywrightTest("page-request-fulfill.spec.ts", "should work with file path")] - [Fact(Skip = "We need screenshots for this")] - public async Task ShouldWorkWithFilePath() - { - await Page.RouteAsync("**/*", (route) => - { - route.FulfillAsync( - contentType: "shouldBeIgnored", - path: TestUtils.GetWebServerFile("pptr.png")); - }); - - await Page.EvaluateAsync(@"PREFIX => { - const img = document.createElement('img'); - img.src = PREFIX + '/does-not-exist.png'; - document.body.appendChild(img); - return new Promise(fulfill => img.onload = fulfill); - }", TestConstants.ServerUrl); - var img = await Page.QuerySelectorAsync("img"); - Assert.True(ScreenshotHelper.PixelMatch("mock-binary-response.png", await img.ScreenshotAsync())); - } - - [PlaywrightTest("page-request-fulfill.spec.ts", "should stringify intercepted request response headers")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldStringifyInterceptedRequestResponseHeaders() - { - await Page.RouteAsync("**/*", (route) => - { - route.FulfillAsync( - status: HttpStatusCode.OK, - headers: new Dictionary - { - ["foo"] = "true" - }, - body: "Yo, page!"); - }); - - var response = await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("true", response.GetHeaderValue("foo")); - Assert.Equal("Yo, page!", await Page.EvaluateAsync("() => document.body.textContent")); - } - - [PlaywrightTest("page-request-fulfill.spec.ts", "should not modify the headers sent to the server")] - [Fact(Skip = "Flacky with the ASP.NET server")] - public async Task ShouldNotModifyTheHeadersSentToTheServer() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var interceptedRequests = new List>(); - - await Page.GoToAsync(TestConstants.ServerUrl + "/unused"); - - Server.SetRoute("/something", ctx => - { - interceptedRequests.Add(ctx.Request.Headers.ToDictionary()); - ctx.Response.Headers["Access-Control-Allow-Origin"] = "*"; - return ctx.Response.WriteAsync("done"); - }); - - string text = await Page.EvaluateAsync(@"async url => { - const data = await fetch(url); - return data.text(); - }", TestConstants.CrossProcessUrl + "/something"); - - Assert.Equal("done", text); - - IRequest playwrightRequest = null; - - await Page.RouteAsync(TestConstants.CrossProcessUrl + "/something", (route) => - { - playwrightRequest = route.Request; - route.ResumeAsync(headers: route.Request.Headers.ToDictionary(x => x.Key, x => x.Value)); - }); - - string textAfterRoute = await Page.EvaluateAsync(@"async url => { - const data = await fetch(url); - return data.text(); - }", TestConstants.CrossProcessUrl + "/something"); - - Assert.Equal("done", textAfterRoute); - - Assert.Equal(2, interceptedRequests.Count); - Assert.Equal(interceptedRequests[1].OrderBy(kv => kv.Key), interceptedRequests[0].OrderBy(kv => kv.Key)); - } - - [PlaywrightTest("page-request-fulfill.spec.ts", "should include the origin header")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldIncludeTheOriginHeader() - { - await Page.GoToAsync(TestConstants.EmptyPage); - IRequest interceptedRequest = null; - - await Page.RouteAsync(TestConstants.CrossProcessUrl + "/something", (route) => - { - interceptedRequest = route.Request; - route.FulfillAsync( - headers: new Dictionary { ["Access-Control-Allow-Origin"] = "*" }, - contentType: "text/plain", - body: "done"); - }); - - string text = await Page.EvaluateAsync(@"async url => { - const data = await fetch(url); - return data.text(); - }", TestConstants.CrossProcessUrl + "/something"); - - Assert.Equal("done", text); - Assert.Equal(TestConstants.ServerUrl, interceptedRequest.GetHeaderValue("origin")); - } - } -} +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; +using PlaywrightSharp.Tests.Helpers; + +namespace PlaywrightSharp.Tests +{ + public class RequestFulfillTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-request-fulfill.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.RouteAsync("**/*", (route) => + { + route.FulfillAsync( + status: HttpStatusCode.Created, + headers: new Dictionary + { + ["foo"] = "bar" + }, + contentType: "text/html", + body: "Yo, page!"); + }); + var response = await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.Created)); + Assert.That(response.GetHeaderValue("foo"), Is.EqualTo("bar")); + Assert.That(await Page.EvaluateAsync("() => document.body.textContent"), Is.EqualTo("Yo, page!")); + } + + /// + /// In Playwright this method is called ShouldWorkWithStatusCode422. + /// I found that status 422 is not available in all .NET runtime versions (see https://github.com/dotnet/core/blob/4c4642d548074b3fbfd425541a968aadd75fea99/release-notes/2.1/Preview/api-diff/preview2/2.1-preview2_System.Net.md) + /// As the goal here is testing HTTP codes that are not in Chromium (see https://cs.chromium.org/chromium/src/net/http/http_status_code_list.h?sq=package:chromium) we will use code 426: Upgrade Required + /// + [PlaywrightTest("page-request-fulfill.spec.ts", "should work with status code 422")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithStatusCode422() + { + await Page.RouteAsync("**/*", (route) => + { + route.FulfillAsync(HttpStatusCode.UpgradeRequired, "Yo, page!"); + }); + var response = await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.UpgradeRequired)); + Assert.That(response.StatusText, Is.EqualTo("Upgrade Required")); + Assert.That(await Page.EvaluateAsync("() => document.body.textContent"), Is.EqualTo("Yo, page!")); + } + + [PlaywrightTest("page-request-fulfill.spec.ts", "should allow mocking binary responses")] + [Test, Ignore("We need screenshots for this")] + public async Task ShouldAllowMockingBinaryResponses() + { + await Page.RouteAsync("**/*", (route) => + { + byte[] imageBuffer = File.ReadAllBytes(TestUtils.GetWebServerFile("pptr.png")); + route.FulfillAsync( + contentType: "image/png", + bodyBytes: imageBuffer); + }); + await Page.EvaluateAsync(@"PREFIX => { + const img = document.createElement('img'); + img.src = PREFIX + '/does-not-exist.png'; + document.body.appendChild(img); + return new Promise(fulfill => img.onload = fulfill); + }", TestConstants.ServerUrl); + var img = await Page.QuerySelectorAsync("img"); + Assert.That(ScreenshotHelper.PixelMatch("mock-binary-response.png", await img.ScreenshotAsync()), Is.True); + } + + [PlaywrightTest("page-request-fulfill.spec.ts", "should allow mocking svg with charset")] + [Test, Ignore("We need screenshots for this")] + public void ShouldAllowMockingSvgWithCharset() + { + } + + [PlaywrightTest("page-request-fulfill.spec.ts", "should work with file path")] + [Test, Ignore("We need screenshots for this")] + public async Task ShouldWorkWithFilePath() + { + await Page.RouteAsync("**/*", (route) => + { + route.FulfillAsync( + contentType: "shouldBeIgnored", + path: TestUtils.GetWebServerFile("pptr.png")); + }); + + await Page.EvaluateAsync(@"PREFIX => { + const img = document.createElement('img'); + img.src = PREFIX + '/does-not-exist.png'; + document.body.appendChild(img); + return new Promise(fulfill => img.onload = fulfill); + }", TestConstants.ServerUrl); + var img = await Page.QuerySelectorAsync("img"); + Assert.That(ScreenshotHelper.PixelMatch("mock-binary-response.png", await img.ScreenshotAsync()), Is.True); + } + + [PlaywrightTest("page-request-fulfill.spec.ts", "should stringify intercepted request response headers")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldStringifyInterceptedRequestResponseHeaders() + { + await Page.RouteAsync("**/*", (route) => + { + route.FulfillAsync( + status: HttpStatusCode.OK, + headers: new Dictionary + { + ["foo"] = "true" + }, + body: "Yo, page!"); + }); + + var response = await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + Assert.That(response.GetHeaderValue("foo"), Is.EqualTo("true")); + Assert.That(await Page.EvaluateAsync("() => document.body.textContent"), Is.EqualTo("Yo, page!")); + } + + [PlaywrightTest("page-request-fulfill.spec.ts", "should not modify the headers sent to the server")] + [Test, Ignore("Flacky with the ASP.NET server")] + public async Task ShouldNotModifyTheHeadersSentToTheServer() + { + await Page.GoToAsync(TestConstants.EmptyPage); + var interceptedRequests = new List>(); + + await Page.GoToAsync(TestConstants.ServerUrl + "/unused"); + + Server.SetRoute("/something", ctx => + { + interceptedRequests.Add(ctx.Request.Headers.ToDictionary()); + ctx.Response.Headers["Access-Control-Allow-Origin"] = "*"; + return ctx.Response.WriteAsync("done"); + }); + + string text = await Page.EvaluateAsync(@"async url => { + const data = await fetch(url); + return data.text(); + }", TestConstants.CrossProcessUrl + "/something"); + + Assert.That(text, Is.EqualTo("done")); + + IRequest playwrightRequest = null; + + await Page.RouteAsync(TestConstants.CrossProcessUrl + "/something", (route) => + { + playwrightRequest = route.Request; + route.ResumeAsync(headers: route.Request.Headers.ToDictionary(x => x.Key, x => x.Value)); + }); + + string textAfterRoute = await Page.EvaluateAsync(@"async url => { + const data = await fetch(url); + return data.text(); + }", TestConstants.CrossProcessUrl + "/something"); + + Assert.That(textAfterRoute, Is.EqualTo("done")); + + Assert.That(interceptedRequests.Count, Is.EqualTo(2)); + Assert.That(interceptedRequests[0].OrderBy(kv => kv.Key), Is.EqualTo(interceptedRequests[1].OrderBy(kv => kv.Key))); + } + + [PlaywrightTest("page-request-fulfill.spec.ts", "should include the origin header")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldIncludeTheOriginHeader() + { + await Page.GoToAsync(TestConstants.EmptyPage); + IRequest interceptedRequest = null; + + await Page.RouteAsync(TestConstants.CrossProcessUrl + "/something", (route) => + { + interceptedRequest = route.Request; + route.FulfillAsync( + headers: new Dictionary { ["Access-Control-Allow-Origin"] = "*" }, + contentType: "text/plain", + body: "done"); + }); + + string text = await Page.EvaluateAsync(@"async url => { + const data = await fetch(url); + return data.text(); + }", TestConstants.CrossProcessUrl + "/something"); + + Assert.That(text, Is.EqualTo("done")); + Assert.That(interceptedRequest.GetHeaderValue("origin"), Is.EqualTo(TestConstants.ServerUrl)); + } + } +} diff --git a/src/Playwright.Tests/PageRouteTests.cs b/src/PlaywrightSharp.Tests/PageRouteTests.cs similarity index 72% rename from src/Playwright.Tests/PageRouteTests.cs rename to src/PlaywrightSharp.Tests/PageRouteTests.cs index 34fd3190bf..5688d850ce 100644 --- a/src/Playwright.Tests/PageRouteTests.cs +++ b/src/PlaywrightSharp.Tests/PageRouteTests.cs @@ -1,665 +1,658 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Primitives; -using Microsoft.Playwright.Contracts.Constants; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageRouteTests : PlaywrightSharpPageBaseTest - { - /// - public PageRouteTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-route.spec.ts", "should intercept")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldIntercept() - { - bool intercepted = false; - await Page.RouteAsync("**/empty.html", (route) => - { - Assert.Contains("empty.html", route.Request.Url); - Assert.Contains(route.Request.Headers, x => string.Equals(x.Key, "user-agent", StringComparison.OrdinalIgnoreCase)); - Assert.Equal(HttpMethod.Get.Method, route.Request.Method); - Assert.Null(route.Request.PostData); - Assert.True(route.Request.IsNavigationRequest); - Assert.Equal(ResourceTypes.Document, route.Request.ResourceType, true); - Assert.Same(route.Request.Frame, Page.MainFrame); - Assert.Equal("about:blank", route.Request.Frame.Url); - route.ResumeAsync(); - intercepted = true; - }); - - var response = await Page.GoToAsync(TestConstants.EmptyPage); - Assert.True(response.Ok); - Assert.True(intercepted); - } - - [PlaywrightTest("page-route.spec.ts", "should unroute")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldUnroute() - { - var intercepted = new List(); - Action handler1 = (route) => - { - intercepted.Add(1); - route.ResumeAsync(); - }; - - await Page.RouteAsync("**/empty.html", handler1); - await Page.RouteAsync("**/empty.html", (route) => - { - intercepted.Add(2); - route.ResumeAsync(); - }); - - await Page.RouteAsync("**/empty.html", (route) => - { - intercepted.Add(3); - route.ResumeAsync(); - }); - - await Page.RouteAsync("**/*", (route) => - { - intercepted.Add(4); - route.ResumeAsync(); - }); - - var response = await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(new[] { 1 }, intercepted.ToArray()); - - intercepted.Clear(); - await Page.UnrouteAsync("**/empty.html", handler1); - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(new[] { 2 }, intercepted.ToArray()); - - intercepted.Clear(); - await Page.UnrouteAsync("**/empty.html"); - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.Equal(new[] { 4 }, intercepted.ToArray()); - } - - [PlaywrightTest("page-route.spec.ts", "should work when POST is redirected with 302")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWhenPostIsRedirectedWith302() - { - Server.SetRedirect("/rredirect", "/empty.html"); - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); - await Page.SetContentAsync(@" -
- -
"); - await TaskUtils.WhenAll( - Page.EvalOnSelectorAsync("form", "form => form.submit()"), - Page.WaitForNavigationAsync() - ); - } - - [PlaywrightTest("page-route.spec.ts", "should work when header manipulation headers with redirect")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWhenHeaderManipulationHeadersWithRedirect() - { - Server.SetRedirect("/rrredirect", "/empty.html"); - await Page.RouteAsync("**/*", (route) => - { - var headers = new Dictionary(route.Request.Headers.ToDictionary(x => x.Key, x => x.Value)) { ["foo"] = "bar" }; - route.ResumeAsync(headers: headers); - }); - await Page.GoToAsync(TestConstants.ServerUrl + "/rrredirect"); - } - - [PlaywrightTest("page-route.spec.ts", "should be able to remove headers")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToRemoveHeaders() - { - await Page.RouteAsync("**/*", (route) => - { - var headers = new Dictionary(route.Request.Headers.ToDictionary(x => x.Key, x => x.Value)) { ["foo"] = "bar" }; - headers.Remove("origin"); - route.ResumeAsync(headers: headers); - }); - - var originRequestHeader = Server.WaitForRequest("/empty.html", request => request.Headers["origin"]); - await TaskUtils.WhenAll( - originRequestHeader, - Page.GoToAsync(TestConstants.EmptyPage) - ); - Assert.Equal(StringValues.Empty, originRequestHeader.Result); - } - - [PlaywrightTest("page-route.spec.ts", "should contain referer header")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldContainRefererHeader() - { - var requests = new List(); - await Page.RouteAsync("**/*", (route) => - { - requests.Add(route.Request); - route.ResumeAsync(); - }); - await Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); - Assert.Contains("/one-style.css", requests[1].Url); - Assert.Contains("/one-style.html", requests[1].GetHeaderValue("referer")); - } - - [PlaywrightTest("page-route.spec.ts", "should properly return navigation response when URL has cookies")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldProperlyReturnNavigationResponseWhenURLHasCookies() - { - // Setup cookie. - await Page.GoToAsync(TestConstants.EmptyPage); - await Context.AddCookiesAsync(new Cookie - { - Url = TestConstants.EmptyPage, - Name = "foo", - Value = "bar" - }); - - // Setup request interception. - await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); - var response = await Page.ReloadAsync(); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - - [PlaywrightTest("page-route.spec.ts", "should show custom HTTP headers")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldShowCustomHTTPHeaders() - { - await Page.SetExtraHttpHeadersAsync(new Dictionary - { - ["foo"] = "bar" - }); - await Page.RouteAsync("**/*", (route) => - { - Assert.Equal("bar", route.Request.GetHeaderValue("foo")); - route.ResumeAsync(); - }); - var response = await Page.GoToAsync(TestConstants.EmptyPage); - Assert.True(response.Ok); - } - - [PlaywrightTest("page-route.spec.ts", "should work with redirect inside sync XHR")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithRedirectInsideSyncXHR() - { - await Page.GoToAsync(TestConstants.EmptyPage); - Server.SetRedirect("/logo.png", "/pptr.png"); - await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); - int status = await Page.EvaluateAsync(@"async () => { - var request = new XMLHttpRequest(); - request.open('GET', '/logo.png', false); // `false` makes the request synchronous - request.send(null); - return request.status; - }"); - Assert.Equal(200, status); - } - - [PlaywrightTest("page-route.spec.ts", "should work with custom referer headers")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithCustomRefererHeaders() - { - await Page.SetExtraHttpHeadersAsync(new Dictionary { ["referer"] = TestConstants.EmptyPage }); - await Page.RouteAsync("**/*", (route) => - { - Assert.Equal(TestConstants.EmptyPage, route.Request.GetHeaderValue("referer")); - route.ResumeAsync(); - }); - var response = await Page.GoToAsync(TestConstants.EmptyPage); - Assert.True(response.Ok); - } - - [PlaywrightTest("page-route.spec.ts", "should be abortable")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbortable() - { - await Page.RouteAsync(new Regex("\\.css"), (route) => route.AbortAsync()); - - int failedRequests = 0; - Page.RequestFailed += (_, _) => ++failedRequests; - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); - Assert.True(response.Ok); - Assert.Null(response.Request.Failure); - Assert.Equal(1, failedRequests); - } - - [PlaywrightTest("page-route.spec.ts", "should be abortable with custom error codes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbortableWithCustomErrorCodes() - { - await Page.RouteAsync("**/*", (route) => - { - route.AbortAsync(RequestAbortErrorCode.InternetDisconnected); - }); - - IRequest failedRequest = null; - Page.RequestFailed += (_, e) => failedRequest = e; - await Page.GoToAsync(TestConstants.EmptyPage).ContinueWith(_ => { }); - Assert.NotNull(failedRequest); - if (TestConstants.IsWebKit) - { - Assert.Equal("Request intercepted", failedRequest.Failure); - } - else if (TestConstants.IsFirefox) - { - Assert.Equal("NS_ERROR_OFFLINE", failedRequest.Failure); - } - else - { - Assert.Equal("net::ERR_INTERNET_DISCONNECTED", failedRequest.Failure); - } - } - - [PlaywrightTest("page-route.spec.ts", "should send referer")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSendReferer() - { - await Page.SetExtraHttpHeadersAsync(new Dictionary { ["referer"] = "http://google.com/" }); - await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); - var requestTask = Server.WaitForRequest("/grid.html", request => request.Headers["referer"]); - await TaskUtils.WhenAll( - requestTask, - Page.GoToAsync(TestConstants.ServerUrl + "/grid.html") - ); - Assert.Equal("http://google.com/", requestTask.Result); - } - - [PlaywrightTest("page-route.spec.ts", "should fail navigation when aborting main resource")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailNavigationWhenAbortingMainResource() - { - await Page.RouteAsync("**/*", (route) => route.AbortAsync()); - var exception = await Assert.ThrowsAnyAsync(() => Page.GoToAsync(TestConstants.EmptyPage)); - Assert.NotNull(exception); - if (TestConstants.IsWebKit) - { - Assert.Contains("Request intercepted", exception.Message); - } - else if (TestConstants.IsFirefox) - { - Assert.Contains("NS_ERROR_FAILURE", exception.Message); - } - else - { - Assert.Contains("net::ERR_FAILED", exception.Message); - } - } - - [PlaywrightTest("page-route.spec.ts", "should not work with redirects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotWorkWithRedirects() - { - var requests = new List(); - await Page.RouteAsync("**/*", (route) => - { - route.ResumeAsync(); - requests.Add(route.Request); - }); - Server.SetRedirect("/non-existing-page.html", "/non-existing-page-2.html"); - Server.SetRedirect("/non-existing-page-2.html", "/non-existing-page-3.html"); - Server.SetRedirect("/non-existing-page-3.html", "/non-existing-page-4.html"); - Server.SetRedirect("/non-existing-page-4.html", "/empty.html"); - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/non-existing-page.html"); - - Assert.Contains("non-existing-page.html", requests[0].Url); - Assert.Single(requests); - Assert.Equal(ResourceTypes.Document, requests[0].ResourceType, true); - Assert.True(requests[0].IsNavigationRequest); - - var chain = new List(); - - for (var request = response.Request; request != null; request = request.RedirectedFrom) - { - chain.Add(request); - Assert.True(request.IsNavigationRequest); - } - - Assert.Equal(5, chain.Count); - Assert.Contains("/empty.html", chain[0].Url); - Assert.Contains("/non-existing-page-4.html", chain[1].Url); - Assert.Contains("/non-existing-page-3.html", chain[2].Url); - Assert.Contains("/non-existing-page-2.html", chain[3].Url); - Assert.Contains("/non-existing-page.html", chain[4].Url); - - for (int i = 0; i < chain.Count; ++i) - { - var request = chain[i]; - Assert.True(request.IsNavigationRequest); - Assert.Equal(i > 0 ? chain[i - 1] : null, chain[i].RedirectedTo); - } - } - - [PlaywrightTest("page-route.spec.ts", "should work with redirects for subresources")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithRedirectsForSubresources() - { - var requests = new List(); - await Page.RouteAsync("**/*", (route) => - { - route.ResumeAsync(); - requests.Add(route.Request); - }); - Server.SetRedirect("/one-style.css", "/two-style.css"); - Server.SetRedirect("/two-style.css", "/three-style.css"); - Server.SetRedirect("/three-style.css", "/four-style.css"); - Server.SetRoute("/four-style.css", context => context.Response.WriteAsync("body {box-sizing: border-box; }")); - - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Contains("one-style.html", response.Url); - - Assert.Equal(2, requests.Count); - Assert.Equal(ResourceTypes.Document, requests[0].ResourceType, true); - Assert.Contains("one-style.html", requests[0].Url); - - var request = requests[1]; - foreach (string url in new[] { "/one-style.css", "/two-style.css", "/three-style.css", "/four-style.css" }) - { - Assert.Equal(ResourceTypes.Stylesheet, request.ResourceType, true); - Assert.Contains(url, request.Url); - request = request.RedirectedTo; - } - - Assert.Null(request); - } - - [PlaywrightTest("page-route.spec.ts", "should work with equal requests")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithEqualRequests() - { - await Page.GoToAsync(TestConstants.EmptyPage); - int responseCount = 1; - Server.SetRoute("/zzz", context => context.Response.WriteAsync((responseCount++ * 11).ToString())); - - bool spinner = false; - // Cancel 2nd request. - await Page.RouteAsync("**/*", (route) => - { - if (spinner) - { - _ = route.AbortAsync(); - } - else - { - _ = route.ResumeAsync(); - } - spinner = !spinner; - }); - - var results = new List(); - for (int i = 0; i < 3; ++i) - { - results.Add(await Page.EvaluateAsync("fetch('/zzz').then(response => response.text()).catch (e => 'FAILED')")); - } - - Assert.Equal(new[] { "11", "FAILED", "22" }, results); - } - - [PlaywrightTest("page-route.spec.ts", "should navigate to dataURL and not fire dataURL requests")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNavigateToDataURLAndNotFireDataURLRequests() - { - var requests = new List(); - await Page.RouteAsync("**/*", (route) => - { - requests.Add(route.Request); - route.ResumeAsync(); - }); - string dataURL = "data:text/html,
yo
"; - var response = await Page.GoToAsync(dataURL); - Assert.Null(response); - Assert.Empty(requests); - } - - [PlaywrightTest("page-route.spec.ts", "should be able to fetch dataURL and not fire dataURL requests")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToFetchDataURLAndNotFireDataURLRequests() - { - await Page.GoToAsync(TestConstants.EmptyPage); - - var requests = new List(); - await Page.RouteAsync("**/*", (route) => - { - requests.Add(route.Request); - route.ResumeAsync(); - }); - string dataURL = "data:text/html,
yo
"; - string text = await Page.EvaluateAsync("url => fetch(url).then(r => r.text())", dataURL); - Assert.Equal("
yo
", text); - Assert.Empty(requests); - } - - [PlaywrightTest("page-route.spec.ts", "should navigate to URL with hash and and fire requests without hash")] - [Fact(Skip = "Not implemented")] - public async Task ShouldNavigateToURLWithHashAndAndFireRequestsWithoutHash() - { - var requests = new List(); - await Page.RouteAsync("**/*", (route) => - { - requests.Add(route.Request); - route.ResumeAsync(); - }); - var response = await Page.GoToAsync(TestConstants.EmptyPage + "#hash"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(TestConstants.EmptyPage, response.Url); - Assert.Single(requests); - Assert.Equal(TestConstants.EmptyPage, requests[0].Url); - } - - [PlaywrightTest("page-route.spec.ts", "should work with encoded server")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithEncodedServer() - { - // The requestWillBeSent will report encoded URL, whereas interception will - // report URL as-is. @see crbug.com/759388 - await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/some nonexisting page"); - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - - [PlaywrightTest("page-route.spec.ts", "should work with badly encoded server")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithBadlyEncodedServer() - { - Server.SetRoute("/malformed?rnd=%911", _ => Task.CompletedTask); - await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); - var response = await Page.GoToAsync(TestConstants.ServerUrl + "/malformed?rnd=%911"); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - - [PlaywrightTest("page-route.spec.ts", "should work with encoded server - 2")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithEncodedServer2() - { - // The requestWillBeSent will report URL as-is, whereas interception will - // report encoded URL for stylesheet. @see crbug.com/759388 - var requests = new List(); - await Page.RouteAsync("**/*", (route) => - { - route.ResumeAsync(); - requests.Add(route.Request); - }); - var response = await Page.GoToAsync($"data:text/html,"); - Assert.Null(response); - Assert.Single(requests); - Assert.Equal(HttpStatusCode.NotFound, (await requests[0].GetResponseAsync()).StatusCode); - } - - [PlaywrightTest("page-route.spec.ts", @"should not throw ""Invalid Interception Id"" if the request was cancelled")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotThrowInvalidInterceptionIdIfTheRequestWasCancelled() - { - await Page.SetContentAsync(""); - IRoute route = null; - await Page.RouteAsync("**/*", (r) => route = r); - _ = Page.EvalOnSelectorAsync("iframe", "(frame, url) => frame.src = url", TestConstants.EmptyPage); - // Wait for request interception. - await Page.WaitForEventAsync(PageEvent.Request); - // Delete frame to cause request to be canceled. - await Page.EvalOnSelectorAsync("iframe", "frame => frame.remove()"); - await route.ResumeAsync(); - } - - [PlaywrightTest("page-route.spec.ts", "should intercept main resource during cross-process navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldInterceptMainResourceDuringCrossProcessNavigation() - { - await Page.GoToAsync(TestConstants.EmptyPage); - bool intercepted = false; - await Page.RouteAsync(TestConstants.CrossProcessUrl + "/empty.html", (route) => - { - if (route.Request.Url.Contains(TestConstants.CrossProcessHttpPrefix + "/empty.html")) - { - intercepted = true; - } - - route.ResumeAsync(); - }); - var response = await Page.GoToAsync(TestConstants.CrossProcessHttpPrefix + "/empty.html"); - Assert.True(response.Ok); - Assert.True(intercepted); - } - - [PlaywrightTest("page-route.spec.ts", "should fulfill with redirect status")] - [SkipBrowserAndPlatformFact(skipWebkit: true)] - public async Task ShouldFulfillWithRedirectStatus() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/title.html"); - Server.SetRoute("/final", context => context.Response.WriteAsync("foo")); - await Page.RouteAsync("**/*", (route) => - { - if (route.Request.Url != TestConstants.ServerUrl + "/redirect_this") - { - route.ResumeAsync(); - return; - } - - _ = route.FulfillAsync( - status: HttpStatusCode.MovedPermanently, - headers: new Dictionary - { - ["location"] = "/final", - }); - }); - - string text = await Page.EvaluateAsync(@"async url => { - const data = await fetch(url); - return data.text(); - }", TestConstants.ServerUrl + "/redirect_this"); - - Assert.Equal("foo", text); - } - - [PlaywrightTest("page-route.spec.ts", "should support cors with GET")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportCorsWithGET() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.RouteAsync("**/cars*", (route) => - { - var headers = route.Request.Url.EndsWith("allow") - ? new Dictionary { ["access-control-allow-origin"] = "*" } - : new Dictionary(); - - _ = route.FulfillAsync( - contentType: "application/json", - headers: headers, - status: HttpStatusCode.OK, - body: "[\"electric\", \"cars\"]"); - }); - - string[] resp = await Page.EvaluateAsync(@"async () => { - const response = await fetch('https://example.com/cars?allow', { mode: 'cors' }); - return response.json(); - }"); - - Assert.Equal(new[] { "electric", "cars" }, resp); - - var exception = await Assert.ThrowsAnyAsync(() => Page.EvaluateAsync(@"async () => { - const response = await fetch('https://example.com/cars?reject', { mode: 'cors' }); - return response.json(); - }")); - - Assert.Contains("failed", exception.Message); - } - - [PlaywrightTest("page-route.spec.ts", "should support cors with POST")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportCorsWithPOST() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.RouteAsync("**/cars*", (route) => - { - _ = route.FulfillAsync( - contentType: "application/json", - headers: new Dictionary { ["access-control-allow-origin"] = "*" }, - status: HttpStatusCode.OK, - body: "[\"electric\", \"cars\"]"); - }); - - string[] resp = await Page.EvaluateAsync(@"async () => { - const response = await fetch('https://example.com/cars', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - mode: 'cors', - body: JSON.stringify({ 'number': 1 }) - }); - return response.json(); - }"); - - Assert.Equal(new[] { "electric", "cars" }, resp); - } - - [PlaywrightTest("page-route.spec.ts", "should support cors with different methods")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSupportCorsWithDifferentMethods() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.RouteAsync("**/cars*", (route) => - { - _ = route.FulfillAsync( - contentType: "application/json", - headers: new Dictionary { ["access-control-allow-origin"] = "*" }, - status: HttpStatusCode.OK, - body: $"[\"{ route.Request.Method.ToString().ToUpper() }\", \"electric\", \"cars\"]"); - }); - - string[] resp = await Page.EvaluateAsync(@"async () => { - const response = await fetch('https://example.com/cars', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - mode: 'cors', - body: JSON.stringify({ 'number': 1 }) - }); - return response.json(); - }"); - - Assert.Equal(new[] { "POST", "electric", "cars" }, resp); - - resp = await Page.EvaluateAsync(@"async () => { - const response = await fetch('https://example.com/cars', { - method: 'DELETE', - headers: { 'Content-Type': 'application/json' }, - mode: 'cors', - body: JSON.stringify({ 'number': 1 }) - }); - return response.json(); - }"); - - Assert.Equal(new[] { "DELETE", "electric", "cars" }, resp); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; +using NUnit.Framework; +using PlaywrightSharp.Contracts.Constants; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageRouteTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-route.spec.ts", "should intercept")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldIntercept() + { + bool intercepted = false; + await Page.RouteAsync("**/empty.html", (route) => + { + Assert.That(route.Request.Url, Does.Contain("empty.html")); + Assert.That(route.Request.Headers.Any(x => string.Equals(x.Key, "user-agent", StringComparison.OrdinalIgnoreCase)), Is.True); + Assert.That(route.Request.Method, Is.EqualTo(HttpMethod.Get.Method)); + Assert.That(route.Request.PostData, Is.Null); + Assert.That(route.Request.IsNavigationRequest, Is.True); + Assert.That(route.Request.ResourceType, Is.EqualTo(ResourceTypes.Document).IgnoreCase); + Assert.That(Page.MainFrame, Is.SameAs(route.Request.Frame)); + Assert.That(route.Request.Frame.Url, Is.EqualTo("about:blank")); + route.ResumeAsync(); + intercepted = true; + }); + + var response = await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.Ok, Is.True); + Assert.That(intercepted, Is.True); + } + + [PlaywrightTest("page-route.spec.ts", "should unroute")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldUnroute() + { + var intercepted = new List(); + Action handler1 = (route) => + { + intercepted.Add(1); + route.ResumeAsync(); + }; + + await Page.RouteAsync("**/empty.html", handler1); + await Page.RouteAsync("**/empty.html", (route) => + { + intercepted.Add(2); + route.ResumeAsync(); + }); + + await Page.RouteAsync("**/empty.html", (route) => + { + intercepted.Add(3); + route.ResumeAsync(); + }); + + await Page.RouteAsync("**/*", (route) => + { + intercepted.Add(4); + route.ResumeAsync(); + }); + + var response = await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(intercepted.ToArray(), Is.EqualTo(new[] { 1 })); + + intercepted.Clear(); + await Page.UnrouteAsync("**/empty.html", handler1); + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(intercepted.ToArray(), Is.EqualTo(new[] { 2 })); + + intercepted.Clear(); + await Page.UnrouteAsync("**/empty.html"); + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(intercepted.ToArray(), Is.EqualTo(new[] { 4 })); + } + + [PlaywrightTest("page-route.spec.ts", "should work when POST is redirected with 302")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWhenPostIsRedirectedWith302() + { + Server.SetRedirect("/rredirect", "/empty.html"); + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); + await Page.SetContentAsync(@" +
+ +
"); + await TaskUtils.WhenAll( + Page.EvalOnSelectorAsync("form", "form => form.submit()"), + Page.WaitForNavigationAsync() + ); + } + + [PlaywrightTest("page-route.spec.ts", "should work when header manipulation headers with redirect")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWhenHeaderManipulationHeadersWithRedirect() + { + Server.SetRedirect("/rrredirect", "/empty.html"); + await Page.RouteAsync("**/*", (route) => + { + var headers = new Dictionary(route.Request.Headers.ToDictionary(x => x.Key, x => x.Value)) { ["foo"] = "bar" }; + route.ResumeAsync(headers: headers); + }); + await Page.GoToAsync(TestConstants.ServerUrl + "/rrredirect"); + } + + [PlaywrightTest("page-route.spec.ts", "should be able to remove headers")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToRemoveHeaders() + { + await Page.RouteAsync("**/*", (route) => + { + var headers = new Dictionary(route.Request.Headers.ToDictionary(x => x.Key, x => x.Value)) { ["foo"] = "bar" }; + headers.Remove("origin"); + route.ResumeAsync(headers: headers); + }); + + var originRequestHeader = Server.WaitForRequest("/empty.html", request => request.Headers["origin"]); + await TaskUtils.WhenAll( + originRequestHeader, + Page.GoToAsync(TestConstants.EmptyPage) + ); + Assert.That(originRequestHeader.Result, Is.EqualTo(StringValues.Empty)); + } + + [PlaywrightTest("page-route.spec.ts", "should contain referer header")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldContainRefererHeader() + { + var requests = new List(); + await Page.RouteAsync("**/*", (route) => + { + requests.Add(route.Request); + route.ResumeAsync(); + }); + await Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); + Assert.That(requests[1].Url, Does.Contain("/one-style.css")); + Assert.That(requests[1].GetHeaderValue("referer"), Does.Contain("/one-style.html")); + } + + [PlaywrightTest("page-route.spec.ts", "should properly return navigation response when URL has cookies")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldProperlyReturnNavigationResponseWhenURLHasCookies() + { + // Setup cookie. + await Page.GoToAsync(TestConstants.EmptyPage); + await Context.AddCookiesAsync(new Cookie + { + Url = TestConstants.EmptyPage, + Name = "foo", + Value = "bar" + }); + + // Setup request interception. + await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); + var response = await Page.ReloadAsync(); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [PlaywrightTest("page-route.spec.ts", "should show custom HTTP headers")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldShowCustomHTTPHeaders() + { + await Page.SetExtraHttpHeadersAsync(new Dictionary + { + ["foo"] = "bar" + }); + await Page.RouteAsync("**/*", (route) => + { + Assert.That(route.Request.GetHeaderValue("foo"), Is.EqualTo("bar")); + route.ResumeAsync(); + }); + var response = await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.Ok, Is.True); + } + + [PlaywrightTest("page-route.spec.ts", "should work with redirect inside sync XHR")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithRedirectInsideSyncXHR() + { + await Page.GoToAsync(TestConstants.EmptyPage); + Server.SetRedirect("/logo.png", "/pptr.png"); + await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); + int status = await Page.EvaluateAsync(@"async () => { + var request = new XMLHttpRequest(); + request.open('GET', '/logo.png', false); // `false` makes the request synchronous + request.send(null); + return request.status; + }"); + Assert.That(status, Is.EqualTo(200)); + } + + [PlaywrightTest("page-route.spec.ts", "should work with custom referer headers")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithCustomRefererHeaders() + { + await Page.SetExtraHttpHeadersAsync(new Dictionary { ["referer"] = TestConstants.EmptyPage }); + await Page.RouteAsync("**/*", (route) => + { + Assert.That(route.Request.GetHeaderValue("referer"), Is.EqualTo(TestConstants.EmptyPage)); + route.ResumeAsync(); + }); + var response = await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(response.Ok, Is.True); + } + + [PlaywrightTest("page-route.spec.ts", "should be abortable")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbortable() + { + await Page.RouteAsync(new Regex("\\.css"), (route) => route.AbortAsync()); + + int failedRequests = 0; + Page.RequestFailed += (_, _) => ++failedRequests; + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); + Assert.That(response.Ok, Is.True); + Assert.That(response.Request.Failure, Is.Null); + Assert.That(failedRequests, Is.EqualTo(1)); + } + + [PlaywrightTest("page-route.spec.ts", "should be abortable with custom error codes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbortableWithCustomErrorCodes() + { + await Page.RouteAsync("**/*", (route) => + { + route.AbortAsync(RequestAbortErrorCode.InternetDisconnected); + }); + + IRequest failedRequest = null; + Page.RequestFailed += (_, e) => failedRequest = e; + await Page.GoToAsync(TestConstants.EmptyPage).ContinueWith(_ => { }); + Assert.That(failedRequest, Is.Not.Null); + if (TestConstants.IsWebKit) + { + Assert.That(failedRequest.Failure, Is.EqualTo("Request intercepted")); + } + else if (TestConstants.IsFirefox) + { + Assert.That(failedRequest.Failure, Is.EqualTo("NS_ERROR_OFFLINE")); + } + else + { + Assert.That(failedRequest.Failure, Is.EqualTo("net::ERR_INTERNET_DISCONNECTED")); + } + } + + [PlaywrightTest("page-route.spec.ts", "should send referer")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSendReferer() + { + await Page.SetExtraHttpHeadersAsync(new Dictionary { ["referer"] = "http://google.com/" }); + await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); + var requestTask = Server.WaitForRequest("/grid.html", request => request.Headers["referer"]); + await TaskUtils.WhenAll( + requestTask, + Page.GoToAsync(TestConstants.ServerUrl + "/grid.html") + ); + Assert.That(requestTask.Result, Is.EqualTo("http://google.com/")); + } + + [PlaywrightTest("page-route.spec.ts", "should fail navigation when aborting main resource")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailNavigationWhenAbortingMainResource() + { + await Page.RouteAsync("**/*", (route) => route.AbortAsync()); + var exception = Assert.CatchAsync(() => Page.GoToAsync(TestConstants.EmptyPage)); + Assert.That(exception, Is.Not.Null); + if (TestConstants.IsWebKit) + { + Assert.That(exception.Message, Does.Contain("Request intercepted")); + } + else if (TestConstants.IsFirefox) + { + Assert.That(exception.Message, Does.Contain("NS_ERROR_FAILURE")); + } + else + { + Assert.That(exception.Message, Does.Contain("net::ERR_FAILED")); + } + } + + [PlaywrightTest("page-route.spec.ts", "should not work with redirects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotWorkWithRedirects() + { + var requests = new List(); + await Page.RouteAsync("**/*", (route) => + { + route.ResumeAsync(); + requests.Add(route.Request); + }); + Server.SetRedirect("/non-existing-page.html", "/non-existing-page-2.html"); + Server.SetRedirect("/non-existing-page-2.html", "/non-existing-page-3.html"); + Server.SetRedirect("/non-existing-page-3.html", "/non-existing-page-4.html"); + Server.SetRedirect("/non-existing-page-4.html", "/empty.html"); + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/non-existing-page.html"); + + Assert.That(requests[0].Url, Does.Contain("non-existing-page.html")); + Assert.That(requests, Has.Exactly(1).Items); + Assert.That(requests[0].ResourceType, Is.EqualTo(ResourceTypes.Document).IgnoreCase); + Assert.That(requests[0].IsNavigationRequest, Is.True); + + var chain = new List(); + + for (var request = response.Request; request != null; request = request.RedirectedFrom) + { + chain.Add(request); + Assert.That(request.IsNavigationRequest, Is.True); + } + + Assert.That(chain.Count, Is.EqualTo(5)); + Assert.That(chain[0].Url, Does.Contain("/empty.html")); + Assert.That(chain[1].Url, Does.Contain("/non-existing-page-4.html")); + Assert.That(chain[2].Url, Does.Contain("/non-existing-page-3.html")); + Assert.That(chain[3].Url, Does.Contain("/non-existing-page-2.html")); + Assert.That(chain[4].Url, Does.Contain("/non-existing-page.html")); + + for (int i = 0; i < chain.Count; ++i) + { + var request = chain[i]; + Assert.That(request.IsNavigationRequest, Is.True); + Assert.That(chain[i].RedirectedTo, Is.EqualTo(i > 0 ? chain[i - 1] : null)); + } + } + + [PlaywrightTest("page-route.spec.ts", "should work with redirects for subresources")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithRedirectsForSubresources() + { + var requests = new List(); + await Page.RouteAsync("**/*", (route) => + { + route.ResumeAsync(); + requests.Add(route.Request); + }); + Server.SetRedirect("/one-style.css", "/two-style.css"); + Server.SetRedirect("/two-style.css", "/three-style.css"); + Server.SetRedirect("/three-style.css", "/four-style.css"); + Server.SetRoute("/four-style.css", context => context.Response.WriteAsync("body {box-sizing: border-box; }")); + + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + Assert.That(response.Url, Does.Contain("one-style.html")); + + Assert.That(requests.Count, Is.EqualTo(2)); + Assert.That(requests[0].ResourceType, Is.EqualTo(ResourceTypes.Document).IgnoreCase); + Assert.That(requests[0].Url, Does.Contain("one-style.html")); + + var request = requests[1]; + foreach (string url in new[] { "/one-style.css", "/two-style.css", "/three-style.css", "/four-style.css" }) + { + Assert.That(request.ResourceType, Is.EqualTo(ResourceTypes.Stylesheet).IgnoreCase); + Assert.That(request.Url, Does.Contain(url)); + request = request.RedirectedTo; + } + + Assert.That(request, Is.Null); + } + + [PlaywrightTest("page-route.spec.ts", "should work with equal requests")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithEqualRequests() + { + await Page.GoToAsync(TestConstants.EmptyPage); + int responseCount = 1; + Server.SetRoute("/zzz", context => context.Response.WriteAsync((responseCount++ * 11).ToString())); + + bool spinner = false; + // Cancel 2nd request. + await Page.RouteAsync("**/*", (route) => + { + if (spinner) + { + _ = route.AbortAsync(); + } + else + { + _ = route.ResumeAsync(); + } + spinner = !spinner; + }); + + var results = new List(); + for (int i = 0; i < 3; ++i) + { + results.Add(await Page.EvaluateAsync("fetch('/zzz').then(response => response.text()).catch (e => 'FAILED')")); + } + + Assert.That(results, Is.EqualTo(new[] { "11", "FAILED", "22" })); + } + + [PlaywrightTest("page-route.spec.ts", "should navigate to dataURL and not fire dataURL requests")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNavigateToDataURLAndNotFireDataURLRequests() + { + var requests = new List(); + await Page.RouteAsync("**/*", (route) => + { + requests.Add(route.Request); + route.ResumeAsync(); + }); + string dataURL = "data:text/html,
yo
"; + var response = await Page.GoToAsync(dataURL); + Assert.That(response, Is.Null); + Assert.That(requests, Is.Empty); + } + + [PlaywrightTest("page-route.spec.ts", "should be able to fetch dataURL and not fire dataURL requests")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToFetchDataURLAndNotFireDataURLRequests() + { + await Page.GoToAsync(TestConstants.EmptyPage); + + var requests = new List(); + await Page.RouteAsync("**/*", (route) => + { + requests.Add(route.Request); + route.ResumeAsync(); + }); + string dataURL = "data:text/html,
yo
"; + string text = await Page.EvaluateAsync("url => fetch(url).then(r => r.text())", dataURL); + Assert.That(text, Is.EqualTo("
yo
")); + Assert.That(requests, Is.Empty); + } + + [PlaywrightTest("page-route.spec.ts", "should navigate to URL with hash and and fire requests without hash")] + [Test, Ignore("Not implemented")] + public async Task ShouldNavigateToURLWithHashAndAndFireRequestsWithoutHash() + { + var requests = new List(); + await Page.RouteAsync("**/*", (route) => + { + requests.Add(route.Request); + route.ResumeAsync(); + }); + var response = await Page.GoToAsync(TestConstants.EmptyPage + "#hash"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + Assert.That(response.Url, Is.EqualTo(TestConstants.EmptyPage)); + Assert.That(requests, Has.Exactly(1).Items); + Assert.That(requests[0].Url, Is.EqualTo(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-route.spec.ts", "should work with encoded server")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithEncodedServer() + { + // The requestWillBeSent will report encoded URL, whereas interception will + // report URL as-is. @see crbug.com/759388 + await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/some nonexisting page"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NotFound)); + } + + [PlaywrightTest("page-route.spec.ts", "should work with badly encoded server")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithBadlyEncodedServer() + { + Server.SetRoute("/malformed?rnd=%911", _ => Task.CompletedTask); + await Page.RouteAsync("**/*", (route) => route.ResumeAsync()); + var response = await Page.GoToAsync(TestConstants.ServerUrl + "/malformed?rnd=%911"); + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + } + + [PlaywrightTest("page-route.spec.ts", "should work with encoded server - 2")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithEncodedServer2() + { + // The requestWillBeSent will report URL as-is, whereas interception will + // report encoded URL for stylesheet. @see crbug.com/759388 + var requests = new List(); + await Page.RouteAsync("**/*", (route) => + { + route.ResumeAsync(); + requests.Add(route.Request); + }); + var response = await Page.GoToAsync($"data:text/html,"); + Assert.That(response, Is.Null); + Assert.That(requests, Has.Exactly(1).Items); + Assert.That((await requests[0].GetResponseAsync()).StatusCode, Is.EqualTo(HttpStatusCode.NotFound)); + } + + [PlaywrightTest("page-route.spec.ts", @"should not throw ""Invalid Interception Id"" if the request was cancelled")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotThrowInvalidInterceptionIdIfTheRequestWasCancelled() + { + await Page.SetContentAsync(""); + IRoute route = null; + await Page.RouteAsync("**/*", (r) => route = r); + _ = Page.EvalOnSelectorAsync("iframe", "(frame, url) => frame.src = url", TestConstants.EmptyPage); + // Wait for request interception. + await Page.WaitForEventAsync(PageEvent.Request); + // Delete frame to cause request to be canceled. + await Page.EvalOnSelectorAsync("iframe", "frame => frame.remove()"); + await route.ResumeAsync(); + } + + [PlaywrightTest("page-route.spec.ts", "should intercept main resource during cross-process navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldInterceptMainResourceDuringCrossProcessNavigation() + { + await Page.GoToAsync(TestConstants.EmptyPage); + bool intercepted = false; + await Page.RouteAsync(TestConstants.CrossProcessUrl + "/empty.html", (route) => + { + if (route.Request.Url.Contains(TestConstants.CrossProcessHttpPrefix + "/empty.html")) + { + intercepted = true; + } + + route.ResumeAsync(); + }); + var response = await Page.GoToAsync(TestConstants.CrossProcessHttpPrefix + "/empty.html"); + Assert.That(response.Ok, Is.True); + Assert.That(intercepted, Is.True); + } + + [PlaywrightTest("page-route.spec.ts", "should fulfill with redirect status")] + [SkipBrowserAndPlatformFact(skipWebkit: true)] + public async Task ShouldFulfillWithRedirectStatus() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/title.html"); + Server.SetRoute("/final", context => context.Response.WriteAsync("foo")); + await Page.RouteAsync("**/*", (route) => + { + if (route.Request.Url != TestConstants.ServerUrl + "/redirect_this") + { + route.ResumeAsync(); + return; + } + + _ = route.FulfillAsync( + status: HttpStatusCode.MovedPermanently, + headers: new Dictionary + { + ["location"] = "/final", + }); + }); + + string text = await Page.EvaluateAsync(@"async url => { + const data = await fetch(url); + return data.text(); + }", TestConstants.ServerUrl + "/redirect_this"); + + Assert.That(text, Is.EqualTo("foo")); + } + + [PlaywrightTest("page-route.spec.ts", "should support cors with GET")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportCorsWithGET() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.RouteAsync("**/cars*", (route) => + { + var headers = route.Request.Url.EndsWith("allow") + ? new Dictionary { ["access-control-allow-origin"] = "*" } + : new Dictionary(); + + _ = route.FulfillAsync( + contentType: "application/json", + headers: headers, + status: HttpStatusCode.OK, + body: "[\"electric\", \"cars\"]"); + }); + + string[] resp = await Page.EvaluateAsync(@"async () => { + const response = await fetch('https://example.com/cars?allow', { mode: 'cors' }); + return response.json(); + }"); + + Assert.That(resp, Is.EqualTo(new[] { "electric", "cars" })); + + var exception = Assert.CatchAsync(() => Page.EvaluateAsync(@"async () => { + const response = await fetch('https://example.com/cars?reject', { mode: 'cors' }); + return response.json(); + }")); + + Assert.That(exception.Message, Does.Contain("failed")); + } + + [PlaywrightTest("page-route.spec.ts", "should support cors with POST")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportCorsWithPOST() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.RouteAsync("**/cars*", (route) => + { + _ = route.FulfillAsync( + contentType: "application/json", + headers: new Dictionary { ["access-control-allow-origin"] = "*" }, + status: HttpStatusCode.OK, + body: "[\"electric\", \"cars\"]"); + }); + + string[] resp = await Page.EvaluateAsync(@"async () => { + const response = await fetch('https://example.com/cars', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + mode: 'cors', + body: JSON.stringify({ 'number': 1 }) + }); + return response.json(); + }"); + + Assert.That(resp, Is.EqualTo(new[] { "electric", "cars" })); + } + + [PlaywrightTest("page-route.spec.ts", "should support cors with different methods")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSupportCorsWithDifferentMethods() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.RouteAsync("**/cars*", (route) => + { + _ = route.FulfillAsync( + contentType: "application/json", + headers: new Dictionary { ["access-control-allow-origin"] = "*" }, + status: HttpStatusCode.OK, + body: $"[\"{route.Request.Method.ToString().ToUpper()}\", \"electric\", \"cars\"]"); + }); + + string[] resp = await Page.EvaluateAsync(@"async () => { + const response = await fetch('https://example.com/cars', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + mode: 'cors', + body: JSON.stringify({ 'number': 1 }) + }); + return response.json(); + }"); + + Assert.That(resp, Is.EqualTo(new[] { "POST", "electric", "cars" })); + + resp = await Page.EvaluateAsync(@"async () => { + const response = await fetch('https://example.com/cars', { + method: 'DELETE', + headers: { 'Content-Type': 'application/json' }, + mode: 'cors', + body: JSON.stringify({ 'number': 1 }) + }); + return response.json(); + }"); + + Assert.That(resp, Is.EqualTo(new[] { "DELETE", "electric", "cars" })); + } + } +} diff --git a/src/Playwright.Tests/PageScreenshotTests.cs b/src/PlaywrightSharp.Tests/PageScreenshotTests.cs similarity index 75% rename from src/Playwright.Tests/PageScreenshotTests.cs rename to src/PlaywrightSharp.Tests/PageScreenshotTests.cs index 57f3a2323c..e1f175121e 100644 --- a/src/Playwright.Tests/PageScreenshotTests.cs +++ b/src/PlaywrightSharp.Tests/PageScreenshotTests.cs @@ -1,446 +1,439 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Microsoft.Playwright.Tests.Helpers; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///page-screenshot.spec.ts - - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageScreenshotTests : PlaywrightSharpPageBaseTest - { - /// - public PageScreenshotTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-screenshot.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - byte[] screenshot = await Page.ScreenshotAsync(); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-sanity.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should clip rect")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClipRect() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - byte[] screenshot = await Page.ScreenshotAsync(clip: - new Clip - { - X = 50, - Y = 100, - Width = 150, - Height = 100 - } - ); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-clip-rect.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should clip rect with fullPage")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClipRectWithFullPage() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - await Page.EvaluateAsync("() => window.scrollBy(150, 200)"); - byte[] screenshot = await Page.ScreenshotAsync( - fullPage: true, - clip: new Clip - { - X = 50, - Y = 100, - Width = 150, - Height = 100, - }); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-clip-rect.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should clip elements to the viewport")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldClipElementsToTheViewport() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - byte[] screenshot = await Page.ScreenshotAsync( - clip: new Clip - { - X = 50, - Y = 450, - Width = 1000, - Height = 100, - }); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-offscreen-clip.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should throw on clip outside the viewport")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowOnClipOutsideTheViewport() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - var exception = await Assert.ThrowsAsync(() => Page.ScreenshotAsync( - clip: new Clip - { - X = 50, - Y = 650, - Width = 100, - Height = 100, - })); - - Assert.Contains("Clipped area is either empty or outside the resulting image", exception.Message); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should run in parallel")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRunInParallel() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - - var tasks = new List>(); - for (int i = 0; i < 3; ++i) - { - tasks.Add(Page.ScreenshotAsync( - clip: new Clip - { - X = 50 * i, - Y = 0, - Width = 50, - Height = 50 - })); - } - - await TaskUtils.WhenAll(tasks); - Assert.True(ScreenshotHelper.PixelMatch("grid-cell-1.png", tasks[0].Result)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should take fullPage screenshots")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTakeFullPageScreenshots() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - byte[] screenshot = await Page.ScreenshotAsync(fullPage: true); - Assert.True(ScreenshotHelper.PixelMatch("screenshot-grid-fullpage.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should restore viewport after fullPage screenshot")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRestoreViewportAfterFullPageScreenshot() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - await Page.ScreenshotAsync(fullPage: true); - - Assert.Equal(500, Page.ViewportSize.Width); - Assert.Equal(500, Page.ViewportSize.Height); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should run in parallel in multiple pages")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRunInParallelInMultiplePages() - { - int n = 5; - var pageTasks = new List>(); - for (int i = 0; i < n; i++) - { - async Task Func() - { - var page = await Context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - return page; - } - - pageTasks.Add(Func()); - } - - await TaskUtils.WhenAll(pageTasks); - - var screenshotTasks = new List>(); - for (int i = 0; i < n; i++) - { - screenshotTasks.Add(pageTasks[i].Result.ScreenshotAsync( - clip: new Clip - { - X = 50 * (i % 2), - Y = 0, - Width = 50, - Height = 50 - })); - } - - await TaskUtils.WhenAll(screenshotTasks); - - for (int i = 0; i < n; i++) - { - Assert.True(ScreenshotHelper.PixelMatch($"grid-cell-{i % 2}.png", screenshotTasks[i].Result)); - } - - var closeTasks = new List(); - for (int i = 0; i < n; i++) - { - closeTasks.Add(pageTasks[i].Result.CloseAsync()); - } - - await TaskUtils.WhenAll(closeTasks); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should allow transparency")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldAllowTransparency() - { - await Page.SetViewportSizeAsync(50, 150); - await Page.GoToAsync(TestConstants.EmptyPage); - byte[] screenshot = await Page.ScreenshotAsync(omitBackground: true); - - Assert.True(ScreenshotHelper.PixelMatch("transparent.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should render white background on jpeg file")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRenderWhiteBackgroundOnJpegFile() - { - await Page.SetViewportSizeAsync(100, 100); - await Page.GoToAsync(TestConstants.EmptyPage); - byte[] screenshot = await Page.ScreenshotAsync( - omitBackground: true, - type: ScreenshotType.Jpeg); - Assert.True(ScreenshotHelper.PixelMatch("white.jpg", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should work with odd clip size on Retina displays")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithOddClipSizeOnRetinaDisplays() - { - byte[] screenshot = await Page.ScreenshotAsync( - clip: new Clip - { - X = 0, - Y = 0, - Width = 11, - Height = 11 - }); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-clip-odd-size.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should work with a mobile viewport")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWorkWithAMobileViewport() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 320, - Height = 480, - }, - IsMobile = true, - }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/overflow.html"); - byte[] screenshot = await page.ScreenshotAsync(); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-mobile.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should work with a mobile viewport and clip")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWorkWithAMobileViewportAndClip() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 320, - Height = 480, - }, - IsMobile = true, - }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/overflow.html"); - byte[] screenshot = await page.ScreenshotAsync( - clip: new Clip - { - X = 10, - Y = 10, - Width = 100, - Height = 150 - }); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-mobile-clip.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should work with a mobile viewport and fullPage")] - [SkipBrowserAndPlatformFact(skipFirefox: true)] - public async Task ShouldWorkWithAMobileViewportAndFullPage() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 320, - Height = 480, - }, - IsMobile = true, - }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/overflow-large.html"); - byte[] screenshot = await page.ScreenshotAsync(fullPage: true); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-mobile-fullpage.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should work for canvas")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForCanvas() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/screenshots/canvas.html"); - byte[] screenshot = await Page.ScreenshotAsync(); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-canvas.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should work for webgl")] - [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] - public async Task ShouldWorkForWebgl() - { - await Page.SetViewportSizeAsync(640, 480); - await Page.GoToAsync(TestConstants.ServerUrl + "/screenshots/webgl.html"); - byte[] screenshot = await Page.ScreenshotAsync(); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-webgl.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should work for translateZ")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForTranslateZ() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/screenshots/translateZ.html"); - byte[] screenshot = await Page.ScreenshotAsync(); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-translateZ.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should work while navigating")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWhileNavigating() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/redirectloop1.html"); - - for (int i = 0; i < 10; ++i) - { - try - { - await Page.ScreenshotAsync(); - } - catch (Exception ex) when (ex.Message.Contains("Cannot take a screenshot while page is navigating")) - { - } - } - } - - [PlaywrightTest("page-screenshot.spec.ts", "should work with device scale factor")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithDeviceScaleFactor() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 320, - Height = 480, - }, - DeviceScaleFactor = 2, - }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - byte[] screenshot = await page.ScreenshotAsync(); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-device-scale-factor.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "should work with iframe in shadow")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithiFrameInShadow() - { - await using var context = await Browser.NewContextAsync(new BrowserContextOptions - { - Viewport = new ViewportSize - { - Width = 500, - Height = 500, - }, - }); - var page = await context.NewPageAsync(); - await page.GoToAsync(TestConstants.ServerUrl + "/grid-iframe-in-shadow.html"); - byte[] screenshot = await page.ScreenshotAsync(); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-iframe.png", screenshot)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "path option should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PathOptionShouldWork() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - using var tmpDir = new TempDirectory(); - string outputPath = Path.Combine(tmpDir.Path, "screenshot.png"); - await Page.ScreenshotAsync(outputPath); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-sanity.png", outputPath)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "path option should create subdirectories")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PathOptionShouldCreateSubdirectories() - { - await Page.SetViewportSizeAsync(500, 500); - await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); - using var tmpDir = new TempDirectory(); - string outputPath = Path.Combine(tmpDir.Path, "these", "are", "directories", "screenshot.png"); - await Page.ScreenshotAsync(outputPath); - - Assert.True(ScreenshotHelper.PixelMatch("screenshot-sanity.png", outputPath)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "path option should detect joeg")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PathOptionShouldDetectJpeg() - { - await Page.SetViewportSizeAsync(100, 100); - await Page.GoToAsync(TestConstants.EmptyPage); - using var tmpDir = new TempDirectory(); - string outputPath = Path.Combine(tmpDir.Path, "screenshot.jpg"); - await Page.ScreenshotAsync(outputPath, omitBackground: true); - - Assert.True(ScreenshotHelper.PixelMatch("white.jpg", outputPath)); - } - - [PlaywrightTest("page-screenshot.spec.ts", "path option should throw for unsupported mime type")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task PathOptionShouldThrowForUnsupportedMimeType() - { - var exception = await Assert.ThrowsAnyAsync(() => Page.ScreenshotAsync("file.txt")); - Assert.Contains("path: unsupported mime type \"text/plain\"", exception.Message); - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; +using PlaywrightSharp.Tests.Helpers; + +namespace PlaywrightSharp.Tests +{ + ///page-screenshot.spec.ts + + public class PageScreenshotTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-screenshot.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + byte[] screenshot = await Page.ScreenshotAsync(); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-sanity.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should clip rect")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClipRect() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + byte[] screenshot = await Page.ScreenshotAsync(clip: + new Clip + { + X = 50, + Y = 100, + Width = 150, + Height = 100 + } + ); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-clip-rect.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should clip rect with fullPage")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClipRectWithFullPage() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + await Page.EvaluateAsync("() => window.scrollBy(150, 200)"); + byte[] screenshot = await Page.ScreenshotAsync( + fullPage: true, + clip: new Clip + { + X = 50, + Y = 100, + Width = 150, + Height = 100, + }); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-clip-rect.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should clip elements to the viewport")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldClipElementsToTheViewport() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + byte[] screenshot = await Page.ScreenshotAsync( + clip: new Clip + { + X = 50, + Y = 450, + Width = 1000, + Height = 100, + }); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-offscreen-clip.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should throw on clip outside the viewport")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowOnClipOutsideTheViewport() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + var exception = Assert.ThrowsAsync(() => Page.ScreenshotAsync( + clip: new Clip + { + X = 50, + Y = 650, + Width = 100, + Height = 100, + })); + + Assert.That(exception.Message, Does.Contain("Clipped area is either empty or outside the resulting image")); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should run in parallel")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRunInParallel() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + + var tasks = new List>(); + for (int i = 0; i < 3; ++i) + { + tasks.Add(Page.ScreenshotAsync( + clip: new Clip + { + X = 50 * i, + Y = 0, + Width = 50, + Height = 50 + })); + } + + await TaskUtils.WhenAll(tasks); + Assert.That(ScreenshotHelper.PixelMatch("grid-cell-1.png", tasks[0].Result), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should take fullPage screenshots")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTakeFullPageScreenshots() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + byte[] screenshot = await Page.ScreenshotAsync(fullPage: true); + Assert.That(ScreenshotHelper.PixelMatch("screenshot-grid-fullpage.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should restore viewport after fullPage screenshot")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRestoreViewportAfterFullPageScreenshot() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + await Page.ScreenshotAsync(fullPage: true); + + Assert.That(Page.ViewportSize.Width, Is.EqualTo(500)); + Assert.That(Page.ViewportSize.Height, Is.EqualTo(500)); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should run in parallel in multiple pages")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRunInParallelInMultiplePages() + { + int n = 5; + var pageTasks = new List>(); + for (int i = 0; i < n; i++) + { + async Task Func() + { + var page = await Context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + return page; + } + + pageTasks.Add(Func()); + } + + await TaskUtils.WhenAll(pageTasks); + + var screenshotTasks = new List>(); + for (int i = 0; i < n; i++) + { + screenshotTasks.Add(pageTasks[i].Result.ScreenshotAsync( + clip: new Clip + { + X = 50 * (i % 2), + Y = 0, + Width = 50, + Height = 50 + })); + } + + await TaskUtils.WhenAll(screenshotTasks); + + for (int i = 0; i < n; i++) + { + Assert.That(ScreenshotHelper.PixelMatch($"grid-cell-{i % 2}.png", screenshotTasks[i].Result), Is.True); + } + + var closeTasks = new List(); + for (int i = 0; i < n; i++) + { + closeTasks.Add(pageTasks[i].Result.CloseAsync()); + } + + await TaskUtils.WhenAll(closeTasks); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should allow transparency")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldAllowTransparency() + { + await Page.SetViewportSizeAsync(50, 150); + await Page.GoToAsync(TestConstants.EmptyPage); + byte[] screenshot = await Page.ScreenshotAsync(omitBackground: true); + + Assert.That(ScreenshotHelper.PixelMatch("transparent.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should render white background on jpeg file")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRenderWhiteBackgroundOnJpegFile() + { + await Page.SetViewportSizeAsync(100, 100); + await Page.GoToAsync(TestConstants.EmptyPage); + byte[] screenshot = await Page.ScreenshotAsync( + omitBackground: true, + type: ScreenshotType.Jpeg); + Assert.That(ScreenshotHelper.PixelMatch("white.jpg", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should work with odd clip size on Retina displays")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithOddClipSizeOnRetinaDisplays() + { + byte[] screenshot = await Page.ScreenshotAsync( + clip: new Clip + { + X = 0, + Y = 0, + Width = 11, + Height = 11 + }); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-clip-odd-size.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should work with a mobile viewport")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWorkWithAMobileViewport() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 320, + Height = 480, + }, + IsMobile = true, + }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/overflow.html"); + byte[] screenshot = await page.ScreenshotAsync(); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-mobile.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should work with a mobile viewport and clip")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWorkWithAMobileViewportAndClip() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 320, + Height = 480, + }, + IsMobile = true, + }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/overflow.html"); + byte[] screenshot = await page.ScreenshotAsync( + clip: new Clip + { + X = 10, + Y = 10, + Width = 100, + Height = 150 + }); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-mobile-clip.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should work with a mobile viewport and fullPage")] + [SkipBrowserAndPlatformFact(skipFirefox: true)] + public async Task ShouldWorkWithAMobileViewportAndFullPage() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 320, + Height = 480, + }, + IsMobile = true, + }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/overflow-large.html"); + byte[] screenshot = await page.ScreenshotAsync(fullPage: true); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-mobile-fullpage.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should work for canvas")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForCanvas() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/screenshots/canvas.html"); + byte[] screenshot = await Page.ScreenshotAsync(); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-canvas.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should work for webgl")] + [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] + public async Task ShouldWorkForWebgl() + { + await Page.SetViewportSizeAsync(640, 480); + await Page.GoToAsync(TestConstants.ServerUrl + "/screenshots/webgl.html"); + byte[] screenshot = await Page.ScreenshotAsync(); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-webgl.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should work for translateZ")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForTranslateZ() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/screenshots/translateZ.html"); + byte[] screenshot = await Page.ScreenshotAsync(); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-translateZ.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should work while navigating")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWhileNavigating() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/redirectloop1.html"); + + for (int i = 0; i < 10; ++i) + { + try + { + await Page.ScreenshotAsync(); + } + catch (Exception ex) when (ex.Message.Contains("Cannot take a screenshot while page is navigating")) + { + } + } + } + + [PlaywrightTest("page-screenshot.spec.ts", "should work with device scale factor")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithDeviceScaleFactor() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 320, + Height = 480, + }, + DeviceScaleFactor = 2, + }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + byte[] screenshot = await page.ScreenshotAsync(); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-device-scale-factor.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "should work with iframe in shadow")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithiFrameInShadow() + { + await using var context = await Browser.NewContextAsync(new BrowserContextOptions + { + Viewport = new ViewportSize + { + Width = 500, + Height = 500, + }, + }); + var page = await context.NewPageAsync(); + await page.GoToAsync(TestConstants.ServerUrl + "/grid-iframe-in-shadow.html"); + byte[] screenshot = await page.ScreenshotAsync(); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-iframe.png", screenshot), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "path option should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PathOptionShouldWork() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + using var tmpDir = new TempDirectory(); + string outputPath = Path.Combine(tmpDir.Path, "screenshot.png"); + await Page.ScreenshotAsync(outputPath); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-sanity.png", outputPath), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "path option should create subdirectories")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PathOptionShouldCreateSubdirectories() + { + await Page.SetViewportSizeAsync(500, 500); + await Page.GoToAsync(TestConstants.ServerUrl + "/grid.html"); + using var tmpDir = new TempDirectory(); + string outputPath = Path.Combine(tmpDir.Path, "these", "are", "directories", "screenshot.png"); + await Page.ScreenshotAsync(outputPath); + + Assert.That(ScreenshotHelper.PixelMatch("screenshot-sanity.png", outputPath), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "path option should detect joeg")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PathOptionShouldDetectJpeg() + { + await Page.SetViewportSizeAsync(100, 100); + await Page.GoToAsync(TestConstants.EmptyPage); + using var tmpDir = new TempDirectory(); + string outputPath = Path.Combine(tmpDir.Path, "screenshot.jpg"); + await Page.ScreenshotAsync(outputPath, omitBackground: true); + + Assert.That(ScreenshotHelper.PixelMatch("white.jpg", outputPath), Is.True); + } + + [PlaywrightTest("page-screenshot.spec.ts", "path option should throw for unsupported mime type")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task PathOptionShouldThrowForUnsupportedMimeType() + { + var exception = Assert.CatchAsync(() => Page.ScreenshotAsync("file.txt")); + Assert.That(exception.Message, Does.Contain("path: unsupported mime type \"text/plain\"")); + } + } +} diff --git a/src/PlaywrightSharp.Tests/PageScrollTests.cs b/src/PlaywrightSharp.Tests/PageScrollTests.cs new file mode 100644 index 0000000000..30a3c983b5 --- /dev/null +++ b/src/PlaywrightSharp.Tests/PageScrollTests.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Helpers; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageScrollTests : PlaywrightSharpPageBaseTest + { + } +} diff --git a/src/Playwright.Tests/PageSelectOptionTests.cs b/src/PlaywrightSharp.Tests/PageSelectOptionTests.cs similarity index 61% rename from src/Playwright.Tests/PageSelectOptionTests.cs rename to src/PlaywrightSharp.Tests/PageSelectOptionTests.cs index c22320c6fb..7c981daf08 100644 --- a/src/Playwright.Tests/PageSelectOptionTests.cs +++ b/src/PlaywrightSharp.Tests/PageSelectOptionTests.cs @@ -1,251 +1,244 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageSelectOptionTests : PlaywrightSharpPageBaseTest - { - /// - public PageSelectOptionTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-select-option.spec.ts", "should select single option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectSingleOption() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - await Page.SelectOptionAsync("select", "blue"); - Assert.Equal(new[] { "blue" }, await Page.EvaluateAsync("() => result.onInput")); - Assert.Equal(new[] { "blue" }, await Page.EvaluateAsync("() => result.onChange")); - } - - [PlaywrightTest("page-select-option.spec.ts", "should select single option by value")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectSingleOptionByValue() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - await Page.SelectOptionAsync("select", new SelectOptionValue { Value = "blue" }); - Assert.Equal(new[] { "blue" }, await Page.EvaluateAsync("() => result.onInput")); - Assert.Equal(new[] { "blue" }, await Page.EvaluateAsync("() => result.onChange")); - } - - [PlaywrightTest("page-select-option.spec.ts", "should select single option by label")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectSingleOptionByLabel() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - await Page.SelectOptionAsync("select", new SelectOptionValue { Label = "Indigo" }); - Assert.Equal(new[] { "indigo" }, await Page.EvaluateAsync("() => result.onInput")); - Assert.Equal(new[] { "indigo" }, await Page.EvaluateAsync("() => result.onChange")); - } - - [PlaywrightTest("page-select-option.spec.ts", "should select single option by handle")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectSingleOptionByHandle() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - await Page.SelectOptionAsync("select", await Page.QuerySelectorAsync("[id=whiteOption]")); - Assert.Equal(new[] { "white" }, await Page.EvaluateAsync("() => result.onInput")); - Assert.Equal(new[] { "white" }, await Page.EvaluateAsync("() => result.onChange")); - } - - [PlaywrightTest("page-select-option.spec.ts", "should select single option by index")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectSingleOptionByIndex() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - await Page.SelectOptionAsync("select", new SelectOptionValue { Index = 2 }); - Assert.Equal(new[] { "brown" }, await Page.EvaluateAsync("() => result.onInput")); - Assert.Equal(new[] { "brown" }, await Page.EvaluateAsync("() => result.onChange")); - } - - [PlaywrightTest("page-select-option.spec.ts", "should select single option by multiple attributes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectSingleOptionByMultipleAttributes() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - await Page.SelectOptionAsync("select", new SelectOptionValue { Value = "green", Label = "Green" }); - Assert.Equal(new[] { "green" }, await Page.EvaluateAsync("() => result.onInput")); - Assert.Equal(new[] { "green" }, await Page.EvaluateAsync("() => result.onChange")); - } - - [PlaywrightTest("page-select-option.spec.ts", "should not select single option when some attributes do not match")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotSelectSingleOptionWhenSomeAttributesDoNotMatch() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - await Page.EvalOnSelectorAsync("select", "s => s.value = undefined"); - await Assert.ThrowsAsync(() => Page.SelectOptionAsync("select", new SelectOptionValue { Value = "green", Label = "Brown" })); - Assert.Empty(await Page.EvaluateAsync("() => document.querySelector('select').value")); - } - - [PlaywrightTest("page-select-option.spec.ts", "should select only first option")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectOnlyFirstOption() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - await Page.SelectOptionAsync("select", "blue", "green", "red"); - Assert.Equal(new[] { "blue" }, await Page.EvaluateAsync("() => result.onInput")); - Assert.Equal(new[] { "blue" }, await Page.EvaluateAsync("() => result.onChange")); - } - - [PlaywrightTest("page-select-option.spec.ts", "should not throw when select causes navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotThrowWhenSelectCausesNavigation() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - await Page.EvalOnSelectorAsync("select", "select => select.addEventListener('input', () => window.location = '/empty.html')"); - await TaskUtils.WhenAll( - Page.SelectOptionAsync("select", "blue"), - Page.WaitForNavigationAsync() - ); - Assert.Contains("empty.html", Page.Url); - } - - [PlaywrightTest("page-select-option.spec.ts", "should select multiple options")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectMultipleOptions() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - await Page.EvaluateAsync("() => makeMultiple()"); - await Page.SelectOptionAsync("select", "blue", "green", "red"); - Assert.Equal(new[] { "blue", "green", "red" }, await Page.EvaluateAsync("() => result.onInput")); - Assert.Equal(new[] { "blue", "green", "red" }, await Page.EvaluateAsync("() => result.onChange")); - } - - [PlaywrightTest("page-select-option.spec.ts", "should select multiple options with attributes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSelectMultipleOptionsWithAttributes() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - await Page.EvaluateAsync("() => makeMultiple()"); - await Page.SelectOptionAsync("select", new SelectOptionValue { Value = "blue" }, new SelectOptionValue { Label = "Green" }, new SelectOptionValue { Index = 4 }); - Assert.Equal(new[] { "blue", "gray", "green" }, await Page.EvaluateAsync("() => result.onInput")); - Assert.Equal(new[] { "blue", "gray", "green" }, await Page.EvaluateAsync("() => result.onChange")); - } - - [PlaywrightTest("page-select-option.spec.ts", "should respect event bubbling")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRespectEventBubbling() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - await Page.SelectOptionAsync("select", "blue"); - Assert.Equal(new[] { "blue" }, await Page.EvaluateAsync("() => result.onBubblingInput")); - Assert.Equal(new[] { "blue" }, await Page.EvaluateAsync("() => result.onBubblingChange")); - } - - [PlaywrightTest("page-select-option.spec.ts", "should throw when element is not a <select>")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowWhenElementIsNotASelect() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); - var exception = await Assert.ThrowsAsync(() => Page.SelectOptionAsync("body", string.Empty)); - Assert.Contains("Element is not a element.")); + } + + [PlaywrightTest("page-select-option.spec.ts", "should return [] on no matched values")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnEmptyArrayOnNoMatchedValues() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); + var result = await Page.SelectOptionAsync("select", Array.Empty()); + Assert.That(result, Is.Empty); + } + + [PlaywrightTest("page-select-option.spec.ts", "should return an array of matched values")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnAnArrayOfMatchedValues() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); + await Page.EvaluateAsync("() => makeMultiple()"); + var result = await Page.SelectOptionAsync("select", "blue", "black", "magenta"); + Assert.That(result.OrderBy(v => v), Is.EqualTo(new[] { "blue", "black", "magenta" }.OrderBy(v => v))); + } + + [PlaywrightTest("page-select-option.spec.ts", "should return an array of one element when multiple is not set")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnAnArrayOfOneElementWhenMultipleIsNotSet() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); + var result = await Page.SelectOptionAsync("select", "42", "blue", "black", "magenta"); + Assert.That(result, Has.Exactly(1).Items); + } + + [PlaywrightTest("page-select-option.spec.ts", "should return [] on no values")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnEmptyArrayOnNoValues() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); + var result = await Page.SelectOptionAsync("select", Array.Empty()); + Assert.That(result, Is.Empty); + } + + [PlaywrightTest("page-select-option.spec.ts", "should not allow null items")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotAllowNullItems() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); + await Page.EvaluateAsync("() => makeMultiple()"); + var exception = Assert.ThrowsAsync( + () => Page.SelectOptionAsync("select", new[] { "blue", null, "black", "magenta" })); + Assert.That(exception.Message, Does.Contain("got null")); + } + + [PlaywrightTest("page-select-option.spec.ts", "should unselect with null")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldUnselectWithNull() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); + await Page.EvaluateAsync("() => makeMultiple()"); + var result = await Page.SelectOptionAsync("select", new[] { "blue", "black", "magenta" }); + Assert.That(result.All(r => new[] { "blue", "black", "magenta" }.Contains(r)), Is.True); + await Page.SelectOptionAsync("select"); + Assert.That(await Page.EvalOnSelectorAsync("select", "select => Array.from(select.options).every(option => !option.selected)"), Is.True); + } + + [PlaywrightTest("page-select-option.spec.ts", "should deselect all options when passed no values for a multiple select")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDeselectAllOptionsWhenPassedNoValuesForAMultipleSelect() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); + await Page.EvaluateAsync("() => makeMultiple()"); + await Page.SelectOptionAsync("select", "blue", "black", "magenta"); + await Page.SelectOptionAsync("select"); + Assert.That(await Page.EvalOnSelectorAsync("select", "select => Array.from(select.options).every(option => !option.selected)"), Is.True); + } + + [PlaywrightTest("page-select-option.spec.ts", "should deselect all options when passed no values for a select without multiple")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDeselectAllOptionsWhenPassedNoValuesForASelectWithoutMultiple() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); + await Page.SelectOptionAsync("select", "blue", "black", "magenta"); + await Page.SelectOptionAsync("select", Array.Empty()); + Assert.That(await Page.EvalOnSelectorAsync("select", "select => Array.from(select.options).every(option => !option.selected)"), Is.True); + } + + [PlaywrightTest("page-select-option.spec.ts", "should throw if passed wrong types")] + [Test, Ignore("Not relevant for C#, js specific")] + public void ShouldThrowIfPassedWrongTypes() + { + } + + [PlaywrightTest("page-select-option.spec.ts", "should work when re-defining top-level Event class")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWhenReDefiningTopLevelEventClass() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/select.html"); + await Page.EvaluateAsync("() => window.Event = null"); + await Page.SelectOptionAsync("select", "blue"); + Assert.That(await Page.EvaluateAsync("() => result.onInput"), Is.EqualTo(new[] { "blue" })); + Assert.That(await Page.EvaluateAsync("() => result.onChange"), Is.EqualTo(new[] { "blue" })); + } + } +} diff --git a/src/Playwright.Tests/PageSetContentTests.cs b/src/PlaywrightSharp.Tests/PageSetContentTests.cs similarity index 68% rename from src/Playwright.Tests/PageSetContentTests.cs rename to src/PlaywrightSharp.Tests/PageSetContentTests.cs index a9e5b7c21f..9feea87b4c 100644 --- a/src/Playwright.Tests/PageSetContentTests.cs +++ b/src/PlaywrightSharp.Tests/PageSetContentTests.cs @@ -1,143 +1,137 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageSetContentTests : PlaywrightSharpPageBaseTest - { - const string _expectedOutput = "
hello
"; - - /// - public PageSetContentTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-set-content.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.SetContentAsync("
hello
"); - string result = await Page.ContentAsync(); - Assert.Equal(_expectedOutput, result); - } - - [PlaywrightTest("page-set-content.spec.ts", "should work with domcontentloaded")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithDomcontentloaded() - { - await Page.SetContentAsync("
hello
", waitUntil: WaitUntilState.DOMContentLoaded); - string result = await Page.ContentAsync(); - Assert.Equal(_expectedOutput, result); - } - - [PlaywrightTest("page-set-content.spec.ts", "should work with doctype")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithDoctype() - { - string doctype = ""; - await Page.SetContentAsync($"{doctype}
hello
"); - string result = await Page.ContentAsync(); - Assert.Equal($"{doctype}{_expectedOutput}", result); - } - - [PlaywrightTest("page-set-content.spec.ts", "should work with HTML 4 doctype")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithHTML4Doctype() - { - string doctype = ""; - await Page.SetContentAsync($"{doctype}
hello
"); - string result = await Page.ContentAsync(); - Assert.Equal($"{doctype}{_expectedOutput}", result); - } - - [PlaywrightTest("page-set-content.spec.ts", "should respect timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRespectTimeout() - { - string imgPath = "/img.png"; - // stall for image - Server.SetRoute(imgPath, _ => Task.Delay(Timeout.Infinite)); - await Assert.ThrowsAsync(() => - Page.SetContentAsync($"", timeout: 1) - ); - } - - [PlaywrightTest("page-set-content.spec.ts", "should respect default navigation timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRespectDefaultNavigationTimeout() - { - Page.DefaultNavigationTimeout = 1; - string imgPath = "/img.png"; - // stall for image - Server.SetRoute(imgPath, _ => Task.Delay(Timeout.Infinite)); - var exception = await Assert.ThrowsAsync(() => - Page.SetContentAsync($"", timeout: 1) - ); - - Assert.Contains("Timeout 1ms exceeded", exception.Message); - } - - [PlaywrightTest("page-set-content.spec.ts", "should await resources to load")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAwaitResourcesToLoad() - { - string imgPath = "/img.png"; - var imgResponse = new TaskCompletionSource(); - Server.SetRoute(imgPath, _ => imgResponse.Task); - bool loaded = false; - var contentTask = Page.SetContentAsync($"").ContinueWith(_ => loaded = true); - await Server.WaitForRequest(imgPath); - Assert.False(loaded); - imgResponse.SetResult(true); - await contentTask; - } - - [PlaywrightTest("page-set-content.spec.ts", "should work fast enough")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkFastEnough() - { - for (int i = 0; i < 20; ++i) - { - await Page.SetContentAsync("
yo
"); - } - } - - [PlaywrightTest("page-set-content.spec.ts", "should work with tricky content")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithTrickyContent() - { - await Page.SetContentAsync("
hello world
" + "\x7F"); - Assert.Equal("hello world", await Page.EvalOnSelectorAsync("div", "div => div.textContent")); - } - - [PlaywrightTest("page-set-content.spec.ts", "should work with accents")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithAccents() - { - await Page.SetContentAsync("
aberración
"); - Assert.Equal("aberración", await Page.EvalOnSelectorAsync("div", "div => div.textContent")); - } - - [PlaywrightTest("page-set-content.spec.ts", "should work with emojis")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithEmojis() - { - await Page.SetContentAsync("
🐥
"); - Assert.Equal("🐥", await Page.EvalOnSelectorAsync("div", "div => div.textContent")); - } - - [PlaywrightTest("page-set-content.spec.ts", "should work with newline")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithNewline() - { - await Page.SetContentAsync("
\n
"); - Assert.Equal("\n", await Page.EvalOnSelectorAsync("div", "div => div.textContent")); - } - } -} +using System; +using System.Threading; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageSetContentTests : PlaywrightSharpPageBaseTest + { + const string _expectedOutput = "
hello
"; + + /// + [PlaywrightTest("page-set-content.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.SetContentAsync("
hello
"); + string result = await Page.ContentAsync(); + Assert.That(result, Is.EqualTo(_expectedOutput)); + } + + [PlaywrightTest("page-set-content.spec.ts", "should work with domcontentloaded")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithDomcontentloaded() + { + await Page.SetContentAsync("
hello
", waitUntil: WaitUntilState.DOMContentLoaded); + string result = await Page.ContentAsync(); + Assert.That(result, Is.EqualTo(_expectedOutput)); + } + + [PlaywrightTest("page-set-content.spec.ts", "should work with doctype")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithDoctype() + { + string doctype = ""; + await Page.SetContentAsync($"{doctype}
hello
"); + string result = await Page.ContentAsync(); + Assert.That(result, Is.EqualTo($"{doctype}{_expectedOutput}")); + } + + [PlaywrightTest("page-set-content.spec.ts", "should work with HTML 4 doctype")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithHTML4Doctype() + { + string doctype = ""; + await Page.SetContentAsync($"{doctype}
hello
"); + string result = await Page.ContentAsync(); + Assert.That(result, Is.EqualTo($"{doctype}{_expectedOutput}")); + } + + [PlaywrightTest("page-set-content.spec.ts", "should respect timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRespectTimeout() + { + string imgPath = "/img.png"; + // stall for image + Server.SetRoute(imgPath, _ => Task.Delay(Timeout.Infinite)); + Assert.ThrowsAsync(() => + Page.SetContentAsync($"", timeout: 1) + ); + } + + [PlaywrightTest("page-set-content.spec.ts", "should respect default navigation timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRespectDefaultNavigationTimeout() + { + Page.DefaultNavigationTimeout = 1; + string imgPath = "/img.png"; + // stall for image + Server.SetRoute(imgPath, _ => Task.Delay(Timeout.Infinite)); + var exception = Assert.ThrowsAsync(() => + Page.SetContentAsync($"", timeout: 1) + ); + + Assert.That(exception.Message, Does.Contain("Timeout 1ms exceeded")); + } + + [PlaywrightTest("page-set-content.spec.ts", "should await resources to load")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAwaitResourcesToLoad() + { + string imgPath = "/img.png"; + var imgResponse = new TaskCompletionSource(); + Server.SetRoute(imgPath, _ => imgResponse.Task); + bool loaded = false; + var contentTask = Page.SetContentAsync($"").ContinueWith(_ => loaded = true); + await Server.WaitForRequest(imgPath); + Assert.That(loaded, Is.False); + imgResponse.SetResult(true); + await contentTask; + } + + [PlaywrightTest("page-set-content.spec.ts", "should work fast enough")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkFastEnough() + { + for (int i = 0; i < 20; ++i) + { + await Page.SetContentAsync("
yo
"); + } + } + + [PlaywrightTest("page-set-content.spec.ts", "should work with tricky content")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithTrickyContent() + { + await Page.SetContentAsync("
hello world
" + "\x7F"); + Assert.That(await Page.EvalOnSelectorAsync("div", "div => div.textContent"), Is.EqualTo("hello world")); + } + + [PlaywrightTest("page-set-content.spec.ts", "should work with accents")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithAccents() + { + await Page.SetContentAsync("
aberración
"); + Assert.That(await Page.EvalOnSelectorAsync("div", "div => div.textContent"), Is.EqualTo("aberración")); + } + + [PlaywrightTest("page-set-content.spec.ts", "should work with emojis")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithEmojis() + { + await Page.SetContentAsync("
🐥
"); + Assert.That(await Page.EvalOnSelectorAsync("div", "div => div.textContent"), Is.EqualTo("🐥")); + } + + [PlaywrightTest("page-set-content.spec.ts", "should work with newline")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithNewline() + { + await Page.SetContentAsync("
\n
"); + Assert.That(await Page.EvalOnSelectorAsync("div", "div => div.textContent"), Is.EqualTo("\n")); + } + } +} diff --git a/src/Playwright.Tests/PageSetExtraHttpHeadersTests.cs b/src/PlaywrightSharp.Tests/PageSetExtraHttpHeadersTests.cs similarity index 76% rename from src/Playwright.Tests/PageSetExtraHttpHeadersTests.cs rename to src/PlaywrightSharp.Tests/PageSetExtraHttpHeadersTests.cs index 74aa4d8db9..fab534d951 100644 --- a/src/Playwright.Tests/PageSetExtraHttpHeadersTests.cs +++ b/src/PlaywrightSharp.Tests/PageSetExtraHttpHeadersTests.cs @@ -1,94 +1,87 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageSetExtraHTTPHeadersTests : PlaywrightSharpPageBaseTest - { - /// - public PageSetExtraHTTPHeadersTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-set-extra-http-headers.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.SetExtraHttpHeadersAsync(new Dictionary - { - ["Foo"] = "Bar" - }); - - var headerTask = Server.WaitForRequest("/empty.html", request => request.Headers["Foo"]); - await TaskUtils.WhenAll(Page.GoToAsync(TestConstants.EmptyPage), headerTask); - - Assert.Equal("Bar", headerTask.Result); - } - - [PlaywrightTest("page-set-extra-http-headers.spec.ts", "should work with redirects")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithRedirects() - { - Server.SetRedirect("/foo.html", "/empty.html"); - await Page.SetExtraHttpHeadersAsync(new Dictionary - { - ["Foo"] = "Bar" - }); - - var headerTask = Server.WaitForRequest("/empty.html", request => request.Headers["Foo"]); - await TaskUtils.WhenAll(Page.GoToAsync(TestConstants.ServerUrl + "/foo.html"), headerTask); - - Assert.Equal("Bar", headerTask.Result); - } - - [PlaywrightTest("page-set-extra-http-headers.spec.ts", "should work with extra headers from browser context")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithExtraHeadersFromBrowserContext() - { - await using var context = await Browser.NewContextAsync(); - await context.SetExtraHttpHeadersAsync(new Dictionary - { - ["Foo"] = "Bar" - }); - var page = await context.NewPageAsync(); - - var headerTask = Server.WaitForRequest("/empty.html", request => request.Headers["Foo"]); - await TaskUtils.WhenAll(page.GoToAsync(TestConstants.EmptyPage), headerTask); - - Assert.Equal("Bar", headerTask.Result); - } - - [PlaywrightTest("page-set-extra-http-headers.spec.ts", "should override extra headers from browser context")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldOverrideExtraHeadersFromBrowserContext() - { - await using var context = await Browser.NewContextAsync(); - await context.SetExtraHttpHeadersAsync(new Dictionary - { - ["fOo"] = "bAr", - ["baR"] = "foO", - }); - var page = await context.NewPageAsync(); - - await page.SetExtraHttpHeadersAsync(new Dictionary - { - ["Foo"] = "Bar" - }); - - var headerTask = Server.WaitForRequest("/empty.html", request => (request.Headers["Foo"], request.Headers["baR"])); - await TaskUtils.WhenAll(page.GoToAsync(TestConstants.EmptyPage), headerTask); - - Assert.Equal("Bar", headerTask.Result.Item1); - Assert.Equal("foO", headerTask.Result.Item2); - } - - [PlaywrightTest("page-set-extra-http-headers.spec.ts", "should throw for non-string header values")] - [Fact(Skip = "We don't need this test")] - public void ShouldThrowForNonStringHeaderValues() { } - } -} +using System.Collections.Generic; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageSetExtraHTTPHeadersTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-set-extra-http-headers.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.SetExtraHttpHeadersAsync(new Dictionary + { + ["Foo"] = "Bar" + }); + + var headerTask = Server.WaitForRequest("/empty.html", request => request.Headers["Foo"]); + await TaskUtils.WhenAll(Page.GoToAsync(TestConstants.EmptyPage), headerTask); + + Assert.That(headerTask.Result, Is.EqualTo("Bar")); + } + + [PlaywrightTest("page-set-extra-http-headers.spec.ts", "should work with redirects")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithRedirects() + { + Server.SetRedirect("/foo.html", "/empty.html"); + await Page.SetExtraHttpHeadersAsync(new Dictionary + { + ["Foo"] = "Bar" + }); + + var headerTask = Server.WaitForRequest("/empty.html", request => request.Headers["Foo"]); + await TaskUtils.WhenAll(Page.GoToAsync(TestConstants.ServerUrl + "/foo.html"), headerTask); + + Assert.That(headerTask.Result, Is.EqualTo("Bar")); + } + + [PlaywrightTest("page-set-extra-http-headers.spec.ts", "should work with extra headers from browser context")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithExtraHeadersFromBrowserContext() + { + await using var context = await Browser.NewContextAsync(); + await context.SetExtraHttpHeadersAsync(new Dictionary + { + ["Foo"] = "Bar" + }); + var page = await context.NewPageAsync(); + + var headerTask = Server.WaitForRequest("/empty.html", request => request.Headers["Foo"]); + await TaskUtils.WhenAll(page.GoToAsync(TestConstants.EmptyPage), headerTask); + + Assert.That(headerTask.Result, Is.EqualTo("Bar")); + } + + [PlaywrightTest("page-set-extra-http-headers.spec.ts", "should override extra headers from browser context")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldOverrideExtraHeadersFromBrowserContext() + { + await using var context = await Browser.NewContextAsync(); + await context.SetExtraHttpHeadersAsync(new Dictionary + { + ["fOo"] = "bAr", + ["baR"] = "foO", + }); + var page = await context.NewPageAsync(); + + await page.SetExtraHttpHeadersAsync(new Dictionary + { + ["Foo"] = "Bar" + }); + + var headerTask = Server.WaitForRequest("/empty.html", request => (request.Headers["Foo"], request.Headers["baR"])); + await TaskUtils.WhenAll(page.GoToAsync(TestConstants.EmptyPage), headerTask); + + Assert.That(headerTask.Result.Item1, Is.EqualTo("Bar")); + Assert.That(headerTask.Result.Item2, Is.EqualTo("foO")); + } + + [PlaywrightTest("page-set-extra-http-headers.spec.ts", "should throw for non-string header values")] + [Test, Ignore("We don't need this test")] + public void ShouldThrowForNonStringHeaderValues() { } + } +} diff --git a/src/Playwright.Tests/PageSetInputFilesTests.cs b/src/PlaywrightSharp.Tests/PageSetInputFilesTests.cs similarity index 70% rename from src/Playwright.Tests/PageSetInputFilesTests.cs rename to src/PlaywrightSharp.Tests/PageSetInputFilesTests.cs index 2bb28286c3..52166917a5 100644 --- a/src/Playwright.Tests/PageSetInputFilesTests.cs +++ b/src/PlaywrightSharp.Tests/PageSetInputFilesTests.cs @@ -1,363 +1,357 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///page-set-input-files.spec.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageSetInputFilesTests : PlaywrightSharpPageBaseTest - { - /// - public PageSetInputFilesTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should upload the file")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldUploadTheFile() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/input/fileupload.html"); - string filePath = Path.Combine(Directory.GetCurrentDirectory(), "Assets", TestConstants.FileToUpload); - var input = await Page.QuerySelectorAsync("input"); - await input.SetInputFilesAsync(filePath); - Assert.Equal("file-to-upload.txt", await Page.EvaluateAsync("e => e.files[0].name", input)); - Assert.Equal("contents of the file", await Page.EvaluateAsync(@"e => { - var reader = new FileReader(); - var promise = new Promise(fulfill => reader.onload = fulfill); - reader.readAsText(e.files[0]); - return promise.then(() => reader.result); - }", input)); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.SetContentAsync(""); - string filePath = Path.Combine(Directory.GetCurrentDirectory(), "Assets", TestConstants.FileToUpload); - await Page.SetInputFilesAsync("input", filePath); - - Assert.Equal(1, await Page.EvalOnSelectorAsync("input", "e => e.files.length")); - Assert.Equal("file-to-upload.txt", await Page.EvalOnSelectorAsync("input", "e => e.files[0].name")); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should set from memory")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSetFromMemory() - { - await Page.SetContentAsync(""); - - await Page.SetInputFilesAsync("input", new FilePayload - { - Name = "test.txt", - MimeType = "text/plain", - Buffer = Encoding.UTF8.GetBytes("this is a test"), - }); - - Assert.Equal(1, await Page.EvalOnSelectorAsync("input", "e => e.files.length")); - Assert.Equal("test.txt", await Page.EvalOnSelectorAsync("input", "e => e.files[0].name")); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should emit event once")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEmitEventOnce() - { - await Page.SetContentAsync(""); - var chooserTsc = new TaskCompletionSource(); - void EventHandler(object sender, IFileChooser e) - { - chooserTsc.SetResult(e.Element); - Page.FileChooser -= EventHandler; - } - Page.FileChooser += EventHandler; - var chooser = await TaskUtils.WhenAll( - chooserTsc.Task, - Page.ClickAsync("input") - ); - Assert.NotNull(chooser); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should emit event on/off")] - [Fact(Skip = "We dont'need to test this")] - public void ShouldEmitEventOnOff() - { - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should emit addListener/removeListener")] - [Fact(Skip = "We dont'need to test this")] - public void ShouldEmitEventAddListenerRemoveListener() - { - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should work when file input is attached to DOM")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWhenFileInputIsAttachedToDOM() - { - await Page.SetContentAsync(""); - var chooser = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.FileChooser), - Page.ClickAsync("input") - ); - Assert.NotNull(chooser?.Element); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should work when file input is not attached to DOM")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWhenFileInputIsNotAttachedToDOM() - { - var (chooser, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.FileChooser), - Page.EvaluateAsync(@"() => { - var el = document.createElement('input'); - el.type = 'file'; - el.click(); - }") - ); - Assert.NotNull(chooser?.Element); - } - - - [PlaywrightTest("page-set-input-files.spec.ts", "should work with CSP")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithCSP() - { - Server.SetCSP("/empty.html", "default-src \"none\""); - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync(""); - - await Page.SetInputFilesAsync("input", Path.Combine(Directory.GetCurrentDirectory(), "Assets", TestConstants.FileToUpload)); - Assert.Equal(1, await Page.EvalOnSelectorAsync("input", "input => input.files.length")); - Assert.Equal("file-to-upload.txt", await Page.EvalOnSelectorAsync("input", "input => input.files[0].name")); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should respect timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public Task ShouldRespectTimeout() => Assert.ThrowsAsync(() - => Page.WaitForEventAsync(PageEvent.FileChooser, timeout: 1)); - - [PlaywrightTest("page-set-input-files.spec.ts", "should respect default timeout when there is no custom timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRespectDefaultTimeoutWhenThereIsNoCustomTimeout() - { - Page.DefaultTimeout = 1; - await Assert.ThrowsAsync(() => Page.WaitForEventAsync(PageEvent.FileChooser)); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should prioritize exact timeout over default timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldPrioritizeExactTimeoutOverDefaultTimeout() - { - Page.DefaultTimeout = 0; - await Assert.ThrowsAsync(() => Page.WaitForEventAsync(PageEvent.FileChooser, timeout: 1)); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should work with no timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithNoTimeout() - { - var (chooser, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.FileChooser, timeout: 0), - Page.EvaluateAsync(@"() => setTimeout(() => { - var el = document.createElement('input'); - el.type = 'file'; - el.click(); - }, 50)") - ); - Assert.NotNull(chooser?.Element); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should return the same file chooser when there are many watchdogs simultaneously")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnTheSameFileChooserWhenThereAreManyWatchdogsSimultaneously() - { - await Page.SetContentAsync(""); - var (fileChooser1, fileChooser2, _) = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.FileChooser), - Page.WaitForEventAsync(PageEvent.FileChooser), - Page.EvalOnSelectorAsync("input", "input => input.click()") - ); - Assert.Equal(fileChooser1, fileChooser2); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should accept single file")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptSingleFile() - { - await Page.SetContentAsync(""); - var fileChooser = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.FileChooser), - Page.ClickAsync("input") - ); - - Assert.Same(Page, fileChooser.Page); - Assert.NotNull(fileChooser.Element); - await fileChooser.SetFilesAsync(TestConstants.FileToUpload); - Assert.Equal(1, await Page.EvalOnSelectorAsync("input", "input => input.files.length")); - Assert.Equal("file-to-upload.txt", await Page.EvalOnSelectorAsync("input", "input => input.files[0].name")); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should detect mime type")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDetectMimeType() - { - var files = new List<(string name, string mime, byte[] content)>(); - - Server.SetRoute("/upload", context => - { - files.AddRange(context.Request.Form.Files.Select(f => - { - using var ms = new MemoryStream(); - f.CopyTo(ms); - return (f.FileName, f.ContentType, ms.ToArray()); - })); - return Task.CompletedTask; - }); - - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync(@" -
- - - -
- "); - - await (await Page.QuerySelectorAsync("input[name=file1]")).SetInputFilesAsync(TestUtils.GetWebServerFile("file-to-upload.txt")); - await (await Page.QuerySelectorAsync("input[name=file2]")).SetInputFilesAsync(TestUtils.GetWebServerFile("pptr.png")); - - await TaskUtils.WhenAll( - Page.ClickAsync("input[type=submit]"), - Server.WaitForRequest("/upload") - ); - - Assert.Equal("file-to-upload.txt", files[0].name); - Assert.Equal("text/plain", files[0].mime); - Assert.Equal(File.ReadAllBytes(TestUtils.GetWebServerFile("file-to-upload.txt")), files[0].content); - - Assert.Equal("pptr.png", files[1].name); - Assert.Equal("image/png", files[1].mime); - Assert.Equal(File.ReadAllBytes(TestUtils.GetWebServerFile("pptr.png")), files[1].content); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should be able to read selected file")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToReadSelectedFile() - { - await Page.SetContentAsync(""); - _ = Page.WaitForEventAsync(PageEvent.FileChooser) - .ContinueWith(task => task.Result.SetFilesAsync(TestConstants.FileToUpload)); - Assert.Equal("contents of the file", await Page.EvalOnSelectorAsync("input", @"async picker => { - picker.click(); - await new Promise(x => picker.oninput = x); - const reader = new FileReader(); - const promise = new Promise(fulfill => reader.onload = fulfill); - reader.readAsText(picker.files[0]); - return promise.then(() => reader.result); - }")); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should be able to reset selected files with empty file list")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldBeAbleToResetSelectedFilesWithEmptyFileList() - { - await Page.SetContentAsync(""); - _ = Page.WaitForEventAsync(PageEvent.FileChooser) - .ContinueWith(task => task.Result.SetFilesAsync(TestConstants.FileToUpload)); - Assert.Equal(1, await Page.EvalOnSelectorAsync("input", @"async picker => { - picker.click(); - await new Promise(x => picker.oninput = x); - return picker.files.length; - }")); - _ = Page.WaitForEventAsync(PageEvent.FileChooser) - .ContinueWith(task => task.Result.Element.SetInputFilesAsync(new string[] { })); - Assert.Equal(0, await Page.EvalOnSelectorAsync("input", @"async picker => { - picker.click(); - await new Promise(x => picker.oninput = x); - return picker.files.length; - }")); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should not accept multiple files for single-file input")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldNotAcceptMultipleFilesForSingleFileInput() - { - await Page.SetContentAsync(""); - var fileChooser = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.FileChooser), - Page.ClickAsync("input") - ); - await Assert.ThrowsAsync(() => fileChooser.SetFilesAsync(new string[] - { - TestUtils.GetWebServerFile(TestConstants.FileToUpload), - TestUtils.GetWebServerFile("pptr.png"), - })); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should emit input and change events")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldEmitInputAndChangeEvents() - { - var events = new List(); - await Page.ExposeFunctionAsync("eventHandled", (string e) => events.Add(e)); - - await Page.SetContentAsync(@" - - - "); - - await (await Page.QuerySelectorAsync("input")).SetInputFilesAsync(TestUtils.GetWebServerFile("file-to-upload.txt")); - Assert.Equal(2, events.Count); - Assert.Equal("input", events[0]); - Assert.Equal("change", events[1]); - } - - [PlaywrightTest("page-set-input-files.spec.ts", "should work for single file pick")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForSingleFilePick() - { - await Page.SetContentAsync(""); - var waitTask = Page.WaitForEventAsync(PageEvent.FileChooser); - - var fileChooser = await TaskUtils.WhenAll( - waitTask, - Page.ClickAsync("input") - ); - Assert.False(fileChooser.IsMultiple); - } - - [PlaywrightTest("page-set-input-files.spec.ts", @"should work for ""multiple""")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForMultiple() - { - await Page.SetContentAsync(""); - var fileChooser = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.FileChooser), - Page.ClickAsync("input") - ); - Assert.True(fileChooser.IsMultiple); - } - - [PlaywrightTest("page-set-input-files.spec.ts", @"should work for ""webkitdirectory""")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForWebkitdirectory() - { - await Page.SetContentAsync(""); - var fileChooser = await TaskUtils.WhenAll( - Page.WaitForEventAsync(PageEvent.FileChooser), - Page.ClickAsync("input") - ); - Assert.True(fileChooser.IsMultiple); - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///page-set-input-files.spec.ts + public class PageSetInputFilesTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-set-input-files.spec.ts", "should upload the file")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldUploadTheFile() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/input/fileupload.html"); + string filePath = Path.Combine(Directory.GetCurrentDirectory(), "Assets", TestConstants.FileToUpload); + var input = await Page.QuerySelectorAsync("input"); + await input.SetInputFilesAsync(filePath); + Assert.That(await Page.EvaluateAsync("e => e.files[0].name", input), Is.EqualTo("file-to-upload.txt")); + Assert.That(await Page.EvaluateAsync(@"e => { + var reader = new FileReader(); + var promise = new Promise(fulfill => reader.onload = fulfill); + reader.readAsText(e.files[0]); + return promise.then(() => reader.result); + }", input), Is.EqualTo("contents of the file")); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should work")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWork() + { + await Page.SetContentAsync(""); + string filePath = Path.Combine(Directory.GetCurrentDirectory(), "Assets", TestConstants.FileToUpload); + await Page.SetInputFilesAsync("input", filePath); + + Assert.That(await Page.EvalOnSelectorAsync("input", "e => e.files.length"), Is.EqualTo(1)); + Assert.That(await Page.EvalOnSelectorAsync("input", "e => e.files[0].name"), Is.EqualTo("file-to-upload.txt")); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should set from memory")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSetFromMemory() + { + await Page.SetContentAsync(""); + + await Page.SetInputFilesAsync("input", new FilePayload + { + Name = "test.txt", + MimeType = "text/plain", + Buffer = Encoding.UTF8.GetBytes("this is a test"), + }); + + Assert.That(await Page.EvalOnSelectorAsync("input", "e => e.files.length"), Is.EqualTo(1)); + Assert.That(await Page.EvalOnSelectorAsync("input", "e => e.files[0].name"), Is.EqualTo("test.txt")); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should emit event once")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEmitEventOnce() + { + await Page.SetContentAsync(""); + var chooserTsc = new TaskCompletionSource(); + void EventHandler(object sender, IFileChooser e) + { + chooserTsc.SetResult(e.Element); + Page.FileChooser -= EventHandler; + } + Page.FileChooser += EventHandler; + var chooser = await TaskUtils.WhenAll( + chooserTsc.Task, + Page.ClickAsync("input") + ); + Assert.That(chooser, Is.Not.Null); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should emit event on/off")] + [Test, Ignore("We dont'need to test this")] + public void ShouldEmitEventOnOff() + { + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should emit addListener/removeListener")] + [Test, Ignore("We dont'need to test this")] + public void ShouldEmitEventAddListenerRemoveListener() + { + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should work when file input is attached to DOM")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWhenFileInputIsAttachedToDOM() + { + await Page.SetContentAsync(""); + var chooser = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.FileChooser), + Page.ClickAsync("input") + ); + Assert.That(chooser?.Element, Is.Not.Null); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should work when file input is not attached to DOM")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWhenFileInputIsNotAttachedToDOM() + { + var (chooser, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.FileChooser), + Page.EvaluateAsync(@"() => { + var el = document.createElement('input'); + el.type = 'file'; + el.click(); + }") + ); + Assert.That(chooser?.Element, Is.Not.Null); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should work with CSP")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithCSP() + { + Server.SetCSP("/empty.html", "default-src \"none\""); + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.SetContentAsync(""); + + await Page.SetInputFilesAsync("input", Path.Combine(Directory.GetCurrentDirectory(), "Assets", TestConstants.FileToUpload)); + Assert.That(await Page.EvalOnSelectorAsync("input", "input => input.files.length"), Is.EqualTo(1)); + Assert.That(await Page.EvalOnSelectorAsync("input", "input => input.files[0].name"), Is.EqualTo("file-to-upload.txt")); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should respect timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public void ShouldRespectTimeout() + { + Assert.ThrowsAsync(() => Page.WaitForEventAsync(PageEvent.FileChooser, timeout: 1)); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should respect default timeout when there is no custom timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRespectDefaultTimeoutWhenThereIsNoCustomTimeout() + { + Page.DefaultTimeout = 1; + Assert.ThrowsAsync(() => Page.WaitForEventAsync(PageEvent.FileChooser)); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should prioritize exact timeout over default timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldPrioritizeExactTimeoutOverDefaultTimeout() + { + Page.DefaultTimeout = 0; + Assert.ThrowsAsync(() => Page.WaitForEventAsync(PageEvent.FileChooser, timeout: 1)); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should work with no timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithNoTimeout() + { + var (chooser, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.FileChooser, timeout: 0), + Page.EvaluateAsync(@"() => setTimeout(() => { + var el = document.createElement('input'); + el.type = 'file'; + el.click(); + }, 50)") + ); + Assert.That(chooser?.Element, Is.Not.Null); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should return the same file chooser when there are many watchdogs simultaneously")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnTheSameFileChooserWhenThereAreManyWatchdogsSimultaneously() + { + await Page.SetContentAsync(""); + var (fileChooser1, fileChooser2, _) = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.FileChooser), + Page.WaitForEventAsync(PageEvent.FileChooser), + Page.EvalOnSelectorAsync("input", "input => input.click()") + ); + Assert.That(fileChooser2, Is.EqualTo(fileChooser1)); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should accept single file")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptSingleFile() + { + await Page.SetContentAsync(""); + var fileChooser = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.FileChooser), + Page.ClickAsync("input") + ); + + Assert.That(fileChooser.Page, Is.SameAs(Page)); + Assert.That(fileChooser.Element, Is.Not.Null); + await fileChooser.SetFilesAsync(TestConstants.FileToUpload); + Assert.That(await Page.EvalOnSelectorAsync("input", "input => input.files.length"), Is.EqualTo(1)); + Assert.That(await Page.EvalOnSelectorAsync("input", "input => input.files[0].name"), Is.EqualTo("file-to-upload.txt")); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should detect mime type")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDetectMimeType() + { + var files = new List<(string name, string mime, byte[] content)>(); + + Server.SetRoute("/upload", context => + { + files.AddRange(context.Request.Form.Files.Select(f => + { + using var ms = new MemoryStream(); + f.CopyTo(ms); + return (f.FileName, f.ContentType, ms.ToArray()); + })); + return Task.CompletedTask; + }); + + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.SetContentAsync(@" +
+ + + +
+ "); + + await (await Page.QuerySelectorAsync("input[name=file1]")).SetInputFilesAsync(TestUtils.GetWebServerFile("file-to-upload.txt")); + await (await Page.QuerySelectorAsync("input[name=file2]")).SetInputFilesAsync(TestUtils.GetWebServerFile("pptr.png")); + + await TaskUtils.WhenAll( + Page.ClickAsync("input[type=submit]"), + Server.WaitForRequest("/upload") + ); + + Assert.That(files[0].name, Is.EqualTo("file-to-upload.txt")); + Assert.That(files[0].mime, Is.EqualTo("text/plain")); + Assert.That(files[0].content, Is.EqualTo(File.ReadAllBytes(TestUtils.GetWebServerFile("file-to-upload.txt")))); + + Assert.That(files[1].name, Is.EqualTo("pptr.png")); + Assert.That(files[1].mime, Is.EqualTo("image/png")); + Assert.That(files[1].content, Is.EqualTo(File.ReadAllBytes(TestUtils.GetWebServerFile("pptr.png")))); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should be able to read selected file")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToReadSelectedFile() + { + await Page.SetContentAsync(""); + _ = Page.WaitForEventAsync(PageEvent.FileChooser) + .ContinueWith(task => task.Result.SetFilesAsync(TestConstants.FileToUpload)); + Assert.That(await Page.EvalOnSelectorAsync("input", @"async picker => { + picker.click(); + await new Promise(x => picker.oninput = x); + const reader = new FileReader(); + const promise = new Promise(fulfill => reader.onload = fulfill); + reader.readAsText(picker.files[0]); + return promise.then(() => reader.result); + }"), Is.EqualTo("contents of the file")); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should be able to reset selected files with empty file list")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldBeAbleToResetSelectedFilesWithEmptyFileList() + { + await Page.SetContentAsync(""); + _ = Page.WaitForEventAsync(PageEvent.FileChooser) + .ContinueWith(task => task.Result.SetFilesAsync(TestConstants.FileToUpload)); + Assert.That(await Page.EvalOnSelectorAsync("input", @"async picker => { + picker.click(); + await new Promise(x => picker.oninput = x); + return picker.files.length; + }"), Is.EqualTo(1)); + _ = Page.WaitForEventAsync(PageEvent.FileChooser) + .ContinueWith(task => task.Result.Element.SetInputFilesAsync(new string[] { })); + Assert.That(await Page.EvalOnSelectorAsync("input", @"async picker => { + picker.click(); + await new Promise(x => picker.oninput = x); + return picker.files.length; + }"), Is.EqualTo(0)); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should not accept multiple files for single-file input")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldNotAcceptMultipleFilesForSingleFileInput() + { + await Page.SetContentAsync(""); + var fileChooser = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.FileChooser), + Page.ClickAsync("input") + ); + Assert.ThrowsAsync(() => fileChooser.SetFilesAsync(new string[] + { + TestUtils.GetWebServerFile(TestConstants.FileToUpload), + TestUtils.GetWebServerFile("pptr.png"), + })); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should emit input and change events")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldEmitInputAndChangeEvents() + { + var events = new List(); + await Page.ExposeFunctionAsync("eventHandled", (string e) => events.Add(e)); + + await Page.SetContentAsync(@" + + + "); + + await (await Page.QuerySelectorAsync("input")).SetInputFilesAsync(TestUtils.GetWebServerFile("file-to-upload.txt")); + Assert.That(events.Count, Is.EqualTo(2)); + Assert.That(events[0], Is.EqualTo("input")); + Assert.That(events[1], Is.EqualTo("change")); + } + + [PlaywrightTest("page-set-input-files.spec.ts", "should work for single file pick")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForSingleFilePick() + { + await Page.SetContentAsync(""); + var waitTask = Page.WaitForEventAsync(PageEvent.FileChooser); + + var fileChooser = await TaskUtils.WhenAll( + waitTask, + Page.ClickAsync("input") + ); + Assert.That(fileChooser.IsMultiple, Is.False); + } + + [PlaywrightTest("page-set-input-files.spec.ts", @"should work for ""multiple""")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForMultiple() + { + await Page.SetContentAsync(""); + var fileChooser = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.FileChooser), + Page.ClickAsync("input") + ); + Assert.That(fileChooser.IsMultiple, Is.True); + } + + [PlaywrightTest("page-set-input-files.spec.ts", @"should work for ""webkitdirectory""")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForWebkitdirectory() + { + await Page.SetContentAsync(""); + var fileChooser = await TaskUtils.WhenAll( + Page.WaitForEventAsync(PageEvent.FileChooser), + Page.ClickAsync("input") + ); + Assert.That(fileChooser.IsMultiple, Is.True); + } + } +} diff --git a/src/Playwright.Tests/PageWaitForFunctionTests.cs b/src/PlaywrightSharp.Tests/PageWaitForFunctionTests.cs similarity index 70% rename from src/Playwright.Tests/PageWaitForFunctionTests.cs rename to src/PlaywrightSharp.Tests/PageWaitForFunctionTests.cs index 840db07109..baaad2798c 100644 --- a/src/Playwright.Tests/PageWaitForFunctionTests.cs +++ b/src/PlaywrightSharp.Tests/PageWaitForFunctionTests.cs @@ -1,271 +1,264 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageWaitForFunctionTests : PlaywrightSharpPageBaseTest - { - /// - public PageWaitForFunctionTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldTimeout() - { - var startTime = DateTime.Now; - int timeout = 42; - await Page.WaitForTimeoutAsync(timeout); - Assert.True((DateTime.Now - startTime).TotalMilliseconds > timeout / 2); - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should accept a string")] - [Fact(Skip = "We don't this test")] - public void ShouldAcceptAString() - { - } - - [PlaywrightTest("page-wait-for-function.spec.tsPageWaitForFunctionTests", "should work when resolved right before execution context disposal")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWhenResolvedRightBeforeExecutionContextDisposal() - { - await Page.AddInitScriptAsync("() => window.__RELOADED = true"); - await Page.WaitForFunctionAsync(@"() => - { - if (!window.__RELOADED) - window.location.reload(); - return true; - }"); - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should poll on interval")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldPollOnInterval() - { - int polling = 100; - var timeDelta = await Page.WaitForFunctionAsync(@"() => { - if (!window.__startTime) { - window.__startTime = Date.now(); - return false; - } - return Date.now() - window.__startTime; - }", pollingInterval: polling); - int value = (await timeDelta.JsonValueAsync()); - - Assert.True(value >= polling); - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should avoid side effects after timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAvoidSideEffectsAfterTimeout() - { - int counter = 0; - Page.Console += (_, _) => ++counter; - - var exception = await Assert.ThrowsAnyAsync(() => Page.WaitForFunctionAsync( - @"() => { - window.counter = (window.counter || 0) + 1; - console.log(window.counter); - }", - pollingInterval: 1, - timeout: 1000)); - - int savedCounter = counter; - await Page.WaitForTimeoutAsync(2000); - - Assert.Contains("Timeout 1000ms exceeded", exception.Message); - Assert.Equal(savedCounter, counter); - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should throw on polling:mutation")] - [Fact(Skip = "We don't need to test this")] - public void ShouldThrowOnPollingMutation() - { - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should poll on raf")] - [Fact(Skip = "We don't support raf")] - public void ShouldPollOnRaf() - { - /* - var watchdog = Page.WaitForFunctionAsync( - "() => window.__FOO === 'hit'", - polling: Polling.Raf); - await Page.EvaluateAsync("window.__FOO = 'hit'"); - await watchdog; - */ - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should fail with predicate throwing on first call")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWithPredicateThrowingOnFirstCall() - { - var exception = await Assert.ThrowsAnyAsync(() => Page.WaitForFunctionAsync("() => { throw new Error('oh my'); }")); - Assert.Contains("oh my", exception.Message); - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should fail with predicate throwing sometimes")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWithPredicateThrowingSometimes() - { - var exception = await Assert.ThrowsAnyAsync(() => Page.WaitForFunctionAsync(@"() => { - window.counter = (window.counter || 0) + 1; - if (window.counter === 3) - throw new Error('Bad counter!'); - return window.counter === 5 ? 'result' : false; - }")); - Assert.Contains("Bad counter!", exception.Message); - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should fail with ReferenceError on wrong page")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldFailWithReferenceErrorOnWrongPage() - { - var exception = await Assert.ThrowsAnyAsync(() => Page.WaitForFunctionAsync("() => globalVar === 123")); - Assert.Contains("globalVar", exception.Message); - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should work with strict CSP policy")] - [Fact(Skip = "We don't support raf")] - public void ShouldWorkWithStrictCSPPolicy() - { - /* - Server.SetCSP("/empty.html", "script-src " + TestConstants.ServerUrl); - await Page.GoToAsync(TestConstants.EmptyPage); - await TaskUtils.WhenAll( - Page.WaitForFunctionAsync( - "() => window.__FOO === 'hit'", - polling: Polling.Raf), - Page.EvaluateAsync("window.__FOO = 'hit'")); - */ - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should throw on bad polling value")] - [Fact(Skip = "We don't this test")] - public void ShouldThrowOnBadPollingValue() - { - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should throw negative polling interval")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldThrowNegativePollingInterval() - { - var exception = await Assert.ThrowsAsync(() - => Page.WaitForFunctionAsync("() => !!document.body", pollingInterval: -10)); - - Assert.Contains("Cannot poll with non-positive interval", exception.Message); - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should return the success value as a JSHandle")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnTheSuccessValueAsAJSHandle() - => Assert.Equal(5, await (await Page.WaitForFunctionAsync("() => 5")).JsonValueAsync()); - - [PlaywrightTest("page-wait-for-function.spec.ts", "should return the window as a success value")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldReturnTheWindowAsASuccessValue() - => Assert.NotNull(await Page.WaitForFunctionAsync("() => window")); - - [PlaywrightTest("page-wait-for-function.spec.ts", "should accept ElementHandle arguments")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldAcceptElementHandleArguments() - { - await Page.SetContentAsync("
"); - var div = await Page.QuerySelectorAsync("div"); - bool resolved = false; - var waitForFunction = Page.WaitForFunctionAsync("element => !element.parentElement", div) - .ContinueWith(_ => resolved = true); - Assert.False(resolved); - await Page.EvaluateAsync("element => element.remove()", div); - await waitForFunction; - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should respect timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRespectTimeout() - { - var exception = await Assert.ThrowsAsync(() - => Page.WaitForFunctionAsync("false", timeout: 10)); - - Assert.Contains("Timeout 10ms exceeded", exception.Message); - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should respect default timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRespectDefaultTimeout() - { - Page.DefaultTimeout = 1; - var exception = await Assert.ThrowsAsync(() - => Page.WaitForFunctionAsync("false")); - - Assert.Contains("Timeout 1ms exceeded", exception.Message); - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should disable timeout when its set to 0")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldDisableTimeoutWhenItsSetTo0() - { - var watchdog = Page.WaitForFunctionAsync( - @"() => { - window.__counter = (window.__counter || 0) + 1; - return window.__injected; - }", - pollingInterval: 10, - timeout: 0); - await Page.WaitForFunctionAsync("() => window.__counter > 10"); - await Page.EvaluateAsync("window.__injected = true"); - await watchdog; - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should survive cross-process navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSurviveCrossProcessNavigation() - { - bool fooFound = false; - var waitForFunction = Page.WaitForFunctionAsync("window.__FOO === 1") - .ContinueWith(_ => fooFound = true); - await Page.GoToAsync(TestConstants.EmptyPage); - Assert.False(fooFound); - await Page.ReloadAsync(); - Assert.False(fooFound); - await Page.GoToAsync(TestConstants.CrossProcessUrl + "/grid.html"); - Assert.False(fooFound); - await Page.EvaluateAsync("window.__FOO = 1"); - await waitForFunction; - Assert.True(fooFound); - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should survive navigations")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldSurviveNavigations() - { - var watchdog = Page.WaitForFunctionAsync("() => window.__done"); - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.GoToAsync(TestConstants.ServerUrl + "/consolelog.html"); - await Page.EvaluateAsync("() => window.__done = true"); - await watchdog; - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should work with multiline body")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithMultilineBody() - { - var result = await Page.WaitForFunctionAsync(@" - (() => true)() - "); - - Assert.True(await result.JsonValueAsync()); - } - - [PlaywrightTest("page-wait-for-function.spec.ts", "should wait for predicate with arguments")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public Task ShouldWaitForPredicateWithArguments() - => Page.WaitForFunctionAsync(@"({arg1, arg2}) => arg1 + arg2 === 3", new { arg1 = 1, arg2 = 2 }); - } -} +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + public class PageWaitForFunctionTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-wait-for-function.spec.ts", "should timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldTimeout() + { + var startTime = DateTime.Now; + int timeout = 42; + await Page.WaitForTimeoutAsync(timeout); + Assert.That((DateTime.Now - startTime).TotalMilliseconds > timeout / 2, Is.True); + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should accept a string")] + [Test, Ignore("We don't this test")] + public void ShouldAcceptAString() + { + } + + [PlaywrightTest("page-wait-for-function.spec.tsPageWaitForFunctionTests", "should work when resolved right before execution context disposal")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWhenResolvedRightBeforeExecutionContextDisposal() + { + await Page.AddInitScriptAsync("() => window.__RELOADED = true"); + await Page.WaitForFunctionAsync(@"() => + { + if (!window.__RELOADED) + window.location.reload(); + return true; + }"); + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should poll on interval")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldPollOnInterval() + { + int polling = 100; + var timeDelta = await Page.WaitForFunctionAsync(@"() => { + if (!window.__startTime) { + window.__startTime = Date.now(); + return false; + } + return Date.now() - window.__startTime; + }", pollingInterval: polling); + int value = (await timeDelta.JsonValueAsync()); + + Assert.That(value >= polling, Is.True); + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should avoid side effects after timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAvoidSideEffectsAfterTimeout() + { + int counter = 0; + Page.Console += (_, _) => ++counter; + + var exception = Assert.CatchAsync(() => Page.WaitForFunctionAsync( + @"() => { + window.counter = (window.counter || 0) + 1; + console.log(window.counter); + }", + pollingInterval: 1, + timeout: 1000)); + + int savedCounter = counter; + await Page.WaitForTimeoutAsync(2000); + + Assert.That(exception.Message, Does.Contain("Timeout 1000ms exceeded")); + Assert.That(counter, Is.EqualTo(savedCounter)); + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should throw on polling:mutation")] + [Test, Ignore("We don't need to test this")] + public void ShouldThrowOnPollingMutation() + { + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should poll on raf")] + [Test, Ignore("We don't support raf")] + public void ShouldPollOnRaf() + { + /* + var watchdog = Page.WaitForFunctionAsync( + "() => window.__FOO === 'hit'", + polling: Polling.Raf); + await Page.EvaluateAsync("window.__FOO = 'hit'"); + await watchdog; + */ + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should fail with predicate throwing on first call")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWithPredicateThrowingOnFirstCall() + { + var exception = Assert.CatchAsync(() => Page.WaitForFunctionAsync("() => { throw new Error('oh my'); }")); + Assert.That(exception.Message, Does.Contain("oh my")); + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should fail with predicate throwing sometimes")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWithPredicateThrowingSometimes() + { + var exception = Assert.CatchAsync(() => Page.WaitForFunctionAsync(@"() => { + window.counter = (window.counter || 0) + 1; + if (window.counter === 3) + throw new Error('Bad counter!'); + return window.counter === 5 ? 'result' : false; + }")); + Assert.That(exception.Message, Does.Contain("Bad counter!")); + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should fail with ReferenceError on wrong page")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldFailWithReferenceErrorOnWrongPage() + { + var exception = Assert.CatchAsync(() => Page.WaitForFunctionAsync("() => globalVar === 123")); + Assert.That(exception.Message, Does.Contain("globalVar")); + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should work with strict CSP policy")] + [Test, Ignore("We don't support raf")] + public void ShouldWorkWithStrictCSPPolicy() + { + /* + Server.SetCSP("/empty.html", "script-src " + TestConstants.ServerUrl); + await Page.GoToAsync(TestConstants.EmptyPage); + await TaskUtils.WhenAll( + Page.WaitForFunctionAsync( + "() => window.__FOO === 'hit'", + polling: Polling.Raf), + Page.EvaluateAsync("window.__FOO = 'hit'")); + */ + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should throw on bad polling value")] + [Test, Ignore("We don't this test")] + public void ShouldThrowOnBadPollingValue() + { + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should throw negative polling interval")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldThrowNegativePollingInterval() + { + var exception = Assert.ThrowsAsync(() + => Page.WaitForFunctionAsync("() => !!document.body", pollingInterval: -10)); + + Assert.That(exception.Message, Does.Contain("Cannot poll with non-positive interval")); + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should return the success value as a JSHandle")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnTheSuccessValueAsAJSHandle() + => Assert.That(await (await Page.WaitForFunctionAsync("() => 5")).JsonValueAsync(), Is.EqualTo(5)); + + [PlaywrightTest("page-wait-for-function.spec.ts", "should return the window as a success value")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldReturnTheWindowAsASuccessValue() + => Assert.That(await Page.WaitForFunctionAsync("() => window"), Is.Not.Null); + + [PlaywrightTest("page-wait-for-function.spec.ts", "should accept ElementHandle arguments")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldAcceptElementHandleArguments() + { + await Page.SetContentAsync("
"); + var div = await Page.QuerySelectorAsync("div"); + bool resolved = false; + var waitForFunction = Page.WaitForFunctionAsync("element => !element.parentElement", div) + .ContinueWith(_ => resolved = true); + Assert.That(resolved, Is.False); + await Page.EvaluateAsync("element => element.remove()", div); + await waitForFunction; + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should respect timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRespectTimeout() + { + var exception = Assert.ThrowsAsync(() + => Page.WaitForFunctionAsync("false", timeout: 10)); + + Assert.That(exception.Message, Does.Contain("Timeout 10ms exceeded")); + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should respect default timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRespectDefaultTimeout() + { + Page.DefaultTimeout = 1; + var exception = Assert.ThrowsAsync(() + => Page.WaitForFunctionAsync("false")); + + Assert.That(exception.Message, Does.Contain("Timeout 1ms exceeded")); + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should disable timeout when its set to 0")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldDisableTimeoutWhenItsSetTo0() + { + var watchdog = Page.WaitForFunctionAsync( + @"() => { + window.__counter = (window.__counter || 0) + 1; + return window.__injected; + }", + pollingInterval: 10, + timeout: 0); + await Page.WaitForFunctionAsync("() => window.__counter > 10"); + await Page.EvaluateAsync("window.__injected = true"); + await watchdog; + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should survive cross-process navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSurviveCrossProcessNavigation() + { + bool fooFound = false; + var waitForFunction = Page.WaitForFunctionAsync("window.__FOO === 1") + .ContinueWith(_ => fooFound = true); + await Page.GoToAsync(TestConstants.EmptyPage); + Assert.That(fooFound, Is.False); + await Page.ReloadAsync(); + Assert.That(fooFound, Is.False); + await Page.GoToAsync(TestConstants.CrossProcessUrl + "/grid.html"); + Assert.That(fooFound, Is.False); + await Page.EvaluateAsync("window.__FOO = 1"); + await waitForFunction; + Assert.That(fooFound, Is.True); + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should survive navigations")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldSurviveNavigations() + { + var watchdog = Page.WaitForFunctionAsync("() => window.__done"); + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.GoToAsync(TestConstants.ServerUrl + "/consolelog.html"); + await Page.EvaluateAsync("() => window.__done = true"); + await watchdog; + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should work with multiline body")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkWithMultilineBody() + { + var result = await Page.WaitForFunctionAsync(@" + (() => true)() + "); + + Assert.That(await result.JsonValueAsync(), Is.True); + } + + [PlaywrightTest("page-wait-for-function.spec.ts", "should wait for predicate with arguments")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public Task ShouldWaitForPredicateWithArguments() + => Page.WaitForFunctionAsync(@"({arg1, arg2}) => arg1 + arg2 === 3", new { arg1 = 1, arg2 = 2 }); + } +} diff --git a/src/Playwright.Tests/PageWaitForLoadStateTests.cs b/src/PlaywrightSharp.Tests/PageWaitForLoadStateTests.cs similarity index 79% rename from src/Playwright.Tests/PageWaitForLoadStateTests.cs rename to src/PlaywrightSharp.Tests/PageWaitForLoadStateTests.cs index 5a55d36592..32e5169cb9 100644 --- a/src/Playwright.Tests/PageWaitForLoadStateTests.cs +++ b/src/PlaywrightSharp.Tests/PageWaitForLoadStateTests.cs @@ -1,145 +1,138 @@ -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.Attributes; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - ///page-wait-for-load-state.ts - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageWaitForLoadStateTests : PlaywrightSharpPageBaseTest - { - /// - public PageWaitForLoadStateTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-wait-for-load-state.ts", "should pick up ongoing navigation")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldPickUpOngoingNavigation() - { - var responseTask = new TaskCompletionSource(); - var waitForRequestTask = Server.WaitForRequest("/one-style.css"); - - Server.SetRoute("/one-style.css", async (ctx) => - { - if (await responseTask.Task) - { - ctx.Response.StatusCode = 404; - await ctx.Response.WriteAsync("File not found"); - } - }); - - var navigationTask = Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); - await waitForRequestTask; - var waitLoadTask = Page.WaitForLoadStateAsync(); - responseTask.TrySetResult(true); - await waitLoadTask; - await navigationTask; - } - - [PlaywrightTest("page-wait-for-load-state.ts", "should respect timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRespectTimeout() - { - Server.SetRoute("/one-style.css", _ => Task.Delay(Timeout.Infinite)); - await Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html", WaitUntilState.DOMContentLoaded); - var exception = await Assert.ThrowsAnyAsync(() => Page.WaitForLoadStateAsync(LoadState.Load, 1)); - Assert.Contains("Timeout 1ms exceeded", exception.Message); - } - - [PlaywrightTest("page-wait-for-load-state.ts", "should resolve immediately if loaded")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldResolveImmediatelyIfLoaded() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); - await Page.WaitForLoadStateAsync(); - } - - [PlaywrightTest("page-wait-for-load-state.ts", "should throw for bad state")] - [Fact(Skip = "We don't need this test")] - public void ShouldTthrowForBadState() - { - } - - [PlaywrightTest("page-wait-for-load-state.ts", "should resolve immediately if load state matches")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldResolveImmediatelyIfLoadStateMatches() - { - var responseTask = new TaskCompletionSource(); - var waitForRequestTask = Server.WaitForRequest("/one-style.css"); - - Server.SetRoute("/one-style.css", async (ctx) => - { - if (await responseTask.Task) - { - ctx.Response.StatusCode = 404; - await ctx.Response.WriteAsync("File not found"); - } - }); - - var navigationTask = Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); - await waitForRequestTask; - await Page.WaitForLoadStateAsync(LoadState.DOMContentLoaded); - responseTask.TrySetResult(true); - await navigationTask; - } - - [PlaywrightTest("page-wait-for-load-state.ts", "should work with pages that have loaded before being connected to")] - [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] - public async Task ShouldWorkWithPagesThatHaveLoadedBeforeBeingConnectedTo() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.EvaluateAsync(@"async () => { - const child = window.open(document.location.href); - while (child.document.readyState !== 'complete' || child.document.location.href === 'about:blank') - await new Promise(f => setTimeout(f, 100)); - }"); - var pages = Context.Pages; - Assert.Equal(2, pages.Count); - - // order is not guaranteed - var mainPage = pages.FirstOrDefault(p => ReferenceEquals(Page, p)); - var connectedPage = pages.Single(p => !ReferenceEquals(Page, p)); - - Assert.NotNull(mainPage); - Assert.Equal(TestConstants.EmptyPage, mainPage.Url); - - Assert.Equal(TestConstants.EmptyPage, connectedPage.Url); - await connectedPage.WaitForLoadStateAsync(); - Assert.Equal(TestConstants.EmptyPage, connectedPage.Url); - } - - [PlaywrightTest("page-wait-for-load-state.spec.ts", "should work for frame")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkForFrame() - { - await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); - var frame = Page.Frames.ElementAt(1); - - TaskCompletionSource requestTask = new TaskCompletionSource(); - TaskCompletionSource routeReachedTask = new TaskCompletionSource(); - await Page.RouteAsync(TestConstants.ServerUrl + "/one-style.css", async (route) => - { - routeReachedTask.TrySetResult(true); - await requestTask.Task; - await route.ResumeAsync(); - }); - - await frame.GoToAsync(TestConstants.ServerUrl + "/one-style.html", WaitUntilState.DOMContentLoaded); - - await routeReachedTask.Task; - var loadTask = frame.WaitForLoadStateAsync(); - await Page.EvaluateAsync("1"); - Assert.False(loadTask.IsCompleted); - requestTask.TrySetResult(true); - await loadTask; - } - } -} +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using NUnit.Framework; +using PlaywrightSharp.Nunit; +using PlaywrightSharp.Tests.Attributes; +using PlaywrightSharp.Tests.BaseTests; + +namespace PlaywrightSharp.Tests +{ + ///page-wait-for-load-state.ts + public class PageWaitForLoadStateTests : PlaywrightSharpPageBaseTest + { + [PlaywrightTest("page-wait-for-load-state.ts", "should pick up ongoing navigation")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldPickUpOngoingNavigation() + { + var responseTask = new TaskCompletionSource(); + var waitForRequestTask = Server.WaitForRequest("/one-style.css"); + + Server.SetRoute("/one-style.css", async (ctx) => + { + if (await responseTask.Task) + { + ctx.Response.StatusCode = 404; + await ctx.Response.WriteAsync("File not found"); + } + }); + + var navigationTask = Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); + await waitForRequestTask; + var waitLoadTask = Page.WaitForLoadStateAsync(); + responseTask.TrySetResult(true); + await waitLoadTask; + await navigationTask; + } + + [PlaywrightTest("page-wait-for-load-state.ts", "should respect timeout")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldRespectTimeout() + { + Server.SetRoute("/one-style.css", _ => Task.Delay(Timeout.Infinite)); + await Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html", WaitUntilState.DOMContentLoaded); + var exception = Assert.CatchAsync(() => Page.WaitForLoadStateAsync(LoadState.Load, 1)); + Assert.That(exception.Message, Does.Contain("Timeout 1ms exceeded")); + } + + [PlaywrightTest("page-wait-for-load-state.ts", "should resolve immediately if loaded")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldResolveImmediatelyIfLoaded() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); + await Page.WaitForLoadStateAsync(); + } + + [PlaywrightTest("page-wait-for-load-state.ts", "should throw for bad state")] + [Test, Ignore("We don't need this test")] + public void ShouldTthrowForBadState() + { + } + + [PlaywrightTest("page-wait-for-load-state.ts", "should resolve immediately if load state matches")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldResolveImmediatelyIfLoadStateMatches() + { + var responseTask = new TaskCompletionSource(); + var waitForRequestTask = Server.WaitForRequest("/one-style.css"); + + Server.SetRoute("/one-style.css", async (ctx) => + { + if (await responseTask.Task) + { + ctx.Response.StatusCode = 404; + await ctx.Response.WriteAsync("File not found"); + } + }); + + var navigationTask = Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); + await waitForRequestTask; + await Page.WaitForLoadStateAsync(LoadState.DOMContentLoaded); + responseTask.TrySetResult(true); + await navigationTask; + } + + [PlaywrightTest("page-wait-for-load-state.ts", "should work with pages that have loaded before being connected to")] + [SkipBrowserAndPlatformFact(skipFirefox: true, skipWebkit: true)] + public async Task ShouldWorkWithPagesThatHaveLoadedBeforeBeingConnectedTo() + { + await Page.GoToAsync(TestConstants.EmptyPage); + await Page.EvaluateAsync(@"async () => { + const child = window.open(document.location.href); + while (child.document.readyState !== 'complete' || child.document.location.href === 'about:blank') + await new Promise(f => setTimeout(f, 100)); + }"); + var pages = Context.Pages; + Assert.That(pages.Count, Is.EqualTo(2)); + + // order is not guaranteed + var mainPage = pages.FirstOrDefault(p => ReferenceEquals(Page, p)); + var connectedPage = pages.Single(p => !ReferenceEquals(Page, p)); + + Assert.That(mainPage, Is.Not.Null); + Assert.That(mainPage.Url, Is.EqualTo(TestConstants.EmptyPage)); + + Assert.That(connectedPage.Url, Is.EqualTo(TestConstants.EmptyPage)); + await connectedPage.WaitForLoadStateAsync(); + Assert.That(connectedPage.Url, Is.EqualTo(TestConstants.EmptyPage)); + } + + [PlaywrightTest("page-wait-for-load-state.spec.ts", "should work for frame")] + [Test, Timeout(TestConstants.DefaultTestTimeout)] + public async Task ShouldWorkForFrame() + { + await Page.GoToAsync(TestConstants.ServerUrl + "/frames/one-frame.html"); + var frame = Page.Frames.ElementAt(1); + + TaskCompletionSource requestTask = new TaskCompletionSource(); + TaskCompletionSource routeReachedTask = new TaskCompletionSource(); + await Page.RouteAsync(TestConstants.ServerUrl + "/one-style.css", async (route) => + { + routeReachedTask.TrySetResult(true); + await requestTask.Task; + await route.ResumeAsync(); + }); + + await frame.GoToAsync(TestConstants.ServerUrl + "/one-style.html", WaitUntilState.DOMContentLoaded); + + await routeReachedTask.Task; + var loadTask = frame.WaitForLoadStateAsync(); + await Page.EvaluateAsync("1"); + Assert.That(loadTask.IsCompleted, Is.False); + requestTask.TrySetResult(true); + await loadTask; + } + } +} diff --git a/src/Playwright.Tests/PageWaitForNavigationTests.cs b/src/PlaywrightSharp.Tests/PageWaitForNavigationTests.cs similarity index 69% rename from src/Playwright.Tests/PageWaitForNavigationTests.cs rename to src/PlaywrightSharp.Tests/PageWaitForNavigationTests.cs index 13514ae544..104661ce41 100644 --- a/src/Playwright.Tests/PageWaitForNavigationTests.cs +++ b/src/PlaywrightSharp.Tests/PageWaitForNavigationTests.cs @@ -1,345 +1,340 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.Playwright.Helpers; -using Microsoft.Playwright.Testing.Xunit; -using Microsoft.Playwright.Tests.BaseTests; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Playwright.Tests -{ - [Collection(TestConstants.TestFixtureBrowserCollectionName)] - public class PageWaitForNavigationTests : PlaywrightSharpPageBaseTest - { - /// - public PageWaitForNavigationTests(ITestOutputHelper output) : base(output) - { - } - - [PlaywrightTest("page-wait-for-navigation.spec.ts", "should work")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWork() - { - await Page.GoToAsync(TestConstants.EmptyPage); - var waitForNavigationResult = Page.WaitForNavigationAsync(); - await TaskUtils.WhenAll( - waitForNavigationResult, - Page.EvaluateAsync("url => window.location.href = url", TestConstants.ServerUrl + "/grid.html") - ); - var response = await waitForNavigationResult; - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Contains("grid.html", response.Url); - } - - [PlaywrightTest("page-wait-for-navigation.spec.ts", "should respect timeout")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldRespectTimeout() - { - var waitForNavigationResult = Page.WaitForNavigationAsync("**/frame.html", timeout: 5000); - - await Page.GoToAsync(TestConstants.EmptyPage); - - var exception = await Assert.ThrowsAnyAsync(() => waitForNavigationResult); - - Assert.Contains("Timeout 5000ms exceeded", exception.Message); - Assert.Contains("waiting for navigation to \"**/frame.html\" until \"Load\"", exception.Message); - Assert.Contains($"navigated to \"{TestConstants.EmptyPage}\"", exception.Message); - } - - [PlaywrightTest("page-wait-for-navigation.spec.ts", "should work with both domcontentloaded and load")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithBothDomcontentloadedAndLoad() - { - var responseCompleted = new TaskCompletionSource(); - Server.SetRoute("/one-style.css", _ => responseCompleted.Task); - - var waitForRequestTask = Server.WaitForRequest("/one-style.css"); - var navigationTask = Page.GoToAsync(TestConstants.ServerUrl + "/one-style.html"); - var domContentLoadedTask = Page.WaitForNavigationAsync(WaitUntilState.DOMContentLoaded); - - bool bothFired = false; - var bothFiredTask = TaskUtils.WhenAll( - domContentLoadedTask, - Page.WaitForNavigationAsync(WaitUntilState.Load)).ContinueWith(_ => bothFired = true); - - await waitForRequestTask.WithTimeout(TestConstants.DefaultTaskTimeout); - await domContentLoadedTask.WithTimeout(TestConstants.DefaultTaskTimeout); - Assert.False(bothFired); - responseCompleted.SetResult(true); - await bothFiredTask.WithTimeout(TestConstants.DefaultTaskTimeout); - await navigationTask.WithTimeout(TestConstants.DefaultTaskTimeout); - } - - [PlaywrightTest("page-wait-for-navigation.spec.ts", "should work with clicking on anchor links")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithClickingOnAnchorLinks() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync("foobar"); - var navigationTask = Page.WaitForNavigationAsync(); - await TaskUtils.WhenAll( - navigationTask, - Page.ClickAsync("a") - ); - Assert.Null(await navigationTask); - Assert.Equal(TestConstants.EmptyPage + "#foobar", Page.Url); - } - - [PlaywrightTest("page-wait-for-navigation.spec.ts", "should work with clicking on links which do not commit navigation")] - // [Fact(Timeout = TestConstants.DefaultTestTimeout)] - [Fact(Skip = "Fix me #1058")] - public async Task ShouldWorkWithClickingOnLinksWhichDoNotCommitNavigation() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync($"foobar"); - var navigationTask = Page.WaitForNavigationAsync(); - var exception = await Assert.ThrowsAnyAsync(() => TaskUtils.WhenAll( - navigationTask, - Page.ClickAsync("a") - )); - TestUtils.AssertSSLError(exception.Message); - } - - [PlaywrightTest("page-wait-for-navigation.spec.ts", "should work with history.pushState()")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithHistoryPushState() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync(@" - SPA - - "); - var navigationTask = Page.WaitForNavigationAsync(); - await TaskUtils.WhenAll( - navigationTask, - Page.ClickAsync("a") - ); - Assert.Null(await navigationTask); - Assert.Equal(TestConstants.ServerUrl + "/wow.html", Page.Url); - } - - [PlaywrightTest("page-wait-for-navigation.spec.ts", "should work with history.replaceState()")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithHistoryReplaceState() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync(@" - SPA - - "); - var navigationTask = Page.WaitForNavigationAsync(); - await TaskUtils.WhenAll( - navigationTask, - Page.ClickAsync("a") - ); - Assert.Null(await navigationTask); - Assert.Equal(TestConstants.ServerUrl + "/replaced.html", Page.Url); - } - - [PlaywrightTest("page-wait-for-navigation.spec.ts", "should work with DOM history.back()/history.forward()")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWithDOMHistoryBackAndHistoryForward() - { - await Page.GoToAsync(TestConstants.EmptyPage); - await Page.SetContentAsync(@" - back - forward - - "); - Assert.Equal(TestConstants.ServerUrl + "/second.html", Page.Url); - var navigationTask = Page.WaitForNavigationAsync(); - await TaskUtils.WhenAll( - navigationTask, - Page.ClickAsync("a#back") - ); - Assert.Null(await navigationTask); - Assert.Equal(TestConstants.ServerUrl + "/first.html", Page.Url); - navigationTask = Page.WaitForNavigationAsync(); - await TaskUtils.WhenAll( - navigationTask, - Page.ClickAsync("a#forward") - ); - Assert.Null(await navigationTask); - Assert.Equal(TestConstants.ServerUrl + "/second.html", Page.Url); - } - - [PlaywrightTest("page-wait-for-navigation.spec.ts", "should work when subframe issues window.stop()")] - [Fact(Timeout = TestConstants.DefaultTestTimeout)] - public async Task ShouldWorkWhenSubframeIssuesWindowStop() - { - //This test is slightly different from the one in PW because of .NET Threads (or thanks to .NET Threads) - var framesNavigated = new List