From 87bd7a31591433dd7f7b65c36278aec0f2ec9710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Pilgaard=20Gr=C3=B8ndahl?= Date: Sat, 5 Oct 2024 21:28:11 +0200 Subject: [PATCH 01/12] Remove Azure App config to cut costs --- src/web/Jordnaer/Program.cs | 2 -- src/web/Jordnaer/appsettings.Development.json | 24 +++++++++++++++++++ src/web/Jordnaer/appsettings.json | 5 ++-- 3 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 src/web/Jordnaer/appsettings.Development.json diff --git a/src/web/Jordnaer/Program.cs b/src/web/Jordnaer/Program.cs index 3364b73c..dcd633a1 100644 --- a/src/web/Jordnaer/Program.cs +++ b/src/web/Jordnaer/Program.cs @@ -36,8 +36,6 @@ builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); -builder.AddAzureAppConfiguration(); - builder.AddAuthentication(); builder.Services.AddAuthorization(); diff --git a/src/web/Jordnaer/appsettings.Development.json b/src/web/Jordnaer/appsettings.Development.json new file mode 100644 index 00000000..a805454c --- /dev/null +++ b/src/web/Jordnaer/appsettings.Development.json @@ -0,0 +1,24 @@ +{ + "DataForsyningen": { + "BaseUrl": "https://api.dataforsyningen.dk" + }, + "FeatureManagement": { + "Contacts": false, + "Events": false, + "Posts": false, + "AccountSettings": false, + "NotificationSettings": false + }, + "Serilog": { + "MinimumLevel": { + "Default": "Debug", + "Override": { + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + "System.Net.Http": "Warning", + "Polly": "Warning", + "MudBlazor": "Information" + } + } + } +} \ No newline at end of file diff --git a/src/web/Jordnaer/appsettings.json b/src/web/Jordnaer/appsettings.json index 47e5ae97..acdcf041 100644 --- a/src/web/Jordnaer/appsettings.json +++ b/src/web/Jordnaer/appsettings.json @@ -12,13 +12,12 @@ }, "Serilog": { "MinimumLevel": { - "Default": "Debug", + "Default": "Information", "Override": { "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information", "System.Net.Http": "Warning", - "Polly": "Warning", - "MudBlazor": "Information" + "Polly": "Warning" } } } From 57a6baf5d71ed4351bbcf5218f6e1a22b716cc20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Pilgaard=20Gr=C3=B8ndahl?= Date: Sat, 5 Oct 2024 21:57:23 +0200 Subject: [PATCH 02/12] nuget updates --- .../Jordnaer.Benchmarks.csproj | 4 +-- .../Jordnaer.Chat/Jordnaer.Chat.csproj | 6 ++-- .../Jordnaer.Shared.Infrastructure.csproj | 1 - .../Jordnaer.Shared/Jordnaer.Shared.csproj | 8 ++--- src/web/Jordnaer/Jordnaer.csproj | 36 +++++++++---------- .../Jordnaer.Chat.Tests.csproj | 16 ++++----- .../Jordnaer.E2E.Tests.csproj | 8 ++--- .../Jordnaer.Load.Tests.csproj | 6 ++-- .../web/Jordnaer.Tests/Jordnaer.Tests.csproj | 18 +++++----- 9 files changed, 51 insertions(+), 52 deletions(-) diff --git a/benchmarks/Jordnaer.Benchmarks/Jordnaer.Benchmarks.csproj b/benchmarks/Jordnaer.Benchmarks/Jordnaer.Benchmarks.csproj index 5143eab5..f9c84fdc 100644 --- a/benchmarks/Jordnaer.Benchmarks/Jordnaer.Benchmarks.csproj +++ b/benchmarks/Jordnaer.Benchmarks/Jordnaer.Benchmarks.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/src/container_apps/Jordnaer.Chat/Jordnaer.Chat.csproj b/src/container_apps/Jordnaer.Chat/Jordnaer.Chat.csproj index 9439fac9..ccee49b1 100644 --- a/src/container_apps/Jordnaer.Chat/Jordnaer.Chat.csproj +++ b/src/container_apps/Jordnaer.Chat/Jordnaer.Chat.csproj @@ -11,12 +11,12 @@ - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/shared/Jordnaer.Shared.Infrastructure/Jordnaer.Shared.Infrastructure.csproj b/src/shared/Jordnaer.Shared.Infrastructure/Jordnaer.Shared.Infrastructure.csproj index 63cad0c6..fcdf48d3 100644 --- a/src/shared/Jordnaer.Shared.Infrastructure/Jordnaer.Shared.Infrastructure.csproj +++ b/src/shared/Jordnaer.Shared.Infrastructure/Jordnaer.Shared.Infrastructure.csproj @@ -11,6 +11,5 @@ - diff --git a/src/shared/Jordnaer.Shared/Jordnaer.Shared.csproj b/src/shared/Jordnaer.Shared/Jordnaer.Shared.csproj index 2df7c081..504ba73f 100644 --- a/src/shared/Jordnaer.Shared/Jordnaer.Shared.csproj +++ b/src/shared/Jordnaer.Shared/Jordnaer.Shared.csproj @@ -7,14 +7,14 @@ - + - + - - + + diff --git a/src/web/Jordnaer/Jordnaer.csproj b/src/web/Jordnaer/Jordnaer.csproj index 40269485..0243eeec 100644 --- a/src/web/Jordnaer/Jordnaer.csproj +++ b/src/web/Jordnaer/Jordnaer.csproj @@ -7,29 +7,29 @@ - + - + - - - - - - - - - - + + + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + @@ -39,11 +39,11 @@ - + - - - + + + diff --git a/tests/container_apps/Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj b/tests/container_apps/Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj index 45891d78..087e767d 100644 --- a/tests/container_apps/Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj +++ b/tests/container_apps/Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj @@ -12,23 +12,23 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/web/Jordnaer.E2E.Tests/Jordnaer.E2E.Tests.csproj b/tests/web/Jordnaer.E2E.Tests/Jordnaer.E2E.Tests.csproj index efcbd1c4..4b6c761f 100644 --- a/tests/web/Jordnaer.E2E.Tests/Jordnaer.E2E.Tests.csproj +++ b/tests/web/Jordnaer.E2E.Tests/Jordnaer.E2E.Tests.csproj @@ -19,16 +19,16 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/tests/web/Jordnaer.Load.Tests/Jordnaer.Load.Tests.csproj b/tests/web/Jordnaer.Load.Tests/Jordnaer.Load.Tests.csproj index 7ffc532d..028e8baf 100644 --- a/tests/web/Jordnaer.Load.Tests/Jordnaer.Load.Tests.csproj +++ b/tests/web/Jordnaer.Load.Tests/Jordnaer.Load.Tests.csproj @@ -12,10 +12,10 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj b/tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj index 421d2232..11dd60eb 100644 --- a/tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj +++ b/tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj @@ -8,26 +8,26 @@ - - + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all From 2a2ccd28d418ea5c71c19d84f42db4b1c5c17809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Pilgaard=20Gr=C3=B8ndahl?= Date: Sat, 5 Oct 2024 21:57:55 +0200 Subject: [PATCH 03/12] remove azure app config harder --- src/container_apps/Jordnaer.Chat/Program.cs | 2 -- .../AzureAppConfigurationExtensions.cs | 36 ------------------- src/web/Jordnaer/Program.cs | 1 - 3 files changed, 39 deletions(-) delete mode 100644 src/shared/Jordnaer.Shared.Infrastructure/AzureAppConfigurationExtensions.cs diff --git a/src/container_apps/Jordnaer.Chat/Program.cs b/src/container_apps/Jordnaer.Chat/Program.cs index 6118692a..c865eae6 100644 --- a/src/container_apps/Jordnaer.Chat/Program.cs +++ b/src/container_apps/Jordnaer.Chat/Program.cs @@ -11,8 +11,6 @@ { var builder = WebApplication.CreateBuilder(args); - builder.AddAzureAppConfiguration(); - builder.AddSerilog(); builder.AddDatabase(); diff --git a/src/shared/Jordnaer.Shared.Infrastructure/AzureAppConfigurationExtensions.cs b/src/shared/Jordnaer.Shared.Infrastructure/AzureAppConfigurationExtensions.cs deleted file mode 100644 index 03e7f8e6..00000000 --- a/src/shared/Jordnaer.Shared.Infrastructure/AzureAppConfigurationExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Hosting; -using Microsoft.FeatureManagement; - -namespace Jordnaer.Shared.Infrastructure; - -public static class AzureAppConfigurationExtensions -{ - public static WebApplicationBuilder AddAzureAppConfiguration(this WebApplicationBuilder builder) - { - builder.Services.AddFeatureManagement(); - - if (builder.Environment.IsDevelopment()) - { - return builder; - } - - var connectionString = builder.Configuration.GetConnectionString("AppConfig") - ?? throw new InvalidOperationException( - "Failed to find connection string to Azure App Configuration. " + - "Keys checked: 'ConnectionStrings:AppConfig'"); - - builder.Configuration.AddAzureAppConfiguration(options => - options.Connect(connectionString) - // Load all keys that have no label - .Select("*") - .ConfigureRefresh(refreshOptions => - // Only reload configs if the 'Sentinel' key is modified - refreshOptions.Register("Sentinel", refreshAll: true)) - .UseFeatureFlags()); - builder.Services.AddAzureAppConfiguration(); - - return builder; - } -} \ No newline at end of file diff --git a/src/web/Jordnaer/Program.cs b/src/web/Jordnaer/Program.cs index dcd633a1..ef078c83 100644 --- a/src/web/Jordnaer/Program.cs +++ b/src/web/Jordnaer/Program.cs @@ -117,7 +117,6 @@ app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); - app.UseAzureAppConfiguration(); } app.UseHttpsRedirection(); From 97e6f7e4a10a28b8b70d6ff60a3d27f308bb6323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Pilgaard=20Gr=C3=B8ndahl?= Date: Sat, 5 Oct 2024 22:08:28 +0200 Subject: [PATCH 04/12] fix tests, not related Also change user search to make more testable later on --- ...ensions.cs => QueryableGroupExtensions.cs} | 2 +- .../QueryableUserProfileExtensions.cs | 93 ++++++++++++++++++ .../Features/UserSearch/UserSearchService.cs | 97 ++----------------- .../Chat/ChatNotificationServiceTests.cs | 39 ++++---- .../GroupSearchServiceExtensionsTests.cs | 2 +- .../Infrastructure/SqlServerContainer.cs | 1 + .../UserSearch/UserSearchServiceTests.cs | 18 ++-- 7 files changed, 130 insertions(+), 122 deletions(-) rename src/web/Jordnaer/Features/GroupSearch/{GroupSearchServiceExtensions.cs => QueryableGroupExtensions.cs} (88%) create mode 100644 src/web/Jordnaer/Features/UserSearch/QueryableUserProfileExtensions.cs diff --git a/src/web/Jordnaer/Features/GroupSearch/GroupSearchServiceExtensions.cs b/src/web/Jordnaer/Features/GroupSearch/QueryableGroupExtensions.cs similarity index 88% rename from src/web/Jordnaer/Features/GroupSearch/GroupSearchServiceExtensions.cs rename to src/web/Jordnaer/Features/GroupSearch/QueryableGroupExtensions.cs index e0c3fc99..75b3994c 100644 --- a/src/web/Jordnaer/Features/GroupSearch/GroupSearchServiceExtensions.cs +++ b/src/web/Jordnaer/Features/GroupSearch/QueryableGroupExtensions.cs @@ -2,7 +2,7 @@ namespace Jordnaer.Features.GroupSearch; -internal static class GroupSearchServiceExtensions +internal static class QueryableGroupExtensions { internal static IQueryable ApplyNameFilter(this IQueryable groups, string? name) { diff --git a/src/web/Jordnaer/Features/UserSearch/QueryableUserProfileExtensions.cs b/src/web/Jordnaer/Features/UserSearch/QueryableUserProfileExtensions.cs new file mode 100644 index 00000000..90ab74c9 --- /dev/null +++ b/src/web/Jordnaer/Features/UserSearch/QueryableUserProfileExtensions.cs @@ -0,0 +1,93 @@ +using Jordnaer.Features.Search; +using Jordnaer.Shared; +using Microsoft.EntityFrameworkCore; + +namespace Jordnaer.Features.GroupSearch; + +internal static class QueryableUserProfileExtensions +{ + internal static async Task<(IQueryable UserProfiles, bool AppliedOrdering)> ApplyLocationFilterAsync( + this IQueryable users, + UserSearchFilter filter, + IZipCodeService zipCodeService, + CancellationToken cancellationToken = default) + { + if (string.IsNullOrEmpty(filter.Location) || filter.WithinRadiusKilometers is null) + { + return (users, false); + } + + var (zipCodesWithinCircle, searchedZipCode) = await zipCodeService.GetZipCodesNearLocationAsync( + filter.Location, + filter.WithinRadiusKilometers.Value, + cancellationToken); + + if (zipCodesWithinCircle.Count is 0 || searchedZipCode is null) + { + return (users, false); + } + + users = users.Where(user => user.ZipCode != null && + zipCodesWithinCircle.Contains(user.ZipCode.Value)) + .OrderBy(user => Math.Abs(user.ZipCode!.Value - searchedZipCode.Value)); + + return (users, true); + } + + internal static IQueryable ApplyCategoryFilter(this IQueryable users, + UserSearchFilter filter) + { + if (filter.Categories is not null && filter.Categories.Length > 0) + { + users = users.Where(user => + user.Categories.Any(category => filter.Categories.Contains(category.Name))); + } + + return users; + } + + internal static IQueryable ApplyNameFilter(this IQueryable users, string? filter) + { + if (!string.IsNullOrWhiteSpace(filter)) + { + users = users.Where(user => !string.IsNullOrEmpty(user.SearchableName) && + EF.Functions.Like(user.SearchableName, $"%{filter}%")); + } + + return users; + } + + internal static IQueryable ApplyChildFilters(this IQueryable users,UserSearchFilter filter) + { + if (filter.ChildGender is not null) + { + users = users.Where(user => + user.ChildProfiles.Any(child => child.Gender == filter.ChildGender)); + } + + if (filter is { MinimumChildAge: not null, MaximumChildAge: not null } && + filter.MinimumChildAge == filter.MaximumChildAge) + { + users = users.Where(user => + user.ChildProfiles.Any(child => child.Age != null && + child.Age == filter.MinimumChildAge)); + return users; + } + + if (filter.MinimumChildAge is not null) + { + users = users.Where(user => + user.ChildProfiles.Any(child => child.Age != null && + child.Age >= filter.MinimumChildAge)); + } + + if (filter.MaximumChildAge is not null) + { + users = users.Where(user => + user.ChildProfiles.Any(child => child.Age != null && + child.Age <= filter.MaximumChildAge)); + } + + return users; + } +} diff --git a/src/web/Jordnaer/Features/UserSearch/UserSearchService.cs b/src/web/Jordnaer/Features/UserSearch/UserSearchService.cs index 6f71634a..bb8b6063 100644 --- a/src/web/Jordnaer/Features/UserSearch/UserSearchService.cs +++ b/src/web/Jordnaer/Features/UserSearch/UserSearchService.cs @@ -1,4 +1,5 @@ using Jordnaer.Database; +using Jordnaer.Features.GroupSearch; using Jordnaer.Features.Metrics; using Jordnaer.Features.Search; using Jordnaer.Shared; @@ -17,16 +18,15 @@ public class UserSearchService( IDbContextFactory contextFactory) : IUserSearchService { - public async Task> GetUsersByNameAsync(string currentUserId, string searchString, CancellationToken cancellationToken = default) { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - var users = ApplyNameFilter(searchString, context.UserProfiles); + var users = context.UserProfiles.ApplyNameFilter(searchString); var firstTenUsers = await users .Where(user => user.Id != currentUserId) .OrderBy(user => searchString.StartsWith(searchString)) - .Take(11) + .Take(11) // We take 11 to let the frontend know we might have more than it searched for .Select(user => new UserSlim { ProfilePictureUrl = user.ProfilePictureUrl, @@ -50,10 +50,10 @@ public async Task GetUsersAsync(UserSearchFilter filter, Cance .Where(user => !string.IsNullOrEmpty(user.UserName)) .AsQueryable(); - users = ApplyChildFilters(filter, users); - users = ApplyNameFilter(filter.Name, users); - users = ApplyCategoryFilter(filter, users); - (users, var isOrdered) = await ApplyLocationFilterAsync(filter, users, cancellationToken); + users = users.ApplyChildFilters(filter); + users = users.ApplyNameFilter(filter.Name); + users = users.ApplyCategoryFilter(filter); + (users, var isOrdered) = await users.ApplyLocationFilterAsync(filter, zipCodeService, cancellationToken); if (!isOrdered) { @@ -94,89 +94,6 @@ public async Task GetUsersAsync(UserSearchFilter filter, Cance return new UserSearchResult { TotalCount = totalCount, Users = paginatedUsers }; } - private async Task<(IQueryable UserProfiles, bool AppliedOrdering)> ApplyLocationFilterAsync( - UserSearchFilter filter, - IQueryable users, - CancellationToken cancellationToken = default) - { - if (string.IsNullOrEmpty(filter.Location) || filter.WithinRadiusKilometers is null) - { - return (users, false); - } - - var (zipCodesWithinCircle, searchedZipCode) = await zipCodeService.GetZipCodesNearLocationAsync( - filter.Location, - filter.WithinRadiusKilometers.Value, - cancellationToken); - - if (zipCodesWithinCircle.Count is 0 || searchedZipCode is null) - { - return (users, false); - } - - users = users.Where(user => user.ZipCode != null && - zipCodesWithinCircle.Contains(user.ZipCode.Value)) - .OrderBy(user => Math.Abs(user.ZipCode!.Value - searchedZipCode.Value)); - - return (users, true); - } - - private static IQueryable ApplyCategoryFilter(UserSearchFilter filter, IQueryable users) - { - if (filter.Categories is not null && filter.Categories.Length > 0) - { - users = users.Where(user => - user.Categories.Any(category => filter.Categories.Contains(category.Name))); - } - - return users; - } - - private static IQueryable ApplyNameFilter(string? filter, IQueryable users) - { - if (!string.IsNullOrWhiteSpace(filter)) - { - users = users.Where(user => !string.IsNullOrEmpty(user.SearchableName) && - EF.Functions.Like(user.SearchableName, $"%{filter}%")); - } - - return users; - } - - private static IQueryable ApplyChildFilters(UserSearchFilter filter, IQueryable users) - { - if (filter.ChildGender is not null) - { - users = users.Where(user => - user.ChildProfiles.Any(child => child.Gender == filter.ChildGender)); - } - - if (filter is { MinimumChildAge: not null, MaximumChildAge: not null } && - filter.MinimumChildAge == filter.MaximumChildAge) - { - users = users.Where(user => - user.ChildProfiles.Any(child => child.Age != null && - child.Age == filter.MinimumChildAge)); - return users; - } - - if (filter.MinimumChildAge is not null) - { - users = users.Where(user => - user.ChildProfiles.Any(child => child.Age != null && - child.Age >= filter.MinimumChildAge)); - } - - if (filter.MaximumChildAge is not null) - { - users = users.Where(user => - user.ChildProfiles.Any(child => child.Age != null && - child.Age <= filter.MaximumChildAge)); - } - - return users; - } - private static ReadOnlySpan> MakeTagList(UserSearchFilter filter) { return new KeyValuePair[] diff --git a/tests/web/Jordnaer.Tests/Chat/ChatNotificationServiceTests.cs b/tests/web/Jordnaer.Tests/Chat/ChatNotificationServiceTests.cs index 9336175d..adf9e3dc 100644 --- a/tests/web/Jordnaer.Tests/Chat/ChatNotificationServiceTests.cs +++ b/tests/web/Jordnaer.Tests/Chat/ChatNotificationServiceTests.cs @@ -19,7 +19,6 @@ namespace Jordnaer.Tests.Chat; [Trait("Category", "UnitTest")] public class ChatNotificationServiceTests { - private readonly Mock> _contextFactoryMock; private readonly Mock _contextMock; private readonly Mock _publishEndpointMock; private readonly IServer _serverMock; @@ -27,10 +26,11 @@ public class ChatNotificationServiceTests public ChatNotificationServiceTests() { - _contextFactoryMock = new Mock>( + _contextMock = new Mock( new DbContextOptionsBuilder().Options); - _contextMock = new Mock(); - _contextFactoryMock + + var contextFactoryMock = new Mock>(); + contextFactoryMock .Setup(x => x.CreateDbContextAsync(It.IsAny())) .ReturnsAsync(_contextMock.Object); @@ -38,7 +38,7 @@ public ChatNotificationServiceTests() _serverMock = Substitute.For(); _service = new ChatNotificationService( - _contextFactoryMock.Object, + contextFactoryMock.Object, new NullLogger(), _publishEndpointMock.Object, _serverMock @@ -105,8 +105,7 @@ public async Task NotifyRecipients_ShouldFetchRecipientsAndPublishEmails() // Assert _publishEndpointMock - .Verify(p => p.Publish(It.IsAny(), -It.IsAny()), + .Verify(p => p.Publish(It.IsAny(), It.IsAny()), Times.Exactly(users.Count - 1)); // chat participants excluding the initiator } @@ -121,19 +120,19 @@ public void CreateEmails_ShouldGenerateCorrectEmailContent() Recipients = [ new UserSlim - { - Id = "initiator-id", - DisplayName = "Initiator", - ProfilePictureUrl = null, - UserName = null - }, - new UserSlim - { - Id = "recipient-id", - DisplayName = "Recipient", - ProfilePictureUrl = null, - UserName = null - } + { + Id = "initiator-id", + DisplayName = "Initiator", + ProfilePictureUrl = null, + UserName = null + }, + new UserSlim + { + Id = "recipient-id", + DisplayName = "Recipient", + ProfilePictureUrl = null, + UserName = null + } ] }; diff --git a/tests/web/Jordnaer.Tests/Groups/GroupSearchServiceExtensionsTests.cs b/tests/web/Jordnaer.Tests/Groups/GroupSearchServiceExtensionsTests.cs index 56a3f135..974e3d4f 100644 --- a/tests/web/Jordnaer.Tests/Groups/GroupSearchServiceExtensionsTests.cs +++ b/tests/web/Jordnaer.Tests/Groups/GroupSearchServiceExtensionsTests.cs @@ -6,7 +6,7 @@ namespace Jordnaer.Tests.Groups; [Trait("Category", "UnitTest")] -public class GroupSearchServiceExtensionsTests +public class QueryableGroupExtensionsTests { [Fact] public void ApplyNameFilter_WithNullName_ReturnsOriginalGroups() diff --git a/tests/web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs b/tests/web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs index 363004bb..3c248bb1 100644 --- a/tests/web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs +++ b/tests/web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs @@ -25,6 +25,7 @@ public virtual async Task InitializeAsync() _connectionString = Container.GetConnectionString(); await using var context = CreateContext(); + await context.Database.EnsureCreatedAsync(); } diff --git a/tests/web/Jordnaer.Tests/UserSearch/UserSearchServiceTests.cs b/tests/web/Jordnaer.Tests/UserSearch/UserSearchServiceTests.cs index 7e46af33..091bfecc 100644 --- a/tests/web/Jordnaer.Tests/UserSearch/UserSearchServiceTests.cs +++ b/tests/web/Jordnaer.Tests/UserSearch/UserSearchServiceTests.cs @@ -15,9 +15,9 @@ namespace Jordnaer.Tests.UserSearch; [Trait("Category", "IntegrationTest")] [Collection(nameof(SqlServerContainerCollection))] -public class UserSearchServiceTests : IAsyncLifetime +public class UserSearchServiceTests { - private readonly Mock> _contextFactory = new(); + private readonly IDbContextFactory _contextFactory = Substitute.For>(); private readonly IZipCodeService _zipCodeServiceMock = Substitute.For(); private readonly UserSearchService _sut; private readonly Faker _faker = new(); @@ -26,10 +26,9 @@ public class UserSearchServiceTests : IAsyncLifetime public UserSearchServiceTests(SqlServerContainer sqlServerContainer) { _context = sqlServerContainer.CreateContext(); - _contextFactory.Setup(x => x.CreateDbContextAsync(It.IsAny())) - .ReturnsAsync(_context); + _contextFactory.CreateDbContextAsync().ReturnsForAnyArgs(_context); - _sut = new UserSearchService(_zipCodeServiceMock, _contextFactory.Object); + _sut = new UserSearchService(_zipCodeServiceMock, _contextFactory); } [Fact] @@ -39,10 +38,10 @@ public async Task Return_UserSearchResult_Given_Valid_Filter() var filter = new UserSearchFilter(); // Act + await _context.UserProfiles.ExecuteDeleteAsync(); var result = await _sut.GetUsersAsync(filter); // Assert - result.Should().BeOfType(); result.TotalCount.Should().Be(0); result.Users.Should().BeEquivalentTo(new List()); } @@ -95,6 +94,7 @@ public async Task Return_UserSearchResult_With_LastName_Filter() var users = CreateTestUsers(5); // Ensure at least one user has the specified name in their SearchableName users[0].LastName = lastName; + _context.UserProfiles.RemoveRange(_context.UserProfiles); _context.UserProfiles.AddRange(users); await _context.SaveChangesAsync(); @@ -163,6 +163,7 @@ public async Task Return_UserSearchResult_With_ChildGender_Filter() Gender = filter.ChildGender.Value, FirstName = _faker.Name.FirstName() }); + _context.UserProfiles.RemoveRange(_context.UserProfiles); _context.UserProfiles.AddRange(users); await _context.SaveChangesAsync(); @@ -186,6 +187,7 @@ public async Task Return_UserSearchResult_With_MinimumChildAge_Filter() DateOfBirth = DateTime.UtcNow.AddYears(-filter.MinimumChildAge.Value), FirstName = _faker.Name.FirstName() }); + _context.UserProfiles.RemoveRange(_context.UserProfiles); _context.UserProfiles.AddRange(users); await _context.SaveChangesAsync(); @@ -265,8 +267,4 @@ private static List CreateTestUsers(int count) return users; } - - public Task InitializeAsync() => Task.CompletedTask; - - public async Task DisposeAsync() => await _context.UserProfiles.ExecuteDeleteAsync(); } From 0aaa1513eb2f40dfff6de92d0e21dac8134c8f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Pilgaard=20Gr=C3=B8ndahl?= Date: Sat, 5 Oct 2024 22:14:59 +0200 Subject: [PATCH 05/12] re-register feature mangement --- src/web/Jordnaer/Program.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/web/Jordnaer/Program.cs b/src/web/Jordnaer/Program.cs index ef078c83..fef97020 100644 --- a/src/web/Jordnaer/Program.cs +++ b/src/web/Jordnaer/Program.cs @@ -22,6 +22,7 @@ using Jordnaer.Database; using Jordnaer.Features.Membership; using Jordnaer.Features.Search; +using Microsoft.FeatureManagement; using Microsoft.Net.Http.Headers; using Sidio.Sitemap.AspNetCore; using Sidio.Sitemap.Blazor; @@ -36,6 +37,8 @@ builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); +builder.Services.AddFeatureManagement(); + builder.AddAuthentication(); builder.Services.AddAuthorization(); From 8dc2094a5f80d063fe1058c28515f883fbe8ebf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Pilgaard=20Gr=C3=B8ndahl?= Date: Sat, 5 Oct 2024 22:19:51 +0200 Subject: [PATCH 06/12] Update QueryableUserProfileExtensions.cs --- .../Features/UserSearch/QueryableUserProfileExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/Jordnaer/Features/UserSearch/QueryableUserProfileExtensions.cs b/src/web/Jordnaer/Features/UserSearch/QueryableUserProfileExtensions.cs index 90ab74c9..f0806626 100644 --- a/src/web/Jordnaer/Features/UserSearch/QueryableUserProfileExtensions.cs +++ b/src/web/Jordnaer/Features/UserSearch/QueryableUserProfileExtensions.cs @@ -2,7 +2,7 @@ using Jordnaer.Shared; using Microsoft.EntityFrameworkCore; -namespace Jordnaer.Features.GroupSearch; +namespace Jordnaer.Features.UserSearch; internal static class QueryableUserProfileExtensions { From ddc6dae648ac3c33162f0be178d38309f14801f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Pilgaard=20Gr=C3=B8ndahl?= Date: Sat, 5 Oct 2024 22:19:53 +0200 Subject: [PATCH 07/12] Update serviceDependencies.json --- src/web/Jordnaer/Properties/serviceDependencies.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/web/Jordnaer/Properties/serviceDependencies.json b/src/web/Jordnaer/Properties/serviceDependencies.json index 16cd064c..a6a4817f 100644 --- a/src/web/Jordnaer/Properties/serviceDependencies.json +++ b/src/web/Jordnaer/Properties/serviceDependencies.json @@ -1,9 +1,5 @@ { "dependencies": { - "appInsights1": { - "type": "appInsights", - "dynamicId": null - }, "secrets1": { "type": "secrets", "dynamicId": null From b5bd79f8d7d63fb6bbfe72ac6eff90b591f6de23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Pilgaard=20Gr=C3=B8ndahl?= Date: Sat, 5 Oct 2024 22:32:34 +0200 Subject: [PATCH 08/12] Update Jordnaer.Tests.csproj --- tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj b/tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj index 11dd60eb..0359d348 100644 --- a/tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj +++ b/tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj @@ -25,8 +25,8 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + runtime; build; native; contentfiles; analyzers; buildtransitive From e4f4d5675340f49b16c97a4371ad1a008c410d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Pilgaard=20Gr=C3=B8ndahl?= Date: Sat, 5 Oct 2024 22:36:10 +0200 Subject: [PATCH 09/12] Update Jordnaer.Chat.Tests.csproj --- .../Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/container_apps/Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj b/tests/container_apps/Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj index 087e767d..de188411 100644 --- a/tests/container_apps/Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj +++ b/tests/container_apps/Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj @@ -27,7 +27,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + runtime; build; native; contentfiles; analyzers; buildtransitive From 45f99e3cec80cff0ed9ac72c389e8443a82572b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Pilgaard=20Gr=C3=B8ndahl?= Date: Sun, 6 Oct 2024 09:06:30 +0200 Subject: [PATCH 10/12] Update SqlServerContainer.cs --- tests/web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs b/tests/web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs index 3c248bb1..09ce586d 100644 --- a/tests/web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs +++ b/tests/web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs @@ -7,6 +7,7 @@ namespace Jordnaer.Tests.Infrastructure; public class SqlServerContainer : IAsyncLifetime where TDbContext : DbContext { public readonly MsSqlContainer Container = new MsSqlBuilder() + .WithImage("mcr.microsoft.com/mssql/server:2022-latest") .WithName($"SqlServerTestcontainer-{Guid.NewGuid()}") .Build(); From c35964f99a236696e4fd52dd36e3e3d9273c205b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Pilgaard=20Gr=C3=B8ndahl?= Date: Sun, 6 Oct 2024 19:47:17 +0200 Subject: [PATCH 11/12] update testcontainers --- .../Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj | 4 ++-- tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/container_apps/Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj b/tests/container_apps/Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj index de188411..a551d3c8 100644 --- a/tests/container_apps/Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj +++ b/tests/container_apps/Jordnaer.Chat.Tests/Jordnaer.Chat.Tests.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -27,7 +27,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj b/tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj index 0359d348..11dd60eb 100644 --- a/tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj +++ b/tests/web/Jordnaer.Tests/Jordnaer.Tests.csproj @@ -25,8 +25,8 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + runtime; build; native; contentfiles; analyzers; buildtransitive From 73768e6e3e675b2f761d86d329b83b2d49904a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Pilgaard=20Gr=C3=B8ndahl?= Date: Sun, 6 Oct 2024 19:53:26 +0200 Subject: [PATCH 12/12] one more fix sqlserver container --- .../Infrastructure/JordnaerWebApplicationFactory.cs | 5 +++-- .../web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/web/Jordnaer.Tests/Infrastructure/JordnaerWebApplicationFactory.cs b/tests/web/Jordnaer.Tests/Infrastructure/JordnaerWebApplicationFactory.cs index c738e13b..ab13fe71 100644 --- a/tests/web/Jordnaer.Tests/Infrastructure/JordnaerWebApplicationFactory.cs +++ b/tests/web/Jordnaer.Tests/Infrastructure/JordnaerWebApplicationFactory.cs @@ -14,8 +14,9 @@ namespace Jordnaer.Tests.Infrastructure; public class JordnaerWebApplicationFactory : WebApplicationFactory, IAsyncLifetime { private readonly MsSqlContainer _msSqlContainer = new MsSqlBuilder() - .WithName($"SqlServerTestcontainer-{Guid.NewGuid()}") - .Build(); + .WithImage("mcr.microsoft.com/mssql/server:2022-latest") // We set a specific image to circumvent this bug: https://github.com/testcontainers/testcontainers-dotnet/issues/1271 + .WithName($"SqlServerTestcontainer-{Guid.NewGuid()}") + .Build(); private readonly AzuriteContainer _azureBlobStorageContainer = new AzuriteBuilder() .WithName($"AzuriteTestcontainer-{Guid.NewGuid()}") diff --git a/tests/web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs b/tests/web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs index 09ce586d..d5f002a8 100644 --- a/tests/web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs +++ b/tests/web/Jordnaer.Tests/Infrastructure/SqlServerContainer.cs @@ -7,7 +7,7 @@ namespace Jordnaer.Tests.Infrastructure; public class SqlServerContainer : IAsyncLifetime where TDbContext : DbContext { public readonly MsSqlContainer Container = new MsSqlBuilder() - .WithImage("mcr.microsoft.com/mssql/server:2022-latest") + .WithImage("mcr.microsoft.com/mssql/server:2022-latest") // We set a specific image to circumvent this bug: https://github.com/testcontainers/testcontainers-dotnet/issues/1271 .WithName($"SqlServerTestcontainer-{Guid.NewGuid()}") .Build();