From 1bd65a6824fb912a94a42adb4c2911178e9c3bda Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Tue, 18 Jul 2023 22:01:49 +0200 Subject: [PATCH 01/18] Updated to .net7 --- .../CoffeeCard.Common.csproj | 5 ++-- .../CoffeeCard.MobilePay.GenerateApi.csproj | 25 ++++++++----------- .../CoffeeCard.MobilePay.csproj | 11 ++++---- .../CoffeeCard.Tests.Integration.csproj | 23 ++++++++--------- .../CoffeeCard.Tests.Unit.csproj | 4 +-- .../CoffeeCard.WebApi.csproj | 22 ++++++---------- coffeecard/CoffeeCardAPI.sln | 8 +++--- 7 files changed, 42 insertions(+), 56 deletions(-) diff --git a/coffeecard/CoffeeCard.Common/CoffeeCard.Common.csproj b/coffeecard/CoffeeCard.Common/CoffeeCard.Common.csproj index b337e671..ccb60958 100644 --- a/coffeecard/CoffeeCard.Common/CoffeeCard.Common.csproj +++ b/coffeecard/CoffeeCard.Common/CoffeeCard.Common.csproj @@ -1,11 +1,10 @@ - netstandard2.1 + net7.0 33C1BE09-BD3A-4584-B195-C57B47B9063C - - + \ No newline at end of file diff --git a/coffeecard/CoffeeCard.MobilePay.GenerateApi/CoffeeCard.MobilePay.GenerateApi.csproj b/coffeecard/CoffeeCard.MobilePay.GenerateApi/CoffeeCard.MobilePay.GenerateApi.csproj index a929ca87..2583378c 100644 --- a/coffeecard/CoffeeCard.MobilePay.GenerateApi/CoffeeCard.MobilePay.GenerateApi.csproj +++ b/coffeecard/CoffeeCard.MobilePay.GenerateApi/CoffeeCard.MobilePay.GenerateApi.csproj @@ -1,15 +1,12 @@ - - - Exe - net6.0 - enable - 8 - - - - - - - - + + Exe + net7.0 + enable + 8 + + + + + + \ No newline at end of file diff --git a/coffeecard/CoffeeCard.MobilePay/CoffeeCard.MobilePay.csproj b/coffeecard/CoffeeCard.MobilePay/CoffeeCard.MobilePay.csproj index 0a9ab86a..692fa9ef 100644 --- a/coffeecard/CoffeeCard.MobilePay/CoffeeCard.MobilePay.csproj +++ b/coffeecard/CoffeeCard.MobilePay/CoffeeCard.MobilePay.csproj @@ -1,18 +1,17 @@ - net6.0 + net7.0 AFF9D584-58F4-4A8D-A6BF-515890A9A3EF enable - - - - - + + + + diff --git a/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj b/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj index 723d78cf..3be5697a 100644 --- a/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj +++ b/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj @@ -1,6 +1,6 @@  - net6.0 + net7.0 false 8 81E81CE9-7DDA-4A9B-860B-6A473BC4F06F @@ -10,19 +10,10 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -30,6 +21,12 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj b/coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj index 9e7c3edc..6c421503 100644 --- a/coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj +++ b/coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj @@ -1,6 +1,6 @@ - net6.0 + net7.0 false 8 24274C8F-678F-4E4D-98A0-2899163BCCBA @@ -10,7 +10,6 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - @@ -22,6 +21,7 @@ all runtime; build; native; contentfiles; analyzers + diff --git a/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj b/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj index 49798d10..fbdb6383 100644 --- a/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj +++ b/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj @@ -1,6 +1,6 @@  - net6.0 + net7.0 InProcess 8 5562C898-513F-493A-A335-417C39476714 @@ -30,29 +30,23 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - + - + + + + + + diff --git a/coffeecard/CoffeeCardAPI.sln b/coffeecard/CoffeeCardAPI.sln index c3660e14..02a8a0de 100644 --- a/coffeecard/CoffeeCardAPI.sln +++ b/coffeecard/CoffeeCardAPI.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29806.167 @@ -13,11 +13,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.MobilePay", "Cof EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.Common", "CoffeeCard.Common\CoffeeCard.Common.csproj", "{2CCAF827-E341-48FC-ABCE-7EDFA3E84E65}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoffeeCard.Library", "CoffeeCard.Library\CoffeeCard.Library.csproj", "{F05C6E90-C02D-43BF-8BBB-615785C465DF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.Library", "CoffeeCard.Library\CoffeeCard.Library.csproj", "{F05C6E90-C02D-43BF-8BBB-615785C465DF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoffeeCard.Models", "CoffeeCard.Models\CoffeeCard.Models.csproj", "{0BF48733-C3DF-4006-BD25-F5340710B5FA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.Models", "CoffeeCard.Models\CoffeeCard.Models.csproj", "{0BF48733-C3DF-4006-BD25-F5340710B5FA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoffeeCard.MobilePay.GenerateApi", "CoffeeCard.MobilePay.GenerateApi\CoffeeCard.MobilePay.GenerateApi.csproj", "{D295CCD7-DDB7-477D-82B6-53AFA97F5749}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.MobilePay.GenerateApi", "CoffeeCard.MobilePay.GenerateApi\CoffeeCard.MobilePay.GenerateApi.csproj", "{D295CCD7-DDB7-477D-82B6-53AFA97F5749}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution From 3ae6a11a12cc0f381791687ad4e2bb4c5df2d0f9 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Tue, 25 Jul 2023 19:17:06 +0200 Subject: [PATCH 02/18] Added new project for creating entities. TO be used when writing unit, and integration tests --- .../Builders/BaseBuilder.cs | 35 +++++++++++++++++++ .../Builders/ProductBuilder.cs | 22 ++++++++++++ .../Builders/ProductUserGroupBuilder.cs | 21 +++++++++++ .../Builders/ProgrammeBuilder.cs | 21 +++++++++++ .../Builders/PurchaseBuilder.cs | 23 ++++++++++++ .../Builders/StatisticBuilder.cs | 20 +++++++++++ .../Builders/TicketBuilder.cs | 25 +++++++++++++ .../Builders/TokenBuilder.cs | 19 ++++++++++ .../Builders/UserBuilder.cs | 33 +++++++++++++++++ .../Builders/VoucherBuilder.cs | 23 ++++++++++++ .../CoffeeCard.Tests.Common.csproj | 22 ++++++++++++ coffeecard/CoffeeCardAPI.sln | 6 ++++ 12 files changed, 270 insertions(+) create mode 100644 coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs create mode 100644 coffeecard/CoffeeCard.Tests.Common/Builders/ProductBuilder.cs create mode 100644 coffeecard/CoffeeCard.Tests.Common/Builders/ProductUserGroupBuilder.cs create mode 100644 coffeecard/CoffeeCard.Tests.Common/Builders/ProgrammeBuilder.cs create mode 100644 coffeecard/CoffeeCard.Tests.Common/Builders/PurchaseBuilder.cs create mode 100644 coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs create mode 100644 coffeecard/CoffeeCard.Tests.Common/Builders/TicketBuilder.cs create mode 100644 coffeecard/CoffeeCard.Tests.Common/Builders/TokenBuilder.cs create mode 100644 coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs create mode 100644 coffeecard/CoffeeCard.Tests.Common/Builders/VoucherBuilder.cs create mode 100644 coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs new file mode 100644 index 00000000..e19cc81d --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs @@ -0,0 +1,35 @@ +using AutoBogus; +using AutoBogus.Conventions; + +namespace CoffeeCard.Tests.Common.Builders +{ + public abstract class BaseBuilder where T : class + { + protected readonly AutoFaker Faker = new(); + protected BaseBuilder() + { + Faker.Configure(builder => builder.WithConventions()); + } + + /// + /// Gives a standard configured builder, + /// where lists of linked entities are empty + /// and nullable enities are null + /// + public abstract BaseBuilder Simple(); + + /// + /// Gives a standard configured builder, + /// where all linked entities are populated + /// + public abstract BaseBuilder Typical(); + + /// + /// Creates a new instance of type T, + /// using the configuration set by + /// + public T Build(){ + return Faker.Generate(); + } + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/ProductBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/ProductBuilder.cs new file mode 100644 index 00000000..ce633748 --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/ProductBuilder.cs @@ -0,0 +1,22 @@ +using CoffeeCard.Models.Entities; + +namespace CoffeeCard.Tests.Common.Builders +{ + public class ProductBuilder : BaseBuilder + { + public override ProductBuilder Simple() + { + Faker.RuleFor(p => p.Id, f => f.IndexGlobal) + .RuleFor(p => p.Name, f => f.Commerce.Product()) + .RuleFor(p => p.Description, f => f.Commerce.ProductDescription()) + .RuleFor(p => p.NumberOfTickets, f => f.PickRandom(1, 10)) + .RuleFor(p => p.ProductUserGroup, new List()); + return this; + } + + public override ProductBuilder Typical() + { + return Simple(); + } + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/ProductUserGroupBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/ProductUserGroupBuilder.cs new file mode 100644 index 00000000..e17a17d3 --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/ProductUserGroupBuilder.cs @@ -0,0 +1,21 @@ +using CoffeeCard.Models.Entities; + +namespace CoffeeCard.Tests.Common.Builders +{ + public class ProductUserGroupBuilder : BaseBuilder + { + public override ProductUserGroupBuilder Simple() + { + var product = new ProductBuilder().Simple().Build(); + Faker.RuleFor(p => p.Product, product) + .RuleFor(p => p.ProductId, product.Id) + .RuleFor(p => p.UserGroup, f => f.PickRandom(UserGroup.Barista, UserGroup.Board, UserGroup.Customer, UserGroup.Manager)); + return this; + } + + public override ProductUserGroupBuilder Typical() + { + return Simple(); + } + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/ProgrammeBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/ProgrammeBuilder.cs new file mode 100644 index 00000000..ae982fdd --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/ProgrammeBuilder.cs @@ -0,0 +1,21 @@ +using CoffeeCard.Models.Entities; + +namespace CoffeeCard.Tests.Common.Builders +{ + public class ProgrammeBuilder : BaseBuilder + { + public override ProgrammeBuilder Simple() + { + Faker.RuleFor(p => p.Id, f => f.IndexGlobal) + .RuleFor(p => p.FullName, f => f.Commerce.Department()) + .RuleFor(p => p.ShortName, f => f.Random.String2(3)) + .RuleFor(p => p.Users, () => new List()); + return this; + } + + public override ProgrammeBuilder Typical() + { + return Simple(); + } + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/PurchaseBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/PurchaseBuilder.cs new file mode 100644 index 00000000..03e60f3a --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/PurchaseBuilder.cs @@ -0,0 +1,23 @@ +using CoffeeCard.Models.Entities; + +namespace CoffeeCard.Tests.Common.Builders +{ + public class PurchaseBuilder : BaseBuilder + { + public override PurchaseBuilder Simple() + { + var purchasedBy = new UserBuilder().Simple().Build(); + Faker.RuleFor(p => p.Id, f => f.IndexGlobal) + .RuleFor(p => p.PurchasedBy, purchasedBy) + .RuleFor(p => p.PurchasedById, purchasedBy.Id) + .RuleFor(p => p.Tickets, new List()) + .RuleFor(p => p.NumberOfTickets, 0); + return this; + } + + public override PurchaseBuilder Typical() + { + return Simple(); + } + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs new file mode 100644 index 00000000..296b506a --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs @@ -0,0 +1,20 @@ +using CoffeeCard.Models.Entities; + +namespace CoffeeCard.Tests.Common.Builders +{ + public class StatisticBuilder : BaseBuilder + { + public override StatisticBuilder Simple() + { + var user = new UserBuilder().Simple().Build(); + Faker.RuleFor(p => p.Id, f => f.IndexGlobal) + .RuleFor(p => p.User, user); + return this; + } + + public override StatisticBuilder Typical() + { + return Simple(); + } + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/TicketBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/TicketBuilder.cs new file mode 100644 index 00000000..0f996000 --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/TicketBuilder.cs @@ -0,0 +1,25 @@ +using CoffeeCard.Models.Entities; + +namespace CoffeeCard.Tests.Common.Builders +{ + public class TicketBuilder : BaseBuilder + { + public override TicketBuilder Simple() + { + var owner = new UserBuilder().Simple().Build(); + var purchase = new PurchaseBuilder().Simple().Build(); + Faker.RuleFor(p => p.Id, f => f.IndexGlobal) + .RuleFor(p => p.Owner, owner) + .RuleFor(p => p.OwnerId, owner.Id) + .RuleFor(p => p.Purchase, f => purchase) + .RuleFor(p => p.PurchaseId, purchase.Id); + + return this; + } + + public override TicketBuilder Typical() + { + return Simple(); + } + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/TokenBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/TokenBuilder.cs new file mode 100644 index 00000000..537fed92 --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/TokenBuilder.cs @@ -0,0 +1,19 @@ +using CoffeeCard.Models.Entities; + +namespace CoffeeCard.Tests.Common.Builders +{ + public class TokenBuilder : BaseBuilder + { + public override TokenBuilder Simple() + { + Faker.RuleFor(p => p.Id, f => f.IndexGlobal) + .RuleFor(p => p.User, new UserBuilder().Simple().Build()); + return this; + } + + public override TokenBuilder Typical() + { + return Simple(); + } + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs new file mode 100644 index 00000000..359a257a --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs @@ -0,0 +1,33 @@ +using CoffeeCard.Models.Entities; + +namespace CoffeeCard.Tests.Common.Builders +{ + public class UserBuilder : BaseBuilder + { + public override UserBuilder Simple() + { + var programme = new ProgrammeBuilder().Simple().Build(); + Faker.RuleFor(u => u.Id, f => f.IndexGlobal) + .RuleFor(u => u.ProgrammeId, programme.Id) + .RuleFor(u => u.Programme, programme) + .RuleFor(u => u.Purchases, new List()) + .RuleFor(u => u.Statistics, new List()) + .RuleFor(u => u.LoginAttempts, new List()) + .RuleFor(u => u.Tokens, new List()) + .RuleFor(u => u.UserState, UserState.Active) + .RuleFor(u => u.IsVerified, true) + .RuleFor(u => u.Tickets, new List()); + return this; + } + + public UserBuilder DefaultCustomer(){ + Faker.RuleFor(u => u.UserGroup, UserGroup.Customer); + return Simple(); + } + + public override UserBuilder Typical() + { + return Simple(); + } + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/VoucherBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/VoucherBuilder.cs new file mode 100644 index 00000000..8d569c3c --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/VoucherBuilder.cs @@ -0,0 +1,23 @@ +using CoffeeCard.Models.Entities; + +namespace CoffeeCard.Tests.Common.Builders +{ + public class VoucherBuilder : BaseBuilder + { + public override VoucherBuilder Simple() + { + var product = new ProductBuilder().Simple().Build(); + Faker.RuleFor(p => p.Id, f => f.IndexGlobal) + .RuleFor(p => p.User, f => null) + .RuleFor(v => v.UserId, f => null) + .RuleFor(v => v.Product, product) + .RuleFor(v => v.ProductId, product.Id); + return this; + } + + public override VoucherBuilder Typical() + { + return Simple(); + } + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj b/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj new file mode 100644 index 00000000..93d3f8dd --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + net7.0 + enable + enable + + + diff --git a/coffeecard/CoffeeCardAPI.sln b/coffeecard/CoffeeCardAPI.sln index 02a8a0de..469ddd18 100644 --- a/coffeecard/CoffeeCardAPI.sln +++ b/coffeecard/CoffeeCardAPI.sln @@ -19,6 +19,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.Models", "Coffee EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.MobilePay.GenerateApi", "CoffeeCard.MobilePay.GenerateApi\CoffeeCard.MobilePay.GenerateApi.csproj", "{D295CCD7-DDB7-477D-82B6-53AFA97F5749}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoffeeCard.Common.Test", "CoffeeCard.Tests.Common\CoffeeCard.Tests.Common.csproj", "{938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -57,6 +59,10 @@ Global {D295CCD7-DDB7-477D-82B6-53AFA97F5749}.Debug|Any CPU.Build.0 = Debug|Any CPU {D295CCD7-DDB7-477D-82B6-53AFA97F5749}.Release|Any CPU.ActiveCfg = Release|Any CPU {D295CCD7-DDB7-477D-82B6-53AFA97F5749}.Release|Any CPU.Build.0 = Release|Any CPU + {938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From e7a8462a5245b44cb5d32981d7bfe867fe1bf448 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Tue, 25 Jul 2023 19:18:43 +0200 Subject: [PATCH 03/18] Added some shared setup between all integration tests --- .../CoffeeCard.Tests.Integration.csproj | 1 + .../WebApplication/BaseIntegrationTest.cs | 108 ++++++++++++++++++ .../CustomWebApplicationFactory.cs | 10 +- 3 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 coffeecard/CoffeeCard.Tests.Integration/WebApplication/BaseIntegrationTest.cs diff --git a/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj b/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj index 3be5697a..62319e4d 100644 --- a/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj +++ b/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj @@ -30,6 +30,7 @@ + diff --git a/coffeecard/CoffeeCard.Tests.Integration/WebApplication/BaseIntegrationTest.cs b/coffeecard/CoffeeCard.Tests.Integration/WebApplication/BaseIntegrationTest.cs new file mode 100644 index 00000000..fc4b792b --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Integration/WebApplication/BaseIntegrationTest.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Net.Http; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; +using CoffeeCard.Common.Configuration; +using CoffeeCard.Library.Persistence; +using CoffeeCard.Models.Entities; +using CoffeeCard.WebApi; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Tokens; +using Newtonsoft.Json; +using Xunit; + +namespace CoffeeCard.Tests.Integration.WebApplication +{ + [Collection("Integration tests, to be run sequentially")] + public abstract class BaseIntegrationTest : CustomWebApplicationFactory, IClassFixture> + { + private readonly CustomWebApplicationFactory _factory; + private readonly IServiceScope _scope; + protected readonly HttpClient Client; + protected readonly CoffeeCardContext Context; + + protected BaseIntegrationTest(CustomWebApplicationFactory factory) + { + _factory = factory; + _scope = _factory.Services.CreateScope(); + + Client = GetHttpClient(); + Context = GetCoffeeCardContext(); + } + + private HttpClient GetHttpClient() + { + var client = CreateClient(); + + return client; + } + + protected void SetDefaultAuthHeader(User user) + { + var claims = new[] + { + new Claim(ClaimTypes.Email, user.Email), + new Claim(ClaimTypes.Name, user.Name), + new Claim("UserId", user.Id.ToString()), + new Claim(ClaimTypes.Role, user.UserGroup.ToString()) + }; + var token = GenerateToken(claims); + Client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", token); + } + + private string GenerateToken(IEnumerable claims) + { + var scopedServices = _scope.ServiceProvider; + var identitySettings = scopedServices.GetRequiredService(); + var key = new SymmetricSecurityKey( + Encoding.UTF8.GetBytes(identitySettings.TokenKey)); // get token from appsettings.json + + var jwt = new JwtSecurityToken("AnalogIO", + "Everyone", + claims, + DateTime.UtcNow, + DateTime.UtcNow.AddHours(24), + new SigningCredentials(key, SecurityAlgorithms.HmacSha256) + ); + + return new JwtSecurityTokenHandler().WriteToken(jwt); //the method is called WriteToken but returns a string + } + + protected void RemoveRequestHeaders() + { + Client.DefaultRequestHeaders.Clear(); + } + + private CoffeeCardContext GetCoffeeCardContext() + { + // Create a scope to obtain a reference to the database context (ApplicationDbContext). + var scopedServices = _scope.ServiceProvider; + var context = scopedServices.GetRequiredService(); + + // Ensure the database is cleaned for each test run + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + + return context; + } + + /// + /// Helper method to deserialize a response from the api + /// + protected static async Task DeserializeResponseAsync(HttpResponseMessage response) + { + response.EnsureSuccessStatusCode(); + var content = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(content); + } + + public override ValueTask DisposeAsync() + { + _scope.Dispose(); + return base.DisposeAsync(); + } + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Integration/WebApplication/CustomWebApplicationFactory.cs b/coffeecard/CoffeeCard.Tests.Integration/WebApplication/CustomWebApplicationFactory.cs index c7c272f1..424da64f 100644 --- a/coffeecard/CoffeeCard.Tests.Integration/WebApplication/CustomWebApplicationFactory.cs +++ b/coffeecard/CoffeeCard.Tests.Integration/WebApplication/CustomWebApplicationFactory.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using CoffeeCard.Common.Configuration; using CoffeeCard.Library.Persistence; @@ -50,14 +51,7 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) // Build the service provider var sp = services.BuildServiceProvider(); - - // Create a scope to obtain a reference to the database context (ApplicationDbContext). - using var scope = sp.CreateScope(); - var scopedServices = scope.ServiceProvider; - var db = scopedServices.GetRequiredService(); - - // Ensure the database is created. - db.Database.EnsureCreated(); + }); } } From 844217358969bdb54dacf2e6b94cafe028da79d7 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Tue, 25 Jul 2023 19:19:22 +0200 Subject: [PATCH 04/18] Added some basic integration tests for demonstrating the new setup --- .../Controllers/Account/GetAccountTest.cs | 36 ++++++++++ .../Controllers/Account/LoginTest.cs | 69 +++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/GetAccountTest.cs create mode 100644 coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/LoginTest.cs diff --git a/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/GetAccountTest.cs b/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/GetAccountTest.cs new file mode 100644 index 00000000..28b333c0 --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/GetAccountTest.cs @@ -0,0 +1,36 @@ +using System.Threading.Tasks; +using CoffeeCard.Tests.Integration.WebApplication; +using CoffeeCard.WebApi; +using Xunit; +using CoffeeCard.Models.DataTransferObjects.v2.User; +using CoffeeCard.Tests.Common.Builders; +using CoffeeCard.Models.Entities; + +namespace CoffeeCard.Tests.Integration.Controllers.Account { + + public class GetAccountTest : BaseIntegrationTest + { + private const string GetAccountUrl = "api/v2/account"; + public GetAccountTest(CustomWebApplicationFactory factory) : base(factory) + { + } + + [Fact] + public async Task Get_account_succeeds_when_authenticated_for_existing_account() + { + var user = new UserBuilder().DefaultCustomer().Build(); + await Context.Users.AddAsync(user); + await Context.SaveChangesAsync(); + SetDefaultAuthHeader(user); + + var response = await Client.GetAsync(GetAccountUrl); + var account = await DeserializeResponseAsync(response); + + Assert.Equal(user.Email, account.Email); + Assert.Equal(user.Name, account.Name); + Assert.Equal(user.Programme.FullName, account.Programme.FullName); + Assert.Equal(user.UserGroup.toUserRole(), account.Role); + } + + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/LoginTest.cs b/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/LoginTest.cs new file mode 100644 index 00000000..a5410d20 --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/LoginTest.cs @@ -0,0 +1,69 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using CoffeeCard.Models.DataTransferObjects.User; +using CoffeeCard.Tests.Common.Builders; +using CoffeeCard.Tests.Integration.WebApplication; +using CoffeeCard.WebApi; +using Xunit; + +namespace CoffeeCard.Tests.Integration.Controllers.Account +{ + + public class LoginTest : BaseIntegrationTest + { + private const string LoginUrl = "api/v1/account/login"; + public LoginTest(CustomWebApplicationFactory factory) : base(factory) + { + } + + [Fact] + public async Task Unknown_user_login_fails() + { + var loginRequest = new LoginDto + { + Password = "test", + Email = "test@email.dk", + Version = "2.1.0" + }; + + var response = await Client.PostAsJsonAsync(LoginUrl, loginRequest); + + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + [Fact] + public async Task Known_user_login_succeeds_returns_token() + { + var user = new UserBuilder().DefaultCustomer().Build(); + var plaintextPassword = user.Password; + user.Password = HashPassword(plaintextPassword + user.Salt); + + await Context.Users.AddAsync(user); + await Context.SaveChangesAsync(); + + var loginRequest = new LoginDto + { + Password = plaintextPassword, + Email = user.Email, + Version = "2.1.0" + }; + var response = await Client.PostAsJsonAsync(LoginUrl, loginRequest); + + var token = await DeserializeResponseAsync(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotEmpty(token.Token!); + } + + private static string HashPassword(string password) + { + var byteArr = Encoding.UTF8.GetBytes(password); + using var hasher = SHA256.Create(); + var hashBytes = hasher.ComputeHash(byteArr); + return Convert.ToBase64String(hashBytes); + } + } +} \ No newline at end of file From e53486af6f55d217403524463b314a7640e29c58 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Sat, 7 Oct 2023 21:48:51 +0200 Subject: [PATCH 05/18] Added a global seed for the bogus randomizer to ensure determinism in test --- .../WebApplication/BaseIntegrationTest.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/coffeecard/CoffeeCard.Tests.Integration/WebApplication/BaseIntegrationTest.cs b/coffeecard/CoffeeCard.Tests.Integration/WebApplication/BaseIntegrationTest.cs index fc4b792b..4b418bc8 100644 --- a/coffeecard/CoffeeCard.Tests.Integration/WebApplication/BaseIntegrationTest.cs +++ b/coffeecard/CoffeeCard.Tests.Integration/WebApplication/BaseIntegrationTest.cs @@ -26,6 +26,10 @@ public abstract class BaseIntegrationTest : CustomWebApplicationFactory protected BaseIntegrationTest(CustomWebApplicationFactory factory) { + // Set the random seed used for generation of data in the builders + // This ensures our tests are deterministic within a specific version of the code + var seed = new Random(42); + Bogus.Randomizer.Seed = seed; _factory = factory; _scope = _factory.Services.CreateScope(); From 9a49f41f057f4a5a324d63e8653e569760a9c36a Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Sat, 7 Oct 2023 21:52:28 +0200 Subject: [PATCH 06/18] Added source generator, that is able to generate builder methods i.e. withPropertyName for classes tagged with the marking attribute BuilderForAttribute --- .../Builder/BuilderGenerator.cs | 92 +++++++++++++++++++ .../CoffeeCard.Generators.csproj | 19 ++++ .../BuilderForAttribute.cs | 17 ++++ coffeecard/CoffeeCardAPI.sln | 6 ++ 4 files changed, 134 insertions(+) create mode 100644 coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs create mode 100644 coffeecard/CoffeeCard.Generators/CoffeeCard.Generators.csproj create mode 100644 coffeecard/CoffeeCard.Tests.Common/BuilderForAttribute.cs diff --git a/coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs b/coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs new file mode 100644 index 00000000..c0ccfb3b --- /dev/null +++ b/coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs @@ -0,0 +1,92 @@ +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; + +namespace CoffeeCard.Generators.Builder; + +[Generator] +public class BuilderGenerator : IIncrementalGenerator +{ + private const string BuilderForAttribute = "CoffeeCard.Tests.Common.BuilderForAttribute"; + + public void Initialize(IncrementalGeneratorInitializationContext context) + { + var namedTypeSymbols = context.SyntaxProvider + .ForAttributeWithMetadataName( + fullyQualifiedMetadataName: BuilderForAttribute, + predicate: IsSyntaxTargetForGeneration, + transform: GetSemanticTargetForGeneration) + .Where(t => t is not null).Collect(); + + context.RegisterSourceOutput(namedTypeSymbols, (productionContext, array) => + { + foreach (var typeSymbol in array) + { + //Retrieve the entity it is a builder for + var entity = (INamedTypeSymbol)typeSymbol.GetAttributes() + .Single(attr => attr.AttributeClass.Name == "BuilderForAttribute").ConstructorArguments[0].Value; + var code = GenerateBuilderCode(typeSymbol, entity); + var sourceText = SourceText.From(code, Encoding.UTF8); + productionContext.AddSource($"{typeSymbol.Name}.g.cs", sourceText); + } + }); + } + + private static bool IsSyntaxTargetForGeneration( + SyntaxNode syntaxNode, + CancellationToken cancellationToken) + { + return syntaxNode is ClassDeclarationSyntax classDeclaration; + } + + private static INamedTypeSymbol GetSemanticTargetForGeneration(GeneratorAttributeSyntaxContext context, + CancellationToken cancellationToken) + { + return (INamedTypeSymbol)context.TargetSymbol; + } + + private string GenerateBuilderCode(INamedTypeSymbol typeSymbol, ITypeSymbol entity) + { + var codeBuilder = new StringBuilder(); + + codeBuilder.AppendLine("// "); + codeBuilder.AppendLine("using System;"); + codeBuilder.AppendLine("using CoffeeCard.Models.Entities;"); + codeBuilder.AppendLine(); + codeBuilder.AppendLine("namespace CoffeeCard.Tests.Common.Builders;"); + codeBuilder.AppendLine(); + + codeBuilder.AppendLine($"public partial class {typeSymbol.Name} : BaseBuilder<{entity.Name}>"); + codeBuilder.AppendLine("{"); + + // Generate your builder methods here + var properties = entity.GetMembers().OfType().Where(p => p.Kind == SymbolKind.Property); + + foreach (var property in properties) + { + codeBuilder.AppendLine( + $" public {typeSymbol.Name} With{property.Name}({property.Type} {property.Name}Value)"); + codeBuilder.AppendLine(" {"); + // Faker.RuleFor(u => u.Id, f => f.IndexGlobal) + + codeBuilder.AppendLine( + $" Faker.RuleFor({entity.Name[0]} => {entity.Name[0]}.{property.Name}, {property.Name}Value);"); + codeBuilder.AppendLine(" return this;"); + codeBuilder.AppendLine(" }"); + + codeBuilder.AppendLine( + $" public {typeSymbol.Name} With{property.Name}(Func {property.Name}Setter)"); + codeBuilder.AppendLine(" {"); + + codeBuilder.AppendLine( + $" Faker.RuleFor({entity.Name[0]} => {entity.Name[0]}.{property.Name}, {property.Name}Setter);"); + codeBuilder.AppendLine(" return this;"); + codeBuilder.AppendLine(" }"); + } + + codeBuilder.AppendLine("}"); + + return codeBuilder.ToString(); + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Generators/CoffeeCard.Generators.csproj b/coffeecard/CoffeeCard.Generators/CoffeeCard.Generators.csproj new file mode 100644 index 00000000..9529a0b1 --- /dev/null +++ b/coffeecard/CoffeeCard.Generators/CoffeeCard.Generators.csproj @@ -0,0 +1,19 @@ + + + + netstandard2.0 + enable + enable + 11.0 + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/coffeecard/CoffeeCard.Tests.Common/BuilderForAttribute.cs b/coffeecard/CoffeeCard.Tests.Common/BuilderForAttribute.cs new file mode 100644 index 00000000..381492a7 --- /dev/null +++ b/coffeecard/CoffeeCard.Tests.Common/BuilderForAttribute.cs @@ -0,0 +1,17 @@ +namespace CoffeeCard.Tests.Common; + +/// +/// Serves as a marker attribute used for source generation +/// The Type given, will have builder methods generated for it +/// The methods will be in the format WithPropertyName and allow for fluent api style configuration +/// +[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +sealed class BuilderForAttribute : Attribute +{ + public Type EntityType { get; } + + public BuilderForAttribute(Type entityType) + { + EntityType = entityType; + } +} \ No newline at end of file diff --git a/coffeecard/CoffeeCardAPI.sln b/coffeecard/CoffeeCardAPI.sln index 469ddd18..bc8b6641 100644 --- a/coffeecard/CoffeeCardAPI.sln +++ b/coffeecard/CoffeeCardAPI.sln @@ -21,6 +21,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.MobilePay.Genera EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoffeeCard.Common.Test", "CoffeeCard.Tests.Common\CoffeeCard.Tests.Common.csproj", "{938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoffeeCard.Generators", "CoffeeCard.Generators\CoffeeCard.Generators.csproj", "{BE332D7E-FD07-4878-B7E3-A06988F0C382}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -63,6 +65,10 @@ Global {938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}.Debug|Any CPU.Build.0 = Debug|Any CPU {938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}.Release|Any CPU.ActiveCfg = Release|Any CPU {938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}.Release|Any CPU.Build.0 = Release|Any CPU + {BE332D7E-FD07-4878-B7E3-A06988F0C382}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE332D7E-FD07-4878-B7E3-A06988F0C382}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE332D7E-FD07-4878-B7E3-A06988F0C382}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE332D7E-FD07-4878-B7E3-A06988F0C382}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 70ddaa8f665244acd5a4b7a47c7da3d168fd4e6c Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Thu, 12 Oct 2023 17:24:34 +0200 Subject: [PATCH 07/18] Refactored BuilderGenerator --- .../Builder/BuilderGenerator.cs | 72 +++++++++++++------ 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs b/coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs index c0ccfb3b..4f65d9ce 100644 --- a/coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs +++ b/coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs @@ -52,41 +52,71 @@ private string GenerateBuilderCode(INamedTypeSymbol typeSymbol, ITypeSymbol enti codeBuilder.AppendLine("// "); codeBuilder.AppendLine("using System;"); - codeBuilder.AppendLine("using CoffeeCard.Models.Entities;"); + codeBuilder.AppendLine($"using {entity.ContainingNamespace};"); codeBuilder.AppendLine(); codeBuilder.AppendLine("namespace CoffeeCard.Tests.Common.Builders;"); codeBuilder.AppendLine(); - codeBuilder.AppendLine($"public partial class {typeSymbol.Name} : BaseBuilder<{entity.Name}>"); + codeBuilder.AppendLine($"public partial class {typeSymbol.Name} : BaseBuilder<{entity.Name}>, IBuilder<{typeSymbol.Name}>"); codeBuilder.AppendLine("{"); - // Generate your builder methods here + // Retrieve all properties of the given entity var properties = entity.GetMembers().OfType().Where(p => p.Kind == SymbolKind.Property); + var entityNameChar = entity.Name.ToLowerInvariant()[0]; + // Generate builder methods for all properties foreach (var property in properties) { - codeBuilder.AppendLine( - $" public {typeSymbol.Name} With{property.Name}({property.Type} {property.Name}Value)"); - codeBuilder.AppendLine(" {"); - // Faker.RuleFor(u => u.Id, f => f.IndexGlobal) - - codeBuilder.AppendLine( - $" Faker.RuleFor({entity.Name[0]} => {entity.Name[0]}.{property.Name}, {property.Name}Value);"); - codeBuilder.AppendLine(" return this;"); - codeBuilder.AppendLine(" }"); - - codeBuilder.AppendLine( - $" public {typeSymbol.Name} With{property.Name}(Func {property.Name}Setter)"); - codeBuilder.AppendLine(" {"); - - codeBuilder.AppendLine( - $" Faker.RuleFor({entity.Name[0]} => {entity.Name[0]}.{property.Name}, {property.Name}Setter);"); - codeBuilder.AppendLine(" return this;"); - codeBuilder.AppendLine(" }"); + AddWithPropertyValueToCodeBuilder(codeBuilder: codeBuilder, + typeSymbol: typeSymbol, + property: property, + entityNameChar: entityNameChar); + + AddWithPropertySetterToCodeBuilder( + codeBuilder: codeBuilder, + typeSymbol: typeSymbol, + property: property, + entityNameChar: entityNameChar); } + // End class codeBuilder.AppendLine("}"); return codeBuilder.ToString(); } + + /// + /// Generates a private constructor for the builder, to ensure the simple, or typical methods are used for instantiation + /// + /// + /// + private void AddPrivateConstructorToCodeBuilder(StringBuilder codeBuilder, ITypeSymbol typeSymbol) + { + codeBuilder.AppendLine( + $" private {typeSymbol.Name} ()"); + codeBuilder.AppendLine(" {}"); + } + + private void AddWithPropertyValueToCodeBuilder(StringBuilder codeBuilder, ITypeSymbol typeSymbol ,IPropertySymbol property, char entityNameChar) + { + codeBuilder.AppendLine( + $" public {typeSymbol.Name} With{property.Name}({property.Type} {property.Name}Value)"); + codeBuilder.AppendLine(" {"); + + codeBuilder.AppendLine( + $" Faker.RuleFor({entityNameChar} => {entityNameChar}.{property.Name}, {property.Name}Value);"); + codeBuilder.AppendLine(" return this;"); + codeBuilder.AppendLine(" }"); + } + private void AddWithPropertySetterToCodeBuilder(StringBuilder codeBuilder, ITypeSymbol typeSymbol ,IPropertySymbol property, char entityNameChar) + { + codeBuilder.AppendLine( + $" public {typeSymbol.Name} With{property.Name}(Func {property.Name}Setter)"); + codeBuilder.AppendLine(" {"); + + codeBuilder.AppendLine( + $" Faker.RuleFor({entityNameChar} => {entityNameChar}.{property.Name}, {property.Name}Setter);"); + codeBuilder.AppendLine(" return this;"); + codeBuilder.AppendLine(" }"); + } } \ No newline at end of file From 4d63139b143aac4c89fe537c18941615d1a8353e Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Thu, 12 Oct 2023 17:25:23 +0200 Subject: [PATCH 08/18] Updated builders and integration tests to make use of generated code --- .../Builders/BaseBuilder.cs | 33 ++++++++++----- .../Builders/ProductBuilder.cs | 18 ++++---- .../Builders/ProductUserGroupBuilder.cs | 17 ++++---- .../Builders/ProgrammeBuilder.cs | 17 ++++---- .../Builders/PurchaseBuilder.cs | 21 +++++----- .../Builders/StatisticBuilder.cs | 14 +++---- .../Builders/TicketBuilder.cs | 22 +++++----- .../Builders/TokenBuilder.cs | 13 +++--- .../Builders/UserBuilder.cs | 41 ++++++++++--------- .../Builders/VoucherBuilder.cs | 19 ++++----- .../CoffeeCard.Tests.Common.csproj | 7 +--- .../Controllers/Account/GetAccountTest.cs | 2 +- .../Controllers/Account/LoginTest.cs | 4 +- 13 files changed, 121 insertions(+), 107 deletions(-) diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs index e19cc81d..bdea99c1 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs @@ -3,33 +3,44 @@ namespace CoffeeCard.Tests.Common.Builders { - public abstract class BaseBuilder where T : class + public abstract class BaseBuilder where T: class { protected readonly AutoFaker Faker = new(); protected BaseBuilder() { Faker.Configure(builder => builder.WithConventions()); } + + /// + /// Creates a new instance of type T, + /// using the configuration set by + /// + public T Build(){ + return Faker.Generate(); + } + + /// + /// Creates a new list of type T, + /// using the configuration set by + /// + public List Build(int count){ + return Faker.Generate(count); + } + } + public interface IBuilder where T: class + { /// /// Gives a standard configured builder, /// where lists of linked entities are empty /// and nullable enities are null /// - public abstract BaseBuilder Simple(); + public static abstract T Simple(); /// /// Gives a standard configured builder, /// where all linked entities are populated /// - public abstract BaseBuilder Typical(); - - /// - /// Creates a new instance of type T, - /// using the configuration set by - /// - public T Build(){ - return Faker.Generate(); - } + public static abstract T Typical(); } } \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/ProductBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/ProductBuilder.cs index ce633748..50db3e93 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/ProductBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/ProductBuilder.cs @@ -2,19 +2,19 @@ namespace CoffeeCard.Tests.Common.Builders { - public class ProductBuilder : BaseBuilder + [BuilderFor(typeof(Product))] + public partial class ProductBuilder { - public override ProductBuilder Simple() + public static ProductBuilder Simple() { - Faker.RuleFor(p => p.Id, f => f.IndexGlobal) - .RuleFor(p => p.Name, f => f.Commerce.Product()) - .RuleFor(p => p.Description, f => f.Commerce.ProductDescription()) - .RuleFor(p => p.NumberOfTickets, f => f.PickRandom(1, 10)) - .RuleFor(p => p.ProductUserGroup, new List()); - return this; + return new ProductBuilder() + .WithName(f => f.Commerce.ProductName()) + .WithDescription(f => f.Commerce.ProductDescription()) + .WithNumberOfTickets(f => f.PickRandom(1, 10)) + .WithProductUserGroup(new List()); } - public override ProductBuilder Typical() + public static ProductBuilder Typical() { return Simple(); } diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/ProductUserGroupBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/ProductUserGroupBuilder.cs index e17a17d3..91011ab0 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/ProductUserGroupBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/ProductUserGroupBuilder.cs @@ -2,18 +2,19 @@ namespace CoffeeCard.Tests.Common.Builders { - public class ProductUserGroupBuilder : BaseBuilder + [BuilderFor(typeof(ProductUserGroup))] + public partial class ProductUserGroupBuilder { - public override ProductUserGroupBuilder Simple() + public static ProductUserGroupBuilder Simple() { - var product = new ProductBuilder().Simple().Build(); - Faker.RuleFor(p => p.Product, product) - .RuleFor(p => p.ProductId, product.Id) - .RuleFor(p => p.UserGroup, f => f.PickRandom(UserGroup.Barista, UserGroup.Board, UserGroup.Customer, UserGroup.Manager)); - return this; + var product = ProductBuilder.Simple().Build(); + return new ProductUserGroupBuilder() + .WithProduct(product) + .WithUserGroup(f => + f.PickRandom(UserGroup.Barista, UserGroup.Board, UserGroup.Customer, UserGroup.Manager)); } - public override ProductUserGroupBuilder Typical() + public static ProductUserGroupBuilder Typical() { return Simple(); } diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/ProgrammeBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/ProgrammeBuilder.cs index ae982fdd..9492f532 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/ProgrammeBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/ProgrammeBuilder.cs @@ -2,18 +2,19 @@ namespace CoffeeCard.Tests.Common.Builders { - public class ProgrammeBuilder : BaseBuilder + [BuilderFor(typeof(Programme))] + public partial class ProgrammeBuilder { - public override ProgrammeBuilder Simple() + public static ProgrammeBuilder Simple() { - Faker.RuleFor(p => p.Id, f => f.IndexGlobal) - .RuleFor(p => p.FullName, f => f.Commerce.Department()) - .RuleFor(p => p.ShortName, f => f.Random.String2(3)) - .RuleFor(p => p.Users, () => new List()); - return this; + return new ProgrammeBuilder() + //TODO ID? + .WithUsers(new List()) + .WithShortName(f => f.Random.String2(3)) + .WithFullName(f => f.Commerce.Department()); } - public override ProgrammeBuilder Typical() + public static ProgrammeBuilder Typical() { return Simple(); } diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/PurchaseBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/PurchaseBuilder.cs index 03e60f3a..6839f628 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/PurchaseBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/PurchaseBuilder.cs @@ -2,20 +2,21 @@ namespace CoffeeCard.Tests.Common.Builders { - public class PurchaseBuilder : BaseBuilder + [BuilderFor(typeof(Purchase))] + public partial class PurchaseBuilder { - public override PurchaseBuilder Simple() + public static PurchaseBuilder Simple() { - var purchasedBy = new UserBuilder().Simple().Build(); - Faker.RuleFor(p => p.Id, f => f.IndexGlobal) - .RuleFor(p => p.PurchasedBy, purchasedBy) - .RuleFor(p => p.PurchasedById, purchasedBy.Id) - .RuleFor(p => p.Tickets, new List()) - .RuleFor(p => p.NumberOfTickets, 0); - return this; + var purchasedBy = UserBuilder.Simple().Build(); + //TODO id and purseById? + return new PurchaseBuilder().WithPurchasedBy(purchasedBy) + .WithProductName(f => f.Commerce.ProductName()) + .WithTickets(new List()) + .WithTickets(new List()) + .WithNumberOfTickets(0); } - public override PurchaseBuilder Typical() + public static PurchaseBuilder Typical() { return Simple(); } diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs index 296b506a..f74122ef 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs @@ -2,17 +2,17 @@ namespace CoffeeCard.Tests.Common.Builders { - public class StatisticBuilder : BaseBuilder + [BuilderFor(typeof(Statistic))] + public partial class StatisticBuilder { - public override StatisticBuilder Simple() + public static StatisticBuilder Simple() { - var user = new UserBuilder().Simple().Build(); - Faker.RuleFor(p => p.Id, f => f.IndexGlobal) - .RuleFor(p => p.User, user); - return this; + var user = UserBuilder.Simple().Build(); + return new StatisticBuilder() + .WithUser(user);; } - public override StatisticBuilder Typical() + public static StatisticBuilder Typical() { return Simple(); } diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/TicketBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/TicketBuilder.cs index 0f996000..29205fe6 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/TicketBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/TicketBuilder.cs @@ -2,22 +2,20 @@ namespace CoffeeCard.Tests.Common.Builders { - public class TicketBuilder : BaseBuilder + [BuilderFor(typeof(Ticket))] + public partial class TicketBuilder { - public override TicketBuilder Simple() + public static TicketBuilder Simple() { - var owner = new UserBuilder().Simple().Build(); - var purchase = new PurchaseBuilder().Simple().Build(); - Faker.RuleFor(p => p.Id, f => f.IndexGlobal) - .RuleFor(p => p.Owner, owner) - .RuleFor(p => p.OwnerId, owner.Id) - .RuleFor(p => p.Purchase, f => purchase) - .RuleFor(p => p.PurchaseId, purchase.Id); - - return this; + var owner = UserBuilder.Simple().Build(); + var purchase = PurchaseBuilder.Simple().Build(); + //TODO Ids? + return new TicketBuilder() + .WithOwner(owner) + .WithPurchase(purchase); } - public override TicketBuilder Typical() + public static TicketBuilder Typical() { return Simple(); } diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/TokenBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/TokenBuilder.cs index 537fed92..8502214c 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/TokenBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/TokenBuilder.cs @@ -2,16 +2,17 @@ namespace CoffeeCard.Tests.Common.Builders { - public class TokenBuilder : BaseBuilder + [BuilderFor(typeof(Token))] + public partial class TokenBuilder { - public override TokenBuilder Simple() + public static TokenBuilder Simple() { - Faker.RuleFor(p => p.Id, f => f.IndexGlobal) - .RuleFor(p => p.User, new UserBuilder().Simple().Build()); - return this; + return new TokenBuilder() + //TODO id? + .WithUser(UserBuilder.Simple().Build()); } - public override TokenBuilder Typical() + public static TokenBuilder Typical() { return Simple(); } diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs index 359a257a..ec2c1505 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs @@ -2,30 +2,33 @@ namespace CoffeeCard.Tests.Common.Builders { - public class UserBuilder : BaseBuilder + [BuilderFor(typeof(User))] + public partial class UserBuilder { - public override UserBuilder Simple() + public static UserBuilder Simple() { - var programme = new ProgrammeBuilder().Simple().Build(); - Faker.RuleFor(u => u.Id, f => f.IndexGlobal) - .RuleFor(u => u.ProgrammeId, programme.Id) - .RuleFor(u => u.Programme, programme) - .RuleFor(u => u.Purchases, new List()) - .RuleFor(u => u.Statistics, new List()) - .RuleFor(u => u.LoginAttempts, new List()) - .RuleFor(u => u.Tokens, new List()) - .RuleFor(u => u.UserState, UserState.Active) - .RuleFor(u => u.IsVerified, true) - .RuleFor(u => u.Tickets, new List()); - return this; + var programme = new ProgrammeBuilder().Simple().Build(); + + return new UserBuilder() + // ID? + //todo programme ID? + .WithProgramme(programme) + .WithPurchases(new List()) + .WithStatistics(new List()) + .WithLoginAttempts(new List()) + .WithTokens(new List()) + .WithUserState(UserState.Active) + .WithTickets(new List()); } - public UserBuilder DefaultCustomer(){ - Faker.RuleFor(u => u.UserGroup, UserGroup.Customer); - return Simple(); - } + public static UserBuilder DefaultCustomer() + { + return Simple() + .WithUserGroup(UserGroup.Customer) + .WithIsVerified(true); + } - public override UserBuilder Typical() + public static UserBuilder Typical() { return Simple(); } diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/VoucherBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/VoucherBuilder.cs index 8d569c3c..90a79cce 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/VoucherBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/VoucherBuilder.cs @@ -2,20 +2,19 @@ namespace CoffeeCard.Tests.Common.Builders { - public class VoucherBuilder : BaseBuilder + [BuilderFor(typeof(Voucher))] + public partial class VoucherBuilder { - public override VoucherBuilder Simple() + public static VoucherBuilder Simple() { - var product = new ProductBuilder().Simple().Build(); - Faker.RuleFor(p => p.Id, f => f.IndexGlobal) - .RuleFor(p => p.User, f => null) - .RuleFor(v => v.UserId, f => null) - .RuleFor(v => v.Product, product) - .RuleFor(v => v.ProductId, product.Id); - return this; + var product = ProductBuilder.Simple().Build(); + //TODO ids? + return new VoucherBuilder() + .WithProduct(product) + .WithUser(f => null); } - public override VoucherBuilder Typical() + public static VoucherBuilder Typical() { return Simple(); } diff --git a/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj b/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj index 93d3f8dd..1e63820b 100644 --- a/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj +++ b/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj @@ -1,6 +1,7 @@ + @@ -9,12 +10,8 @@ - - - - - net7.0 + net7 enable enable diff --git a/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/GetAccountTest.cs b/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/GetAccountTest.cs index 28b333c0..389423aa 100644 --- a/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/GetAccountTest.cs +++ b/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/GetAccountTest.cs @@ -18,7 +18,7 @@ public GetAccountTest(CustomWebApplicationFactory factory) : base(facto [Fact] public async Task Get_account_succeeds_when_authenticated_for_existing_account() { - var user = new UserBuilder().DefaultCustomer().Build(); + var user = UserBuilder.DefaultCustomer().Build(); await Context.Users.AddAsync(user); await Context.SaveChangesAsync(); SetDefaultAuthHeader(user); diff --git a/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/LoginTest.cs b/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/LoginTest.cs index a5410d20..70336e39 100644 --- a/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/LoginTest.cs +++ b/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/LoginTest.cs @@ -32,13 +32,14 @@ public async Task Unknown_user_login_fails() var response = await Client.PostAsJsonAsync(LoginUrl, loginRequest); + Assert.Equal(UserBuilder.DefaultCustomer().Build(), UserBuilder.DefaultCustomer().Build()); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } [Fact] public async Task Known_user_login_succeeds_returns_token() { - var user = new UserBuilder().DefaultCustomer().Build(); + var user = UserBuilder.DefaultCustomer().Build(); var plaintextPassword = user.Password; user.Password = HashPassword(plaintextPassword + user.Salt); @@ -55,6 +56,7 @@ public async Task Known_user_login_succeeds_returns_token() var token = await DeserializeResponseAsync(response); Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(user, UserBuilder.DefaultCustomer().Build()); Assert.NotEmpty(token.Token!); } From 5edd2bdca17069434d4d10ac268dfb1f953e4fa4 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Thu, 12 Oct 2023 19:13:31 +0200 Subject: [PATCH 09/18] Updated userBuilder --- coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs index ec2c1505..d3f90baf 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs @@ -7,7 +7,7 @@ public partial class UserBuilder { public static UserBuilder Simple() { - var programme = new ProgrammeBuilder().Simple().Build(); + var programme = ProgrammeBuilder.Simple().Build(); return new UserBuilder() // ID? From 8c2113ebdb0e792b31bc6435f8372d57d90a0c79 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Sun, 29 Oct 2023 06:43:53 +0100 Subject: [PATCH 10/18] Updated builderGenerator to skip Ids, and removed todos from builders --- .../Builder/BuilderGenerator.cs | 28 +++++++++++++------ .../CoffeeCard.Generators.csproj | 8 ++++-- .../Builders/BaseBuilder.cs | 4 +-- .../Builders/ProgrammeBuilder.cs | 1 - .../Builders/PurchaseBuilder.cs | 1 - .../Builders/TicketBuilder.cs | 1 - .../Builders/TokenBuilder.cs | 1 - .../Builders/UserBuilder.cs | 2 -- .../Builders/VoucherBuilder.cs | 3 +- .../CoffeeCard.Tests.Common.csproj | 2 +- 10 files changed, 30 insertions(+), 21 deletions(-) diff --git a/coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs b/coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs index 4f65d9ce..cf916185 100644 --- a/coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs +++ b/coffeecard/CoffeeCard.Generators/Builder/BuilderGenerator.cs @@ -52,9 +52,10 @@ private string GenerateBuilderCode(INamedTypeSymbol typeSymbol, ITypeSymbol enti codeBuilder.AppendLine("// "); codeBuilder.AppendLine("using System;"); + codeBuilder.AppendLine("using AutoBogus.Conventions;"); codeBuilder.AppendLine($"using {entity.ContainingNamespace};"); codeBuilder.AppendLine(); - codeBuilder.AppendLine("namespace CoffeeCard.Tests.Common.Builders;"); + codeBuilder.AppendLine($"namespace {typeSymbol.ContainingNamespace};"); codeBuilder.AppendLine(); codeBuilder.AppendLine($"public partial class {typeSymbol.Name} : BaseBuilder<{entity.Name}>, IBuilder<{typeSymbol.Name}>"); @@ -65,19 +66,25 @@ private string GenerateBuilderCode(INamedTypeSymbol typeSymbol, ITypeSymbol enti var entityNameChar = entity.Name.ToLowerInvariant()[0]; // Generate builder methods for all properties + var configBuilder = new StringBuilder(); foreach (var property in properties) { + if (property.Name.Contains("Id")) + { + configBuilder.AppendLine($" .WithSkip<{entity.Name}>(\"{property.Name}\")"); + } AddWithPropertyValueToCodeBuilder(codeBuilder: codeBuilder, - typeSymbol: typeSymbol, + typeSymbol: typeSymbol, property: property, entityNameChar: entityNameChar); AddWithPropertySetterToCodeBuilder( codeBuilder: codeBuilder, - typeSymbol: typeSymbol, + typeSymbol: typeSymbol, property: property, entityNameChar: entityNameChar); } + AddPrivateConstructorToCodeBuilder(codeBuilder, typeSymbol, configBuilder); // End class codeBuilder.AppendLine("}"); @@ -90,14 +97,19 @@ private string GenerateBuilderCode(INamedTypeSymbol typeSymbol, ITypeSymbol enti /// /// /// - private void AddPrivateConstructorToCodeBuilder(StringBuilder codeBuilder, ITypeSymbol typeSymbol) + /// + private void AddPrivateConstructorToCodeBuilder(StringBuilder codeBuilder, ITypeSymbol typeSymbol, StringBuilder configBuilder) { codeBuilder.AppendLine( $" private {typeSymbol.Name} ()"); - codeBuilder.AppendLine(" {}"); - } + codeBuilder.AppendLine(" {"); + codeBuilder.AppendLine(" Faker.Configure(builder => builder"); + codeBuilder.Append($"{configBuilder}"); + codeBuilder.AppendLine(" .WithConventions());"); + codeBuilder.AppendLine(" }"); + } - private void AddWithPropertyValueToCodeBuilder(StringBuilder codeBuilder, ITypeSymbol typeSymbol ,IPropertySymbol property, char entityNameChar) + private void AddWithPropertyValueToCodeBuilder(StringBuilder codeBuilder, ITypeSymbol typeSymbol, IPropertySymbol property, char entityNameChar) { codeBuilder.AppendLine( $" public {typeSymbol.Name} With{property.Name}({property.Type} {property.Name}Value)"); @@ -108,7 +120,7 @@ private void AddWithPropertyValueToCodeBuilder(StringBuilder codeBuilder, ITypeS codeBuilder.AppendLine(" return this;"); codeBuilder.AppendLine(" }"); } - private void AddWithPropertySetterToCodeBuilder(StringBuilder codeBuilder, ITypeSymbol typeSymbol ,IPropertySymbol property, char entityNameChar) + private void AddWithPropertySetterToCodeBuilder(StringBuilder codeBuilder, ITypeSymbol typeSymbol, IPropertySymbol property, char entityNameChar) { codeBuilder.AppendLine( $" public {typeSymbol.Name} With{property.Name}(Func {property.Name}Setter)"); diff --git a/coffeecard/CoffeeCard.Generators/CoffeeCard.Generators.csproj b/coffeecard/CoffeeCard.Generators/CoffeeCard.Generators.csproj index 9529a0b1..345c8608 100644 --- a/coffeecard/CoffeeCard.Generators/CoffeeCard.Generators.csproj +++ b/coffeecard/CoffeeCard.Generators/CoffeeCard.Generators.csproj @@ -6,14 +6,18 @@ enable 11.0 + + $(BaseIntermediateOutputPath)GeneratedCode\ + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs index bdea99c1..28d7fc7d 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs @@ -13,7 +13,7 @@ protected BaseBuilder() /// /// Creates a new instance of type T, - /// using the configuration set by + /// using the configuration set by using the builderMethods /// public T Build(){ return Faker.Generate(); @@ -21,7 +21,7 @@ public T Build(){ /// /// Creates a new list of type T, - /// using the configuration set by + /// using the configuration set by using the builderMethods /// public List Build(int count){ return Faker.Generate(count); diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/ProgrammeBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/ProgrammeBuilder.cs index 9492f532..bda9291d 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/ProgrammeBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/ProgrammeBuilder.cs @@ -8,7 +8,6 @@ public partial class ProgrammeBuilder public static ProgrammeBuilder Simple() { return new ProgrammeBuilder() - //TODO ID? .WithUsers(new List()) .WithShortName(f => f.Random.String2(3)) .WithFullName(f => f.Commerce.Department()); diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/PurchaseBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/PurchaseBuilder.cs index 6839f628..783fcdd5 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/PurchaseBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/PurchaseBuilder.cs @@ -8,7 +8,6 @@ public partial class PurchaseBuilder public static PurchaseBuilder Simple() { var purchasedBy = UserBuilder.Simple().Build(); - //TODO id and purseById? return new PurchaseBuilder().WithPurchasedBy(purchasedBy) .WithProductName(f => f.Commerce.ProductName()) .WithTickets(new List()) diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/TicketBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/TicketBuilder.cs index 29205fe6..716835ca 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/TicketBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/TicketBuilder.cs @@ -9,7 +9,6 @@ public static TicketBuilder Simple() { var owner = UserBuilder.Simple().Build(); var purchase = PurchaseBuilder.Simple().Build(); - //TODO Ids? return new TicketBuilder() .WithOwner(owner) .WithPurchase(purchase); diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/TokenBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/TokenBuilder.cs index 8502214c..fb6d090b 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/TokenBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/TokenBuilder.cs @@ -8,7 +8,6 @@ public partial class TokenBuilder public static TokenBuilder Simple() { return new TokenBuilder() - //TODO id? .WithUser(UserBuilder.Simple().Build()); } diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs index d3f90baf..15b83e69 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/UserBuilder.cs @@ -10,8 +10,6 @@ public static UserBuilder Simple() var programme = ProgrammeBuilder.Simple().Build(); return new UserBuilder() - // ID? - //todo programme ID? .WithProgramme(programme) .WithPurchases(new List()) .WithStatistics(new List()) diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/VoucherBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/VoucherBuilder.cs index 90a79cce..90530e6a 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/VoucherBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/VoucherBuilder.cs @@ -7,8 +7,7 @@ public partial class VoucherBuilder { public static VoucherBuilder Simple() { - var product = ProductBuilder.Simple().Build(); - //TODO ids? + var product = ProductBuilder.Simple().Build(); return new VoucherBuilder() .WithProduct(product) .WithUser(f => null); diff --git a/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj b/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj index 1e63820b..1ea0d662 100644 --- a/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj +++ b/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj @@ -11,7 +11,7 @@ - net7 + net7.0 enable enable From 36d64e421fd2f6da41dda8d296452571be70f301 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Sun, 29 Oct 2023 06:45:34 +0100 Subject: [PATCH 11/18] Cleaned up LoginTest --- .../Controllers/Account/LoginTest.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/LoginTest.cs b/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/LoginTest.cs index 70336e39..191aa661 100644 --- a/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/LoginTest.cs +++ b/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/LoginTest.cs @@ -32,7 +32,6 @@ public async Task Unknown_user_login_fails() var response = await Client.PostAsJsonAsync(LoginUrl, loginRequest); - Assert.Equal(UserBuilder.DefaultCustomer().Build(), UserBuilder.DefaultCustomer().Build()); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } @@ -56,7 +55,6 @@ public async Task Known_user_login_succeeds_returns_token() var token = await DeserializeResponseAsync(response); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal(user, UserBuilder.DefaultCustomer().Build()); Assert.NotEmpty(token.Token!); } From ade9ca9a4ecdb1bc7249ea1caeff68f4868812e3 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Sun, 29 Oct 2023 13:45:46 +0100 Subject: [PATCH 12/18] Updated docker file to dotnet 7 --- coffeecard/CoffeeCard.WebApi/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coffeecard/CoffeeCard.WebApi/Dockerfile b/coffeecard/CoffeeCard.WebApi/Dockerfile index 63d1ca9e..8a8af53b 100644 --- a/coffeecard/CoffeeCard.WebApi/Dockerfile +++ b/coffeecard/CoffeeCard.WebApi/Dockerfile @@ -1,11 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build WORKDIR /src COPY ["CoffeeCard.WebApi/CoffeeCard.WebApi.csproj", "CoffeeCard.WebApi/"] COPY ["CoffeeCard.Common/CoffeeCard.Common.csproj", "CoffeeCard.Common/"] From 8a450da159e6f7eec209558f93051c8e9b664f51 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Sun, 29 Oct 2023 13:49:59 +0100 Subject: [PATCH 13/18] Ran formatter --- .../Builders/BaseBuilder.cs | 12 ++++--- .../Builders/StatisticBuilder.cs | 4 +-- .../Controllers/Account/GetAccountTest.cs | 35 ++++++++++--------- .../WebApplication/BaseIntegrationTest.cs | 2 +- .../CustomWebApplicationFactory.cs | 2 +- 5 files changed, 29 insertions(+), 26 deletions(-) diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs index 28d7fc7d..2762820a 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/BaseBuilder.cs @@ -3,19 +3,20 @@ namespace CoffeeCard.Tests.Common.Builders { - public abstract class BaseBuilder where T: class + public abstract class BaseBuilder where T : class { protected readonly AutoFaker Faker = new(); protected BaseBuilder() { Faker.Configure(builder => builder.WithConventions()); } - + /// /// Creates a new instance of type T, /// using the configuration set by using the builderMethods /// - public T Build(){ + public T Build() + { return Faker.Generate(); } @@ -23,12 +24,13 @@ public T Build(){ /// Creates a new list of type T, /// using the configuration set by using the builderMethods /// - public List Build(int count){ + public List Build(int count) + { return Faker.Generate(count); } } - public interface IBuilder where T: class + public interface IBuilder where T : class { /// /// Gives a standard configured builder, diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs index f74122ef..12fe2455 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs @@ -7,9 +7,9 @@ public partial class StatisticBuilder { public static StatisticBuilder Simple() { - var user = UserBuilder.Simple().Build(); + var user = UserBuilder.Simple().Build(); return new StatisticBuilder() - .WithUser(user);; + .WithUser(user); ; } public static StatisticBuilder Typical() diff --git a/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/GetAccountTest.cs b/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/GetAccountTest.cs index 389423aa..a35c64da 100644 --- a/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/GetAccountTest.cs +++ b/coffeecard/CoffeeCard.Tests.Integration/Controllers/Account/GetAccountTest.cs @@ -6,31 +6,32 @@ using CoffeeCard.Tests.Common.Builders; using CoffeeCard.Models.Entities; -namespace CoffeeCard.Tests.Integration.Controllers.Account { +namespace CoffeeCard.Tests.Integration.Controllers.Account +{ public class GetAccountTest : BaseIntegrationTest { - private const string GetAccountUrl = "api/v2/account"; + private const string GetAccountUrl = "api/v2/account"; public GetAccountTest(CustomWebApplicationFactory factory) : base(factory) { } - [Fact] - public async Task Get_account_succeeds_when_authenticated_for_existing_account() - { - var user = UserBuilder.DefaultCustomer().Build(); - await Context.Users.AddAsync(user); - await Context.SaveChangesAsync(); - SetDefaultAuthHeader(user); + [Fact] + public async Task Get_account_succeeds_when_authenticated_for_existing_account() + { + var user = UserBuilder.DefaultCustomer().Build(); + await Context.Users.AddAsync(user); + await Context.SaveChangesAsync(); + SetDefaultAuthHeader(user); + + var response = await Client.GetAsync(GetAccountUrl); + var account = await DeserializeResponseAsync(response); - var response = await Client.GetAsync(GetAccountUrl); - var account = await DeserializeResponseAsync(response); + Assert.Equal(user.Email, account.Email); + Assert.Equal(user.Name, account.Name); + Assert.Equal(user.Programme.FullName, account.Programme.FullName); + Assert.Equal(user.UserGroup.toUserRole(), account.Role); + } - Assert.Equal(user.Email, account.Email); - Assert.Equal(user.Name, account.Name); - Assert.Equal(user.Programme.FullName, account.Programme.FullName); - Assert.Equal(user.UserGroup.toUserRole(), account.Role); - } - } } \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Integration/WebApplication/BaseIntegrationTest.cs b/coffeecard/CoffeeCard.Tests.Integration/WebApplication/BaseIntegrationTest.cs index 4b418bc8..155d71f3 100644 --- a/coffeecard/CoffeeCard.Tests.Integration/WebApplication/BaseIntegrationTest.cs +++ b/coffeecard/CoffeeCard.Tests.Integration/WebApplication/BaseIntegrationTest.cs @@ -89,7 +89,7 @@ private CoffeeCardContext GetCoffeeCardContext() // Ensure the database is cleaned for each test run context.Database.EnsureDeleted(); context.Database.EnsureCreated(); - + return context; } diff --git a/coffeecard/CoffeeCard.Tests.Integration/WebApplication/CustomWebApplicationFactory.cs b/coffeecard/CoffeeCard.Tests.Integration/WebApplication/CustomWebApplicationFactory.cs index 424da64f..8037cf50 100644 --- a/coffeecard/CoffeeCard.Tests.Integration/WebApplication/CustomWebApplicationFactory.cs +++ b/coffeecard/CoffeeCard.Tests.Integration/WebApplication/CustomWebApplicationFactory.cs @@ -51,7 +51,7 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) // Build the service provider var sp = services.BuildServiceProvider(); - + }); } } From 1521d391decbf10aa067ff09054e87ddeee5976e Mon Sep 17 00:00:00 2001 From: TTA777 Date: Thu, 4 Jan 2024 20:28:45 +0100 Subject: [PATCH 14/18] Bumped project to .net8 --- .github/workflows/core-build.yml | 2 +- .../CoffeeCard.Common.csproj | 2 +- .../CoffeeCard.Generators.csproj | 4 +- .../CoffeeCard.Library.csproj | 81 +++++++++---------- .../CoffeeCard.MobilePay.csproj | 10 +-- .../CoffeeCard.Models.csproj | 36 ++++----- .../v2/Purchase/FreeProductPaymentDetails.cs | 2 +- .../v2/Purchase/MobilePayPaymentDetails.cs | 2 +- .../v2/Purchase/PaymentDetails.cs | 2 +- .../Builders/StatisticBuilder.cs | 4 +- .../CoffeeCard.Tests.Common.csproj | 10 +-- .../CoffeeCard.Tests.Integration.csproj | 14 ++-- .../CoffeeCard.Tests.Unit.csproj | 4 +- .../CoffeeCard.WebApi.csproj | 22 ++--- coffeecard/CoffeeCard.WebApi/Startup.cs | 6 +- coffeecard/CoffeeCardAPI.sln | 2 +- coffeecard/global.json | 6 +- 17 files changed, 98 insertions(+), 111 deletions(-) diff --git a/.github/workflows/core-build.yml b/.github/workflows/core-build.yml index 83d1321b..52e46329 100644 --- a/.github/workflows/core-build.yml +++ b/.github/workflows/core-build.yml @@ -1,7 +1,7 @@ name: Build and test solution env: - DOTNET_VERSION: 6 + DOTNET_VERSION: 8 on: workflow_call: diff --git a/coffeecard/CoffeeCard.Common/CoffeeCard.Common.csproj b/coffeecard/CoffeeCard.Common/CoffeeCard.Common.csproj index ccb60958..a5c9273e 100644 --- a/coffeecard/CoffeeCard.Common/CoffeeCard.Common.csproj +++ b/coffeecard/CoffeeCard.Common/CoffeeCard.Common.csproj @@ -1,6 +1,6 @@ - net7.0 + net8.0 33C1BE09-BD3A-4584-B195-C57B47B9063C diff --git a/coffeecard/CoffeeCard.Generators/CoffeeCard.Generators.csproj b/coffeecard/CoffeeCard.Generators/CoffeeCard.Generators.csproj index 345c8608..70d54689 100644 --- a/coffeecard/CoffeeCard.Generators/CoffeeCard.Generators.csproj +++ b/coffeecard/CoffeeCard.Generators/CoffeeCard.Generators.csproj @@ -16,8 +16,8 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/coffeecard/CoffeeCard.Library/CoffeeCard.Library.csproj b/coffeecard/CoffeeCard.Library/CoffeeCard.Library.csproj index e9b1c175..859831b4 100644 --- a/coffeecard/CoffeeCard.Library/CoffeeCard.Library.csproj +++ b/coffeecard/CoffeeCard.Library/CoffeeCard.Library.csproj @@ -1,46 +1,39 @@ - - - net6.0 - 8 - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + net8.0 + default + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/coffeecard/CoffeeCard.MobilePay/CoffeeCard.MobilePay.csproj b/coffeecard/CoffeeCard.MobilePay/CoffeeCard.MobilePay.csproj index 692fa9ef..6af6845e 100644 --- a/coffeecard/CoffeeCard.MobilePay/CoffeeCard.MobilePay.csproj +++ b/coffeecard/CoffeeCard.MobilePay/CoffeeCard.MobilePay.csproj @@ -1,6 +1,6 @@ - net7.0 + net8.0 AFF9D584-58F4-4A8D-A6BF-515890A9A3EF enable @@ -8,10 +8,10 @@ - - - - + + + + diff --git a/coffeecard/CoffeeCard.Models/CoffeeCard.Models.csproj b/coffeecard/CoffeeCard.Models/CoffeeCard.Models.csproj index 33b2ba20..1e4e2bb0 100644 --- a/coffeecard/CoffeeCard.Models/CoffeeCard.Models.csproj +++ b/coffeecard/CoffeeCard.Models/CoffeeCard.Models.csproj @@ -1,22 +1,18 @@ - - - net6.0 - true - enable - default - - - - - - - - - - - - - - + + net8.0 + true + enable + default + + + + + + + + + + + diff --git a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/FreeProductPaymentDetails.cs b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/FreeProductPaymentDetails.cs index 16ce980d..aee28f7d 100644 --- a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/FreeProductPaymentDetails.cs +++ b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/FreeProductPaymentDetails.cs @@ -14,7 +14,7 @@ namespace CoffeeCard.Models.DataTransferObjects.v2.Purchase /// } /// [KnownType(typeof(FreePurchasePaymentDetails))] - [JsonConverter(typeof(JsonInheritanceConverter))] + [JsonConverter(typeof(JsonInheritanceConverter))] public class FreePurchasePaymentDetails : PaymentDetails { /// diff --git a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/MobilePayPaymentDetails.cs b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/MobilePayPaymentDetails.cs index 61b8215d..5c77da0b 100644 --- a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/MobilePayPaymentDetails.cs +++ b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/MobilePayPaymentDetails.cs @@ -17,7 +17,7 @@ namespace CoffeeCard.Models.DataTransferObjects.v2.Purchase /// } /// [KnownType(typeof(MobilePayPaymentDetails))] - [JsonConverter(typeof(JsonInheritanceConverter))] + [JsonConverter(typeof(JsonInheritanceConverter))] public class MobilePayPaymentDetails : PaymentDetails { /// diff --git a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/PaymentDetails.cs b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/PaymentDetails.cs index 378d5a63..c1e54cdc 100644 --- a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/PaymentDetails.cs +++ b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/PaymentDetails.cs @@ -7,7 +7,7 @@ namespace CoffeeCard.Models.DataTransferObjects.v2.Purchase { [KnownType(typeof(MobilePayPaymentDetails))] [KnownType(typeof(FreePurchasePaymentDetails))] - [JsonConverter(typeof(JsonInheritanceConverter))] + [JsonConverter(typeof(JsonInheritanceConverter))] public abstract class PaymentDetails { /// diff --git a/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs b/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs index 12fe2455..5fa02625 100644 --- a/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs +++ b/coffeecard/CoffeeCard.Tests.Common/Builders/StatisticBuilder.cs @@ -9,7 +9,7 @@ public static StatisticBuilder Simple() { var user = UserBuilder.Simple().Build(); return new StatisticBuilder() - .WithUser(user); ; + .WithUser(user); } public static StatisticBuilder Typical() @@ -17,4 +17,4 @@ public static StatisticBuilder Typical() return Simple(); } } -} \ No newline at end of file +} diff --git a/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj b/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj index 1ea0d662..69cf9e18 100644 --- a/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj +++ b/coffeecard/CoffeeCard.Tests.Common/CoffeeCard.Tests.Common.csproj @@ -1,19 +1,15 @@ - - + - - - net7.0 + net8.0 enable enable - - + \ No newline at end of file diff --git a/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj b/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj index 62319e4d..f36b81f8 100644 --- a/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj +++ b/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj @@ -1,6 +1,6 @@  - net7.0 + net8.0 false 8 81E81CE9-7DDA-4A9B-860B-6A473BC4F06F @@ -21,12 +21,12 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - + + + + + + diff --git a/coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj b/coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj index 6c421503..47cb3679 100644 --- a/coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj +++ b/coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj @@ -1,6 +1,6 @@ - net7.0 + net8.0 false 8 24274C8F-678F-4E4D-98A0-2899163BCCBA @@ -21,7 +21,7 @@ all runtime; build; native; contentfiles; analyzers - + diff --git a/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj b/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj index fbdb6383..7df97549 100644 --- a/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj +++ b/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj @@ -1,6 +1,6 @@  - net7.0 + net8.0 InProcess 8 5562C898-513F-493A-A335-417C39476714 @@ -35,18 +35,20 @@ - + - - - - - - - + + + + + + + + + @@ -56,4 +58,4 @@ - \ No newline at end of file + diff --git a/coffeecard/CoffeeCard.WebApi/Startup.cs b/coffeecard/CoffeeCard.WebApi/Startup.cs index dc0aaa9e..ad1cffa8 100644 --- a/coffeecard/CoffeeCard.WebApi/Startup.cs +++ b/coffeecard/CoffeeCard.WebApi/Startup.cs @@ -241,7 +241,7 @@ private static void GenerateOpenApiDocument(IServiceCollection services) config.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("apikey")); // Assume not null as default unless parameter is marked as nullable - config.DefaultReferenceTypeNullHandling = ReferenceTypeNullHandling.NotNull; + // config.DefaultReferenceTypeNullHandling = ReferenceTypeNullHandling.NotNull; }); } } @@ -260,7 +260,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVers app.UseHsts(); app.UseOpenApi(); - app.UseSwaggerUi3(); + app.UseSwaggerUi(); app.UseHttpsRedirection(); @@ -289,4 +289,4 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVers } } #pragma warning restore CS1591 -} \ No newline at end of file +} diff --git a/coffeecard/CoffeeCardAPI.sln b/coffeecard/CoffeeCardAPI.sln index bc8b6641..1ae693c7 100644 --- a/coffeecard/CoffeeCardAPI.sln +++ b/coffeecard/CoffeeCardAPI.sln @@ -19,7 +19,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.Models", "Coffee EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.MobilePay.GenerateApi", "CoffeeCard.MobilePay.GenerateApi\CoffeeCard.MobilePay.GenerateApi.csproj", "{D295CCD7-DDB7-477D-82B6-53AFA97F5749}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoffeeCard.Common.Test", "CoffeeCard.Tests.Common\CoffeeCard.Tests.Common.csproj", "{938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoffeeCard.Common.Test", "CoffeeCard.Tests.Common\CoffeeCard.Tests.Common.csproj", "{938E0AD9-C1C8-4C10-B9FB-DD279DAD4D0B}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoffeeCard.Generators", "CoffeeCard.Generators\CoffeeCard.Generators.csproj", "{BE332D7E-FD07-4878-B7E3-A06988F0C382}" EndProject diff --git a/coffeecard/global.json b/coffeecard/global.json index 6fbe9d02..18b689d1 100644 --- a/coffeecard/global.json +++ b/coffeecard/global.json @@ -1,7 +1,7 @@ { "sdk": { - "version": "6.0.0", - "rollForward": "latestMajor", - "allowPrerelease": true + "version": "8.0.0", + "rollForward": "latestMinor", + "allowPrerelease": false } } From 2a5ec8630cd279a7b368939a53f1224ffe2ae53c Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Thu, 18 Jan 2024 19:06:19 +0100 Subject: [PATCH 15/18] Fixed broken tests --- .../CoffeeCard.Tests.Unit/Services/AccountServiceTest.cs | 4 ++-- .../CoffeeCard.Tests.Unit/Services/TokenServiceTest.cs | 6 +++--- coffeecard/CoffeeCard.WebApi/appsettings.json | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/coffeecard/CoffeeCard.Tests.Unit/Services/AccountServiceTest.cs b/coffeecard/CoffeeCard.Tests.Unit/Services/AccountServiceTest.cs index 34d49b41..d3ca0612 100644 --- a/coffeecard/CoffeeCard.Tests.Unit/Services/AccountServiceTest.cs +++ b/coffeecard/CoffeeCard.Tests.Unit/Services/AccountServiceTest.cs @@ -632,7 +632,7 @@ public async Task VerifyRegistrationReturnsTrueGivenValidToken() }; var identitySettings = new IdentitySettings { - TokenKey = "This is a long test token key" + TokenKey = "SuperLongSigningKeySuperLongSigningKey" }; var tokenService = new TokenService(identitySettings, new ClaimsUtilities(context)); @@ -697,7 +697,7 @@ private static string WriteTokenString(IEnumerable claims) { var tokenHandler = new JwtSecurityTokenHandler(); var key = new SymmetricSecurityKey( - Encoding.UTF8.GetBytes("This is a long test token key")); + Encoding.UTF8.GetBytes("SuperLongSigningKeySuperLongSigningKey")); var jwt = new JwtSecurityToken("AnalogIO", "Everyone", diff --git a/coffeecard/CoffeeCard.Tests.Unit/Services/TokenServiceTest.cs b/coffeecard/CoffeeCard.Tests.Unit/Services/TokenServiceTest.cs index ef628af9..3c9ddb31 100644 --- a/coffeecard/CoffeeCard.Tests.Unit/Services/TokenServiceTest.cs +++ b/coffeecard/CoffeeCard.Tests.Unit/Services/TokenServiceTest.cs @@ -22,7 +22,7 @@ public TokenServiceTest() _identity = new IdentitySettings(); //creates the key for signing the token - const string keyForHmacSha256 = "signingKey"; + const string keyForHmacSha256 = "SuperLongSigningKey"; _identity.TokenKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(keyForHmacSha256)).ToString(); } @@ -99,7 +99,7 @@ public async Task ValidateTokenGivenInvalidSignedTokenReturnsFalse() await using (context) { var key = new SymmetricSecurityKey( - Encoding.UTF8.GetBytes("Invalid signing key")); + Encoding.UTF8.GetBytes("Super long invalid signing key, longer than 256bytes")); var jwt = new JwtSecurityToken("AnalogIO", "Everyone", @@ -213,4 +213,4 @@ private CoffeeCardContext GenerateCoffeeCardContext(string uniqueString) return new CoffeeCardContext(builder.Options, databaseSettings, environmentSettings); } } -} \ No newline at end of file +} diff --git a/coffeecard/CoffeeCard.WebApi/appsettings.json b/coffeecard/CoffeeCard.WebApi/appsettings.json index a5aaf876..5f78c643 100644 --- a/coffeecard/CoffeeCard.WebApi/appsettings.json +++ b/coffeecard/CoffeeCard.WebApi/appsettings.json @@ -13,7 +13,7 @@ "SchemaName": "dbo" }, "IdentitySettings": { - "TokenKey": "local-development-token", + "TokenKey": "super-long-local-development-token", "AdminToken": "local-development-admintoken", "ApiKey": "local-development-apikey" }, @@ -43,7 +43,7 @@ "Default": "Information", "Override": { "System": "Information", - "Microsoft": "Warning" + "Microsoft": "Information" } }, "WriteTo": [ From c27c0ccf162df5619155ee59d20f17e1ad48cdb9 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Thu, 25 Jan 2024 20:08:59 +0100 Subject: [PATCH 16/18] Bumped sdk version in dockerFile --- coffeecard/CoffeeCard.WebApi/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coffeecard/CoffeeCard.WebApi/Dockerfile b/coffeecard/CoffeeCard.WebApi/Dockerfile index 8a8af53b..945d0878 100644 --- a/coffeecard/CoffeeCard.WebApi/Dockerfile +++ b/coffeecard/CoffeeCard.WebApi/Dockerfile @@ -1,11 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build WORKDIR /src COPY ["CoffeeCard.WebApi/CoffeeCard.WebApi.csproj", "CoffeeCard.WebApi/"] COPY ["CoffeeCard.Common/CoffeeCard.Common.csproj", "CoffeeCard.Common/"] From d141135be1a80be86de49232e0eb6dd93f5a9202 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Thu, 25 Jan 2024 20:13:25 +0100 Subject: [PATCH 17/18] Set language versions to default --- .../CoffeeCard.MobilePay.GenerateApi.csproj | 4 ++-- .../CoffeeCard.Tests.Integration.csproj | 4 ++-- coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj | 4 ++-- coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/coffeecard/CoffeeCard.MobilePay.GenerateApi/CoffeeCard.MobilePay.GenerateApi.csproj b/coffeecard/CoffeeCard.MobilePay.GenerateApi/CoffeeCard.MobilePay.GenerateApi.csproj index 2583378c..a7558958 100644 --- a/coffeecard/CoffeeCard.MobilePay.GenerateApi/CoffeeCard.MobilePay.GenerateApi.csproj +++ b/coffeecard/CoffeeCard.MobilePay.GenerateApi/CoffeeCard.MobilePay.GenerateApi.csproj @@ -3,10 +3,10 @@ Exe net7.0 enable - 8 + default - \ No newline at end of file + diff --git a/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj b/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj index f36b81f8..243b45ef 100644 --- a/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj +++ b/coffeecard/CoffeeCard.Tests.Integration/CoffeeCard.Tests.Integration.csproj @@ -2,7 +2,7 @@ net8.0 false - 8 + default 81E81CE9-7DDA-4A9B-860B-6A473BC4F06F @@ -40,4 +40,4 @@ - \ No newline at end of file + diff --git a/coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj b/coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj index 47cb3679..05587902 100644 --- a/coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj +++ b/coffeecard/CoffeeCard.Tests.Unit/CoffeeCard.Tests.Unit.csproj @@ -2,7 +2,7 @@ net8.0 false - 8 + default 24274C8F-678F-4E4D-98A0-2899163BCCBA @@ -27,4 +27,4 @@ - \ No newline at end of file + diff --git a/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj b/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj index 7df97549..5eebbc7e 100644 --- a/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj +++ b/coffeecard/CoffeeCard.WebApi/CoffeeCard.WebApi.csproj @@ -2,7 +2,7 @@ net8.0 InProcess - 8 + default 5562C898-513F-493A-A335-417C39476714 d3bbf778-c5fe-4240-b2ca-dfa64082cc0e true From 35b07e786c09faf4ae5f98740879193e6d3806d8 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Tue, 13 Feb 2024 19:55:10 +0100 Subject: [PATCH 18/18] Removed jsonConverter from paymentDetails and inheriting classes --- .../v2/Purchase/FreeProductPaymentDetails.cs | 3 --- .../DataTransferObjects/v2/Purchase/MobilePayPaymentDetails.cs | 2 -- .../DataTransferObjects/v2/Purchase/PaymentDetails.cs | 3 --- 3 files changed, 8 deletions(-) diff --git a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/FreeProductPaymentDetails.cs b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/FreeProductPaymentDetails.cs index aee28f7d..159a15d0 100644 --- a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/FreeProductPaymentDetails.cs +++ b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/FreeProductPaymentDetails.cs @@ -1,6 +1,4 @@ using System.Runtime.Serialization; -using System.Text.Json.Serialization; -using NJsonSchema.Converters; namespace CoffeeCard.Models.DataTransferObjects.v2.Purchase { @@ -14,7 +12,6 @@ namespace CoffeeCard.Models.DataTransferObjects.v2.Purchase /// } /// [KnownType(typeof(FreePurchasePaymentDetails))] - [JsonConverter(typeof(JsonInheritanceConverter))] public class FreePurchasePaymentDetails : PaymentDetails { /// diff --git a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/MobilePayPaymentDetails.cs b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/MobilePayPaymentDetails.cs index 5c77da0b..3fd4795d 100644 --- a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/MobilePayPaymentDetails.cs +++ b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/MobilePayPaymentDetails.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using NJsonSchema.Converters; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; @@ -17,7 +16,6 @@ namespace CoffeeCard.Models.DataTransferObjects.v2.Purchase /// } /// [KnownType(typeof(MobilePayPaymentDetails))] - [JsonConverter(typeof(JsonInheritanceConverter))] public class MobilePayPaymentDetails : PaymentDetails { /// diff --git a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/PaymentDetails.cs b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/PaymentDetails.cs index c1e54cdc..1b72271e 100644 --- a/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/PaymentDetails.cs +++ b/coffeecard/CoffeeCard.Models/DataTransferObjects/v2/Purchase/PaymentDetails.cs @@ -1,13 +1,10 @@ using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; -using System.Text.Json.Serialization; -using NJsonSchema.Converters; namespace CoffeeCard.Models.DataTransferObjects.v2.Purchase { [KnownType(typeof(MobilePayPaymentDetails))] [KnownType(typeof(FreePurchasePaymentDetails))] - [JsonConverter(typeof(JsonInheritanceConverter))] public abstract class PaymentDetails { ///