From 6390c454d0b0d420f78fe178b6accf77dfe207d4 Mon Sep 17 00:00:00 2001 From: Mikhail Shabanov Date: Mon, 30 Aug 2021 18:06:29 +0200 Subject: [PATCH] feat: added login/out buttons to nav menu and index page --- .../Pages/MainLayoutTest.cs | 6 + .../Pages/NavMenuAndIndexPageTests.cs | 116 ++++++++++++++++++ .../Messages/LogOutFromWgMessage.cs | 8 ++ .../Pages/Index.razor | 34 ++++- .../Resources/App.de.resx | 3 + .../Resources/App.ru.resx | 3 + .../Shared/NavMenu.razor | 10 +- .../Shared/NavMenuBase.cs | 16 +++ 8 files changed, 190 insertions(+), 6 deletions(-) create mode 100644 WotBlitzStatisticsPro.Blazor/Messages/LogOutFromWgMessage.cs diff --git a/WotBlitzStatisticsPro.Blazor.Tests/Pages/MainLayoutTest.cs b/WotBlitzStatisticsPro.Blazor.Tests/Pages/MainLayoutTest.cs index 1ebfe35..f53af5f 100644 --- a/WotBlitzStatisticsPro.Blazor.Tests/Pages/MainLayoutTest.cs +++ b/WotBlitzStatisticsPro.Blazor.Tests/Pages/MainLayoutTest.cs @@ -1,22 +1,28 @@ using System.Threading; using Bunit; using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; using Moq; using NUnit.Framework; using Radzen; using WotBlitzStatisticsPro.Blazor.Messages; using WotBlitzStatisticsPro.Blazor.Model; +using WotBlitzStatisticsPro.Blazor.Services; using WotBlitzStatisticsPro.Blazor.Shared; namespace WotBlitzStatisticsPro.Blazor.Tests.Pages { public class MainLayoutTest : TestContextBase { + private Mock _localStorageServiceMock; private IRenderedComponent _component; [SetUp] public void Setup() { + _localStorageServiceMock = new(); + TestContext?.Services.AddSingleton(_localStorageServiceMock.Object); + _component = TestContext?.RenderComponent(); } diff --git a/WotBlitzStatisticsPro.Blazor.Tests/Pages/NavMenuAndIndexPageTests.cs b/WotBlitzStatisticsPro.Blazor.Tests/Pages/NavMenuAndIndexPageTests.cs index 1b8c2f4..a53e695 100644 --- a/WotBlitzStatisticsPro.Blazor.Tests/Pages/NavMenuAndIndexPageTests.cs +++ b/WotBlitzStatisticsPro.Blazor.Tests/Pages/NavMenuAndIndexPageTests.cs @@ -3,10 +3,12 @@ using System.Threading; using AngleSharp.Dom; using Bunit; using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; using Moq; using NUnit.Framework; using WotBlitzStatisticsPro.Blazor.Messages; using WotBlitzStatisticsPro.Blazor.Model; +using WotBlitzStatisticsPro.Blazor.Services; using WotBlitzStatisticsPro.Blazor.Shared; using Index = WotBlitzStatisticsPro.Blazor.Pages.Index; @@ -25,10 +27,17 @@ namespace WotBlitzStatisticsPro.Blazor.Tests.Pages private IRenderedComponent _indexComponent; private IRefreshableElementCollection _indexButtons; + private LoginInfo _loginInfo; + private Mock _localStorageServiceMock; [SetUp] public void Setup() { + _loginInfo = new LoginInfo { NickName = "Fake_Nick", AccountId = 123456789 }; + _localStorageServiceMock = new(); + + TestContext?.Services.AddSingleton(_localStorageServiceMock.Object); + _navMenuComponent = TestContext?.RenderComponent(); _indexComponent = TestContext?.RenderComponent(); @@ -104,5 +113,112 @@ namespace WotBlitzStatisticsPro.Blazor.Tests.Pages } + [TestCase(ComponentType.NavMenu)] + [TestCase(ComponentType.Index)] + public void ShouldShowLoginItemAndHideNickIfLoginInfoIsMissing(ComponentType componentType) + { + switch (componentType) + { + case ComponentType.NavMenu: + _navMenuElements.Should().Contain(e => e.InnerHtml.Contains("Login with WG.net ID")); + _navMenuElements.Should().NotContain(e => e.InnerHtml.Contains(_loginInfo.NickName)); + _navMenuElements.Should().NotContain(e => e.InnerHtml.Contains("Log out")); + break; + case ComponentType.Index: + _indexButtons.Should().Contain(e => e.InnerHtml.Contains("Login with WG.net ID")); + _indexButtons.Should().NotContain(e => e.InnerHtml.Contains(_loginInfo.NickName)); + _indexButtons.Should().NotContain(e => e.InnerHtml.Contains("Log out")); + break; + } + } + + [TestCase(ComponentType.NavMenu)] + [TestCase(ComponentType.Index)] + public void ShouldShowNickItemAndHideLoginIfLoginInfoIsPresent(ComponentType componentType) + { + _localStorageServiceMock.Setup(s => s.GetItemAsync(It.IsAny())).ReturnsAsync(_loginInfo); + + switch (componentType) + { + case ComponentType.NavMenu: + var navMenuComponent = TestContext?.RenderComponent(); + var navMenuElements = navMenuComponent?.FindAll(".rz-navigation-item"); + navMenuElements.Should().NotBeNull(); + navMenuElements.Count.Should().Be(5); + navMenuElements.Should().NotContain(e => e.InnerHtml.Contains("Login with WG.net ID")); + navMenuElements.Should().Contain(e => e.InnerHtml.Contains(_loginInfo.NickName)); + navMenuElements.Should().Contain(e => e.InnerHtml.Contains("Log out")); + break; + case ComponentType.Index: + var indexComponent = TestContext?.RenderComponent(); + var indexButtons = indexComponent?.FindAll(".rz-button"); + indexButtons.Should().NotBeNull(); + indexButtons.Count.Should().Be(4); + indexButtons.Should().NotContain(e => e.InnerHtml.Contains("Login with WG.net ID")); + indexButtons.Should().Contain(e => e.InnerHtml.Contains(_loginInfo.NickName)); + indexButtons.Should().Contain(e => e.InnerHtml.Contains("Log out")); + break; + } + } + + [TestCase(ComponentType.NavMenu)] + [TestCase(ComponentType.Index)] + public void ShouldFireOpenPlayerMessageWhenNickItemClicked(ComponentType componentType) + { + _localStorageServiceMock.Setup(s => s.GetItemAsync(It.IsAny())).ReturnsAsync(_loginInfo); + + IElement targetElement = null; + + switch (componentType) + { + case ComponentType.NavMenu: + var navMenuComponent = TestContext?.RenderComponent(); + var navMenuElements = navMenuComponent?.FindAll(".rz-navigation-item"); + targetElement = navMenuElements[1]; + break; + case ComponentType.Index: + var indexComponent = TestContext?.RenderComponent(); + var indexButtons = indexComponent?.FindAll(".rz-button"); + targetElement = indexButtons[0]; + + break; + } + + targetElement?.Click(); + + MediatorMock.Verify(m => m.Publish( + It.Is(m => m.AccountId == _loginInfo.AccountId && m.IsLoggedIn), + It.IsAny()), Times.Once); + } + + [TestCase(ComponentType.NavMenu)] + [TestCase(ComponentType.Index)] + public void ShouldFireLoGoutMessageIfLogOutItemClicked(ComponentType componentType) + { + _localStorageServiceMock.Setup(s => s.GetItemAsync(It.IsAny())).ReturnsAsync(_loginInfo); + + IElement targetElement = null; + + switch (componentType) + { + case ComponentType.NavMenu: + var navMenuComponent = TestContext?.RenderComponent(); + var navMenuElements = navMenuComponent?.FindAll(".rz-navigation-item"); + targetElement = navMenuElements[2]; + break; + case ComponentType.Index: + var indexComponent = TestContext?.RenderComponent(); + var indexButtons = indexComponent?.FindAll(".rz-button"); + targetElement = indexButtons[1]; + + break; + } + + targetElement?.Click(); + + MediatorMock.Verify(m => m.Publish( + It.IsAny(), + It.IsAny()), Times.Once); + } } } \ No newline at end of file diff --git a/WotBlitzStatisticsPro.Blazor/Messages/LogOutFromWgMessage.cs b/WotBlitzStatisticsPro.Blazor/Messages/LogOutFromWgMessage.cs new file mode 100644 index 0000000..730f09d --- /dev/null +++ b/WotBlitzStatisticsPro.Blazor/Messages/LogOutFromWgMessage.cs @@ -0,0 +1,8 @@ +using MediatR; + +namespace WotBlitzStatisticsPro.Blazor.Messages +{ + public class LogOutFromWgMessage: INotification + { + } +} diff --git a/WotBlitzStatisticsPro.Blazor/Pages/Index.razor b/WotBlitzStatisticsPro.Blazor/Pages/Index.razor index 2de3222..2d7323d 100644 --- a/WotBlitzStatisticsPro.Blazor/Pages/Index.razor +++ b/WotBlitzStatisticsPro.Blazor/Pages/Index.razor @@ -2,16 +2,31 @@ @using MediatR @using WotBlitzStatisticsPro.Blazor.Messages @using WotBlitzStatisticsPro.Blazor.Model +@using WotBlitzStatisticsPro.Blazor.Services @inject IStringLocalizer Localize @inject IMediator Mediator +@inject ILocalStorageService LocalStorage
- - { await Mediator.Publish(new LoginToWgMessage()); }) - Icon="vpn_key" - Text=@Localize["Login with WG.net ID"] - Style="width: 300px; margin: 30px" /> + @if(LoginInfo != null) + { + { await Mediator.Publish(new OpenPlayerInfoMessage(LoginInfo.AccountId, true)); }) + Icon="person" + Text=@LoginInfo.NickName + Style="width: 300px; margin: 30px" /> + { await Mediator.Publish(new LogOutFromWgMessage()); }) + Icon="logout" + Text=@Localize["Log out"] + Style="width: 300px; margin: 30px" /> + } + else + { + { await Mediator.Publish(new LoginToWgMessage()); }) + Icon="vpn_key" + Text=@Localize["Login with WG.net ID"] + Style="width: 300px; margin: 30px" /> + } { await Mediator.Publish(new OpenSearchDialogMessage(DialogType.FindPlayer)); }) Icon="person_search" Text=@Localize["Search player"] @@ -24,3 +39,12 @@
+@code { + public LoginInfo? LoginInfo { get; set; } + + protected override async Task OnInitializedAsync() + { + LoginInfo = await LocalStorage.GetItemAsync(Constants.LoginInfoLocalStorageKey); + } +} + diff --git a/WotBlitzStatisticsPro.Blazor/Resources/App.de.resx b/WotBlitzStatisticsPro.Blazor/Resources/App.de.resx index a9e4df6..74ac7ee 100644 --- a/WotBlitzStatisticsPro.Blazor/Resources/App.de.resx +++ b/WotBlitzStatisticsPro.Blazor/Resources/App.de.resx @@ -177,6 +177,9 @@ Letzte Gefecht + + Abmelden + Anmelden mit WG.net-ID diff --git a/WotBlitzStatisticsPro.Blazor/Resources/App.ru.resx b/WotBlitzStatisticsPro.Blazor/Resources/App.ru.resx index 50b820a..666ee5e 100644 --- a/WotBlitzStatisticsPro.Blazor/Resources/App.ru.resx +++ b/WotBlitzStatisticsPro.Blazor/Resources/App.ru.resx @@ -177,6 +177,9 @@ Последний бой + + Выйти + Войти с WG.net ID diff --git a/WotBlitzStatisticsPro.Blazor/Shared/NavMenu.razor b/WotBlitzStatisticsPro.Blazor/Shared/NavMenu.razor index 0014acd..8e4805c 100644 --- a/WotBlitzStatisticsPro.Blazor/Shared/NavMenu.razor +++ b/WotBlitzStatisticsPro.Blazor/Shared/NavMenu.razor @@ -4,7 +4,15 @@
- + @if(LoginInfo != null) + { + + + } + else + { + + } diff --git a/WotBlitzStatisticsPro.Blazor/Shared/NavMenuBase.cs b/WotBlitzStatisticsPro.Blazor/Shared/NavMenuBase.cs index 02ab994..8a9daa6 100644 --- a/WotBlitzStatisticsPro.Blazor/Shared/NavMenuBase.cs +++ b/WotBlitzStatisticsPro.Blazor/Shared/NavMenuBase.cs @@ -23,10 +23,20 @@ namespace WotBlitzStatisticsPro.Blazor.Shared [Inject] private IStringLocalizer Localizer { get; set; } + [Inject] + public ILocalStorageService LocalStorage { get; set; } + [Parameter] public EventCallback CloseSideBar { get; set; } + public LoginInfo? LoginInfo { get; set; } + + protected override async Task OnInitializedAsync() + { + LoginInfo = await LocalStorage.GetItemAsync(Constants.LoginInfoLocalStorageKey); + } + public async Task MenuClicked(MenuItemEventArgs menuItem) { await CloseSideBar.InvokeAsync(); @@ -38,6 +48,9 @@ namespace WotBlitzStatisticsPro.Blazor.Shared case var _ when (Localizer.GetString("Login with WG.net ID")) == menuItem.Text: await Mediator.Publish(new LoginToWgMessage()); break; + case var _ when (Localizer.GetString("Log out")) == menuItem.Text: + await Mediator.Publish(new LogOutFromWgMessage()); + break; case var _ when (Localizer.GetString("Search player")) == menuItem.Text: await Mediator.Publish(new OpenSearchDialogMessage(DialogType.FindPlayer)); //await SearchDialogService.OpenSearchDialog(DialogType.FindPlayer); @@ -45,6 +58,9 @@ namespace WotBlitzStatisticsPro.Blazor.Shared case var _ when (Localizer.GetString("Search clan")) == menuItem.Text: await Mediator.Publish(new OpenSearchDialogMessage(DialogType.FindClan)); break; + case var _ when (LoginInfo?.NickName) == menuItem.Text: + await Mediator.Publish(new OpenPlayerInfoMessage(LoginInfo.AccountId, true)); + break; } } }