diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7ba82b9e..3fc1688e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,12 +14,6 @@ jobs: name: Build runs-on: windows-latest steps: - - name: Set up JDK 11 - uses: actions/setup-java@v4 - with: - java-version: 11 - distribution: 'temurin' - - name: Checkout repository with submodules uses: actions/checkout@v4 with: @@ -32,38 +26,9 @@ jobs: key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} restore-keys: | ${{ runner.os }}-nuget- - - name: Cache SonarCloud packages - uses: actions/cache@v4 - with: - path: ~\sonar\cache - key: ${{ runner.os }}-sonar - restore-keys: ${{ runner.os }}-sonar - - - name: Cache SonarCloud scanner - id: cache-sonar-scanner - uses: actions/cache@v4 - with: - path: .\.sonar\scanner - key: ${{ runner.os }}-sonar-scanner - restore-keys: ${{ runner.os }}-sonar-scanner - - - name: Install SonarCloud scanner - if: steps.cache-sonar-scanner.outputs.cache-hit != 'true' - shell: powershell - run: | - New-Item -Path .\.sonar\scanner -ItemType Directory - dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner - - name: Restore dependencies run: dotnet restore - - - name: Build and analyze - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - shell: powershell - run: | - .\.sonar\scanner\dotnet-sonarscanner begin /k:"Geta_${{ github.event.repository.name }}" /o:"geta" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths=**/**/coverage.opencover.xml - dotnet build - dotnet test --filter Category!=Integration /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput=coverage - .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" + - name: Build + run: dotnet build --configuration Release --no-restore + - name: Test + run: dotnet test --configuration Release --no-build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 68e0ec2e..73d3a172 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -52,7 +52,12 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Create GitHub Release with Auto-Generated Notes run: | - gh release create ${{ github.ref_name }} --generate-notes + $notes = @" + ## Release notes + + - Removed the explicit ``System.Text.Json`` package reference. It now comes as a transitive dependency from Optimizely, so it no longer needs to be declared in the package. + "@ + gh release create ${{ github.ref_name }} --notes "$notes" --generate-notes env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Loop through all .nupkg files in the current directory and upload them to the release diff --git a/.gitignore b/.gitignore index ac8c7d9f..74604fc6 100644 --- a/.gitignore +++ b/.gitignore @@ -198,4 +198,5 @@ FakesAssemblies/ # Rider */.idea/* -.idea/* \ No newline at end of file +.idea/* +/.claude diff --git a/CHANGELOG.md b/CHANGELOG.md index 340ab5c2..842eb98b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,19 @@ All notable changes to this project will be documented in this file. +## [7.0.0] - 2026-06-01 + +### Changed + +- Upgraded target framework to .NET 10. +- Upgraded to Optimizely CMS 13 (`EPiServer.CMS.UI.Core` 13) and Optimizely Commerce 15. +- Bumped `Microsoft.Data.SqlClient` to 6.1.5. +- Replaced `Newtonsoft.Json` with `System.Text.Json` for content URL history serialization in `SqlContentUrlHistoryRepository`. `System.Text.Json` is provided transitively by Optimizely, so no explicit package reference is added. + +### Fixed + +- `Geta.NotFoundHandler.Optimizely` now registers its Optimizely Shell module when the package is referenced transitively (for example when only `Geta.NotFoundHandler.Optimizely.Commerce` is installed). The `module.config` copy target is now shipped under `buildTransitive`, fixing the "Unable to find a module by assembly 'Geta.NotFoundHandler.Optimizely'" error in the admin UI. + ## [1.1.0] - Refctoring diff --git a/README.md b/README.md index b51d2002..5ccc68d7 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,8 @@ # NotFound Handler for ASP.NET Core and Optimizely [![Build](https://github.com/Geta/geta-notfoundhandler/actions/workflows/build.yml/badge.svg)](https://github.com/Geta/geta-notfoundhandler/actions/workflows/build.yml) -[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Geta_geta-notfoundhandler&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Geta_geta-notfoundhandler) -[![Platform](https://img.shields.io/badge/Platform-.NET%205-blue.svg?style=flat)](https://docs.microsoft.com/en-us/dotnet/) -[![Platform](https://img.shields.io/badge/Optimizely-%2012-orange.svg?style=flat)](http://world.episerver.com/cms/) +[![Platform](https://img.shields.io/badge/Platform-.NET%2010-blue.svg?style=flat)](https://docs.microsoft.com/en-us/dotnet/) +[![Platform](https://img.shields.io/badge/Optimizely-%2013-orange.svg?style=flat)](http://world.episerver.com/cms/) ## Description diff --git a/src/Geta.NotFoundHandler.Admin/Geta.NotFoundHandler.Admin.csproj b/src/Geta.NotFoundHandler.Admin/Geta.NotFoundHandler.Admin.csproj index b3446e9b..0590f29e 100644 --- a/src/Geta.NotFoundHandler.Admin/Geta.NotFoundHandler.Admin.csproj +++ b/src/Geta.NotFoundHandler.Admin/Geta.NotFoundHandler.Admin.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 true Geta.NotFoundHandler.Admin Admin UI for NotFound Handler for ASP.NET Core and EPiServer diff --git a/src/Geta.NotFoundHandler.Optimizely.Commerce/Geta.NotFoundHandler.Optimizely.Commerce.csproj b/src/Geta.NotFoundHandler.Optimizely.Commerce/Geta.NotFoundHandler.Optimizely.Commerce.csproj index c02be0a0..1a8ff24e 100644 --- a/src/Geta.NotFoundHandler.Optimizely.Commerce/Geta.NotFoundHandler.Optimizely.Commerce.csproj +++ b/src/Geta.NotFoundHandler.Optimizely.Commerce/Geta.NotFoundHandler.Optimizely.Commerce.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 Geta.NotFoundHandler.Optimizely.Commerce NotFound handler Admin UI integration Optimizely Commerce Geta Digital @@ -30,7 +30,9 @@ - + + + diff --git a/src/Geta.NotFoundHandler.Optimizely/Core/AutomaticRedirects/CmsContentLinkProvider.cs b/src/Geta.NotFoundHandler.Optimizely/Core/AutomaticRedirects/CmsContentLinkProvider.cs index cda0e978..963dec2d 100644 --- a/src/Geta.NotFoundHandler.Optimizely/Core/AutomaticRedirects/CmsContentLinkProvider.cs +++ b/src/Geta.NotFoundHandler.Optimizely/Core/AutomaticRedirects/CmsContentLinkProvider.cs @@ -4,26 +4,27 @@ using System.Collections.Generic; using System.Linq; using EPiServer; +using EPiServer.Applications; using EPiServer.Core; -using EPiServer.Web; namespace Geta.NotFoundHandler.Optimizely.Core.AutomaticRedirects { public class CmsContentLinkProvider : IContentLinkProvider { - private readonly ISiteDefinitionRepository _siteDefinitionRepository; + private readonly IApplicationRepository _applicationRepository; private readonly IContentLoader _contentLoader; - public CmsContentLinkProvider(ISiteDefinitionRepository siteDefinitionRepository, IContentLoader contentLoader) + public CmsContentLinkProvider(IApplicationRepository applicationRepository, IContentLoader contentLoader) { - _siteDefinitionRepository = siteDefinitionRepository; + _applicationRepository = applicationRepository; _contentLoader = contentLoader; } public IEnumerable GetAllLinks() { - var allSites = _siteDefinitionRepository.List(); - return allSites.SelectMany(site => _contentLoader.GetDescendents(site.StartPage)); + return _applicationRepository.List() + .OfType() + .SelectMany(app => _contentLoader.GetDescendents(app.EntryPoint)); } } } diff --git a/src/Geta.NotFoundHandler.Optimizely/Core/AutomaticRedirects/IndexContentUrlsJob.cs b/src/Geta.NotFoundHandler.Optimizely/Core/AutomaticRedirects/IndexContentUrlsJob.cs index c13b968b..67080778 100644 --- a/src/Geta.NotFoundHandler.Optimizely/Core/AutomaticRedirects/IndexContentUrlsJob.cs +++ b/src/Geta.NotFoundHandler.Optimizely/Core/AutomaticRedirects/IndexContentUrlsJob.cs @@ -3,15 +3,13 @@ using System; using System.Linq; -using EPiServer.PlugIn; using EPiServer.Scheduler; using Geta.NotFoundHandler.Optimizely.Infrastructure; namespace Geta.NotFoundHandler.Optimizely.Core.AutomaticRedirects { - [ScheduledPlugIn(DisplayName = "[Geta NotFoundHandler] Index content URLs", - GUID = "53C743AE-E152-497A-A7E5-7E30F4B5B321", - SortIndex = 5555)] + [ScheduledJob(DisplayName = "[Geta NotFoundHandler] Index content URLs", + GUID = "53C743AE-E152-497A-A7E5-7E30F4B5B321")] public class IndexContentUrlsJob : ScheduledJobBase { private bool _stopped; diff --git a/src/Geta.NotFoundHandler.Optimizely/Core/AutomaticRedirects/RegisterMovedContentRedirectsJob.cs b/src/Geta.NotFoundHandler.Optimizely/Core/AutomaticRedirects/RegisterMovedContentRedirectsJob.cs index 5d69dda0..48167bcf 100644 --- a/src/Geta.NotFoundHandler.Optimizely/Core/AutomaticRedirects/RegisterMovedContentRedirectsJob.cs +++ b/src/Geta.NotFoundHandler.Optimizely/Core/AutomaticRedirects/RegisterMovedContentRedirectsJob.cs @@ -3,15 +3,13 @@ using System; using System.Linq; -using EPiServer.PlugIn; using EPiServer.Scheduler; using Geta.NotFoundHandler.Optimizely.Infrastructure; namespace Geta.NotFoundHandler.Optimizely.Core.AutomaticRedirects { - [ScheduledPlugIn(DisplayName = "[Geta NotFoundHandler] Register content move redirects", - GUID = "EC96ABEE-5DA4-404F-A0C8-451C77CA4983", - SortIndex = 5555)] + [ScheduledJob(DisplayName = "[Geta NotFoundHandler] Register content move redirects", + GUID = "EC96ABEE-5DA4-404F-A0C8-451C77CA4983")] public class RegisterMovedContentRedirectsJob : ScheduledJobBase { private readonly IContentUrlHistoryLoader _contentUrlHistoryLoader; diff --git a/src/Geta.NotFoundHandler.Optimizely/Core/Suggestions/Jobs/SuggestionsCleanupJob.cs b/src/Geta.NotFoundHandler.Optimizely/Core/Suggestions/Jobs/SuggestionsCleanupJob.cs index e40de31c..fa8247e6 100644 --- a/src/Geta.NotFoundHandler.Optimizely/Core/Suggestions/Jobs/SuggestionsCleanupJob.cs +++ b/src/Geta.NotFoundHandler.Optimizely/Core/Suggestions/Jobs/SuggestionsCleanupJob.cs @@ -1,16 +1,14 @@ // Copyright (c) Geta Digital. All rights reserved. // Licensed under Apache-2.0. See the LICENSE file in the project root for more information -using EPiServer.PlugIn; using EPiServer.Scheduler; using Geta.NotFoundHandler.Core.Suggestions; namespace Geta.NotFoundHandler.Optimizely.Core.Suggestions.Jobs; -[ScheduledPlugIn(DisplayName = "[Geta NotFoundHandler] Suggestions cleanup job", - Description = "As suggestions table grow fast we should add a possibility to clean up old suggestions", - GUID = "6AE19CEC-1052-4482-97DF-981076DDD6F2", - SortIndex = 5555)] +[ScheduledJob(DisplayName = "[Geta NotFoundHandler] Suggestions cleanup job", + Description = "As suggestions table grow fast we should add a possibility to clean up old suggestions", + GUID = "6AE19CEC-1052-4482-97DF-981076DDD6F2")] public class SuggestionsCleanupJob : ScheduledJobBase { private readonly ISuggestionsCleanupService _suggestionsCleanupService; diff --git a/src/Geta.NotFoundHandler.Optimizely/Data/SqlContentUrlHistoryRepository.cs b/src/Geta.NotFoundHandler.Optimizely/Data/SqlContentUrlHistoryRepository.cs index 5905597c..e5e98eab 100644 --- a/src/Geta.NotFoundHandler.Optimizely/Data/SqlContentUrlHistoryRepository.cs +++ b/src/Geta.NotFoundHandler.Optimizely/Data/SqlContentUrlHistoryRepository.cs @@ -7,10 +7,10 @@ using System.Linq; using Geta.NotFoundHandler.Data; using Geta.NotFoundHandler.Optimizely.Core.AutomaticRedirects; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; using System.Security.Cryptography; using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Geta.NotFoundHandler.Optimizely.Data { @@ -25,18 +25,10 @@ public SqlContentUrlHistoryRepository(IDataExecutor dataExecutor) _dataExecutor = dataExecutor; } - private static JsonSerializerSettings JsonSettings + private static readonly JsonSerializerOptions JsonSettings = new() { - get - { - var settings = new JsonSerializerSettings - { - DateTimeZoneHandling = DateTimeZoneHandling.Utc, Formatting = Formatting.None - }; - settings.Converters.Add(new StringEnumConverter()); - return settings; - } - } + Converters = { new JsonStringEnumConverter() } + }; private static byte[] CalculateMd5Hash(string input) { @@ -173,14 +165,14 @@ private void Update(ContentUrlHistory entity) private static string ToJson(ICollection urls) { - return JsonConvert.SerializeObject(urls, JsonSettings); + return JsonSerializer.Serialize(urls, JsonSettings); } private static ICollection FromJson(string value) { return string.IsNullOrEmpty(value) ? new List() - : JsonConvert.DeserializeObject>(value, JsonSettings); + : JsonSerializer.Deserialize>(value, JsonSettings); } private static IEnumerable ToContentUrlHistory(DataTable table) diff --git a/src/Geta.NotFoundHandler.Optimizely/Geta.NotFoundHandler.Optimizely.Views/Views/Shared/_ShellLayout.cshtml b/src/Geta.NotFoundHandler.Optimizely/Geta.NotFoundHandler.Optimizely.Views/Views/Shared/_ShellLayout.cshtml index e498446d..21ccdcfc 100644 --- a/src/Geta.NotFoundHandler.Optimizely/Geta.NotFoundHandler.Optimizely.Views/Views/Shared/_ShellLayout.cshtml +++ b/src/Geta.NotFoundHandler.Optimizely/Geta.NotFoundHandler.Optimizely.Views/Views/Shared/_ShellLayout.cshtml @@ -1,5 +1,4 @@ @using EPiServer.Framework.Web.Resources -@using EPiServer.Shell.Navigation @@ -31,8 +30,8 @@ @Html.AntiForgeryToken() - @Html.CreatePlatformNavigationMenu() -
+ +
@RenderBody()
diff --git a/src/Geta.NotFoundHandler.Optimizely/Geta.NotFoundHandler.Optimizely.csproj b/src/Geta.NotFoundHandler.Optimizely/Geta.NotFoundHandler.Optimizely.csproj index 4e040931..9f0795cd 100644 --- a/src/Geta.NotFoundHandler.Optimizely/Geta.NotFoundHandler.Optimizely.csproj +++ b/src/Geta.NotFoundHandler.Optimizely/Geta.NotFoundHandler.Optimizely.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 true Geta.NotFoundHandler.Optimizely NotFound handler Admin UI integration Optimizely @@ -23,7 +23,8 @@ - + + @@ -49,7 +50,7 @@ true true None - build\net6.0\$(MSBuildProjectName).targets + build\net6.0\$(MSBuildProjectName).targets;buildTransitive\net6.0\$(MSBuildProjectName).targets diff --git a/src/Geta.NotFoundHandler.Web/.gitignore b/src/Geta.NotFoundHandler.Web/.gitignore index f3afdcd2..696bcccb 100644 --- a/src/Geta.NotFoundHandler.Web/.gitignore +++ b/src/Geta.NotFoundHandler.Web/.gitignore @@ -201,4 +201,5 @@ FakesAssemblies/ .idea/* wwwroot -modules \ No newline at end of file +modules/* +!modules/ModulesInclude.proj \ No newline at end of file diff --git a/src/Geta.NotFoundHandler.Web/Geta.NotFoundHandler.Web.csproj b/src/Geta.NotFoundHandler.Web/Geta.NotFoundHandler.Web.csproj index 60e782f3..64d7853c 100644 --- a/src/Geta.NotFoundHandler.Web/Geta.NotFoundHandler.Web.csproj +++ b/src/Geta.NotFoundHandler.Web/Geta.NotFoundHandler.Web.csproj @@ -2,18 +2,18 @@ Exe - net9.0 + net10.0 enable enable - - - - + + + + - + diff --git a/src/Geta.NotFoundHandler.Web/Startup.cs b/src/Geta.NotFoundHandler.Web/Startup.cs index 6015fe27..51e63658 100644 --- a/src/Geta.NotFoundHandler.Web/Startup.cs +++ b/src/Geta.NotFoundHandler.Web/Startup.cs @@ -1,4 +1,6 @@ using EPiServer.Authorization; +using EPiServer.Cms.Shell.UI; +using EPiServer.DependencyInjection; using EPiServer.Framework.Hosting; using EPiServer.Web.Hosting; using Geta.NotFoundHandler.Infrastructure.Configuration; @@ -25,6 +27,10 @@ public void ConfigureServices(IServiceCollection services) services.AddNotFoundHandler(o => o.UseSqlServer(_configuration.GetConnectionString("EPiServerDB")), policy => policy.RequireRole(Roles.CmsAdmins)); services.AddOptimizelyNotFoundHandler(); + services.AddAdminUserRegistration(options => + { + options.Behavior = RegisterAdminUserBehaviors.Enabled; + }); _foundationStartup.ConfigureServices(services); var moduleName = typeof(ContainerController).Assembly.GetName().Name; @@ -33,7 +39,7 @@ public void ConfigureServices(IServiceCollection services) services.Configure(options => { options.BasePathFileProviders.Add(new MappingPhysicalFileProvider( - $"/EPiServer/{moduleName}", + $"/Optimizely/{moduleName}", string.Empty, fullPath)); }); diff --git a/src/Geta.NotFoundHandler.Web/appsettings.json b/src/Geta.NotFoundHandler.Web/appsettings.json index 59fc6bdd..37d39be8 100644 --- a/src/Geta.NotFoundHandler.Web/appsettings.json +++ b/src/Geta.NotFoundHandler.Web/appsettings.json @@ -8,16 +8,19 @@ "Default": "Warning", "Microsoft.AspNetCore.Mvc.Razor": "Debug", "Microsoft.AspNetCore.Mvc.ViewEngines": "Debug" + } }, "AllowedHosts": "*", - "EPiServer": { - "Find": { - "DefaultIndex": "changeme", - "ServiceUrl": "http://changeme", - "TrackingSanitizerEnabled": true, - "TrackingTimeout": 30000 - }, + "Optimizely": { + "ContentGraph": { + "GatewayAddress": "https://cg.optimizely.com", + "AppKey": "changeme", + "Secret": "changeme", + "SingleKey": "changeme" + } + }, + "EPiServer": { "OdpVisitorGroupOptions": { "OdpCookieName": "vuid", "CacheTimeoutSeconds": 1, diff --git a/src/Geta.NotFoundHandler.Web/modules/ModulesInclude.proj b/src/Geta.NotFoundHandler.Web/modules/ModulesInclude.proj new file mode 100644 index 00000000..40849f49 --- /dev/null +++ b/src/Geta.NotFoundHandler.Web/modules/ModulesInclude.proj @@ -0,0 +1,39 @@ + + + + + + ..\..\sub\geta-foundation-core\src\Foundation\modules + modules + + + + + + + + + + + + + + + + + + modules + $(PublishDir)\modules + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Geta.NotFoundHandler/Geta.NotFoundHandler.csproj b/src/Geta.NotFoundHandler/Geta.NotFoundHandler.csproj index 2e59c544..9b38be3d 100644 --- a/src/Geta.NotFoundHandler/Geta.NotFoundHandler.csproj +++ b/src/Geta.NotFoundHandler/Geta.NotFoundHandler.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0 Geta.NotFoundHandler NotFound Handler for ASP.NET Core Geta Digital @@ -28,7 +28,7 @@ - + diff --git a/sub/geta-foundation-core b/sub/geta-foundation-core index d71244c7..df52563c 160000 --- a/sub/geta-foundation-core +++ b/sub/geta-foundation-core @@ -1 +1 @@ -Subproject commit d71244c7c12339a3dfb278ba15ca423768c33118 +Subproject commit df52563cdfeed1ffe56b919be2d6016877f66062 diff --git a/tests/Geta.NotFoundHandler.Optimizely.Tests/AutomaticRedirects/CmsContentLinkProviderTests.cs b/tests/Geta.NotFoundHandler.Optimizely.Tests/AutomaticRedirects/CmsContentLinkProviderTests.cs index 064dbca5..dbd0ea7b 100644 --- a/tests/Geta.NotFoundHandler.Optimizely.Tests/AutomaticRedirects/CmsContentLinkProviderTests.cs +++ b/tests/Geta.NotFoundHandler.Optimizely.Tests/AutomaticRedirects/CmsContentLinkProviderTests.cs @@ -1,8 +1,9 @@ using System; +using System.Collections.Generic; using System.Linq; using EPiServer; +using EPiServer.Applications; using EPiServer.Core; -using EPiServer.Web; using FakeItEasy; using Geta.NotFoundHandler.Optimizely.Core.AutomaticRedirects; using Xunit; @@ -12,22 +13,22 @@ namespace Geta.NotFoundHandler.Optimizely.Tests.AutomaticRedirects; public class CmsContentLinkProviderTests { private readonly CmsContentLinkProvider _provider; - private readonly ISiteDefinitionRepository _fakeSiteDefinitionRepository; + private readonly IApplicationRepository _fakeApplicationRepository; private readonly IContentLoader _fakeContentLoader; public CmsContentLinkProviderTests() { - _fakeSiteDefinitionRepository = A.Fake(); + _fakeApplicationRepository = A.Fake(); _fakeContentLoader = A.Fake(); - _provider = new CmsContentLinkProvider(_fakeSiteDefinitionRepository, _fakeContentLoader); + _provider = new CmsContentLinkProvider(_fakeApplicationRepository, _fakeContentLoader); } [Fact] public void GetAllLinks_returns_descendants_for_each_site() { var numberOfSites = new Random(DateTime.Now.Millisecond).Next(1, 10); - var sites = A.CollectionOfDummy(numberOfSites); - A.CallTo(() => _fakeSiteDefinitionRepository.List()).Returns(sites); + var apps = CreateFakeRoutableApplications(numberOfSites); + A.CallTo(() => _fakeApplicationRepository.List()).Returns(apps); var _ = _provider.GetAllLinks().ToList(); @@ -37,10 +38,10 @@ public void GetAllLinks_returns_descendants_for_each_site() [Fact] public void GetAllLinks_returns_descendants() { - var sites = A.CollectionOfDummy(1); + var apps = CreateFakeRoutableApplications(1); var numberOfDescendants = new Random(DateTime.Now.Millisecond).Next(1, 10); var descendants = A.CollectionOfDummy(numberOfDescendants); - A.CallTo(() => _fakeSiteDefinitionRepository.List()).Returns(sites); + A.CallTo(() => _fakeApplicationRepository.List()).Returns(apps); A.CallTo(() => _fakeContentLoader.GetDescendents(A._)).Returns(descendants); var result = _provider.GetAllLinks().ToList(); @@ -48,4 +49,18 @@ public void GetAllLinks_returns_descendants() Assert.Equal(numberOfDescendants, result.Count); Assert.Equal(descendants, result); } + + /// + /// Creates fake Application instances that also implement IRoutableApplication, + /// matching the CMS 13 application model (ISiteDefinitionRepository was replaced + /// by IApplicationRepository in CMS 13). + /// + private static IEnumerable CreateFakeRoutableApplications(int count) + { + return Enumerable.Range(0, count) + .Select(i => A.Fake(x => x + .Implements() + .WithArgumentsForConstructor(new object[] { $"app-{i}" }))) + .ToList(); + } } diff --git a/tests/Geta.NotFoundHandler.Optimizely.Tests/Geta.NotFoundHandler.Optimizely.Tests.csproj b/tests/Geta.NotFoundHandler.Optimizely.Tests/Geta.NotFoundHandler.Optimizely.Tests.csproj index 05827468..aa106f19 100644 --- a/tests/Geta.NotFoundHandler.Optimizely.Tests/Geta.NotFoundHandler.Optimizely.Tests.csproj +++ b/tests/Geta.NotFoundHandler.Optimizely.Tests/Geta.NotFoundHandler.Optimizely.Tests.csproj @@ -1,23 +1,23 @@  - net8.0 + net10.0 false - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/Geta.NotFoundHandler.Tests/Geta.NotFoundHandler.Tests.csproj b/tests/Geta.NotFoundHandler.Tests/Geta.NotFoundHandler.Tests.csproj index b48a184b..28abcf8c 100644 --- a/tests/Geta.NotFoundHandler.Tests/Geta.NotFoundHandler.Tests.csproj +++ b/tests/Geta.NotFoundHandler.Tests/Geta.NotFoundHandler.Tests.csproj @@ -1,24 +1,24 @@  - net8.0 + net10.0 false - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive