Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,52 +1,23 @@
using System.Net;
using AwesomeAssertions;
using Microsoft.AspNetCore.TestHost;
using Sitecore.AspNetCore.SDK.AutoFixture.Mocks;
using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions;
using Sitecore.AspNetCore.SDK.LayoutService.Client.Response;
using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions;
using Sitecore.AspNetCore.SDK.TestData;
using Xunit;

namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Binding;

public class ModelBindingFixture : IDisposable
public class ModelBindingFixture(TestWebApplicationFactory<TestModelBindingProgram> factory) : IClassFixture<TestWebApplicationFactory<TestModelBindingProgram>>
{
private readonly TestServer _server;
private readonly MockHttpMessageHandler _mockClientHandler;
private readonly Uri _layoutServiceUri = new("http://layout.service");

public ModelBindingFixture()
{
TestServerBuilder testHostBuilder = new();
_mockClientHandler = new MockHttpMessageHandler();
testHostBuilder
.ConfigureServices(builder =>
{
builder
.AddSitecoreLayoutService()
.AddHttpHandler("mock", _ => new HttpClient(_mockClientHandler) { BaseAddress = _layoutServiceUri })
.AsDefaultHandler();
builder.AddSitecoreRenderingEngine();
})
.Configure(app =>
{
app.UseSitecoreRenderingEngine();
});

_server = testHostBuilder.BuildServer(new Uri("http://localhost"));
}

[Fact]
public async Task SitecoreRouteModelBinding_ReturnsCorrectData()
{
_mockClientHandler.Responses.Push(new HttpResponseMessage
factory.MockClientHandler.Responses.Push(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
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
Expand All @@ -62,13 +33,13 @@ public async Task SitecoreRouteModelBinding_ReturnsCorrectData()
[Fact]
public async Task SitecoreContextModelBinding_ReturnsCorrectData()
{
_mockClientHandler.Responses.Push(new HttpResponseMessage
factory.MockClientHandler.Responses.Push(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
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
Expand All @@ -82,23 +53,16 @@ public async Task SitecoreContextModelBinding_ReturnsCorrectData()
[Fact]
public async Task SitecoreResponseModelBinding_ReturnsCorrectData()
{
_mockClientHandler.Responses.Push(new HttpResponseMessage
factory.MockClientHandler.Responses.Push(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
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
response.Should().Contain(TestConstants.DatabaseName);
}

public void Dispose()
{
_server.Dispose();
_mockClientHandler.Dispose();
GC.SuppressFinalize(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Microsoft.AspNetCore.Hosting;
using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions;
using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions;
using Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Interfaces;

namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Fixtures.Binding;

/// <summary>
/// Test program class for model binding scenarios.
/// </summary>
public class TestModelBindingProgram : IStandardTestProgram
{
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureServices(services =>
{
services.AddRouting()
.AddMvc();

services.AddSitecoreLayoutService()
.AddHttpHandler("mock", _ => new HttpClient() { BaseAddress = new Uri("http://layout.service") })
.AsDefaultHandler();

services.AddSitecoreRenderingEngine();
})
.Configure(app =>
{
app.UseRouting();
app.UseSitecoreRenderingEngine();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
using Sitecore.AspNetCore.SDK.Pages.Configuration;
using Sitecore.AspNetCore.SDK.Pages.Extensions;
using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions;
using Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Interfaces;
using Sitecore.AspNetCore.SDK.TestData;

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
WebApplicationBuilder builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
ContentRootPath = Directory.GetCurrentDirectory()
});

builder.Services.AddRouting()
.AddMvc();
Expand Down Expand Up @@ -39,6 +44,6 @@
/// <summary>
/// Partial class allowing this TestProgram to be created by a WebApplicationFactory for integration testing.
/// </summary>
public partial class TestPagesProgram
public partial class TestPagesProgram : IPagesTestProgram
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Interfaces;

/// <summary>
/// Marker interface to identify test programs that require Pages functionality.
/// </summary>
public interface IPagesTestProgram
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Interfaces;

/// <summary>
/// Marker interface to identify test programs that require standard Sitecore functionality without Pages.
/// </summary>
public interface IStandardTestProgram
{
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,150 @@
using GraphQL.Client.Abstractions;
using System.IO;
using GraphQL.Client.Abstractions;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using NSubstitute;
using Sitecore.AspNetCore.SDK.AutoFixture.Mocks;
using Sitecore.AspNetCore.SDK.LayoutService.Client.Configuration;
using Sitecore.AspNetCore.SDK.LayoutService.Client.Extensions;
using Sitecore.AspNetCore.SDK.LayoutService.Client.Request.Handlers;
using Sitecore.AspNetCore.SDK.LayoutService.Client.Serialization;
using Sitecore.AspNetCore.SDK.Pages.Configuration;
using Sitecore.AspNetCore.SDK.Pages.Extensions;
using Sitecore.AspNetCore.SDK.Pages.Request.Handlers.GraphQL;
using Sitecore.AspNetCore.SDK.Pages.Services;
using Sitecore.AspNetCore.SDK.RenderingEngine.Extensions;
using Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests.Interfaces;
using Sitecore.AspNetCore.SDK.TestData;

namespace Sitecore.AspNetCore.SDK.RenderingEngine.Integration.Tests
{
public class TestWebApplicationFactory<T>
: WebApplicationFactory<T>
where T : class
{
private bool IsPagesTest => typeof(IPagesTestProgram).IsAssignableFrom(typeof(T));

public IGraphQLClient MockGraphQLClient { get; set; } = Substitute.For<IGraphQLClient>();

public MockHttpMessageHandler MockClientHandler { get; set; } = new();

public Uri LayoutServiceUri { get; set; } = new("http://layout.service");

protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseContentRoot(Path.GetFullPath(Directory.GetCurrentDirectory()))
builder.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureTestServices(services =>
{
ServiceProvider serviceProvider = services.BuildServiceProvider();
ServiceDescriptor descriptor = new(typeof(IGraphQLClient), MockGraphQLClient);
services.Replace(descriptor);

// Configure mock layout service handlers
services.PostConfigure<SitecoreLayoutClientOptions>(options =>
{
options.HandlerRegistry.Clear();
options.HandlerRegistry["mock"] = serviceProvider =>
{
HttpClient client = new HttpClient(MockClientHandler) { BaseAddress = LayoutServiceUri };

var mockOptions = Substitute.For<IOptionsSnapshot<HttpLayoutRequestHandlerOptions>>();
var handlerOptions = new HttpLayoutRequestHandlerOptions();
mockOptions.Get(Arg.Any<string>()).Returns(handlerOptions);

return new HttpLayoutRequestHandler(
client,
serviceProvider.GetRequiredService<ISitecoreLayoutSerializer>(),
mockOptions,
serviceProvider.GetRequiredService<ILogger<HttpLayoutRequestHandler>>());
};

if (IsPagesTest)
{
options.HandlerRegistry["pages"] = serviceProvider =>
{
var graphQLClient = serviceProvider.GetRequiredService<IGraphQLClient>();
return new GraphQLEditingServiceHandler(
graphQLClient,
serviceProvider.GetRequiredService<ISitecoreLayoutSerializer>(),
serviceProvider.GetRequiredService<ILogger<GraphQLEditingServiceHandler>>(),
serviceProvider.GetRequiredService<IDictionaryService>());
};
options.DefaultHandler = "pages";
}
else
{
options.DefaultHandler = "mock";
}
});

if (IsPagesTest)
{
services.AddRouting()
.AddMvc();

services.AddSitecoreLayoutService()
.AddSitecorePagesHandler();

services.AddSitecoreRenderingEngine(options =>
{
options.AddDefaultPartialView("_ComponentNotFound");
})
.WithSitecorePages(TestConstants.ContextId, options => { options.EditingSecret = TestConstants.JssEditingSecret; });

// Configure PagesOptions for the middleware
services.Configure<PagesOptions>(options =>
{
options.ConfigEndpoint = TestConstants.ConfigRoute;
});
}
else
{
services.AddRouting()
.AddMvc();

services.AddSitecoreLayoutService()
.AddHttpHandler("mock", _ => new HttpClient() { BaseAddress = new Uri("http://layout.service") })
.AsDefaultHandler();

services.AddSitecoreRenderingEngine();
}
})
.Configure(app =>
{
if (IsPagesTest)
{
app.UseMiddleware<Sitecore.AspNetCore.SDK.Pages.Middleware.PagesRenderMiddleware>();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
// Map the config endpoint to PagesSetup controller
endpoints.MapControllerRoute(
name: "pagesconfig",
pattern: "api/editing/config",
defaults: new { controller = "PagesSetup", action = "Config" });

// Map the render endpoint to PagesSetup controller
endpoints.MapControllerRoute(
name: "pagesrender",
pattern: "api/editing/render",
defaults: new { controller = "PagesSetup", action = "Render" });

// Map the default route to Pages controller
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Pages}/{action=Index}");
});
}
else
{
app.UseRouting();
app.UseSitecoreRenderingEngine();
app.UseEndpoints(configure =>
{
configure.MapDefaultControllerRoute();
});
}
});
}
}
Expand Down