Content and media type CRUD controllers and services (#14665)
* Add GetAsync method * Fix up delete document type controller * Add scope to delete async * Add some scaffolding * Add create model * Start working on validation * Move validation to its own service * Use GetAllAsync instead of GetAsync * Add initial composition support Still need to figure out some kinks * Validate compositions when creating * Add initial folder support * Initial handling of generic properties * Add operation status responses * Move create operation into service * Add first test * Fix issued shown by test * Ensure a specific key can be specified when creating * Rename container id to container key Let's try and be consistent * Create basic composition test * Ensure new property groups are created with the correct key * Add test showing property type issue * Fix property types not using the expected key. * Validate against model fetched from content type service Just to make sure nothing explodes on the round trip * Make helper for creating create models * Add helper for creating container * Make helper methods simpler to use * Add test for compositions using compositions * Add more composition tests * Fix bug allowing element types to be composed by non element types * Remove validators This can just be a part of the editing service * Minor cleanup * Ensure that multiple levels of inheritance is possible * Ensure doctype cannot be used as both composition and inheritance on the same doctype * Ensure no duplicate aliases from composition and that compositions exists * Minor cleanup * Address todos * Add SaveAsync method * Renamed some models * Rename from DocumentType to ContentType * Clarify ParentKey as being container only + untangle things a tiny bit * Clean out another TODO (less duplicate code) + more tests * Refactor for reuse across different content types + add media type editing service + unit tests * Refactor in preparation for update handling * More tests + fixed bugs found while testing * Simplify things a bit * Content type update + a lot of unit tests + some refactor + fix bugs found while testing * Begin building presentation factories for mapping view models to editing models * Use async save * Mapping factories and some clean-up * Rename Key to Id (ParentKey to ParentId) * Fix slight typo * Use editing service in document type controllers and introduce media type controllers * Validate containers and align container aliases with the current backoffice * Remove ParentId from response * Fix scope handling in DeleteAsync * Refactor ContentTypeSort * A little renaming for clarity + safeguard against changes to inheritance * Persist allowed content types * Fix bad merge + update controller response annotations * Update OpenAPI JSON * Update src/Umbraco.Cms.Api.Management/Controllers/DocumentType/DocumentTypeControllerBase.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Fix review comments * Update usage of MapCreateAsync to ValidateAndMapForCreationAsync --------- Co-authored-by: Nikolaj <nikolajlauridsen@protonmail.ch>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,805 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.ContentTypeEditing;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services;
|
||||
|
||||
public partial class ContentTypeEditingServiceTests
|
||||
{
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public async Task Can_Update_All_Basic_Settings(bool isElement)
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test", isElement: isElement);
|
||||
createModel.Description = "This is the Test description";
|
||||
createModel.Icon = "icon icon-something";
|
||||
createModel.AllowedAsRoot = true;
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test updated", "testUpdated", isElement: isElement);
|
||||
updateModel.Description = "This is the Test description updated";
|
||||
updateModel.Icon = "icon icon-something-updated";
|
||||
updateModel.AllowedAsRoot = false;
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
contentType = await ContentTypeService.GetAsync(result.Result!.Key);
|
||||
Assert.IsNotNull(contentType);
|
||||
|
||||
Assert.AreEqual(isElement, contentType.IsElement);
|
||||
Assert.AreEqual("testUpdated", contentType.Alias);
|
||||
Assert.AreEqual("Test updated", contentType.Name);
|
||||
Assert.AreEqual(result.Result.Id, contentType.Id);
|
||||
Assert.AreEqual(result.Result.Key, contentType.Key);
|
||||
Assert.AreEqual("This is the Test description updated", contentType.Description);
|
||||
Assert.AreEqual("icon icon-something-updated", contentType.Icon);
|
||||
Assert.IsFalse(contentType.AllowedAsRoot);
|
||||
}
|
||||
|
||||
[TestCase(false, false)]
|
||||
[TestCase(true, false)]
|
||||
[TestCase(false, true)]
|
||||
[TestCase(true, true)]
|
||||
public async Task Can_Update_Variation(bool variesByCulture, bool variesBySegment)
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
createModel.VariesByCulture = variesByCulture;
|
||||
createModel.VariesBySegment = variesBySegment;
|
||||
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test");
|
||||
updateModel.VariesByCulture = !variesByCulture;
|
||||
updateModel.VariesBySegment = !variesBySegment;
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
contentType = await ContentTypeService.GetAsync(result.Result!.Key);
|
||||
Assert.IsNotNull(contentType);
|
||||
|
||||
Assert.AreEqual(!variesByCulture, contentType.VariesByCulture());
|
||||
Assert.AreEqual(!variesBySegment, contentType.VariesBySegment());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Add_Allowed_Types()
|
||||
{
|
||||
var allowedOne = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result!;
|
||||
var allowedTwo = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
createModel.AllowedContentTypes = new[]
|
||||
{
|
||||
new ContentTypeSort(allowedOne.Key, 10, allowedOne.Alias),
|
||||
};
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test");
|
||||
updateModel.AllowedContentTypes = new[]
|
||||
{
|
||||
new ContentTypeSort(allowedOne.Key, 10, allowedOne.Alias),
|
||||
new ContentTypeSort(allowedTwo.Key, 20, allowedTwo.Alias),
|
||||
};
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
contentType = await ContentTypeService.GetAsync(result.Result.Key);
|
||||
Assert.IsNotNull(contentType);
|
||||
|
||||
var allowedContentTypes = contentType.AllowedContentTypes?.ToArray();
|
||||
Assert.IsNotNull(allowedContentTypes);
|
||||
Assert.AreEqual(2, allowedContentTypes.Length);
|
||||
Assert.IsTrue(allowedContentTypes.Any(c => c.Key == allowedOne.Key && c.SortOrder == 0 && c.Alias == allowedOne.Alias));
|
||||
Assert.IsTrue(allowedContentTypes.Any(c => c.Key == allowedTwo.Key && c.SortOrder == 1 && c.Alias == allowedTwo.Alias));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Remove_Allowed_Types()
|
||||
{
|
||||
var allowedOne = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result!;
|
||||
var allowedTwo = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
createModel.AllowedContentTypes = new[]
|
||||
{
|
||||
new ContentTypeSort(allowedOne.Key, 10, allowedOne.Alias),
|
||||
new ContentTypeSort(allowedTwo.Key, 20, allowedTwo.Alias),
|
||||
};
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test");
|
||||
updateModel.AllowedContentTypes = Array.Empty<ContentTypeSort>();
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
contentType = await ContentTypeService.GetAsync(result.Result.Key);
|
||||
Assert.IsNotNull(contentType);
|
||||
|
||||
var allowedContentTypes = contentType.AllowedContentTypes?.ToArray();
|
||||
Assert.IsNotNull(allowedContentTypes);
|
||||
Assert.AreEqual(0, allowedContentTypes.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Rearrange_Allowed_Types()
|
||||
{
|
||||
var allowedOne = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result!;
|
||||
var allowedTwo = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
createModel.AllowedContentTypes = new[]
|
||||
{
|
||||
new ContentTypeSort(allowedOne.Key, 0, allowedOne.Alias),
|
||||
new ContentTypeSort(allowedTwo.Key, 1, allowedTwo.Alias),
|
||||
};
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test");
|
||||
updateModel.AllowedContentTypes = new[]
|
||||
{
|
||||
new ContentTypeSort(allowedOne.Key, 1, allowedOne.Alias),
|
||||
new ContentTypeSort(allowedTwo.Key, 0, allowedTwo.Alias),
|
||||
};
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
contentType = await ContentTypeService.GetAsync(result.Result.Key);
|
||||
Assert.IsNotNull(contentType);
|
||||
|
||||
var allowedContentTypes = contentType.AllowedContentTypes?.ToArray();
|
||||
Assert.IsNotNull(allowedContentTypes);
|
||||
Assert.AreEqual(2, allowedContentTypes.Length);
|
||||
Assert.IsTrue(allowedContentTypes.Any(c => c.Key == allowedOne.Key && c.SortOrder == 1 && c.Alias == allowedOne.Alias));
|
||||
Assert.IsTrue(allowedContentTypes.Any(c => c.Key == allowedTwo.Key && c.SortOrder == 0 && c.Alias == allowedTwo.Alias));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Add_Self_To_Allowed_Types()
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
var id = contentType.Id;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test");
|
||||
updateModel.AllowedContentTypes = new[]
|
||||
{
|
||||
new ContentTypeSort(contentType.Key, 0, contentType.Alias)
|
||||
};
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
contentType = await ContentTypeService.GetAsync(result.Result.Key);
|
||||
Assert.IsNotNull(contentType);
|
||||
|
||||
var allowedContentTypes = contentType.AllowedContentTypes?.ToArray();
|
||||
Assert.IsNotNull(allowedContentTypes);
|
||||
Assert.AreEqual(1, allowedContentTypes.Length);
|
||||
Assert.IsTrue(allowedContentTypes.Any(c => c.Key == contentType.Key && c.SortOrder == 0 && c.Alias == contentType.Alias));
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public async Task Can_Add_Properties(bool isElement)
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test", isElement: isElement);
|
||||
var container = CreateContainer();
|
||||
createModel.Containers = new[] { container };
|
||||
|
||||
var propertyType = CreatePropertyType("Test Property", "testProperty", containerKey: container.Key);
|
||||
createModel.Properties = new[] { propertyType };
|
||||
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test", isElement: isElement);
|
||||
updateModel.Containers = new[] { container };
|
||||
var newPropertyType = CreatePropertyType("Test Property 2", "testProperty2", containerKey: container.Key);
|
||||
newPropertyType.SortOrder = 0;
|
||||
propertyType.SortOrder = 1;
|
||||
updateModel.Properties = new[] { propertyType, newPropertyType };
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
contentType = await ContentTypeService.GetAsync(result.Result!.Key);
|
||||
|
||||
Assert.IsNotNull(contentType);
|
||||
Assert.AreEqual(isElement, contentType.IsElement);
|
||||
Assert.AreEqual(1, contentType.PropertyGroups.Count);
|
||||
Assert.AreEqual(2, contentType.PropertyTypes.Count());
|
||||
Assert.AreEqual(2, contentType.PropertyGroups.First().PropertyTypes!.Count);
|
||||
|
||||
var allPropertyTypes = contentType.PropertyTypes.OrderBy(p => p.SortOrder).ToArray();
|
||||
Assert.AreEqual("testProperty2", allPropertyTypes.First().Alias);
|
||||
Assert.AreEqual("testProperty", allPropertyTypes.Last().Alias);
|
||||
|
||||
var propertyTypesInContainer = contentType.PropertyGroups.First().PropertyTypes!.OrderBy(p => p.SortOrder).ToArray();
|
||||
Assert.AreEqual("testProperty2", propertyTypesInContainer.First().Alias);
|
||||
Assert.AreEqual("testProperty", propertyTypesInContainer.Last().Alias);
|
||||
|
||||
Assert.IsEmpty(contentType.NoGroupPropertyTypes);
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public async Task Can_Remove_Properties(bool isElement)
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test", isElement: isElement);
|
||||
var container = CreateContainer();
|
||||
createModel.Containers = new[] { container };
|
||||
|
||||
var propertyType = CreatePropertyType("Test Property", "testProperty", containerKey: container.Key);
|
||||
createModel.Properties = new[] { propertyType };
|
||||
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test", isElement: isElement);
|
||||
updateModel.Containers = new[] { container };
|
||||
updateModel.Properties = Array.Empty<ContentTypePropertyTypeModel>();
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
contentType = await ContentTypeService.GetAsync(result.Result!.Key);
|
||||
|
||||
Assert.IsNotNull(contentType);
|
||||
Assert.AreEqual(isElement, contentType.IsElement);
|
||||
Assert.AreEqual(0, contentType.PropertyGroups.Count);
|
||||
Assert.AreEqual(0, contentType.PropertyTypes.Count());
|
||||
|
||||
Assert.AreEqual(0, contentType.NoGroupPropertyTypes.Count());
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public async Task Can_Edit_Properties(bool isElement)
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test", isElement: isElement);
|
||||
var propertyType = CreatePropertyType("Test Property", "testProperty");
|
||||
propertyType.Description = "The description";
|
||||
createModel.Properties = new[] { propertyType };
|
||||
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
var originalPropertyTypeKey = contentType.PropertyTypes.First().Key;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test", isElement: isElement);
|
||||
propertyType = CreatePropertyType("Test Property 2", "testProperty", key: originalPropertyTypeKey);
|
||||
propertyType.Description = "The updated description";
|
||||
updateModel.Properties = new[] { propertyType };
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
contentType = await ContentTypeService.GetAsync(result.Result!.Key);
|
||||
|
||||
Assert.IsNotNull(contentType);
|
||||
Assert.AreEqual(isElement, contentType.IsElement);
|
||||
Assert.AreEqual(0, contentType.PropertyGroups.Count);
|
||||
Assert.AreEqual(1, contentType.PropertyTypes.Count());
|
||||
|
||||
var property = contentType.PropertyTypes.First();
|
||||
Assert.AreEqual("Test Property 2", property.Name);
|
||||
Assert.AreEqual("testProperty", property.Alias);
|
||||
Assert.AreEqual("The updated description", property.Description);
|
||||
Assert.AreEqual(originalPropertyTypeKey, property.Key);
|
||||
|
||||
Assert.AreEqual(1, contentType.NoGroupPropertyTypes.Count());
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public async Task Can_Move_Properties_To_Another_Container(bool isElement)
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test", isElement: isElement);
|
||||
var container1 = CreateContainer("One");
|
||||
createModel.Containers = new[] { container1 };
|
||||
|
||||
var propertyType1 = CreatePropertyType("Test Property 1", "testProperty1", containerKey: container1.Key);
|
||||
var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2", containerKey: container1.Key);
|
||||
createModel.Properties = new[] { propertyType1, propertyType2 };
|
||||
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test", isElement: isElement);
|
||||
var container2 = CreateContainer("Two");
|
||||
container2.SortOrder = 0;
|
||||
container1.SortOrder = 1;
|
||||
updateModel.Containers = new[] { container1, container2 };
|
||||
propertyType2.ContainerKey = container2.Key;
|
||||
updateModel.Properties = new[] { propertyType1, propertyType2 };
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
contentType = await ContentTypeService.GetAsync(result.Result!.Key);
|
||||
|
||||
Assert.IsNotNull(contentType);
|
||||
Assert.AreEqual(isElement, contentType.IsElement);
|
||||
Assert.AreEqual(2, contentType.PropertyGroups.Count);
|
||||
Assert.AreEqual(2, contentType.PropertyTypes.Count());
|
||||
Assert.AreEqual(1, contentType.PropertyGroups.First().PropertyTypes!.Count);
|
||||
Assert.AreEqual(1, contentType.PropertyGroups.Last().PropertyTypes!.Count);
|
||||
Assert.IsEmpty(contentType.NoGroupPropertyTypes);
|
||||
|
||||
var sortedPropertyGroups = contentType.PropertyGroups.OrderBy(g => g.SortOrder).ToArray();
|
||||
Assert.AreEqual("testProperty2", sortedPropertyGroups.First().PropertyTypes!.Single().Alias);
|
||||
Assert.AreEqual("testProperty1", sortedPropertyGroups.Last().PropertyTypes!.Single().Alias);
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public async Task Can_Rearrange_Containers(bool isElement)
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test", isElement: isElement);
|
||||
var container1 = CreateContainer("One");
|
||||
container1.SortOrder = 0;
|
||||
var container2 = CreateContainer("Two");
|
||||
container2.SortOrder = 1;
|
||||
createModel.Containers = new[] { container1, container2 };
|
||||
|
||||
var propertyType1 = CreatePropertyType("Test Property 1", "testProperty1", containerKey: container1.Key);
|
||||
var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2", containerKey: container2.Key);
|
||||
createModel.Properties = new[] { propertyType1, propertyType2 };
|
||||
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test", isElement: isElement);
|
||||
container2.SortOrder = 0;
|
||||
container1.SortOrder = 1;
|
||||
updateModel.Containers = new[] { container1, container2 };
|
||||
updateModel.Properties = new[] { propertyType1, propertyType2 };
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
contentType = await ContentTypeService.GetAsync(result.Result!.Key);
|
||||
|
||||
Assert.IsNotNull(contentType);
|
||||
Assert.AreEqual(isElement, contentType.IsElement);
|
||||
Assert.AreEqual(2, contentType.PropertyGroups.Count);
|
||||
|
||||
var sortedPropertyGroups = contentType.PropertyGroups.OrderBy(g => g.SortOrder).ToArray();
|
||||
Assert.AreEqual("testProperty2", sortedPropertyGroups.First().PropertyTypes!.Single().Alias);
|
||||
Assert.AreEqual("testProperty1", sortedPropertyGroups.Last().PropertyTypes!.Single().Alias);
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public async Task Can_Make_Properties_Orphaned(bool isElement)
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test", isElement: isElement);
|
||||
var container1 = CreateContainer("One");
|
||||
var container2 = CreateContainer("Two");
|
||||
createModel.Containers = new[] { container1, container2 };
|
||||
|
||||
var propertyType1 = CreatePropertyType("Test Property 1", "testProperty1", containerKey: container1.Key);
|
||||
var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2", containerKey: container2.Key);
|
||||
createModel.Properties = new[] { propertyType1, propertyType2 };
|
||||
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test", isElement: isElement);
|
||||
updateModel.Containers = new[] { container1 };
|
||||
propertyType2.ContainerKey = null;
|
||||
updateModel.Properties = new[] { propertyType1, propertyType2 };
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
contentType = await ContentTypeService.GetAsync(result.Result!.Key);
|
||||
|
||||
Assert.IsNotNull(contentType);
|
||||
Assert.AreEqual(isElement, contentType.IsElement);
|
||||
Assert.AreEqual(1, contentType.PropertyGroups.Count);
|
||||
Assert.AreEqual(2, contentType.PropertyTypes.Count());
|
||||
Assert.AreEqual(1, contentType.PropertyGroups.First().PropertyTypes!.Count);
|
||||
Assert.AreEqual(1, contentType.NoGroupPropertyTypes.Count());
|
||||
|
||||
Assert.AreEqual("testProperty1", contentType.PropertyGroups.First().PropertyTypes!.Single().Alias);
|
||||
Assert.AreEqual("testProperty2", contentType.NoGroupPropertyTypes.Single().Alias);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Add_Compositions()
|
||||
{
|
||||
var propertyType1 = CreatePropertyType("Test Property 1", "testProperty1");
|
||||
var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2");
|
||||
|
||||
var compositionCreateModel = CreateCreateModel("Composition", "composition");
|
||||
compositionCreateModel.Properties = new[] { propertyType1 };
|
||||
var compositionContentType = (await ContentTypeEditingService.CreateAsync(compositionCreateModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
createModel.Properties = new[] { propertyType2 };
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test");
|
||||
updateModel.Properties = new[] { propertyType2 };
|
||||
updateModel.Compositions = new[]
|
||||
{
|
||||
new Composition { Key = compositionContentType.Key, CompositionType = CompositionType.Composition }
|
||||
};
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
contentType = await ContentTypeService.GetAsync(result.Result!.Key);
|
||||
|
||||
Assert.IsNotNull(contentType);
|
||||
Assert.AreEqual(1, contentType.ContentTypeComposition.Count());
|
||||
Assert.AreEqual(compositionContentType.Key, contentType.ContentTypeComposition.Single().Key);
|
||||
var propertyTypeAliases = contentType.CompositionPropertyTypes.Select(c => c.Alias).ToArray();
|
||||
Assert.AreEqual(2, propertyTypeAliases.Length);
|
||||
Assert.IsTrue(propertyTypeAliases.Contains("testProperty1"));
|
||||
Assert.IsTrue(propertyTypeAliases.Contains("testProperty2"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Reapply_Compositions()
|
||||
{
|
||||
var propertyType1 = CreatePropertyType("Test Property 1", "testProperty1");
|
||||
var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2");
|
||||
|
||||
var compositionCreateModel = CreateCreateModel("Composition", "composition");
|
||||
compositionCreateModel.Properties = new[] { propertyType1 };
|
||||
var compositionContentType = (await ContentTypeEditingService.CreateAsync(compositionCreateModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
createModel.Properties = new[] { propertyType2 };
|
||||
createModel.Compositions = new[]
|
||||
{
|
||||
new Composition { Key = compositionContentType.Key, CompositionType = CompositionType.Composition }
|
||||
};
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test");
|
||||
updateModel.Properties = new[] { propertyType2 };
|
||||
updateModel.Compositions = new[]
|
||||
{
|
||||
new Composition { Key = compositionContentType.Key, CompositionType = CompositionType.Composition }
|
||||
};
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
contentType = await ContentTypeService.GetAsync(result.Result!.Key);
|
||||
|
||||
Assert.IsNotNull(contentType);
|
||||
Assert.AreEqual(1, contentType.ContentTypeComposition.Count());
|
||||
Assert.AreEqual(compositionContentType.Key, contentType.ContentTypeComposition.Single().Key);
|
||||
var propertyTypeAliases = contentType.CompositionPropertyTypes.Select(c => c.Alias).ToArray();
|
||||
Assert.AreEqual(2, propertyTypeAliases.Length);
|
||||
Assert.IsTrue(propertyTypeAliases.Contains("testProperty1"));
|
||||
Assert.IsTrue(propertyTypeAliases.Contains("testProperty2"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Remove_Compositions()
|
||||
{
|
||||
var propertyType1 = CreatePropertyType("Test Property 1", "testProperty1");
|
||||
var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2");
|
||||
|
||||
var compositionCreateModel = CreateCreateModel("Composition", "composition");
|
||||
compositionCreateModel.Properties = new[] { propertyType1 };
|
||||
var compositionContentType = (await ContentTypeEditingService.CreateAsync(compositionCreateModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
createModel.Properties = new[] { propertyType2 };
|
||||
createModel.Compositions = new[]
|
||||
{
|
||||
new Composition { Key = compositionContentType.Key, CompositionType = CompositionType.Composition }
|
||||
};
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test");
|
||||
updateModel.Properties = new[] { propertyType2 };
|
||||
updateModel.Compositions = Array.Empty<Composition>();
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
contentType = await ContentTypeService.GetAsync(result.Result!.Key);
|
||||
|
||||
Assert.IsNotNull(contentType);
|
||||
Assert.IsEmpty(contentType.ContentTypeComposition);
|
||||
Assert.AreEqual(1, contentType.CompositionPropertyTypes.Count());
|
||||
Assert.AreEqual("testProperty2", contentType.CompositionPropertyTypes.Single().Alias);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Reapply_Inheritance()
|
||||
{
|
||||
var parentContentType = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent"), Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var createModel = CreateCreateModel(
|
||||
"Child",
|
||||
compositions: new Composition[]
|
||||
{
|
||||
new() { CompositionType = CompositionType.Inheritance, Key = parentContentType.Key }
|
||||
});
|
||||
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
var originalPath = contentType.Path;
|
||||
|
||||
var updateModel = CreateUpdateModel(
|
||||
"Child",
|
||||
compositions: new Composition[]
|
||||
{
|
||||
new() { CompositionType = CompositionType.Inheritance, Key = parentContentType.Key }
|
||||
});
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
contentType = await ContentTypeService.GetAsync(result.Result!.Key);
|
||||
|
||||
Assert.IsNotNull(contentType);
|
||||
Assert.AreEqual(1, contentType.ContentTypeComposition.Count());
|
||||
Assert.AreEqual(parentContentType.Id, contentType.ParentId);
|
||||
Assert.AreEqual(originalPath, contentType.Path);
|
||||
Assert.AreEqual($"-1,{parentContentType.Id},{contentType.Id}", contentType.Path);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Update_History_Cleanup()
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
createModel.Cleanup = new ContentTypeCleanup
|
||||
{
|
||||
PreventCleanup = true, KeepAllVersionsNewerThanDays = 123, KeepLatestVersionPerDayForDays = 456
|
||||
};
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test updated", "testUpdated");
|
||||
updateModel.Cleanup = new ContentTypeCleanup
|
||||
{
|
||||
PreventCleanup = false, KeepAllVersionsNewerThanDays = 234, KeepLatestVersionPerDayForDays = 567
|
||||
};
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
contentType = await ContentTypeService.GetAsync(result.Result!.Key);
|
||||
Assert.IsNotNull(contentType);
|
||||
|
||||
Assert.IsNotNull(contentType.HistoryCleanup);
|
||||
Assert.IsFalse(contentType.HistoryCleanup.PreventCleanup);
|
||||
Assert.AreEqual(234, contentType.HistoryCleanup.KeepAllVersionsNewerThanDays);
|
||||
Assert.AreEqual(567, contentType.HistoryCleanup.KeepLatestVersionPerDayForDays);
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public async Task Cannot_Move_Properties_To_Non_Existing_Containers(bool isElement)
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test", isElement: isElement);
|
||||
var container = CreateContainer("One");
|
||||
createModel.Containers = new[] { container };
|
||||
|
||||
var property = CreatePropertyType("Test Property", "testProperty", containerKey: container.Key);
|
||||
createModel.Properties = new[] { property };
|
||||
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test", isElement: isElement);
|
||||
property.ContainerKey = Guid.NewGuid();
|
||||
updateModel.Containers = new[] { container };
|
||||
updateModel.Properties = new[] { property };
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentTypeOperationStatus.MissingContainer, result.Status);
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public async Task Cannot_Move_Containers_To_Non_Existing_Containers(bool isElement)
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test", isElement: isElement);
|
||||
var container = CreateContainer("One");
|
||||
createModel.Containers = new[] { container };
|
||||
|
||||
var property = CreatePropertyType("Test Property", "testProperty", containerKey: container.Key);
|
||||
createModel.Properties = new[] { property };
|
||||
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test", isElement: isElement);
|
||||
container.ParentKey = Guid.NewGuid();
|
||||
updateModel.Containers = new[] { container };
|
||||
updateModel.Properties = new[] { property };
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentTypeOperationStatus.MissingContainer, result.Status);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Add_Self_As_Composition()
|
||||
{
|
||||
var property = CreatePropertyType("Test Property", "testProperty");
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
createModel.Properties = new[] { property };
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test");
|
||||
updateModel.Properties = new[] { property };
|
||||
updateModel.Compositions = new[]
|
||||
{
|
||||
new Composition { Key = contentType.Key, CompositionType = CompositionType.Composition }
|
||||
};
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentTypeOperationStatus.InvalidComposition, result.Status);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Change_Inheritance()
|
||||
{
|
||||
var parentContentType1 = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent1"), Constants.Security.SuperUserKey)).Result!;
|
||||
var parentContentType2 = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent2"), Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var createModel = CreateCreateModel(
|
||||
"Child",
|
||||
compositions: new Composition[]
|
||||
{
|
||||
new() { CompositionType = CompositionType.Inheritance, Key = parentContentType1.Key }
|
||||
});
|
||||
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel(
|
||||
"Child",
|
||||
compositions: new Composition[]
|
||||
{
|
||||
new() { CompositionType = CompositionType.Inheritance, Key = parentContentType2.Key }
|
||||
});
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentTypeOperationStatus.InvalidInheritance, result.Status);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Add_Inheritance()
|
||||
{
|
||||
var parentContentType = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent"), Constants.Security.SuperUserKey)).Result!;
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Child"), Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel(
|
||||
"Child",
|
||||
compositions: new Composition[]
|
||||
{
|
||||
new() { CompositionType = CompositionType.Inheritance, Key = parentContentType.Key }
|
||||
});
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentTypeOperationStatus.InvalidInheritance, result.Status);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Add_Multiple_Inheritance()
|
||||
{
|
||||
var parentContentType1 = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent1"), Constants.Security.SuperUserKey)).Result!;
|
||||
var parentContentType2 = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent2"), Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var createModel = CreateCreateModel(
|
||||
"Child",
|
||||
compositions: new Composition[]
|
||||
{
|
||||
new() { CompositionType = CompositionType.Inheritance, Key = parentContentType1.Key }
|
||||
});
|
||||
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel(
|
||||
"Child",
|
||||
compositions: new Composition[]
|
||||
{
|
||||
new() { CompositionType = CompositionType.Inheritance, Key = parentContentType1.Key },
|
||||
new() { CompositionType = CompositionType.Inheritance, Key = parentContentType2.Key }
|
||||
});
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentTypeOperationStatus.InvalidInheritance, result.Status);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Add_Self_As_Inheritance()
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test");
|
||||
updateModel.Compositions = new Composition[]
|
||||
{
|
||||
new() { CompositionType = CompositionType.Inheritance, Key = contentType.Key }
|
||||
};
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentTypeOperationStatus.InvalidInheritance, result.Status);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Add_Inheritance_When_Created_In_A_Folder()
|
||||
{
|
||||
EntityContainer container = ContentTypeService.CreateContainer(Constants.System.Root, Guid.NewGuid(), "Test folder").Result!.Entity;
|
||||
|
||||
var parentContentType = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Parent"), Constants.Security.SuperUserKey)).Result!;
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(CreateCreateModel("Child", parentKey: container.Key), Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel(
|
||||
"Child",
|
||||
compositions: new Composition[]
|
||||
{
|
||||
new() { CompositionType = CompositionType.Inheritance, Key = parentContentType.Key }
|
||||
});
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentTypeOperationStatus.InvalidInheritance, result.Status);
|
||||
}
|
||||
|
||||
[TestCase(CompositionType.Composition, CompositionType.Inheritance)]
|
||||
[TestCase(CompositionType.Inheritance, CompositionType.Composition)]
|
||||
public async Task Cannot_Change_Composition_To_Inheritance(CompositionType from, CompositionType to)
|
||||
{
|
||||
var compositionCreateModel = CreateCreateModel("Composition", "composition");
|
||||
var compositionContentType = (await ContentTypeEditingService.CreateAsync(compositionCreateModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
createModel.Compositions = new[]
|
||||
{
|
||||
new Composition { Key = compositionContentType.Key, CompositionType = from }
|
||||
};
|
||||
var contentType = (await ContentTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test");
|
||||
updateModel.Compositions = new[]
|
||||
{
|
||||
new Composition { Key = compositionContentType.Key, CompositionType = to }
|
||||
};
|
||||
|
||||
var result = await ContentTypeEditingService.UpdateAsync(contentType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentTypeOperationStatus.InvalidInheritance, result.Status);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models.ContentTypeEditing;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.ContentTypeEditing;
|
||||
using Umbraco.Cms.Tests.Common.Testing;
|
||||
using Umbraco.Cms.Tests.Integration.Testing;
|
||||
using PropertyTypeValidation = Umbraco.Cms.Core.Models.ContentTypeEditing.PropertyTypeValidation;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services;
|
||||
|
||||
[TestFixture]
|
||||
[UmbracoTest(
|
||||
Database = UmbracoTestOptions.Database.NewSchemaPerTest,
|
||||
PublishedRepositoryEvents = true,
|
||||
WithApplication = true)]
|
||||
public partial class ContentTypeEditingServiceTests : UmbracoIntegrationTest
|
||||
{
|
||||
private IContentTypeEditingService ContentTypeEditingService => GetRequiredService<IContentTypeEditingService>();
|
||||
|
||||
private IContentTypeService ContentTypeService => GetRequiredService<IContentTypeService>();
|
||||
|
||||
private const string TabContainerType = "Tab";
|
||||
|
||||
private const string GroupContainerType = "Group";
|
||||
|
||||
private ContentTypeCreateModel CreateCreateModel(
|
||||
string name = "Test",
|
||||
string? alias = null,
|
||||
Guid? key = null,
|
||||
bool isElement = false,
|
||||
Guid? parentKey = null,
|
||||
IEnumerable<ContentTypePropertyTypeModel>? propertyTypes = null,
|
||||
IEnumerable<ContentTypePropertyContainerModel>? containers = null,
|
||||
IEnumerable<Composition>? compositions = null) =>
|
||||
new()
|
||||
{
|
||||
Name = name,
|
||||
Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name),
|
||||
Key = key ?? Guid.NewGuid(),
|
||||
ContainerKey = parentKey,
|
||||
Properties = propertyTypes ?? Enumerable.Empty<ContentTypePropertyTypeModel>(),
|
||||
Containers = containers ?? Enumerable.Empty<ContentTypePropertyContainerModel>(),
|
||||
Compositions = compositions ?? Enumerable.Empty<Composition>(),
|
||||
IsElement = isElement
|
||||
};
|
||||
|
||||
private ContentTypeUpdateModel CreateUpdateModel(
|
||||
string name = "Test",
|
||||
string? alias = null,
|
||||
bool isElement = false,
|
||||
IEnumerable<ContentTypePropertyTypeModel>? propertyTypes = null,
|
||||
IEnumerable<ContentTypePropertyContainerModel>? containers = null,
|
||||
IEnumerable<Composition>? compositions = null) =>
|
||||
new()
|
||||
{
|
||||
Name = name,
|
||||
Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name),
|
||||
Properties = propertyTypes ?? Enumerable.Empty<ContentTypePropertyTypeModel>(),
|
||||
Containers = containers ?? Enumerable.Empty<ContentTypePropertyContainerModel>(),
|
||||
Compositions = compositions ?? Enumerable.Empty<Composition>(),
|
||||
IsElement = isElement
|
||||
};
|
||||
|
||||
private ContentTypePropertyTypeModel CreatePropertyType(
|
||||
string name = "Title",
|
||||
string? alias = null,
|
||||
Guid? key = null,
|
||||
Guid? containerKey = null,
|
||||
Guid? dataTypeKey = null) =>
|
||||
new()
|
||||
{
|
||||
Name = name,
|
||||
Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name),
|
||||
Key = key ?? Guid.NewGuid(),
|
||||
ContainerKey = containerKey,
|
||||
DataTypeKey = dataTypeKey ?? Constants.DataTypes.Guids.TextstringGuid,
|
||||
Validation = new PropertyTypeValidation(),
|
||||
Appearance = new PropertyTypeAppearance(),
|
||||
};
|
||||
|
||||
private ContentTypePropertyContainerModel CreateContainer(
|
||||
string name = "Container",
|
||||
string type = TabContainerType,
|
||||
Guid? key = null) =>
|
||||
new()
|
||||
{
|
||||
Name = name,
|
||||
Type = type,
|
||||
Key = key ?? Guid.NewGuid(),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models.ContentTypeEditing;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services;
|
||||
|
||||
public partial class MediaTypeEditingServiceTests
|
||||
{
|
||||
[Test]
|
||||
public async Task Can_Create_With_All_Basic_Settings()
|
||||
{
|
||||
var createModel = CreateCreateModel("Test Media Type", "testMediaType");
|
||||
createModel.Description = "This is the Test description";
|
||||
createModel.Icon = "icon icon-something";
|
||||
createModel.AllowedAsRoot = true;
|
||||
var result = await MediaTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
var mediaType = await MediaTypeService.GetAsync(result.Result!.Key);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(mediaType);
|
||||
Assert.AreEqual("testMediaType", mediaType.Alias);
|
||||
Assert.AreEqual("Test Media Type", mediaType.Name);
|
||||
Assert.AreEqual(result.Result.Id, mediaType.Id);
|
||||
Assert.AreEqual(result.Result.Key, mediaType.Key);
|
||||
Assert.AreEqual("This is the Test description", mediaType.Description);
|
||||
Assert.AreEqual("icon icon-something", mediaType.Icon);
|
||||
Assert.IsTrue(mediaType.AllowedAsRoot);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Create_In_A_Folder()
|
||||
{
|
||||
var containerResult = MediaTypeService.CreateContainer(Constants.System.Root, Guid.NewGuid(), "Test folder");
|
||||
Assert.IsTrue(containerResult.Success);
|
||||
var container = containerResult.Result?.Entity;
|
||||
Assert.IsNotNull(container);
|
||||
|
||||
var createModel = CreateCreateModel("Test", "test", parentKey: container.Key);
|
||||
var result = await MediaTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
|
||||
// Ensure it's actually persisted in the folder
|
||||
var mediaType = await MediaTypeService.GetAsync(result.Result!.Key);
|
||||
Assert.IsNotNull(mediaType);
|
||||
Assert.AreEqual(container.Id, mediaType.ParentId);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Create_With_Properties_In_A_Container()
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
var container = CreateContainer();
|
||||
createModel.Containers = new[] { container };
|
||||
|
||||
var propertyType = CreatePropertyType(name: "Test Property", alias: "testProperty", containerKey: container.Key);
|
||||
createModel.Properties = new[] { propertyType };
|
||||
|
||||
var result = await MediaTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
var mediaType = await MediaTypeService.GetAsync(result.Result!.Key);
|
||||
|
||||
Assert.IsNotNull(mediaType);
|
||||
Assert.AreEqual(1, mediaType.PropertyGroups.Count);
|
||||
Assert.AreEqual(1, mediaType.PropertyTypes.Count());
|
||||
Assert.AreEqual(1, mediaType.PropertyGroups.First().PropertyTypes!.Count);
|
||||
Assert.AreEqual("testProperty", mediaType.PropertyTypes.First().Alias);
|
||||
Assert.AreEqual("testProperty", mediaType.PropertyGroups.First().PropertyTypes!.First().Alias);
|
||||
Assert.IsEmpty(mediaType.NoGroupPropertyTypes);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Create_As_Child()
|
||||
{
|
||||
var parentProperty = CreatePropertyType("Parent Property", "parentProperty");
|
||||
var parentModel = CreateCreateModel(
|
||||
name: "Parent",
|
||||
propertyTypes: new[] { parentProperty });
|
||||
|
||||
var parentResult = await MediaTypeEditingService.CreateAsync(parentModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(parentResult.Success);
|
||||
|
||||
var childProperty = CreatePropertyType("Child Property", "childProperty");
|
||||
var parentKey = parentResult.Result!.Key;
|
||||
Composition[] composition =
|
||||
{
|
||||
new()
|
||||
{
|
||||
CompositionType = CompositionType.Inheritance, Key = parentKey,
|
||||
},
|
||||
};
|
||||
|
||||
var childModel = CreateCreateModel(
|
||||
name: "Child",
|
||||
propertyTypes: new[] { childProperty },
|
||||
compositions: composition);
|
||||
|
||||
var result = await MediaTypeEditingService.CreateAsync(childModel, Constants.Security.SuperUserKey);
|
||||
|
||||
Assert.IsTrue(result.Success);
|
||||
|
||||
var mediaType = result.Result!;
|
||||
|
||||
Assert.AreEqual(parentResult.Result.Id, mediaType.ParentId);
|
||||
Assert.AreEqual(1, mediaType.ContentTypeComposition.Count());
|
||||
Assert.AreEqual(parentResult.Result.Key, mediaType.ContentTypeComposition.FirstOrDefault()?.Key);
|
||||
Assert.AreEqual(2, mediaType.CompositionPropertyTypes.Count());
|
||||
Assert.IsTrue(mediaType.CompositionPropertyTypes.Any(x => x.Alias == parentProperty.Alias));
|
||||
Assert.IsTrue(mediaType.CompositionPropertyTypes.Any(x => x.Alias == childProperty.Alias));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services;
|
||||
|
||||
public partial class MediaTypeEditingServiceTests
|
||||
{
|
||||
[Test]
|
||||
public async Task Can_Update_All_Basic_Settings()
|
||||
{
|
||||
var createModel = CreateCreateModel("Test Media Type", "testMediaType");
|
||||
var mediaType = (await MediaTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test updated", "testUpdated");
|
||||
updateModel.Description = "This is the Test description updated";
|
||||
updateModel.Icon = "icon icon-something-updated";
|
||||
updateModel.AllowedAsRoot = false;
|
||||
|
||||
var result = await MediaTypeEditingService.UpdateAsync(mediaType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
mediaType = await MediaTypeService.GetAsync(result.Result!.Key);
|
||||
Assert.IsNotNull(mediaType);
|
||||
|
||||
Assert.AreEqual("testUpdated", mediaType.Alias);
|
||||
Assert.AreEqual("Test updated", mediaType.Name);
|
||||
Assert.AreEqual(result.Result.Id, mediaType.Id);
|
||||
Assert.AreEqual(result.Result.Key, mediaType.Key);
|
||||
Assert.AreEqual("This is the Test description updated", mediaType.Description);
|
||||
Assert.AreEqual("icon icon-something-updated", mediaType.Icon);
|
||||
Assert.IsFalse(mediaType.AllowedAsRoot);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Add_Allowed_Types()
|
||||
{
|
||||
var allowedOne = (await MediaTypeEditingService.CreateAsync(CreateCreateModel("Allowed One", "allowedOne"), Constants.Security.SuperUserKey)).Result!;
|
||||
var allowedTwo = (await MediaTypeEditingService.CreateAsync(CreateCreateModel("Allowed Two", "allowedTwo"), Constants.Security.SuperUserKey)).Result!;
|
||||
var allowedThree = (await MediaTypeEditingService.CreateAsync(CreateCreateModel("Allowed Three", "allowedThree"), Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
createModel.AllowedContentTypes = new[]
|
||||
{
|
||||
new ContentTypeSort(allowedOne.Key, 10, allowedOne.Alias),
|
||||
new ContentTypeSort(allowedTwo.Key, 20, allowedTwo.Alias),
|
||||
};
|
||||
var mediaType = (await MediaTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test");
|
||||
updateModel.AllowedContentTypes = new[]
|
||||
{
|
||||
new ContentTypeSort(allowedTwo.Key, 20, allowedTwo.Alias),
|
||||
new ContentTypeSort(allowedThree.Key, 30, allowedThree.Alias),
|
||||
};
|
||||
|
||||
var result = await MediaTypeEditingService.UpdateAsync(mediaType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
mediaType = await MediaTypeService.GetAsync(result.Result.Key);
|
||||
Assert.IsNotNull(mediaType);
|
||||
|
||||
var allowedContentTypes = mediaType.AllowedContentTypes?.ToArray();
|
||||
Assert.IsNotNull(allowedContentTypes);
|
||||
Assert.AreEqual(2, allowedContentTypes.Length);
|
||||
Assert.IsTrue(allowedContentTypes.Any(c => c.Key == allowedTwo.Key && c.SortOrder == 0 && c.Alias == allowedTwo.Alias));
|
||||
Assert.IsTrue(allowedContentTypes.Any(c => c.Key == allowedThree.Key && c.SortOrder == 1 && c.Alias == allowedThree.Alias));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Edit_Properties()
|
||||
{
|
||||
var createModel = CreateCreateModel("Test", "test");
|
||||
var propertyType = CreatePropertyType("Test Property", "testProperty");
|
||||
propertyType.Description = "The description";
|
||||
createModel.Properties = new[] { propertyType };
|
||||
|
||||
var mediaType = (await MediaTypeEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result!;
|
||||
var originalPropertyTypeKey = mediaType.PropertyTypes.First().Key;
|
||||
|
||||
var updateModel = CreateUpdateModel("Test", "test");
|
||||
propertyType = CreatePropertyType("Test Property Updated", "testProperty", key: originalPropertyTypeKey);
|
||||
propertyType.Description = "The updated description";
|
||||
propertyType.SortOrder = 10;
|
||||
var propertyType2 = CreatePropertyType("Test Property 2", "testProperty2");
|
||||
propertyType2.Description = "The description 2";
|
||||
propertyType2.SortOrder = 5;
|
||||
updateModel.Properties = new[] { propertyType, propertyType2 };
|
||||
|
||||
var result = await MediaTypeEditingService.UpdateAsync(mediaType, updateModel, Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
// Ensure it's actually persisted
|
||||
mediaType = await MediaTypeService.GetAsync(result.Result!.Key);
|
||||
|
||||
Assert.IsNotNull(mediaType);
|
||||
Assert.AreEqual(2, mediaType.PropertyTypes.Count());
|
||||
|
||||
var property1 = mediaType.PropertyTypes.First();
|
||||
Assert.AreEqual("Test Property 2", property1.Name);
|
||||
Assert.AreEqual("testProperty2", property1.Alias);
|
||||
Assert.AreEqual("The description 2", property1.Description);
|
||||
Assert.AreEqual(5, property1.SortOrder);
|
||||
var property2 = mediaType.PropertyTypes.Last();
|
||||
Assert.AreEqual("Test Property Updated", property2.Name);
|
||||
Assert.AreEqual("testProperty", property2.Alias);
|
||||
Assert.AreEqual("The updated description", property2.Description);
|
||||
Assert.AreEqual(originalPropertyTypeKey, property2.Key);
|
||||
Assert.AreEqual(10, property2.SortOrder);
|
||||
|
||||
Assert.AreEqual(2, mediaType.NoGroupPropertyTypes.Count());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models.ContentTypeEditing;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.ContentTypeEditing;
|
||||
using Umbraco.Cms.Tests.Common.Testing;
|
||||
using Umbraco.Cms.Tests.Integration.Testing;
|
||||
using PropertyTypeValidation = Umbraco.Cms.Core.Models.ContentTypeEditing.PropertyTypeValidation;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the media type editing service. Please notice that a lot of functional test is covered by the content type
|
||||
/// editing service tests, since these services share the same base implementation.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[UmbracoTest(
|
||||
Database = UmbracoTestOptions.Database.NewSchemaPerTest,
|
||||
PublishedRepositoryEvents = true,
|
||||
WithApplication = true)]
|
||||
public partial class MediaTypeEditingServiceTests : UmbracoIntegrationTest
|
||||
{
|
||||
private IMediaTypeEditingService MediaTypeEditingService => GetRequiredService<IMediaTypeEditingService>();
|
||||
|
||||
private IMediaTypeService MediaTypeService => GetRequiredService<IMediaTypeService>();
|
||||
|
||||
private const string TabContainerType = "Tab";
|
||||
|
||||
private const string GroupContainerType = "Group";
|
||||
|
||||
private MediaTypeCreateModel CreateCreateModel(
|
||||
string name = "Test",
|
||||
string? alias = null,
|
||||
Guid? key = null,
|
||||
Guid? parentKey = null,
|
||||
IEnumerable<MediaTypePropertyTypeModel>? propertyTypes = null,
|
||||
IEnumerable<MediaTypePropertyContainerModel>? containers = null,
|
||||
IEnumerable<Composition>? compositions = null) =>
|
||||
new()
|
||||
{
|
||||
Name = name,
|
||||
Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name),
|
||||
Key = key ?? Guid.NewGuid(),
|
||||
ParentKey = parentKey,
|
||||
Properties = propertyTypes ?? Enumerable.Empty<MediaTypePropertyTypeModel>(),
|
||||
Containers = containers ?? Enumerable.Empty<MediaTypePropertyContainerModel>(),
|
||||
Compositions = compositions ?? Enumerable.Empty<Composition>(),
|
||||
};
|
||||
|
||||
private MediaTypeUpdateModel CreateUpdateModel(
|
||||
string name = "Test",
|
||||
string? alias = null,
|
||||
IEnumerable<MediaTypePropertyTypeModel>? propertyTypes = null,
|
||||
IEnumerable<MediaTypePropertyContainerModel>? containers = null,
|
||||
IEnumerable<Composition>? compositions = null) =>
|
||||
new()
|
||||
{
|
||||
Name = name,
|
||||
Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name),
|
||||
Properties = propertyTypes ?? Enumerable.Empty<MediaTypePropertyTypeModel>(),
|
||||
Containers = containers ?? Enumerable.Empty<MediaTypePropertyContainerModel>(),
|
||||
Compositions = compositions ?? Enumerable.Empty<Composition>()
|
||||
};
|
||||
|
||||
private MediaTypePropertyTypeModel CreatePropertyType(
|
||||
string name = "Title",
|
||||
string? alias = null,
|
||||
Guid? key = null,
|
||||
Guid? containerKey = null,
|
||||
Guid? dataTypeKey = null) =>
|
||||
new()
|
||||
{
|
||||
Name = name,
|
||||
Alias = alias ?? ShortStringHelper.CleanStringForSafeAlias(name),
|
||||
Key = key ?? Guid.NewGuid(),
|
||||
ContainerKey = containerKey,
|
||||
DataTypeKey = dataTypeKey ?? Constants.DataTypes.Guids.TextstringGuid,
|
||||
Validation = new PropertyTypeValidation(),
|
||||
Appearance = new PropertyTypeAppearance(),
|
||||
};
|
||||
|
||||
private MediaTypePropertyContainerModel CreateContainer(
|
||||
string name = "Container",
|
||||
string type = TabContainerType,
|
||||
Guid? key = null) =>
|
||||
new()
|
||||
{
|
||||
Name = name,
|
||||
Type = type,
|
||||
Key = key ?? Guid.NewGuid(),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user