Files
Umbraco-CMS/tests/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/ContentControllerTests.cs
Bjarke Berg b0a4a92f57 ContentVersion cleanup backoffice UI (#11637) (#11644)
* ContentVersion cleanup backoffice UI (#11637)

* init rollback ui prototype

* add busy state to button, deselect version, add pagination status

* add localisation

* style current version

* disable rollback button when nothing is selected

* stop click event

* Endpoints for paginated content versions.
Light on tests, tight on time.

* Endpoints to "pin" content versions

* camel case json output.
Not sure why json formatter not set for controller, bit risky to add it now

* wire up paging

* wire up pin/unpin

* rename getPagedRollbackVersions to getPagedContentVersions

* prevent selection of current version and current draft

* add current draft and current version to UI

* remove pointer if the row is not selectable

* Improve warning for globally disabled cleanup feature.

* Fix current loses prevent cleanup state on publish.

* Added umbracoLog audit entries for "pin" / "unpin"

* Match v9 defaults for keepVersions settings

* Fix - losing preventCleanup on save current with content changes

* update pin/unpin button labels

* fix pagination bug

* add missing "

* always send culture when a doc type can vary

Co-authored-by: Mads Rasmussen <madsr@hey.com>
# Conflicts:
#	src/Umbraco.Core/ContentEditing/ContentVersionMetaViewModel.cs
#	src/Umbraco.Core/Models/HistoricContentVersionMeta.cs
#	src/Umbraco.Infrastructure/Services/Implement/ContentService.cs
#	src/Umbraco.Tests/Persistence/Repositories/DocumentVersionRepository_Tests_Integration.cs
#	src/Umbraco.Tests/Services/ContentVersionCleanupService_Tests_UnitTests.cs
#	src/Umbraco.Web.BackOffice/Controllers/ContentController.cs
#	src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js
#	src/Umbraco.Web.UI/config/umbracoSettings.Release.config
#	src/Umbraco.Web.UI/umbraco/config/lang/en.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
#	src/Umbraco.Web/Umbraco.Web.csproj

* Added tests

* Misc - missed translation update

* Bugfix - DocumentVersionRepository.Get should not join culture variation

* Bugfix - Missing write lock

* Removed unnecessary view model

* Misc - kill some warnings

* Misc - Kill some more warnings

* Fixed cypress rollback test

* Bugfix - Policy returns items to delete not items to keep.
Switch to inverse behavior.

# Conflicts:
#	src/Umbraco.Tests/Services/DefaultContentVersionCleanupPolicy_Tests_UnitTests.cs

Co-authored-by: Paul Johnson <pmj@umbraco.com>
2021-11-16 13:04:31 +01:00

275 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Actions;
using Umbraco.Cms.Core.Dictionary;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Tests.Common.Builders.Extensions;
using Umbraco.Cms.Web.BackOffice.Controllers;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Controllers
{
[TestFixture]
public class ContentControllerTests
{
[Test]
public void Root_Node_With_Domains_Causes_No_Warning()
{
// Setup domain service
var domainServiceMock = new Mock<IDomainService>();
domainServiceMock.Setup(x => x.GetAssignedDomains(1060, It.IsAny<bool>()))
.Returns(new []{new UmbracoDomain("/", "da-dk"), new UmbracoDomain("/en", "en-us")});
// Create content, we need to specify and ID in order to be able to configure domain service
Content rootNode = new ContentBuilder()
.WithContentType(CreateContentType())
.WithId(1060)
.AddContentCultureInfosCollection()
.AddCultureInfos()
.WithCultureIso("da-dk")
.Done()
.AddCultureInfos()
.WithCultureIso("en-us")
.Done()
.Done()
.Build();
var culturesPublished = new []{ "en-us", "da-dk" };
var notifications = new SimpleNotificationModel();
ContentController contentController = CreateContentController(domainServiceMock.Object);
contentController.AddDomainWarnings(rootNode, culturesPublished, notifications);
Assert.IsEmpty(notifications.Notifications);
}
[Test]
public void Node_With_Single_Published_Culture_Causes_No_Warning()
{
var domainServiceMock = new Mock<IDomainService>();
domainServiceMock.Setup(x => x.GetAssignedDomains(It.IsAny<int>(), It.IsAny<bool>()))
.Returns(Enumerable.Empty<IDomain>());
Content rootNode = new ContentBuilder()
.WithContentType(CreateContentType())
.WithId(1060)
.AddContentCultureInfosCollection()
.AddCultureInfos()
.WithCultureIso("da-dk")
.Done()
.Done()
.Build();
var culturesPublished = new []{"da-dk" };
var notifications = new SimpleNotificationModel();
ContentController contentController = CreateContentController(domainServiceMock.Object);
contentController.AddDomainWarnings(rootNode, culturesPublished, notifications);
Assert.IsEmpty(notifications.Notifications);
}
[Test]
public void Root_Node_Without_Domains_Causes_SingleWarning()
{
var domainServiceMock = new Mock<IDomainService>();
domainServiceMock.Setup(x => x.GetAssignedDomains(It.IsAny<int>(), It.IsAny<bool>()))
.Returns(Enumerable.Empty<IDomain>());
Content rootNode = new ContentBuilder()
.WithContentType(CreateContentType())
.WithId(1060)
.AddContentCultureInfosCollection()
.AddCultureInfos()
.WithCultureIso("da-dk")
.Done()
.AddCultureInfos()
.WithCultureIso("en-us")
.Done()
.Done()
.Build();
var culturesPublished = new []{ "en-us", "da-dk" };
var notifications = new SimpleNotificationModel();
ContentController contentController = CreateContentController(domainServiceMock.Object);
contentController.AddDomainWarnings(rootNode, culturesPublished, notifications);
Assert.AreEqual(1, notifications.Notifications.Count(x => x.NotificationType == NotificationStyle.Warning));
}
[Test]
public void One_Warning_Per_Culture_Being_Published()
{
var domainServiceMock = new Mock<IDomainService>();
domainServiceMock.Setup(x => x.GetAssignedDomains(It.IsAny<int>(), It.IsAny<bool>()))
.Returns(new []{new UmbracoDomain("/", "da-dk")});
Content rootNode = new ContentBuilder()
.WithContentType(CreateContentType())
.WithId(1060)
.AddContentCultureInfosCollection()
.AddCultureInfos()
.WithCultureIso("da-dk")
.Done()
.AddCultureInfos()
.WithCultureIso("en-us")
.Done()
.Done()
.Build();
var culturesPublished = new []{ "en-us", "da-dk", "nl-bk", "se-sv" };
var notifications = new SimpleNotificationModel();
ContentController contentController = CreateContentController(domainServiceMock.Object);
contentController.AddDomainWarnings(rootNode, culturesPublished, notifications);
Assert.AreEqual(3, notifications.Notifications.Count(x => x.NotificationType == NotificationStyle.Warning));
}
[Test]
public void Ancestor_Domains_Counts()
{
var rootId = 1060;
var level1Id = 1061;
var level2Id = 1062;
var level3Id = 1063;
var domainServiceMock = new Mock<IDomainService>();
domainServiceMock.Setup(x => x.GetAssignedDomains(rootId, It.IsAny<bool>()))
.Returns(new[] { new UmbracoDomain("/", "da-dk") });
domainServiceMock.Setup(x => x.GetAssignedDomains(level1Id, It.IsAny<bool>()))
.Returns(new[] { new UmbracoDomain("/en", "en-us") });
domainServiceMock.Setup(x => x.GetAssignedDomains(level2Id, It.IsAny<bool>()))
.Returns(new[] { new UmbracoDomain("/se", "se-sv"), new UmbracoDomain("/nl", "nl-bk") });
Content level3Node = new ContentBuilder()
.WithContentType(CreateContentType())
.WithId(level3Id)
.WithPath($"-1,{rootId},{level1Id},{level2Id},{level3Id}")
.AddContentCultureInfosCollection()
.AddCultureInfos()
.WithCultureIso("da-dk")
.Done()
.AddCultureInfos()
.WithCultureIso("en-us")
.Done()
.AddCultureInfos()
.WithCultureIso("se-sv")
.Done()
.AddCultureInfos()
.WithCultureIso("nl-bk")
.Done()
.AddCultureInfos()
.WithCultureIso("de-de")
.Done()
.Done()
.Build();
var culturesPublished = new []{ "en-us", "da-dk", "nl-bk", "se-sv", "de-de" };
ContentController contentController = CreateContentController(domainServiceMock.Object);
var notifications = new SimpleNotificationModel();
contentController.AddDomainWarnings(level3Node, culturesPublished, notifications);
// We expect one error because all domains except "de-de" is registered somewhere in the ancestor path
Assert.AreEqual(1, notifications.Notifications.Count(x => x.NotificationType == NotificationStyle.Warning));
}
[Test]
public void Only_Warns_About_Cultures_Being_Published()
{
var domainServiceMock = new Mock<IDomainService>();
domainServiceMock.Setup(x => x.GetAssignedDomains(It.IsAny<int>(), It.IsAny<bool>()))
.Returns(new []{new UmbracoDomain("/", "da-dk")});
Content rootNode = new ContentBuilder()
.WithContentType(CreateContentType())
.WithId(1060)
.AddContentCultureInfosCollection()
.AddCultureInfos()
.WithCultureIso("da-dk")
.Done()
.AddCultureInfos()
.WithCultureIso("en-us")
.Done()
.AddCultureInfos()
.WithCultureIso("se-sv")
.Done()
.AddCultureInfos()
.WithCultureIso("de-de")
.Done()
.Done()
.Build();
var culturesPublished = new []{ "en-us", "se-sv" };
var notifications = new SimpleNotificationModel();
ContentController contentController = CreateContentController(domainServiceMock.Object);
contentController.AddDomainWarnings(rootNode, culturesPublished, notifications);
// We only get two errors, one for each culture being published, so no errors from previously published cultures.
Assert.AreEqual(2, notifications.Notifications.Count(x => x.NotificationType == NotificationStyle.Warning));
}
private ContentController CreateContentController(IDomainService domainService)
{
// We have to configure ILocalizedTextService to return a new string every time Localize is called
// Otherwise it won't add the notification because it skips dupes
var localizedTextServiceMock = new Mock<ILocalizedTextService>();
localizedTextServiceMock.Setup(x => x.Localize(It.IsAny<string>(),
It.IsAny<string>(), It.IsAny<CultureInfo>(), It.IsAny<IDictionary<string, string>>()))
.Returns(() => Guid.NewGuid().ToString());
var controller = new ContentController(
Mock.Of<ICultureDictionary>(),
NullLoggerFactory.Instance,
Mock.Of<IShortStringHelper>(),
Mock.Of<IEventMessagesFactory>(),
localizedTextServiceMock.Object,
new PropertyEditorCollection(new DataEditorCollection(() => null)),
Mock.Of<IContentService>(),
Mock.Of<IUserService>(),
Mock.Of<IBackOfficeSecurityAccessor>(),
Mock.Of<IContentTypeService>(),
Mock.Of<IUmbracoMapper>(),
Mock.Of<IPublishedUrlProvider>(),
domainService,
Mock.Of<IDataTypeService>(),
Mock.Of<ILocalizationService>(),
Mock.Of<IFileService>(),
Mock.Of<INotificationService>(),
new ActionCollection(() => null),
Mock.Of<ISqlContext>(),
Mock.Of<IJsonSerializer>(),
Mock.Of<IScopeProvider>(),
Mock.Of<IAuthorizationService>(),
Mock.Of<IContentVersionService>()
);
return controller;
}
private IContentType CreateContentType() =>
new ContentTypeBuilder().WithContentVariation(ContentVariation.Culture).Build();
}
}