Merge branch 'main' into v17/dev

# Conflicts:
#	src/Umbraco.Core/Services/DataTypeService.cs
This commit is contained in:
Andy Butland
2025-09-15 13:36:37 +02:00
80 changed files with 4314 additions and 485 deletions

View File

@@ -81,6 +81,9 @@ internal sealed class PublishContentTypeFactoryTest : UmbracoIntegrationTest
{
var dataType = new DataTypeBuilder()
.WithId(0)
.AddEditor()
.WithAlias(Constants.PropertyEditors.Aliases.TextBox)
.Done()
.Build();
dataType.EditorUiAlias = "NotUpdated";
var dataTypeCreateResult = await DataTypeService.CreateAsync(dataType, Constants.Security.SuperUserKey);

View File

@@ -690,7 +690,7 @@ internal sealed class ContentServiceTests : UmbracoIntegrationTestWithContent
}
[Test]
public void Can_Get_Scheduled_Content_Keys()
public void Can_Get_Content_Schedules_By_Keys()
{
// Arrange
var root = ContentService.GetById(Textpage.Id);
@@ -701,11 +701,12 @@ internal sealed class ContentServiceTests : UmbracoIntegrationTestWithContent
ContentService.Publish(content, content.AvailableCultures.ToArray());
// Act
var keys = ContentService.GetScheduledContentKeys([Textpage.Key, Subpage.Key, Subpage2.Key]).ToList();
var keys = ContentService.GetContentSchedulesByIds([Textpage.Key, Subpage.Key, Subpage2.Key]).ToList();
// Assert
Assert.AreEqual(1, keys.Count);
Assert.AreEqual(Subpage.Key, keys.First());
Assert.AreEqual(keys[0].Key, Subpage.Id);
Assert.AreEqual(keys[0].Value.First().Id, contentSchedule.FullSchedule.First().Id);
}
[Test]

View File

