Skip to content

Commit c61ff67

Browse files
ilonatommyCopilot
andauthored
Make sure WebRootComponentManager is initialized for dynamic JS roots (#64467)
* Make JS root tests do not interfere with other tests. * Simplest fix. * Feedback - move the initialization to CircuitFactory. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent da2e7e1 commit c61ff67

File tree

7 files changed

+105
-1
lines changed

7 files changed

+105
-1
lines changed

src/Components/Server/src/Circuits/CircuitFactory.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ public async ValueTask<CircuitHost> CreateCircuitHostAsync(
9393
resourceCollection);
9494

9595
circuitActivitySource.Init(new Infrastructure.Server.ComponentsActivityLinkStore(renderer));
96+
renderer.GetOrCreateWebRootComponentManager();
9697

9798
// In Blazor Server we have already restored the app state, so we can get the handlers from DI.
9899
// In Blazor Web the state is provided in the first call to UpdateRootComponents, so we need to
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Components.TestServer.RazorComponents;
5+
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
6+
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
7+
using Microsoft.AspNetCore.Components.E2ETests.ServerRenderingTests;
8+
using Microsoft.AspNetCore.Components.Web;
9+
using Microsoft.AspNetCore.E2ETesting;
10+
using OpenQA.Selenium;
11+
using TestServer;
12+
using Xunit.Abstractions;
13+
14+
namespace Microsoft.AspNetCore.Components.E2ETests.Tests;
15+
16+
// These tests are for Blazor Web implementation
17+
// For Blazor Server and Webassembly, check SaveStateTest.cs
18+
public class StatePersistanceJSRootTest : ServerTestBase<BasicTestAppServerSiteFixture<RazorComponentEndpointsStartup<App>>>
19+
{
20+
public StatePersistanceJSRootTest(
21+
BrowserFixture browserFixture,
22+
BasicTestAppServerSiteFixture<RazorComponentEndpointsStartup<App>> serverFixture,
23+
ITestOutputHelper output)
24+
: base(browserFixture, serverFixture, output)
25+
{
26+
serverFixture.AdditionalArguments.AddRange("--RegisterDynamicJSRootComponent", "true");
27+
}
28+
29+
[Theory]
30+
[InlineData("ServerNonPrerendered")]
31+
[InlineData("WebAssemblyNonPrerendered")]
32+
public void PersistentStateIsSupportedInDynamicJSRoots(string renderMode)
33+
{
34+
Navigate($"subdir/WasmMinimal/dynamic-js-root.html?renderMode={renderMode}");
35+
36+
Browser.Equal("Counter", () => Browser.Exists(By.TagName("h1")).Text);
37+
Browser.Equal("Current count: 0", () => Browser.Exists(By.CssSelector("p[role='status']")).Text);
38+
39+
Browser.Click(By.CssSelector("button.btn-primary"));
40+
Browser.Equal("Current count: 1", () => Browser.Exists(By.CssSelector("p[role='status']")).Text);
41+
}
42+
}

src/Components/test/testassets/Components.TestServer/Program.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ public static async Task Main(string[] args)
2323
["Server authentication"] = (BuildWebHost<ServerAuthenticationStartup>(CreateAdditionalArgs(args)), "/subdir"),
2424
["CORS (WASM)"] = (BuildWebHost<CorsStartup>(CreateAdditionalArgs(args)), "/subdir"),
2525
["Prerendering (Server-side)"] = (BuildWebHost<PrerenderedStartup>(CreateAdditionalArgs(args)), "/prerendered"),
26-
["Razor Component Endpoints"] = (BuildWebHost<RazorComponentEndpointsStartup<Components.TestServer.RazorComponents.App>>(CreateAdditionalArgs(args)), "/subdir"),
26+
["Razor Component Endpoints"] = (BuildWebHost<RazorComponentEndpointsStartup<App>>(CreateAdditionalArgs(args)), "/subdir"),
27+
["Razor Component Endpoints with JS Root Component"] = (BuildWebHost<RazorComponentEndpointsStartup<App>>(CreateAdditionalArgs([.. args, "--RegisterDynamicJSRootComponent", "true"])), "/subdir"),
2728
["Deferred component content (Server-side)"] = (BuildWebHost<DeferredComponentContentStartup>(CreateAdditionalArgs(args)), "/deferred-component-content"),
2829
["Locked navigation (Server-side)"] = (BuildWebHost<LockedNavigationStartup>(CreateAdditionalArgs(args)), "/locked-navigation"),
2930
["Client-side with fallback"] = (BuildWebHost<StartupWithMapFallbackToClientSideBlazor>(CreateAdditionalArgs(args)), "/fallback"),

src/Components/test/testassets/Components.TestServer/RazorComponentEndpointsStartup.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Web;
88
using Components.TestServer.RazorComponents;
99
using Components.TestServer.RazorComponents.Pages.Forms;
10+
using Components.TestServer.RazorComponents.Pages.PersistentState;
1011
using Components.TestServer.Services;
1112
using Microsoft.AspNetCore.Components;
1213
using Microsoft.AspNetCore.Components.Server.Circuits;
@@ -50,6 +51,10 @@ public void ConfigureServices(IServiceCollection services)
5051
options.DisconnectedCircuitMaxRetained = 0;
5152
options.DetailedErrors = true;
5253
}
54+
if (Configuration.GetValue<bool>("RegisterDynamicJSRootComponent"))
55+
{
56+
options.RootComponents.RegisterForJavaScript<TestContentPackage.PersistentComponents.ComponentWithPersistentState>("dynamic-js-root-counter");
57+
}
5358
})
5459
.AddAuthenticationStateSerialization(options =>
5560
{
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
@page "/persistent-state/counter"
2+
3+
<TestContentPackage.PersistentComponents.ComponentWithPersistentState @rendermode="@RenderModeHelper.GetRenderMode(_renderMode)"/>
4+
5+
6+
@code{
7+
[Parameter, SupplyParameterFromQuery(Name = "renderMode")]
8+
public string? RenderModeStr { get; set; }
9+
10+
private RenderModeId _renderMode;
11+
12+
protected override void OnInitialized()
13+
{
14+
if (!string.IsNullOrEmpty(RenderModeStr))
15+
{
16+
_renderMode = RenderModeHelper.ParseRenderMode(RenderModeStr);
17+
}
18+
else
19+
{
20+
throw new ArgumentException("RenderModeStr cannot be null or empty", nameof(RenderModeStr));
21+
}
22+
}
23+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<html>
2+
<head>
3+
<base href="/subdir/" />
4+
</head>
5+
<body>
6+
<div id="app">
7+
</div>
8+
9+
<script src="_framework/blazor.server.js" autostart="false"></script>
10+
<script>
11+
Blazor.start().then(() => {
12+
Blazor.rootComponents.add(document.getElementById("app"), "dynamic-js-root-counter", {});
13+
});
14+
</script>
15+
</body>
16+
</html>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<PageTitle>Counter</PageTitle>
2+
3+
<h1>Counter</h1>
4+
5+
<p role="status">Current count: @currentCount</p>
6+
7+
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
8+
9+
@code {
10+
[PersistentState] public int currentCount { get; set; }
11+
12+
private void IncrementCount()
13+
{
14+
currentCount++;
15+
}
16+
}

0 commit comments

Comments
 (0)