/
githubmirror
/
aspnetcore
Обзор
Документация
Войти
/
githubmirror
/
aspnetcore
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Components/Authorization/test/CascadingAuthenticationStateTest.cs
202 строки
8 KB
Mackinnon Buck
Introduce 'RenderTreeBuilder.AddComponentParameter()' (#46562)
23 фев 2023, 00:40
Не верифицирован
23 фев 2023, 00:40
33e7a9a
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Security.Claims; using System.Security.Principal; using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.Test.Helpers; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Components.Authorization; public class CascadingAuthenticationStateTest { [Fact] public void RequiresRegisteredService() { // Arrange var renderer = new TestRenderer(); var component = new AutoRenderFragmentComponent(builder => { builder.OpenComponent<CascadingAuthenticationState>(0); builder.CloseComponent(); }); // Act/Assert renderer.AssignRootComponentId(component); var ex = Assert.Throws<InvalidOperationException>(() => component.TriggerRender()); Assert.Contains($"There is no registered service of type '{typeof(AuthenticationStateProvider).FullName}'.", ex.Message); } [Fact] public void SuppliesSynchronouslyAvailableAuthStateToChildContent() { // Arrange: Service var services = new ServiceCollection(); var authStateProvider = new TestAuthenticationStateProvider() { CurrentAuthStateTask = Task.FromResult(CreateAuthenticationState("Bert")) }; services.AddSingleton<AuthenticationStateProvider>(authStateProvider); // Arrange: Renderer and component var renderer = new TestRenderer(services.BuildServiceProvider()); var component = new UseCascadingAuthenticationStateComponent(); // Act renderer.AssignRootComponentId(component); component.TriggerRender(); // Assert var batch = renderer.Batches.Single(); var receiveAuthStateId = batch.GetComponentFrames<ReceiveAuthStateComponent>().Single().ComponentId; var receiveAuthStateDiff = batch.DiffsByComponentId[receiveAuthStateId].Single(); Assert.Collection(receiveAuthStateDiff.Edits, edit => { Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); AssertFrame.Text( batch.ReferenceFrames[edit.ReferenceFrameIndex], "Authenticated: True; Name: Bert; Pending: False; Renders: 1"); }); } [Fact] public void SuppliesAsynchronouslyAvailableAuthStateToChildContent() { // Arrange: Service var services = new ServiceCollection(); var authStateTaskCompletionSource = new TaskCompletionSource<AuthenticationState>(); var authStateProvider = new TestAuthenticationStateProvider() { CurrentAuthStateTask = authStateTaskCompletionSource.Task }; services.AddSingleton<AuthenticationStateProvider>(authStateProvider); // Arrange: Renderer and component var renderer = new TestRenderer(services.BuildServiceProvider()); var component = new UseCascadingAuthenticationStateComponent(); // Act 1: Initial synchronous render renderer.AssignRootComponentId(component); component.TriggerRender(); // Assert 1: Empty state var batch1 = renderer.Batches.Single(); var receiveAuthStateFrame = batch1.GetComponentFrames<ReceiveAuthStateComponent>().Single(); var receiveAuthStateId = receiveAuthStateFrame.ComponentId; var receiveAuthStateComponent = (ReceiveAuthStateComponent)receiveAuthStateFrame.Component; var receiveAuthStateDiff1 = batch1.DiffsByComponentId[receiveAuthStateId].Single(); Assert.Collection(receiveAuthStateDiff1.Edits, edit => { Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); AssertFrame.Text( batch1.ReferenceFrames[edit.ReferenceFrameIndex], "Authenticated: False; Name: ; Pending: True; Renders: 1"); }); // Act/Assert 2: Auth state fetch task completes in background // No new renders yet, because the cascading parameter itself hasn't changed authStateTaskCompletionSource.SetResult(CreateAuthenticationState("Bert")); Assert.Single(renderer.Batches); // Act/Assert 3: Refresh display receiveAuthStateComponent.TriggerRender(); Assert.Equal(2, renderer.Batches.Count); var batch2 = renderer.Batches.Last(); var receiveAuthStateDiff2 = batch2.DiffsByComponentId[receiveAuthStateId].Single(); Assert.Collection(receiveAuthStateDiff2.Edits, edit => { Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); AssertFrame.Text( batch2.ReferenceFrames[edit.ReferenceFrameIndex], "Authenticated: True; Name: Bert; Pending: False; Renders: 2"); }); } [Fact] public void RespondsToNotificationsFromAuthenticationStateProvider() { // Arrange: Service var services = new ServiceCollection(); var authStateProvider = new TestAuthenticationStateProvider() { CurrentAuthStateTask = Task.FromResult(CreateAuthenticationState(null)) }; services.AddSingleton<AuthenticationStateProvider>(authStateProvider); // Arrange: Renderer and component, initially rendered var renderer = new TestRenderer(services.BuildServiceProvider()); var component = new UseCascadingAuthenticationStateComponent(); renderer.AssignRootComponentId(component); component.TriggerRender(); var receiveAuthStateId = renderer.Batches.Single() .GetComponentFrames<ReceiveAuthStateComponent>().Single().ComponentId; // Act 2: AuthenticationStateProvider issues notification authStateProvider.TriggerAuthenticationStateChanged( Task.FromResult(CreateAuthenticationState("Bert"))); // Assert 2: Re-renders content Assert.Equal(2, renderer.Batches.Count); var batch = renderer.Batches.Last(); var receiveAuthStateDiff = batch.DiffsByComponentId[receiveAuthStateId].Single(); Assert.Collection(receiveAuthStateDiff.Edits, edit => { Assert.Equal(RenderTreeEditType.UpdateText, edit.Type); AssertFrame.Text( batch.ReferenceFrames[edit.ReferenceFrameIndex], "Authenticated: True; Name: Bert; Pending: False; Renders: 2"); }); } class ReceiveAuthStateComponent : AutoRenderComponent { int numRenders; [CascadingParameter] Task<AuthenticationState> AuthStateTask { get; set; } protected override void BuildRenderTree(RenderTreeBuilder builder) { numRenders++; if (AuthStateTask.IsCompleted) { var identity = AuthStateTask.Result.User.Identity; builder.AddContent(0, $"Authenticated: {identity.IsAuthenticated}; Name: {identity.Name}; Pending: False; Renders: {numRenders}"); } else { builder.AddContent(0, $"Authenticated: False; Name: ; Pending: True; Renders: {numRenders}"); } } } class UseCascadingAuthenticationStateComponent : AutoRenderComponent { protected override void BuildRenderTree(RenderTreeBuilder builder) { builder.OpenComponent<CascadingAuthenticationState>(0); builder.AddComponentParameter(1, "ChildContent", new RenderFragment(childBuilder => { childBuilder.OpenComponent<ReceiveAuthStateComponent>(0); childBuilder.CloseComponent(); })); builder.CloseComponent(); } } public static AuthenticationState CreateAuthenticationState(string username) => new AuthenticationState(new ClaimsPrincipal(username == null ? new ClaimsIdentity() : (IIdentity)new TestIdentity { Name = username })); class TestIdentity : IIdentity { public string AuthenticationType => "Test"; public bool IsAuthenticated => true; public string Name { get; set; } } }