@@ -1,3 +1,4 @@
using System.Text.Json.Nodes;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
@@ -19,29 +20,41 @@ internal sealed class MediaEditingServiceTests : UmbracoIntegrationTest
protected IMediaType ImageMediaType { get; set; }
protected IMediaType ArticleMediaType { get; set; }
[SetUp]
public async Task Setup()
{
ImageMediaType = MediaTypeService.Get(Constants.Conventions.MediaTypes.Image);
ArticleMediaType = MediaTypeService.Get(Constants.Conventions.MediaTypes.ArticleAlias);
}
[Test]
public async Task Cannot_Create_Media_With_Mandatory_Property()
public async Task Cannot_Create_Media_With_Mandatory_File_Property_Without_Providing_File()
{
var imageModel = CreateMediaCreateModel("Image", new Guid(), ImageMediaType.Key);
var imageModel = CreateMediaCreateModel("Image", Guid.NewGuid(), ImageMediaType.Key);
var imageCreateAttempt = await MediaEditingService.CreateAsync(imageModel, Constants.Security.SuperUserKey);
// Assert
Assert.IsFalse(imageCreateAttempt.Success);
Assert.AreEqual(ContentEditingOperationStatus.PropertyValidationError, imageCreateAttempt.Status);
}
[Test]
public async Task Can_Create_Media_Without_Mandatory_Property()
public async Task Can_Create_Media_With_Mandatory_File_Property_With_File_Provided()
{
ImageMediaType.PropertyTypes.First(x => x.Alias == "umbracoFile").Mandatory = false;
var imageModel = CreateMediaCreateModelWithFile("Image", Guid.NewGuid(), ArticleMediaType.Key);
var imageCreateAttempt = await MediaEditingService.CreateAsync(imageModel, Constants.Security.SuperUserKey);
Assert.IsTrue(imageCreateAttempt.Success);
Assert.AreEqual(ContentEditingOperationStatus.Success, imageCreateAttempt.Status);
}
[Test]
public async Task Can_Create_Media_With_Optional_File_Property_Without_Providing_File()
{
ImageMediaType.PropertyTypes.First(x => x.Alias == Constants.Conventions.Media.File).Mandatory = false;
MediaTypeService.Save(ImageMediaType);
var imageModel = CreateMediaCreateModel("Image", new Guid(), ImageMediaType.Key);
var imageModel = CreateMediaCreateModel("Image", Guid.NewGuid(), ImageMediaType.Key);
var imageCreateAttempt = await MediaEditingService.CreateAsync(imageModel, Constants.Security.SuperUserKey);
// Assert
@@ -49,12 +62,57 @@ internal sealed class MediaEditingServiceTests : UmbracoIntegrationTest
Assert.AreEqual(ContentEditingOperationStatus.Success, imageCreateAttempt.Status);
}
private MediaCreateModel CreateMediaCreateModel(string name, Guid key, Guid mediaTypeKey)
[Test]
public async Task Can_Update_Media_With_Mandatory_File_Property_With_File_Provided()
{
Guid articleKey = Guid.NewGuid();
var articleModel = CreateMediaCreateModelWithFile("Article", articleKey, ArticleMediaType.Key);
var articleCreateAttempt = await MediaEditingService.CreateAsync(articleModel, Constants.Security.SuperUserKey);
Assert.IsTrue(articleCreateAttempt.Success);
var updateModel = new MediaUpdateModel
{
Properties =
[
new PropertyValueModel
{
Alias = Constants.Conventions.Media.File,
Value = new JsonObject
{
{ "src", string.Empty },
},
}
],
Variants = articleModel.Variants,
};
var articleUpdateAttempt = await MediaEditingService.ValidateUpdateAsync(articleKey, updateModel);
Assert.IsFalse(articleUpdateAttempt.Success);
Assert.AreEqual(ContentEditingOperationStatus.PropertyValidationError, articleUpdateAttempt.Status);
}
private static MediaCreateModel CreateMediaCreateModel(string name, Guid key, Guid mediaTypeKey)
=> new()
{
ContentTypeKey = mediaTypeKey,
ParentKey = Constants.System.RootKey,
Variants = [new () { Name = name }],
Variants = [new() { Name = name }],
Key = key,
};
private static MediaCreateModel CreateMediaCreateModelWithFile(string name, Guid key, Guid mediaTypeKey)
{
var model = CreateMediaCreateModel(name, key, mediaTypeKey);
model.Properties = [
new PropertyValueModel
{
Alias = Constants.Conventions.Media.File,
Value = new JsonObject
{
{ "src", "reference-to-file" },
},
}
];
return model;
}
}

View File

@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
@@ -103,7 +104,14 @@ internal sealed class DocumentRepositoryTest : UmbracoIntegrationTest
var ctRepository = CreateRepository(scopeAccessor, out contentTypeRepository, out TemplateRepository tr);
var editors = new PropertyEditorCollection(new DataEditorCollection(() => Enumerable.Empty<IDataEditor>()));
dtdRepository = new DataTypeRepository(scopeAccessor, appCaches, editors, LoggerFactory.CreateLogger<DataTypeRepository>(), LoggerFactory, ConfigurationEditorJsonSerializer);
dtdRepository = new DataTypeRepository(
scopeAccessor,
appCaches,
editors,
LoggerFactory.CreateLogger<DataTypeRepository>(),
LoggerFactory,
ConfigurationEditorJsonSerializer,
Services.GetRequiredService<IDataValueEditorFactory>());
return ctRepository;
}

View File

