Add tests for content editing service

This commit is contained in:
kjac
2023-02-23 07:30:16 +01:00
parent 95ec06e119
commit 767e3cd9eb
10 changed files with 931 additions and 9 deletions

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -10,7 +10,7 @@ public enum ContentEditingOperationStatus
ParentNotFound,
NotAllowed,
TemplateNotFound,
TemplateNotAllowed,
PropertyTypeNotFound,
Unknown,
TemplateNotAllowed
Unknown
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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"));
}
}

View File

@@ -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!;
}
}

View File

@@ -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>