V14: Test new content and media list view service (#16193)
* Fix operation status msg * Cleanup * Removing unused status * Adding WithConfigurationEditor on DataEditorBuilder to be able to create new list views with custom configuration * Adding list view service tests for content and media * Adding list view service tests base * Consistency * Clean up * More cleanup --------- Co-authored-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
committed by
GitHub
parent
94b0f4d1a2
commit
c8180d508b
@@ -68,10 +68,6 @@ public abstract class ContentCollectionControllerBase<TContent, TCollectionRespo
|
||||
.WithTitle("Data type id does not belong to a collection")
|
||||
.WithDetail("The specified data type does not represent a collection")
|
||||
.Build()),
|
||||
ContentCollectionOperationStatus.DataTypeNotContentCollection => new BadRequestObjectResult(problemDetailsBuilder
|
||||
.WithTitle("Data type id does not represent the configured collection")
|
||||
.WithDetail($"The specified data type is not the configured collection for the given {type} item")
|
||||
.Build()),
|
||||
ContentCollectionOperationStatus.DataTypeNotContentProperty => new BadRequestObjectResult(problemDetailsBuilder
|
||||
.WithTitle($"Data type id is not a {type} property")
|
||||
.WithDetail($"The specified data type is not part of the {type} properties")
|
||||
|
||||
@@ -17,7 +17,7 @@ public abstract class ContentControllerBase : ManagementApiControllerBase
|
||||
.WithDetail("A notification handler prevented the content operation.")
|
||||
.Build()),
|
||||
ContentEditingOperationStatus.ContentTypeNotFound => NotFound(problemDetailsBuilder
|
||||
.WithTitle("The requested content could not be found")
|
||||
.WithTitle("The requested content type could not be found")
|
||||
.Build()),
|
||||
ContentEditingOperationStatus.ContentTypeCultureVarianceMismatch => BadRequest(problemDetailsBuilder
|
||||
.WithTitle("Content type culture variance mismatch")
|
||||
|
||||
@@ -8,7 +8,6 @@ public enum ContentCollectionOperationStatus
|
||||
ContentNotFound,
|
||||
ContentTypeNotFound,
|
||||
DataTypeNotCollection,
|
||||
DataTypeNotContentCollection,
|
||||
DataTypeNotContentProperty,
|
||||
DataTypeNotFound,
|
||||
DataTypeWithoutContentType,
|
||||
|
||||
@@ -5,7 +5,6 @@ using Umbraco.Cms.Core.Models.Membership;
|
||||
using Umbraco.Cms.Core.Persistence.Querying;
|
||||
using Umbraco.Cms.Core.Security.Authorization;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.AuthorizationStatus;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ using Umbraco.Cms.Core.Models.Membership;
|
||||
using Umbraco.Cms.Core.Persistence.Querying;
|
||||
using Umbraco.Cms.Core.Security.Authorization;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.AuthorizationStatus;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ public class DataEditorBuilder<TParent>
|
||||
private string _alias;
|
||||
private IDictionary<string, object> _defaultConfiguration;
|
||||
private string _name;
|
||||
private ConfigurationEditor? _configurationEditor;
|
||||
|
||||
public DataEditorBuilder(TParent parentBuilder)
|
||||
: base(parentBuilder)
|
||||
@@ -46,6 +47,12 @@ public class DataEditorBuilder<TParent>
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataEditorBuilder<TParent> WithConfigurationEditor(ConfigurationEditor configurationEditor)
|
||||
{
|
||||
_configurationEditor = configurationEditor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfigurationEditorBuilder<DataEditorBuilder<TParent>> AddExplicitConfigurationEditorBuilder() =>
|
||||
_explicitConfigurationEditorBuilder;
|
||||
|
||||
@@ -58,7 +65,7 @@ public class DataEditorBuilder<TParent>
|
||||
var alias = _alias ?? name.ToCamelCase();
|
||||
|
||||
var defaultConfiguration = _defaultConfiguration ?? new Dictionary<string, object>();
|
||||
var explicitConfigurationEditor = _explicitConfigurationEditorBuilder.Build();
|
||||
var explicitConfigurationEditor = _configurationEditor ?? _explicitConfigurationEditorBuilder.Build();
|
||||
var explicitValueEditor = _explicitValueEditorBuilder.Build();
|
||||
|
||||
return new DataEditor(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,53 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Membership;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Tests.Common.Testing;
|
||||
using Umbraco.Cms.Tests.Integration.Testing;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services;
|
||||
|
||||
[TestFixture]
|
||||
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
|
||||
public abstract class ContentListViewServiceTestsBase : UmbracoIntegrationTest
|
||||
{
|
||||
protected IDataTypeService DataTypeService => GetRequiredService<IDataTypeService>();
|
||||
|
||||
protected IUserGroupService UserGroupService => GetRequiredService<IUserGroupService>();
|
||||
|
||||
protected IUserService UserService => GetRequiredService<IUserService>();
|
||||
|
||||
protected async Task<IUser> GetSuperUser()
|
||||
=> await UserService.GetAsync(Constants.Security.SuperUserKey);
|
||||
|
||||
protected async Task AssertListViewConfiguration(ListViewConfiguration actualConfiguration, Guid expectedListViewDataTypeKey)
|
||||
{
|
||||
var actualCollectionPropertyAliases = actualConfiguration
|
||||
.IncludeProperties
|
||||
.Select(p => p.Alias)
|
||||
.WhereNotNull()
|
||||
.ToArray();
|
||||
|
||||
// The configured list view
|
||||
var expectedContentListViewConfig = await GetListViewConfigurationFromListViewDataType(expectedListViewDataTypeKey);
|
||||
var expectedCollectionPropertyAliases = expectedContentListViewConfig
|
||||
.IncludeProperties
|
||||
.Select(p => p.Alias)
|
||||
.WhereNotNull()
|
||||
.ToArray();
|
||||
|
||||
Assert.AreEqual(expectedCollectionPropertyAliases.Length, actualCollectionPropertyAliases.Length);
|
||||
Assert.IsTrue(expectedCollectionPropertyAliases.SequenceEqual(actualCollectionPropertyAliases));
|
||||
}
|
||||
|
||||
private async Task<ListViewConfiguration> GetListViewConfigurationFromListViewDataType(Guid dataTypeKey)
|
||||
{
|
||||
IDataType? dataType = await DataTypeService.GetAsync(dataTypeKey);
|
||||
var listViewConfiguration = dataType.ConfigurationObject;
|
||||
Assert.IsTrue(listViewConfiguration is ListViewConfiguration);
|
||||
|
||||
return listViewConfiguration as ListViewConfiguration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.ContentEditing;
|
||||
using Umbraco.Cms.Core.Models.Membership;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
using Umbraco.Cms.Tests.Common.Builders;
|
||||
using Umbraco.Cms.Tests.Common.Builders.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the media list view service. Please notice that a lot of functional test is covered by the content list
|
||||
/// view service tests, since these services share the same base implementation.
|
||||
/// </summary>
|
||||
public class MediaListViewServiceTests : ContentListViewServiceTestsBase
|
||||
{
|
||||
private IMediaListViewService MediaListViewService => GetRequiredService<IMediaListViewService>();
|
||||
|
||||
private IMediaTypeService MediaTypeService => GetRequiredService<IMediaTypeService>();
|
||||
|
||||
private IMediaService MediaService => GetRequiredService<IMediaService>();
|
||||
|
||||
private IMediaEditingService MediaEditingService => GetRequiredService<IMediaEditingService>();
|
||||
|
||||
private IUser SuperUser { get; set; }
|
||||
|
||||
[SetUp]
|
||||
public async Task Setup()
|
||||
=> SuperUser = await GetSuperUser();
|
||||
|
||||
[Test]
|
||||
public async Task Can_Get_List_View_Items_At_Root()
|
||||
{
|
||||
// Arrange
|
||||
CreateTenMediaItemsFromTwoMediaTypesAtRoot();
|
||||
var descendants = MediaService.GetPagedDescendants(Constants.System.Root, 0, int.MaxValue, out _);
|
||||
|
||||
// Act
|
||||
var result = await MediaListViewService.GetListViewItemsByKeyAsync(
|
||||
SuperUser,
|
||||
null,
|
||||
null,
|
||||
"updateDate",
|
||||
Direction.Ascending,
|
||||
null,
|
||||
0,
|
||||
10);
|
||||
|
||||
// Assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentCollectionOperationStatus.Success, result.Status);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
PagedModel<IMedia> collectionItemsResult = result.Result.Items;
|
||||
|
||||
Assert.AreEqual(10, collectionItemsResult.Total);
|
||||
CollectionAssert.AreEquivalent(descendants, collectionItemsResult.Items);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Get_Items_With_Default_List_View_Configuration()
|
||||
{
|
||||
// Arrange
|
||||
CreateTenMediaItemsFromTwoMediaTypesAtRoot();
|
||||
|
||||
// Act
|
||||
var result = await MediaListViewService.GetListViewItemsByKeyAsync(
|
||||
SuperUser,
|
||||
null,
|
||||
null,
|
||||
"updateDate",
|
||||
Direction.Ascending,
|
||||
null,
|
||||
0,
|
||||
10);
|
||||
|
||||
// Assert
|
||||
Assert.Multiple(async () =>
|
||||
{
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentCollectionOperationStatus.Success, result.Status);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
await AssertListViewConfiguration(result.Result.ListViewConfiguration, Constants.DataTypes.Guids.ListViewMediaGuid);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Get_List_View_Items_By_Key()
|
||||
{
|
||||
// Arrange
|
||||
var root = await CreateRootMediaWithFiveChildrenAsListViewItems();
|
||||
var descendants = MediaService.GetPagedDescendants(root.Id, 0, int.MaxValue, out _);
|
||||
|
||||
// Act
|
||||
var result = await MediaListViewService.GetListViewItemsByKeyAsync(
|
||||
SuperUser,
|
||||
root.Key,
|
||||
null,
|
||||
"updateDate",
|
||||
Direction.Ascending,
|
||||
null,
|
||||
0,
|
||||
10);
|
||||
|
||||
// Assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
// Assert the content type is configured as list view
|
||||
Assert.IsNotNull(root.ContentType.ListView);
|
||||
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentCollectionOperationStatus.Success, result.Status);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
PagedModel<IMedia> collectionItemsResult = result.Result.Items;
|
||||
|
||||
Assert.AreEqual(5, collectionItemsResult.Total);
|
||||
CollectionAssert.AreEquivalent(descendants, collectionItemsResult.Items);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Only_Get_List_View_Items_That_The_User_Has_Access_To()
|
||||
{
|
||||
// Arrange
|
||||
// Media item that the user doesn't have access to
|
||||
var imageMediaType = MediaTypeService.Get(Constants.Conventions.MediaTypes.Image);
|
||||
var image = MediaBuilder.CreateMediaImage(imageMediaType, -1);
|
||||
MediaService.Save(image);
|
||||
|
||||
// Media item that serves as a start node
|
||||
var album = await CreateRootMediaWithFiveChildrenAsListViewItems();
|
||||
|
||||
MediaService.GetPagedChildren(Constants.System.Root, 0, int.MaxValue, out var totalChildren);
|
||||
|
||||
// New user and user group
|
||||
var userGroup = new UserGroupBuilder()
|
||||
.WithAlias("test")
|
||||
.WithName("Test")
|
||||
.WithAllowedSections(new[] { "packages" })
|
||||
.WithStartMediaId(album.Id)
|
||||
.Build();
|
||||
var userGroupCreateResult = await UserGroupService.CreateAsync(userGroup, Constants.Security.SuperUserKey);
|
||||
|
||||
var userCreateModel = new UserCreateModel
|
||||
{
|
||||
UserName = "testUser@mail.com",
|
||||
Email = "testUser@mail.com",
|
||||
Name = "Test user",
|
||||
UserGroupKeys = new HashSet<Guid> { userGroupCreateResult.Result.Key },
|
||||
};
|
||||
|
||||
var userCreateResult =
|
||||
await UserService.CreateAsync(Constants.Security.SuperUserKey, userCreateModel, true);
|
||||
|
||||
// Act
|
||||
var result = await MediaListViewService.GetListViewItemsByKeyAsync(
|
||||
userCreateResult.Result.CreatedUser,
|
||||
null,
|
||||
null,
|
||||
"updateDate",
|
||||
Direction.Ascending,
|
||||
null,
|
||||
0,
|
||||
10);
|
||||
|
||||
// Assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentCollectionOperationStatus.Success, result.Status);
|
||||
Assert.IsNotNull(result.Result);
|
||||
Assert.AreEqual(2, totalChildren);
|
||||
|
||||
Assert.AreEqual(1, result.Result.Items.Items.Count());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void CreateTenMediaItemsFromTwoMediaTypesAtRoot()
|
||||
{
|
||||
var mediaType1 = MediaTypeBuilder.CreateImageMediaType("Image2");
|
||||
MediaTypeService.Save(mediaType1);
|
||||
var mediaType2 = MediaTypeBuilder.CreateImageMediaType("Image3");
|
||||
MediaTypeService.Save(mediaType2);
|
||||
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
var m1 = MediaBuilder.CreateMediaImage(mediaType1, -1);
|
||||
MediaService.Save(m1);
|
||||
var m2 = MediaBuilder.CreateMediaImage(mediaType2, -1);
|
||||
MediaService.Save(m2);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<IMedia> CreateRootMediaWithFiveChildrenAsListViewItems(Guid? listViewDataTypeKey = null)
|
||||
{
|
||||
var childImageMediaType = MediaTypeService.Get(Constants.Conventions.MediaTypes.Image);
|
||||
|
||||
var mediaTypeWithListView = new MediaTypeBuilder()
|
||||
.WithAlias("album")
|
||||
.WithName("Album")
|
||||
.WithIsContainer(listViewDataTypeKey ?? Constants.DataTypes.Guids.ListViewMediaGuid)
|
||||
.Build();
|
||||
|
||||
mediaTypeWithListView.AllowedAsRoot = true;
|
||||
mediaTypeWithListView.AllowedContentTypes = new[]
|
||||
{
|
||||
new ContentTypeSort(childImageMediaType.Key, 1, childImageMediaType.Alias),
|
||||
};
|
||||
MediaTypeService.Save(mediaTypeWithListView);
|
||||
|
||||
var rootContentCreateModel = new MediaCreateModel
|
||||
{
|
||||
ContentTypeKey = mediaTypeWithListView.Key,
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantName = "Album",
|
||||
};
|
||||
|
||||
var result = await MediaEditingService.CreateAsync(rootContentCreateModel, Constants.Security.SuperUserKey);
|
||||
var root = result.Result.Content;
|
||||
|
||||
for (var i = 1; i < 6; i++)
|
||||
{
|
||||
var createModel = new MediaCreateModel
|
||||
{
|
||||
ContentTypeKey = childImageMediaType.Key,
|
||||
ParentKey = root.Key,
|
||||
InvariantName = $"Image {i}",
|
||||
Key = i.ToGuid(),
|
||||
};
|
||||
|
||||
await MediaEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user