-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Fix Blazor persistent component state restoration for components without keys and add E2E test coverage #63194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 11 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
3715f11
Initial plan
Copilot bd8bba1
Fix Blazor persistent component state issue and add comprehensive tests
Copilot 8b9d70d
Add comprehensive test for skipNotifications scenario
Copilot 3db6c92
Rewrite persistent state tests to properly simulate component recreat…
Copilot 687eee6
Add E2E test pages for conditional component rendering to test persis…
Copilot 8ea8b49
Cleanup
javiercn 29eefdf
Fix build errors
javiercn 7f1b952
Fix tests
javiercn fe216c2
Fix tests
javiercn 82246b9
Fix E2E tests
javiercn eea088a
Fix test
javiercn 73b9c81
Remove unused file
javiercn 5892d95
Update src/Components/test/testassets/Components.TestServer/RazorComp…
javiercn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
...erver/RazorComponents/Pages/PersistentState/PageWithConditionalPersistentComponents.razor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
@page "/persistent-state/page-with-conditional-components" | ||
@using TestContentPackage.PersistentComponents | ||
|
||
<h3>Persistent component state with conditional rendering</h3> | ||
|
||
<h3> | ||
This page tests persistent component state restoration for: | ||
1. A component without @@key that always renders (tests component recreation during navigation) | ||
2. A component that gets conditionally rendered based on query string (tests add/remove scenarios) | ||
Both should restore state correctly regardless of when they are destroyed and recreated. | ||
</h3> | ||
|
||
<p id="render-mode">Render mode: @_renderMode?.GetType()?.Name</p> | ||
<p id="streaming-id">Streaming id:@StreamingId</p> | ||
<p id="show-conditional">Show conditional: @ShowConditional</p> | ||
|
||
@if (_renderMode != null) | ||
{ | ||
@* Component without @key that always renders - tests navigation scenarios *@ | ||
<div id="always-rendered-component"> | ||
<h4>Always Rendered Component (no @@key)</h4> | ||
@if (!string.IsNullOrEmpty(StreamingId)) | ||
{ | ||
<StreamingComponentWithDeclarativePersistentState @rendermode="@_renderMode" StreamingId="@StreamingId" ServerState="@ServerState" /> | ||
} | ||
else | ||
{ | ||
<NonStreamingComponentWithDeclarativePersistentState @rendermode="@_renderMode" ServerState="@ServerState" /> | ||
} | ||
</div> | ||
|
||
@* Conditionally rendered component - tests add/remove scenarios *@ | ||
@if (ShowConditional) | ||
{ | ||
<div id="conditional-component"> | ||
<h4>Conditionally Rendered Component</h4> | ||
@if (!string.IsNullOrEmpty(StreamingId)) | ||
{ | ||
<StreamingComponentWithDeclarativePersistentState @key="@("conditional")" @rendermode="@_renderMode" StreamingId="@($"{StreamingId}-conditional")" ServerState="@($"{ServerState}-conditional")" /> | ||
} | ||
else | ||
{ | ||
<NonStreamingComponentWithDeclarativePersistentState @key="@("conditional")" @rendermode="@_renderMode" ServerState="@($"{ServerState}-conditional")" /> | ||
} | ||
</div> | ||
} | ||
} | ||
|
||
@if (!string.IsNullOrEmpty(StreamingId)) | ||
{ | ||
<a id="end-streaming" href="@($"persistent-state/end-streaming?streaming-id={StreamingId}")" target="_blank">End streaming</a> | ||
} | ||
|
||
<a id="toggle-conditional" href="@GetToggleConditionalUrl()">@(ShowConditional ? "Hide" : "Show") conditional component</a> | ||
<br /> | ||
<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> | ||
|
||
@code { | ||
|
||
private IComponentRenderMode _renderMode; | ||
|
||
[SupplyParameterFromQuery(Name = "render-mode")] public string RenderMode { get; set; } | ||
|
||
[SupplyParameterFromQuery(Name = "streaming-id")] public string StreamingId { get; set; } | ||
|
||
[SupplyParameterFromQuery(Name = "server-state")] public string ServerState { get; set; } | ||
|
||
[SupplyParameterFromQuery(Name = "show-conditional")] public bool ShowConditional { get; set; } | ||
|
||
protected override void OnInitialized() | ||
{ | ||
if (!string.IsNullOrEmpty(RenderMode)) | ||
{ | ||
switch (RenderMode) | ||
{ | ||
case "server": | ||
_renderMode = new InteractiveServerRenderMode(true); | ||
break; | ||
case "wasm": | ||
_renderMode = new InteractiveWebAssemblyRenderMode(true); | ||
break; | ||
case "auto": | ||
_renderMode = new InteractiveAutoRenderMode(true); | ||
break; | ||
default: | ||
throw new ArgumentException($"Invalid render mode: {RenderMode}"); | ||
} | ||
} | ||
} | ||
|
||
private string GetToggleConditionalUrl() | ||
{ | ||
var uri = new UriBuilder(Navigation.Uri); | ||
var query = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query); | ||
|
||
query["show-conditional"] = (!ShowConditional).ToString().ToLowerInvariant(); | ||
|
||
uri.Query = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString("", query) | ||
javiercn marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
.TrimStart('?'); | ||
|
||
return uri.ToString(); | ||
} | ||
|
||
[Inject] public NavigationManager Navigation { get; set; } | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.