diff --git a/src/MusicStore/Controllers/CheckoutController.cs b/src/MusicStore/Controllers/CheckoutController.cs index 738389029f..d5aaed9379 100644 --- a/src/MusicStore/Controllers/CheckoutController.cs +++ b/src/MusicStore/Controllers/CheckoutController.cs @@ -29,8 +29,13 @@ namespace MusicStore.Controllers [HttpPost] [ValidateAntiForgeryToken] - public async Task AddressAndPayment(Order order, CancellationToken requestAborted) + public async Task AddressAndPayment([FromForm] Order order, CancellationToken requestAborted) { + if (!ModelState.IsValid) + { + return View(order); + } + var formCollection = await Context.Request.ReadFormAsync(); try diff --git a/test/MusicStore.Test/CheckoutControllerTest.cs b/test/MusicStore.Test/CheckoutControllerTest.cs new file mode 100644 index 0000000000..f008e6c455 --- /dev/null +++ b/test/MusicStore.Test/CheckoutControllerTest.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNet.Http.Core; +using Microsoft.AspNet.Http.Core.Collections; +using Microsoft.AspNet.Mvc; +using Microsoft.AspNet.Routing; +using Microsoft.Framework.DependencyInjection; +using Microsoft.Framework.DependencyInjection.Fallback; +using MusicStore.Models; +using Xunit; + +namespace MusicStore.Controllers +{ + public class CheckoutControllerTest + { + private readonly IServiceProvider _serviceProvider; + + public CheckoutControllerTest() + { + var services = new ServiceCollection(); + + services.AddEntityFramework() + .AddInMemoryStore() + .AddDbContext(); + + _serviceProvider = services.BuildServiceProvider(); + } + + [Fact] + public void AddressAndPayment_ReturnsDefaultView() + { + // Arrange + var controller = new CheckoutController(); + + // Act + var result = controller.AddressAndPayment(); + + // Assert + var viewResult = Assert.IsType(result); + Assert.Null(viewResult.ViewName); + } + + [Fact] + public async Task AddressAndPayment_ReturnsOrderIfInvalidPromoCode() + { + // Arrange + var context = new DefaultHttpContext(); + + // AddressAndPayment action reads the Promo code from FormCollection. + context.Request.Form = + new FormCollection(new Dictionary()); + + var controller = new CheckoutController(); + controller.ActionContext.HttpContext = context; + + // Do not need actual data for Order; the Order object will be checked for the reference equality. + var order = new Order(); + + // Act + var result = await controller.AddressAndPayment(order, CancellationToken.None); + + // Assert + var viewResult = Assert.IsType(result); + Assert.Null(viewResult.ViewName); + + Assert.NotNull(viewResult.ViewData); + Assert.Same(order, viewResult.ViewData.Model); + } + + [Fact] + public async Task AddressAndPayment_ReturnsOrderIfRequestCanceled() + { + // Arrange + var context = new DefaultHttpContext(); + context.Request.Form = + new FormCollection(new Dictionary()); + + var controller = new CheckoutController(); + controller.ActionContext.HttpContext = context; + + var order = new Order(); + + // Act + var result = await controller.AddressAndPayment(order, new CancellationToken(true)); + + // Assert + var viewResult = Assert.IsType(result); + Assert.Null(viewResult.ViewName); + + Assert.NotNull(viewResult.ViewData); + Assert.Same(order, viewResult.ViewData.Model); + } + + [Fact] + public async Task AddressAndPayment_ReturnsOrderIfInvalidOrderModel() + { + // Arrange + var controller = new CheckoutController(); + controller.ModelState.AddModelError("a", "ModelErrorA"); + + var order = new Order(); + + // Act + var result = await controller.AddressAndPayment(order, CancellationToken.None); + + // Assert + var viewResult = Assert.IsType(result); + Assert.Null(viewResult.ViewName); + + Assert.NotNull(viewResult.ViewData); + Assert.Same(order, viewResult.ViewData.Model); + } + + [Fact] + public async Task Complete_ReturnsOrderIdIfValid() + { + // Arrange + var orderId = 100; + var userName = "TestUserA"; + var claims = new List { new Claim(ClaimTypes.Name, userName) }; + + var httpContext = new DefaultHttpContext() + { + User = new ClaimsPrincipal(new ClaimsIdentity(claims)), + }; + + var dbContext = + _serviceProvider.GetRequiredService(); + dbContext.Add(new Order() + { + OrderId = orderId, + Username = userName + }); + dbContext.SaveChanges(); + + var controller = new CheckoutController() + { + DbContext = dbContext, + }; + controller.ActionContext.HttpContext = httpContext; + + // Act + var result = await controller.Complete(orderId); + + // Assert + var viewResult = Assert.IsType(result); + Assert.Null(viewResult.ViewName); + + Assert.NotNull(viewResult.ViewData); + Assert.Equal(orderId, viewResult.ViewData.Model); + } + + [Fact] + public async Task Complete_ReturnsErrorIfInvalidOrder() + { + // Arrange + var invalidOrderId = 100; + var dbContext = + _serviceProvider.GetRequiredService(); + + var controller = new CheckoutController() + { + DbContext = dbContext, + }; + controller.ActionContext.HttpContext = new DefaultHttpContext(); + + // Act + var result = await controller.Complete(invalidOrderId); + + // Assert + var viewResult = Assert.IsType(result); + + Assert.Equal("Error", viewResult.ViewName); + } + } +} \ No newline at end of file diff --git a/test/MusicStore.Test/HomeControllerTest.cs b/test/MusicStore.Test/HomeControllerTest.cs new file mode 100644 index 0000000000..7254d4e98b --- /dev/null +++ b/test/MusicStore.Test/HomeControllerTest.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNet.Mvc; +using Microsoft.Data.Entity; +using Microsoft.Framework.Cache.Memory; +using Microsoft.Framework.DependencyInjection; +using Microsoft.Framework.DependencyInjection.Fallback; +using MusicStore.Models; +using Xunit; + +namespace MusicStore.Controllers +{ + public class HomeControllerTest + { + private readonly IServiceProvider _serviceProvider; + + public HomeControllerTest() + { + var services = new ServiceCollection(); + + services.AddEntityFramework() + .AddInMemoryStore() + .AddDbContext(); + + _serviceProvider = services.BuildServiceProvider(); + } + + [Fact] + public void Error_ReturnsErrorView() + { + // Arrange + var controller = new HomeController(); + var errorView = "~/Views/Shared/Error.cshtml"; + + // Act + var result = controller.Error(); + + // Assert + var viewResult = Assert.IsType(result); + + Assert.Equal(errorView, viewResult.ViewName); + } + + [Fact] + public async Task Index_GetsSixTopAlbums() + { + // Arrange + var controller = new HomeController() + { + DbContext = _serviceProvider.GetRequiredService(), + Cache = _serviceProvider.GetRequiredService(), + }; + + PopulateData(controller.DbContext); + + // Action + var result = await controller.Index(); + + // Assert + var viewResult = Assert.IsType(result); + Assert.Null(viewResult.ViewName); + + Assert.NotNull(viewResult.ViewData); + Assert.NotNull(viewResult.ViewData.Model); + + var albums = Assert.IsType>(viewResult.ViewData.Model); + Assert.Equal(6, albums.Count); + } + + [Fact] + public void StatusCodePage_ReturnsStatusCodePage() + { + // Arrange + var controller = new HomeController(); + var statusCodeView = "~/Views/Shared/StatusCodePage.cshtml"; + + // Action + var result = controller.StatusCodePage(); + + // Assert + var viewResult = Assert.IsType(result); + + Assert.Equal(statusCodeView, viewResult.ViewName); + } + + private void PopulateData(DbContext context) + { + var albums = TestAlbumDataProvider.GetAlbums(); + + foreach (var album in albums) + { + context.Add(album); + } + + context.SaveChanges(); + } + + private class TestAlbumDataProvider + { + public static Album[] GetAlbums() + { + var generes = Enumerable.Range(1, 10).Select(n => + new Genre() + { + GenreId = n, + Name = "Genre Name " + n, + }).ToArray(); + + var artists = Enumerable.Range(1, 10).Select(n => + new Artist() + { + ArtistId = n + 1, + Name = "Artist Name " + n, + }).ToArray(); + + var albums = Enumerable.Range(1, 10).Select(n => + new Album() + { + Artist = artists[n - 1], + ArtistId = n, + Genre = generes[n - 1], + GenreId = n, + }).ToArray(); + + return albums; + } + } + } +} \ No newline at end of file