Skip to content

Commit 0fddad7

Browse files
Copilotjaviercn
andcommitted
Add tests and update calling code with persistence reasons
Co-authored-by: javiercn <[email protected]>
1 parent 2519ee8 commit 0fddad7

File tree

6 files changed

+197
-3
lines changed

6 files changed

+197
-3
lines changed

src/Components/Components/src/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Microsoft.AspNetCore.Components.Routing.NotFoundEventArgs.Path.get -> string!
1111
Microsoft.AspNetCore.Components.Infrastructure.ComponentStatePersistenceManager.ComponentStatePersistenceManager(Microsoft.Extensions.Logging.ILogger<Microsoft.AspNetCore.Components.Infrastructure.ComponentStatePersistenceManager!>! logger, System.IServiceProvider! serviceProvider) -> void
1212
Microsoft.AspNetCore.Components.Infrastructure.ComponentStatePersistenceManager.SetPlatformRenderMode(Microsoft.AspNetCore.Components.IComponentRenderMode! renderMode) -> void
1313
Microsoft.AspNetCore.Components.Infrastructure.ComponentStatePersistenceManager.PersistStateAsync(Microsoft.AspNetCore.Components.IPersistentComponentStateStore! store, Microsoft.AspNetCore.Components.RenderTree.Renderer! renderer, Microsoft.AspNetCore.Components.IPersistenceReason! persistenceReason) -> System.Threading.Tasks.Task
14+
Microsoft.AspNetCore.Components.Infrastructure.ComponentStatePersistenceManager.PersistStateAsync(Microsoft.AspNetCore.Components.IPersistentComponentStateStore! store, Microsoft.AspNetCore.Components.RenderTree.Renderer! renderer, Microsoft.AspNetCore.Components.IPersistenceReason! persistenceReason) -> System.Threading.Tasks.Task
1415
Microsoft.AspNetCore.Components.Infrastructure.RegisterPersistentComponentStateServiceCollectionExtensions
1516
Microsoft.AspNetCore.Components.SupplyParameterFromPersistentComponentStateAttribute
1617
Microsoft.AspNetCore.Components.SupplyParameterFromPersistentComponentStateAttribute.SupplyParameterFromPersistentComponentStateAttribute() -> void
@@ -31,6 +32,7 @@ Microsoft.AspNetCore.Components.PersistReasonFilter<TReason>
3132
Microsoft.AspNetCore.Components.PersistReasonFilter<TReason>.PersistReasonFilter(bool persist) -> void
3233
Microsoft.AspNetCore.Components.PersistReasonFilter<TReason>.ShouldPersist(Microsoft.AspNetCore.Components.IPersistenceReason! reason) -> bool?
3334
Microsoft.AspNetCore.Components.PersistentComponentState.RegisterOnPersisting(System.Func<System.Threading.Tasks.Task!>! callback, Microsoft.AspNetCore.Components.IComponentRenderMode? renderMode, System.Collections.Generic.IReadOnlyList<Microsoft.AspNetCore.Components.IPersistenceReasonFilter!>? reasonFilters) -> Microsoft.AspNetCore.Components.PersistingComponentStateSubscription
35+
Microsoft.AspNetCore.Components.PersistentComponentState.RegisterOnPersisting(System.Func<System.Threading.Tasks.Task!>! callback, Microsoft.AspNetCore.Components.IComponentRenderMode? renderMode, System.Collections.Generic.IReadOnlyList<Microsoft.AspNetCore.Components.IPersistenceReasonFilter!>? reasonFilters) -> Microsoft.AspNetCore.Components.PersistingComponentStateSubscription
3436
Microsoft.Extensions.DependencyInjection.SupplyParameterFromPersistentComponentStateProviderServiceCollectionExtensions
3537
static Microsoft.AspNetCore.Components.Infrastructure.RegisterPersistentComponentStateServiceCollectionExtensions.AddPersistentServiceRegistration<TService>(Microsoft.Extensions.DependencyInjection.IServiceCollection! services, Microsoft.AspNetCore.Components.IComponentRenderMode! componentRenderMode) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
3638
static Microsoft.AspNetCore.Components.Infrastructure.ComponentsMetricsServiceCollectionExtensions.AddComponentsMetrics(Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!

src/Components/Components/test/PersistentState/ComponentStatePersistenceManagerTest.cs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,98 @@ IEnumerator IEnumerable.GetEnumerator()
418418
}
419419
}
420420