@@ -1,7 +1,6 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Linq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
@@ -487,4 +486,36 @@ internal sealed class DataTypeServiceTests : UmbracoIntegrationTest
Assert.AreEqual("bodyText", secondResult.NodeAlias);
Assert.AreEqual("Body text", secondResult.NodeName);
}
[Test]
public async Task Gets_MissingPropertyEditor_When_Editor_NotFound()
{
// Arrange
IDataType? dataType = (await DataTypeService.CreateAsync(
new DataType(new TestEditor(DataValueEditorFactory), ConfigurationEditorJsonSerializer)
{
Name = "Test Missing Editor",
DatabaseType = ValueStorageType.Ntext,
},
Constants.Security.SuperUserKey)).Result;
Assert.IsNotNull(dataType);
// Act
IDataType? actual = await DataTypeService.GetAsync(dataType.Key);
// Assert
Assert.NotNull(actual);
Assert.AreEqual(dataType.Key, actual.Key);
Assert.IsAssignableFrom(typeof(MissingPropertyEditor), actual.Editor);
Assert.AreEqual("Test Editor", actual.EditorAlias, "The alias should be the same as the original editor");
Assert.AreEqual("Umb.PropertyEditorUi.Missing", actual.EditorUiAlias, "The editor UI alias should be the Missing Editor UI");
}
private class TestEditor : DataEditor
{
public TestEditor(IDataValueEditorFactory dataValueEditorFactory)
: base(dataValueEditorFactory) =>
Alias = "Test Editor";
}
}

View File

@@ -1,16 +1,15 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.Persistence.Relations;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Tests.Common.Testing;
using Umbraco.Cms.Tests.Integration.Testing;
using Umbraco.Extensions;
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services;
@@ -32,6 +31,13 @@ internal sealed class RelationServiceTests : UmbracoIntegrationTest
private IRelationService RelationService => GetRequiredService<IRelationService>();
protected override void CustomTestSetup(IUmbracoBuilder builder)
{
base.CustomTestSetup(builder);
builder
.AddNotificationHandler<ContentSavedNotification, ContentRelationsUpdate>();
}
[Test]
public void Get_Paged_Relations_By_Relation_Type()
{

View File

@@ -3,7 +3,9 @@ using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.Persistence.Relations;
using Umbraco.Cms.Tests.Common.Attributes;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Tests.Common.Testing;
@@ -29,11 +31,12 @@ internal sealed class TrackRelationsTests : UmbracoIntegrationTestWithContent
private IRelationService RelationService => GetRequiredService<IRelationService>();
// protected override void CustomTestSetup(IUmbracoBuilder builder)
// {
// base.CustomTestSetup(builder);
// builder.AddNuCache();
// }
protected override void CustomTestSetup(IUmbracoBuilder builder)
{
base.CustomTestSetup(builder);
builder
.AddNotificationHandler<ContentSavedNotification, ContentRelationsUpdate>();
}
[Test]
[LongRunning]
@@ -89,6 +92,5 @@ internal sealed class TrackRelationsTests : UmbracoIntegrationTestWithContent
Assert.AreEqual(c1.Id, relations[2].ChildId);
Assert.AreEqual(Constants.Conventions.RelationTypes.RelatedMemberAlias, relations[3].RelationType.Alias);
Assert.AreEqual(member.Id, relations[3].ChildId);
}
}

View File

@@ -3,7 +3,9 @@
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.Persistence.Relations;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Tests.Common.Builders.Extensions;
using Umbraco.Cms.Tests.Common.Testing;
@@ -25,6 +27,13 @@ internal class TrackedReferencesServiceTests : UmbracoIntegrationTest
private IContentType ContentType { get; set; }
protected override void CustomTestSetup(IUmbracoBuilder builder)
{
base.CustomTestSetup(builder);
builder
.AddNotificationHandler<ContentSavedNotification, ContentRelationsUpdate>();
}
[SetUp]
public void Setup() => CreateTestData();

View File

