From a2a6db2ee3f8569177c2a4c9b436dd5b504674f5 Mon Sep 17 00:00:00 2001 From: Juan Barahona Date: Fri, 14 Aug 2020 05:40:01 -0400 Subject: [PATCH] [Blazor][Fixes #22912] Fix "registration is not supported" never displayed in blazor webassembly authentication (#24862) --- .../src/RemoteAuthenticatorViewCore.cs | 3 +- .../test/RemoteAuthenticatorCoreTests.cs | 113 +++++++++++++++--- 2 files changed, 97 insertions(+), 19 deletions(-) diff --git a/src/Components/WebAssembly/WebAssembly.Authentication/src/RemoteAuthenticatorViewCore.cs b/src/Components/WebAssembly/WebAssembly.Authentication/src/RemoteAuthenticatorViewCore.cs index 6d76fd0247..30763ce44a 100644 --- a/src/Components/WebAssembly/WebAssembly.Authentication/src/RemoteAuthenticatorViewCore.cs +++ b/src/Components/WebAssembly/WebAssembly.Authentication/src/RemoteAuthenticatorViewCore.cs @@ -197,9 +197,8 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication else { Registering ??= LoggingIn; + await RedirectToRegister(); } - - await RedirectToRegister(); break; case RemoteAuthenticationActions.LogOut: await ProcessLogOut(GetReturnUrl(state: null, Navigation.ToAbsoluteUri(ApplicationPaths.LogOutSucceededPath).AbsoluteUri)); diff --git a/src/Components/WebAssembly/WebAssembly.Authentication/test/RemoteAuthenticatorCoreTests.cs b/src/Components/WebAssembly/WebAssembly.Authentication/test/RemoteAuthenticatorCoreTests.cs index 61e44bf3bb..17fbb5c317 100644 --- a/src/Components/WebAssembly/WebAssembly.Authentication/test/RemoteAuthenticatorCoreTests.cs +++ b/src/Components/WebAssembly/WebAssembly.Authentication/test/RemoteAuthenticatorCoreTests.cs @@ -488,39 +488,39 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication public static TheoryData DisplaysRightUIData { get; } = new TheoryData { { new UIValidator { - Action = "login", SetupAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LoggingIn = validator.Render; } } + Action = "login", SetupFakeRenderAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LoggingIn = validator.FakeRender; } } }, { new UIValidator { - Action = "login-callback", SetupAction = (validator, remoteAuthenticator) => { remoteAuthenticator.CompletingLoggingIn = validator.Render; } } + Action = "login-callback", SetupFakeRenderAction = (validator, remoteAuthenticator) => { remoteAuthenticator.CompletingLoggingIn = validator.FakeRender; } } }, { new UIValidator { - Action = "login-failed", SetupAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LogInFailed = m => builder => validator.Render(builder); } } + Action = "login-failed", SetupFakeRenderAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LogInFailed = m => builder => validator.FakeRender(builder); } } }, { new UIValidator { - Action = "profile", SetupAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LoggingIn = validator.Render; } } + Action = "profile", SetupFakeRenderAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LoggingIn = validator.FakeRender; } } }, // Profile fragment overrides { new UIValidator { - Action = "profile", SetupAction = (validator, remoteAuthenticator) => { remoteAuthenticator.UserProfile = validator.Render; } } + Action = "profile", SetupFakeRenderAction = (validator, remoteAuthenticator) => { remoteAuthenticator.UserProfile = validator.FakeRender; } } }, { new UIValidator { - Action = "register", SetupAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LoggingIn = validator.Render; } } + Action = "register", SetupFakeRenderAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LoggingIn = validator.FakeRender; } } }, // Register fragment overrides { new UIValidator { - Action = "register", SetupAction = (validator, remoteAuthenticator) => { remoteAuthenticator.Registering = validator.Render; } } + Action = "register", SetupFakeRenderAction = (validator, remoteAuthenticator) => { remoteAuthenticator.Registering = validator.FakeRender; } } }, { new UIValidator { - Action = "logout", SetupAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LogOut = validator.Render; } } + Action = "logout", SetupFakeRenderAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LogOut = validator.FakeRender; } } }, { new UIValidator { - Action = "logout-callback", SetupAction = (validator, remoteAuthenticator) => { remoteAuthenticator.CompletingLogOut = validator.Render; } } + Action = "logout-callback", SetupFakeRenderAction = (validator, remoteAuthenticator) => { remoteAuthenticator.CompletingLogOut = validator.FakeRender; } } }, { new UIValidator { - Action = "logout-failed", SetupAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LogOutFailed = m => builder => validator.Render(builder); } } + Action = "logout-failed", SetupFakeRenderAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LogOutFailed = m => builder => validator.FakeRender(builder); } } }, { new UIValidator { - Action = "logged-out", SetupAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LogOutSucceeded = validator.Render; } } + Action = "logged-out", SetupFakeRenderAction = (validator, remoteAuthenticator) => { remoteAuthenticator.LogOutSucceeded = validator.FakeRender; } } }, }; @@ -531,8 +531,8 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication // Arrange var renderer = new TestRenderer(new ServiceCollection().BuildServiceProvider()); var authenticator = new TestRemoteAuthenticatorView(); - renderer.Attach(authenticator); - validator.Setup(authenticator); + renderer.Attach(authenticator); + validator.SetupFakeRender(authenticator); var parameters = ParameterView.FromDictionary(new Dictionary { @@ -546,16 +546,89 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication Assert.True(validator.WasCalled); } + [Theory] + [MemberData(nameof(DisplaysRightUIData))] + public async Task AuthenticationManager_DoesNotThrowExceptionOnDisplaysUI_WhenPathsAreMissing(UIValidator validator) + { + // Arrange + var renderer = new TestRenderer(new ServiceCollection().BuildServiceProvider()); + var authenticator = new TestRemoteAuthenticatorView(new RemoteAuthenticationApplicationPathsOptions()); + renderer.Attach(authenticator); + validator.SetupFakeRender(authenticator); + + var parameters = ParameterView.FromDictionary(new Dictionary + { + [_action] = validator.Action + }); + + // Act + Task result = await renderer.Dispatcher.InvokeAsync(() => authenticator.SetParametersAsync(parameters)); + + + // Assert + Assert.Null(result.Exception); + } + + public static TheoryData DisplaysRightUIWhenPathsAreMissingData { get; } = new TheoryData + { + // Profile fragment overrides + { + new UIValidator { + Action = "profile", + SetupFakeRenderAction = (validator, remoteAuthenticator) => { remoteAuthenticator.UserProfile = validator.FakeRender; }, + RetrieveOriginalRenderAction = (validator, remoteAuthenticator) => { validator.OriginalRender = remoteAuthenticator.UserProfile; } }, + "ProfileNotSupportedFragment" + }, + { + new UIValidator { + Action = "register", + SetupFakeRenderAction = (validator, remoteAuthenticator) => { remoteAuthenticator.Registering = validator.FakeRender; }, + RetrieveOriginalRenderAction = (validator, remoteAuthenticator) => { validator.OriginalRender = remoteAuthenticator.Registering; } }, + "RegisterNotSupportedFragment" + } + }; + + [Theory] + [MemberData(nameof(DisplaysRightUIWhenPathsAreMissingData))] + public async Task AuthenticationManager_DisplaysRightUI_WhenPathsAreMissing(UIValidator validator, string methodName) + { + // Arrange + var renderer = new TestRenderer(new ServiceCollection().BuildServiceProvider()); + var jsRuntime = new TestJsRuntime(); + var authenticator = new TestRemoteAuthenticatorView(new RemoteAuthenticationApplicationPathsOptions(), jsRuntime); + renderer.Attach(authenticator); + + var parameters = ParameterView.FromDictionary(new Dictionary + { + [_action] = validator.Action + }); + + // Act + await renderer.Dispatcher.InvokeAsync(() => authenticator.SetParametersAsync(parameters)); + validator.RetrieveOriginalRender(authenticator); + validator.SetupFakeRender(authenticator); + Task result = await renderer.Dispatcher.InvokeAsync(() => authenticator.SetParametersAsync(parameters)); + + + // Assert + Assert.True(validator.WasCalled); + Assert.Equal(methodName, validator.OriginalRender.Method.Name); + Assert.Equal(default, jsRuntime.LastInvocation); + } + public class UIValidator { public string Action { get; set; } - public Action> SetupAction { get; set; } + public Action> SetupFakeRenderAction { get; set; } + public Action> RetrieveOriginalRenderAction { get; set; } public bool WasCalled { get; set; } - public RenderFragment Render { get; set; } + public RenderFragment OriginalRender { get; set; } + public RenderFragment FakeRender { get; set; } - public UIValidator() => Render = builder => WasCalled = true; + public UIValidator() => FakeRender = builder => WasCalled = true; - internal void Setup(TestRemoteAuthenticatorView manager) => SetupAction(this, manager); + internal void SetupFakeRender(TestRemoteAuthenticatorView manager) => SetupFakeRenderAction(this, manager); + internal void RetrieveOriginalRender(TestRemoteAuthenticatorView manager) => RetrieveOriginalRenderAction(this, manager); } private static @@ -646,6 +719,12 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication }; } + public TestRemoteAuthenticatorView(RemoteAuthenticationApplicationPathsOptions applicationPaths, IJSRuntime jsRuntime = default) + { + ApplicationPaths = applicationPaths; + JS = jsRuntime; + } + protected override Task OnParametersSetAsync() { if (Action == "register" || Action == "profile")