Add tests for content editing service
This commit is contained in:
@@ -35,7 +35,7 @@ internal sealed class ContentEditingService
|
||||
return await Task.FromResult(content);
|
||||
}
|
||||
|
||||
public async Task<Attempt<IContent?, ContentEditingOperationStatus>> CreateAsync(ContentCreateModel createModel, int userId)
|
||||
public async Task<Attempt<IContent?, ContentEditingOperationStatus>> CreateAsync(ContentCreateModel createModel, int userId = Constants.Security.SuperUserId)
|
||||
{
|
||||
Attempt<IContent?, ContentEditingOperationStatus> result = await MapCreate(createModel);
|
||||
if (result.Success == false)
|
||||
@@ -56,7 +56,7 @@ internal sealed class ContentEditingService
|
||||
: Attempt.FailWithStatus<IContent?, ContentEditingOperationStatus>(operationStatus, content);
|
||||
}
|
||||
|
||||
public async Task<Attempt<IContent, ContentEditingOperationStatus>> UpdateAsync(IContent content, ContentUpdateModel updateModel, int userId)
|
||||
public async Task<Attempt<IContent, ContentEditingOperationStatus>> UpdateAsync(IContent content, ContentUpdateModel updateModel, int userId = Constants.Security.SuperUserId)
|
||||
{
|
||||
Attempt<ContentEditingOperationStatus> result = await MapUpdate(content, updateModel);
|
||||
if (result.Success == false)
|
||||
@@ -76,10 +76,10 @@ internal sealed class ContentEditingService
|
||||
: Attempt.FailWithStatus(operationStatus, content);
|
||||
}
|
||||
|
||||
public async Task<Attempt<IContent?, ContentEditingOperationStatus>> MoveToRecycleBinAsync(Guid id, int userId)
|
||||
public async Task<Attempt<IContent?, ContentEditingOperationStatus>> MoveToRecycleBinAsync(Guid id, int userId = Constants.Security.SuperUserId)
|
||||
=> await HandleDeletionAsync(id, content => ContentService.MoveToRecycleBin(content, userId));
|
||||
|
||||
public async Task<Attempt<IContent?, ContentEditingOperationStatus>> DeleteAsync(Guid id, int userId)
|
||||
public async Task<Attempt<IContent?, ContentEditingOperationStatus>> DeleteAsync(Guid id, int userId = Constants.Security.SuperUserId)
|
||||
=> await HandleDeletionAsync(id, content => ContentService.Delete(content, userId));
|
||||
|
||||
protected override IContent Create(string? name, int parentId, IContentType contentType) => new Content(name, parentId, contentType);
|
||||
|
||||
@@ -156,6 +156,19 @@ public abstract class ContentEditingServiceBase<TContent, TContentType, TContent
|
||||
return null;
|
||||
}
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
TContentType? parentContentType = ContentTypeService.Get(parent.ContentType.Key);
|
||||
Guid[] allowedContentTypeKeys = parentContentType?.AllowedContentTypes?.Select(c => c.Key).ToArray()
|
||||
?? Array.Empty<Guid>();
|
||||
|
||||
if (allowedContentTypeKeys.Contains(contentType.Key) == false)
|
||||
{
|
||||
operationStatus = ContentEditingOperationStatus.NotAllowed;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
operationStatus = ContentEditingOperationStatus.Success;
|
||||
return parent;
|
||||
}
|
||||
|
||||
@@ -8,9 +8,11 @@ public interface IContentEditingService
|
||||
{
|
||||
Task<IContent?> GetAsync(Guid id);
|
||||
|
||||
Task<Attempt<IContent?, ContentEditingOperationStatus>> CreateAsync(ContentCreateModel createModel, int userId);
|
||||
Task<Attempt<IContent?, ContentEditingOperationStatus>> CreateAsync(ContentCreateModel createModel, int userId = Constants.Security.SuperUserId);
|
||||
|
||||
Task<Attempt<IContent, ContentEditingOperationStatus>> UpdateAsync(IContent content, ContentUpdateModel updateMode, int userId);
|
||||
Task<Attempt<IContent, ContentEditingOperationStatus>> UpdateAsync(IContent content, ContentUpdateModel updateModel, int userId = Constants.Security.SuperUserId);
|
||||
|
||||
Task<Attempt<IContent?, ContentEditingOperationStatus>> MoveToRecycleBinAsync(Guid id, int userId);
|
||||
Task<Attempt<IContent?, ContentEditingOperationStatus>> MoveToRecycleBinAsync(Guid id, int userId = Constants.Security.SuperUserId);
|
||||
|
||||
Task<Attempt<IContent?, ContentEditingOperationStatus>> DeleteAsync(Guid id, int userId = Constants.Security.SuperUserId);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ public enum ContentEditingOperationStatus
|
||||
ParentNotFound,
|
||||
NotAllowed,
|
||||
TemplateNotFound,
|
||||
TemplateNotAllowed,
|
||||
PropertyTypeNotFound,
|
||||
Unknown,
|
||||
TemplateNotAllowed
|
||||
Unknown
|
||||
}
|
||||
|
||||
@@ -0,0 +1,428 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.ContentEditing;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
using Umbraco.Cms.Tests.Common.Builders;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services;
|
||||
|
||||
public partial class ContentEditingServiceTests
|
||||
{
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public async Task Create_At_Root(bool allowedAtRoot)
|
||||
{
|
||||
var template = TemplateBuilder.CreateTextPageTemplate();
|
||||
await TemplateService.CreateAsync(template);
|
||||
|
||||
var contentType = ContentTypeBuilder.CreateTextPageContentType(defaultTemplateId: template.Id);
|
||||
contentType.AllowedAsRoot = allowedAtRoot;
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
TemplateKey = template.Key,
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantName = "Test Create",
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "title", Value = "The title value" },
|
||||
new PropertyValueModel { Alias = "bodyText", Value = "The body text" }
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
|
||||
if (allowedAtRoot)
|
||||
{
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status);
|
||||
VerifyCreate(result.Result);
|
||||
|
||||
// re-get and re-test
|
||||
VerifyCreate(await ContentEditingService.GetAsync(result.Result!.Key));
|
||||
|
||||
void VerifyCreate(IContent? createdContent)
|
||||
{
|
||||
Assert.IsNotNull(createdContent);
|
||||
Assert.AreNotEqual(Guid.Empty, createdContent.Key);
|
||||
Assert.IsTrue(createdContent.HasIdentity);
|
||||
Assert.AreEqual("Test Create", createdContent.Name);
|
||||
Assert.AreEqual("The title value", createdContent.GetValue<string>("title"));
|
||||
Assert.AreEqual("The body text", createdContent.GetValue<string>("bodyText"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.NotAllowed, result.Status);
|
||||
Assert.IsNull(result.Result);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public async Task Create_As_Child(bool allowedAsChild)
|
||||
{
|
||||
var template = TemplateBuilder.CreateTextPageTemplate();
|
||||
await TemplateService.CreateAsync(template);
|
||||
|
||||
var childContentType = ContentTypeBuilder.CreateTextPageContentType(defaultTemplateId: template.Id);
|
||||
childContentType.AllowedAsRoot = false;
|
||||
ContentTypeService.Save(childContentType);
|
||||
|
||||
var rootContentType = ContentTypeBuilder.CreateBasicContentType();
|
||||
rootContentType.AllowedAsRoot = true;
|
||||
if (allowedAsChild)
|
||||
{
|
||||
rootContentType.AllowedContentTypes = new[]
|
||||
{
|
||||
new ContentTypeSort(new Lazy<int>(() => childContentType.Id), childContentType.Key, 1, childContentType.Alias)
|
||||
};
|
||||
}
|
||||
ContentTypeService.Save(rootContentType);
|
||||
|
||||
var rootKey = (await ContentEditingService.CreateAsync(new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = rootContentType.Key, InvariantName = "Root", ParentKey = Constants.System.RootKey,
|
||||
})).Result.Key;
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = childContentType.Key,
|
||||
TemplateKey = template.Key,
|
||||
ParentKey = rootKey,
|
||||
InvariantName = "Test Create Child",
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "title", Value = "The child title value" },
|
||||
new PropertyValueModel { Alias = "bodyText", Value = "The child body text" }
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
|
||||
if (allowedAsChild)
|
||||
{
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status);
|
||||
|
||||
var createdContent = result.Result;
|
||||
Assert.NotNull(createdContent);
|
||||
Assert.AreNotEqual(Guid.Empty, createdContent.Key);
|
||||
Assert.IsTrue(createdContent.HasIdentity);
|
||||
Assert.AreEqual("Test Create Child", createdContent.Name);
|
||||
Assert.AreEqual("The child title value", createdContent.GetValue<string>("title"));
|
||||
Assert.AreEqual("The child body text", createdContent.GetValue<string>("bodyText"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.NotAllowed, result.Status);
|
||||
Assert.IsNull(result.Result);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Create_Without_Template()
|
||||
{
|
||||
var contentType = ContentTypeBuilder.CreateContentMetaContentType();
|
||||
contentType.AllowedTemplates = null;
|
||||
contentType.AllowedAsRoot = true;
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantName = "Test Create",
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "title", Value = "The title value" }
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status);
|
||||
Assert.IsNotNull(result.Result);
|
||||
Assert.IsTrue(result.Result.HasIdentity);
|
||||
Assert.AreEqual("The title value", result.Result.GetValue<string>("title"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Create_Without_Properties()
|
||||
{
|
||||
var template = TemplateBuilder.CreateTextPageTemplate();
|
||||
await TemplateService.CreateAsync(template);
|
||||
|
||||
var contentType = ContentTypeBuilder.CreateTextPageContentType(defaultTemplateId: template.Id);
|
||||
contentType.AllowedAsRoot = true;
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantName = "Test Create"
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status);
|
||||
Assert.IsNotNull(result.Result);
|
||||
Assert.IsTrue(result.Result.HasIdentity);
|
||||
Assert.AreEqual(null, result.Result.GetValue<string>("title"));
|
||||
Assert.AreEqual(null, result.Result.GetValue<string>("bodyText"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Create_With_Non_Existing_Parent()
|
||||
{
|
||||
var contentType = ContentTypeBuilder.CreateBasicContentType();
|
||||
contentType.AllowedAsRoot = true;
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
ParentKey = Guid.NewGuid(),
|
||||
InvariantName = "Test Create"
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.ParentNotFound, result.Status);
|
||||
Assert.IsNull(result.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Create_Without_Content_Type()
|
||||
{
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = Guid.NewGuid(),
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantName = "Test Create"
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.ContentTypeNotFound, result.Status);
|
||||
Assert.IsNull(result.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Create_With_Invalid_Template()
|
||||
{
|
||||
var template = TemplateBuilder.CreateTextPageTemplate();
|
||||
await TemplateService.CreateAsync(template);
|
||||
|
||||
var contentType = ContentTypeBuilder.CreateBasicContentType();
|
||||
contentType.AllowedAsRoot = true;
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
TemplateKey = template.Key,
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantName = "Test Create"
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.TemplateNotAllowed, result.Status);
|
||||
Assert.IsNotNull(result.Result);
|
||||
Assert.IsFalse(result.Result.HasIdentity);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Create_With_Non_Existing_Template()
|
||||
{
|
||||
var contentType = ContentTypeBuilder.CreateBasicContentType();
|
||||
contentType.AllowedAsRoot = true;
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
TemplateKey = Guid.NewGuid(),
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantName = "Test Create"
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.TemplateNotFound, result.Status);
|
||||
Assert.IsNotNull(result.Result);
|
||||
Assert.IsFalse(result.Result.HasIdentity);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Create_With_Non_Existing_Properties()
|
||||
{
|
||||
var contentType = ContentTypeBuilder.CreateContentMetaContentType();
|
||||
contentType.AllowedTemplates = null;
|
||||
contentType.AllowedAsRoot = true;
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantName = "Test Create",
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "title", Value = "The title value" },
|
||||
new PropertyValueModel { Alias = "no_such_property", Value = "No such property value" },
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.PropertyTypeNotFound, result.Status);
|
||||
Assert.IsNull(result.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Create_Invariant_Content_Without_Name()
|
||||
{
|
||||
var contentType = ContentTypeBuilder.CreateContentMetaContentType();
|
||||
contentType.AllowedTemplates = null;
|
||||
contentType.AllowedAsRoot = true;
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantName = null,
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "title", Value = "The title value" }
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.ContentTypeCultureVarianceMismatch, result.Status);
|
||||
Assert.IsNull(result.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Create_With_Variant_Property_Value_For_Invariant_Content()
|
||||
{
|
||||
var contentType = ContentTypeBuilder.CreateContentMetaContentType();
|
||||
contentType.AllowedTemplates = null;
|
||||
contentType.AllowedAsRoot = true;
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantName = "Test Create",
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "title", Value = "The title value" }
|
||||
},
|
||||
Variants = new []
|
||||
{
|
||||
new VariantModel
|
||||
{
|
||||
Culture = "en-US",
|
||||
Name = "The English Name",
|
||||
Properties = new []
|
||||
{
|
||||
new PropertyValueModel { Alias = "bodyText", Value = "The body text value" }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.ContentTypeCultureVarianceMismatch, result.Status);
|
||||
Assert.IsNull(result.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Create_Culture_Variant()
|
||||
{
|
||||
var contentType = await CreateVariantContentType();
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "invariantTitle", Value = "The Invariant Title" }
|
||||
},
|
||||
Variants = new[]
|
||||
{
|
||||
new VariantModel
|
||||
{
|
||||
Culture = "en-US",
|
||||
Name = "The English Name",
|
||||
Properties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "variantTitle", Value = "The English Title" }
|
||||
}
|
||||
},
|
||||
new VariantModel
|
||||
{
|
||||
Culture = "da-DK",
|
||||
Name = "The Danish Name",
|
||||
Properties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "variantTitle", Value = "The Danish Title" }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status);
|
||||
VerifyCreate(result.Result);
|
||||
|
||||
// re-get and re-test
|
||||
VerifyCreate(await ContentEditingService.GetAsync(result.Result!.Key));
|
||||
|
||||
void VerifyCreate(IContent? createdContent)
|
||||
{
|
||||
Assert.IsNotNull(createdContent);
|
||||
Assert.AreEqual("The English Name", createdContent.GetCultureName("en-US"));
|
||||
Assert.AreEqual("The Danish Name", createdContent.GetCultureName("da-DK"));
|
||||
Assert.AreEqual("The Invariant Title", createdContent.GetValue<string>("invariantTitle"));
|
||||
Assert.AreEqual("The English Title", createdContent.GetValue<string>("variantTitle", "en-US"));
|
||||
Assert.AreEqual("The Danish Title", createdContent.GetValue<string>("variantTitle", "da-DK"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Create_With_Invariant_Property_Value_For_Variant_Content()
|
||||
{
|
||||
var contentType = await CreateVariantContentType();
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "invariantTitle", Value = "The Invariant Title" },
|
||||
new PropertyValueModel { Alias = "variantTitle", Value = "The Variant Title" }
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.PropertyTypeNotFound, result.Status);
|
||||
Assert.IsNull(result.Result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services;
|
||||
|
||||
public partial class ContentEditingServiceTests
|
||||
{
|
||||
[TestCase(true)]
|
||||
[TestCase(true)]
|
||||
public async Task Can_Delete(bool variant)
|
||||
{
|
||||
var content = await (variant ? CreateVariantContent() : CreateInvariantContent());
|
||||
|
||||
var result = await ContentEditingService.DeleteAsync(content.Key);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status);
|
||||
|
||||
// re-get and verify deletion
|
||||
content = await ContentEditingService.GetAsync(content.Key);
|
||||
Assert.IsNull(content);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Delete_Non_Existing()
|
||||
{
|
||||
var result = await ContentEditingService.DeleteAsync(Guid.NewGuid());
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.NotFound, result.Status);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services;
|
||||
|
||||
public partial class ContentEditingServiceTests
|
||||
{
|
||||
[TestCase(true)]
|
||||
[TestCase(true)]
|
||||
public async Task Can_Get(bool variant)
|
||||
{
|
||||
var content = await (variant ? CreateVariantContent() : CreateInvariantContent());
|
||||
|
||||
var result = await ContentEditingService.GetAsync(content.Key);
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(content.Key, result.Key);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Get_Non_Existing()
|
||||
{
|
||||
var result = await ContentEditingService.GetAsync(Guid.NewGuid());
|
||||
Assert.IsNull(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.ContentEditing;
|
||||
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;
|
||||
|
||||
public partial class ContentEditingServiceTests
|
||||
{
|
||||
[Test]
|
||||
public async Task Can_Update_Invariant()
|
||||
{
|
||||
var content = await CreateInvariantContent();
|
||||
|
||||
var updateModel = new ContentUpdateModel
|
||||
{
|
||||
InvariantName = "Updated Name",
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "title", Value = "The updated title" },
|
||||
new PropertyValueModel { Alias = "text", Value = "The updated text" }
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.UpdateAsync(content, updateModel);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status);
|
||||
VerifyUpdate(result.Result);
|
||||
|
||||
// re-get and re-test
|
||||
VerifyUpdate(await ContentEditingService.GetAsync(content.Key));
|
||||
|
||||
void VerifyUpdate(IContent? updatedContent)
|
||||
{
|
||||
Assert.IsNotNull(updatedContent);
|
||||
Assert.AreEqual("Updated Name", updatedContent.Name);
|
||||
Assert.AreEqual("The updated title", updatedContent.GetValue<string>("title"));
|
||||
Assert.AreEqual("The updated text", updatedContent.GetValue<string>("text"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Update_Variant()
|
||||
{
|
||||
var content = await CreateVariantContent();
|
||||
|
||||
var updateModel = new ContentUpdateModel
|
||||
{
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" }
|
||||
},
|
||||
Variants = new []
|
||||
{
|
||||
new VariantModel
|
||||
{
|
||||
Culture = "en-US",
|
||||
Name = "Updated English Name",
|
||||
Properties = new []
|
||||
{
|
||||
new PropertyValueModel { Alias = "variantTitle", Value = "The updated English title" }
|
||||
}
|
||||
},
|
||||
new VariantModel
|
||||
{
|
||||
Culture = "da-DK",
|
||||
Name = "Updated Danish Name",
|
||||
Properties = new []
|
||||
{
|
||||
new PropertyValueModel { Alias = "variantTitle", Value = "The updated Danish title" }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.UpdateAsync(content, updateModel);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status);
|
||||
VerifyUpdate(result.Result);
|
||||
|
||||
// re-get and re-test
|
||||
VerifyUpdate(await ContentEditingService.GetAsync(content.Key));
|
||||
|
||||
void VerifyUpdate(IContent? updatedContent)
|
||||
{
|
||||
Assert.IsNotNull(updatedContent);
|
||||
Assert.AreEqual("Updated English Name", updatedContent.GetCultureName("en-US"));
|
||||
Assert.AreEqual("Updated Danish Name", updatedContent.GetCultureName("da-DK"));
|
||||
Assert.AreEqual("The updated invariant title", updatedContent.GetValue<string>("invariantTitle"));
|
||||
Assert.AreEqual("The updated English title", updatedContent.GetValue<string>("variantTitle", "en-US"));
|
||||
Assert.AreEqual("The updated Danish title", updatedContent.GetValue<string>("variantTitle", "da-DK"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Update_Template()
|
||||
{
|
||||
var templateOne = new TemplateBuilder().WithAlias("textPageOne").WithName("Text page one").Build();
|
||||
var templateTwo = new TemplateBuilder().WithAlias("textPageTwo").WithName("Text page two").Build();
|
||||
await TemplateService.CreateAsync(templateOne);
|
||||
await TemplateService.CreateAsync(templateTwo);
|
||||
|
||||
var content = await CreateInvariantContent(templateOne, templateTwo);
|
||||
Assert.AreEqual(templateOne.Id, content.TemplateId);
|
||||
|
||||
var updateModel = new ContentUpdateModel
|
||||
{
|
||||
InvariantName = "Updated Name",
|
||||
TemplateKey = templateTwo.Key
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.UpdateAsync(content, updateModel);
|
||||
VerifyUpdate(result.Result);
|
||||
|
||||
// re-get and re-test
|
||||
VerifyUpdate(await ContentEditingService.GetAsync(content.Key));
|
||||
|
||||
void VerifyUpdate(IContent? updatedContent)
|
||||
{
|
||||
Assert.IsNotNull(updatedContent);
|
||||
Assert.AreEqual("Updated Name", updatedContent.Name);
|
||||
Assert.AreEqual(templateTwo.Id, updatedContent.TemplateId);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Remove_Template()
|
||||
{
|
||||
var templateOne = new TemplateBuilder().WithAlias("textPageOne").WithName("Text page one").Build();
|
||||
await TemplateService.CreateAsync(templateOne);
|
||||
|
||||
var content = await CreateInvariantContent(templateOne);
|
||||
Assert.AreEqual(templateOne.Id, content.TemplateId);
|
||||
|
||||
var updateModel = new ContentUpdateModel
|
||||
{
|
||||
InvariantName = "Updated Name",
|
||||
TemplateKey = null
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.UpdateAsync(content, updateModel);
|
||||
VerifyUpdate(result.Result);
|
||||
|
||||
// re-get and re-test
|
||||
VerifyUpdate(await ContentEditingService.GetAsync(content.Key));
|
||||
|
||||
void VerifyUpdate(IContent? updatedContent)
|
||||
{
|
||||
Assert.IsNotNull(updatedContent);
|
||||
Assert.AreEqual("Updated Name", updatedContent.Name);
|
||||
Assert.AreEqual(null, updatedContent.TemplateId);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Can_Remove_Property_Value()
|
||||
{
|
||||
var content = await CreateInvariantContent();
|
||||
|
||||
var updateModel = new ContentUpdateModel
|
||||
{
|
||||
InvariantName = "Updated Name",
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "title", Value = "The updated title" }
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.UpdateAsync(content, updateModel);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status);
|
||||
VerifyUpdate(result.Result);
|
||||
|
||||
// re-get and re-test
|
||||
VerifyUpdate(await ContentEditingService.GetAsync(content.Key));
|
||||
|
||||
void VerifyUpdate(IContent? updatedContent)
|
||||
{
|
||||
Assert.IsNotNull(updatedContent);
|
||||
Assert.AreEqual("Updated Name", updatedContent.Name);
|
||||
Assert.AreEqual("The updated title", updatedContent.GetValue<string>("title"));
|
||||
Assert.AreEqual(null, updatedContent.GetValue<string>("text"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Update_With_Variant_Property_Value_For_Invariant_Content()
|
||||
{
|
||||
var content = await CreateInvariantContent();
|
||||
|
||||
var updateModel = new ContentUpdateModel
|
||||
{
|
||||
InvariantName = "Updated Name",
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "title", Value = "The updated title" },
|
||||
},
|
||||
Variants = new[]
|
||||
{
|
||||
new VariantModel
|
||||
{
|
||||
Culture = "en-US",
|
||||
Name = "Updated English Name",
|
||||
Properties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "text", Value = "The updated text" }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.UpdateAsync(content, updateModel);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.ContentTypeCultureVarianceMismatch, result.Status);
|
||||
|
||||
// re-get and validate
|
||||
content = await ContentEditingService.GetAsync(content.Key);
|
||||
Assert.IsNotNull(content);
|
||||
Assert.AreEqual("Initial Name", content.Name);
|
||||
Assert.AreEqual("The initial title", content.GetValue<string>("title"));
|
||||
Assert.AreEqual("The initial text", content.GetValue<string>("text"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Cannot_Update_With_Invariant_Property_Value_For_Variant_Content()
|
||||
{
|
||||
var content = await CreateVariantContent();
|
||||
|
||||
var updateModel = new ContentUpdateModel
|
||||
{
|
||||
InvariantName = "Updated Name",
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" },
|
||||
new PropertyValueModel { Alias = "variantTitle", Value = "The updated variant title" }
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.UpdateAsync(content, updateModel);
|
||||
Assert.IsFalse(result.Success);
|
||||
Assert.AreEqual(ContentEditingOperationStatus.PropertyTypeNotFound, result.Status);
|
||||
Assert.IsNotNull(result.Result);
|
||||
|
||||
// re-get and validate
|
||||
content = await ContentEditingService.GetAsync(content.Key);
|
||||
Assert.IsNotNull(content);
|
||||
Assert.AreEqual("Initial English Name", content.GetCultureName("en-US"));
|
||||
Assert.AreEqual("The initial invariant title", content.GetValue<string>("invariantTitle"));
|
||||
Assert.AreEqual("The initial English title", content.GetValue<string>("variantTitle", "en-US"));
|
||||
Assert.AreEqual("The initial Danish title", content.GetValue<string>("variantTitle", "da-DK"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.ContentEditing;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement;
|
||||
using Umbraco.Cms.Tests.Common.Builders;
|
||||
using Umbraco.Cms.Tests.Common.Builders.Extensions;
|
||||
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,
|
||||
PublishedRepositoryEvents = true,
|
||||
WithApplication = true)]
|
||||
public partial class ContentEditingServiceTests : UmbracoIntegrationTestWithContent
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup() => ContentRepositoryBase.ThrowOnWarning = true;
|
||||
|
||||
private ITemplateService TemplateService => GetRequiredService<ITemplateService>();
|
||||
|
||||
private ILanguageService LanguageService => GetRequiredService<ILanguageService>();
|
||||
|
||||
private IContentEditingService ContentEditingService => GetRequiredService<IContentEditingService>();
|
||||
|
||||
private IContentType CreateInvariantContentType(params ITemplate[] templates)
|
||||
{
|
||||
var contentTypeBuilder = new ContentTypeBuilder()
|
||||
.WithAlias("invariantTest")
|
||||
.WithName("Invariant Test")
|
||||
.WithContentVariation(ContentVariation.Nothing)
|
||||
.AddPropertyType()
|
||||
.WithAlias("title")
|
||||
.WithName("Title")
|
||||
.WithVariations(ContentVariation.Nothing)
|
||||
.Done()
|
||||
.AddPropertyType()
|
||||
.WithAlias("text")
|
||||
.WithName("Text")
|
||||
.WithVariations(ContentVariation.Nothing)
|
||||
.Done();
|
||||
|
||||
foreach (var template in templates)
|
||||
{
|
||||
contentTypeBuilder
|
||||
.AddAllowedTemplate()
|
||||
.WithId(template.Id)
|
||||
.WithAlias(template.Alias)
|
||||
.WithName(template.Name ?? template.Alias)
|
||||
.Done();
|
||||
}
|
||||
|
||||
if (templates.Any())
|
||||
{
|
||||
contentTypeBuilder.WithDefaultTemplateId(templates.First().Id);
|
||||
}
|
||||
|
||||
var contentType = contentTypeBuilder.Build();
|
||||
contentType.AllowedAsRoot = true;
|
||||
ContentTypeService.Save(contentType);
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
private async Task<IContentType> CreateVariantContentType()
|
||||
{
|
||||
var language = new LanguageBuilder()
|
||||
.WithCultureInfo("da-DK")
|
||||
.Build();
|
||||
await LanguageService.CreateAsync(language);
|
||||
|
||||
var contentType = new ContentTypeBuilder()
|
||||
.WithAlias("cultureVariationTest")
|
||||
.WithName("Culture Variation Test")
|
||||
.WithContentVariation(ContentVariation.Culture)
|
||||
.AddPropertyType()
|
||||
.WithAlias("variantTitle")
|
||||
.WithName("Variant Title")
|
||||
.WithVariations(ContentVariation.Culture)
|
||||
.Done()
|
||||
.AddPropertyType()
|
||||
.WithAlias("invariantTitle")
|
||||
.WithName("Invariant Title")
|
||||
.WithVariations(ContentVariation.Nothing)
|
||||
.Done()
|
||||
.Build();
|
||||
contentType.AllowedAsRoot = true;
|
||||
ContentTypeService.Save(contentType);
|
||||
return contentType;
|
||||
}
|
||||
|
||||
private async Task<IContent> CreateInvariantContent(params ITemplate[] templates)
|
||||
{
|
||||
var contentType = CreateInvariantContentType(templates);
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantName = "Initial Name",
|
||||
TemplateKey = templates.FirstOrDefault()?.Key,
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "title", Value = "The initial title" },
|
||||
new PropertyValueModel { Alias = "text", Value = "The initial text" }
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
Assert.IsTrue(result.Success);
|
||||
return result.Result!;
|
||||
}
|
||||
|
||||
private async Task<IContent> CreateVariantContent()
|
||||
{
|
||||
var contentType = await CreateVariantContentType();
|
||||
|
||||
var createModel = new ContentCreateModel
|
||||
{
|
||||
ContentTypeKey = contentType.Key,
|
||||
ParentKey = Constants.System.RootKey,
|
||||
InvariantProperties = new[]
|
||||
{
|
||||
new PropertyValueModel { Alias = "invariantTitle", Value = "The initial invariant title" }
|
||||
},
|
||||
Variants = new []
|
||||
{
|
||||
new VariantModel
|
||||
{
|
||||
Culture = "en-US",
|
||||
Name = "Initial English Name",
|
||||
Properties = new []
|
||||
{
|
||||
new PropertyValueModel { Alias = "variantTitle", Value = "The initial English title" }
|
||||
}
|
||||
},
|
||||
new VariantModel
|
||||
{
|
||||
Culture = "da-DK",
|
||||
Name = "Initial Danish Name",
|
||||
Properties = new []
|
||||
{
|
||||
new PropertyValueModel { Alias = "variantTitle", Value = "The initial Danish title" }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var result = await ContentEditingService.CreateAsync(createModel);
|
||||
Assert.IsTrue(result.Success);
|
||||
return result.Result!;
|
||||
}
|
||||
}
|
||||
@@ -49,5 +49,17 @@
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Umbraco.Web.BackOffice\UrlAndDomains\package.xml" />
|
||||
<Content Include="appsettings.Tests.json" CopyToOutputDirectory="PreserveNewest" />
|
||||
<Compile Update="Umbraco.Infrastructure\Services\ContentEditingServiceTests.Create.cs">
|
||||
<DependentUpon>ContentEditingServiceTests.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Umbraco.Infrastructure\Services\ContentEditingServiceTests.Delete.cs">
|
||||
<DependentUpon>ContentEditingServiceTests.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Umbraco.Infrastructure\Services\ContentEditingServiceTests.Get.cs">
|
||||
<DependentUpon>ContentEditingServiceTests.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Umbraco.Infrastructure\Services\ContentEditingServiceTests.Update.cs">
|
||||
<DependentUpon>ContentEditingServiceTests.cs</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user