diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks/ExperienceEditorMiddlewareBenchmarks.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks/ExperienceEditorMiddlewareBenchmarks.cs index d5b44f2..9447e68 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks/ExperienceEditorMiddlewareBenchmarks.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks/ExperienceEditorMiddlewareBenchmarks.cs @@ -1,6 +1,8 @@ using System.Diagnostics.CodeAnalysis; using BenchmarkDotNet.Attributes; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using NSubstitute; @@ -17,19 +19,24 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks; [ExcludeFromCodeCoverage] public class ExperienceEditorMiddlewareBenchmarks : IDisposable { - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; private readonly HttpClient _client; private readonly StringContent _content; private RenderingEngineBenchmarks? _baseLineTestInstance; public ExperienceEditorMiddlewareBenchmarks() { - TestServerBuilder testHostBuilder = new(); - testHostBuilder - .ConfigureServices(builder => + WebApplicationFactory factory = new TestWebApplicationFactory(); + + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => { - builder.AddSingleton(Substitute.For()); - builder.AddSitecoreRenderingEngine(options => + services.AddRouting(); + + services.AddSingleton(Substitute.For()); + + services.AddSitecoreRenderingEngine(options => { options.AddDefaultComponentRenderer(); }).WithExperienceEditor(options => @@ -37,17 +44,17 @@ public ExperienceEditorMiddlewareBenchmarks() options.Endpoint = TestConstants.EEMiddlewarePostEndpoint; options.JssEditingSecret = TestConstants.JssEditingSecret; }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseSitecoreExperienceEditor(); app.UseRouting(); app.UseSitecoreRenderingEngine(); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); - - _client = _server.CreateClient(); + _client = _factory.CreateClient(); _content = new StringContent(TestConstants.EESampleRequest); } @@ -76,7 +83,7 @@ public async Task RegularExperienceEditorRequestHandling() public void Dispose() { - _server.Dispose(); + _factory.Dispose(); _client.Dispose(); _content.Dispose(); _baseLineTestInstance?.Dispose(); diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks/RenderingEngineBenchmarks.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks/RenderingEngineBenchmarks.cs index 2bd3f89..0bd58fa 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks/RenderingEngineBenchmarks.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks/RenderingEngineBenchmarks.cs @@ -2,11 +2,13 @@ using System.Net; using BenchmarkDotNet.Attributes; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.TestHost; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.Extensions.DependencyInjection; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; +using Sitecore.AspNetCore.SDK.LayoutService.Client.Interfaces; using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions; -using Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests; using Sitecore.AspNetCore.SDK.TestData; namespace Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks; @@ -16,38 +18,42 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks; [ExcludeFromCodeCoverage] public class RenderingEngineBenchmarks : IDisposable { - private TestServer? _server; + private WebApplicationFactory? _factory; private HttpClient? _client; private MockHttpMessageHandler? _mockClientHandler; [GlobalSetup] public void Setup() - { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => - { - builder - .AddSitecoreLayoutService() - .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = new Uri("http://layout.service") }) - .AsDefaultHandler(); + { + _mockClientHandler = new MockHttpMessageHandler(); - builder.AddSitecoreRenderingEngine(options => + _factory = new WebApplicationFactory() + .WithWebHostBuilder(builder => { - options.AddDefaultComponentRenderer(); - }); - }) - .Configure(app => - { - app.UseRouting(); - app.UseSitecoreRenderingEngine(); - }); + builder.ConfigureServices(services => + { + services.AddRouting(); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + ISitecoreLayoutClientBuilder layoutBuilder = services.AddSitecoreLayoutService(); + layoutBuilder + .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler!) { BaseAddress = new Uri("http://layout.service") }) + .AsDefaultHandler(); - _client = _server.CreateClient(); - } + services.AddSitecoreRenderingEngine(options => + { + options.AddDefaultComponentRenderer(); + }); + }); + + builder.Configure(app => + { + app.UseRouting(); + app.UseSitecoreRenderingEngine(); + }); + }); + + _client = _factory.CreateClient(); + } [Benchmark(Baseline = true)] public async Task RegularHomePageRequest() @@ -71,8 +77,8 @@ public async Task RegularHomePageRequest() public void Dispose() { - _server?.Dispose(); _client?.Dispose(); + _factory?.Dispose(); _mockClientHandler?.Dispose(); GC.SuppressFinalize(this); } diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks/TrackingBenchmarks.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks/TrackingBenchmarks.cs index 0b9137a..1df7f8c 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks/TrackingBenchmarks.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks/TrackingBenchmarks.cs @@ -2,13 +2,14 @@ using System.Net; using BenchmarkDotNet.Attributes; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpOverrides; -using Microsoft.AspNetCore.TestHost; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.DependencyInjection; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; +using Sitecore.AspNetCore.SDK.LayoutService.Client.Interfaces; using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions; -using Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests; using Sitecore.AspNetCore.SDK.TestData; using Sitecore.AspNetCore.SDK.Tracking; using Sitecore.AspNetCore.SDK.Tracking.VisitorIdentification; @@ -21,7 +22,7 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Benchmarks; [ExcludeFromCodeCoverage] public class TrackingBenchmarks : IDisposable { - private TestServer? _server; + private WebApplicationFactory? _factory; private HttpClient? _client; private MockHttpMessageHandler? _mockClientHandler; private RenderingEngineBenchmarks? _baseLineTestInstance; @@ -29,23 +30,25 @@ public class TrackingBenchmarks : IDisposable [GlobalSetup(Target = nameof(RegularHomePageRequestWithTracking))] public void TrackingBenchmarksSetup() { - TestServerBuilder testHostBuilder = new(); _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + + _factory = new WebApplicationFactory() + .WithWebHostBuilder(builder => { - builder.Configure(options => + builder.ConfigureServices(services => { - options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | - ForwardedHeaders.XForwardedProto; - }); + services.Configure(options => + { + options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | + ForwardedHeaders.XForwardedProto; + }); - builder - .AddSitecoreLayoutService() - .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = new Uri("http://layout.service") }) - .AsDefaultHandler(); + ISitecoreLayoutClientBuilder layoutBuilder = services.AddSitecoreLayoutService(); + layoutBuilder + .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler!) { BaseAddress = new Uri("http://layout.service") }) + .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + services.AddSitecoreRenderingEngine(options => { options.AddDefaultComponentRenderer(); }).ForwardHeaders(options => @@ -66,22 +69,15 @@ public void TrackingBenchmarksSetup() }) .WithTracking(); - builder.AddSitecoreVisitorIdentification(options => - { - options.SitecoreInstanceUri = new Uri("http://layout.service"); + services.AddSitecoreVisitorIdentification(options => + { + options.SitecoreInstanceUri = new Uri("http://layout.service"); + }); + services.AddSingleton(); }); - }) - .Configure(app => - { - app.UseForwardedHeaders(); - app.UseRouting(); - app.UseSitecoreVisitorIdentification(); - app.UseSitecoreRenderingEngine(); }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); - - _client = _server.CreateClient(); + _client = _factory.CreateClient(); } [GlobalSetup(Target = nameof(RegularHomePageRequest))] @@ -119,10 +115,25 @@ public async Task RegularHomePageRequestWithTracking() public void Dispose() { - _server?.Dispose(); _client?.Dispose(); + _factory?.Dispose(); _mockClientHandler?.Dispose(); _baseLineTestInstance?.Dispose(); GC.SuppressFinalize(this); } + + private class PipelineStartupFilter : IStartupFilter + { + public Action Configure(Action next) + { + return app => + { + app.UseForwardedHeaders(); + app.UseRouting(); + app.UseSitecoreVisitorIdentification(); + app.UseSitecoreRenderingEngine(); + next(app); + }; + } + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ComplexModelBindingFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ComplexModelBindingFixture.cs index d3aec2f..d975c67 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ComplexModelBindingFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ComplexModelBindingFixture.cs @@ -1,6 +1,7 @@ using System.Net; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -10,31 +11,32 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Binding; -public class ComplexModelBindingFixture : IDisposable +public class ComplexModelBindingFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); - public ComplexModelBindingFixture() + private readonly WebApplicationFactory _factory; + + public ComplexModelBindingFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView(name => name.Equals("Complex-Component", StringComparison.OrdinalIgnoreCase), "ComplexComponent") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -43,8 +45,10 @@ public ComplexModelBindingFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -57,7 +61,7 @@ public async Task SitecoreLayoutModelBinders_BindDataCorrectly() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -103,8 +107,8 @@ public async Task SitecoreLayoutModelBinders_BindDataCorrectly() public void Dispose() { - _server.Dispose(); _mockClientHandler.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/CustomModelContextBindingFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/CustomModelContextBindingFixture.cs index 41c55e1..aaf3948 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/CustomModelContextBindingFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/CustomModelContextBindingFixture.cs @@ -2,6 +2,7 @@ using System.Text.Json.Nodes; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -12,31 +13,31 @@ // ReSharper disable StringLiteralTypo namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Binding; -public class CustomModelContextBindingFixture : IDisposable +public class CustomModelContextBindingFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); + private readonly WebApplicationFactory _factory; - public CustomModelContextBindingFixture() + public CustomModelContextBindingFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView(name => name.Equals("Custom-Model-Context-Component", StringComparison.OrdinalIgnoreCase), "CustomModelContextComponent") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -45,8 +46,10 @@ public CustomModelContextBindingFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -73,7 +76,7 @@ public async Task SitecoreLayoutModelBinders_BindDataCorrectly() Content = new StringContent(jObject!.ToJsonString(Serializer.GetOptions())) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -109,8 +112,8 @@ public async Task SitecoreLayoutModelBinders_BindDataCorrectly() public void Dispose() { - _server.Dispose(); _mockClientHandler.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/CustomResolverBindingFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/CustomResolverBindingFixture.cs index 84961d2..f4383b4 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/CustomResolverBindingFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/CustomResolverBindingFixture.cs @@ -1,6 +1,7 @@ using System.Net; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -11,32 +12,33 @@ // ReSharper disable StringLiteralTypo namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Binding; -public class CustomResolverBindingFixture : IDisposable +public class CustomResolverBindingFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); + private readonly WebApplicationFactory _factory; - public CustomResolverBindingFixture() + public CustomResolverBindingFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView("PartialDesignDynamicPlaceholder") .AddModelBoundView(name => name.Equals("Navigation", StringComparison.OrdinalIgnoreCase), "CustomResolver") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -45,8 +47,10 @@ public CustomResolverBindingFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -60,7 +64,7 @@ public async Task SitecoreLayoutModelBinders_BindDataCorrectly() Content = new StringContent(json) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -80,8 +84,8 @@ public async Task SitecoreLayoutModelBinders_BindDataCorrectly() public void Dispose() { - _server.Dispose(); _mockClientHandler.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ModelBindingErrorHandlingFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ModelBindingErrorHandlingFixture.cs index 67f70c5..8d8d28d 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ModelBindingErrorHandlingFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ModelBindingErrorHandlingFixture.cs @@ -1,6 +1,7 @@ using System.Net; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -10,31 +11,32 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Binding; -public class ModelBindingErrorHandlingFixture : IDisposable +public class ModelBindingErrorHandlingFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); - public ModelBindingErrorHandlingFixture() + private readonly WebApplicationFactory _factory; + + public ModelBindingErrorHandlingFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView(name => name.Equals("Component-With-Missing-Data", StringComparison.OrdinalIgnoreCase), "ComponentWithMissingData") .AddModelBoundView(name => name.Equals("Component-Without-Id", StringComparison.OrdinalIgnoreCase), "ComponentWithoutId"); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -43,8 +45,10 @@ public ModelBindingErrorHandlingFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -57,7 +61,7 @@ public async Task SitecoreLayoutModelBinders_HandleMissingDataCorrectly() Content = new StringContent(Serializer.Serialize(CannedResponses.WithMissingData)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -92,8 +96,8 @@ public async Task SitecoreLayoutModelBinders_HandleMissingDataCorrectly() public void Dispose() { - _server.Dispose(); _mockClientHandler.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ModelBindingFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ModelBindingFixture.cs index 91cb431..7393cc6 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ModelBindingFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ModelBindingFixture.cs @@ -1,5 +1,6 @@ using System.Net; using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -10,31 +11,33 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Binding; -public class ModelBindingFixture : IDisposable +public class ModelBindingFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); - public ModelBindingFixture() + private readonly WebApplicationFactory _factory; + + public ModelBindingFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(); - }) - .Configure(app => + services.AddSitecoreRenderingEngine(); + }); + + builder.Configure(app => { + app.UseRouting(); app.UseSitecoreRenderingEngine(); + app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + }); } [Fact] @@ -46,7 +49,7 @@ public async Task SitecoreRouteModelBinding_ReturnsCorrectData() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); string response = await client.GetStringAsync("WithBoundSitecoreRoute"); // assert that the SitecoreRouteProperty attribute binding worked @@ -68,7 +71,7 @@ public async Task SitecoreContextModelBinding_ReturnsCorrectData() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); string response = await client.GetStringAsync("WithBoundSitecoreContext"); // assert that the SitecoreContextProperty attribute binding worked @@ -88,7 +91,7 @@ public async Task SitecoreResponseModelBinding_ReturnsCorrectData() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); string response = await client.GetStringAsync("WithBoundSitecoreResponse"); // assert that the SitecoreLayoutResponse attribute binding worked @@ -97,8 +100,8 @@ public async Task SitecoreResponseModelBinding_ReturnsCorrectData() public void Dispose() { - _server.Dispose(); _mockClientHandler.Dispose(); + _factory?.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ViewFieldsBindingFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ViewFieldsBindingFixture.cs index 8912153..82624b9 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ViewFieldsBindingFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Binding/ViewFieldsBindingFixture.cs @@ -1,6 +1,7 @@ using System.Net; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -10,31 +11,32 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Binding; -public class ViewFieldsBindingFixture : IDisposable +public class ViewFieldsBindingFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); - public ViewFieldsBindingFixture() + private readonly WebApplicationFactory _factory; + + public ViewFieldsBindingFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView(name => name.Equals("Component-5", StringComparison.OrdinalIgnoreCase), "Component5") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -43,8 +45,10 @@ public ViewFieldsBindingFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -57,7 +61,7 @@ public async Task SitecoreLayoutModelBinders_BindDataCorrectly() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -83,8 +87,8 @@ public async Task SitecoreLayoutModelBinders_BindDataCorrectly() public void Dispose() { - _server.Dispose(); _mockClientHandler.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ControllerMiddlewareFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ControllerMiddlewareFixture.cs index 4ea399e..8449c37 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ControllerMiddlewareFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ControllerMiddlewareFixture.cs @@ -1,32 +1,33 @@ using System.Net; using AwesomeAssertions; -using Microsoft.AspNetCore.TestHost; +using Microsoft.AspNetCore.Mvc.Testing; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; +using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions; using Xunit; namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures; -public class ControllerMiddlewareFixture : IDisposable +public class ControllerMiddlewareFixture : IClassFixture>, IDisposable { private const string MiddlewareController = "ControllerMiddleware"; private const string GlobalMiddlewareController = "GlobalMiddleware"; - private readonly TestServer _server; - - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new MockHttpMessageHandler(); private readonly Uri _layoutServiceUri = new("http://layout.service"); - public ControllerMiddlewareFixture() + private readonly WebApplicationFactory _factory; + + public ControllerMiddlewareFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder + services + .AddRouting() .AddSitecoreLayoutService() .AddHttpHandler( "mock", @@ -35,10 +36,16 @@ public ControllerMiddlewareFixture() BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - }) - .Configure(_ => { }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + services.AddSitecoreRenderingEngine(); + }); + + builder.Configure(app => + { + app.UseRouting(); + app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); + }); + }); } [Fact] @@ -49,7 +56,7 @@ public async Task HttpClient_IsInvoked() StatusCode = HttpStatusCode.OK }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); await client.GetAsync(MiddlewareController); _mockClientHandler.WasInvoked.Should().BeTrue(); @@ -63,7 +70,7 @@ public async Task HttpClient_IsNotInvoked() StatusCode = HttpStatusCode.OK }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); await client.GetAsync(GlobalMiddlewareController); _mockClientHandler.WasInvoked.Should().BeFalse(); @@ -77,7 +84,7 @@ public async Task Controller_ReturnsCorrectContent() StatusCode = HttpStatusCode.OK }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); string response = await client.GetStringAsync(GlobalMiddlewareController); response.Should().Be("\"success\""); @@ -91,7 +98,7 @@ public async Task HttpClient_LayoutServiceUriMapped() StatusCode = HttpStatusCode.OK }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); await client.GetAsync(MiddlewareController); _mockClientHandler.Requests.Single().RequestUri!.AbsoluteUri.Should() @@ -100,8 +107,8 @@ public async Task HttpClient_LayoutServiceUriMapped() public void Dispose() { - _server.Dispose(); _mockClientHandler.Dispose(); + _factory?.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/CustomRenderTypes/LoggingComponentRendererFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/CustomRenderTypes/LoggingComponentRendererFixture.cs index 2c22dd2..63c70ad 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/CustomRenderTypes/LoggingComponentRendererFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/CustomRenderTypes/LoggingComponentRendererFixture.cs @@ -1,6 +1,7 @@ using System.Net; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -11,32 +12,32 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.CustomRenderTypes; -public class LoggingComponentRendererFixture : IDisposable +public class LoggingComponentRendererFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); - public LoggingComponentRendererFixture() - { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); + private readonly WebApplicationFactory _factory; - testHostBuilder - .ConfigureServices(builder => + public LoggingComponentRendererFixture(TestWebApplicationFactory factory) + { + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => { - builder.AddSingleton(new IntegrationTestLoggerProvider()); + services.AddSingleton(new IntegrationTestLoggerProvider()); - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + services.AddSitecoreRenderingEngine(options => { options.AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -45,8 +46,10 @@ public LoggingComponentRendererFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -59,7 +62,7 @@ public async Task CustomRenderTypes_DefaultRendererWritesToLogWithoutRenderingHt Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -77,7 +80,7 @@ public async Task CustomRenderTypes_DefaultRendererWritesToLogWithoutRenderingHt public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/CustomRenderTypes/MultipleComponentsAddedFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/CustomRenderTypes/MultipleComponentsAddedFixture.cs index 8212bfa..7957e98 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/CustomRenderTypes/MultipleComponentsAddedFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/CustomRenderTypes/MultipleComponentsAddedFixture.cs @@ -2,6 +2,7 @@ using System.Text.Encodings.Web; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -11,32 +12,32 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.CustomRenderTypes; -public class MultipleComponentsAddedFixture : IDisposable +public class MultipleComponentsAddedFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); + private readonly WebApplicationFactory _factory; - public MultipleComponentsAddedFixture() + public MultipleComponentsAddedFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView(name => name.Equals("Component-3", StringComparison.OrdinalIgnoreCase), "Component3") .AddModelBoundView(name => name.Equals("Component-6", StringComparison.OrdinalIgnoreCase), "Component6") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -45,8 +46,10 @@ public MultipleComponentsAddedFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -59,7 +62,7 @@ public async Task CustomRenderTypes_MultipleComponentsBoundsInCorrectOrder() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -85,7 +88,7 @@ public async Task CustomRenderTypes_MultipleComponentsBoundsInCorrectOrder() public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/CustomRenderTypes/PartialViewRendererFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/CustomRenderTypes/PartialViewRendererFixture.cs index 02773de..4f15ca8 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/CustomRenderTypes/PartialViewRendererFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/CustomRenderTypes/PartialViewRendererFixture.cs @@ -1,6 +1,7 @@ using System.Net; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -10,31 +11,32 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.CustomRenderTypes; -public class PartialViewRendererFixture : IDisposable +public class PartialViewRendererFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); + private readonly WebApplicationFactory _factory; - public PartialViewRendererFixture() + public PartialViewRendererFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + + services.AddSitecoreRenderingEngine(options => { options .AddPartialView(name => name.Equals("Component-6", StringComparison.OrdinalIgnoreCase), "_PartialView") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -43,8 +45,10 @@ public PartialViewRendererFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -57,7 +61,7 @@ public async Task CustomRenderTypes_PartialViewRendersCorrectly() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -74,7 +78,7 @@ public async Task CustomRenderTypes_PartialViewRendersCorrectly() public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ErrorHandlingFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ErrorHandlingFixture.cs index a476e37..6f85972 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ErrorHandlingFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ErrorHandlingFixture.cs @@ -2,7 +2,7 @@ using AutoFixture; using AwesomeAssertions; using HtmlAgilityPack; -using Microsoft.AspNetCore.TestHost; +using Microsoft.AspNetCore.Mvc.Testing; using Sitecore.AspNetCore.SDK.AutoFixture.Attributes; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Exceptions; @@ -22,77 +22,95 @@ public class ErrorHandlingFixture public static Action ValidHttpClient => f => { - TestServerBuilder testHostBuilder = new(); - MockHttpMessageHandler mockClientHandler = new(); - testHostBuilder - .ConfigureServices(builder => + MockHttpMessageHandler mockClientHandler = new MockHttpMessageHandler(); + WebApplicationFactory factory = new TestWebApplicationFactory() + .WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder - .AddSitecoreLayoutService() + services.AddRouting(); + services.AddControllersWithViews(); + services.AddSitecoreLayoutService() .AddHttpHandler("valid", _ => new HttpClient(mockClientHandler) { BaseAddress = new Uri("http://layout.service") }) .AsDefaultHandler(); - }) - .Configure(app => + + services.AddSitecoreRenderingEngine(); + }); + + builder.Configure(app => { + app.UseRouting(); app.UseSitecoreRenderingEngine(); + app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); }); - - TestServer server = testHostBuilder.BuildServer(new Uri("http://localhost")); + }); f.Inject(mockClientHandler); - f.Inject(server); + f.Inject(factory); }; public static Action InvalidHttpClient => f => { - TestServerBuilder testHostBuilder = new(); - MockHttpMessageHandler mockClientHandler = new(); - testHostBuilder - .ConfigureServices(builder => + MockHttpMessageHandler mockClientHandler = new MockHttpMessageHandler(); + WebApplicationFactory factory = new TestWebApplicationFactory() + .WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder - .AddSitecoreLayoutService() + services.AddRouting(); + services.AddControllersWithViews(); + services.AddSitecoreLayoutService() .AddHttpHandler("invalid", _ => new HttpClient { BaseAddress = new Uri("http://invalid.url") }) .AsDefaultHandler(); - }) - .Configure(app => + + services.AddSitecoreRenderingEngine(); + }); + + builder.Configure(app => { + app.UseRouting(); app.UseSitecoreRenderingEngine(); + app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); }); - - TestServer server = testHostBuilder.BuildServer(new Uri("http://localhost")); + }); f.Inject(mockClientHandler); - f.Inject(server); + f.Inject(factory); }; public static Action InvalidHttpMessageConfiguration => f => { - TestServerBuilder testHostBuilder = new(); - MockHttpMessageHandler mockClientHandler = new(); - testHostBuilder - .ConfigureServices(builder => + MockHttpMessageHandler mockClientHandler = new MockHttpMessageHandler(); + WebApplicationFactory factory = new TestWebApplicationFactory() + .WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder - .AddSitecoreLayoutService() + services.AddRouting(); + services.AddControllersWithViews(); + services.AddSitecoreLayoutService() .AddHttpHandler("valid", _ => new HttpClient(mockClientHandler) { BaseAddress = new Uri("http://layout.service") }) .MapFromRequest((layoutRequest, httpMessage) => httpMessage.Headers.Add("test", layoutRequest["invalidkey"]!.ToString())) .AsDefaultHandler(); - }) - .Configure(app => + + services.AddSitecoreRenderingEngine(); + }); + + builder.Configure(app => { + app.UseRouting(); app.UseSitecoreRenderingEngine(); + app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); }); - - TestServer server = testHostBuilder.BuildServer(new Uri("http://localhost")); + }); f.Inject(mockClientHandler); - f.Inject(server); + f.Inject(factory); }; [Theory] [AutoNSubstituteData(nameof(InvalidHttpMessageConfiguration))] - public async Task HttpMessageConfigurationError_Returns_SitecoreLayoutServiceMessageConfigurationException(TestServer server, MockHttpMessageHandler clientHandler) + public async Task HttpMessageConfigurationError_Returns_SitecoreLayoutServiceMessageConfigurationException(TestWebApplicationFactory factory, MockHttpMessageHandler clientHandler) { // Arrange clientHandler.Responses.Push(new HttpResponseMessage @@ -100,7 +118,33 @@ public async Task HttpMessageConfigurationError_Returns_SitecoreLayoutServiceMes StatusCode = HttpStatusCode.OK }); - ISitecoreLayoutClient layoutClient = server.Services.GetRequiredService(); + WebApplicationFactory configuredFactory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => + { + services.AddRouting(); + services.AddControllersWithViews(); + services.AddLogging(); + services.AddSitecoreLayoutService() + .AddHttpHandler("valid", _ => new HttpClient(clientHandler) { BaseAddress = new Uri("http://layout.service") }) + .MapFromRequest((layoutRequest, httpMessage) => httpMessage.Headers.Add("test", layoutRequest["invalidkey"]!.ToString())) + .AsDefaultHandler(); + + services.AddSitecoreRenderingEngine(); + }); + + builder.Configure(app => + { + app.UseRouting(); + app.UseSitecoreRenderingEngine(); + app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); + }); + }); + + // Ensure host is started so services are available + _ = configuredFactory.Server; + + ISitecoreLayoutClient layoutClient = configuredFactory.Services.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("test"); @@ -114,12 +158,18 @@ public async Task HttpMessageConfigurationError_Returns_SitecoreLayoutServiceMes response.Errors.Should().ContainSingle(e => e.GetType() == typeof(SitecoreLayoutServiceMessageConfigurationException)); } - [Theory] - [AutoNSubstituteData(nameof(InvalidHttpClient))] - public async Task HttpRequestTimeoutError_Returns_CouldNotContactSitecoreLayoutServiceClientException(TestServer server) + [Fact] + public async Task HttpRequestTimeoutError_Returns_CouldNotContactSitecoreLayoutServiceClientException() { // Arrange - ISitecoreLayoutClient layoutClient = server.Services.GetRequiredService(); + // Build a local service provider with the layout client registered so tests are independent + IServiceCollection services = new ServiceCollection(); + services.AddLogging(); + services.AddSitecoreLayoutService() + .AddHttpHandler("invalid", _ => new HttpClient { BaseAddress = new Uri("http://invalid.url") }) + .AsDefaultHandler(); + IServiceProvider provider = services.BuildServiceProvider(); + ISitecoreLayoutClient layoutClient = provider.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("test"); @@ -135,7 +185,7 @@ public async Task HttpRequestTimeoutError_Returns_CouldNotContactSitecoreLayoutS [Theory] [AutoNSubstituteData(nameof(ValidHttpClient))] - public async Task HttpResponse50xErrors_Return_InvalidResponseSitecoreLayoutServiceClientException(TestServer server, MockHttpMessageHandler clientHandler) + public async Task HttpResponse50xErrors_Return_InvalidResponseSitecoreLayoutServiceClientException(MockHttpMessageHandler clientHandler) { // Arrange HttpStatusCode[] responseStatuses = @@ -160,7 +210,14 @@ public async Task HttpResponse50xErrors_Return_InvalidResponseSitecoreLayoutServ StatusCode = responseStatus }); - ISitecoreLayoutClient layoutClient = server.Services.GetRequiredService(); + // Build a local service provider with the layout client registered so tests are independent + IServiceCollection services = new ServiceCollection(); + services.AddLogging(); + services.AddSitecoreLayoutService() + .AddHttpHandler("valid", _ => new HttpClient(clientHandler) { BaseAddress = new Uri("http://layout.service") }) + .AsDefaultHandler(); + IServiceProvider provider = services.BuildServiceProvider(); + ISitecoreLayoutClient layoutClient = provider.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("test"); @@ -185,7 +242,7 @@ public async Task HttpResponse50xErrors_Return_InvalidResponseSitecoreLayoutServ [Theory] [AutoNSubstituteData(nameof(ValidHttpClient))] - public async Task HttpResponse40xErrors_Return_InvalidRequestSitecoreLayoutServiceClientException(TestServer server, MockHttpMessageHandler clientHandler) + public async Task HttpResponse40xErrors_Return_InvalidRequestSitecoreLayoutServiceClientException(MockHttpMessageHandler clientHandler) { // Arrange HttpStatusCode[] responseStatuses = @@ -225,7 +282,14 @@ public async Task HttpResponse40xErrors_Return_InvalidRequestSitecoreLayoutServi StatusCode = responseStatus }); - ISitecoreLayoutClient layoutClient = server.Services.GetRequiredService(); + // Build a local service provider with the layout client registered so tests are independent + IServiceCollection services = new ServiceCollection(); + services.AddLogging(); + services.AddSitecoreLayoutService() + .AddHttpHandler("valid", _ => new HttpClient(clientHandler) { BaseAddress = new Uri("http://layout.service") }) + .AsDefaultHandler(); + IServiceProvider provider = services.BuildServiceProvider(); + ISitecoreLayoutClient layoutClient = provider.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("test"); @@ -247,7 +311,7 @@ public async Task HttpResponse40xErrors_Return_InvalidRequestSitecoreLayoutServi [Theory] [AutoNSubstituteData(nameof(ValidHttpClient))] - public async Task HttpResponse404Error_Returns_ContentAndItemNotFoundSitecoreLayoutServiceClientException(TestServer server, MockHttpMessageHandler clientHandler) + public async Task HttpResponse404Error_Returns_ContentAndItemNotFoundSitecoreLayoutServiceClientException(MockHttpMessageHandler clientHandler) { // Arrange const HttpStatusCode responseStatus = HttpStatusCode.NotFound; @@ -258,7 +322,14 @@ public async Task HttpResponse404Error_Returns_ContentAndItemNotFoundSitecoreLay Content = new StringContent("""{ "sitecore": { "sitecoredata": { "context": { "site": { "name": "404test" }}}}}""") }); - ISitecoreLayoutClient layoutClient = server.Services.GetRequiredService(); + // Build a local service provider with the layout client registered so tests are independent + IServiceCollection services = new ServiceCollection(); + services.AddLogging(); + services.AddSitecoreLayoutService() + .AddHttpHandler("valid", _ => new HttpClient(clientHandler) { BaseAddress = new Uri("http://layout.service") }) + .AsDefaultHandler(); + IServiceProvider provider = services.BuildServiceProvider(); + ISitecoreLayoutClient layoutClient = provider.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("test"); @@ -281,7 +352,7 @@ public async Task HttpResponse404Error_Returns_ContentAndItemNotFoundSitecoreLay [Theory] [AutoNSubstituteData(nameof(ValidHttpClient))] - public async Task HttpResponseDeserializationError_Returns_InvalidResponseSitecoreLayoutServiceClientException(TestServer server, MockHttpMessageHandler clientHandler) + public async Task HttpResponseDeserializationError_Returns_InvalidResponseSitecoreLayoutServiceClientException(MockHttpMessageHandler clientHandler) { // Arrange HttpStatusCode responseStatus = HttpStatusCode.NotFound; @@ -292,7 +363,14 @@ public async Task HttpResponseDeserializationError_Returns_InvalidResponseSiteco Content = new StringContent("invalid json") }); - ISitecoreLayoutClient layoutClient = server.Services.GetRequiredService(); + // Build a local service provider with the layout client registered so tests are independent + IServiceCollection services = new ServiceCollection(); + services.AddLogging(); + services.AddSitecoreLayoutService() + .AddHttpHandler("valid", _ => new HttpClient(clientHandler) { BaseAddress = new Uri("http://layout.service") }) + .AsDefaultHandler(); + IServiceProvider provider = services.BuildServiceProvider(); + ISitecoreLayoutClient layoutClient = provider.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("test"); @@ -308,7 +386,7 @@ public async Task HttpResponseDeserializationError_Returns_InvalidResponseSiteco [Theory] [AutoNSubstituteData(nameof(ValidHttpClient))] - public async Task HttpResponse10xErrors_Return_SitecoreLayoutServiceClientException(TestServer server, MockHttpMessageHandler clientHandler) + public async Task HttpResponse10xErrors_Return_SitecoreLayoutServiceClientException(MockHttpMessageHandler clientHandler) { // Arrange HttpStatusCode[] responseStatuses = @@ -326,7 +404,14 @@ public async Task HttpResponse10xErrors_Return_SitecoreLayoutServiceClientExcept StatusCode = responseStatus }); - ISitecoreLayoutClient layoutClient = server.Services.GetRequiredService(); + // Build a local service provider with the layout client registered so tests are independent + IServiceCollection services = new ServiceCollection(); + services.AddLogging(); + services.AddSitecoreLayoutService() + .AddHttpHandler("valid", _ => new HttpClient(clientHandler) { BaseAddress = new Uri("http://layout.service") }) + .AsDefaultHandler(); + IServiceProvider provider = services.BuildServiceProvider(); + ISitecoreLayoutClient layoutClient = provider.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("test"); @@ -348,7 +433,7 @@ public async Task HttpResponse10xErrors_Return_SitecoreLayoutServiceClientExcept [Theory] [AutoNSubstituteData(nameof(ValidHttpClient))] - public async Task HttpResponse30xErrors_Return_SitecoreLayoutServiceClientException(TestServer server, MockHttpMessageHandler clientHandler) + public async Task HttpResponse30xErrors_Return_SitecoreLayoutServiceClientException(MockHttpMessageHandler clientHandler) { // Arrange HttpStatusCode[] responseStatuses = @@ -376,7 +461,14 @@ public async Task HttpResponse30xErrors_Return_SitecoreLayoutServiceClientExcept StatusCode = responseStatus }); - ISitecoreLayoutClient layoutClient = server.Services.GetRequiredService(); + // Build a local service provider with the layout client registered so tests are independent + IServiceCollection services = new ServiceCollection(); + services.AddLogging(); + services.AddSitecoreLayoutService() + .AddHttpHandler("valid", _ => new HttpClient(clientHandler) { BaseAddress = new Uri("http://layout.service") }) + .AsDefaultHandler(); + IServiceProvider provider = services.BuildServiceProvider(); + ISitecoreLayoutClient layoutClient = provider.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("test"); @@ -398,14 +490,36 @@ public async Task HttpResponse30xErrors_Return_SitecoreLayoutServiceClientExcept [Theory] [AutoNSubstituteData(nameof(ValidHttpClient))] - public async Task ErrorView_Returns_InvalidResponseSitecoreLayoutServiceClientException(TestServer server, MockHttpMessageHandler clientHandler) + public async Task ErrorView_Returns_InvalidResponseSitecoreLayoutServiceClientException(TestWebApplicationFactory factory, MockHttpMessageHandler clientHandler) { clientHandler.Responses.Push(new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest }); - HttpClient client = server.CreateClient(); + WebApplicationFactory configuredFactory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => + { + services.AddRouting(); + services.AddControllersWithViews(); + services.AddLogging(); + services.AddSitecoreLayoutService() + .AddHttpHandler("valid", _ => new HttpClient(clientHandler) { BaseAddress = new Uri("http://layout.service") }) + .AsDefaultHandler(); + + services.AddSitecoreRenderingEngine(); + }); + + builder.Configure(app => + { + app.UseRouting(); + app.UseSitecoreRenderingEngine(); + app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); + }); + }); + + HttpClient client = configuredFactory.CreateClient(); // Act string response = await client.GetStringAsync("Error"); diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ExperienceEditor/ExperienceEditorCustomRoutingFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ExperienceEditor/ExperienceEditorCustomRoutingFixture.cs index 11b0c75..6a67f60 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ExperienceEditor/ExperienceEditorCustomRoutingFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ExperienceEditor/ExperienceEditorCustomRoutingFixture.cs @@ -1,55 +1,34 @@ using System.Net; using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using NSubstitute; using Sitecore.AspNetCore.SDK.ExperienceEditor.Extensions; +using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; using Sitecore.AspNetCore.SDK.LayoutService.Client.Interfaces; +using Sitecore.AspNetCore.SDK.LayoutService.Client.Request; +using Sitecore.AspNetCore.SDK.LayoutService.Client.Response; +using Sitecore.AspNetCore.SDK.LayoutService.Client.Response.Model; +using Sitecore.AspNetCore.SDK.LayoutService.Client.Serialization; using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions; using Sitecore.AspNetCore.SDK.TestData; using Xunit; +using Route = Sitecore.AspNetCore.SDK.LayoutService.Client.Response.Model.Route; namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.ExperienceEditor; public class ExperienceEditorCustomRoutingFixture : IDisposable { - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; public ExperienceEditorCustomRoutingFixture() { - TestServerBuilder testHostBuilder = new(); - _ = testHostBuilder - .ConfigureServices(builder => - { - builder.AddSingleton(Substitute.For()); - builder.AddSitecoreRenderingEngine(options => - { - options.AddDefaultComponentRenderer(); - }).WithExperienceEditor(options => - { - options.Endpoint = TestConstants.EEMiddlewarePostEndpoint; - options.JssEditingSecret = TestConstants.JssEditingSecret; - - options.MapToRequest((sitecoreResponse, scPath, httpRequest) => - httpRequest.Path = scPath + "/" + sitecoreResponse.Sitecore?.Route?.DatabaseName); - }); - }) - .Configure(app => - { - app.UseSitecoreExperienceEditor(); - app.UseRouting(); - app.UseSitecoreRenderingEngine(); - app.UseEndpoints(endpoints => - { - endpoints.MapFallbackToController("Default", "Home"); - }); - }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + _factory = BuildExperienceEditorCustomRoutingWebApplicationFactory(); } public void Dispose() { - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } @@ -57,7 +36,7 @@ public void Dispose() public async Task EECustomRoute_MapsToCorrectRoute_WhenCustomRouteSetInOptions() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EESampleRequest); // Act @@ -76,4 +55,43 @@ public async Task EECustomRoute_MapsToCorrectRoute_WhenCustomRouteSetInOptions() responseString.Should().EndWith("}"); responseString.Should().Contain("master"); } + + private WebApplicationFactory BuildExperienceEditorCustomRoutingWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddSingleton(Substitute.For()); + services.AddRouting(); + services.AddSitecoreLayoutService(); + services.AddControllersWithViews(); + + services.AddSitecoreRenderingEngine(options => + { + options.AddDefaultComponentRenderer(); + }).WithExperienceEditor(options => + { + options.Endpoint = TestConstants.EEMiddlewarePostEndpoint; + options.JssEditingSecret = TestConstants.JssEditingSecret; + + options.MapToRequest((sitecoreResponse, scPath, httpRequest) => + httpRequest.Path = scPath + "/" + sitecoreResponse.Sitecore?.Route?.DatabaseName); + }); + }); + + builder.Configure(app => + { + app.UseSitecoreExperienceEditor(); + app.UseRouting(); + app.UseSitecoreRenderingEngine(); + app.UseEndpoints(endpoints => + { + endpoints.MapFallbackToController("Default", "Home"); + }); + }); + }); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ExperienceEditor/ExperienceEditorFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ExperienceEditor/ExperienceEditorFixture.cs index 8d9515c..fc561b6 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ExperienceEditor/ExperienceEditorFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ExperienceEditor/ExperienceEditorFixture.cs @@ -1,9 +1,11 @@ using System.Net; using System.Text; using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using NSubstitute; using Sitecore.AspNetCore.SDK.ExperienceEditor.Extensions; +using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; using Sitecore.AspNetCore.SDK.LayoutService.Client.Interfaces; using Sitecore.AspNetCore.SDK.LayoutService.Client.Request; using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions; @@ -15,43 +17,18 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Exp public class ExperienceEditorFixture : IDisposable { - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; public ExperienceEditorFixture() { - TestServerBuilder testHostBuilder = new(); - _ = testHostBuilder - .ConfigureServices(builder => - { - builder.AddSingleton(Substitute.For()); - builder.AddSitecoreRenderingEngine(options => - { - options.AddDefaultComponentRenderer(); - }).WithExperienceEditor(options => - { - options.Endpoint = TestConstants.EEMiddlewarePostEndpoint; - options.JssEditingSecret = TestConstants.JssEditingSecret; - }); - }) - .Configure(app => - { - app.UseSitecoreExperienceEditor(); - app.UseRouting(); - app.UseSitecoreRenderingEngine(); - app.UseEndpoints(endpoints => - { - endpoints.MapFallbackToController("Default", "Home"); - }); - }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + _factory = BuildExperienceEditorWebApplicationFactory(); } [Fact] public async Task EEEndpoint_SendsNonWrappedResponse_WhenGetRequest() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act HttpResponseMessage response = await client.GetAsync(TestConstants.EEMiddlewarePostEndpoint); @@ -66,7 +43,7 @@ public async Task EEEndpoint_SendsNonWrappedResponse_WhenGetRequest() public async Task EEEndpoint_SendsNonWrappedResponse_WhenGetRequestInSampleEndPoint() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act HttpResponseMessage response = await client.GetAsync(TestConstants.SampleEndPoint); @@ -81,7 +58,7 @@ public async Task EEEndpoint_SendsNonWrappedResponse_WhenGetRequestInSampleEndPo public async Task EEEndpoint_Sends400ErrorCodeInResponse_WhenEmptyStringSentInRequestBody() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(string.Empty, Encoding.UTF8, "application/json"); // Act @@ -97,7 +74,7 @@ public async Task EEEndpoint_Sends400ErrorCodeInResponse_WhenEmptyStringSentInRe public async Task EEEndpoint_Sends400ErrorCodeInResponse_WhenInvalidRequestBody() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new("abcnnmkksmvkdmfvkdkvmkdmv"); HttpResponseMessage response = await client @@ -112,9 +89,9 @@ public async Task EEEndpoint_Sends400ErrorCodeInResponse_WhenInvalidRequestBody( public async Task EEEndpoint_SendsNonWrappedResponse_WhenPostedToNonEEEndpoint() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EESampleRequest); - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); // Act HttpResponseMessage response = await client @@ -135,7 +112,7 @@ public async Task EEEndpoint_SendsNonWrappedResponse_WhenPostedToNonEEEndpoint() public async Task EEEndpoint_SendsCorrectResponse_WhenCorrectDataSentInRequestBody() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EESampleRequest); // Act @@ -159,7 +136,7 @@ public async Task EEEndpoint_SendsCorrectResponse_WhenCorrectDataSentInRequestBo public async Task EEEndpoint_SendsCorrectResponse_WhenLargeDataSentInRequestBody() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EELargeRequest); // Act @@ -180,9 +157,9 @@ public async Task EEEndpoint_SendsCorrectResponse_WhenLargeDataSentInRequestBody public async Task EEEndpoint_ByPassesLayoutServiceRequest_WhenCorrectDataSentInRequestBody() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EESampleRequest); - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); // Act HttpResponseMessage response = await client @@ -198,8 +175,8 @@ public async Task EEEndpoint_ByPassesLayoutServiceRequest_WhenCorrectDataSentInR public async Task EEEndpoint_MakeLayoutServiceRequest_WhenGetRequest() { // Arrange - HttpClient client = _server.CreateClient(); - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + HttpClient client = _factory.CreateClient(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); // Act HttpResponseMessage response = await client @@ -217,9 +194,9 @@ public async Task EEEndpoint_MakeLayoutServiceRequest_WhenGetRequest() public async Task EEEndpoint_MakesLayoutServiceRequest_WhenInvalidRequest_SendToSampleEEndPoint() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new("invalidPostRequest"); - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); // Act HttpResponseMessage response = await client @@ -234,8 +211,8 @@ public async Task EEEndpoint_MakesLayoutServiceRequest_WhenInvalidRequest_SendTo public async Task EEEndpoint_MakesLayoutServiceRequest_WhenPostedToNonEEEndpoint() { // Arrange - HttpClient client = _server.CreateClient(); - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + HttpClient client = _factory.CreateClient(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); // Act HttpResponseMessage response = await client.PostAsync(TestConstants.SampleEndPoint, new StringContent(string.Empty, Encoding.UTF8, "application/json")); @@ -249,10 +226,10 @@ public async Task EEEndpoint_MakesLayoutServiceRequest_WhenPostedToNonEEEndpoint public async Task EEEndpoint_MakesLayoutServiceRequest_WhenValidRequest_SendToSampleEndPoint() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EESampleRequest); - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); // Act HttpResponseMessage response = await client.PostAsync(TestConstants.SampleEndPoint, content); @@ -266,7 +243,7 @@ public async Task EEEndpoint_MakesLayoutServiceRequest_WhenValidRequest_SendToSa public async Task EEEndpoint_ChangePostToGet_WhenPostedToEEEndpoint() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EESampleRoutingRequest); // Act @@ -284,7 +261,7 @@ public async Task EEEndpoint_ChangePostToGet_WhenPostedToEEEndpoint() public async Task EEEndpoint_NotChangePostToGet_WhenPostedToNonEEEndpoint() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EESampleRoutingRequest); // Act @@ -307,7 +284,7 @@ public async Task EEEndpoint_NotChangePostToGet_WhenPostedToNonEEEndpoint() public async Task EEEndpoint_SendsInvalidResponse_WhenPostedToNonEEEndpoint(string invalidEndPoint) { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EESampleRequest); // Act @@ -328,7 +305,7 @@ public async Task EEEndpoint_SendsInvalidResponse_WhenPostedToNonEEEndpoint(stri public async Task EEEndpoint_SendsCorrectResponse_withoutCaseSensitiveEndPoint(string validEndPoint) { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EESampleRequest); // Act @@ -347,7 +324,7 @@ public async Task EEEndpoint_SendsCorrectResponse_withoutCaseSensitiveEndPoint(s public async Task EEEndpoint_ReturnSuccess_WhenRequestContainEmptyPath() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EEEmptyRoutingRequest); // Act @@ -366,7 +343,7 @@ public async Task EEEndpoint_ReturnSuccess_WhenRequestContainEmptyPath() public async Task EEEndpoint_NotChangeToGET_WhenRequestSendToDefaultRouting_ToSampleRoutingPoint() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EEDefaultRoutingRequest); // Act @@ -384,7 +361,7 @@ public async Task EEEndpoint_NotChangeToGET_WhenRequestSendToDefaultRouting_ToSa public async Task EEEndpoint_NotChangeToGet_whenInvalidRequest_SendToSampleRoutingEndPoint() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new("InvalidPost"); // Act @@ -402,7 +379,7 @@ public async Task EEEndpoint_NotChangeToGet_whenInvalidRequest_SendToSampleRouti public async Task ReturnSuccess_whenRequestSendWithoutPath_ToSampleRoutingEndPoint() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EmptyPathRequest); // Act @@ -420,7 +397,7 @@ public async Task ReturnSuccess_whenRequestSendWithoutPath_ToSampleRoutingEndPoi public async Task EEEndpoint_Send400ErrorCode_WhenIncompleteRequest_EEEndPoint() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EEIncompleteRequest); // Act @@ -437,7 +414,7 @@ public async Task EEEndpoint_Send400ErrorCode_WhenIncompleteRequest_EEEndPoint() public async Task EEndpoint_ReturnSuccess_WhenRequestContainDefaultPath() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EEDefaultRoutingRequest); // Act @@ -454,7 +431,7 @@ public async Task EEndpoint_ReturnSuccess_WhenRequestContainDefaultPath() public async Task EEEndpoint_SendsWrappedResponse_WhenRequestContainLongPath() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EELongPathRequest); // Act @@ -471,7 +448,7 @@ public async Task EEEndpoint_SendsWrappedResponse_WhenRequestContainLongPath() public async Task EEEndpoint_Sends400Error_WhenRequestDoesNotHaveItemPath() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EmptyPathRequest); // Act @@ -488,7 +465,7 @@ public async Task EEEndpoint_Sends400Error_WhenRequestDoesNotHaveItemPath() public async Task EEEndpoint_ChangePostToGet_WhenRequestHaveCaseSensitivePath() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.CaseSensitiveItemPathRequest); // Act @@ -506,7 +483,7 @@ public async Task EEEndpoint_ChangePostToGet_WhenRequestHaveCaseSensitivePath() public async Task NotChangeToGet_WhenRequestContainCaseSensitivePath_PostToNonEEEndPoint() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.CaseSensitiveItemPathRequest); // Act @@ -524,7 +501,7 @@ public async Task NotChangeToGet_WhenRequestContainCaseSensitivePath_PostToNonEE public async Task EEEndpoint_SendsUnauthorizedErrorCodeInResponse_WhenWrongSecret() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EESampleRequestWithWrongRequestedSecret, Encoding.UTF8, "application/json"); // Act @@ -540,7 +517,7 @@ public async Task EEEndpoint_SendsUnauthorizedErrorCodeInResponse_WhenWrongSecre public async Task EEEndpoint_SendsUnauthorizedErrorCodeInResponse_WhenNoSecret() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); StringContent content = new(TestConstants.EESampleRequestWithNoSecret, Encoding.UTF8, "application/json"); // Act @@ -554,7 +531,42 @@ public async Task EEEndpoint_SendsUnauthorizedErrorCodeInResponse_WhenNoSecret() public void Dispose() { - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } + + private WebApplicationFactory BuildExperienceEditorWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddRouting(); + services.AddSitecoreLayoutService(); + services.AddSingleton(Substitute.For()); + services.AddControllersWithViews(); + services.AddSitecoreRenderingEngine(options => + { + options.AddDefaultComponentRenderer(); + }).WithExperienceEditor(options => + { + options.Endpoint = TestConstants.EEMiddlewarePostEndpoint; + options.JssEditingSecret = TestConstants.JssEditingSecret; + }); + }); + + builder.Configure(app => + { + app.UseSitecoreExperienceEditor(); + app.UseRouting(); + app.UseSitecoreRenderingEngine(); + app.UseEndpoints(endpoints => + { + endpoints.MapFallbackToController("Default", "Home"); + }); + }); + }); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ExperienceEditor/ExperienceEditorParsePathByItemIdFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ExperienceEditor/ExperienceEditorParsePathByItemIdFixture.cs index 83488f6..9d070fb 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ExperienceEditor/ExperienceEditorParsePathByItemIdFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ExperienceEditor/ExperienceEditorParsePathByItemIdFixture.cs @@ -1,10 +1,11 @@ using System.Dynamic; using System.Text; using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using NSubstitute; -using Sitecore.AspNetCore.SDK.ExperienceEditor.Configuration; using Sitecore.AspNetCore.SDK.ExperienceEditor.Extensions; +using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; using Sitecore.AspNetCore.SDK.LayoutService.Client.Interfaces; using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions; using Sitecore.AspNetCore.SDK.TestData; @@ -23,15 +24,11 @@ public class ExperienceEditorParsePathByItemIdFixture : IDisposable private const string PreviewRequestWithoutItemPath = """{"id":"jss-sample-app","args":["/?sc_itemid=%7bcfdd7ba2-e646-5294-87fc-6fad34451a97%7d&sc_ee_fb=false&sc_lang=en&sc_mode=preview&sc_debug=0&sc_trace=0&sc_prof=0&sc_ri=0&sc_rb=0","{\"sitecore\":{\"context\":{\"pageEditing\":false,\"site\":{\"name\":\"jss-sample-app\"},\"pageState\":\"preview\",\"language\":\"en\"},\"route\":{\"name\":\"sample-1\",\"displayName\":\"sample-1\",\"fields\":{\"pageTitle\":{\"value\":\"Sample 1 Page Title\"}},\"databaseName\":\"master\",\"deviceId\":\"fe5d7fdf-89c0-4d99-9aa3-b5fbd009c9f3\",\"itemId\":\"cfdd7ba2-e646-5294-87fc-6fad34451a97\",\"itemLanguage\":\"en\",\"itemVersion\":1,\"layoutId\":\"5179e218-3df6-5af7-8147-d2d4c05da992\",\"templateId\":\"dfe73d70-9835-584e-b0f5-28c58ab064d7\",\"templateName\":\"App Route\",\"placeholders\":{\"jss-main\":[{\"uid\":\"9157cc8c-5760-5114-9f2d-93cbe39b30dc\",\"componentName\":\"ContentBlock\",\"dataSource\":\"{27F322AF-3D30-5F2F-ADA2-DAB630D35EC6}\",\"params\":{},\"fields\":{\"heading\":{\"value\":\"GraphQL Sample 1\"},\"content\":{\"value\":\"

A child route here to illustrate the power of GraphQL queries. Back to GraphQL route

\\n\"}}}]}}}}","{\"language\":\"en\",\"dictionary\":{\"Documentation\":\"Documentation\",\"GraphQL\":\"GraphQL\",\"Styleguide\":\"Styleguide\",\"styleguide-sample\":\"This is a dictionary entry in English as a demonstration\"},\"httpContext\":{\"request\":{\"url\":\"https://sc100xm1cm:443/?sc_itemid={cfdd7ba2-e646-5294-87fc-6fad34451a97}&sc_ee_fb=false&sc_lang=en&sc_mode=preview&sc_debug=0&sc_trace=0&sc_prof=0&sc_ri=0&sc_rb=0\",\"path\":\"/\",\"querystring\":{\"sc_itemid\":\"{cfdd7ba2-e646-5294-87fc-6fad34451a97}\",\"sc_ee_fb\":\"false\",\"sc_lang\":\"en\",\"sc_mode\":\"preview\",\"sc_debug\":\"0\",\"sc_trace\":\"0\",\"sc_prof\":\"0\",\"sc_ri\":\"0\",\"sc_rb\":\"0\"},\"userAgent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.45 Safari/537.36 Edg/84.0.522.20\"}}}"],"functionName":"renderView","moduleName":"server.bundle","jssEditingSecret":"mysecret"}"""; - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; public ExperienceEditorParsePathByItemIdFixture() { - _server = CreateTestServer(options => - { - options.Endpoint = TestConstants.EEMiddlewarePostEndpoint; - options.JssEditingSecret = TestConstants.JssEditingSecret; - }); + _factory = BuildExperienceEditorWebApplicationFactory(); } [Fact] @@ -41,7 +38,7 @@ public async Task EE_SendPathWhenItemLoadedByItemID() const string eeUrl = TestConstants.EEMiddlewarePostEndpoint; // Act - string response = await SendPost(_server, eeUrl, PreviewRequest); + string response = await SendPost(_factory, eeUrl, PreviewRequest); dynamic? json = Serializer.Deserialize(response); string? actualPath = json?.html.ToString(); @@ -56,7 +53,7 @@ public async Task EE_SendPathWhenItemLoadedByItemIDIsEmpty() const string eeUrl = TestConstants.EEMiddlewarePostEndpoint; // Act - string response = await SendPost(_server, eeUrl, PreviewRequestWithNullItemPath); + string response = await SendPost(_factory, eeUrl, PreviewRequestWithNullItemPath); dynamic? json = Serializer.Deserialize(response); string? actualPath = json?.html.ToString(); @@ -71,7 +68,7 @@ public async Task EE_SendPathWhenItemLoadedWithoutItemID() const string eeUrl = TestConstants.EEMiddlewarePostEndpoint; // Act - string response = await SendPost(_server, eeUrl, PreviewRequestWithoutItemPath); + string response = await SendPost(_factory, eeUrl, PreviewRequestWithoutItemPath); dynamic? json = Serializer.Deserialize(response); string? actualPath = json?.html.ToString(); @@ -81,14 +78,14 @@ public async Task EE_SendPathWhenItemLoadedWithoutItemID() public void Dispose() { - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } - private static async Task SendPost(TestServer server, string eeUrl, string requestBody) + private static async Task SendPost(WebApplicationFactory factory, string eeUrl, string requestBody) { // Act - HttpClient client = server.CreateClient(); + HttpClient client = factory.CreateClient(); HttpResponseMessage response = await client .PostAsync(eeUrl, new StringContent(requestBody)) .ConfigureAwait(false); @@ -96,19 +93,31 @@ private static async Task SendPost(TestServer server, string eeUrl, stri return await response.Content.ReadAsStringAsync().ConfigureAwait(false); } - private static TestServer CreateTestServer(Action eeOptions) => - new TestServerBuilder() - .ConfigureServices(builder => + private WebApplicationFactory BuildExperienceEditorWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => { - builder.AddSingleton(Substitute.For()); - builder.AddSitecoreRenderingEngine(options => - { - options.AddDefaultComponentRenderer(); - }) - .WithExperienceEditor(eeOptions); - builder.AddSingleton(); - }) - .Configure(app => + services + .AddRouting() + .AddSitecoreLayoutService(); + services.AddSingleton(Substitute.For()); + services.AddSitecoreRenderingEngine(options => + { + options.AddDefaultComponentRenderer(); + }).WithExperienceEditor(options => + { + options.Endpoint = TestConstants.EEMiddlewarePostEndpoint; + options.JssEditingSecret = TestConstants.JssEditingSecret; + }); + + services.AddControllersWithViews(); + }); + + builder.Configure(app => { app.UseSitecoreExperienceEditor(); app.UseMiddleware(); @@ -118,8 +127,9 @@ private static TestServer CreateTestServer(Action eeOpt { endpoints.MapFallbackToController("Default", "Home"); }); - }) - .BuildServer(new Uri("http://localhost")); + }); + }); + } #pragma warning disable CS9113 #pragma warning disable CA1822 diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ForwardHeaders/ForwardHeadersToLayoutServiceFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ForwardHeaders/ForwardHeadersToLayoutServiceFixture.cs index 924db9c..a9b2684 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ForwardHeaders/ForwardHeadersToLayoutServiceFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/ForwardHeaders/ForwardHeadersToLayoutServiceFixture.cs @@ -1,7 +1,7 @@ using System.Net; using AwesomeAssertions; using Microsoft.AspNetCore.HttpOverrides; -using Microsoft.AspNetCore.TestHost; +using Microsoft.AspNetCore.Mvc.Testing; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions; @@ -11,28 +11,27 @@ // ReSharper disable StringLiteralTypo namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.ForwardHeaders; -public class ForwardHeadersToLayoutServiceFixture : IDisposable +public class ForwardHeadersToLayoutServiceFixture : IClassFixture>, IDisposable { private const string TestHeaderRhResponse = "testHeaderResponseFromRenderingHost"; - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); - public ForwardHeadersToLayoutServiceFixture() - { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); + private readonly WebApplicationFactory _factory; - _ = testHostBuilder - .ConfigureServices(builder => + public ForwardHeadersToLayoutServiceFixture(TestWebApplicationFactory factory) + { + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder.Configure(options => + services.Configure(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; }); - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { @@ -40,10 +39,9 @@ public ForwardHeadersToLayoutServiceFixture() }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + services.AddSitecoreRenderingEngine(options => { - options - .AddDefaultComponentRenderer(); + options.AddDefaultComponentRenderer(); }).ForwardHeaders(options => { options.HeadersWhitelist.Add("HEADERTOCOPY"); @@ -62,14 +60,14 @@ public ForwardHeadersToLayoutServiceFixture() result.AppendValue(TestHeaderRhResponse, "testHeaderResponseValueFromRenderingHost"); }); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseForwardedHeaders(); app.UseSitecoreRenderingEngine(); }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + }); } [Fact] @@ -82,7 +80,7 @@ public async Task SitecoreLayoutServiceRequest_FiltersHeaders() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)), }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage request = BrowserWhitelistedHeaders(); request.Headers.Add("connection", string.Empty); request.Headers.Add("keep-alive", "sometestvalueshere"); @@ -118,7 +116,7 @@ public async Task SitecoreLayoutServiceRequest_FiltersHeaders_CaseSensitive() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage request = new(HttpMethod.Get, new Uri("/", UriKind.Relative)); request.Headers.Add("COOKIE", "testValue"); @@ -140,7 +138,7 @@ public async Task SitecoreLayoutServiceRequest_FiltersHeaders_NonWhitelistedHead Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage request = new(HttpMethod.Get, new Uri("/", UriKind.Relative)); request.Headers.Add("testNonWhitelistedHeader", "testNonWhitelistedHeaderValue"); @@ -161,7 +159,7 @@ public async Task SitecoreLayoutServiceRequest_FiltersHeadersNegativeCasesEmptyH Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage request = BrowserWhitelistedHeaders(); request.Headers.Add("connection", string.Empty); @@ -187,7 +185,7 @@ public async Task SitecoreResponse_Headers_CopiedToResponse_AreFilteredAndModifi _mockClientHandler.Responses.Push(responseMsg); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage request = BrowserWhitelistedHeaders(); request.Headers.Add("headerToModify", "oldHeaderValue"); request.Headers.Add("HEADERTOCOPY", "sometestvalueshere"); @@ -215,7 +213,7 @@ public async Task SitecoreResponse_Headers_CopiedToResponse_WhitelistedFilteredA _mockClientHandler.Responses.Push(responseMsg); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage request = BrowserWhitelistedHeaders(); request.Headers.Add("Cookie", ["ASP.NET_SessionId=rku2oxmotbrkwkfxe0cpfrvn; path=/; HttpOnly; SameSite=Lax", "SC_ANALYTICS_GLOBAL_COOKIE=0f82f53555ce4304a1ee8ae99ab9f9a8|False; expires = Fri, 15 - Mar - 2030 13:15:08 GMT; path =/; HttpOnly"]); @@ -231,8 +229,8 @@ public async Task SitecoreResponse_Headers_CopiedToResponse_WhitelistedFilteredA public void Dispose() { - _server.Dispose(); _mockClientHandler.Dispose(); + _factory?.Dispose(); GC.SuppressFinalize(this); } diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/GlobalMiddlewareFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/GlobalMiddlewareFixture.cs index c0c3243..820ed1d 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/GlobalMiddlewareFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/GlobalMiddlewareFixture.cs @@ -1,5 +1,7 @@ -using System.Net; +using System; +using System.Net; using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -15,7 +17,7 @@ public class GlobalMiddlewareFixture : IDisposable private const string GlobalMiddlewareController = "UsingGlobalMiddleware"; - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; private readonly MockHttpMessageHandler _mockClientHandler; @@ -23,27 +25,9 @@ public class GlobalMiddlewareFixture : IDisposable public GlobalMiddlewareFixture() { - TestServerBuilder testHostBuilder = new(); _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => - { - builder - .AddSitecoreLayoutService() - .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) - .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => - { - options.AddDefaultPartialView("_ComponentNotFound"); - options.AddPostRenderingAction(httpContext => httpContext.Response.Headers.Append(CustomHeaderName, "value")); - }); - }) - .Configure(app => - { - app.UseSitecoreRenderingEngine(); - }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + _factory = BuildGlobalMiddlewareWebApplicationFactory(); } [Fact] @@ -54,7 +38,7 @@ public async Task HttpClient_IsInvoked() StatusCode = HttpStatusCode.OK }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); await client.GetAsync(GlobalMiddlewareController); _mockClientHandler.WasInvoked.Should().BeTrue(); @@ -65,7 +49,7 @@ public async Task Controller_ReturnsCorrectContent() { _mockClientHandler.Responses.Push(new HttpResponseMessage { StatusCode = HttpStatusCode.OK }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); string response = await client.GetStringAsync(GlobalMiddlewareController); response.Should().Be("\"success\""); @@ -76,7 +60,7 @@ public async Task HttpClient_LayoutServiceUriMapped() { _mockClientHandler.Responses.Push(new HttpResponseMessage { StatusCode = HttpStatusCode.OK }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); await client.GetAsync(GlobalMiddlewareController); _mockClientHandler.Requests.Single().RequestUri!.AbsoluteUri.Should() @@ -92,7 +76,7 @@ public async Task HttpClient_MissingComponent() Content = new StringContent(Serializer.Serialize(CannedResponses.WithMissingComponent)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); string response = await client.GetStringAsync("WithRoute"); response.Should().Contain("ComponentIsMissing"); @@ -106,7 +90,7 @@ public async Task HttpClient_PostRenderingEnginActionIsExecuted() StatusCode = HttpStatusCode.OK }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpResponseMessage response = await client.GetAsync(GlobalMiddlewareController); response.Headers.Contains(CustomHeaderName).Should().BeTrue(); @@ -114,8 +98,40 @@ public async Task HttpClient_PostRenderingEnginActionIsExecuted() public void Dispose() { - _server.Dispose(); + _factory.Dispose(); _mockClientHandler.Dispose(); GC.SuppressFinalize(this); } + + private WebApplicationFactory BuildGlobalMiddlewareWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddRouting(); + services.AddControllersWithViews(); + + services + .AddSitecoreLayoutService() + .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) + .AsDefaultHandler(); + + services.AddSitecoreRenderingEngine(options => + { + options.AddDefaultPartialView("_ComponentNotFound"); + options.AddPostRenderingAction(httpContext => httpContext.Response.Headers.Append(CustomHeaderName, "value")); + }); + }); + + builder.Configure(app => + { + app.UseRouting(); + app.UseSitecoreRenderingEngine(); + app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); + }); + }); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/AdvanceLocalizationFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/AdvanceLocalizationFixture.cs index 5483406..d4a3a7c 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/AdvanceLocalizationFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/AdvanceLocalizationFixture.cs @@ -4,6 +4,7 @@ using HtmlAgilityPack; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Mvc.Razor; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -15,55 +16,14 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Loc public class AdvanceLocalizationFixture : IDisposable { - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; private readonly MockHttpMessageHandler _mockClientHandler; private readonly Uri _layoutServiceUri = new("http://layout.service"); public AdvanceLocalizationFixture() { - TestServerBuilder testHostBuilder = new(); _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => - { - builder.AddLocalization(options => options.ResourcesPath = "Resources"); - builder.AddSitecoreLayoutService() - .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) - .AsDefaultHandler(); - - builder.AddSitecoreRenderingEngine(options => - { - options.AddModelBoundView("Component-4", "Component4") - .AddDefaultComponentRenderer(); - }); - builder.AddMvc() - .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix); - }) - .Configure(app => - { - app.UseRouting(); - app.UseRequestLocalization(options => - { - List supportedCultures = [new("en"), new("da")]; - options.DefaultRequestCulture = new RequestCulture(culture: "en", uiCulture: "en"); - options.SupportedCultures = supportedCultures; - options.SupportedUICultures = supportedCultures; - options.UseSitecoreRequestLocalization(); - }); - app.UseSitecoreRenderingEngine(); - - app.UseEndpoints(endpoints => - { - // ReSharper disable once RouteTemplates.RouteParameterConstraintNotResolved - Custom constraint - endpoints.MapControllerRoute( - name: "default", - pattern: "content/{culture:culture}/{**sitecoreRoute}", - defaults: new { controller = "Home", action = "Index" }); - endpoints.MapDefaultControllerRoute(); - }); - }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + _factory = BuildAdvanceLocalizationWebApplicationFactory(); } [Fact] @@ -76,7 +36,7 @@ public async Task LocalizationRouteProvider_SetsCorrectRequestsLanguage() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act await client.GetStringAsync(new Uri("content/da/UsingGlobalMiddleware", UriKind.Relative)); @@ -94,7 +54,7 @@ public async Task LocalizedRequest_PicksDefaultView() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -118,7 +78,7 @@ public async Task LocalizedRequest_PicksLocalizedView() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("content/da", UriKind.Relative)); @@ -135,7 +95,56 @@ public async Task LocalizedRequest_PicksLocalizedView() public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } + + private WebApplicationFactory BuildAdvanceLocalizationWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddLocalization(options => options.ResourcesPath = "Resources"); + services.AddRouting(); + services.AddControllersWithViews().AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix); + + services.AddSitecoreLayoutService() + .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) + .AsDefaultHandler(); + + services.AddSitecoreRenderingEngine(options => + { + options.AddModelBoundView("Component-4", "Component4") + .AddDefaultComponentRenderer(); + }); + }); + + builder.Configure(app => + { + app.UseRouting(); + app.UseRequestLocalization(options => + { + List supportedCultures = [new("en"), new("da")]; + options.DefaultRequestCulture = new RequestCulture(culture: "en", uiCulture: "en"); + options.SupportedCultures = supportedCultures; + options.SupportedUICultures = supportedCultures; + options.UseSitecoreRequestLocalization(); + }); + app.UseSitecoreRenderingEngine(); + + app.UseEndpoints(endpoints => + { + // ReSharper disable once RouteTemplates.RouteParameterConstraintNotResolved - Custom constraint + endpoints.MapControllerRoute( + name: "default", + pattern: "content/{culture:culture}/{**sitecoreRoute}", + defaults: new { controller = "Home", action = "Index" }); + endpoints.MapDefaultControllerRoute(); + }); + }); + }); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/DefaultLocalizationFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/DefaultLocalizationFixture.cs index 19f429b..2a56532 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/DefaultLocalizationFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/DefaultLocalizationFixture.cs @@ -1,5 +1,6 @@ using System.Net; using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -12,19 +13,53 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Loc public class DefaultLocalizationFixture : IDisposable { - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; private readonly MockHttpMessageHandler _mockClientHandler; private readonly Uri _layoutServiceUri = new("http://layout.service"); public DefaultLocalizationFixture() { - TestServerBuilder testHostBuilder = new(); _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = BuildDefaultLocalizationWebApplicationFactory(); + } + + [Fact] + public async Task LocalizationRouteProvider_SetsCorrectRequestsLanguage() + { + // Arrange + _mockClientHandler.Responses.Push(new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK, + Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) + }); + + HttpClient client = _factory.CreateClient(); + + // Act + await client.GetStringAsync(new Uri("/da/UsingGlobalMiddleware", UriKind.Relative)); + + _mockClientHandler.Requests.Single().RequestUri!.AbsoluteUri.Should().Contain("sc_lang=da"); + } + + public void Dispose() + { + _mockClientHandler.Dispose(); + _factory.Dispose(); + GC.SuppressFinalize(this); + } + + private WebApplicationFactory BuildDefaultLocalizationWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => { - builder.AddLocalization(options => options.ResourcesPath = "Resources"); - builder + services.AddLocalization(options => options.ResourcesPath = "Resources"); + services.AddRouting(); + services.AddControllersWithViews(); + services .AddSitecoreLayoutService().WithDefaultRequestOptions(request => { request @@ -32,14 +67,15 @@ public DefaultLocalizationFixture() }) .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView("Component-4", "Component4") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); @@ -51,32 +87,6 @@ public DefaultLocalizationFixture() endpoints.MapDefaultControllerRoute(); }); }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); - } - - [Fact] - public async Task LocalizationRouteProvider_SetsCorrectRequestsLanguage() - { - // Arrange - _mockClientHandler.Responses.Push(new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - - HttpClient client = _server.CreateClient(); - - // Act - await client.GetStringAsync(new Uri("/da/UsingGlobalMiddleware", UriKind.Relative)); - - _mockClientHandler.Requests.Single().RequestUri!.AbsoluteUri.Should().Contain("sc_lang=da"); - } - - public void Dispose() - { - _mockClientHandler.Dispose(); - _server.Dispose(); - GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/LocalizationFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/LocalizationFixture.cs index 871719d..e3cb321 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/LocalizationFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/LocalizationFixture.cs @@ -2,6 +2,7 @@ using System.Net; using AwesomeAssertions; using Microsoft.AspNetCore.Localization; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -13,30 +14,67 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Loc public class LocalizationFixture : IDisposable { - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; private readonly MockHttpMessageHandler _mockClientHandler; private readonly Uri _layoutServiceUri = new("http://layout.service"); public LocalizationFixture() { - TestServerBuilder testHostBuilder = new(); _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = BuildLocalizationWebApplicationFactory(); + } + + [Fact] + public async Task LocalizationRouteProvider_SetsCorrectRequestsLanguage() + { + // Arrange + _mockClientHandler.Responses.Push(new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK, + Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) + }); + + HttpClient client = _factory.CreateClient(); + + // Act + await client.GetStringAsync(new Uri("/ru-RU/UsingGlobalMiddleware", UriKind.Relative)); + + _mockClientHandler.Requests.Single().RequestUri!.AbsoluteUri.Should().Contain("sc_lang=ru-RU"); + } + + public void Dispose() + { + _mockClientHandler.Dispose(); + _factory.Dispose(); + GC.SuppressFinalize(this); + } + + private WebApplicationFactory BuildLocalizationWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => { - builder.AddLocalization(options => options.ResourcesPath = "Resources"); - builder + services.AddLocalization(options => options.ResourcesPath = "Resources"); + services.AddRouting(); + services.AddControllersWithViews(); + + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView("Component-4", "Component4") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseRequestLocalization(options => @@ -56,32 +94,6 @@ public LocalizationFixture() endpoints.MapDefaultControllerRoute(); }); }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); - } - - [Fact] - public async Task LocalizationRouteProvider_SetsCorrectRequestsLanguage() - { - // Arrange - _mockClientHandler.Responses.Push(new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - - HttpClient client = _server.CreateClient(); - - // Act - await client.GetStringAsync(new Uri("/ru-RU/UsingGlobalMiddleware", UriKind.Relative)); - - _mockClientHandler.Requests.Single().RequestUri!.AbsoluteUri.Should().Contain("sc_lang=ru-RU"); - } - - public void Dispose() - { - _mockClientHandler.Dispose(); - _server.Dispose(); - GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/LocalizationUsingAttributeMiddlewareFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/LocalizationUsingAttributeMiddlewareFixture.cs index 6fc2bc6..7f1d5e7 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/LocalizationUsingAttributeMiddlewareFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Localization/LocalizationUsingAttributeMiddlewareFixture.cs @@ -3,6 +3,7 @@ using System.Net.Http.Headers; using AwesomeAssertions; using Microsoft.AspNetCore.Localization; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -14,49 +15,14 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Loc public class LocalizationUsingAttributeMiddlewareFixture : IDisposable { - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; private readonly MockHttpMessageHandler _mockClientHandler; private readonly Uri _layoutServiceUri = new("http://layout.service"); public LocalizationUsingAttributeMiddlewareFixture() { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => - { - builder.AddLocalization(options => options.ResourcesPath = "Resources"); - builder - .AddSitecoreLayoutService() - .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) - .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => - { - options - .AddModelBoundView("Component-4", "Component4") - .AddDefaultComponentRenderer(); - }); - }) - .Configure(app => - { - app.UseRouting(); - app.UseRequestLocalization(options => - { - List supportedCultures = [new("en"), new("uk-UA"), new("da-DK")]; - - options.DefaultRequestCulture = new RequestCulture(culture: "en", uiCulture: "en"); - options.SupportedCultures = supportedCultures; - options.SupportedUICultures = supportedCultures; - options.UseSitecoreRequestLocalization(); - }); - app.UseEndpoints(endpoints => - { - endpoints.MapSitecoreLocalizedRoute("Localized", "UseLocalizeWithAttribute", "UsingAttribute"); - endpoints.MapDefaultControllerRoute(); - }); - }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + _mockClientHandler = new MockHttpMessageHandler(); + _factory = BuildLocalizationUsingAttributeWebApplicationFactory(); } [Theory] @@ -72,7 +38,7 @@ public async Task LocalizationRouteProvider_SetsCorrectRequestsLanguage_FromTheR Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act await client.GetStringAsync(new Uri($"/{routeLanguage}/UsingAttribute/UseLocalizeWithAttribute", UriKind.Relative)); @@ -95,7 +61,7 @@ public async Task LocalizationRouteProvider_SetsCorrectRequestsLanguage_FromAcce Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); client.DefaultRequestHeaders.AcceptLanguage.Clear(); if (!string.IsNullOrWhiteSpace(acceptLanguageHeader)) @@ -125,7 +91,7 @@ public async Task LocalizationRouteProvider_SetsCorrectRequestsLanguage_RouteLan Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); client.DefaultRequestHeaders.AcceptLanguage.Clear(); if (!string.IsNullOrWhiteSpace(acceptLanguageHeader)) @@ -143,7 +109,53 @@ public async Task LocalizationRouteProvider_SetsCorrectRequestsLanguage_RouteLan public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } + + private WebApplicationFactory BuildLocalizationUsingAttributeWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddLocalization(options => options.ResourcesPath = "Resources"); + services.AddRouting(); + services.AddControllersWithViews(); + + services + .AddSitecoreLayoutService() + .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) + .AsDefaultHandler(); + + services.AddSitecoreRenderingEngine(options => + { + options + .AddModelBoundView("Component-4", "Component4") + .AddDefaultComponentRenderer(); + }); + }); + + builder.Configure(app => + { + app.UseRouting(); + app.UseRequestLocalization(options => + { + List supportedCultures = [new("en"), new("uk-UA"), new("da-DK")]; + + options.DefaultRequestCulture = new RequestCulture(culture: "en", uiCulture: "en"); + options.SupportedCultures = supportedCultures; + options.SupportedUICultures = supportedCultures; + options.UseSitecoreRequestLocalization(); + }); + app.UseEndpoints(endpoints => + { + endpoints.MapSitecoreLocalizedRoute("Localized", "UseLocalizeWithAttribute", "UsingAttribute"); + endpoints.MapDefaultControllerRoute(); + }); + }); + }); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Multisite/MultisiteFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Multisite/MultisiteFixture.cs index 42b36ee..2653482 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Multisite/MultisiteFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Multisite/MultisiteFixture.cs @@ -3,7 +3,7 @@ using AwesomeAssertions; using GraphQL; using GraphQL.Client.Abstractions; -using Microsoft.AspNetCore.TestHost; +using Microsoft.AspNetCore.Mvc.Testing; using NSubstitute; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -15,21 +15,43 @@ // ReSharper disable StringLiteralTypo namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Multisite; -public class MultisiteFixture : IDisposable +public class MultisiteFixture : IClassFixture>, IDisposable { private const string DefaultSiteName = "defaultSiteName"; - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); - public MultisiteFixture() + private readonly WebApplicationFactory _factory; + + public MultisiteFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder + IGraphQLClient? mockedGraphQLClient = Substitute.For(); + mockedGraphQLClient + .SendQueryAsync(Arg.Any()) + .Returns(new GraphQLResponse + { + Data = new SiteInfoCollectionResult + { + Site = new Site + { + SiteInfoCollection = new[] + { + new SiteInfo { HostName = "host1", Name = "siteForHost1" }, + new SiteInfo { HostName = "host2", Name = "siteForHost2" }, + new SiteInfo { HostName = "foo.bar", Name = "fooSite" }, + new SiteInfo { HostName = "*.test.com", Name = "wildcardSite" }, + new SiteInfo { HostName = "concrete.test.com", Name = "concrete" }, + new SiteInfo { HostName = "multiHostname1.test.com | multiHostname2.test.com ", Name = "multiHostNameTestSite" } + } + } + } + }); + + services .AddSitecoreLayoutService().WithDefaultRequestOptions(request => { request @@ -42,35 +64,16 @@ public MultisiteFixture() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - IGraphQLClient? mockedGraphQLClient = Substitute.For(); - mockedGraphQLClient.SendQueryAsync(Arg.Any()).Returns(new GraphQLResponse - { - Data = new SiteInfoCollectionResult - { - Site = new Site - { - SiteInfoCollection = - [ - new SiteInfo { HostName = "host1", Name = "siteForHost1" }, - new SiteInfo { HostName = "host2", Name = "siteForHost2" }, - new SiteInfo { HostName = "foo.bar", Name = "fooSite" }, - new SiteInfo { HostName = "*.test.com", Name = "wildcardSite" }, - new SiteInfo { HostName = "concrete.test.com", Name = "concrete" }, - new SiteInfo { HostName = "multiHostname1.test.com | multiHostname2.test.com ", Name = "multiHostNameTestSite" } - ] - } - } - }); - - builder.AddSitecoreRenderingEngine(options => + services.AddSitecoreRenderingEngine(options => { options.AddDefaultPartialView("_ComponentNotFound"); }); - builder.AddSingleton(mockedGraphQLClient); - builder.AddMultisite(); - }) - .Configure(app => + services.AddSingleton(mockedGraphQLClient); + services.AddMultisite(); + }); + + builder.Configure(app => { app.UseRouting(); app.UseMultisite(); @@ -80,12 +83,15 @@ public MultisiteFixture() endpoints.MapFallbackToController("Index", "Multisite"); }); }); + }); + // provide a default per-fixture response so startup/concurrent requests don't consume per-test responses _mockClientHandler.Responses.Push(new HttpResponseMessage { StatusCode = HttpStatusCode.OK }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + + _ = _factory.Server; } [Theory] @@ -100,7 +106,7 @@ public MultisiteFixture() public async Task Multisite_Should_Resolve_SiteName_ByHostName(string hostname, string expectedSiteName) { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); client.BaseAddress = new Uri($"http://{hostname}"); // Act @@ -116,7 +122,7 @@ public async Task Multisite_Should_Resolve_SiteName_ByHostName(string hostname, public async Task Multisite_Should_Resolve_SiteName_ByQueryParam() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); const string expectedSiteName = "siteNameFromQueryString"; // Act @@ -133,7 +139,7 @@ public async Task Multisite_Should_Resolve_SiteName_ByQueryParam() public async Task Multisite_Should_FallBacks_To_DefaultSite_If_Site_Is_NotResolved(string hostname) { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); client.BaseAddress = new Uri($"http://{hostname}"); // Act @@ -150,7 +156,7 @@ public async Task Multisite_Should_FallBacks_To_DefaultSite_If_Site_Is_NotResolv public async Task Multisite_Should_FallBacks_To_DefaultSite_If_Site_Is_NotResolved_OnSecondRequest(string hostnameFirstRequest, string hostnameSecondRequest, string resolvedFirsSite) { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage msg = new() { @@ -175,8 +181,8 @@ public async Task Multisite_Should_FallBacks_To_DefaultSite_If_Site_Is_NotResolv public void Dispose() { - _server.Dispose(); _mockClientHandler.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Pages/PagesEditingFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Pages/PagesEditingFixture.cs index 50e2ad3..d7eb16d 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Pages/PagesEditingFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Pages/PagesEditingFixture.cs @@ -1,24 +1,77 @@ using System.Net; using AwesomeAssertions; using GraphQL; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; using NSubstitute; using Sitecore.AspNetCore.SDK.GraphQL.Request; +using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; +using Sitecore.AspNetCore.SDK.Pages.Extensions; +using Sitecore.AspNetCore.SDK.Pages.Middleware; using Sitecore.AspNetCore.SDK.Pages.Request.Handlers.GraphQL; +using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions; using Sitecore.AspNetCore.SDK.TestData; using Xunit; namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Pages; -public class PagesEditingFixture(TestWebApplicationFactory factory) : IClassFixture> +public class PagesEditingFixture : IClassFixture>, IDisposable { - private readonly TestWebApplicationFactory _factory = factory; + private readonly TestWebApplicationFactory _sourceFactory; + private readonly WebApplicationFactory _factory; + + public PagesEditingFixture(TestWebApplicationFactory factory) + { + _sourceFactory = factory; + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddSitecoreLayoutService() + .AddSitecorePagesHandler() + .AddGraphQLWithContextHandler("default", TestConstants.ContextId, siteName: TestConstants.SiteName) + .AsDefaultHandler(); + + services.AddSitecoreRenderingEngine(options => + { + options.AddDefaultPartialView("_ComponentNotFound"); + }) + .WithSitecorePages(TestConstants.ContextId, options => { options.EditingSecret = TestConstants.JssEditingSecret; }); + }); + + builder.Configure(app => + { + app.UseRouting(); + app.UseMiddleware(); + app.UseEndpoints(endpoints => + { + endpoints.MapControllerRoute( + name: "default", + pattern: "{controller=Pages}/{action=Index}"); + + endpoints.MapControllerRoute( + "pages-config", + TestConstants.ConfigRoute, + new { controller = "PagesSetup", action = "Config" }); + + endpoints.MapControllerRoute( + "pages-render", + TestConstants.RenderRoute, + new { controller = "PagesSetup", action = "Render" }); + }); + }); + }); + + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; + } [Fact] public async Task EditingRequest_ValidRequest_ReturnsChromeDecoratedResponse() { // Arrange - _factory.MockGraphQLClient.SendQueryAsync(Arg.Any()).Returns(TestConstants.SimpleEditingLayoutQueryResponse); - _factory.MockGraphQLClient.SendQueryAsync(Arg.Any()).Returns(TestConstants.DictionaryResponseWithoutPaging); + _sourceFactory.MockGraphQLClient.SendQueryAsync(Arg.Any()).Returns(TestConstants.SimpleEditingLayoutQueryResponse); + _sourceFactory.MockGraphQLClient.SendQueryAsync(Arg.Any()).Returns(TestConstants.DictionaryResponseWithoutPaging); HttpClient client = _factory.CreateClient(); string url = $"/Pages/index?mode=edit&secret={TestConstants.JssEditingSecret}&sc_itemid={TestConstants.TestItemId}&sc_version=1&sc_layoutKind=final"; @@ -34,4 +87,10 @@ public async Task EditingRequest_ValidRequest_ReturnsChromeDecoratedResponse() responseBody.Should().Contain(""); responseBody.Should().Contain(""); } + + public void Dispose() + { + _factory.Dispose(); + GC.SuppressFinalize(this); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Pages/PagesSetupRoutingFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Pages/PagesSetupRoutingFixture.cs index 23c16ba..e596976 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Pages/PagesSetupRoutingFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Pages/PagesSetupRoutingFixture.cs @@ -1,13 +1,64 @@ -using System.Net; +using System.Net; using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; +using Sitecore.AspNetCore.SDK.Pages.Extensions; +using Sitecore.AspNetCore.SDK.Pages.Middleware; +using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions; using Sitecore.AspNetCore.SDK.TestData; using Xunit; namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Pages; -public class PagesSetupRoutingFixture(TestWebApplicationFactory factory) : IClassFixture> +public class PagesSetupRoutingFixture : IClassFixture>, IDisposable { - private readonly TestWebApplicationFactory _factory = factory; + private readonly WebApplicationFactory _factory; + + public PagesSetupRoutingFixture(TestWebApplicationFactory factory) + { + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddSitecoreLayoutService() + .AddSitecorePagesHandler() + .AddGraphQLWithContextHandler("default", TestConstants.ContextId, siteName: TestConstants.SiteName) + .AsDefaultHandler(); + + services.AddSitecoreRenderingEngine(options => + { + options.AddDefaultPartialView("_ComponentNotFound"); + }) + .WithSitecorePages(TestConstants.ContextId, options => { options.EditingSecret = TestConstants.JssEditingSecret; }); + }); + + builder.Configure(app => + { + app.UseRouting(); + app.UseMiddleware(); + app.UseEndpoints(endpoints => + { + endpoints.MapControllerRoute( + name: "default", + pattern: "{controller=Pages}/{action=Index}"); + + endpoints.MapControllerRoute( + "pages-config", + TestConstants.ConfigRoute, + new { controller = "PagesSetup", action = "Config" }); + + endpoints.MapControllerRoute( + "pages-render", + TestConstants.RenderRoute, + new { controller = "PagesSetup", action = "Render" }); + }); + }); + }); + + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; + } [Fact] public async Task ConfigRoute_MissingSecret_ReturnsBadRequest() @@ -128,4 +179,10 @@ public async Task RenderRoute_ValidCall_ReturnsCorrectResponse() response.Should().NotBeNull(); response.StatusCode.Should().Be(HttpStatusCode.Redirect); } + + public void Dispose() + { + _factory.Dispose(); + GC.SuppressFinalize(this); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Pages/TestPagesProgram.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Pages/TestPagesProgram.cs deleted file mode 100644 index 7b65ba8..0000000 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Pages/TestPagesProgram.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Sitecore.AspNetCore.SDK.GraphQL.Extensions; -using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; -using Sitecore.AspNetCore.SDK.Pages.Configuration; -using Sitecore.AspNetCore.SDK.Pages.Extensions; -using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions; -using Sitecore.AspNetCore.SDK.TestData; - -WebApplicationBuilder builder = WebApplication.CreateBuilder(args); - -builder.Services.AddRouting() - .AddMvc(); - -builder.Services.AddGraphQLClient(configuration => -{ - configuration.ContextId = TestConstants.ContextId; -}); - -builder.Services.AddSitecoreLayoutService() - .AddSitecorePagesHandler() - .AddGraphQLWithContextHandler("default", TestConstants.ContextId!, siteName: TestConstants.SiteName!) - .AsDefaultHandler(); - -builder.Services.AddSitecoreRenderingEngine(options => - { - options.AddDefaultPartialView("_ComponentNotFound"); - }) - .WithSitecorePages(TestConstants.ContextId, options => { options.EditingSecret = TestConstants.JssEditingSecret; }); - -WebApplication app = builder.Build(); -app.UseSitecorePages(new PagesOptions { ConfigEndpoint = TestConstants.ConfigRoute }); -app.UseRouting(); - -app.MapControllerRoute( - name: "default", - pattern: "{controller=Pages}/{action=Index}"); - -app.Run(); - -/// -/// Partial class allowing this TestProgram to be created by a WebApplicationFactory for integration testing. -/// -public partial class TestPagesProgram -{ -} \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestDefaultsConfigurationFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestDefaultsConfigurationFixture.cs index 387a745..1cd9eaa 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestDefaultsConfigurationFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestDefaultsConfigurationFixture.cs @@ -1,4 +1,5 @@ using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -14,50 +15,19 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures; public class RequestDefaultsConfigurationFixture : IDisposable { private readonly MockHttpMessageHandler _clientHandler; - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; public RequestDefaultsConfigurationFixture() { - TestServerBuilder testHostBuilder = new(); _clientHandler = new MockHttpMessageHandler(); - - testHostBuilder - .ConfigureServices(builder => - { - ISitecoreLayoutClientBuilder lsc = builder - .AddSitecoreLayoutService() - .WithDefaultRequestOptions(request => - { - request["key1"] = "value1"; - request["key2"] = "value2"; - }); - - lsc.AddHttpHandler("mock", _ => new HttpClient(_clientHandler) { BaseAddress = new Uri("http://layout.service") }) - .WithRequestOptions(request => - { - request["key1"] = "value3"; - request["key3"] = "value4"; - }) - .AsDefaultHandler(); - - lsc.AddHttpHandler("mockwithoutoptions", _ => new HttpClient(_clientHandler) { BaseAddress = new Uri("http://layout.service") }); - - builder - .AddSitecoreRenderingEngine(options => options.MapToRequest((http, sc) => { sc.Path(http.Path); })); - }) - .Configure(app => - { - app.UseSitecoreRenderingEngine(); - }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + _factory = BuildRequestDefaultsConfigurationWebApplicationFactory(); } [Fact] public async Task Request_OnlyGlobalOptionsProvided_FinalRequestUsesGlobalOptions() { // Arrange - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("test"); @@ -74,7 +44,7 @@ public async Task Request_OnlyGlobalOptionsProvided_FinalRequestUsesGlobalOption public async Task Request_OnlyHandlerOptionsProvided_FinalRequestUsesHandlerOptions() { // Arrange - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); SitecoreLayoutRequest request = []; @@ -90,7 +60,7 @@ public async Task Request_OnlyHandlerOptionsProvided_FinalRequestUsesHandlerOpti public async Task Request_OnlyRequestParameterProvided_FinalRequestUsesRequestParameter() { // Arrange - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); SitecoreLayoutRequest request = new() { @@ -109,7 +79,7 @@ public async Task Request_OnlyRequestParameterProvided_FinalRequestUsesRequestPa public async Task Request_GlobalAndHandlerOptionsProvided_FinalRequestUsesHandlerOptions() { // Arrange - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); SitecoreLayoutRequest request = []; @@ -125,7 +95,7 @@ public async Task Request_GlobalAndHandlerOptionsProvided_FinalRequestUsesHandle public async Task Request_GlobalOptionsAndRequestParametersProvided_FinalRequestUsesRequestParameters() { // Arrange - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); SitecoreLayoutRequest request = new() { { "key2", "requestvalue" } }; @@ -141,7 +111,7 @@ public async Task Request_GlobalOptionsAndRequestParametersProvided_FinalRequest public async Task Request_GlobalAndHandlerOptionsAndRequestParametersProvided_FinalRequestUsesRequestParameters() { // Arrange - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); SitecoreLayoutRequest request = new() { { "key1", "requestvalue" } }; @@ -157,7 +127,7 @@ public async Task Request_GlobalAndHandlerOptionsAndRequestParametersProvided_Fi public async Task Request_GlobalAndHandlerAndRequestSetDifferentParameters_FinalRequestUsesAllParameters() { // Arrange - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); SitecoreLayoutRequest request = new() { { "requestKey", "requestValue" } }; @@ -175,7 +145,7 @@ public async Task Request_GlobalAndHandlerAndRequestSetDifferentParameters_Final public async Task Request_GlobalOptionsProvidedRequestSetsParameterToNull_FinalRequestExcludesParameter() { // Arrange - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); SitecoreLayoutRequest request = new() { @@ -194,7 +164,7 @@ public async Task Request_GlobalOptionsProvidedRequestSetsParameterToNull_FinalR public async Task Request_HandlerOptionsProvidedRequestSetsParameterToNull_FinalRequestExcludesParameter() { // Arrange - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutClient = _factory.Services.GetRequiredService(); SitecoreLayoutRequest request = new() { @@ -212,7 +182,45 @@ public async Task Request_HandlerOptionsProvidedRequestSetsParameterToNull_Final public void Dispose() { _clientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } + + private WebApplicationFactory BuildRequestDefaultsConfigurationWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + ISitecoreLayoutClientBuilder lsc = services + .AddSitecoreLayoutService() + .WithDefaultRequestOptions(request => + { + request["key1"] = "value1"; + request["key2"] = "value2"; + }); + + lsc.AddHttpHandler("mock", _ => new HttpClient(_clientHandler) { BaseAddress = new Uri("http://layout.service") }) + .WithRequestOptions(request => + { + request["key1"] = "value3"; + request["key3"] = "value4"; + }) + .AsDefaultHandler(); + + lsc.AddHttpHandler("mockwithoutoptions", _ => new HttpClient(_clientHandler) { BaseAddress = new Uri("http://layout.service") }); + + services.AddSitecoreRenderingEngine(options => options.MapToRequest((http, sc) => { sc.Path(http.Path); })); + }); + + builder.Configure(app => + { + app.UseRouting(); + app.UseSitecoreRenderingEngine(); + app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); + }); + }); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestExtensionsFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestExtensionsFixture.cs index 1ffa0e9..c68d6ef 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestExtensionsFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestExtensionsFixture.cs @@ -1,6 +1,8 @@ using System.Net; using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; using Sitecore.AspNetCore.SDK.LayoutService.Client.Interfaces; @@ -14,26 +16,12 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures; public class RequestExtensionsFixture : IDisposable { private readonly MockHttpMessageHandler _clientHandler; - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; public RequestExtensionsFixture() { - TestServerBuilder testHostBuilder = new(); _clientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => - { - builder - .AddSitecoreLayoutService() - .AddHttpHandler("mock", _ => new HttpClient(_clientHandler) { BaseAddress = new Uri("http://layout.service") }) - .AsDefaultHandler(); - }) - .Configure(app => - { - app.UseSitecoreRenderingEngine(); - }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + _factory = BuildRequestExtensionsWebApplicationFactory(); } [Fact] @@ -44,7 +32,7 @@ public async Task Properties_WithPath_AddedToRequest() StatusCode = HttpStatusCode.OK }); - ISitecoreLayoutClient layoutService = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutService = _factory.Services.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("UsingGlobalMiddleware"); @@ -63,7 +51,7 @@ public async Task Properties_WithLanguage_AddedToRequest() StatusCode = HttpStatusCode.OK }); - ISitecoreLayoutClient layoutService = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutService = _factory.Services.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("UsingGlobalMiddleware") @@ -83,7 +71,7 @@ public async Task Properties_WithApiKey_AddedToRequest() StatusCode = HttpStatusCode.OK }); - ISitecoreLayoutClient layoutService = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutService = _factory.Services.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("UsingGlobalMiddleware") @@ -103,7 +91,7 @@ public async Task Properties_WithSiteName_AddedToRequest() StatusCode = HttpStatusCode.OK }); - ISitecoreLayoutClient layoutService = _server.Services.GetRequiredService(); + ISitecoreLayoutClient layoutService = _factory.Services.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("UsingGlobalMiddleware") @@ -118,7 +106,32 @@ public async Task Properties_WithSiteName_AddedToRequest() public void Dispose() { _clientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } + + private WebApplicationFactory BuildRequestExtensionsWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services + .AddSitecoreLayoutService() + .AddHttpHandler("mock", _ => new HttpClient(_clientHandler) { BaseAddress = new Uri("http://layout.service") }) + .AsDefaultHandler(); + + services.AddSitecoreRenderingEngine(options => options.MapToRequest((http, sc) => { sc.Path(http.Path); })); + }); + + builder.Configure(app => + { + app.UseRouting(); + app.UseSitecoreRenderingEngine(); + app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); + }); + }); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestHeadersValidationFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestHeadersValidationFixture.cs index ff45b5c..ef1e623 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestHeadersValidationFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestHeadersValidationFixture.cs @@ -1,5 +1,6 @@ -using AwesomeAssertions; -using Microsoft.AspNetCore.TestHost; +using System.Net; +using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; using Sitecore.AspNetCore.SDK.LayoutService.Client.Interfaces; @@ -10,17 +11,23 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures; -public class RequestHeadersValidationFixture : IDisposable +public class RequestHeadersValidationFixture : IClassFixture>, IDisposable { + private readonly TestWebApplicationFactory _factory; private MockHttpMessageHandler _clientHandler = new(); - private TestServer _server = null!; + private WebApplicationFactory _appFactory = null!; + + public RequestHeadersValidationFixture(TestWebApplicationFactory factory) + { + _factory = factory; + } [Fact] public async Task Request_WithNonValidatedHeaders_HeadersAreProperlyValidated() { // Arrange - ConfigureServices(["User-Agent"]); - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + _appFactory = BuildRequestHeadersWebApplicationFactory(["User-Agent"]); + ISitecoreLayoutClient layoutClient = _appFactory.Services.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("test"); @@ -41,8 +48,8 @@ public async Task Request_WithNonValidatedHeaders_HeadersAreProperlyValidated() public async Task Request_WithoutNonValidatedHeaders_ErrorThrown() { // Arrange - ConfigureServices([]); - ISitecoreLayoutClient layoutClient = _server.Services.GetRequiredService(); + _appFactory = BuildRequestHeadersWebApplicationFactory(Array.Empty()); + ISitecoreLayoutClient layoutClient = _appFactory.Services.GetRequiredService(); SitecoreLayoutRequest request = new SitecoreLayoutRequest() .Path("test"); @@ -58,24 +65,23 @@ public async Task Request_WithoutNonValidatedHeaders_ErrorThrown() public void Dispose() { _clientHandler.Dispose(); - _server.Dispose(); + _appFactory?.Dispose(); GC.SuppressFinalize(this); } - private void ConfigureServices(string[] nonValidatedHeaders) + private WebApplicationFactory BuildRequestHeadersWebApplicationFactory(string[] nonValidatedHeaders) { - TestServerBuilder testHostBuilder = new(); _clientHandler = new MockHttpMessageHandler(); Dictionary headers = new() { { "User-Agent", ["site;core"] } }; - testHostBuilder - .ConfigureServices(builder => + return _factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - ISitecoreLayoutClientBuilder lsc = builder - .AddSitecoreLayoutService(); + ISitecoreLayoutClientBuilder lsc = services.AddSitecoreLayoutService(); lsc.AddHttpHandler("mock", _ => new HttpClient(_clientHandler) { BaseAddress = new Uri("http://layout.service") }, nonValidatedHeaders) .WithRequestOptions(request => @@ -85,14 +91,13 @@ private void ConfigureServices(string[] nonValidatedHeaders) }) .AsDefaultHandler(); - builder - .AddSitecoreRenderingEngine(); - }) - .Configure(app => + services.AddSitecoreRenderingEngine(); + }); + + builder.Configure(app => { app.UseSitecoreRenderingEngine(); }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + }); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestMappingFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestMappingFixture.cs index 9162b96..4f03387 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestMappingFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/RequestMappingFixture.cs @@ -1,6 +1,8 @@ using System.Net; using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Primitives; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -21,7 +23,7 @@ public class RequestMappingFixture : IDisposable private const string QueryStringTestActionMethod = "QueryStringTest"; - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; private readonly MockHttpMessageHandler _mockClientHandler; @@ -29,51 +31,8 @@ public class RequestMappingFixture : IDisposable public RequestMappingFixture() { - TestServerBuilder testHostBuilder = new(); _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => - { - builder - .AddSitecoreLayoutService() - .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) - .MapFromRequest((layoutRequest, httpMessage) => - { - if (layoutRequest.TryGetValue("Authorization", out object? auth)) - { - httpMessage.Headers.Add("Authorization", auth!.ToString()); - } - - if (layoutRequest.TryGetValue("AspNetCookie", out object? aspnet)) - { - httpMessage.Headers.Add("Cookie", aspnet!.ToString()); - } - - httpMessage.RequestUri = layoutRequest.BuildDefaultSitecoreLayoutRequestUri(httpMessage.RequestUri!, ["param1", "param2"]); - }) - .AsDefaultHandler(); - - builder.AddSitecoreRenderingEngine(options => - options.MapToRequest((httpRequest, layoutRequest) => - { - layoutRequest.Path(httpRequest.Path); - foreach (KeyValuePair q in httpRequest.Query) - { - layoutRequest.Add(q.Key, q.Value.ToString()); - } - - layoutRequest.Add("testnullvalue", null); - - // simulate there is an authorization cookie in the HTTP request - httpRequest.Headers.Append("Authorization", TestAuthHeader); - layoutRequest.Add("Authorization", httpRequest.Headers.Authorization); - - layoutRequest.Add("AspNetCookie", TestCookie); - })); - }) - .Configure(_ => { }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + _factory = BuildRequestMappingWebApplicationFactory(); } [Fact] @@ -87,7 +46,7 @@ public async Task HttpRequest_WithValidQueryStringParams_GeneratesCorrectLayoutS StatusCode = HttpStatusCode.OK }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act await client.GetAsync(MiddlewareController + "/" + QueryStringTestActionMethod + "?" + testQueryString); @@ -108,7 +67,7 @@ public async Task HttpRequest_WithInvalidQueryStringParams_GeneratesCorrectLayou StatusCode = HttpStatusCode.OK }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act await client.GetAsync(MiddlewareController + "/" + QueryStringTestActionMethod + "?" + testQueryString); @@ -129,7 +88,7 @@ public async Task HttpRequest_WithUnencodedQueryStringParams_GeneratesCorrectLay StatusCode = HttpStatusCode.OK }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act await client.GetAsync(MiddlewareController + "/" + QueryStringTestActionMethod + "?" + testQueryString); @@ -145,7 +104,7 @@ public async Task HttpRequest_WithAuthenticationHeaders_HeadersMappedToLayoutSer // Arrange _mockClientHandler.Responses.Push(new HttpResponseMessage { StatusCode = HttpStatusCode.OK }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act await client.GetAsync(MiddlewareController + "/" + QueryStringTestActionMethod) @@ -162,7 +121,7 @@ public async Task HttpRequest_WithCookie_CookieMappedToLayoutServiceRequest() // Arrange _mockClientHandler.Responses.Push(new HttpResponseMessage { StatusCode = HttpStatusCode.OK }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act await client.GetAsync(MiddlewareController + "/" + QueryStringTestActionMethod) @@ -175,8 +134,62 @@ await client.GetAsync(MiddlewareController + "/" + QueryStringTestActionMethod) public void Dispose() { - _server.Dispose(); + _factory.Dispose(); _mockClientHandler.Dispose(); GC.SuppressFinalize(this); } + + private WebApplicationFactory BuildRequestMappingWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services + .AddSitecoreLayoutService() + .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) + .MapFromRequest((layoutRequest, httpMessage) => + { + if (layoutRequest.TryGetValue("Authorization", out object? auth)) + { + httpMessage.Headers.Add("Authorization", auth!.ToString()); + } + + if (layoutRequest.TryGetValue("AspNetCookie", out object? aspnet)) + { + httpMessage.Headers.Add("Cookie", aspnet!.ToString()); + } + + httpMessage.RequestUri = layoutRequest.BuildDefaultSitecoreLayoutRequestUri(httpMessage.RequestUri!, ["param1", "param2"]); + }) + .AsDefaultHandler(); + + services.AddSitecoreRenderingEngine(options => + options.MapToRequest((httpRequest, layoutRequest) => + { + layoutRequest.Path(httpRequest.Path); + foreach (KeyValuePair q in httpRequest.Query) + { + layoutRequest.Add(q.Key, q.Value.ToString()); + } + + layoutRequest.Add("testnullvalue", null); + + // simulate there is an authorization cookie in the HTTP request + httpRequest.Headers.Append("Authorization", TestAuthHeader); + layoutRequest.Add("Authorization", httpRequest.Headers.Authorization); + + layoutRequest.Add("AspNetCookie", TestCookie); + })); + }); + + builder.Configure(app => + { + app.UseRouting(); + app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); + }); + }); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/SearchOptimization/EdgeSitemapProxyFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/SearchOptimization/EdgeSitemapProxyFixture.cs index 9540022..4f797b6 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/SearchOptimization/EdgeSitemapProxyFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/SearchOptimization/EdgeSitemapProxyFixture.cs @@ -2,6 +2,7 @@ using AwesomeAssertions; using GraphQL; using GraphQL.Client.Abstractions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using NSubstitute; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; @@ -13,70 +14,79 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.SearchOptimization; -public class EdgeSitemapProxyFixture : IDisposable +public class EdgeSitemapProxyFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly ISitemapService _mockSitemapService = Substitute.For(); private readonly Uri _edgeSitemapUrl = new("https://xmcloud-test.com/sitemap.xml"); + private readonly WebApplicationFactory _factory; - public EdgeSitemapProxyFixture() + public EdgeSitemapProxyFixture(TestWebApplicationFactory factory) { - _mockClientHandler.Responses.Push(new HttpResponseMessage + _factory = factory.WithWebHostBuilder(builder => { - StatusCode = HttpStatusCode.OK - }); - - TestServerBuilder testHostBuilder = new(); - _ = testHostBuilder - .ConfigureServices(builder => + builder.ConfigureServices(services => { - builder.AddSingleton(_mockSitemapService); - builder.AddSingleton(_ => + services.AddSingleton(_mockSitemapService); + + services.AddSingleton(_ => { return new CustomHttpClientFactory( - () => - new HttpClient(_mockClientHandler)); + () => new HttpClient(_mockClientHandler)); }); IGraphQLClient? mockedGraphQLClient = Substitute.For(); - mockedGraphQLClient.SendQueryAsync(Arg.Any()).Returns(new GraphQLResponse - { - Data = new SiteInfoResultModel + mockedGraphQLClient + .SendQueryAsync(Arg.Any()) + .Returns(new GraphQLResponse { - Site = new Site + Data = new SiteInfoResultModel { - SiteInfo = new SiteInfo + Site = new Site { - Sitemap = - [ - _edgeSitemapUrl.ToString() - ] + SiteInfo = new SiteInfo + { + Sitemap = [_edgeSitemapUrl.ToString()] + } } } - } - }); + }); + + services.AddSingleton(mockedGraphQLClient); + services.AddEdgeSitemap(); + }); - builder.AddSingleton(mockedGraphQLClient); - builder.AddEdgeSitemap(); - }) - .Configure(app => + builder.Configure(app => { app.UseSitemap(); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // provide a default per-fixture response so concurrent/startup requests don't consume the per-test response + _mockClientHandler.Responses.Push(new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK + }); + + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] public async Task EdgeSitemap_MustBeProxied() { - // Arrange - HttpClient client = _server.CreateClient(); - HttpRequestMessage request = new(HttpMethod.Get, new Uri("/sitemap.xml", UriKind.Relative)); + // Arrange - push per-test response + _mockClientHandler.Responses.Push(new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK + }); + _mockSitemapService.GetSitemapUrl(Arg.Any(), Arg.Any()) .Returns(_edgeSitemapUrl.AbsoluteUri); + HttpClient client = _factory.CreateClient(); + HttpRequestMessage request = new(HttpMethod.Get, new Uri("/sitemap.xml", UriKind.Relative)); + // Act await client.SendAsync(request); @@ -89,8 +99,8 @@ public async Task EdgeSitemap_MustBeProxied() public void Dispose() { - _server.Dispose(); _mockClientHandler.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/SearchOptimization/SitemapProxyFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/SearchOptimization/SitemapProxyFixture.cs index 62aec98..ebb534d 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/SearchOptimization/SitemapProxyFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/SearchOptimization/SitemapProxyFixture.cs @@ -1,5 +1,6 @@ using System.Net; using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Mocks; @@ -8,45 +9,47 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.SearchOptimization; -public class SitemapProxyFixture : IDisposable +public class SitemapProxyFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _cdInstanceUri = new("http://cd"); + private readonly WebApplicationFactory _factory; - public SitemapProxyFixture() + public SitemapProxyFixture(TestWebApplicationFactory factory) { - _mockClientHandler.Responses.Push(new HttpResponseMessage + _factory = factory.WithWebHostBuilder(builder => { - StatusCode = HttpStatusCode.OK - }); + _mockClientHandler.Responses.Push(new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK + }); - TestServerBuilder testHostBuilder = new(); - _ = testHostBuilder - .ConfigureServices(builder => + builder.ConfigureServices(services => { - builder.AddSingleton(_ => + services.AddSingleton(_ => { return new CustomHttpClientFactory( - () => - new HttpClient(_mockClientHandler)); + () => new HttpClient(_mockClientHandler)); }); - builder.AddSitemap(c => c.Url = _cdInstanceUri); - }) - .Configure(app => + services.AddSitemap(c => c.Url = _cdInstanceUri); + }); + + builder.Configure(app => { app.UseSitemap(); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] public async Task SitemapRequest_MustBeProxied() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage request = new(HttpMethod.Get, new Uri("/sitemap.xml", UriKind.Relative)); // Act @@ -61,8 +64,8 @@ public async Task SitemapRequest_MustBeProxied() public void Dispose() { - _server.Dispose(); _mockClientHandler.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/SitecoreLayoutClientBuilderExtensionsFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/SitecoreLayoutClientBuilderExtensionsFixture.cs index 85fd063..b76c619 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/SitecoreLayoutClientBuilderExtensionsFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/SitecoreLayoutClientBuilderExtensionsFixture.cs @@ -1,4 +1,5 @@ using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.Options; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; @@ -13,36 +14,19 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures; public class SitecoreLayoutClientBuilderExtensionsFixture : IDisposable { private readonly MockHttpMessageHandler _messageHandler; - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; public SitecoreLayoutClientBuilderExtensionsFixture() { - TestServerBuilder testHostBuilder = new(); _messageHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => - { - ISitecoreLayoutClientBuilder lsc = builder - .AddSitecoreLayoutService(); - - lsc.AddHttpHandler("mock", _ => new HttpClient(_messageHandler) { BaseAddress = new Uri("http://layout.service") }); - - lsc.AddHttpHandler("otherMock", _ => new HttpClient(_messageHandler) { BaseAddress = new Uri("http://layout.service") }) - .AsDefaultHandler(); - }) - .Configure(app => - { - app.UseSitecoreRenderingEngine(); - }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + _factory = BuildSitecoreLayoutClientBuilderWebApplicationFactory(); } [Fact] public void DefaultHandler_SetsSitecoreLayoutServiceOptions() { // Act - IOptions layoutService = _server.Services.GetRequiredService>(); + IOptions layoutService = _factory.Services.GetRequiredService>(); // Assert layoutService.Value.DefaultHandler.Should().Be("otherMock"); @@ -51,7 +35,33 @@ public void DefaultHandler_SetsSitecoreLayoutServiceOptions() public void Dispose() { _messageHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } + + private WebApplicationFactory BuildSitecoreLayoutClientBuilderWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + ISitecoreLayoutClientBuilder lsc = services + .AddSitecoreLayoutService(); + + lsc.AddHttpHandler("mock", _ => new HttpClient(_messageHandler) { BaseAddress = new Uri("http://layout.service") }); + + lsc.AddHttpHandler("otherMock", _ => new HttpClient(_messageHandler) { BaseAddress = new Uri("http://layout.service") }) + .AsDefaultHandler(); + + services.AddSitecoreRenderingEngine(); + }); + + builder.Configure(app => + { + app.UseSitecoreRenderingEngine(); + }); + }); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/AllFieldTagHelpersFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/AllFieldTagHelpersFixture.cs index 052830a..e0bfcd8 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/AllFieldTagHelpersFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/AllFieldTagHelpersFixture.cs @@ -2,6 +2,7 @@ using System.Net; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -12,31 +13,32 @@ // ReSharper disable StringLiteralTypo namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.TagHelpers; -public class AllFieldTagHelpersFixture : IDisposable +public class AllFieldTagHelpersFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); + private readonly WebApplicationFactory _factory; - public AllFieldTagHelpersFixture() + public AllFieldTagHelpersFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView("Component-With-All-Field-Types", "ComponentWithAllFieldTypes") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -45,8 +47,10 @@ public AllFieldTagHelpersFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -59,7 +63,7 @@ public async Task ComponentWithAllFieldTypes_RendersFieldsCorrectly() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -92,7 +96,7 @@ public async Task ComponentWithAllFieldTypes_RendersFieldsCorrectly() public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/DateFieldTagHelperFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/DateFieldTagHelperFixture.cs index a3bdf8b..5e390e7 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/DateFieldTagHelperFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/DateFieldTagHelperFixture.cs @@ -2,6 +2,7 @@ using System.Net; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -11,31 +12,32 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.TagHelpers; -public class DateFieldTagHelperFixture : IDisposable +public class DateFieldTagHelperFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); + private readonly WebApplicationFactory _factory; - public DateFieldTagHelperFixture() + public DateFieldTagHelperFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView("Component-With-Dates", "ComponentWithDates") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -44,8 +46,10 @@ public DateFieldTagHelperFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -58,7 +62,7 @@ public async Task DateTagHelper_DoesNotResetOtherTagHelperOutput() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -83,7 +87,7 @@ public async Task DateTagHelper_GeneratesProperDate() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -102,7 +106,7 @@ public async Task DateTagHelper_GeneratesProperDate() public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/FileFieldTagHelperFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/FileFieldTagHelperFixture.cs index 8006ed5..64536f9 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/FileFieldTagHelperFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/FileFieldTagHelperFixture.cs @@ -1,6 +1,7 @@ using System.Net; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -10,31 +11,34 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.TagHelpers; -public class FileFieldTagHelperFixture : IDisposable +public class FileFieldTagHelperFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); + private readonly WebApplicationFactory _factory; - public FileFieldTagHelperFixture() + public FileFieldTagHelperFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView("Component-With-Files", "ComponentWithFiles") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + + services.AddControllersWithViews(); + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -43,8 +47,10 @@ public FileFieldTagHelperFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -57,7 +63,7 @@ public async Task FileTagHelper_RendersAttributeFromModel() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -107,7 +113,7 @@ public async Task FileTagHelper_RendersCustomTagsAttributes() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -168,7 +174,7 @@ public async Task FileTagHelper_OverridesModelAttributes() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -217,7 +223,7 @@ public async Task FileTagHelper_RendersInnerHtml() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -240,7 +246,7 @@ public async Task FileTagHelper_RendersInnerHtml() public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/ImageFieldTagHelperFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/ImageFieldTagHelperFixture.cs index 3b0b421..1b9961c 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/ImageFieldTagHelperFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/ImageFieldTagHelperFixture.cs @@ -1,7 +1,9 @@ using System.Net; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions; @@ -11,24 +13,24 @@ // ReSharper disable StringLiteralTypo namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.TagHelpers; -public class ImageFieldTagHelperFixture : IDisposable +public class ImageFieldTagHelperFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); + private readonly WebApplicationFactory _factory; - public ImageFieldTagHelperFixture() + public ImageFieldTagHelperFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView("Component-With-Images", "ComponentWithImages") @@ -36,8 +38,11 @@ public ImageFieldTagHelperFixture() .AddModelBoundView("Component-2", "Component2") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + + services.AddControllersWithViews(); + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -46,8 +51,10 @@ public ImageFieldTagHelperFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -60,7 +67,7 @@ public async Task ImgTagHelper_GeneratedProperImageWithCustomAttributes() Content = new StringContent(Serializer.Serialize(CannedResponses.PageWithPreview)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -84,7 +91,7 @@ public async Task ImgTagHelper_GeneratesImageTags() Content = new StringContent(Serializer.Serialize(CannedResponses.PageWithPreview)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -108,7 +115,7 @@ public async Task ImgTagHelper_GeneratedProperHtmlWithoutTagName() Content = new StringContent(Serializer.Serialize(CannedResponses.PageWithPreview)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -132,7 +139,7 @@ public async Task ImgTagHelper_GeneratesProperImageUrlIncludingImageParams() Content = new StringContent(Serializer.Serialize(CannedResponses.PageWithPreview)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -158,7 +165,7 @@ public async Task ImgTagHelper_GeneratesProperEditableImageMarkupWithCustomPrope Content = new StringContent(Serializer.Serialize(CannedResponses.EditablePage)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -179,7 +186,7 @@ public async Task ImgTagHelper_GeneratesProperEditableImageMarkupWithCustomPrope public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/LinkFieldTagHelperFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/LinkFieldTagHelperFixture.cs index 9d0b7e5..757601d 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/LinkFieldTagHelperFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/LinkFieldTagHelperFixture.cs @@ -1,6 +1,7 @@ using System.Net; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -10,31 +11,34 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.TagHelpers; -public class LinkFieldTagHelperFixture : IDisposable +public class LinkFieldTagHelperFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); + private readonly WebApplicationFactory _factory; - public LinkFieldTagHelperFixture() + public LinkFieldTagHelperFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView("Component-With-Links", "ComponentWithLinks") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + + services.AddControllersWithViews(); + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -43,8 +47,10 @@ public LinkFieldTagHelperFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -57,7 +63,7 @@ public async Task LinkTagHelper_DoesNotResetOtherTagHelperOutput() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -82,7 +88,7 @@ public async Task LinkTagHelper_GeneratesAnchorTags() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -106,7 +112,7 @@ public async Task LinkTagHelper_PrioritizeUserProvidedLinkText() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -130,7 +136,7 @@ public async Task LinkTagHelper_RenderFieldLinkTextIfNoInnerContent() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -154,7 +160,7 @@ public async Task LinkTagHelper_RendersLinkAttributes() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -188,7 +194,7 @@ public async Task LinkTagHelper_GeneratesNestedTags() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -212,7 +218,7 @@ public async Task LinkTagHelper_DoesNotTrimUserAttributes() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -236,7 +242,7 @@ public async Task LinkTagHelper_RenderFieldAuthorLinkTextInEEIfEditableTrue() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -260,7 +266,7 @@ public async Task LinkTagHelper_RenderFieldCustomLinkTextInEEIfEditableFalse() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -277,7 +283,7 @@ public async Task LinkTagHelper_RenderFieldCustomLinkTextInEEIfEditableFalse() public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/NumberFieldTagHelperFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/NumberFieldTagHelperFixture.cs index 181d140..7319b54 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/NumberFieldTagHelperFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/NumberFieldTagHelperFixture.cs @@ -2,6 +2,7 @@ using System.Net; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -11,32 +12,33 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.TagHelpers; -public class NumberFieldTagHelperFixture : IDisposable +public class NumberFieldTagHelperFixture : IClassFixture>, IDisposable { private const decimal TestValue = 1.21M; - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); - public NumberFieldTagHelperFixture() + private readonly WebApplicationFactory _factory; + + public NumberFieldTagHelperFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView("Component-With-Number", "ComponentWithNumber") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -45,8 +47,11 @@ public NumberFieldTagHelperFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // ensure host started so services are available and analyzers are happy + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -59,7 +64,7 @@ public async Task NumberTagHelper_DoesNotResetOtherTagHelperOutput() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -84,7 +89,7 @@ public async Task NumberHelper_GeneratesProperNumber() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -103,7 +108,7 @@ public async Task NumberHelper_GeneratesProperNumber() public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/PlaceholderTagHelperFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/PlaceholderTagHelperFixture.cs index 3326444..2a5be9c 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/PlaceholderTagHelperFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/PlaceholderTagHelperFixture.cs @@ -1,5 +1,6 @@ using System.Net; using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -10,32 +11,33 @@ // ReSharper disable StringLiteralTypo namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.TagHelpers; -public class PlaceholderTagHelperFixture : IDisposable +public class PlaceholderTagHelperFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); + private readonly WebApplicationFactory _factory; - public PlaceholderTagHelperFixture() + public PlaceholderTagHelperFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + + services.AddSitecoreRenderingEngine(options => { options .AddViewComponent("Component-1", "Component1") .AddModelBoundView("Component-2", "Component2") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -44,8 +46,10 @@ public PlaceholderTagHelperFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -58,7 +62,7 @@ public async Task PageInNormalMode_WithNestedPlaceholderComponent_ComponentIsRen Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -77,7 +81,7 @@ public async Task PageInEditableMode_WithComponentsAndChromes_ComponentAndChrome Content = new StringContent(Serializer.Serialize(CannedResponses.EditablePage)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -104,7 +108,7 @@ public async Task PageInHorizonEditableMode_WithComponentsAndChromes_ComponentAn Content = new StringContent(Serializer.Serialize(CannedResponses.HorizonEditablePage)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -124,7 +128,7 @@ public async Task PageInHorizonEditableMode_WithComponentsAndChromes_ComponentAn public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/RichTextFieldTagHelperFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/RichTextFieldTagHelperFixture.cs index e9e268e..7d52902 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/RichTextFieldTagHelperFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/RichTextFieldTagHelperFixture.cs @@ -2,6 +2,7 @@ using System.Text.Encodings.Web; using AwesomeAssertions; using HtmlAgilityPack; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -12,31 +13,32 @@ // ReSharper disable StringLiteralTypo namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.TagHelpers; -public class RichTextFieldTagHelperFixture : IDisposable +public class RichTextFieldTagHelperFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); + private readonly WebApplicationFactory _factory; - public RichTextFieldTagHelperFixture() + public RichTextFieldTagHelperFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView("Component-4", "Component4") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -45,8 +47,10 @@ public RichTextFieldTagHelperFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + // Accessing _factory.Server forces the TestServer to start. The variable is unused; this is intentional. + _ = _factory.Server; } [Fact] @@ -59,7 +63,7 @@ public async Task RichTextFieldTagHelper_DoesNotResetOtherTagHelperOutput() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -83,7 +87,7 @@ public async Task RichTextFieldTagHelper_RendersFieldsCorrectly() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -115,7 +119,7 @@ public async Task RichTextFieldTagHelper_RendersEditableFieldsCorrectly() Content = new StringContent(Serializer.Serialize(CannedResponses.HorizonEditablePage)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -144,7 +148,7 @@ public async Task RichTextFieldTagHelper_RendersEditableFieldsCorrectly() public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/TextFieldTagHelperFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/TextFieldTagHelperFixture.cs index 920cbfd..5eea888 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/TextFieldTagHelperFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/TagHelpers/TextFieldTagHelperFixture.cs @@ -2,7 +2,7 @@ using System.Text.Encodings.Web; using AwesomeAssertions; using HtmlAgilityPack; -using Microsoft.AspNetCore.TestHost; +using Microsoft.AspNetCore.Mvc.Testing; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions; @@ -12,31 +12,32 @@ // ReSharper disable StringLiteralTypo namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.TagHelpers; -public class TextFieldTagHelperFixture : IDisposable +public class TextFieldTagHelperFixture : IClassFixture>, IDisposable { - private readonly TestServer _server; - private readonly MockHttpMessageHandler _mockClientHandler; + private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); + private readonly WebApplicationFactory _factory; - public TextFieldTagHelperFixture() + public TextFieldTagHelperFixture(TestWebApplicationFactory factory) { - TestServerBuilder testHostBuilder = new(); - _mockClientHandler = new MockHttpMessageHandler(); - testHostBuilder - .ConfigureServices(builder => + _factory = factory.WithWebHostBuilder(builder => + { + builder.ConfigureServices(services => { - builder + services .AddSitecoreLayoutService() .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) .AsDefaultHandler(); - builder.AddSitecoreRenderingEngine(options => + + services.AddSitecoreRenderingEngine(options => { options .AddModelBoundView("Component-3", "Component3") .AddDefaultComponentRenderer(); }); - }) - .Configure(app => + }); + + builder.Configure(app => { app.UseRouting(); app.UseSitecoreRenderingEngine(); @@ -45,8 +46,9 @@ public TextFieldTagHelperFixture() endpoints.MapDefaultControllerRoute(); }); }); + }); - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + _ = _factory.Server; } [Fact] @@ -59,7 +61,7 @@ public async Task TextFieldTagHelper_RendersFieldsCorrectly() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -94,7 +96,7 @@ public async Task TextFieldTagHelper_RendersEditableFieldsCorrectly() Content = new StringContent(Serializer.Serialize(CannedResponses.HorizonEditablePage)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act string response = await client.GetStringAsync(new Uri("/", UriKind.Relative)); @@ -123,7 +125,7 @@ public async Task TextFieldTagHelper_RendersEditableFieldsCorrectly() public void Dispose() { _mockClientHandler.Dispose(); - _server.Dispose(); + _factory.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Tracking/AttributeBasedTrackingFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Tracking/AttributeBasedTrackingFixture.cs index c1e0a9b..a072be8 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Tracking/AttributeBasedTrackingFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Tracking/AttributeBasedTrackingFixture.cs @@ -1,5 +1,6 @@ using System.Net; using AwesomeAssertions; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -24,7 +25,7 @@ public class AttributeBasedTrackingFixture : IDisposable "SC_ANALYTICS_GLOBAL_COOKIE=0f82f53555ce4304a1ee8ae99ab9f9a8|False; expires = Fri, 15 - Mar - 2030 13:15:08 GMT; path =/; HttpOnly" ]; - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; private readonly MockHttpMessageHandler _mockClientHandler; @@ -34,35 +35,8 @@ public class AttributeBasedTrackingFixture : IDisposable public AttributeBasedTrackingFixture() { - TestServerBuilder testHostBuilder = new(); _mockClientHandler = new MockHttpMessageHandler(); - - _ = testHostBuilder - .ConfigureServices(builder => - { - builder - .AddSitecoreLayoutService() - .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) - { - BaseAddress = _layoutServiceUri - }) - .AsDefaultHandler(); - - builder.AddSitecoreRenderingEngine(options => - { - options - .AddDefaultComponentRenderer(); - }) - .WithTracking(); - - builder.AddSitecoreVisitorIdentification(o => o.SitecoreInstanceUri = _cmInstanceUri); - }) - .Configure(app => - { - app.UseSitecoreVisitorIdentification(); - }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + _factory = BuildAttributeBasedTrackingWebApplicationFactory(); } [Fact] @@ -80,7 +54,7 @@ public async Task SitecoreLayoutServiceResponseMetadata_ProxyCookies() } }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act HttpResponseMessage response = await client.GetAsync(new Uri("/AttributeBased", UriKind.Relative)); @@ -100,7 +74,7 @@ public async Task SitecoreLayoutServer_ProxyCookiesFromRequest() Content = new StringContent(Serializer.Serialize(CannedResponses.WithVisitorIdentificationLayoutPlaceholder)), }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage request = new(HttpMethod.Get, new Uri("/AttributeBased", UriKind.Relative)); request.Headers.Add("Cookie", ["ASP.NET_SessionId=rku2oxmotbrkwkfxe0cpfrvn; path=/; HttpOnly; SameSite=Lax", "SC_ANALYTICS_GLOBAL_COOKIE=0f82f53555ce4304a1ee8ae99ab9f9a8|False; expires = Fri, 15 - Mar - 2030 13:15:08 GMT; path =/; HttpOnly"]); @@ -124,7 +98,7 @@ public async Task SitecoreRequests_ToLayouts_MustIncludeVisitorIdentificationJs( Content = new StringContent(Serializer.Serialize(CannedResponses.WithVisitorIdentificationLayoutPlaceholder)), }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage request = new(HttpMethod.Get, new Uri("/AttributeBased", UriKind.Relative)); // Act @@ -138,8 +112,49 @@ public async Task SitecoreRequests_ToLayouts_MustIncludeVisitorIdentificationJs( public void Dispose() { - _server.Dispose(); + _factory.Dispose(); _mockClientHandler.Dispose(); GC.SuppressFinalize(this); } + + private WebApplicationFactory BuildAttributeBasedTrackingWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddRouting(); + services.AddControllersWithViews(); + services + .AddSitecoreLayoutService() + .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) + { + BaseAddress = _layoutServiceUri + }) + .AsDefaultHandler(); + + services.AddSitecoreRenderingEngine(options => + { + options + .AddDefaultComponentRenderer(); + }) + .WithTracking(); + + services.AddSitecoreVisitorIdentification(o => o.SitecoreInstanceUri = _cmInstanceUri); + }); + + builder.Configure(app => + { + app.UseRouting(); + app.UseSitecoreVisitorIdentification(); + + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + }); + }); + }); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Tracking/TrackingFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Tracking/TrackingFixture.cs index f5db9a0..cd1e1d1 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Tracking/TrackingFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Tracking/TrackingFixture.cs @@ -1,6 +1,7 @@ using System.Net; using AwesomeAssertions; using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -25,7 +26,7 @@ public class TrackingFixture : IDisposable "SC_ANALYTICS_GLOBAL_COOKIE=0f82f53555ce4304a1ee8ae99ab9f9a8|False; expires = Fri, 15 - Mar - 2030 13:15:08 GMT; path =/; HttpOnly" ]; - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; private readonly MockHttpMessageHandler _mockClientHandler; @@ -35,39 +36,8 @@ public class TrackingFixture : IDisposable public TrackingFixture() { - TestServerBuilder testHostBuilder = new(); _mockClientHandler = new MockHttpMessageHandler(); - - _ = testHostBuilder - .ConfigureServices(builder => - { - builder.Configure(options => - { - options.ForwardedHeaders = ForwardedHeaders.XForwardedFor; - }); - - builder - .AddSitecoreLayoutService() - .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) - .AsDefaultHandler(); - - builder.AddSitecoreRenderingEngine(options => - { - options - .AddDefaultComponentRenderer(); - }) - .WithTracking(); - - builder.AddSitecoreVisitorIdentification(o => o.SitecoreInstanceUri = _cmInstanceUri); - }) - .Configure(app => - { - app.UseForwardedHeaders(); - app.UseSitecoreVisitorIdentification(); - app.UseSitecoreRenderingEngine(); - }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + _factory = BuildTrackingWebApplicationFactory(); } [Fact] @@ -80,7 +50,7 @@ public async Task SitecoreResponse_WithRobotDetection_MustIncludeVisitorIdentifi Content = new StringContent(Serializer.Serialize(CannedResponses.WithVisitorIdentificationLayoutPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage request = new(HttpMethod.Get, new Uri("/", UriKind.Relative)); // Act @@ -108,7 +78,7 @@ public async Task SitecoreRenderingHostResponseMetadata_ProxyCookiesWithLSRespon } }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act HttpRequestMessage browserRequest = new(HttpMethod.Get, new Uri("/", UriKind.Relative)); @@ -134,7 +104,7 @@ public async Task SitecoreLayoutServer_ProxyCookiesFromRequest() Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage browserRequest = new(HttpMethod.Get, new Uri("/", UriKind.Relative)); browserRequest.Headers.Add("Cookie", ["ASP.NET_SessionId=rku2oxmotbrkwkfxe0cpfrvn; path=/; HttpOnly; SameSite=Lax", "SC_ANALYTICS_GLOBAL_COOKIE=0f82f53555ce4304a1ee8ae99ab9f9a8|False; expires = Fri, 15 - Mar - 2030 13:15:08 GMT; path =/; HttpOnly"]); @@ -159,7 +129,7 @@ public async Task SitecoreLayoutServiceRequest_IPAddress_MustBeResolvedCorrectly Content = new StringContent(Serializer.Serialize(CannedResponses.WithNestedPlaceholder)) }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage request = new(HttpMethod.Get, new Uri("/", UriKind.Relative)); request.Headers.Add("X-Forwarded-For", "192.168.1.0, 172.217.16.14"); @@ -187,7 +157,7 @@ public async Task SitecoreLayoutServiceResponseMetadata_ProxyCookies() } }); - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); // Act HttpResponseMessage response = await client.GetAsync(new Uri("/", UriKind.Relative)); @@ -200,8 +170,54 @@ public async Task SitecoreLayoutServiceResponseMetadata_ProxyCookies() public void Dispose() { - _server.Dispose(); + _factory.Dispose(); _mockClientHandler.Dispose(); GC.SuppressFinalize(this); } + + private WebApplicationFactory BuildTrackingWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.Configure(options => + { + options.ForwardedHeaders = ForwardedHeaders.XForwardedFor; + }); + + services.AddRouting(); + services.AddControllersWithViews(); + + services + .AddSitecoreLayoutService() + .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) + .AsDefaultHandler(); + + services.AddSitecoreRenderingEngine(options => + { + options + .AddDefaultComponentRenderer(); + }) + .WithTracking(); + + services.AddSitecoreVisitorIdentification(o => o.SitecoreInstanceUri = _cmInstanceUri); + }); + + builder.Configure(app => + { + app.UseForwardedHeaders(); + app.UseRouting(); + app.UseSitecoreVisitorIdentification(); + app.UseSitecoreRenderingEngine(); + + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + }); + }); + }); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Tracking/TrackingProxyFixture.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Tracking/TrackingProxyFixture.cs index 5715e8e..621315e 100644 --- a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Tracking/TrackingProxyFixture.cs +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/Fixtures/Tracking/TrackingProxyFixture.cs @@ -1,6 +1,7 @@ using System.Net; using AwesomeAssertions; using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Sitecore.AspNetCore.SDK.AutoFixture.Mocks; using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions; @@ -15,62 +16,22 @@ namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Tra public class TrackingProxyFixture : IDisposable { - private readonly TestServer _server; + private readonly WebApplicationFactory _factory; private readonly MockHttpMessageHandler _mockClientHandler = new(); private readonly Uri _layoutServiceUri = new("http://layout.service"); private readonly Uri _cmInstanceUri = new("http://layout.service"); public TrackingProxyFixture() { - TestServerBuilder testHostBuilder = new(); _mockClientHandler.Responses.Push(new HttpResponseMessage(HttpStatusCode.OK)); - - _ = testHostBuilder - .ConfigureServices(builder => - { - builder.Configure(options => - { - options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; - }); - - builder - .AddSitecoreLayoutService() - .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) - .AsDefaultHandler(); - - builder.AddSitecoreRenderingEngine(options => - { - options.AddDefaultComponentRenderer(); - }) - .WithTracking(); - - builder.AddSitecoreVisitorIdentification(options => - { - options.SitecoreInstanceUri = _cmInstanceUri; - }); - - builder.AddSingleton(_ => - { - return new CustomHttpClientFactory( - () => - new HttpClient(_mockClientHandler)); - }); - }) - .Configure(app => - { - app.UseForwardedHeaders(); - app.UseSitecoreVisitorIdentification(); - app.UseSitecoreRenderingEngine(); - }); - - _server = testHostBuilder.BuildServer(new Uri("http://localhost")); + _factory = BuildTrackingProxyWebApplicationFactory(); } [Fact] public async Task SitecoreRequests_ToLayouts_MustBeProxied() { // Arrange - HttpClient client = _server.CreateClient(); + HttpClient client = _factory.CreateClient(); HttpRequestMessage request = new(HttpMethod.Get, new Uri("/layouts/System/VisitorIdentification.js", UriKind.Relative)); request.Headers.Add("Cookie", ["ASP.NET_SessionId=rku2oxmotbrkwkfxe0cpfrvn; path=/; HttpOnly; SameSite=Lax", "SC_ANALYTICS_GLOBAL_COOKIE=0f82f53555ce4304a1ee8ae99ab9f9a8|False; expires = Fri, 15 - Mar - 2030 13:15:08 GMT; path =/; HttpOnly"]); request.Headers.Add("X-Forwarded-For", "172.217.16.14"); @@ -91,8 +52,62 @@ public async Task SitecoreRequests_ToLayouts_MustBeProxied() public void Dispose() { - _server.Dispose(); + _factory.Dispose(); _mockClientHandler.Dispose(); GC.SuppressFinalize(this); } + + private WebApplicationFactory BuildTrackingProxyWebApplicationFactory() + { + WebApplicationFactory factory = new TestWebApplicationFactory(); + + return factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.Configure(options => + { + options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; + }); + + services.AddRouting(); + services.AddControllersWithViews(); + + services + .AddSitecoreLayoutService() + .AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri }) + .AsDefaultHandler(); + + services.AddSitecoreRenderingEngine(options => + { + options.AddDefaultComponentRenderer(); + }) + .WithTracking(); + + services.AddSitecoreVisitorIdentification(options => + { + options.SitecoreInstanceUri = _cmInstanceUri; + }); + + services.AddSingleton(_ => + { + return new CustomHttpClientFactory( + () => new HttpClient(_mockClientHandler)); + }); + }); + + builder.Configure(app => + { + app.UseForwardedHeaders(); + app.UseRouting(); + app.UseSitecoreVisitorIdentification(); + app.UseSitecoreRenderingEngine(); + + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + }); + }); + }); + } } \ No newline at end of file diff --git a/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/TestWebApplicationProgram.cs b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/TestWebApplicationProgram.cs new file mode 100644 index 0000000..ee6d61e --- /dev/null +++ b/tests/Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests/TestWebApplicationProgram.cs @@ -0,0 +1,22 @@ +using Sitecore.AspNetCore.SDK.GraphQL.Extensions; +using Sitecore.AspNetCore.SDK.TestData; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + +builder.Services.AddRouting() + .AddMvc(); + +builder.Services.AddGraphQLClient(configuration => +{ + configuration.ContextId = TestConstants.ContextId; +}); + +WebApplication app = builder.Build(); +app.Start(); + +/// +/// Partial class allowing this TestProgram to be created by a WebApplicationFactory for integration testing. +/// +public partial class TestWebApplicationProgram +{ +} \ No newline at end of file