421+
[Fact]
422+
public void PersistenceReasons_HaveCorrectDefaults()
423+
{
424+
// Arrange & Act
425+
var prerenderingReason = new PersistOnPrerendering();
426+
var enhancedNavReason = new PersistOnEnhancedNavigation();
427+
var circuitPauseReason = new PersistOnCircuitPause();
428+
429+
// Assert
430+
Assert.True(prerenderingReason.PersistByDefault);
431+
Assert.False(enhancedNavReason.PersistByDefault);
432+
Assert.True(circuitPauseReason.PersistByDefault);
433+
}
434+
435+
[Fact]
436+
public async Task PersistStateAsync_RespectsReasonFilters()
437+
{
438+
// Arrange
439+
var logger = NullLogger<ComponentStatePersistenceManager>.Instance;
440+
var manager = new ComponentStatePersistenceManager(logger);
441+
var renderer = new TestRenderer();
442+
var store = new TestStore([]);
443+
var callbackExecuted = false;
444+
445+
// Register callback with filter that blocks enhanced navigation
446+
var filters = new List<IPersistenceReasonFilter>
447+
{
448+
new TestPersistenceReasonFilter<PersistOnEnhancedNavigation>(false)
449+
};
450+
451+
manager.State.RegisterOnPersisting(() =>
452+
{
453+
callbackExecuted = true;
454+
return Task.CompletedTask;
455+
}, new TestRenderMode(), filters);
456+
457+
// Act - persist with enhanced navigation reason
458+
await manager.PersistStateAsync(store, renderer, new PersistOnEnhancedNavigation());
459+
460+
// Assert - callback should not be executed
461+
Assert.False(callbackExecuted);
462+
}
463+
464+
[Fact]
465+
public async Task PersistStateAsync_AllowsWhenFilterMatches()
466+
{
467+
// Arrange
468+
var logger = NullLogger<ComponentStatePersistenceManager>.Instance;
469+
var manager = new ComponentStatePersistenceManager(logger);
470+
var renderer = new TestRenderer();
471+
var store = new TestStore([]);
472+
var callbackExecuted = false;
473+
474+
// Register callback with filter that allows prerendering
475+
var filters = new List<IPersistenceReasonFilter>
476+
{
477+
new TestPersistenceReasonFilter<PersistOnPrerendering>(true)
478+
};
479+
480+
manager.State.RegisterOnPersisting(() =>
481+
{
482+
callbackExecuted = true;
483+
return Task.CompletedTask;
484+
}, new TestRenderMode(), filters);
485+
486+
// Act - persist with prerendering reason
487+
await manager.PersistStateAsync(store, renderer, new PersistOnPrerendering());
488+
489+
// Assert - callback should be executed
490+
Assert.True(callbackExecuted);
491+
}
492+
493+
private class TestPersistenceReasonFilter<TReason> : IPersistenceReasonFilter
494+
where TReason : IPersistenceReason
495+
{
496+
private readonly bool _allow;
497+
498+
public TestPersistenceReasonFilter(bool allow)
499+
{
500+
_allow = allow;
501+
}
502+
503+
public bool? ShouldPersist(IPersistenceReason reason)
504+
{
505+
if (reason is TReason)
506+
{
507+
return _allow;
508+
}
509+
return null;
510+
}
511+
}
512+
421513
private class TestRenderMode : IComponentRenderMode
422514
{
423515
}

