Skip to content

Commit

Permalink
Allow specifying no group to render a shape (#16904)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Sébastien Ros <sebastienros@gmail.com>
  • Loading branch information
MikeAlhayek and sebastienros authored Oct 18, 2024
1 parent cbffc6c commit f7c4fe3
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 125 deletions.
27 changes: 16 additions & 11 deletions src/OrchardCore/OrchardCore.DisplayManagement/Views/ShapeResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,26 @@ private async Task ApplyImplementationAsync(BuildShapeContext context, string di
// Parse group placement.
var groupId = placement.GetGroup();

// Apply group constraints from placement
if (!string.IsNullOrEmpty(groupId))
{
_groupIds = StringValues.Concat(_groupIds, groupId);
OnGroup(groupId);
}

bool hasGroupConstraints = !StringValues.IsNullOrEmpty(_groupIds);

// If no specific group is requested, use "" as it represents "any group" when applied on a shape.
// This allows to render shapes when no shape constraints are set and also on specific groups.
var requestedGroup = context.GroupId ?? string.Empty;

// If the shape's group doesn't match the currently rendered one, return.
if (!string.IsNullOrEmpty(context.GroupId) && !_groupIds.Contains(context.GroupId, StringComparer.OrdinalIgnoreCase))
if (hasGroupConstraints && !_groupIds.Contains(requestedGroup, StringComparer.OrdinalIgnoreCase))
{
return;
}

// If we try to render the shape without a group, but we require one, don't render it
if (!hasGroupConstraints && !string.IsNullOrEmpty(context.GroupId))
{
return;
}
Expand Down Expand Up @@ -312,15 +325,7 @@ public ShapeResult OnGroup(params string[] groupIds)
{
ArgumentNullException.ThrowIfNull(groupIds);

foreach (var groupId in groupIds)
{
if (string.IsNullOrEmpty(groupId))
{
continue;
}

_groupIds = StringValues.Concat(_groupIds, groupId);
}
_groupIds = StringValues.Concat(_groupIds, groupIds);

return this;
}
Expand Down
123 changes: 19 additions & 104 deletions test/OrchardCore.Tests/DisplayManagement/ShapeResultTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,26 @@
using OrchardCore.Scripting;
using OrchardCore.Tests.DisplayManagement.Stubs;
using OrchardCore.Tests.Stubs;

namespace OrchardCore.Tests.DisplayManagement;

public class ShapeResultTests
{
[Fact]
public async Task Shape_WhenCalled_ReturnShapeWhenNoGroupIsProvided()
{
var serviceProvider = GetServiceProvider(new GroupDisplayDriverStub());

var displayManager = serviceProvider.GetRequiredService<IDisplayManager<GroupModel>>();
var model = new GroupModel();

var shape = await displayManager.BuildEditorAsync(model, updater: null, isNew: false);

var testZone = shape.GetProperty<IShape>(GroupDisplayDriverStub.ZoneName);

Assert.NotNull(testZone);

var shapeModel = testZone.Items[0] as ShapeViewModel<GroupModel>;

Assert.NotNull(shapeModel);
Assert.Equal(shapeModel.Value.Value, model.Value);
}

[Fact]
public async Task Shape_WhenCalled_ReturnShapeWhenGroupIsMatched()
[Theory]
[InlineData("groupOne", "gRoUpOnE")] // case insensitive check.
[InlineData("groupOne", "groupOne")]
[InlineData("", "")]
[InlineData("", null)]
[InlineData(null, "")]
[InlineData(null, null)]
public async Task Shape_WhenCalled_ReturnShapeWhenGroupIsMatched(string groupId, string renderingGroupId)
{
var groupId = "abc";
var serviceProvider = GetServiceProvider(new GroupDisplayDriverStub(groupId));

var displayManager = serviceProvider.GetRequiredService<IDisplayManager<GroupModel>>();
var model = new GroupModel();

var shape = await displayManager.BuildEditorAsync(model, updater: null, isNew: false, groupId: groupId);
var shape = await displayManager.BuildEditorAsync(model, updater: null, isNew: false, groupId: renderingGroupId);

var testZone = shape.GetProperty<IShape>(GroupDisplayDriverStub.ZoneName);

Expand All @@ -54,91 +40,20 @@ public async Task Shape_WhenCalled_ReturnShapeWhenGroupIsMatched()
Assert.Equal(shapeModel.Value.Value, model.Value);
}

[Fact]
public async Task Shape_WhenCalled_NullGroupShouldBeTreatedAsEmptyString()
[Theory]
[InlineData("groupOne", "groupTwo")]
[InlineData("", "groupTwo")]
[InlineData(null, "groupTwo")]
[InlineData("groupOne", "")]
[InlineData("groupOne", null)]
public async Task Shape_WhenCalled_ReturnNullWhenIncorrectGroupIsSpecified(string groupId, string renderingGroupId)
{
var serviceProvider = GetServiceProvider(new GroupDisplayDriverStub(""));

var displayManager = serviceProvider.GetRequiredService<IDisplayManager<GroupModel>>();
var model = new GroupModel();

var shape = await displayManager.BuildEditorAsync(model, updater: null, isNew: false, groupId: null);

var testZone = shape.GetProperty<IShape>(GroupDisplayDriverStub.ZoneName);

Assert.NotNull(testZone);

var shapeModel = testZone.Items[0] as ShapeViewModel<GroupModel>;

Assert.NotNull(shapeModel);
Assert.Equal(shapeModel.Value.Value, model.Value);
}

[Fact]
public async Task Shape_WhenCalled_ReturnShapeWhenMatchedToAnyGroup()
{
var groupId = "abc";
var serviceProvider = GetServiceProvider(new GroupDisplayDriverStub("xyz", "test", groupId));

var displayManager = serviceProvider.GetRequiredService<IDisplayManager<GroupModel>>();
var model = new GroupModel();

var shape = await displayManager.BuildEditorAsync(model, updater: null, isNew: false, groupId: groupId);

var testZone = shape.GetProperty<IShape>(GroupDisplayDriverStub.ZoneName);

Assert.NotNull(testZone);

var shapeModel = testZone.Items[0] as ShapeViewModel<GroupModel>;

Assert.NotNull(shapeModel);
Assert.Equal(shapeModel.Value.Value, model.Value);
}

[Fact]
public async Task Shape_WhenCalled_ReturnShapeWhenMatchedToAnyGroupCaseInsensitive()
{
var serviceProvider = GetServiceProvider(new GroupDisplayDriverStub("xyz", "test"));

var displayManager = serviceProvider.GetRequiredService<IDisplayManager<GroupModel>>();
var model = new GroupModel();

var shape = await displayManager.BuildEditorAsync(model, updater: null, isNew: false, groupId: "xYz");

var testZone = shape.GetProperty<IShape>(GroupDisplayDriverStub.ZoneName);

Assert.NotNull(testZone);

var shapeModel = testZone.Items[0] as ShapeViewModel<GroupModel>;

Assert.NotNull(shapeModel);
Assert.Equal(shapeModel.Value.Value, model.Value);
}

[Fact]
public async Task Shape_WhenCalled_ReturnNullWhenIncorrectGroupIsSpecified()
{
var serviceProvider = GetServiceProvider(new GroupDisplayDriverStub("groupOne"));

var displayManager = serviceProvider.GetRequiredService<IDisplayManager<GroupModel>>();
var model = new GroupModel();

var shape = await displayManager.BuildEditorAsync(model, updater: null, isNew: false, groupId: "groupTwo");

var testZone = shape.GetProperty<IShape>(GroupDisplayDriverStub.ZoneName);

Assert.Null(testZone);
}

[Fact]
public async Task Shape_WhenCalled_ReturnNullWhenGroupDoesNotMatchExactGroup()
{
var serviceProvider = GetServiceProvider(new GroupDisplayDriverStub());
var serviceProvider = GetServiceProvider(new GroupDisplayDriverStub(groupId));

var displayManager = serviceProvider.GetRequiredService<IDisplayManager<GroupModel>>();
var model = new GroupModel();

var shape = await displayManager.BuildEditorAsync(model, updater: null, isNew: false, groupId: "groupTwo");
var shape = await displayManager.BuildEditorAsync(model, updater: null, isNew: false, groupId: renderingGroupId);

var testZone = shape.GetProperty<IShape>(GroupDisplayDriverStub.ZoneName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,14 @@ internal sealed class GroupDisplayDriverStub : DisplayDriver<GroupModel>

public GroupDisplayDriverStub(params string[] groupIds)
{
_groupIds = groupIds;
_groupIds = groupIds ?? [];
}

public override IDisplayResult Edit(GroupModel model, BuildEditorContext context)
{
var result = View("test", model)
.Location(ZoneName);

if (_groupIds != null)
{
foreach (var groupId in _groupIds)
{
result.OnGroup(groupId);
}
}
.Location(ZoneName)
.OnGroup(_groupIds);

return result;
}
Expand Down

0 comments on commit f7c4fe3

Please sign in to comment.