@@ -11,116 +11,76 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Cms.Api.Management.Services.Signs;
internal class HasPendingChangesSignProviderTests
{
[Test]
public void HasPendingChangesSignProvider_Can_Provide_Document_Tree_Signs()
public void HasPendingChangesSignProvider_Can_Provide_Variant_Item_Signs()
{
var sut = new HasPendingChangesSignProvider();
Assert.IsTrue(sut.CanProvideSigns<DocumentTreeItemResponseModel>());
Assert.IsTrue(sut.CanProvideSigns<DocumentVariantItemResponseModel>());
}
[Test]
public void HasPendingChangesSignProvider_Can_Provide_Document_Collection_Signs()
public void HasPendingChangesSignProvider_Can_Provide_Variant_Signs()
{
var sut = new HasPendingChangesSignProvider();
Assert.IsTrue(sut.CanProvideSigns<DocumentCollectionResponseModel>());
Assert.IsTrue(sut.CanProvideSigns<DocumentVariantResponseModel>());
}
[Test]
public void HasPendingChangesSignProvider_Can_Provide_Document_Item_Signs()
{
var sut = new HasPendingChangesSignProvider();
Assert.IsTrue(sut.CanProvideSigns<DocumentItemResponseModel>());
}
[Test]
public async Task HasPendingChangesSignProvider_Should_Populate_Document_Tree_Signs()
public async Task HasPendingChangesSignProvider_Should_Populate_Variant_Item_Signs()
{
var sut = new HasPendingChangesSignProvider();
var viewModels = new List<DocumentTreeItemResponseModel>
var variants = new List<DocumentVariantItemResponseModel>
{
new() { Id = Guid.NewGuid() },
new()
{
Id = Guid.NewGuid(), Variants =
[
new()
{
State = DocumentVariantState.PublishedPendingChanges,
Culture = null,
Name = "Test",
},
],
State = DocumentVariantState.PublishedPendingChanges,
Culture = null,
Name = "Test",
},
new()
{
State = DocumentVariantState.Published,
Culture = null,
Name = "Test2",
},
};
await sut.PopulateSignsAsync(viewModels);
await sut.PopulateSignsAsync(variants);
Assert.AreEqual(viewModels[0].Signs.Count(), 0);
Assert.AreEqual(viewModels[1].Signs.Count(), 1);
Assert.AreEqual(variants[0].Signs.Count(), 1);
Assert.AreEqual(variants[1].Signs.Count(), 0);
var signModel = viewModels[1].Signs.First();
var signModel = variants[0].Signs.First();
Assert.AreEqual("Umb.PendingChanges", signModel.Alias);
}
[Test]
public async Task HasPendingChangesSignProvider_Should_Populate_Document_Collection_Signs()
public async Task HasPendingChangesSignProvider_Should_Populate_Variant_Signs()
{
var sut = new HasPendingChangesSignProvider();
var viewModels = new List<DocumentCollectionResponseModel>
var variants = new List<DocumentVariantResponseModel>
{
new() { Id = Guid.NewGuid() },
new()
{
Id = Guid.NewGuid(), Variants =
[
new()
{
State = DocumentVariantState.PublishedPendingChanges,
Culture = null,
Name = "Test",
},
],
State = DocumentVariantState.PublishedPendingChanges,
Culture = null,
Name = "Test",
},
new()
{
State = DocumentVariantState.Published,
Culture = null,
Name = "Test2",
},
};
await sut.PopulateSignsAsync(viewModels);
await sut.PopulateSignsAsync(variants);
Assert.AreEqual(viewModels[0].Signs.Count(), 0);
Assert.AreEqual(viewModels[1].Signs.Count(), 1);
Assert.AreEqual(variants[0].Signs.Count(), 1);
Assert.AreEqual(variants[1].Signs.Count(), 0);
var signModel = viewModels[1].Signs.First();
Assert.AreEqual("Umb.PendingChanges", signModel.Alias);
}
[Test]
public async Task HasPendingChangesSignProvider_Should_Populate_Document_Item_Signs()
{
var sut = new HasPendingChangesSignProvider();
var viewModels = new List<DocumentItemResponseModel>
{
new() { Id = Guid.NewGuid() },
new()
{
Id = Guid.NewGuid(), Variants =
[
new()
{
State = DocumentVariantState.PublishedPendingChanges,
Culture = null,
Name = "Test",
},
],
},
};
await sut.PopulateSignsAsync(viewModels);
Assert.AreEqual(viewModels[0].Signs.Count(), 0);
Assert.AreEqual(viewModels[1].Signs.Count(), 1);
var signModel = viewModels[1].Signs.First();
var signModel = variants[0].Signs.First();
Assert.AreEqual("Umb.PendingChanges", signModel.Alias);
}
}

