Turn on scope validation for service provider in Development (#19908)
* Turn on scope validation for service provider * Make WebAssemblyJSRuntime interop-specific overloads extension methods Fixes https://github.com/dotnet/aspnetcore/issues/9365
This commit is contained in:
commit
56d22a817b
|
|
@ -42,41 +42,6 @@ namespace Microsoft.JSInterop.WebAssembly
|
||||||
BeginInvokeJS(0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", args);
|
BeginInvokeJS(0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Custom WebAssemblyJSRuntime methods
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes the JavaScript function registered with the specified identifier.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
|
||||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
|
||||||
/// <returns>The result of the function invocation.</returns>
|
|
||||||
public TResult InvokeUnmarshalled<TResult>(string identifier)
|
|
||||||
=> InvokeUnmarshalled<object, object, object, TResult>(identifier, null, null, null);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes the JavaScript function registered with the specified identifier.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
|
||||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
|
||||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
|
||||||
/// <param name="arg0">The first argument.</param>
|
|
||||||
/// <returns>The result of the function invocation.</returns>
|
|
||||||
public TResult InvokeUnmarshalled<T0, TResult>(string identifier, T0 arg0)
|
|
||||||
=> InvokeUnmarshalled<T0, object, object, TResult>(identifier, arg0, null, null);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes the JavaScript function registered with the specified identifier.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
|
||||||
/// <typeparam name="T1">The type of the second argument.</typeparam>
|
|
||||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
|
||||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
|
||||||
/// <param name="arg0">The first argument.</param>
|
|
||||||
/// <param name="arg1">The second argument.</param>
|
|
||||||
/// <returns>The result of the function invocation.</returns>
|
|
||||||
public TResult InvokeUnmarshalled<T0, T1, TResult>(string identifier, T0 arg0, T1 arg1)
|
|
||||||
=> InvokeUnmarshalled<T0, T1, object, TResult>(identifier, arg0, arg1, null);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invokes the JavaScript function registered with the specified identifier.
|
/// Invokes the JavaScript function registered with the specified identifier.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -89,14 +54,12 @@ namespace Microsoft.JSInterop.WebAssembly
|
||||||
/// <param name="arg1">The second argument.</param>
|
/// <param name="arg1">The second argument.</param>
|
||||||
/// <param name="arg2">The third argument.</param>
|
/// <param name="arg2">The third argument.</param>
|
||||||
/// <returns>The result of the function invocation.</returns>
|
/// <returns>The result of the function invocation.</returns>
|
||||||
public TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
public virtual TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
||||||
{
|
{
|
||||||
var result = InternalCalls.InvokeJSUnmarshalled<T0, T1, T2, TResult>(out var exception, identifier, arg0, arg1, arg2);
|
var result = InternalCalls.InvokeJSUnmarshalled<T0, T1, T2, TResult>(out var exception, identifier, arg0, arg1, arg2);
|
||||||
return exception != null
|
return exception != null
|
||||||
? throw new JSException(exception)
|
? throw new JSException(exception)
|
||||||
: result;
|
: result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.JSInterop.WebAssembly
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for <see cref="WebAssemblyJSRuntime"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static class WebAssemblyJSRuntimeExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the JavaScript function registered with the specified identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
||||||
|
/// <param name="jsRuntime">The <see cref="WebAssemblyJSRuntime"/>.</param>
|
||||||
|
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||||
|
/// <returns>The result of the function invocation.</returns>
|
||||||
|
public static TResult InvokeUnmarshalled<TResult>(this WebAssemblyJSRuntime jsRuntime, string identifier)
|
||||||
|
{
|
||||||
|
if (jsRuntime is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(jsRuntime));
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsRuntime.InvokeUnmarshalled<object, object, object, TResult>(identifier, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the JavaScript function registered with the specified identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
||||||
|
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
||||||
|
/// <param name="jsRuntime">The <see cref="WebAssemblyJSRuntime"/>.</param>
|
||||||
|
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||||
|
/// <param name="arg0">The first argument.</param>
|
||||||
|
/// <returns>The result of the function invocation.</returns>
|
||||||
|
public static TResult InvokeUnmarshalled<T0, TResult>(this WebAssemblyJSRuntime jsRuntime, string identifier, T0 arg0)
|
||||||
|
{
|
||||||
|
if (jsRuntime is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(jsRuntime));
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsRuntime.InvokeUnmarshalled<T0, object, object, TResult>(identifier, arg0, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the JavaScript function registered with the specified identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
||||||
|
/// <typeparam name="T1">The type of the second argument.</typeparam>
|
||||||
|
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
||||||
|
/// <param name="jsRuntime">The <see cref="WebAssemblyJSRuntime"/>.</param>
|
||||||
|
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||||
|
/// <param name="arg0">The first argument.</param>
|
||||||
|
/// <param name="arg1">The second argument.</param>
|
||||||
|
/// <returns>The result of the function invocation.</returns>
|
||||||
|
public static TResult InvokeUnmarshalled<T0, T1, TResult>(this WebAssemblyJSRuntime jsRuntime, string identifier, T0 arg0, T1 arg1)
|
||||||
|
{
|
||||||
|
if (jsRuntime is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(jsRuntime));
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsRuntime.InvokeUnmarshalled<T0, T1, object, TResult>(identifier, arg0, arg1, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,8 @@ using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.JSInterop.WebAssembly;
|
||||||
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
|
|
@ -15,7 +17,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CanResolve_AccessTokenProvider()
|
public void CanResolve_AccessTokenProvider()
|
||||||
{
|
{
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(GetJSRuntime());
|
||||||
builder.Services.AddApiAuthorization();
|
builder.Services.AddApiAuthorization();
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
|
|
@ -25,7 +27,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CanResolve_IRemoteAuthenticationService()
|
public void CanResolve_IRemoteAuthenticationService()
|
||||||
{
|
{
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(GetJSRuntime());
|
||||||
builder.Services.AddApiAuthorization();
|
builder.Services.AddApiAuthorization();
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
|
|
@ -35,7 +37,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ApiAuthorizationOptions_ConfigurationDefaultsGetApplied()
|
public void ApiAuthorizationOptions_ConfigurationDefaultsGetApplied()
|
||||||
{
|
{
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(GetJSRuntime());
|
||||||
builder.Services.AddApiAuthorization();
|
builder.Services.AddApiAuthorization();
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
|
|
@ -69,7 +71,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ApiAuthorizationOptions_DefaultsCanBeOverriden()
|
public void ApiAuthorizationOptions_DefaultsCanBeOverriden()
|
||||||
{
|
{
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(GetJSRuntime());
|
||||||
builder.Services.AddApiAuthorization(options =>
|
builder.Services.AddApiAuthorization(options =>
|
||||||
{
|
{
|
||||||
options.AuthenticationPaths = new RemoteAuthenticationApplicationPathsOptions
|
options.AuthenticationPaths = new RemoteAuthenticationApplicationPathsOptions
|
||||||
|
|
@ -129,7 +131,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
[Fact]
|
[Fact]
|
||||||
public void OidcOptions_ConfigurationDefaultsGetApplied()
|
public void OidcOptions_ConfigurationDefaultsGetApplied()
|
||||||
{
|
{
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(GetJSRuntime());
|
||||||
builder.Services.Replace(ServiceDescriptor.Singleton<NavigationManager, TestNavigationManager>());
|
builder.Services.Replace(ServiceDescriptor.Singleton<NavigationManager, TestNavigationManager>());
|
||||||
builder.Services.AddOidcAuthentication(options => { });
|
builder.Services.AddOidcAuthentication(options => { });
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
@ -167,7 +169,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
[Fact]
|
[Fact]
|
||||||
public void OidcOptions_DefaultsCanBeOverriden()
|
public void OidcOptions_DefaultsCanBeOverriden()
|
||||||
{
|
{
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(GetJSRuntime());
|
||||||
builder.Services.AddOidcAuthentication(options =>
|
builder.Services.AddOidcAuthentication(options =>
|
||||||
{
|
{
|
||||||
options.AuthenticationPaths = new RemoteAuthenticationApplicationPathsOptions
|
options.AuthenticationPaths = new RemoteAuthenticationApplicationPathsOptions
|
||||||
|
|
@ -242,5 +244,19 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
|
|
||||||
protected override void NavigateToCore(string uri, bool forceLoad) => throw new System.NotImplementedException();
|
protected override void NavigateToCore(string uri, bool forceLoad) => throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WebAssemblyJSRuntime GetJSRuntime(string environment = "Production")
|
||||||
|
{
|
||||||
|
var jsRuntime = new Mock<WebAssemblyJSRuntime>();
|
||||||
|
jsRuntime.Setup(j => j.InvokeUnmarshalled<object, object, object, string>("Blazor._internal.getApplicationEnvironment", null, null, null))
|
||||||
|
.Returns(environment)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
jsRuntime.Setup(j => j.InvokeUnmarshalled<string, object, object, byte[]>("Blazor._internal.getConfig", It.IsAny<string>(), null, null))
|
||||||
|
.Returns((byte[])null)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
return jsRuntime.Object;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using Microsoft.AspNetCore.Components.Routing;
|
using Microsoft.AspNetCore.Components.Routing;
|
||||||
using Microsoft.AspNetCore.Components.WebAssembly.Services;
|
using Microsoft.AspNetCore.Components.WebAssembly.Services;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
@ -14,6 +13,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
|
using Microsoft.JSInterop.WebAssembly;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
{
|
{
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
// We don't use the args for anything right now, but we want to accept them
|
// We don't use the args for anything right now, but we want to accept them
|
||||||
// here so that it shows up this way in the project templates.
|
// here so that it shows up this way in the project templates.
|
||||||
args ??= Array.Empty<string>();
|
args ??= Array.Empty<string>();
|
||||||
var builder = new WebAssemblyHostBuilder();
|
var builder = new WebAssemblyHostBuilder(DefaultWebAssemblyJSRuntime.Instance);
|
||||||
|
|
||||||
// Right now we don't have conventions or behaviors that are specific to this method
|
// Right now we don't have conventions or behaviors that are specific to this method
|
||||||
// however, making this the default for the template allows us to add things like that
|
// however, making this the default for the template allows us to add things like that
|
||||||
|
|
@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates an instance of <see cref="WebAssemblyHostBuilder"/> with the minimal configuration.
|
/// Creates an instance of <see cref="WebAssemblyHostBuilder"/> with the minimal configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private WebAssemblyHostBuilder()
|
internal WebAssemblyHostBuilder(WebAssemblyJSRuntime jsRuntime)
|
||||||
{
|
{
|
||||||
// Private right now because we don't have much reason to expose it. This can be exposed
|
// Private right now because we don't have much reason to expose it. This can be exposed
|
||||||
// in the future if we want to give people a choice between CreateDefault and something
|
// in the future if we want to give people a choice between CreateDefault and something
|
||||||
|
|
@ -58,25 +58,20 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
|
|
||||||
InitializeDefaultServices();
|
InitializeDefaultServices();
|
||||||
|
|
||||||
|
var hostEnvironment = InitializeEnvironment(jsRuntime);
|
||||||
|
|
||||||
_createServiceProvider = () =>
|
_createServiceProvider = () =>
|
||||||
{
|
{
|
||||||
return Services.BuildServiceProvider();
|
return Services.BuildServiceProvider(validateScopes: hostEnvironment.Environment == "Development");
|
||||||
};
|
};
|
||||||
|
|
||||||
InitializeEnvironment();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeEnvironment()
|
private WebAssemblyHostEnvironment InitializeEnvironment(WebAssemblyJSRuntime jsRuntime)
|
||||||
{
|
{
|
||||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Create("WEBASSEMBLY")))
|
var applicationEnvironment = jsRuntime.InvokeUnmarshalled<string>("Blazor._internal.getApplicationEnvironment");
|
||||||
{
|
var hostEnvironment = new WebAssemblyHostEnvironment(applicationEnvironment);
|
||||||
// The remainder of this method relies on the ability to make .NET WebAssembly-specific JSInterop calls.
|
|
||||||
// Note that this short-circuit exists as a way for unit tests running in .NET Core without JSInterop to run.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var applicationEnvironment = DefaultWebAssemblyJSRuntime.Instance.InvokeUnmarshalled<string>("Blazor._internal.getApplicationEnvironment");
|
Services.AddSingleton<IWebAssemblyHostEnvironment>(hostEnvironment);
|
||||||
Services.AddSingleton<IWebAssemblyHostEnvironment>(new WebAssemblyHostEnvironment(applicationEnvironment));
|
|
||||||
|
|
||||||
var configFiles = new[]
|
var configFiles = new[]
|
||||||
{
|
{
|
||||||
|
|
@ -86,7 +81,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
|
|
||||||
foreach (var configFile in configFiles)
|
foreach (var configFile in configFiles)
|
||||||
{
|
{
|
||||||
var appSettingsJson = DefaultWebAssemblyJSRuntime.Instance.InvokeUnmarshalled<string, byte[]>(
|
var appSettingsJson = jsRuntime.InvokeUnmarshalled<string, byte[]>(
|
||||||
"Blazor._internal.getConfig",
|
"Blazor._internal.getConfig",
|
||||||
configFile);
|
configFile);
|
||||||
|
|
||||||
|
|
@ -97,6 +92,8 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
Configuration.Add<JsonStreamConfigurationSource>(s => s.Stream = new MemoryStream(appSettingsJson));
|
Configuration.Add<JsonStreamConfigurationSource>(s => s.Stream = new MemoryStream(appSettingsJson));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return hostEnvironment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<InternalsVisibleTo Include="Microsoft.AspNetCore.Components.WebAssembly.Tests" />
|
<InternalsVisibleTo Include="Microsoft.AspNetCore.Components.WebAssembly.Tests" />
|
||||||
|
<InternalsVisibleTo Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication.Tests" />
|
||||||
<InternalsVisibleTo Include="BasicTestApp" />
|
<InternalsVisibleTo Include="BasicTestApp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Components.RenderTree;
|
using Microsoft.AspNetCore.Components.RenderTree;
|
||||||
using Microsoft.AspNetCore.Components.WebAssembly.Services;
|
using Microsoft.AspNetCore.Components.WebAssembly.Services;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.JSInterop.WebAssembly;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.JSInterop.WebAssembly;
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
|
{
|
||||||
|
public class TestWebAssemblyJSRuntime
|
||||||
|
{
|
||||||
|
public static WebAssemblyJSRuntime Create(string environment = "Production")
|
||||||
|
{
|
||||||
|
var jsRuntime = new Mock<WebAssemblyJSRuntime>();
|
||||||
|
jsRuntime.Setup(j => j.InvokeUnmarshalled<object, object, object, string>("Blazor._internal.getApplicationEnvironment", null, null, null))
|
||||||
|
.Returns(environment)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
jsRuntime.Setup(j => j.InvokeUnmarshalled<string, object, object, byte[]>("Blazor._internal.getConfig", It.IsAny<string>(), null, null))
|
||||||
|
.Returns((byte[])null)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
return jsRuntime.Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,14 +3,14 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
using Microsoft.AspNetCore.Components.Routing;
|
using Microsoft.AspNetCore.Components.Routing;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
|
using Microsoft.JSInterop.WebAssembly;
|
||||||
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Build_AllowsConfiguringConfiguration()
|
public void Build_AllowsConfiguringConfiguration()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
builder.Configuration.AddInMemoryCollection(new[]
|
builder.Configuration.AddInMemoryCollection(new[]
|
||||||
{
|
{
|
||||||
|
|
@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Build_AllowsConfiguringServices()
|
public void Build_AllowsConfiguringServices()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
// This test also verifies that we create a scope.
|
// This test also verifies that we create a scope.
|
||||||
builder.Services.AddScoped<StringBuilder>();
|
builder.Services.AddScoped<StringBuilder>();
|
||||||
|
|
@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Build_AllowsConfiguringContainer()
|
public void Build_AllowsConfiguringContainer()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
builder.Services.AddScoped<StringBuilder>();
|
builder.Services.AddScoped<StringBuilder>();
|
||||||
var factory = new MyFakeServiceProviderFactory();
|
var factory = new MyFakeServiceProviderFactory();
|
||||||
|
|
@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Build_AllowsConfiguringContainer_WithDelegate()
|
public void Build_AllowsConfiguringContainer_WithDelegate()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
builder.Services.AddScoped<StringBuilder>();
|
builder.Services.AddScoped<StringBuilder>();
|
||||||
|
|
||||||
|
|
@ -92,6 +92,46 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
Assert.NotNull(host.Services.GetRequiredService<List<string>>());
|
Assert.NotNull(host.Services.GetRequiredService<List<string>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Build_InDevelopment_ConfiguresWithServiceProviderWithScopeValidation()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create(environment: "Development"));
|
||||||
|
|
||||||
|
builder.Services.AddScoped<StringBuilder>();
|
||||||
|
builder.Services.AddSingleton<TestServiceThatTakesStringBuilder>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var host = builder.Build();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(host.Services.GetRequiredService<StringBuilder>());
|
||||||
|
Assert.Throws<InvalidOperationException>(() => host.Services.GetRequiredService<TestServiceThatTakesStringBuilder>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Build_InProduction_ConfiguresWithServiceProviderWithScopeValidation()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
|
builder.Services.AddScoped<StringBuilder>();
|
||||||
|
builder.Services.AddSingleton<TestServiceThatTakesStringBuilder>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var host = builder.Build();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(host.Services.GetRequiredService<StringBuilder>());
|
||||||
|
Assert.NotNull(host.Services.GetRequiredService<TestServiceThatTakesStringBuilder>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestServiceThatTakesStringBuilder
|
||||||
|
{
|
||||||
|
public TestServiceThatTakesStringBuilder(StringBuilder builder) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private class MyFakeDIBuilderThing
|
private class MyFakeDIBuilderThing
|
||||||
{
|
{
|
||||||
public MyFakeDIBuilderThing(IServiceCollection serviceCollection)
|
public MyFakeDIBuilderThing(IServiceCollection serviceCollection)
|
||||||
|
|
@ -125,7 +165,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Build_AddsConfigurationToServices()
|
public void Build_AddsConfigurationToServices()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
builder.Configuration.AddInMemoryCollection(new[]
|
builder.Configuration.AddInMemoryCollection(new[]
|
||||||
{
|
{
|
||||||
|
|
@ -151,6 +191,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
typeof(INavigationInterception),
|
typeof(INavigationInterception),
|
||||||
typeof(ILoggerFactory),
|
typeof(ILoggerFactory),
|
||||||
typeof(ILogger<>),
|
typeof(ILogger<>),
|
||||||
|
typeof(IWebAssemblyHostEnvironment),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +200,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Constructor_AddsDefaultServices()
|
public void Constructor_AddsDefaultServices()
|
||||||
{
|
{
|
||||||
// Arrange & Act
|
// Arrange & Act
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(DefaultServiceTypes.Count, builder.Services.Count);
|
Assert.Equal(DefaultServiceTypes.Count, builder.Services.Count);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public async Task RunAsync_CanExitBasedOnCancellationToken()
|
public async Task RunAsync_CanExitBasedOnCancellationToken()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
|
|
@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public async Task RunAsync_CallingTwiceCausesException()
|
public async Task RunAsync_CallingTwiceCausesException()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
|
|
@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public async Task DisposeAsync_CanDisposeAfterCallingRunAsync()
|
public async Task DisposeAsync_CanDisposeAfterCallingRunAsync()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault();
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
builder.Services.AddSingleton<DisposableService>();
|
builder.Services.AddSingleton<DisposableService>();
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue