From f417c4d41012530dbf06433a671b91e863882298 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Mon, 30 Mar 2026 17:15:01 +0200 Subject: [PATCH 1/2] Unquarantine WebWorker E2E tests and add diagnostics Remove [QuarantinedTest] from 4 WebWorker template E2E tests that were quarantined by #66035. The tests pass locally on current HEAD. Add LogBuildDiagnostics() to capture: - Processed HTML script tags (fingerprint resolution) - Endpoints manifest routes for blazor.webassembly - Source index.html placeholder state This will help diagnose any CI-only failures where the fingerprint placeholder resolves to empty, causing blazor.webassembly.js 404s. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../WebWorkerTemplateE2ETest.cs | 81 ++++++++++++++++++- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/src/ProjectTemplates/test/Templates.Blazor.Tests/WebWorkerTemplateE2ETest.cs b/src/ProjectTemplates/test/Templates.Blazor.Tests/WebWorkerTemplateE2ETest.cs index 6612066e0f25..7335d1070965 100644 --- a/src/ProjectTemplates/test/Templates.Blazor.Tests/WebWorkerTemplateE2ETest.cs +++ b/src/ProjectTemplates/test/Templates.Blazor.Tests/WebWorkerTemplateE2ETest.cs @@ -42,7 +42,6 @@ protected override async Task InitializeCoreAsync(TestContext context) [Theory] [InlineData(BrowserKind.Chromium)] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/66035")] public async Task WebWorkerTemplate_CanInvokeMethods(BrowserKind browserKind) { await using var testRun = await SetupWorkerLibAndBuild(_sharedHostProject); @@ -58,7 +57,6 @@ public async Task WebWorkerTemplate_CanInvokeMethods(BrowserKind browserKind) [Theory] [InlineData(BrowserKind.Chromium)] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/66035")] public async Task WebWorkerTemplate_HandlesErrors(BrowserKind browserKind) { await using var testRun = await SetupWorkerLibAndBuild(_sharedHostProject); @@ -74,7 +72,6 @@ public async Task WebWorkerTemplate_HandlesErrors(BrowserKind browserKind) [Theory] [InlineData(BrowserKind.Chromium)] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/66035")] public async Task WebWorkerTemplate_CanDisposeWorker(BrowserKind browserKind) { await using var testRun = await SetupWorkerLibAndBuild(_sharedHostProject); @@ -90,7 +87,6 @@ public async Task WebWorkerTemplate_CanDisposeWorker(BrowserKind browserKind) [Theory] [InlineData(BrowserKind.Chromium)] - [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/66035")] public async Task WebWorkerTemplate_CanInvokeMethodsAfterPublish(BrowserKind browserKind) { await using var testRun = await SetupWorkerLibAndPublish(_sharedHostProject); @@ -117,6 +113,8 @@ private async Task SetupWorkerLibAndPublish(Project hostProjec await AddWorkerLibReferenceAsync(hostProject); await hostProject.RunDotNetPublishAsync(noRestore: false); + LogBuildDiagnostics(hostProject, "publish"); + return new WorkerLibTestRun(workerLibDir, hostProject, Output); } @@ -135,6 +133,8 @@ private async Task SetupWorkerLibAndBuild(Project hostProject) await AddWorkerLibReferenceAsync(hostProject); await hostProject.RunDotNetBuildAsync(); + LogBuildDiagnostics(hostProject, "build"); + return new WorkerLibTestRun(workerLibDir, hostProject, Output); } @@ -235,6 +235,79 @@ private void CopyTestAssets(Project hostProject) File.Copy(workerMethodsSource, Path.Combine(hostProject.TemplateOutputDir, "TestWorkerMethods.cs"), overwrite: true); } + private void LogBuildDiagnostics(Project hostProject, string buildKind) + { + // Log the processed index.html to check if fingerprints resolved correctly. + // The #[.{fingerprint}] placeholder should be replaced with an actual hash. + // If it resolves to empty, the script tag will reference the unfingerprinted + // 'blazor.webassembly.js' which returns 404 from the dev server. + var processedHtmlFiles = Directory.GetFiles( + Path.Combine(hostProject.TemplateOutputDir, "obj"), + "*.html", + SearchOption.AllDirectories); + + Output.WriteLine($"[Diagnostics:{buildKind}] Processed HTML files found: {processedHtmlFiles.Length}"); + foreach (var htmlFile in processedHtmlFiles) + { + var html = File.ReadAllText(htmlFile); + var scriptLines = html.Split('\n') + .Where(l => l.Contains("blazor.webassembly", StringComparison.OrdinalIgnoreCase)) + .Select(l => l.Trim()); + Output.WriteLine($"[Diagnostics:{buildKind}] {htmlFile}"); + foreach (var line in scriptLines) + { + Output.WriteLine($"[Diagnostics:{buildKind}] {line}"); + } + } + + // Log endpoints manifest routes for blazor.webassembly to verify route registration. + var endpointsManifest = Path.Combine( + hostProject.TemplateOutputDir, + "bin", "Debug", "net11.0", + $"{hostProject.ProjectName}.staticwebassets.endpoints.json"); + if (File.Exists(endpointsManifest)) + { + try + { + using var doc = System.Text.Json.JsonDocument.Parse(File.ReadAllText(endpointsManifest)); + var endpoints = doc.RootElement.GetProperty("Endpoints"); + Output.WriteLine($"[Diagnostics:{buildKind}] Endpoints manifest blazor.webassembly routes:"); + foreach (var endpoint in endpoints.EnumerateArray()) + { + var route = endpoint.GetProperty("Route").GetString(); + if (route?.Contains("blazor.webassembly", StringComparison.OrdinalIgnoreCase) == true) + { + var assetFile = endpoint.GetProperty("AssetFile").GetString(); + Output.WriteLine($"[Diagnostics:{buildKind}] Route: {route} -> AssetFile: {assetFile}"); + } + } + } + catch (Exception ex) + { + Output.WriteLine($"[Diagnostics:{buildKind}] Failed to parse endpoints manifest: {ex.Message}"); + } + } + else + { + Output.WriteLine($"[Diagnostics:{buildKind}] WARNING: Endpoints manifest not found at {endpointsManifest}"); + } + + // Log the original index.html to check the raw source state. + var sourceHtml = Path.Combine(hostProject.TemplateOutputDir, "wwwroot", "index.html"); + if (File.Exists(sourceHtml)) + { + var html = File.ReadAllText(sourceHtml); + var scriptLines = html.Split('\n') + .Where(l => l.Contains("blazor.webassembly", StringComparison.OrdinalIgnoreCase)) + .Select(l => l.Trim()); + Output.WriteLine($"[Diagnostics:{buildKind}] Source wwwroot/index.html blazor.webassembly references:"); + foreach (var line in scriptLines) + { + Output.WriteLine($"[Diagnostics:{buildKind}] {line}"); + } + } + } + private async Task TestWebWorkerInteraction(BrowserKind browserKind, string baseUri, string clientRoute = null) { if (!BrowserManager.IsAvailable(browserKind)) From 7296a5bdac7a890610f30c38beb731ba1e5ab8d8 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Mon, 30 Mar 2026 17:33:18 +0200 Subject: [PATCH 2/2] Address review feedback on LogBuildDiagnostics - Use TemplateBuildDir/TemplatePublishDir instead of hardcoded path - Guard against missing obj directory - Only log HTML files that have matching blazor.webassembly lines - Use File.ReadLines instead of File.ReadAllText - Log full exception (ex.ToString()) instead of just ex.Message Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../WebWorkerTemplateE2ETest.cs | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/ProjectTemplates/test/Templates.Blazor.Tests/WebWorkerTemplateE2ETest.cs b/src/ProjectTemplates/test/Templates.Blazor.Tests/WebWorkerTemplateE2ETest.cs index 7335d1070965..bd0f5e0c2d42 100644 --- a/src/ProjectTemplates/test/Templates.Blazor.Tests/WebWorkerTemplateE2ETest.cs +++ b/src/ProjectTemplates/test/Templates.Blazor.Tests/WebWorkerTemplateE2ETest.cs @@ -241,29 +241,38 @@ private void LogBuildDiagnostics(Project hostProject, string buildKind) // The #[.{fingerprint}] placeholder should be replaced with an actual hash. // If it resolves to empty, the script tag will reference the unfingerprinted // 'blazor.webassembly.js' which returns 404 from the dev server. - var processedHtmlFiles = Directory.GetFiles( - Path.Combine(hostProject.TemplateOutputDir, "obj"), - "*.html", - SearchOption.AllDirectories); + var objDirectory = Path.Combine(hostProject.TemplateOutputDir, "obj"); + var processedHtmlFiles = Array.Empty(); + if (!Directory.Exists(objDirectory)) + { + Output.WriteLine($"[Diagnostics:{buildKind}] WARNING: Build obj directory not found at {objDirectory}"); + } + else + { + processedHtmlFiles = Directory.GetFiles(objDirectory, "*.html", SearchOption.AllDirectories); + } Output.WriteLine($"[Diagnostics:{buildKind}] Processed HTML files found: {processedHtmlFiles.Length}"); foreach (var htmlFile in processedHtmlFiles) { - var html = File.ReadAllText(htmlFile); - var scriptLines = html.Split('\n') + var scriptLines = File.ReadLines(htmlFile) .Where(l => l.Contains("blazor.webassembly", StringComparison.OrdinalIgnoreCase)) - .Select(l => l.Trim()); - Output.WriteLine($"[Diagnostics:{buildKind}] {htmlFile}"); - foreach (var line in scriptLines) + .Select(l => l.Trim()) + .ToList(); + if (scriptLines.Count > 0) { - Output.WriteLine($"[Diagnostics:{buildKind}] {line}"); + Output.WriteLine($"[Diagnostics:{buildKind}] {htmlFile}"); + foreach (var line in scriptLines) + { + Output.WriteLine($"[Diagnostics:{buildKind}] {line}"); + } } } // Log endpoints manifest routes for blazor.webassembly to verify route registration. - var endpointsManifest = Path.Combine( - hostProject.TemplateOutputDir, - "bin", "Debug", "net11.0", + // Use TemplateBuildDir for build, TemplatePublishDir for publish to match actual output paths. + var outputDir = buildKind == "publish" ? hostProject.TemplatePublishDir : hostProject.TemplateBuildDir; + var endpointsManifest = Path.Combine(outputDir, $"{hostProject.ProjectName}.staticwebassets.endpoints.json"); if (File.Exists(endpointsManifest)) { @@ -284,7 +293,7 @@ private void LogBuildDiagnostics(Project hostProject, string buildKind) } catch (Exception ex) { - Output.WriteLine($"[Diagnostics:{buildKind}] Failed to parse endpoints manifest: {ex.Message}"); + Output.WriteLine($"[Diagnostics:{buildKind}] Failed to parse endpoints manifest: {ex}"); } } else @@ -296,10 +305,10 @@ private void LogBuildDiagnostics(Project hostProject, string buildKind) var sourceHtml = Path.Combine(hostProject.TemplateOutputDir, "wwwroot", "index.html"); if (File.Exists(sourceHtml)) { - var html = File.ReadAllText(sourceHtml); - var scriptLines = html.Split('\n') + var scriptLines = File.ReadLines(sourceHtml) .Where(l => l.Contains("blazor.webassembly", StringComparison.OrdinalIgnoreCase)) - .Select(l => l.Trim()); + .Select(l => l.Trim()) + .ToList(); Output.WriteLine($"[Diagnostics:{buildKind}] Source wwwroot/index.html blazor.webassembly references:"); foreach (var line in scriptLines) {