diff --git a/MusicStore.sln b/MusicStore.sln index c17a8f8213..0deb72a72c 100644 --- a/MusicStore.sln +++ b/MusicStore.sln @@ -24,7 +24,9 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MusicStore", "src\MusicStor EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MusicStore.Spa", "src\MusicStore.Spa\MusicStore.Spa.kproj", "{93891170-A8D5-46FD-A291-40F90CF258C2}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MusicStore.Test", "test\MusicStore.Test\MusicStore.Test.kproj", "{BECA766F-093E-4D08-9530-2BFA63C5BF93}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MusicStore.Test", "test\MusicStore.Test\MusicStore.Test.kproj", "{CA663205-77DE-4E55-B300-85594181B5A9}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MusicStore.Spa.Test", "test\MusicStore.Spa.Test\MusicStore.Spa.Test.kproj", "{9D3326C4-1F12-4526-9F25-712A1463B3FA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -86,18 +88,30 @@ Global {93891170-A8D5-46FD-A291-40F90CF258C2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {93891170-A8D5-46FD-A291-40F90CF258C2}.Release|Mixed Platforms.Build.0 = Release|Any CPU {93891170-A8D5-46FD-A291-40F90CF258C2}.Release|x86.ActiveCfg = Release|Any CPU - {BECA766F-093E-4D08-9530-2BFA63C5BF93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BECA766F-093E-4D08-9530-2BFA63C5BF93}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BECA766F-093E-4D08-9530-2BFA63C5BF93}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {BECA766F-093E-4D08-9530-2BFA63C5BF93}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {BECA766F-093E-4D08-9530-2BFA63C5BF93}.Debug|x86.ActiveCfg = Debug|Any CPU - {BECA766F-093E-4D08-9530-2BFA63C5BF93}.Debug|x86.Build.0 = Debug|Any CPU - {BECA766F-093E-4D08-9530-2BFA63C5BF93}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BECA766F-093E-4D08-9530-2BFA63C5BF93}.Release|Any CPU.Build.0 = Release|Any CPU - {BECA766F-093E-4D08-9530-2BFA63C5BF93}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {BECA766F-093E-4D08-9530-2BFA63C5BF93}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {BECA766F-093E-4D08-9530-2BFA63C5BF93}.Release|x86.ActiveCfg = Release|Any CPU - {BECA766F-093E-4D08-9530-2BFA63C5BF93}.Release|x86.Build.0 = Release|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Debug|x86.ActiveCfg = Debug|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Debug|x86.Build.0 = Debug|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Release|Any CPU.Build.0 = Release|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Release|x86.ActiveCfg = Release|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Release|x86.Build.0 = Release|Any CPU + {9D3326C4-1F12-4526-9F25-712A1463B3FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9D3326C4-1F12-4526-9F25-712A1463B3FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9D3326C4-1F12-4526-9F25-712A1463B3FA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9D3326C4-1F12-4526-9F25-712A1463B3FA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9D3326C4-1F12-4526-9F25-712A1463B3FA}.Debug|x86.ActiveCfg = Debug|Any CPU + {9D3326C4-1F12-4526-9F25-712A1463B3FA}.Debug|x86.Build.0 = Debug|Any CPU + {9D3326C4-1F12-4526-9F25-712A1463B3FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9D3326C4-1F12-4526-9F25-712A1463B3FA}.Release|Any CPU.Build.0 = Release|Any CPU + {9D3326C4-1F12-4526-9F25-712A1463B3FA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9D3326C4-1F12-4526-9F25-712A1463B3FA}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9D3326C4-1F12-4526-9F25-712A1463B3FA}.Release|x86.ActiveCfg = Release|Any CPU + {9D3326C4-1F12-4526-9F25-712A1463B3FA}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -108,6 +122,7 @@ Global {A319ACCE-060B-4385-9534-9F2202F6180E} = {363D2681-31A6-48C9-90BB-9ACFF4A41F06} {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0} = {B7B176B6-8D4D-4EF1-BBD2-DDA650C78FFF} {93891170-A8D5-46FD-A291-40F90CF258C2} = {B7B176B6-8D4D-4EF1-BBD2-DDA650C78FFF} - {BECA766F-093E-4D08-9530-2BFA63C5BF93} = {363D2681-31A6-48C9-90BB-9ACFF4A41F06} + {CA663205-77DE-4E55-B300-85594181B5A9} = {363D2681-31A6-48C9-90BB-9ACFF4A41F06} + {9D3326C4-1F12-4526-9F25-712A1463B3FA} = {363D2681-31A6-48C9-90BB-9ACFF4A41F06} EndGlobalSection EndGlobal diff --git a/test/MusicStore.Spa.Test/MusicStore.Spa.Test.kproj b/test/MusicStore.Spa.Test/MusicStore.Spa.Test.kproj new file mode 100644 index 0000000000..bdc0cfd13e --- /dev/null +++ b/test/MusicStore.Spa.Test/MusicStore.Spa.Test.kproj @@ -0,0 +1,20 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + 9d3326c4-1f12-4526-9f25-712a1463b3fa + MusicStore.Spa.Test + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + \ No newline at end of file diff --git a/test/MusicStore.Spa.Test/ShoppingCartTest.cs b/test/MusicStore.Spa.Test/ShoppingCartTest.cs new file mode 100644 index 0000000000..0c1d64fbda --- /dev/null +++ b/test/MusicStore.Spa.Test/ShoppingCartTest.cs @@ -0,0 +1,45 @@ +using Microsoft.AspNet.Http; +using Microsoft.AspNet.Http.Core; +using Microsoft.AspNet.Http.Core.Collections; +using Xunit; + +namespace MusicStore.Models +{ + public class ShoppingCartTest + { + [Fact] + public void GetCartId_ReturnsCartIdFromCookies() + { + // Arrange + var cartId = "cartId_A"; + + var httpContext = new DefaultHttpContext(); + httpContext.SetFeature(new CookiesFeature("Session=" + cartId)); + + var cart = new ShoppingCart(new MusicStoreContext()); + + // Act + var result = cart.GetCartId(httpContext); + + // Assert + Assert.NotNull(result); + Assert.Equal(cartId, result); + } + + private class CookiesFeature : IRequestCookiesFeature + { + private readonly RequestCookiesCollection _cookies; + + public CookiesFeature(string cookiesHeader) + { + _cookies = new RequestCookiesCollection(); + _cookies.Reparse(cookiesHeader); + } + + public IReadableStringCollection Cookies + { + get { return _cookies; } + } + } + } +} diff --git a/test/MusicStore.Spa.Test/project.json b/test/MusicStore.Spa.Test/project.json new file mode 100644 index 0000000000..048212b9bc --- /dev/null +++ b/test/MusicStore.Spa.Test/project.json @@ -0,0 +1,17 @@ +{ + "compilationOptions": { + "warningsAsErrors": "true" + }, + "dependencies": { + "MusicStore.Spa": "", + "Microsoft.AspNet.Mvc" : "6.0.0-*", + "Microsoft.AspNet.Testing.Logging" : "1.0.0-*", + "xunit.runner.kre": "1.0.0-*" + }, + "commands": { + "test": "xunit.runner.kre" + }, + "frameworks": { + "aspnet50": { }, + } +} \ No newline at end of file diff --git a/test/MusicStore.Test/ShoppingCartControllerTest.cs b/test/MusicStore.Test/ShoppingCartControllerTest.cs new file mode 100644 index 0000000000..61cd85a4e6 --- /dev/null +++ b/test/MusicStore.Test/ShoppingCartControllerTest.cs @@ -0,0 +1,172 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNet.Http; +using Microsoft.AspNet.Http.Core; +using Microsoft.AspNet.Http.Interfaces; +using Microsoft.AspNet.Mvc; +using Microsoft.AspNet.Session; +using Microsoft.AspNet.Testing.Logging; +using Microsoft.Framework.Cache.Distributed; +using Microsoft.Framework.Cache.Memory; +using Microsoft.Framework.DependencyInjection; +using MusicStore.Models; +using MusicStore.ViewModels; +using Xunit; + +namespace MusicStore.Controllers +{ + public class ShoppingCartControllerTest + { + private readonly IServiceProvider _serviceProvider; + + public ShoppingCartControllerTest() + { + var services = new ServiceCollection(); + + services.AddEntityFramework() + .AddInMemoryStore() + .AddDbContext(); + + _serviceProvider = services.BuildServiceProvider(); + } + + [Fact] + public async Task Index_ReturnsNoCartItems_WhenSessionEmpty() + { + // Arrange + var sessionFeature = new SessionFeature() + { + Session = CreateTestSession(), + }; + + var httpContext = new DefaultHttpContext(); + httpContext.SetFeature(sessionFeature); + + var controller = new ShoppingCartController() + { + DbContext = _serviceProvider.GetRequiredService(), + }; + controller.ActionContext.HttpContext = httpContext; + + // Act + var result = await controller.Index(); + + // Assert + var viewResult = Assert.IsType(result); + Assert.NotNull(viewResult.ViewData); + Assert.Null(viewResult.ViewName); + + var model = Assert.IsType(viewResult.ViewData.Model); + Assert.Equal(0, model.CartItems.Count); + Assert.Equal(0, model.CartTotal); + } + + [Fact] + public async Task Index_ReturnsNoCartItems_WhenNoItemsInCart() + { + // Arrange + var sessionFeature = new SessionFeature() + { + Session = CreateTestSession(), + }; + + var httpContext = new DefaultHttpContext(); + httpContext.SetFeature(sessionFeature); + httpContext.Session.SetString("Session", "CartId_A"); + + var controller = new ShoppingCartController() + { + DbContext = _serviceProvider.GetRequiredService(), + }; + controller.ActionContext.HttpContext = httpContext; + + // Act + var result = await controller.Index(); + + // Assert + var viewResult = Assert.IsType(result); + Assert.NotNull(viewResult.ViewData); + Assert.Null(viewResult.ViewName); + + var model = Assert.IsType(viewResult.ViewData.Model); + Assert.Equal(0, model.CartItems.Count); + Assert.Equal(0, model.CartTotal); + } + + [Fact] + public async Task Index_ReturnsCartItems_WhenItemsInCart() + { + // Arrange + var cartId = "CartId_A"; + var sessionFeature = new SessionFeature() + { + Session = CreateTestSession(), + }; + + var httpContext = new DefaultHttpContext(); + httpContext.SetFeature(sessionFeature); + httpContext.Session.SetString("Session", cartId); + + var dbContext = _serviceProvider.GetRequiredService(); + var cartItems = CreateTestCartItems( + cartId, + itemPrice: 10, + numberOfItem: 5); + dbContext.AddRange(cartItems.Select(n => n.Album).Distinct()); + dbContext.AddRange(cartItems); + dbContext.SaveChanges(); + + var controller = new ShoppingCartController() + { + DbContext = dbContext, + }; + controller.ActionContext.HttpContext = httpContext; + + // Act + var result = await controller.Index(); + + // Assert + var viewResult = Assert.IsType(result); + Assert.NotNull(viewResult.ViewData); + Assert.Null(viewResult.ViewName); + + var model = Assert.IsType(viewResult.ViewData.Model); + Assert.Equal(5, model.CartItems.Count); + Assert.Equal(5 * 10, model.CartTotal); + } + + private static ISession CreateTestSession() + { + + return new DistributedSession( + new LocalCache(new MemoryCache(new MemoryCacheOptions())), + "sessionId_A", + idleTimeout: TimeSpan.MaxValue, + tryEstablishSession: () => true, + loggerFactory: new NullLoggerFactory(), + isNewSessionKey: true); + } + + private static CartItem[] CreateTestCartItems(string cartId, decimal itemPrice, int numberOfItem) + { + var albums = Enumerable.Range(1, 10).Select(n => + new Album() + { + AlbumId = n, + Price = itemPrice, + }).ToArray(); + + var cartItems = Enumerable.Range(1, numberOfItem).Select(n => + new CartItem() + { + Count = 1, + CartId = cartId, + AlbumId = n, + Album = albums[n - 1], + }).ToArray(); + + return cartItems; + } + } +} \ No newline at end of file diff --git a/test/MusicStore.Test/project.json b/test/MusicStore.Test/project.json index 28300d1ed5..35111a9dbb 100644 --- a/test/MusicStore.Test/project.json +++ b/test/MusicStore.Test/project.json @@ -5,6 +5,7 @@ "dependencies": { "MusicStore": "", "Microsoft.AspNet.Mvc" : "6.0.0-*", + "Microsoft.AspNet.Testing.Logging" : "1.0.0-*", "xunit.runner.kre": "1.0.0-*" }, "commands": {