* Property level validation for content - initial implementation * Always succeed create/update regardless of property level validation errors * Move old complex editor validation classes to Web.BackOffice so they will be deleted * Include operation status and property validation errors in ProblemDetails * Refactor property validation to its own service(s) * Make the problem details builder a little more generic towards extensions * Validation for item and branch publish * Moved malplaced test * Get rid of a TODO * Integration tests for content validation service * Simplify validation service * Add missing response types to create and update for document and media * Remove test that no longer applies * Use "errors" for model validation errors (property validation errors) * Split create/update and validation into their own endpoints * Fix forward merge * Correct wrong assumption for missing properties * Remove localization from validation error messages - decreases dependencies, adds a lot of obsolete constructors * Reuse existing validation service + support custom error messages * Fix merge errors * Review comments
123 lines
5.1 KiB
C#
123 lines
5.1 KiB
C#
using NUnit.Framework;
|
|
using Umbraco.Cms.Core;
|
|
using Umbraco.Cms.Core.Events;
|
|
using Umbraco.Cms.Core.Models;
|
|
using Umbraco.Cms.Core.Notifications;
|
|
using Umbraco.Cms.Core.Services;
|
|
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)]
|
|
public partial class ContentPublishingServiceTests : UmbracoIntegrationTestWithContent
|
|
{
|
|
private IContentPublishingService ContentPublishingService => GetRequiredService<IContentPublishingService>();
|
|
|
|
private static readonly string[] _allCultures = new[] { "*" };
|
|
|
|
[SetUp]
|
|
public void SetupTest()
|
|
{
|
|
ContentNotificationHandler.PublishingContent = null;
|
|
ContentNotificationHandler.UnpublishingContent = null;
|
|
}
|
|
|
|
private async Task<Content> CreateInvalidContent(IContent? parent = null)
|
|
{
|
|
var template = TemplateBuilder.CreateTextPageTemplate();
|
|
await TemplateService.CreateAsync(template, Constants.Security.SuperUserKey);
|
|
|
|
// create a new content type and allow the default content type as child
|
|
var contentType = ContentTypeBuilder.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type", mandatoryProperties: true, defaultTemplateId: template.Id);
|
|
contentType.AllowedAsRoot = true;
|
|
contentType.AllowedContentTypes = new[] { new ContentTypeSort(ContentType.Key, 0, ContentType.Alias) };
|
|
ContentTypeService.Save(contentType);
|
|
|
|
// allow the new content type as child to the default content type
|
|
ContentType.AllowedContentTypes = new[] { new ContentTypeSort(contentType.Key, 0, contentType.Alias) };
|
|
ContentTypeService.Save(ContentType);
|
|
|
|
var content = ContentBuilder.CreateSimpleContent(contentType, "Invalid Content", parent?.Id ?? Constants.System.Root);
|
|
content.SetValue("title", string.Empty);
|
|
content.SetValue("bodyText", string.Empty);
|
|
content.SetValue("author", string.Empty);
|
|
ContentService.Save(content);
|
|
|
|
return content;
|
|
}
|
|
|
|
private async Task<(ILanguage LangEn, ILanguage LangDa, IContentType contentType)> SetupVariantTest(bool englishIsMandatoryLanguage = false)
|
|
{
|
|
var langEn = (await LanguageService.GetAsync("en-US"))!;
|
|
if (englishIsMandatoryLanguage)
|
|
{
|
|
langEn.IsMandatory = true;
|
|
await LanguageService.UpdateAsync(langEn, Constants.Security.SuperUserKey);
|
|
}
|
|
|
|
var langDa = new LanguageBuilder()
|
|
.WithCultureInfo("da-DK")
|
|
.Build();
|
|
await LanguageService.CreateAsync(langDa, Constants.Security.SuperUserKey);
|
|
|
|
var template = TemplateBuilder.CreateTextPageTemplate();
|
|
await TemplateService.CreateAsync(template, Constants.Security.SuperUserKey);
|
|
|
|
var key = Guid.NewGuid();
|
|
var contentType = new ContentTypeBuilder()
|
|
.WithAlias("variantContent")
|
|
.WithName("Variant Content")
|
|
.WithKey(key)
|
|
.WithContentVariation(ContentVariation.Culture)
|
|
.AddAllowedContentType()
|
|
.WithKey(key)
|
|
.WithAlias("variantContent")
|
|
.Done()
|
|
.AddPropertyGroup()
|
|
.WithAlias("content")
|
|
.WithName("Content")
|
|
.WithSupportsPublishing(true)
|
|
.AddPropertyType()
|
|
.WithAlias("title")
|
|
.WithName("Title")
|
|
.WithVariations(ContentVariation.Culture)
|
|
.WithMandatory(true)
|
|
.Done()
|
|
.Done()
|
|
.Build();
|
|
|
|
contentType.AllowedAsRoot = true;
|
|
await ContentTypeService.SaveAsync(contentType, Constants.Security.SuperUserKey);
|
|
|
|
return (langEn, langDa, contentType);
|
|
}
|
|
|
|
protected override void CustomTestSetup(IUmbracoBuilder builder)
|
|
=> builder
|
|
.AddNotificationHandler<ContentPublishingNotification, ContentNotificationHandler>()
|
|
.AddNotificationHandler<ContentUnpublishingNotification, ContentNotificationHandler>();
|
|
|
|
private void VerifyIsPublished(Guid key) => Assert.IsTrue(ContentService.GetById(key)!.Published);
|
|
|
|
private void VerifyIsNotPublished(Guid key) => Assert.IsFalse(ContentService.GetById(key)!.Published);
|
|
|
|
private ILanguageService LanguageService => GetRequiredService<ILanguageService>();
|
|
|
|
private ITemplateService TemplateService => GetRequiredService<ITemplateService>();
|
|
|
|
private class ContentNotificationHandler : INotificationHandler<ContentPublishingNotification>, INotificationHandler<ContentUnpublishingNotification>
|
|
{
|
|
public static Action<ContentPublishingNotification>? PublishingContent { get; set; }
|
|
|
|
public static Action<ContentUnpublishingNotification>? UnpublishingContent { get; set; }
|
|
|
|
public void Handle(ContentPublishingNotification notification) => PublishingContent?.Invoke(notification);
|
|
|
|
public void Handle(ContentUnpublishingNotification notification) => UnpublishingContent?.Invoke(notification);
|
|
}
|
|
}
|