src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.PrerenderingState.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public async ValueTask<IHtmlContent> PrerenderPersistedStateAsync(HttpContext ht
5050

5151
if (store != null)
5252
{
53-
await manager.PersistStateAsync(store, this);
53+
await manager.PersistStateAsync(store, this, new PersistOnPrerendering());
5454
return store switch
5555
{
5656
ProtectedPrerenderComponentApplicationStore protectedStore => new ComponentStateHtmlContent(protectedStore, null),
@@ -80,7 +80,7 @@ public async ValueTask<IHtmlContent> PrerenderPersistedStateAsync(HttpContext ht
8080
var webAssembly = new CopyOnlyStore<InteractiveWebAssemblyRenderMode>();
8181
store = new CompositeStore(server, auto, webAssembly);
8282

83-
await manager.PersistStateAsync(store, this);
83+
await manager.PersistStateAsync(store, this, new PersistOnPrerendering());
8484

8585
foreach (var kvp in auto.Saved)
8686
{

src/Components/Server/src/Circuits/CircuitPersistenceManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public async Task PauseCircuitAsync(CircuitHost circuit, bool saveStateToClient
2828
collector.PersistRootComponents,
2929
RenderMode.InteractiveServer);
3030

31-
await persistenceManager.PersistStateAsync(collector, renderer);
31+
await persistenceManager.PersistStateAsync(collector, renderer, new PersistOnCircuitPause());
3232

3333
if (saveStateToClient)
3434
{
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
#nullable enable
22
Microsoft.AspNetCore.Components.Web.Internal.IInternalWebJSInProcessRuntime.InvokeJS(in Microsoft.JSInterop.Infrastructure.JSInvocationInfo invocationInfo) -> string!
3+
Microsoft.AspNetCore.Components.Web.PersistOnCircuitPauseFilter
4+
Microsoft.AspNetCore.Components.Web.PersistOnCircuitPauseFilter.PersistOnCircuitPauseFilter(bool persist = true) -> void
5+
Microsoft.AspNetCore.Components.Web.PersistOnEnhancedNavigationFilter
6+
Microsoft.AspNetCore.Components.Web.PersistOnEnhancedNavigationFilter.PersistOnEnhancedNavigationFilter(bool persist = true) -> void
7+
Microsoft.AspNetCore.Components.Web.PersistOnPrerenderingFilter
8+
Microsoft.AspNetCore.Components.Web.PersistOnPrerenderingFilter.PersistOnPrerenderingFilter(bool persist = true) -> void
39
virtual Microsoft.AspNetCore.Components.Routing.NavLink.ShouldMatch(string! uriAbsolute) -> bool
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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 Microsoft.AspNetCore.Components;
5+
using Xunit;
6+
7+
namespace Microsoft.AspNetCore.Components.Web;
8+
9+
public class PersistenceReasonFiltersTest
10+
{
11+
[Fact]
12+
public void PersistOnPrerenderingFilter_AllowsByDefault()
13+
{
14+
// Arrange
15+
var filter = new PersistOnPrerenderingFilter();
16+
var reason = new PersistOnPrerendering();
17+
18+
// Act
19+
var result = filter.ShouldPersist(reason);
20+
21+
// Assert
22+
Assert.True(result);
23+
}
24+
25+
[Fact]
26+
public void PersistOnPrerenderingFilter_CanBlock()
27+
{
28+
// Arrange
29+
var filter = new PersistOnPrerenderingFilter(persist: false);
30+
var reason = new PersistOnPrerendering();
31+
32+
// Act
33+
var result = filter.ShouldPersist(reason);
34+
35+
// Assert
36+
Assert.False(result);
37+
}
38+
39+
[Fact]
40+
public void PersistOnEnhancedNavigationFilter_AllowsByDefault()
41+
{
42+
// Arrange
43+
var filter = new PersistOnEnhancedNavigationFilter();
44+
var reason = new PersistOnEnhancedNavigation();
45+
46+
// Act
47+
var result = filter.ShouldPersist(reason);
48+
49+
// Assert
50+
Assert.True(result);
51+
}
52+
53+
[Fact]
54+
public void PersistOnEnhancedNavigationFilter_DoesNotMatchDifferentReason()
55+
{
56+
// Arrange
57+
var filter = new PersistOnEnhancedNavigationFilter();
58+
var reason = new PersistOnPrerendering();
59+
60+
// Act
61+
var result = filter.ShouldPersist(reason);
62+
63+
// Assert
64+
Assert.Null(result);
65+
}
66+
67+
[Fact]
68+
public void PersistOnCircuitPauseFilter_AllowsByDefault()
69+
{
70+
// Arrange
71+
var filter = new PersistOnCircuitPauseFilter();
72+
var reason = new PersistOnCircuitPause();
73+
74+
// Act
75+
var result = filter.ShouldPersist(reason);
76+
77+
// Assert
78+
Assert.True(result);
79+
}
80+
81+
[Fact]
82+
public void PersistOnCircuitPauseFilter_CanBlock()
83+
{
84+
// Arrange
85+
var filter = new PersistOnCircuitPauseFilter(persist: false);
86+
var reason = new PersistOnCircuitPause();
87+
88+
// Act
89+
var result = filter.ShouldPersist(reason);
90+
91+
// Assert
92+
Assert.False(result);
93+
}
94+
}

0 commit comments

Comments
 (0)