From 87ae6c618c74a96c7f053cc4762944bc8ad89f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Michel?= Date: Tue, 25 Jan 2022 16:50:15 +0100 Subject: [PATCH] fix some issue and cover by test (#669) --- .../Identity/Pages/Account/Login.cshtml.cs | 8 +- src/Web/Controllers/ManageController.cs | 5 +- src/Web/Controllers/OrderController.cs | 3 +- src/Web/Pages/Basket/BasketItemViewModel.cs | 2 +- src/Web/Pages/Basket/Checkout.cshtml.cs | 8 +- src/Web/ViewModels/Manage/IndexViewModel.cs | 4 +- src/Web/Web.csproj | 2 +- .../Controllers/AccountControllerSignIn.cs | 67 ++++++++---- .../Pages/{ => Basket}/BasketPageCheckout.cs | 39 ++----- .../Web/Pages/Basket/CheckoutTest.cs | 68 ++++++++++++ .../Web/Pages/Basket/IndexTest.cs | 100 ++++++++++++++++++ tests/FunctionalTests/Web/WebPageHelpers.cs | 27 +++++ .../AuthEndpoints/AuthenticateEndpointTest.cs | 13 ++- tests/UnitTests/UnitTests.csproj | 3 + 14 files changed, 268 insertions(+), 81 deletions(-) rename tests/FunctionalTests/Web/Pages/{ => Basket}/BasketPageCheckout.cs (51%) create mode 100644 tests/FunctionalTests/Web/Pages/Basket/CheckoutTest.cs create mode 100644 tests/FunctionalTests/Web/Pages/Basket/IndexTest.cs create mode 100644 tests/FunctionalTests/Web/WebPageHelpers.cs diff --git a/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs b/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs index eed08342e..afd0bcd04 100644 --- a/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs +++ b/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs @@ -1,17 +1,11 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; +using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.eShopWeb.ApplicationCore.Interfaces; using Microsoft.eShopWeb.Infrastructure.Identity; -using Microsoft.Extensions.Logging; namespace Microsoft.eShopWeb.Web.Areas.Identity.Pages.Account; diff --git a/src/Web/Controllers/ManageController.cs b/src/Web/Controllers/ManageController.cs index 90be6a9a8..4f0604ee0 100644 --- a/src/Web/Controllers/ManageController.cs +++ b/src/Web/Controllers/ManageController.cs @@ -1,8 +1,5 @@ -using System; -using System.Linq; -using System.Text; +using System.Text; using System.Text.Encodings.Web; -using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; diff --git a/src/Web/Controllers/OrderController.cs b/src/Web/Controllers/OrderController.cs index ce6d6d01a..f8e409398 100644 --- a/src/Web/Controllers/OrderController.cs +++ b/src/Web/Controllers/OrderController.cs @@ -1,5 +1,4 @@ -using System.Threading.Tasks; -using MediatR; +using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.eShopWeb.Web.Features.MyOrders; diff --git a/src/Web/Pages/Basket/BasketItemViewModel.cs b/src/Web/Pages/Basket/BasketItemViewModel.cs index c102dfb9b..8c3a142f2 100644 --- a/src/Web/Pages/Basket/BasketItemViewModel.cs +++ b/src/Web/Pages/Basket/BasketItemViewModel.cs @@ -12,6 +12,6 @@ public class BasketItemViewModel [Range(0, int.MaxValue, ErrorMessage = "Quantity must be bigger than 0")] public int Quantity { get; set; } - + public string? PictureUrl { get; set; } } diff --git a/src/Web/Pages/Basket/Checkout.cshtml.cs b/src/Web/Pages/Basket/Checkout.cshtml.cs index be616891b..90f6a92fc 100644 --- a/src/Web/Pages/Basket/Checkout.cshtml.cs +++ b/src/Web/Pages/Basket/Checkout.cshtml.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; diff --git a/src/Web/ViewModels/Manage/IndexViewModel.cs b/src/Web/ViewModels/Manage/IndexViewModel.cs index 6be255394..fc00b3f7d 100644 --- a/src/Web/ViewModels/Manage/IndexViewModel.cs +++ b/src/Web/ViewModels/Manage/IndexViewModel.cs @@ -4,7 +4,7 @@ namespace Microsoft.eShopWeb.Web.ViewModels.Manage; public class IndexViewModel { - public string Username { get; set; } + public string? Username { get; set; } public bool IsEmailConfirmed { get; set; } @@ -16,5 +16,5 @@ public class IndexViewModel [Display(Name = "Phone number")] public string PhoneNumber { get; set; } - public string StatusMessage { get; set; } + public string? StatusMessage { get; set; } } diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index f69f30eec..98225adb1 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -2,7 +2,7 @@ net6.0 - disable + enable enable Microsoft.eShopWeb.Web aspnet-Web2-1FA3F72E-E7E3-4360-9E49-1CCCD7FE85F7 diff --git a/tests/FunctionalTests/Web/Controllers/AccountControllerSignIn.cs b/tests/FunctionalTests/Web/Controllers/AccountControllerSignIn.cs index 37d8a1a98..3375c94be 100644 --- a/tests/FunctionalTests/Web/Controllers/AccountControllerSignIn.cs +++ b/tests/FunctionalTests/Web/Controllers/AccountControllerSignIn.cs @@ -1,10 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Http; +using System.Net; using System.Text.RegularExpressions; -using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Testing; using Xunit; @@ -54,35 +49,65 @@ public async Task ReturnsFormWithRequestVerificationToken() response.EnsureSuccessStatusCode(); var stringResponse = await response.Content.ReadAsStringAsync(); - string token = GetRequestVerificationToken(stringResponse); + string token = WebPageHelpers.GetRequestVerificationToken(stringResponse); Assert.True(token.Length > 50); } - private string GetRequestVerificationToken(string input) - { - string regexpression = @"name=""__RequestVerificationToken"" type=""hidden"" value=""([-A-Za-z0-9+=/\\_]+?)"""; - var regex = new Regex(regexpression); - var match = regex.Match(input); - return match.Groups.Values.LastOrDefault().Value; - } - [Fact] public async Task ReturnsSuccessfulSignInOnPostWithValidCredentials() { var getResponse = await Client.GetAsync("/identity/account/login"); getResponse.EnsureSuccessStatusCode(); var stringResponse1 = await getResponse.Content.ReadAsStringAsync(); - string token = GetRequestVerificationToken(stringResponse1); - var keyValues = new List>(); - keyValues.Add(new KeyValuePair("Email", "demouser@microsoft.com")); - keyValues.Add(new KeyValuePair("Password", "Pass@word1")); - - keyValues.Add(new KeyValuePair("__RequestVerificationToken", token)); + var keyValues = new List> + { + new KeyValuePair("Email", "demouser@microsoft.com"), + new KeyValuePair("Password", "Pass@word1"), + new KeyValuePair(WebPageHelpers.TokenTag, WebPageHelpers.GetRequestVerificationToken(stringResponse1)) + }; var formContent = new FormUrlEncodedContent(keyValues); var postResponse = await Client.PostAsync("/identity/account/login", formContent); Assert.Equal(HttpStatusCode.Redirect, postResponse.StatusCode); Assert.Equal(new System.Uri("/", UriKind.Relative), postResponse.Headers.Location); } + + [Fact] + public async Task UpdatePhoneNumberProfile() + { + //Login + var getResponse = await Client.GetAsync("/identity/account/login"); + getResponse.EnsureSuccessStatusCode(); + var stringResponse1 = await getResponse.Content.ReadAsStringAsync(); + var keyValues = new List> + { + new KeyValuePair("Email", "demouser@microsoft.com"), + new KeyValuePair("Password", "Pass@word1"), + new KeyValuePair(WebPageHelpers.TokenTag, WebPageHelpers.GetRequestVerificationToken(stringResponse1)) + }; + var formContent = new FormUrlEncodedContent(keyValues); + await Client.PostAsync("/identity/account/login", formContent); + + //Profile page + var profileResponse = await Client.GetAsync("/manage/my-account"); + profileResponse.EnsureSuccessStatusCode(); + var stringProfileResponse = await profileResponse.Content.ReadAsStringAsync(); + + //Update phone number + var updateProfileValues = new List> + { + new KeyValuePair("Email", "demouser@microsoft.com"), + new KeyValuePair("PhoneNumber", "03656565"), + new KeyValuePair(WebPageHelpers.TokenTag, WebPageHelpers.GetRequestVerificationToken(stringProfileResponse)) + }; + var updateProfileContent = new FormUrlEncodedContent(updateProfileValues); + var postProfileResponse = await Client.PostAsync("/manage/my-account", updateProfileContent); + + Assert.Equal(HttpStatusCode.Redirect, postProfileResponse.StatusCode); + var profileResponse2 = await Client.GetAsync("/manage/my-account"); + var stringProfileResponse2 = await profileResponse2.Content.ReadAsStringAsync(); + Assert.Contains("03656565", stringProfileResponse2); + + } } diff --git a/tests/FunctionalTests/Web/Pages/BasketPageCheckout.cs b/tests/FunctionalTests/Web/Pages/Basket/BasketPageCheckout.cs similarity index 51% rename from tests/FunctionalTests/Web/Pages/BasketPageCheckout.cs rename to tests/FunctionalTests/Web/Pages/Basket/BasketPageCheckout.cs index 202334618..dd19a714c 100644 --- a/tests/FunctionalTests/Web/Pages/BasketPageCheckout.cs +++ b/tests/FunctionalTests/Web/Pages/Basket/BasketPageCheckout.cs @@ -1,13 +1,7 @@ -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc.Testing; -using Microsoft.eShopWeb.FunctionalTests.Web; +using Microsoft.AspNetCore.Mvc.Testing; using Xunit; -namespace Microsoft.eShopWeb.FunctionalTests.WebRazorPages; +namespace Microsoft.eShopWeb.FunctionalTests.Web.Pages.Basket; [Collection("Sequential")] public class BasketPageCheckout : IClassFixture @@ -22,45 +16,32 @@ public BasketPageCheckout(TestApplication factory) public HttpClient Client { get; } - private string GetRequestVerificationToken(string input) - { - string regexpression = @"name=""__RequestVerificationToken"" type=""hidden"" value=""([-A-Za-z0-9+=/\\_]+?)"""; - var regex = new Regex(regexpression); - var match = regex.Match(input); - return match.Groups.Values.LastOrDefault().Value; - } - [Fact] public async Task RedirectsToLoginIfNotAuthenticated() { - // Arrange & Act // Load Home Page var response = await Client.GetAsync("/"); response.EnsureSuccessStatusCode(); var stringResponse1 = await response.Content.ReadAsStringAsync(); - string token = GetRequestVerificationToken(stringResponse1); + string token = WebPageHelpers.GetRequestVerificationToken(stringResponse1); // Add Item to Cart - var keyValues = new List>(); - keyValues.Add(new KeyValuePair("id", "2")); - keyValues.Add(new KeyValuePair("name", "shirt")); - - keyValues.Add(new KeyValuePair("price", "19.49")); - keyValues.Add(new KeyValuePair("__RequestVerificationToken", token)); - + var keyValues = new List> + { + new KeyValuePair("id", "2"), + new KeyValuePair("name", "shirt"), + new KeyValuePair("price", "19.49"), + new KeyValuePair("__RequestVerificationToken", token) + }; var formContent = new FormUrlEncodedContent(keyValues); - var postResponse = await Client.PostAsync("/basket/index", formContent); postResponse.EnsureSuccessStatusCode(); var stringResponse = await postResponse.Content.ReadAsStringAsync(); - - // Assert Assert.Contains(".NET Black & White Mug", stringResponse); keyValues.Clear(); - keyValues.Add(new KeyValuePair("__RequestVerificationToken", token)); formContent = new FormUrlEncodedContent(keyValues); var postResponse2 = await Client.PostAsync("/Basket/Checkout", formContent); diff --git a/tests/FunctionalTests/Web/Pages/Basket/CheckoutTest.cs b/tests/FunctionalTests/Web/Pages/Basket/CheckoutTest.cs new file mode 100644 index 000000000..4657d77d3 --- /dev/null +++ b/tests/FunctionalTests/Web/Pages/Basket/CheckoutTest.cs @@ -0,0 +1,68 @@ +using Microsoft.AspNetCore.Mvc.Testing; +using Xunit; + +namespace Microsoft.eShopWeb.FunctionalTests.Web.Pages.Basket; + +[Collection("Sequential")] +public class CheckoutTest : IClassFixture +{ + public CheckoutTest(TestApplication factory) + { + Client = factory.CreateClient(new WebApplicationFactoryClientOptions + { + AllowAutoRedirect = true + }); + } + + public HttpClient Client { get; } + + [Fact] + public async Task SucessfullyPay() + { + + // Load Home Page + var response = await Client.GetAsync("/"); + response.EnsureSuccessStatusCode(); + var stringResponse = await response.Content.ReadAsStringAsync(); + + // Add Item to Cart + var keyValues = new List> + { + new KeyValuePair("id", "2"), + new KeyValuePair("name", "shirt"), + new KeyValuePair("price", "19.49"), + new KeyValuePair(WebPageHelpers.TokenTag, WebPageHelpers.GetRequestVerificationToken(stringResponse)) + }; + var formContent = new FormUrlEncodedContent(keyValues); + var postResponse = await Client.PostAsync("/basket/index", formContent); + postResponse.EnsureSuccessStatusCode(); + var stringPostResponse = await postResponse.Content.ReadAsStringAsync(); + Assert.Contains(".NET Black & White Mug", stringPostResponse); + + //Load login page + var loginResponse = await Client.GetAsync("/Identity/Account/Login"); + var longinKeyValues = new List> + { + new KeyValuePair("email", "demouser@microsoft.com"), + new KeyValuePair("password", "Pass@word1"), + new KeyValuePair(WebPageHelpers.TokenTag, WebPageHelpers.GetRequestVerificationToken(await loginResponse.Content.ReadAsStringAsync())) + }; + var loginFormContent = new FormUrlEncodedContent(longinKeyValues); + var loginPostResponse = await Client.PostAsync("/Identity/Account/Login?ReturnUrl=%2FBasket%2FCheckout", loginFormContent); + var loginStringResponse = await loginPostResponse.Content.ReadAsStringAsync(); + + //Basket checkout (Pay now) + var checkOutKeyValues = new List> + { + new KeyValuePair("Items[0].Id", "2"), + new KeyValuePair("Items[0].Quantity", "1"), + new KeyValuePair(WebPageHelpers.TokenTag, WebPageHelpers.GetRequestVerificationToken(loginStringResponse)) + }; + var checkOutContent = new FormUrlEncodedContent(checkOutKeyValues); + var checkOutResponse = await Client.PostAsync("/basket/checkout", checkOutContent); + var stringCheckOutResponse = await checkOutResponse.Content.ReadAsStringAsync(); + + Assert.Contains("/Basket/Success", checkOutResponse.RequestMessage.RequestUri.ToString()); + Assert.Contains("Thanks for your Order!", stringCheckOutResponse); + } +} diff --git a/tests/FunctionalTests/Web/Pages/Basket/IndexTest.cs b/tests/FunctionalTests/Web/Pages/Basket/IndexTest.cs new file mode 100644 index 000000000..88ef74370 --- /dev/null +++ b/tests/FunctionalTests/Web/Pages/Basket/IndexTest.cs @@ -0,0 +1,100 @@ +using Microsoft.AspNetCore.Mvc.Testing; +using Xunit; + +namespace Microsoft.eShopWeb.FunctionalTests.Web.Pages.Basket; + +[Collection("Sequential")] +public class IndexTest : IClassFixture +{ + public IndexTest(TestApplication factory) + { + Client = factory.CreateClient(new WebApplicationFactoryClientOptions + { + AllowAutoRedirect = true + }); + } + + public HttpClient Client { get; } + + + [Fact] + public async Task OnPostUpdateTo50Successfully() + { + // Load Home Page + var response = await Client.GetAsync("/"); + response.EnsureSuccessStatusCode(); + var stringResponse1 = await response.Content.ReadAsStringAsync(); + + string token = WebPageHelpers.GetRequestVerificationToken(stringResponse1); + + // Add Item to Cart + var keyValues = new List> + { + new KeyValuePair("id", "2"), + new KeyValuePair("name", "shirt"), + new KeyValuePair("price", "19.49"), + new KeyValuePair("__RequestVerificationToken", token) + }; + var formContent = new FormUrlEncodedContent(keyValues); + var postResponse = await Client.PostAsync("/basket/index", formContent); + postResponse.EnsureSuccessStatusCode(); + var stringResponse = await postResponse.Content.ReadAsStringAsync(); + Assert.Contains(".NET Black & White Mug", stringResponse); + + //Update + var updateKeyValues = new List> + { + new KeyValuePair("Items[0].Id", WebPageHelpers.GetId(stringResponse)), + new KeyValuePair("Items[0].Quantity", "50"), + new KeyValuePair(WebPageHelpers.TokenTag, WebPageHelpers.GetRequestVerificationToken(stringResponse)) + }; + var updateContent = new FormUrlEncodedContent(updateKeyValues); + var updateResponse = await Client.PostAsync("/basket/update", updateContent); + + var stringUpdateResponse = await updateResponse.Content.ReadAsStringAsync(); + + Assert.Contains("/basket/update", updateResponse.RequestMessage.RequestUri.ToString()); + Assert.Contains("974.50", stringUpdateResponse); + } + + [Fact] + public async Task OnPostUpdateTo0EmptyBasket() + { + // Load Home Page + var response = await Client.GetAsync("/"); + response.EnsureSuccessStatusCode(); + var stringResponse1 = await response.Content.ReadAsStringAsync(); + + string token = WebPageHelpers.GetRequestVerificationToken(stringResponse1); + + // Add Item to Cart + var keyValues = new List> + { + new KeyValuePair("id", "2"), + new KeyValuePair("name", "shirt"), + new KeyValuePair("price", "19.49"), + new KeyValuePair("__RequestVerificationToken", token) + }; + var formContent = new FormUrlEncodedContent(keyValues); + var postResponse = await Client.PostAsync("/basket/index", formContent); + postResponse.EnsureSuccessStatusCode(); + var stringResponse = await postResponse.Content.ReadAsStringAsync(); + Assert.Contains(".NET Black & White Mug", stringResponse); + + //Update + var updateKeyValues = new List> + { + new KeyValuePair("Items[0].Id", WebPageHelpers.GetId(stringResponse)), + new KeyValuePair("Items[0].Quantity", "0"), + new KeyValuePair(WebPageHelpers.TokenTag, WebPageHelpers.GetRequestVerificationToken(stringResponse)) + }; + var updateContent = new FormUrlEncodedContent(updateKeyValues); + var updateResponse = await Client.PostAsync("/basket/update", updateContent); + + var stringUpdateResponse = await updateResponse.Content.ReadAsStringAsync(); + + Assert.Contains("/basket/update", updateResponse.RequestMessage.RequestUri.ToString()); + Assert.Contains("Basket is empty", stringUpdateResponse); + + } +} diff --git a/tests/FunctionalTests/Web/WebPageHelpers.cs b/tests/FunctionalTests/Web/WebPageHelpers.cs new file mode 100644 index 000000000..d858bfbbe --- /dev/null +++ b/tests/FunctionalTests/Web/WebPageHelpers.cs @@ -0,0 +1,27 @@ +using System.Text.RegularExpressions; + +namespace Microsoft.eShopWeb.FunctionalTests.Web; + +public static class WebPageHelpers +{ + public static string TokenTag = "__RequestVerificationToken"; + + public static string GetRequestVerificationToken(string input) + { + string regexpression = @"name=""__RequestVerificationToken"" type=""hidden"" value=""([-A-Za-z0-9+=/\\_]+?)"""; + return RegexSearch(regexpression, input); + } + + public static string GetId(string input) + { + string regexpression = @"name=""Items\[0\].Id"" value=""(\d)"""; + return RegexSearch(regexpression, input); + } + + private static string RegexSearch(string regexpression, string input) + { + var regex = new Regex(regexpression); + var match = regex.Match(input); + return match.Groups.Values.LastOrDefault().Value; + } +} diff --git a/tests/PublicApiIntegrationTests/AuthEndpoints/AuthenticateEndpointTest.cs b/tests/PublicApiIntegrationTests/AuthEndpoints/AuthenticateEndpointTest.cs index 3d2aa93fe..03a969c7f 100644 --- a/tests/PublicApiIntegrationTests/AuthEndpoints/AuthenticateEndpointTest.cs +++ b/tests/PublicApiIntegrationTests/AuthEndpoints/AuthenticateEndpointTest.cs @@ -1,18 +1,17 @@ -using Microsoft.AspNetCore.Mvc.Testing; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; using Microsoft.eShopWeb; using Microsoft.eShopWeb.ApplicationCore.Constants; using Microsoft.eShopWeb.PublicApi.AuthEndpoints; using Microsoft.VisualStudio.TestTools.UnitTesting; -using System.Net.Http; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; namespace PublicApiIntegrationTests.AuthEndpoints { [TestClass] public class AuthenticateEndpoint - { + { [TestMethod] [DataRow("demouser@microsoft.com", AuthorizationConstants.DEFAULT_PASSWORD, true)] [DataRow("demouser@microsoft.com", "badpassword", false)] @@ -33,4 +32,4 @@ public async Task ReturnsExpectedResultGivenCredentials(string testUsername, str Assert.AreEqual(expectedResult, model.Result); } } -} \ No newline at end of file +} diff --git a/tests/UnitTests/UnitTests.csproj b/tests/UnitTests/UnitTests.csproj index b9219222e..8ecd3d4fa 100644 --- a/tests/UnitTests/UnitTests.csproj +++ b/tests/UnitTests/UnitTests.csproj @@ -2,8 +2,11 @@ net6.0 + enable Microsoft.eShopWeb.UnitTests false + latest + enable