Skip to content

Commit a12499e

Browse files
committed
Merge in 'release/8.0' changes
2 parents fd749a7 + e91e94d commit a12499e

File tree

6 files changed

+167
-12
lines changed

6 files changed

+167
-12
lines changed

src/Components/Endpoints/test/WebRootComponentParametersTest.cs

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,36 +100,73 @@ public void WebRootComponentParameters_DefinitelyEquals_ReturnsTrue_ForEmptySetO
100100
}
101101

102102
[Fact]
103-
public void WebRootComponentParameters_DefinitelyEquals_Throws_WhenComparingNonJsonElementParameterToJsonElement()
103+
public void WebRootComponentParameters_DefinitelyEquals_ReturnsFalse_WhenComparingNonJsonElementParameterToJsonElement()
104104
{
105105
// Arrange
106106
var parameters1 = CreateParametersWithNonJsonElements(new() { ["First"] = 123 });
107107
var parameters2 = CreateParameters(new() { ["First"] = 456 });
108108

109-
// Act/assert
110-
Assert.Throws<InvalidCastException>(() => parameters1.DefinitelyEquals(parameters2));
109+
// Act
110+
var result = parameters1.DefinitelyEquals(parameters2);
111+
112+
// Assert
113+
Assert.False(result);
111114
}
112115

113116
[Fact]
114-
public void WebRootComponentParameters_DefinitelyEquals_Throws_WhenComparingJsonElementParameterToNonJsonElement()
117+
public void WebRootComponentParameters_DefinitelyEquals_ReturnsFalse_WhenComparingJsonElementParameterToNonJsonElement()
115118
{
116119
// Arrange
117120
var parameters1 = CreateParameters(new() { ["First"] = 123 });
118121
var parameters2 = CreateParametersWithNonJsonElements(new() { ["First"] = 456 });
119122

120-
// Act/assert
121-
Assert.Throws<InvalidCastException>(() => parameters1.DefinitelyEquals(parameters2));
123+
// Act
124+
var result = parameters1.DefinitelyEquals(parameters2);
125+
126+
// Assert
127+
Assert.False(result);
128+
}
129+
130+
[Fact]
131+
public void WebRootComponentParameters_DefinitelyEquals_ReturnsTrue_WhenComparingEqualNonJsonElementParameters()
132+
{
133+
// Arrange
134+
var parameters1 = CreateParametersWithNonJsonElements(new() { ["First"] = 123 });
135+
var parameters2 = CreateParametersWithNonJsonElements(new() { ["First"] = 123 });
136+
137+
// Act
138+
var result = parameters1.DefinitelyEquals(parameters2);
139+
140+
// Assert
141+
Assert.True(result);
122142
}
123143

124144
[Fact]
125-
public void WebRootComponentParameters_DefinitelyEquals_Throws_WhenComparingNonJsonElementParameters()
145+
public void WebRootComponentParameters_DefinitelyEquals_ReturnsFalse_WhenComparingInequalNonJsonElementParameters()
126146
{
127147
// Arrange
128148
var parameters1 = CreateParametersWithNonJsonElements(new() { ["First"] = 123 });
129149
var parameters2 = CreateParametersWithNonJsonElements(new() { ["First"] = 456 });
130150

131-
// Act/assert
132-
Assert.Throws<InvalidCastException>(() => parameters1.DefinitelyEquals(parameters2));
151+
// Act
152+
var result = parameters1.DefinitelyEquals(parameters2);
153+
154+
// Assert
155+
Assert.False(result);
156+
}
157+
158+
[Fact]
159+
public void WebRootComponentParameters_DefinitelyEquals_ReturnsTrue_WhenComparingNullParameters()
160+
{
161+
// Arrange
162+
var parameters1 = CreateParametersWithNonJsonElements(new() { ["First"] = null });
163+
var parameters2 = CreateParametersWithNonJsonElements(new() { ["First"] = null });
164+
165+
// Act
166+
var result = parameters1.DefinitelyEquals(parameters2);
167+
168+
// Assert
169+
Assert.True(result);
133170
}
134171

135172
private static WebRootComponentParameters CreateParameters(Dictionary<string, object> parameters)

src/Components/Shared/src/WebRootComponentParameters.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,17 @@ public bool DefinitelyEquals(in WebRootComponentParameters other)
4545
return false;
4646
}
4747

48-
var value = ((JsonElement)_serializedParameterValues[i]).GetRawText();
49-
var otherValue = ((JsonElement)other._serializedParameterValues[i]).GetRawText();
50-
if (!string.Equals(value, otherValue, StringComparison.Ordinal))
48+
// We expect each serialized parameter value to be either a 'JsonElement' or 'null'.
49+
var value = _serializedParameterValues[i];
50+
var otherValue = other._serializedParameterValues[i];
51+
if (value is JsonElement jsonValue && otherValue is JsonElement otherJsonValue)
52+
{
53+
if (!string.Equals(jsonValue.GetRawText(), otherJsonValue.GetRawText(), StringComparison.Ordinal))
54+
{
55+
return false;
56+
}
57+
}
58+
else if (!Equals(value, otherValue))
5159
{
5260
return false;
5361
}

src/Components/test/E2ETest/ServerRenderingTests/EnhancedNavigationTest.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,38 @@ public void LocationChangingEventGetsInvokedOnEnhancedNavigationOnlyForRuntimeTh
554554
Browser.Equal("0", () => Browser.Exists(By.Id($"location-changing-count-{anotherRuntime}")).Text);
555555
}
556556

