Skip to content

Commit 52e8488

Browse files
Copilotjaviercn
andcommitted
Add E2E tests for persistent component state filtering functionality
Co-authored-by: javiercn <[email protected]>
1 parent a2c9f1c commit 52e8488

File tree

4 files changed

+490
-0
lines changed

4 files changed

+490
-0
lines changed

src/Components/test/E2ETest/Tests/StatePersistenceTest.cs

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,286 @@ private void RenderComponentsWithPersistentStateAndValidate(
210210
interactiveRuntime: interactiveRuntime);
211211
}
212212

213+
[Theory]
214+
[InlineData(true, typeof(InteractiveServerRenderMode), (string)null)]
215+
[InlineData(true, typeof(InteractiveWebAssemblyRenderMode), (string)null)]
216+
[InlineData(true, typeof(InteractiveAutoRenderMode), (string)null)]
217+
[InlineData(false, typeof(InteractiveServerRenderMode), (string)null)]
218+
public void CanFilterPersistentStateCallbacks(bool suppressEnhancedNavigation, Type renderMode, string streaming)
219+
{
220+
var mode = renderMode switch
221+
{
222+
var t when t == typeof(InteractiveServerRenderMode) => "server",
223+
var t when t == typeof(InteractiveWebAssemblyRenderMode) => "wasm",
224+
var t when t == typeof(InteractiveAutoRenderMode) => "auto",
225+
_ => throw new ArgumentException($"Unknown render mode: {renderMode.Name}")
226+
};
227+
228+
if (!suppressEnhancedNavigation)
229+
{
230+
// Navigate to a page without components first to test enhanced navigation filtering
231+
Navigate($"subdir/persistent-state/page-no-components?render-mode={mode}&suppress-autostart");
232+
if (mode == "auto")
233+
{
234+
BlockWebAssemblyResourceLoad();
235+
}
236+
Browser.Click(By.Id("call-blazor-start"));
237+
Browser.Click(By.Id("filtering-test-link"));
238+
}
239+
else
240+
{
241+
EnhancedNavigationTestUtil.SuppressEnhancedNavigation(this, true);
242+
if (mode == "auto")
243+
{
244+
BlockWebAssemblyResourceLoad();
245+
}
246+
}
247+
248+
if (mode != "auto")
249+
{
250+
ValidateFilteringBehavior(suppressEnhancedNavigation, mode, renderMode, streaming);
251+
}
252+
else
253+
{
254+
// For auto mode, validate both server and wasm behavior
255+
ValidateFilteringBehavior(suppressEnhancedNavigation, mode, renderMode, streaming, interactiveRuntime: "server");
256+
257+
UnblockWebAssemblyResourceLoad();
258+
Browser.Navigate().Refresh();
259+
260+
ValidateFilteringBehavior(suppressEnhancedNavigation, mode, renderMode, streaming, interactiveRuntime: "wasm");
261+
}
262+
}
263+
264+
[Theory]
265+
[InlineData(true, typeof(InteractiveServerRenderMode))]
266+
[InlineData(true, typeof(InteractiveWebAssemblyRenderMode))]
267+
[InlineData(true, typeof(InteractiveAutoRenderMode))]
268+
[InlineData(false, typeof(InteractiveServerRenderMode))]
269+
public void CanFilterPersistentStateForEnhancedNavigation(bool suppressEnhancedNavigation, Type renderMode)
270+
{
271+
var mode = renderMode switch
272+
{
273+
var t when t == typeof(InteractiveServerRenderMode) => "server",
274+
var t when t == typeof(InteractiveWebAssemblyRenderMode) => "wasm",
275+
var t when t == typeof(InteractiveAutoRenderMode) => "auto",
276+
_ => throw new ArgumentException($"Unknown render mode: {renderMode.Name}")
277+
};
278+
279+
if (!suppressEnhancedNavigation)
280+
{
281+
// Navigate to a page without components first to test enhanced navigation filtering
282+
Navigate($"subdir/persistent-state/page-no-components?render-mode={mode}&suppress-autostart");
283+
if (mode == "auto")
284+
{
285+
BlockWebAssemblyResourceLoad();
286+
}
287+
Browser.Click(By.Id("call-blazor-start"));
288+
// Click link that enables persistence during enhanced navigation
289+
Browser.Click(By.Id("filtering-test-link-with-enhanced-nav"));
290+
}
291+
else
292+
{
293+
EnhancedNavigationTestUtil.SuppressEnhancedNavigation(this, true);
294+
if (mode == "auto")
295+
{
296+
BlockWebAssemblyResourceLoad();
297+
}
298+
}
299+
300+
if (mode != "auto")
301+
{
302+
ValidateEnhancedNavigationFiltering(suppressEnhancedNavigation, mode, renderMode);
303+
}
304+
else
305+
{
306+
// For auto mode, validate both server and wasm behavior
307+
ValidateEnhancedNavigationFiltering(suppressEnhancedNavigation, mode, renderMode, interactiveRuntime: "server");
308+
309+
UnblockWebAssemblyResourceLoad();
310+
Browser.Navigate().Refresh();
311+
312+
ValidateEnhancedNavigationFiltering(suppressEnhancedNavigation, mode, renderMode, interactiveRuntime: "wasm");
313+
}
314+
}
315+
316+
[Theory]
317+
[InlineData(typeof(InteractiveServerRenderMode))]
318+
[InlineData(typeof(InteractiveWebAssemblyRenderMode))]
319+
[InlineData(typeof(InteractiveAutoRenderMode))]
320+
public void CanDisablePersistenceForPrerendering(Type renderMode)
321+
{
322+
var mode = renderMode switch
323+
{
324+
var t when t == typeof(InteractiveServerRenderMode) => "server",
325+
var t when t == typeof(InteractiveWebAssemblyRenderMode) => "wasm",
326+
var t when t == typeof(InteractiveAutoRenderMode) => "auto",
327+
_ => throw new ArgumentException($"Unknown render mode: {renderMode.Name}")
328+
};
329+
330+
// Navigate to a page without components first
331+
Navigate($"subdir/persistent-state/page-no-components?render-mode={mode}&suppress-autostart");
332+
if (mode == "auto")
333+
{
334+
BlockWebAssemblyResourceLoad();
335+
}
336+
Browser.Click(By.Id("call-blazor-start"));
337+
// Click link that disables persistence during prerendering
338+
Browser.Click(By.Id("filtering-test-link-no-prerendering"));
339+
340+
if (mode != "auto")
341+
{
342+
ValidatePrerenderingFilteringDisabled(mode, renderMode);
343+
}
344+
else
345+
{
346+
// For auto mode, validate both server and wasm behavior
347+
ValidatePrerenderingFilteringDisabled(mode, renderMode, interactiveRuntime: "server");
348+
349+
UnblockWebAssemblyResourceLoad();
350+
Browser.Navigate().Refresh();
351+
352+
ValidatePrerenderingFilteringDisabled(mode, renderMode, interactiveRuntime: "wasm");
353+
}
354+
}
355+
356+
private void ValidateFilteringBehavior(
357+
bool suppressEnhancedNavigation,
358+
string mode,
359+
Type renderMode,
360+
string streaming,
361+
string interactiveRuntime = null)
362+
{
363+
if (suppressEnhancedNavigation)
364+
{
365+
Navigate($"subdir/persistent-state/filtering-test?render-mode={mode}&suppress-autostart");
366+
367+
// Validate server-side state before Blazor starts
368+
AssertFilteringPageState(
369+
mode: mode,
370+
renderMode: renderMode.Name,
371+
interactive: false,
372+
interactiveRuntime: interactiveRuntime);
373+
374+
Browser.Click(By.Id("call-blazor-start"));
375+
}
376+
377+
// Validate state after Blazor is interactive
378+
AssertFilteringPageState(
379+
mode: mode,
380+
renderMode: renderMode.Name,
381+
interactive: true,
382+
interactiveRuntime: interactiveRuntime);
383+
}
384+
385+
private void ValidateEnhancedNavigationFiltering(
386+
bool suppressEnhancedNavigation,
387+
string mode,
388+
Type renderMode,
389+
string interactiveRuntime = null)
390+
{
391+
if (suppressEnhancedNavigation)
392+
{
393+
Navigate($"subdir/persistent-state/filtering-test?render-mode={mode}&persist-enhanced-nav=true&suppress-autostart");
394+
395+
// Validate server-side state before Blazor starts
396+
AssertEnhancedNavFilteringPageState(
397+
mode: mode,
398+
renderMode: renderMode.Name,
399+
interactive: false,
400+
interactiveRuntime: interactiveRuntime);
401+
402+
Browser.Click(By.Id("call-blazor-start"));
403+
}
404+
405+
// Validate state after Blazor is interactive
406+
AssertEnhancedNavFilteringPageState(
407+
mode: mode,
408+
renderMode: renderMode.Name,
409+
interactive: true,
410+
interactiveRuntime: interactiveRuntime);
411+
}
412+
413+
private void ValidatePrerenderingFilteringDisabled(
414+
string mode,
415+
Type renderMode,
416+
string interactiveRuntime = null)
417+
{
418+
// When prerendering persistence is disabled, components should show fresh state
419+
AssertPrerenderingFilteringDisabledPageState(
420+
mode: mode,
421+
renderMode: renderMode.Name,
422+
interactive: true,
423+
interactiveRuntime: interactiveRuntime);
424+
}
425+
426+
private void AssertFilteringPageState(
427+
string mode,
428+
string renderMode,
429+
bool interactive,
430+
string interactiveRuntime = null)
431+
{
432+
Browser.Equal($"Render mode: {renderMode}", () => Browser.FindElement(By.Id("render-mode")).Text);
433+
Browser.Equal($"Interactive: {interactive}", () => Browser.FindElement(By.Id("interactive")).Text);
434+
435+
if (interactive)
436+
{
437+
interactiveRuntime = mode == "server" || mode == "wasm" ? mode : (interactiveRuntime ?? throw new InvalidOperationException("Specify interactiveRuntime for auto mode"));
438+
Browser.Equal($"Interactive runtime: {interactiveRuntime}", () => Browser.FindElement(By.Id("interactive-runtime")).Text);
439+
440+
// Default behavior: persist during prerendering, not during enhanced navigation
441+
Browser.Equal("Prerendering state found:true", () => Browser.FindElement(By.Id("prerendering-state-found")).Text);
442+
Browser.Equal("Enhanced nav state found:false", () => Browser.FindElement(By.Id("enhanced-nav-state-found")).Text);
443+
Browser.Equal("Circuit pause state found:false", () => Browser.FindElement(By.Id("circuit-pause-state-found")).Text);
444+
Browser.Equal("Combined filters state found:true", () => Browser.FindElement(By.Id("combined-filters-state-found")).Text);
445+
}
446+
}
447+
448+
private void AssertEnhancedNavFilteringPageState(
449+
string mode,
450+
string renderMode,
451+
bool interactive,
452+
string interactiveRuntime = null)
453+
{
454+
Browser.Equal($"Render mode: {renderMode}", () => Browser.FindElement(By.Id("render-mode")).Text);
455+
Browser.Equal($"Interactive: {interactive}", () => Browser.FindElement(By.Id("interactive")).Text);
456+
457+
if (interactive)
458+
{
459+
interactiveRuntime = mode == "server" || mode == "wasm" ? mode : (interactiveRuntime ?? throw new InvalidOperationException("Specify interactiveRuntime for auto mode"));
460+
Browser.Equal($"Interactive runtime: {interactiveRuntime}", () => Browser.FindElement(By.Id("interactive-runtime")).Text);
461+
462+
// Enhanced navigation persistence enabled
463+
Browser.Equal("Prerendering state found:true", () => Browser.FindElement(By.Id("prerendering-state-found")).Text);
464+
Browser.Equal("Enhanced nav state found:true", () => Browser.FindElement(By.Id("enhanced-nav-state-found")).Text);
465+
Browser.Equal("Circuit pause state found:false", () => Browser.FindElement(By.Id("circuit-pause-state-found")).Text);
466+
Browser.Equal("Combined filters state found:true", () => Browser.FindElement(By.Id("combined-filters-state-found")).Text);
467+
}
468+
}
469+
470+
private void AssertPrerenderingFilteringDisabledPageState(
471+
string mode,
472+
string renderMode,
473+
bool interactive,
474+
string interactiveRuntime = null)
475+
{
476+
Browser.Equal($"Render mode: {renderMode}", () => Browser.FindElement(By.Id("render-mode")).Text);
477+
Browser.Equal($"Interactive: {interactive}", () => Browser.FindElement(By.Id("interactive")).Text);
478+
479+
if (interactive)
480+
{
481+
interactiveRuntime = mode == "server" || mode == "wasm" ? mode : (interactiveRuntime ?? throw new InvalidOperationException("Specify interactiveRuntime for auto mode"));
482+
Browser.Equal($"Interactive runtime: {interactiveRuntime}", () => Browser.FindElement(By.Id("interactive-runtime")).Text);
483+
484+
// Prerendering persistence disabled - should show fresh values
485+
Browser.Equal("Prerendering state found:false", () => Browser.FindElement(By.Id("prerendering-state-found")).Text);
486+
Browser.Equal("Prerendering state value:fresh-prerendering", () => Browser.FindElement(By.Id("prerendering-state-value")).Text);
487+
Browser.Equal("Enhanced nav state found:false", () => Browser.FindElement(By.Id("enhanced-nav-state-found")).Text);
488+
Browser.Equal("Circuit pause state found:false", () => Browser.FindElement(By.Id("circuit-pause-state-found")).Text);
489+
Browser.Equal("Combined filters state found:false", () => Browser.FindElement(By.Id("combined-filters-state-found")).Text);
490+
}
491+
}
492+
213493
private void AssertPageState(
214494
string mode,
215495
string renderMode,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
@page "/persistent-state/filtering-test"
2+
@using TestContentPackage.PersistentComponents
3+
4+
<h3>Filtered Persistent State Test Page</h3>
5+
6+
<p>
7+
This page tests selective state persistence based on filtering criteria.
8+
It renders components with different filter configurations to validate that state is persisted or skipped based on the persistence reason.
9+
</p>
10+
11+
<p id="render-mode">Render mode: @_renderMode?.GetType()?.Name</p>
12+
<p id="streaming-id">Streaming id:@StreamingId</p>
13+
14+
@if (_renderMode != null)
15+
{
16+
<CascadingValue Name="RunningOnServer" Value="true">
17+
<FilteredPersistentStateComponent @rendermode="@_renderMode"
18+
ServerState="@ServerState"
19+
PersistOnPrerendering="@PersistOnPrerendering"
20+
PersistOnEnhancedNav="@PersistOnEnhancedNav"
21+
PersistOnCircuitPause="@PersistOnCircuitPause" />
22+
</CascadingValue>
23+
}
24+
25+
<a id="page-no-components-link" href=@($"persistent-state/page-no-components?render-mode={RenderMode}&streaming-id={StreamingId}")>Go to page with no components</a>
26+
27+
@code {
28+
private IComponentRenderMode _renderMode;
29+
30+
[SupplyParameterFromQuery(Name = "render-mode")] public string RenderMode { get; set; }
31+
[SupplyParameterFromQuery(Name = "streaming-id")] public string StreamingId { get; set; }
32+
[SupplyParameterFromQuery(Name = "server-state")] public string ServerState { get; set; }
33+
[SupplyParameterFromQuery(Name = "persist-prerendering")] public bool PersistOnPrerendering { get; set; } = true;
34+
[SupplyParameterFromQuery(Name = "persist-enhanced-nav")] public bool PersistOnEnhancedNav { get; set; } = false;
35+
[SupplyParameterFromQuery(Name = "persist-circuit-pause")] public bool PersistOnCircuitPause { get; set; } = true;
36+
37+
protected override void OnInitialized()
38+
{
39+
if (!string.IsNullOrEmpty(RenderMode))
40+
{
41+
switch (RenderMode)
42+
{
43+
case "server":
44+
_renderMode = new InteractiveServerRenderMode(true);
45+
break;
46+
case "wasm":
47+
_renderMode = new InteractiveWebAssemblyRenderMode(true);
48+
break;
49+
case "auto":
50+
_renderMode = new InteractiveAutoRenderMode(true);
51+
break;
52+
default:
53+
throw new ArgumentException($"Invalid render mode: {RenderMode}");
54+
}
55+
}
56+
}
57+
}

src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/PersistentState/PageWithoutComponents.razor

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66

77
<a id="page-with-components-link-and-state" href=@($"persistent-state/page-with-components?render-mode={RenderMode}&streaming-id={StreamingId}&server-state=other")>Go to page with components and state</a>
88

9+
<a id="filtering-test-link" href=@($"persistent-state/filtering-test?render-mode={RenderMode}&streaming-id={StreamingId}")>Go to filtering test page</a>
10+
11+
<a id="filtering-test-link-no-prerendering" href=@($"persistent-state/filtering-test?render-mode={RenderMode}&streaming-id={StreamingId}&persist-prerendering=false")>Go to filtering test page (no prerendering)</a>
12+
13+
<a id="filtering-test-link-with-enhanced-nav" href=@($"persistent-state/filtering-test?render-mode={RenderMode}&streaming-id={StreamingId}&persist-enhanced-nav=true")>Go to filtering test page (with enhanced nav)</a>
14+
915

1016
@code {
1117
[SupplyParameterFromQuery(Name = "render-mode")] public string RenderMode { get; set; }

0 commit comments

Comments
 (0)