Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying no group to render a shape #16904

Merged
merged 3 commits into from
Oct 18, 2024
Merged
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
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