557+
[Theory]
558+
[InlineData("server")]
559+
[InlineData("wasm")]
560+
public void CanReceiveNullParameterValueOnEnhancedNavigation(string renderMode)
561+
{
562+
// See: https://github.com/dotnet/aspnetcore/issues/52434
563+
Navigate($"{ServerPathBase}/nav");
564+
Browser.Equal("Hello", () => Browser.Exists(By.TagName("h1")).Text);
565+
566+
Browser.Exists(By.TagName("nav")).FindElement(By.LinkText($"Null component parameter ({renderMode})")).Click();
567+
Browser.Equal("Page rendering component with null parameter", () => Browser.Exists(By.TagName("h1")).Text);
568+
Browser.Equal("0", () => Browser.Exists(By.Id("current-count")).Text);
569+
570+
Browser.Exists(By.Id("button-increment")).Click();
571+
Browser.Equal("0", () => Browser.Exists(By.Id("location-changed-count")).Text);
572+
Browser.Equal("1", () => Browser.Exists(By.Id("current-count")).Text);
573+
574+
// This refresh causes the interactive component to receive a 'null' parameter value
575+
Browser.Exists(By.Id("button-refresh")).Click();
576+
Browser.Equal("1", () => Browser.Exists(By.Id("location-changed-count")).Text);
577+
Browser.Equal("1", () => Browser.Exists(By.Id("current-count")).Text);
578+
579+
// Increment the count again to ensure that interactivity still works
580+
Browser.Exists(By.Id("button-increment")).Click();
581+
Browser.Equal("2", () => Browser.Exists(By.Id("current-count")).Text);
582+
583+
// Even if the interactive runtime continues to function (as the WebAssembly runtime might),
584+
// fail the test if any errors were logged to the browser console
585+
var logs = Browser.GetBrowserLogs(LogLevel.Warning);
586+
Assert.DoesNotContain(logs, log => log.Message.Contains("Error"));
587+
}
588+
557589
private void AssertEnhancedUpdateCountEquals(long count)
558590
=> Browser.Equal(count, () => ((IJavaScriptExecutor)Browser).ExecuteScript("return window.enhancedPageUpdateCount;"));
559591

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
@page "/nav/null-parameter/{mode}"
2+
@using TestContentPackage
3+
4+
@* https://github.com/dotnet/aspnetcore/issues/52434 *@
5+
6+
<h1>Page rendering component with null parameter</h1>
7+
8+
@if (Mode == "server")
9+
{
10+
<ComponentAcceptingNullParameter @rendermode="RenderMode.InteractiveServer" Value="@null" />
11+
}
12+
else if (Mode == "wasm")
13+
{
14+
<ComponentAcceptingNullParameter @rendermode="RenderMode.InteractiveWebAssembly" Value="@null" />
15+
}
16+
else
17+
{
18+
<p>Expected a render mode of 'server' or 'wasm', but got '@Mode'.</p>
19+
}
20+
21+
@code {
22+
[Parameter]
23+
public string? Mode { get; set; }
24+
}

src/Components/test/testassets/Components.TestServer/RazorComponents/Shared/EnhancedNavLayout.razor

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
<NavLink href="nav/location-changed/server">LocationChanged/LocationChanging event (server)</NavLink>
2424
<NavLink href="nav/location-changed/wasm">LocationChanged/LocationChanging event (wasm)</NavLink>
2525
<NavLink href="nav/location-changed/server-and-wasm">LocationChanged/LocationChanging event (server-and-wasm)</NavLink>
26+
<NavLink href="nav/null-parameter/server">Null component parameter (server)</NavLink>
27+
<NavLink href="nav/null-parameter/wasm">Null component parameter (wasm)</NavLink>
2628
</nav>
2729
<hr/>
2830
<main>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
@implements IDisposable
2+
@inject NavigationManager NavigationManager
3+
@using Microsoft.AspNetCore.Components.Routing
4+
5+
<p>Value: @(Value ?? "(null)")</p>
6+
7+
@if (_interactive)
8+
{
9+
<button id="button-increment" @onclick="Increment">Count: <span id="current-count">@_count</span></button>
10+
<button id="button-refresh" @onclick="Refresh">Refresh</button>
11+
<p>Location changed count: <span id="location-changed-count">@_locationChangedCount</span></p>
12+
}
13+
14+
@code {
15+
private bool _interactive;
16+
private int _count;
17+
private int _locationChangedCount;
18+
19+
[Parameter]
20+
public string Value { get; set; }
21+
22+
protected override void OnAfterRender(bool firstRender)
23+
{
24+
if (firstRender)
25+
{
26+
NavigationManager.LocationChanged += OnLocationChanged;
27+
_interactive = true;
28+
StateHasChanged();
29+
}
30+
}
31+
32+
private void OnLocationChanged(object sender, LocationChangedEventArgs e)
33+
{
34+
_locationChangedCount++;
35+
StateHasChanged();
36+
}
37+
38+
private void Increment()
39+
{
40+
_count++;
41+
}
42+
43+
private void Refresh()
44+
{
45+
NavigationManager.Refresh();
46+
}
47+
48+
public void Dispose()
49+
{
50+
NavigationManager.LocationChanged -= OnLocationChanged;
51+
}
52+
}

0 commit comments

Comments
 (0)