View File

@@ -1,9 +1,13 @@
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Api.Management.Services.Signs;
using Umbraco.Cms.Api.Management.ViewModels.Content;
using Umbraco.Cms.Api.Management.ViewModels.Document;
using Umbraco.Cms.Api.Management.ViewModels.Document.Collection;
using Umbraco.Cms.Api.Management.ViewModels.Document.Item;
using Umbraco.Cms.Api.Management.ViewModels.Tree;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Entities;
using Umbraco.Cms.Core.Services;
@@ -16,8 +20,9 @@ internal class HasScheduleSignProviderTests
public void HasScheduleSignProvider_Can_Provide_Document_Tree_Signs()
{
var contentServiceMock = new Mock<IContentService>();
var idKeyMapMock = new Mock<IIdKeyMap>();
var sut = new HasScheduleSignProvider(contentServiceMock.Object);
var sut = new HasScheduleSignProvider(contentServiceMock.Object, idKeyMapMock.Object);
Assert.IsTrue(sut.CanProvideSigns<DocumentTreeItemResponseModel>());
}
@@ -25,8 +30,9 @@ internal class HasScheduleSignProviderTests
public void HasScheduleSignProvider_Can_Provide_Document_Collection_Signs()
{
var contentServiceMock = new Mock<IContentService>();
var idKeyMapMock = new Mock<IIdKeyMap>();
var sut = new HasScheduleSignProvider(contentServiceMock.Object);
var sut = new HasScheduleSignProvider(contentServiceMock.Object, idKeyMapMock.Object);
Assert.IsTrue(sut.CanProvideSigns<DocumentCollectionResponseModel>());
}
@@ -34,8 +40,9 @@ internal class HasScheduleSignProviderTests
public void HasScheduleSignProvider_Can_Provide_Document_Item_Signs()
{
var contentServiceMock = new Mock<IContentService>();
var idKeyMapMock = new Mock<IIdKeyMap>();
var sut = new HasScheduleSignProvider(contentServiceMock.Object);
var sut = new HasScheduleSignProvider(contentServiceMock.Object, idKeyMapMock.Object);
Assert.IsTrue(sut.CanProvideSigns<DocumentItemResponseModel>());
}
@@ -47,23 +54,37 @@ internal class HasScheduleSignProviderTests
new() { Key = Guid.NewGuid(), Name = "Item 1" }, new() { Key = Guid.NewGuid(), Name = "Item 2" },
};
var idKeyMapMock = new Mock<IIdKeyMap>();
idKeyMapMock.Setup(x => x.GetIdForKey(entities[0].Key, UmbracoObjectTypes.Document))
.Returns(Attempt.Succeed(1));
idKeyMapMock.Setup(x => x.GetIdForKey(entities[1].Key, UmbracoObjectTypes.Document))
.Returns(Attempt.Succeed(2));
Guid[] keys = entities.Select(x => x.Key).ToArray();
var contentServiceMock = new Mock<IContentService>();
contentServiceMock
.Setup(x => x.GetScheduledContentKeys(It.IsAny<IEnumerable<Guid>>()))
.Returns([entities[1].Key]);
var sut = new HasScheduleSignProvider(contentServiceMock.Object);
.Setup(x => x.GetContentSchedulesByIds(keys))
.Returns(CreateContentSchedules());
var sut = new HasScheduleSignProvider(contentServiceMock.Object, idKeyMapMock.Object);
var variant1 = new DocumentVariantItemResponseModel() { State = DocumentVariantState.Published, Name = "Test1", Culture = "en-EN" };
var variant2 = new DocumentVariantItemResponseModel() { State = DocumentVariantState.Published, Name = "Test1", Culture = "da-DA" };
var variant3 = new DocumentVariantItemResponseModel() { State = DocumentVariantState.PublishedPendingChanges, Name = "Test" };
var viewModels = new List<DocumentTreeItemResponseModel>
{
new() { Id = entities[0].Key }, new() { Id = entities[1].Key },
new() { Id = entities[0].Key, Variants = [variant1, variant2] }, new() { Id = entities[1].Key, Variants = [variant3] },
};
await sut.PopulateSignsAsync(viewModels);
Assert.AreEqual(viewModels[0].Signs.Count(), 0);
Assert.AreEqual(viewModels[1].Signs.Count(), 1);
Assert.AreEqual(viewModels[0].Variants.FirstOrDefault(x => x.Culture == "da-DA").Signs.Count(), 0);
Assert.AreEqual(viewModels[0].Variants.FirstOrDefault(x => x.Culture == "en-EN").Signs.Count(), 1);
Assert.AreEqual(viewModels[1].Variants.First().Signs.Count(), 1);
var signModel = viewModels[1].Signs.First();
var signModel = viewModels[0].Variants.First().Signs.First();
Assert.AreEqual("Umb.ScheduledForPublish", signModel.Alias);
}
@@ -75,23 +96,36 @@ internal class HasScheduleSignProviderTests
new() { Key = Guid.NewGuid(), Name = "Item 1" }, new() { Key = Guid.NewGuid(), Name = "Item 2" },
};
var idKeyMapMock = new Mock<IIdKeyMap>();
idKeyMapMock.Setup(x => x.GetIdForKey(entities[0].Key, UmbracoObjectTypes.Document))
.Returns(Attempt.Succeed(1));
idKeyMapMock.Setup(x => x.GetIdForKey(entities[1].Key, UmbracoObjectTypes.Document))
.Returns(Attempt.Succeed(2));
Guid[] keys = entities.Select(x => x.Key).ToArray();
var contentServiceMock = new Mock<IContentService>();
contentServiceMock
.Setup(x => x.GetScheduledContentKeys(It.IsAny<IEnumerable<Guid>>()))
.Returns([entities[1].Key]);
var sut = new HasScheduleSignProvider(contentServiceMock.Object);
.Setup(x => x.GetContentSchedulesByIds(keys))
.Returns(CreateContentSchedules());
var sut = new HasScheduleSignProvider(contentServiceMock.Object, idKeyMapMock.Object);
var variant1 = new DocumentVariantResponseModel() { State = DocumentVariantState.Published, Name = "Test1", Culture = "en-EN" };
var variant2 = new DocumentVariantResponseModel() { State = DocumentVariantState.Published, Name = "Test1", Culture = "da-DA" };
var variant3 = new DocumentVariantResponseModel() { State = DocumentVariantState.PublishedPendingChanges, Name = "Test" };
var viewModels = new List<DocumentCollectionResponseModel>
{
new() { Id = entities[0].Key }, new() { Id = entities[1].Key },
new() { Id = entities[0].Key, Variants = [variant1, variant2] }, new() { Id = entities[1].Key, Variants = [variant3] },
};
await sut.PopulateSignsAsync(viewModels);
Assert.AreEqual(viewModels[0].Signs.Count(), 0);
Assert.AreEqual(viewModels[1].Signs.Count(), 1);
Assert.AreEqual(viewModels[0].Variants.FirstOrDefault(x => x.Culture == "da-DA").Signs.Count(), 0);
Assert.AreEqual(viewModels[0].Variants.FirstOrDefault(x => x.Culture == "en-EN").Signs.Count(), 1);
Assert.AreEqual(viewModels[1].Variants.First().Signs.Count(), 1);
var signModel = viewModels[1].Signs.First();
var signModel = viewModels[0].Variants.First().Signs.First();
Assert.AreEqual("Umb.ScheduledForPublish", signModel.Alias);
}
@@ -103,23 +137,51 @@ internal class HasScheduleSignProviderTests
new() { Key = Guid.NewGuid(), Name = "Item 1" }, new() { Key = Guid.NewGuid(), Name = "Item 2" },
};
var idKeyMapMock = new Mock<IIdKeyMap>();
idKeyMapMock.Setup(x => x.GetIdForKey(entities[0].Key, UmbracoObjectTypes.Document))
.Returns(Attempt.Succeed(1));
idKeyMapMock.Setup(x => x.GetIdForKey(entities[1].Key, UmbracoObjectTypes.Document))
.Returns(Attempt.Succeed(2));
Guid[] keys = entities.Select(x => x.Key).ToArray();
var contentServiceMock = new Mock<IContentService>();
contentServiceMock
.Setup(x => x.GetScheduledContentKeys(It.IsAny<IEnumerable<Guid>>()))
.Returns([entities[1].Key]);
var sut = new HasScheduleSignProvider(contentServiceMock.Object);
.Setup(x => x.GetContentSchedulesByIds(keys))
.Returns(CreateContentSchedules());
var sut = new HasScheduleSignProvider(contentServiceMock.Object, idKeyMapMock.Object);
var variant1 = new DocumentVariantItemResponseModel() { State = DocumentVariantState.Published, Name = "Test1", Culture = "en-EN" };
var variant2 = new DocumentVariantItemResponseModel() { State = DocumentVariantState.Published, Name = "Test1", Culture = "da-DA" };
var variant3 = new DocumentVariantItemResponseModel() { State = DocumentVariantState.PublishedPendingChanges, Name = "Test" };
var viewModels = new List<DocumentItemResponseModel>
{
new() { Id = entities[0].Key }, new() { Id = entities[1].Key },
new() { Id = entities[0].Key, Variants = [variant1, variant2] }, new() { Id = entities[1].Key, Variants = [variant3] },
};
await sut.PopulateSignsAsync(viewModels);
Assert.AreEqual(viewModels[0].Signs.Count(), 0);
Assert.AreEqual(viewModels[1].Signs.Count(), 1);
Assert.AreEqual(viewModels[0].Variants.FirstOrDefault(x => x.Culture == "da-DA").Signs.Count(), 0);
Assert.AreEqual(viewModels[0].Variants.FirstOrDefault(x => x.Culture == "en-EN").Signs.Count(), 1);
Assert.AreEqual(viewModels[1].Variants.First().Signs.Count(), 1);
var signModel = viewModels[1].Signs.First();
var signModel = viewModels[0].Variants.First().Signs.First();
Assert.AreEqual("Umb.ScheduledForPublish", signModel.Alias);
}
private Dictionary<int, IEnumerable<ContentSchedule>> CreateContentSchedules()
{
Dictionary<int, IEnumerable<ContentSchedule>> contentSchedules = new Dictionary<int, IEnumerable<ContentSchedule>>();
contentSchedules.Add(1, [
new ContentSchedule("en-EN", DateTime.Now.AddDays(1), ContentScheduleAction.Release), // Scheduled for release
new ContentSchedule("da-DA", DateTime.Now.AddDays(-1), ContentScheduleAction.Release) // Not Scheduled for release
]);
contentSchedules.Add(2, [
new ContentSchedule("*", DateTime.Now.AddDays(1), ContentScheduleAction.Release) // Scheduled for release
]);
return contentSchedules;
}
}

View File

@@ -0,0 +1,30 @@
using System.Text.Json.Nodes;
using NUnit.Framework;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Infrastructure.PropertyEditors.Validators;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors.Validators;
[TestFixture]
public class FileUploadValueRequiredValidatorTests
{
[Test]
public void Validates_Empty_File_Upload_As_Not_Provided()
{
var validator = new FileUploadValueRequiredValidator();
var value = JsonNode.Parse("{ \"src\": \"\", \"settingsData\": [] }");
var result = validator.ValidateRequired(value, ValueTypes.Json);
Assert.AreEqual(1, result.Count());
}
[Test]
public void Valdiates_File_Upload_As_Provided()
{
var validator = new FileUploadValueRequiredValidator();
var value = JsonNode.Parse("{ \"src\": \"fakePath\", \"settingsData\": [] }");
var result = validator.ValidateRequired(value, ValueTypes.Json);
Assert.IsEmpty(result);
}
}