Skip to content

Commit 0a86864

Browse files
committed
Test JSRuntime for value type handling
1 parent 8b02460 commit 0a86864

File tree

4 files changed

+133
-1
lines changed

4 files changed

+133
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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 BasicTestApp;
5+
using Microsoft.AspNetCore.Components.E2ETest;
6+
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
7+
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
8+
using Microsoft.AspNetCore.E2ETesting;
9+
using OpenQA.Selenium;
10+
using Xunit.Abstractions;
11+
12+
namespace Microsoft.AspNetCore.Components.E2ETests.Tests;
13+
14+
public class InteropValueTypesTest(
15+
BrowserFixture browserFixture,
16+
ToggleExecutionModeServerFixture<Program> serverFixture,
17+
ITestOutputHelper output)
18+
: ServerTestBase<ToggleExecutionModeServerFixture<Program>>(browserFixture, serverFixture, output)
19+
{
20+
protected override void InitializeAsyncCore()
21+
{
22+
Navigate(ServerPathBase);
23+
Browser.MountTestComponent<InteropValueTypesComponent>();
24+
25+
var interopButton = Browser.Exists(By.Id("btn-interop"));
26+
interopButton.Click();
27+
Browser.Exists(By.Id("done-with-interop"));
28+
}
29+
30+
[Fact]
31+
public void CanRetrieveStoredGuidAsString()
32+
{
33+
var stringGuidElement = Browser.Exists(By.Id("string-get-by-interop"));
34+
35+
Browser.NotEqual(string.Empty, () => stringGuidElement.Text);
36+
Browser.NotEqual(default, () => Guid.Parse(stringGuidElement.Text));
37+
}
38+
39+
[Fact]
40+
public void CanRetrieveStoredGuidAsGuid()
41+
{
42+
var guidElement = Browser.Exists(By.Id("guid-get-by-interop"));
43+
44+
Browser.NotEqual(default, () => Guid.Parse(guidElement.Text));
45+
}
46+
47+
[Fact]
48+
public void CanRetrieveStoredGuidAsNullableGuid()
49+
{
50+
var nullableGuidElement = Browser.Exists(By.Id("nullable-guid-get-by-interop"));
51+
52+
Browser.NotEqual(default, () => Guid.Parse(nullableGuidElement.Text));
53+
}
54+
55+
[Fact]
56+
public void CanRetrieveNullAsNullableGuid()
57+
{
58+
var nullableGuidElement = Browser.Exists(By.Id("null-loaded-into-nullable"));
59+
60+
Browser.Equal(true.ToString(), () => nullableGuidElement.Text);
61+
}
62+
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public StartupErrorNotificationTest(
2727
public void DisplaysNotificationForStartupException(bool errorIsAsync)
2828
{
2929
var url = $"{ServerPathBase}?error={(errorIsAsync ? "async" : "sync")}";
30-
30+
3131
Navigate(url);
3232
var errorUiElem = Browser.Exists(By.Id("blazor-error-ui"), TimeSpan.FromSeconds(10));
3333
Assert.NotNull(errorUiElem);

src/Components/test/testassets/BasicTestApp/Index.razor

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
<option value="BasicTestApp.HttpClientTest.HttpRequestsComponent">HttpClient tester</option>
6767
<option value="BasicTestApp.InputEventComponent">Input events</option>
6868
<option value="BasicTestApp.InteropComponent">Interop component</option>
69+
<option value="BasicTestApp.InteropValueTypesComponent">Interop value types</option>
6970
<option value="BasicTestApp.InteropOnInitializationComponent">Interop on initialization</option>
7071
<option value="BasicTestApp.JavaScriptRootComponents">JavaScript root components</option>
7172
<option value="BasicTestApp.JsonSerializationCases">JSON serialization</option>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
@using Microsoft.JSInterop
2+
@inject IJSRuntime JSRuntime
3+
4+
<button id="btn-interop" @onclick="InvokeInteropAsync">Invoke interop!</button>
5+
6+
<p>
7+
This component shows it's possible to save and load value types (in this case, a guid)
8+
to and from localstorage,
9+
and also that a null value can be loaded into a nullable value type, i.e. a Guid?.
10+
</p>
11+
12+
<p>
13+
String value from guid:
14+
<strong id="string-get-by-interop">@(StringFromInterop ?? "No value yet")</strong>
15+
</p>
16+
17+
<p>
18+
Guid value from guid is default(Guid) if it wasn't loaded correctly:
19+
<strong id="guid-get-by-interop">@GuidFromInterop</strong>
20+
</p>
21+
22+
<p>
23+
Nullable Guid value from guid is null if it wasn't loaded correctly:
24+
<strong id="nullable-guid-get-by-interop">@NullableGuidFromInterop</strong>
25+
</p>
26+
27+
<p>
28+
Nullable load result is false if the null value wasn't loaded into the nullable guid correctly:
29+
<strong id="null-loaded-into-nullable">@NullableLoadResult</strong>
30+
</p>
31+
32+
@if (DoneWithInterop)
33+
{
34+
<p id="done-with-interop">
35+
Done with interop!
36+
</p>
37+
}
38+
39+
@code {
40+
public Guid Guid { get; } = Guid.NewGuid();
41+
public string StringFromInterop { get; set; }
42+
public Guid GuidFromInterop { get; set; }
43+
public Guid? NullableGuidFromInterop { get; set; }
44+
public bool NullableLoadResult { get; set; }
45+
public bool DoneWithInterop { get; set; }
46+
47+
private async Task InvokeInteropAsync()
48+
{
49+
// Store guid in localStorage
50+
await JSRuntime.InvokeVoidAsync("localStorage.setItem", "guid", Guid);
51+
52+
// Retrieve guid from localStorage as string because it's a simple conversion
53+
StringFromInterop = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "guid");
54+
55+
// Retrieve guid from localStorage as Guid
56+
GuidFromInterop = await JSRuntime.InvokeAsync<Guid>("localStorage.getItem", "guid");
57+
58+
// Retrieve guid from localStorage as Guid?
59+
NullableGuidFromInterop = await JSRuntime.InvokeAsync<Guid?>("localStorage.getItem", "guid");
60+
61+
// Retrieve null from localStorage as Guid?
62+
var nullableGuid = await JSRuntime.InvokeAsync<Guid?>("localStorage.getItem", "nothingHere");
63+
64+
// If the retrieval crashes, the bool stays false
65+
NullableLoadResult = !nullableGuid.HasValue;
66+
67+
DoneWithInterop = true;
68+
}
69+
}

0 commit comments

Comments
 (0)