From 60abdd60b59e0d14b62051641e6b98aebf588cbf Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 3 Apr 2020 13:16:01 +1100 Subject: [PATCH] Starts fixing up integration tests --- .../Legacy/RequestHandlerSettings.cs | 9 +- .../Legacy/WebRoutingSettings.cs | 16 +- src/Umbraco.Core/Composing/Composition.cs | 1 + .../ApplicationBuilderExtensions.cs | 7 +- .../Extensions/ServiceCollectionExtensions.cs | 1 + .../Implementations/TestHelper.cs | 3 +- src/Umbraco.Tests.Integration/RuntimeTests.cs | 1 + .../Testing/IntegrationTestComposer.cs | 23 ++ .../Testing/LocalDbTestDatabase.cs | 5 +- .../Testing/UmbracoIntegrationTest.cs | 2 +- .../Umbraco.Tests.Integration.csproj | 6 + .../AspNetCoreHostingEnvironment.cs | 2 +- .../RuntimeMinification/SmidgeComposer.cs | 5 + src/Umbraco.Web.UI.NetCore/appsettings.json | 202 +++++++++--------- 14 files changed, 162 insertions(+), 121 deletions(-) create mode 100644 src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs diff --git a/src/Umbraco.Configuration/Legacy/RequestHandlerSettings.cs b/src/Umbraco.Configuration/Legacy/RequestHandlerSettings.cs index 0cd011c863..1c54f4d475 100644 --- a/src/Umbraco.Configuration/Legacy/RequestHandlerSettings.cs +++ b/src/Umbraco.Configuration/Legacy/RequestHandlerSettings.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using Umbraco.Core; using Umbraco.Core.Configuration.UmbracoSettings; @@ -6,9 +7,9 @@ namespace Umbraco.Configuration.Implementations { internal class RequestHandlerSettings : ConfigurationManagerConfigBase, IRequestHandlerSettings { - public bool AddTrailingSlash => UmbracoSettingsSection.RequestHandler.AddTrailingSlash; - public bool ConvertUrlsToAscii => UmbracoSettingsSection.RequestHandler.UrlReplacing.ConvertUrlsToAscii.InvariantEquals("true"); - public bool TryConvertUrlsToAscii => UmbracoSettingsSection.RequestHandler.UrlReplacing.ConvertUrlsToAscii.InvariantEquals("try"); - public IEnumerable CharCollection => UmbracoSettingsSection.RequestHandler.UrlReplacing.CharCollection; + public bool AddTrailingSlash => UmbracoSettingsSection?.RequestHandler?.AddTrailingSlash ?? true; + public bool ConvertUrlsToAscii => UmbracoSettingsSection?.RequestHandler?.UrlReplacing?.ConvertUrlsToAscii.InvariantEquals("true") ?? false; + public bool TryConvertUrlsToAscii => UmbracoSettingsSection?.RequestHandler?.UrlReplacing?.ConvertUrlsToAscii.InvariantEquals("try") ?? false; + public IEnumerable CharCollection => UmbracoSettingsSection?.RequestHandler?.UrlReplacing?.CharCollection ?? Enumerable.Empty(); } } diff --git a/src/Umbraco.Configuration/Legacy/WebRoutingSettings.cs b/src/Umbraco.Configuration/Legacy/WebRoutingSettings.cs index 5da3de20a0..cfca66822b 100644 --- a/src/Umbraco.Configuration/Legacy/WebRoutingSettings.cs +++ b/src/Umbraco.Configuration/Legacy/WebRoutingSettings.cs @@ -4,13 +4,13 @@ namespace Umbraco.Configuration.Implementations { internal class WebRoutingSettings : ConfigurationManagerConfigBase, IWebRoutingSettings { - public bool TrySkipIisCustomErrors => UmbracoSettingsSection.WebRouting.TrySkipIisCustomErrors; - public bool InternalRedirectPreservesTemplate => UmbracoSettingsSection.WebRouting.InternalRedirectPreservesTemplate; - public bool DisableAlternativeTemplates => UmbracoSettingsSection.WebRouting.DisableAlternativeTemplates; - public bool ValidateAlternativeTemplates => UmbracoSettingsSection.WebRouting.ValidateAlternativeTemplates; - public bool DisableFindContentByIdPath => UmbracoSettingsSection.WebRouting.DisableFindContentByIdPath; - public bool DisableRedirectUrlTracking => UmbracoSettingsSection.WebRouting.DisableRedirectUrlTracking; - public string UrlProviderMode => UmbracoSettingsSection.WebRouting.UrlProviderMode; - public string UmbracoApplicationUrl => UmbracoSettingsSection.WebRouting.UmbracoApplicationUrl; + public bool TrySkipIisCustomErrors => UmbracoSettingsSection?.WebRouting?.TrySkipIisCustomErrors ?? false; + public bool InternalRedirectPreservesTemplate => UmbracoSettingsSection?.WebRouting?.InternalRedirectPreservesTemplate ?? false; + public bool DisableAlternativeTemplates => UmbracoSettingsSection?.WebRouting?.DisableAlternativeTemplates ?? false; + public bool ValidateAlternativeTemplates => UmbracoSettingsSection?.WebRouting?.ValidateAlternativeTemplates ?? false; + public bool DisableFindContentByIdPath => UmbracoSettingsSection?.WebRouting?.DisableFindContentByIdPath ?? false; + public bool DisableRedirectUrlTracking => UmbracoSettingsSection?.WebRouting?.DisableRedirectUrlTracking ?? false; + public string UrlProviderMode => UmbracoSettingsSection?.WebRouting?.UrlProviderMode ?? "Auto"; + public string UmbracoApplicationUrl => UmbracoSettingsSection?.WebRouting?.UmbracoApplicationUrl; } } diff --git a/src/Umbraco.Core/Composing/Composition.cs b/src/Umbraco.Core/Composing/Composition.cs index 05c7554eab..f6e8655575 100644 --- a/src/Umbraco.Core/Composing/Composition.cs +++ b/src/Umbraco.Core/Composing/Composition.cs @@ -31,6 +31,7 @@ namespace Umbraco.Core.Composing /// The runtime state. /// Optional configs. /// An IOHelper + /// public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState, Configs configs, IIOHelper ioHelper, AppCaches appCaches) { _register = register ?? throw new ArgumentNullException(nameof(register)); diff --git a/src/Umbraco.Tests.Integration/Extensions/ApplicationBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Extensions/ApplicationBuilderExtensions.cs index d07f4f6ee3..aeb95f0ef1 100644 --- a/src/Umbraco.Tests.Integration/Extensions/ApplicationBuilderExtensions.cs +++ b/src/Umbraco.Tests.Integration/Extensions/ApplicationBuilderExtensions.cs @@ -23,15 +23,14 @@ namespace Umbraco.Tests.Integration.Extensions /// Creates a LocalDb instance to use for the test /// /// - /// + /// /// /// public static IApplicationBuilder UseTestLocalDb(this IApplicationBuilder app, - IHostEnvironment hostEnvironment, + string workingDirectory, UmbracoIntegrationTest integrationTest) { - - var dbFilePath = Path.Combine(hostEnvironment.ContentRootPath, "LocalDb"); + var dbFilePath = Path.Combine(workingDirectory, "LocalDb"); // get the currently set db options var testOptions = TestOptionAttributeBase.GetTestOptions(); diff --git a/src/Umbraco.Tests.Integration/Extensions/ServiceCollectionExtensions.cs b/src/Umbraco.Tests.Integration/Extensions/ServiceCollectionExtensions.cs index dc58d3e9e6..fabb3e9da0 100644 --- a/src/Umbraco.Tests.Integration/Extensions/ServiceCollectionExtensions.cs +++ b/src/Umbraco.Tests.Integration/Extensions/ServiceCollectionExtensions.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Umbraco.Core.Composing; using Umbraco.Tests.Integration.Implementations; namespace Umbraco.Tests.Integration.Extensions diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs index d46c01acba..d5b2d1a196 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -7,6 +7,7 @@ using Moq; using System.Data.Common; using System.IO; using System.Net; +using System.Reflection; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Diagnostics; @@ -42,7 +43,7 @@ namespace Umbraco.Tests.Integration.Implementations var hostEnvironment = new Mock(); hostEnvironment.Setup(x => x.ApplicationName).Returns("UmbracoIntegrationTests"); - hostEnvironment.Setup(x => x.ContentRootPath).Returns(() => WorkingDirectory); + hostEnvironment.Setup(x => x.ContentRootPath).Returns(() => Assembly.GetExecutingAssembly().GetRootDirectorySafe()); hostEnvironment.Setup(x => x.WebRootPath).Returns(() => WorkingDirectory); _hostEnvironment = hostEnvironment.Object; diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index 5968ee89fb..9e518de278 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -4,6 +4,7 @@ using Moq; using NUnit.Framework; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; +using Smidge; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Logging; diff --git a/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs b/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs new file mode 100644 index 0000000000..844877b1fd --- /dev/null +++ b/src/Umbraco.Tests.Integration/Testing/IntegrationTestComposer.cs @@ -0,0 +1,23 @@ +using Moq; +using Umbraco.Core; +using Umbraco.Core.Composing; +using Umbraco.Core.WebAssets; + +namespace Umbraco.Tests.Integration.Testing +{ + /// + /// This is used to replace certain services that are normally registered from our Core / Infrastructure that + /// we do not want active within integration tests + /// + /// + /// This is a IUserComposer so that it runs after all core composers + /// + [RuntimeLevel(MinLevel = RuntimeLevel.Boot)] + public class IntegrationTestComposer : IUserComposer + { + public void Compose(Composition composition) + { + composition.RegisterUnique(factory => Mock.Of()); + } + } +} diff --git a/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs b/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs index da2b83bc39..1d41cdf8b2 100644 --- a/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs +++ b/src/Umbraco.Tests.Integration/Testing/LocalDbTestDatabase.cs @@ -7,10 +7,12 @@ using System.Data.SqlClient; using System.IO; using System.Linq; using System.Threading; +using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Persistence; +using Umbraco.Web.Common.RuntimeMinification; namespace Umbraco.Tests.Integration.Testing { @@ -308,7 +310,8 @@ namespace Umbraco.Tests.Integration.Testing ResetLocalDb(cmd); _prepare?.Invoke(conn, cmd); } - _readyQueue.Add(i); + if (!_readyQueue.IsAddingCompleted) + _readyQueue.Add(i); } } diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index b1f5805ab6..16343a40c5 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -126,7 +126,7 @@ namespace Umbraco.Tests.Integration.Testing Services = app.ApplicationServices; // This will create a db, install the schema and ensure the app is configured to run - app.UseTestLocalDb(Services.GetRequiredService(), this); + app.UseTestLocalDb(testHelper.WorkingDirectory, this); app.UseUmbracoCore(); } diff --git a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj index 59b7de4cf4..1ad1b73b42 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj +++ b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj @@ -7,6 +7,12 @@ 8 + + + + + + diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs index 9344901273..decfcfa660 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs @@ -89,7 +89,7 @@ namespace Umbraco.Web.Common.AspNetCore public string ToAbsolute(string virtualPath) { if (!virtualPath.StartsWith("~/") && !virtualPath.StartsWith("/")) - throw new InvalidOperationException($"{nameof(virtualPath)} must start with ~/ or /"); + throw new InvalidOperationException($"The value {virtualPath} for parameter {nameof(virtualPath)} must start with ~/ or /"); // will occur if it starts with "/" if (Uri.IsWellFormedUriString(virtualPath, UriKind.Absolute)) diff --git a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeComposer.cs b/src/Umbraco.Web.Common/RuntimeMinification/SmidgeComposer.cs index 284b8e91da..6046f9eee6 100644 --- a/src/Umbraco.Web.Common/RuntimeMinification/SmidgeComposer.cs +++ b/src/Umbraco.Web.Common/RuntimeMinification/SmidgeComposer.cs @@ -9,6 +9,11 @@ namespace Umbraco.Web.Common.RuntimeMinification { public void Compose(Composition composition) { + + // TODO: For this to work we need to have services.AddSmidge() based on the Smidge APIs but our composer APIs don't really let us do that + // This makes it a bit awkward to boot the runtime since that call would need to be made outside of the composer... .hrm... + + composition.RegisterUnique(); composition.RegisterUnique(); } diff --git a/src/Umbraco.Web.UI.NetCore/appsettings.json b/src/Umbraco.Web.UI.NetCore/appsettings.json index cc72e1d0e3..46dc20034b 100644 --- a/src/Umbraco.Web.UI.NetCore/appsettings.json +++ b/src/Umbraco.Web.UI.NetCore/appsettings.json @@ -12,111 +12,111 @@ "AllowedHosts": "*", "Umbraco": { "CMS": { - "Hosting": { - "Debug": false - }, - "RuntimeMinification": { - "dataFolder": "App_Data/TEMP/Smidge", - "version": "637212411755687059" - }, - "Imaging": { - "Resize": { - "MaxWidth": 5000, - "MaxHeight": 5000 + "Hosting": { + "Debug": true }, - "Cache": { - "Folder": "../App_Data/Cache", - "MaxBrowserCacheDays": 7, - "MaxCacheDays": 365, - "CachedNameLength": 8 - } - }, - "HealthChecks": { - "DisabledChecks": [ - { - "id": "1B5D221B-CE99-4193-97CB-5F3261EC73DF", - "disabledBy": 1, - "disabledOn": "2020-03-15 19:19:10" - } - ], - "NotificationSettings": { - "Enabled": true, - "FirstRunTime": "", - "PeriodInHours": 24, - "NotificationMethods": { - "Email": { - "Enabled": true, - "Verbosity": "Summary", - "Settings": { - "RecipientEmail": "" - } + "RuntimeMinification": { + "dataFolder": "App_Data/TEMP/Smidge", + "version": "637212411755687059" + }, + "Imaging": { + "Resize": { + "MaxWidth": 5000, + "MaxHeight": 5000 + }, + "Cache": { + "Folder": "../App_Data/Cache", + "MaxBrowserCacheDays": 7, + "MaxCacheDays": 365, + "CachedNameLength": 8 } - }, - "DisabledChecks": [ - { - "id": "1B5D221B-CE99-4193-97CB-5F3261EC73DF", - "disabledBy": 1, - "disabledOn": "2020-03-15 19:19:10" + }, + "HealthChecks": { + "DisabledChecks": [ + { + "id": "1B5D221B-CE99-4193-97CB-5F3261EC73DF", + "disabledBy": 1, + "disabledOn": "2020-03-15 19:19:10" + } + ], + "NotificationSettings": { + "Enabled": true, + "FirstRunTime": "", + "PeriodInHours": 24, + "NotificationMethods": { + "Email": { + "Enabled": true, + "Verbosity": "Summary", + "Settings": { + "RecipientEmail": "" + } + } + }, + "DisabledChecks": [ + { + "id": "1B5D221B-CE99-4193-97CB-5F3261EC73DF", + "disabledBy": 1, + "disabledOn": "2020-03-15 19:19:10" + } + ] } - ] + }, + "Tours": { + "EnableTours": true + }, + "Core": { + "Debug": {} + }, + "Content": { + "Errors": { + "Error404": { + "default": "1047", + "en-US": "$site/error [@name = 'error']", + "en-UK": "8560867F-B88F-4C74-A9A4-679D8E5B3BFC" + } + } + }, + "RequestHandler": { + "AddTrailingSlash": true, + "CharCollection": [ + { + "Char": " ", + "Replacement": "-" + }, + { + "Char": "\"", + "Replacement": "" + }, + { + "Char": "'", + "Replacement": "" + }, + { + "Char": "%", + "Replacement": "" + }, + { + "Char": ".", + "Replacement": "" + }, + { + "Char": ";", + "Replacement": "" + }, + { + "Char": "/", + "Replacement": "" + }, + { + "Char": "\\", + "Replacement": "" + }, + { + "Char": ":", + "Replacement": "" + } + ] } - }, - "Tours": { - "EnableTours": true - }, - "Core": { - "Debug": {} - }, - "Content": { - "Errors": { - "Error404": { - "default": "1047", - "en-US": "$site/error [@name = 'error']", - "en-UK": "8560867F-B88F-4C74-A9A4-679D8E5B3BFC" - } - } - }, - "RequestHandler": { - "AddTrailingSlash": true, - "CharCollection": [ - { - "Char": " ", - "Replacement": "-" - }, - { - "Char": "\"", - "Replacement": "" - }, - { - "Char": "'", - "Replacement": "" - }, - { - "Char": "%", - "Replacement": "" - }, - { - "Char": ".", - "Replacement": "" - }, - { - "Char": ";", - "Replacement": "" - }, - { - "Char": "/", - "Replacement": "" - }, - { - "Char": "\\", - "Replacement": "" - }, - { - "Char": ":", - "Replacement": "" - } - ] - } } } }