Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .generated.NoMobile.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@
<Project Path="test/Sentry.Tests/Sentry.Tests.csproj" />
<Project Path="test/Sentry.TrimTest/Sentry.TrimTest.csproj" />
<Project Path="test/SingleFileTestApp/SingleFileTestApp.csproj" />
<Project Path="test\Sentry.AspNetCore.Blazor.WebAssembly.Tests\Sentry.AspNetCore.Blazor.WebAssembly.Tests.csproj" />
<Project Path="test/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.csproj" />
<Project Path="test/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.TestApp/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.TestApp.csproj" />
<Project Path="test/Sentry.AspNetCore.Blazor.WebAssembly.Tests/Sentry.AspNetCore.Blazor.WebAssembly.Tests.csproj" />
</Folder>
</Solution>
65 changes: 65 additions & 0 deletions .github/workflows/playwright-blazor-wasm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Blazor WASM Playwright Tests

on:
push:
branches:
- main
- release/*
pull_request:
paths:
- 'src/*'
- 'src/Sentry/**'
- 'src/Sentry.AspNetCore/**'
- 'src/Sentry.AspNetCore.Blazor.WebAssembly/**'
- 'src/Sentry.Extensions.Logging/**'
- 'test/*'
- 'test/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests/**'
- 'test/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.TestApp/**'
- 'test/Sentry.Testing/**'
- 'global.json'
- 'Directory.Build.props'
- 'Directory.Build.targets'
- 'nuget.config'
- '.github/workflows/playwright-blazor-wasm.yml'
workflow_dispatch:

jobs:
playwright:
name: Blazor WASM E2E
runs-on: ubuntu-latest
env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_NOLOGO: 1
steps:
- name: Cancel Previous Runs
if: github.ref_name != 'main' && !startsWith(github.ref_name, 'release/')
uses: styfle/cancel-workflow-action@3155a141048f8f89c06b4cdae32e7853e97536bc # 0.13.0

- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: recursive

- name: Install .NET SDK
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
with:
global-json-file: global.json

- name: Install .NET Workloads
run: dotnet workload restore --temp-dir "${{ runner.temp }}" --skip-sign-check

- name: Build
run: dotnet build test/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests -c Release

- name: Install Playwright Browsers
run: pwsh test/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests/bin/Release/net10.0/playwright.ps1 install chromium --with-deps

- name: Run Playwright Tests
run: dotnet test test/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests -c Release --no-build --logger "trx;LogFileName=results.trx"

- name: Upload Test Results
if: failure()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: playwright-blazor-wasm-results
path: test/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests/TestResults/
4 changes: 3 additions & 1 deletion Sentry.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@
<Project Path="test/Sentry.Tests/Sentry.Tests.csproj" />
<Project Path="test/Sentry.TrimTest/Sentry.TrimTest.csproj" />
<Project Path="test/SingleFileTestApp/SingleFileTestApp.csproj" />
<Project Path="test\Sentry.AspNetCore.Blazor.WebAssembly.Tests\Sentry.AspNetCore.Blazor.WebAssembly.Tests.csproj" />
<Project Path="test/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.csproj" />
<Project Path="test/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.TestApp/Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.TestApp.csproj" />
<Project Path="test/Sentry.AspNetCore.Blazor.WebAssembly.Tests/Sentry.AspNetCore.Blazor.WebAssembly.Tests.csproj" />
</Folder>
</Solution>
2 changes: 2 additions & 0 deletions SentryAspNetCore.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
"src\\Sentry.Serilog\\Sentry.Serilog.csproj",
"src\\Sentry\\Sentry.csproj",
"test\\Sentry.Analyzers.Tests\\Sentry.Analyzers.Tests.csproj",
"test\\Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.TestApp\\Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.TestApp.csproj",
"test\\Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests\\Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.csproj",
"test\\Sentry.AspNetCore.Blazor.WebAssembly.Tests\\Sentry.AspNetCore.Blazor.WebAssembly.Tests.csproj",
"test\\Sentry.AspNetCore.Grpc.Tests\\Sentry.AspNetCore.Grpc.Tests.csproj",
"test\\Sentry.AspNetCore.Tests\\Sentry.AspNetCore.Tests.csproj",
Expand Down
2 changes: 2 additions & 0 deletions SentryNoMobile.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
"src\\Sentry\\Sentry.csproj",
"test\\Sentry.Analyzers.Tests\\Sentry.Analyzers.Tests.csproj",
"test\\Sentry.AspNet.Tests\\Sentry.AspNet.Tests.csproj",
"test\\Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.TestApp\\Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.TestApp.csproj",
"test\\Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests\\Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.csproj",
"test\\Sentry.AspNetCore.Blazor.WebAssembly.Tests\\Sentry.AspNetCore.Blazor.WebAssembly.Tests.csproj",
"test\\Sentry.AspNetCore.Grpc.Tests\\Sentry.AspNetCore.Grpc.Tests.csproj",
"test\\Sentry.AspNetCore.Tests\\Sentry.AspNetCore.Tests.csproj",
Expand Down
1 change: 1 addition & 0 deletions SentryNoSamples.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"test\\Sentry.Analyzers.Tests\\Sentry.Analyzers.Tests.csproj",
"test\\Sentry.Android.AssemblyReader.Tests\\Sentry.Android.AssemblyReader.Tests.csproj",
"test\\Sentry.AspNet.Tests\\Sentry.AspNet.Tests.csproj",
"test\\Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests\\Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.csproj",
"test\\Sentry.AspNetCore.Blazor.WebAssembly.Tests\\Sentry.AspNetCore.Blazor.WebAssembly.Tests.csproj",
"test\\Sentry.AspNetCore.Grpc.Tests\\Sentry.AspNetCore.Grpc.Tests.csproj",
"test\\Sentry.AspNetCore.Tests\\Sentry.AspNetCore.Tests.csproj",
Expand Down
7 changes: 7 additions & 0 deletions scripts/generate-solution-filters-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ groupConfigs:
trimTests:
- "**/Sentry.TrimTest.csproj"
- "**/Sentry.MauiTrimTest.csproj"
playwrightTests:
- "**/*PlaywrightTests*.csproj"
mobileOnly:
- "**/*Android*.csproj"
- "**/*Ios*.csproj"
Expand All @@ -50,6 +52,7 @@ filterConfigs:
- "windowsOnly"
- "artefacts"
- "trimTests"
- "playwrightTests"
patterns:
- "**/*AndroidTestApp.csproj"
- "**/*DeviceTests*.csproj"
Expand All @@ -67,6 +70,7 @@ filterConfigs:
- "artefacts"
- "trimTests"
- "mobileOnly"
- "playwrightTests"
patterns:
- "**/*Android*.csproj"
- "**/*DeviceTests*.csproj"
Expand All @@ -83,6 +87,7 @@ filterConfigs:
groups:
- "artefacts"
- "trimTests"
- "playwrightTests"
patterns:
- "**/*AndroidTestApp.csproj"
- "**/*DeviceTests*.csproj"
Expand All @@ -100,6 +105,7 @@ filterConfigs:
- "macOnly"
- "artefacts"
- "trimTests"
- "playwrightTests"
patterns:
- "**/*AndroidTestApp.csproj"
# AssemblyReader tests are flaky on Windows: https://github.com/getsentry/sentry-dotnet/issues/4091
Expand All @@ -121,6 +127,7 @@ filterConfigs:
- "macOnly"
- "artefacts"
- "trimTests"
- "playwrightTests"
patterns:
- "**/*AndroidTestApp.csproj"
# AssemblyReader tests are flaky on Windows: https://github.com/getsentry/sentry-dotnet/issues/4091
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Shared.MainLayout)" />
</Found>
<NotFound>
<p>Not found</p>
</NotFound>
</Router>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Project>
<!-- Stop inheriting test-specific props from test/Directory.Build.props -->
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Project>
<!-- Stop inheriting test-specific targets from test/Directory.Build.targets -->
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@page "/"

<h1 id="page-title">Home</h1>
<a href="second" id="nav-second">Go to Second</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@page "/second"

<h1 id="page-title">Second Page</h1>
<a href="trigger-capture" id="nav-trigger">Go to Trigger</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@page "/trigger-capture"

<h1 id="page-title">Trigger Capture</h1>
<button id="btn-capture" @onclick="Capture">Capture Message</button>

@code {
private void Capture()
{
SentrySdk.CaptureMessage("playwright-test");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.TestApp;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.UseSentry(options =>
{
// Fake DSN — Playwright intercepts requests before they reach the network
options.Dsn = "https://key@o0.ingest.sentry.io/0";
options.AutoSessionTracking = false;
});

builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

await builder.Build().RunAsync();
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<IsTestProject>false</IsTestProject>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.0" PrivateAssets="all" />
<ProjectReference Include="..\..\src\Sentry.AspNetCore.Blazor.WebAssembly\Sentry.AspNetCore.Blazor.WebAssembly.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@inherits LayoutComponentBase

<main>
@Body
</main>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.TestApp
@using Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.TestApp.Shared
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Playwright Test App</title>
<base href="/" />
</head>

<body>
<div id="app">Loading...</div>
<script src="_framework/blazor.webassembly.js"></script>
</body>

</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;

namespace Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests;

internal sealed class BlazorWasmTestApp : IAsyncDisposable
{
private Process? _process;
private readonly ConcurrentQueue<string> _output = new();

public string BaseUrl { get; private set; } = null!;

public async Task StartAsync()
{
var port = GetFreePort();
BaseUrl = $"http://localhost:{port}";

var projectPath = Path.GetFullPath(
Path.Combine(AppContext.BaseDirectory,
"..", "..", "..", "..",
"Sentry.AspNetCore.Blazor.WebAssembly.PlaywrightTests.TestApp"));

_process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "dotnet",
Arguments = $"run --project \"{projectPath}\" --configuration Release --urls {BaseUrl}",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
}
};
_process.OutputDataReceived += (_, e) => { if (e.Data != null) _output.Enqueue($"[stdout] {e.Data}"); };
_process.ErrorDataReceived += (_, e) => { if (e.Data != null) _output.Enqueue($"[stderr] {e.Data}"); };
_process.Start();
_process.BeginOutputReadLine();
_process.BeginErrorReadLine();

using var http = new HttpClient();
var timeout = TimeSpan.FromSeconds(180);
var sw = Stopwatch.StartNew();
while (sw.Elapsed < timeout)
{
if (_process.HasExited)
{
var logs = string.Join(Environment.NewLine, _output);
throw new InvalidOperationException(
$"Blazor WASM test app exited with code {_process.ExitCode} before becoming ready. Output:{Environment.NewLine}{logs}");
}

try
{
var response = await http.GetAsync(BaseUrl);
if (response.IsSuccessStatusCode)
{
return;
}
}
catch
{
// Server not ready yet
}
await Task.Delay(500);
}

var timeoutLogs = string.Join(Environment.NewLine, _output);
throw new TimeoutException(
$"Blazor WASM test app did not start within {(int)timeout.TotalSeconds}s at {BaseUrl}. Output:{Environment.NewLine}{timeoutLogs}");
}

private static int GetFreePort()
{
using var listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
listener.Stop();
return port;
}

public async ValueTask DisposeAsync()
{
if (_process is { HasExited: false })
{
_process.Kill(entireProcessTree: true);
await _process.WaitForExitAsync();
}
_process?.Dispose();
}
}
Loading
Loading