diff --git a/src/Umbraco.Core/PublishedCache/IPublishedMediaCache.cs b/src/Umbraco.Core/PublishedCache/IPublishedMediaCache.cs index eb7810960725..cb66f43c12c6 100644 --- a/src/Umbraco.Core/PublishedCache/IPublishedMediaCache.cs +++ b/src/Umbraco.Core/PublishedCache/IPublishedMediaCache.cs @@ -18,5 +18,5 @@ public interface IPublishedMediaCache : IPublishedCache /// The content unique identifier. /// The content, or null. /// Considers published or unpublished content depending on defaults. - Task GetByKeyAsync(Guid key); + Task GetByIdAsync(Guid key); } diff --git a/src/Umbraco.PublishedCache.HybridCache/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.PublishedCache.HybridCache/DependencyInjection/UmbracoBuilderExtensions.cs index ec7c233cb7ed..c8e93b635175 100644 --- a/src/Umbraco.PublishedCache.HybridCache/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.PublishedCache.HybridCache/DependencyInjection/UmbracoBuilderExtensions.cs @@ -65,6 +65,8 @@ public static IUmbracoBuilder AddUmbracoHybridCache(this IUmbracoBuilder builder builder.AddNotificationAsyncHandler(); builder.AddNotificationAsyncHandler(); builder.AddNotificationAsyncHandler(); + builder.AddNotificationAsyncHandler(); + builder.AddNotificationAsyncHandler(); builder.AddNotificationAsyncHandler(); builder.AddCacheSeeding(); return builder; diff --git a/src/Umbraco.PublishedCache.HybridCache/MediaCache.cs b/src/Umbraco.PublishedCache.HybridCache/MediaCache.cs index 53d59da72c04..7afcde8fb346 100644 --- a/src/Umbraco.PublishedCache.HybridCache/MediaCache.cs +++ b/src/Umbraco.PublishedCache.HybridCache/MediaCache.cs @@ -18,17 +18,17 @@ public MediaCache(IMediaCacheService mediaCacheService, IPublishedContentTypeCac public async Task GetByIdAsync(int id) => await _mediaCacheService.GetByIdAsync(id); - public async Task GetByKeyAsync(Guid key) => await _mediaCacheService.GetByKeyAsync(key); + public async Task GetByIdAsync(Guid key) => await _mediaCacheService.GetByKeyAsync(key); public IPublishedContent? GetById(bool preview, int contentId) => GetByIdAsync(contentId).GetAwaiter().GetResult(); public IPublishedContent? GetById(bool preview, Guid contentId) => - GetByKeyAsync(contentId).GetAwaiter().GetResult(); + GetByIdAsync(contentId).GetAwaiter().GetResult(); public IPublishedContent? GetById(int contentId) => GetByIdAsync(contentId).GetAwaiter().GetResult(); - public IPublishedContent? GetById(Guid contentId) => GetByKeyAsync(contentId).GetAwaiter().GetResult(); + public IPublishedContent? GetById(Guid contentId) => GetByIdAsync(contentId).GetAwaiter().GetResult(); public IPublishedContentType? GetContentType(Guid key) => _publishedContentTypeCache.Get(PublishedItemType.Media, key); diff --git a/src/Umbraco.PublishedCache.HybridCache/NotificationHandlers/CacheRefreshingNotificationHandler.cs b/src/Umbraco.PublishedCache.HybridCache/NotificationHandlers/CacheRefreshingNotificationHandler.cs index a155b3b4ebdc..f61968365c43 100644 --- a/src/Umbraco.PublishedCache.HybridCache/NotificationHandlers/CacheRefreshingNotificationHandler.cs +++ b/src/Umbraco.PublishedCache.HybridCache/NotificationHandlers/CacheRefreshingNotificationHandler.cs @@ -19,7 +19,9 @@ internal sealed class CacheRefreshingNotificationHandler : INotificationAsyncHandler, INotificationAsyncHandler, INotificationAsyncHandler, - INotificationAsyncHandler + INotificationAsyncHandler, + INotificationAsyncHandler, + INotificationAsyncHandler { private readonly IDocumentCacheService _documentCacheService; private readonly IMediaCacheService _mediaCacheService; @@ -126,7 +128,7 @@ public Task HandleAsync(ContentTypeRefreshedNotification notification, Cancellat var contentTypeIds = notification.Changes.Where(x => x.ChangeTypes.HasTypesAny(types)).Select(x => x.Item.Id) .ToArray(); - if (contentTypeIds.Length != 0) + if (contentTypeIds.Length > 0) { foreach (var contentTypeId in contentTypeIds) { @@ -148,4 +150,33 @@ public Task HandleAsync(ContentTypeDeletedNotification notification, Cancellatio return Task.CompletedTask; } + + public Task HandleAsync(MediaTypeRefreshedNotification notification, CancellationToken cancellationToken) + { + const ContentTypeChangeTypes types // only for those that have been refreshed + = ContentTypeChangeTypes.RefreshMain | ContentTypeChangeTypes.RefreshOther; + var mediaTypeIds = notification.Changes.Where(x => x.ChangeTypes.HasTypesAny(types)).Select(x => x.Item.Id) + .ToArray(); + + if (mediaTypeIds.Length > 0) + { + foreach (var mediaTypeId in mediaTypeIds) + { + _publishedContentTypeCache.ClearContentType(mediaTypeId); + } + + _mediaCacheService.Rebuild(mediaTypeIds); + } + return Task.CompletedTask; + } + + public Task HandleAsync(MediaTypeDeletedNotification notification, CancellationToken cancellationToken) + { + foreach (IMediaType deleted in notification.DeletedEntities ) + { + _publishedContentTypeCache.ClearContentType(deleted.Id); + } + + return Task.CompletedTask; + } } diff --git a/src/Umbraco.PublishedCache.HybridCache/Persistence/DatabaseCacheRepository.cs b/src/Umbraco.PublishedCache.HybridCache/Persistence/DatabaseCacheRepository.cs index fd3d64e0f557..4efc2fbebe2a 100644 --- a/src/Umbraco.PublishedCache.HybridCache/Persistence/DatabaseCacheRepository.cs +++ b/src/Umbraco.PublishedCache.HybridCache/Persistence/DatabaseCacheRepository.cs @@ -227,7 +227,7 @@ AND cmsContentNu.nodeId IS NULL return CreateContentNodeKit(dto, serializer, preview); } - private IEnumerable GetContentSourceByDocumentTypeKey(IEnumerable documentTypeKeys) + private IEnumerable GetContentSourceByDocumentTypeKey(IEnumerable documentTypeKeys, Guid objectType) { Guid[] keys = documentTypeKeys.ToArray(); if (keys.Any() is false) @@ -238,19 +238,27 @@ private IEnumerable GetContentSourceByDocumentTypeKey(IEnumera Sql? sql = SqlContentSourcesSelect() .InnerJoin("n") .On((n, c) => n.NodeId == c.ContentTypeId, "n", "umbracoContent") - .Append(SqlObjectTypeNotTrashed(SqlContext, Constants.ObjectTypes.Document)) + .Append(SqlObjectTypeNotTrashed(SqlContext, objectType)) .WhereIn(x => x.UniqueId, keys,"n") .Append(SqlOrderByLevelIdSortOrder(SqlContext)); return GetContentNodeDtos(sql); } - public IEnumerable GetContentByContentTypeKey(IEnumerable keys) + public IEnumerable GetContentByContentTypeKey(IEnumerable keys, ContentCacheDataSerializerEntityType entityType) { - IEnumerable dtos = GetContentSourceByDocumentTypeKey(keys); + Guid objectType = entityType switch + { + ContentCacheDataSerializerEntityType.Document => Constants.ObjectTypes.Document, + ContentCacheDataSerializerEntityType.Media => Constants.ObjectTypes.Media, + ContentCacheDataSerializerEntityType.Member => Constants.ObjectTypes.Member, + _ => throw new ArgumentOutOfRangeException(nameof(entityType), entityType, null), + }; + + IEnumerable dtos = GetContentSourceByDocumentTypeKey(keys, objectType); IContentCacheDataSerializer serializer = - _contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Document); + _contentCacheDataSerializerFactory.Create(entityType); foreach (ContentSourceDto row in dtos) { @@ -259,8 +267,8 @@ public IEnumerable GetContentByContentTypeKey(IEnumerable - public IEnumerable GetContentKeysByContentTypeKeys(IEnumerable keys, bool published = false) - => GetContentSourceByDocumentTypeKey(keys).Where(x => x.Published == published).Select(x => x.Key); + public IEnumerable GetDocumentKeysByContentTypeKeys(IEnumerable keys, bool published = false) + => GetContentSourceByDocumentTypeKey(keys, Constants.ObjectTypes.Document).Where(x => x.Published == published).Select(x => x.Key); public async Task GetMediaSourceAsync(int id) { diff --git a/src/Umbraco.PublishedCache.HybridCache/Persistence/IDatabaseCacheRepository.cs b/src/Umbraco.PublishedCache.HybridCache/Persistence/IDatabaseCacheRepository.cs index 6a88d5405e8a..0b5b739ac32a 100644 --- a/src/Umbraco.PublishedCache.HybridCache/Persistence/IDatabaseCacheRepository.cs +++ b/src/Umbraco.PublishedCache.HybridCache/Persistence/IDatabaseCacheRepository.cs @@ -1,4 +1,5 @@ using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Infrastructure.HybridCache.Serialization; namespace Umbraco.Cms.Infrastructure.HybridCache.Persistence; @@ -15,14 +16,14 @@ internal interface IDatabaseCacheRepository Task GetMediaSourceAsync(Guid key); - IEnumerable GetContentByContentTypeKey(IEnumerable keys); + IEnumerable GetContentByContentTypeKey(IEnumerable keys, ContentCacheDataSerializerEntityType entityType); /// /// Gets all content keys of specific document types /// /// The document types to find content using. /// The keys of all content use specific document types. - IEnumerable GetContentKeysByContentTypeKeys(IEnumerable keys, bool published = false); + IEnumerable GetDocumentKeysByContentTypeKeys(IEnumerable keys, bool published = false); /// /// Refreshes the nucache database row for the given cache node /> diff --git a/src/Umbraco.PublishedCache.HybridCache/SeedKeyProviders/Document/ContentTypeSeedKeyProvider.cs b/src/Umbraco.PublishedCache.HybridCache/SeedKeyProviders/Document/ContentTypeSeedKeyProvider.cs index bb0d721d639f..3b6d4ba2fc94 100644 --- a/src/Umbraco.PublishedCache.HybridCache/SeedKeyProviders/Document/ContentTypeSeedKeyProvider.cs +++ b/src/Umbraco.PublishedCache.HybridCache/SeedKeyProviders/Document/ContentTypeSeedKeyProvider.cs @@ -24,7 +24,7 @@ public ContentTypeSeedKeyProvider( public ISet GetSeedKeys() { using ICoreScope scope = _scopeProvider.CreateCoreScope(); - var documentKeys = _databaseCacheRepository.GetContentKeysByContentTypeKeys(_cacheSettings.ContentTypeKeys, published: true).ToHashSet(); + var documentKeys = _databaseCacheRepository.GetDocumentKeysByContentTypeKeys(_cacheSettings.ContentTypeKeys, published: true).ToHashSet(); scope.Complete(); return documentKeys; diff --git a/src/Umbraco.PublishedCache.HybridCache/Services/DocumentCacheService.cs b/src/Umbraco.PublishedCache.HybridCache/Services/DocumentCacheService.cs index 5e6b253e9bdd..4b8628574f07 100644 --- a/src/Umbraco.PublishedCache.HybridCache/Services/DocumentCacheService.cs +++ b/src/Umbraco.PublishedCache.HybridCache/Services/DocumentCacheService.cs @@ -7,6 +7,7 @@ using Umbraco.Cms.Core.Services; using Umbraco.Cms.Infrastructure.HybridCache.Factories; using Umbraco.Cms.Infrastructure.HybridCache.Persistence; +using Umbraco.Cms.Infrastructure.HybridCache.Serialization; using Umbraco.Extensions; namespace Umbraco.Cms.Infrastructure.HybridCache.Services; @@ -97,7 +98,7 @@ public DocumentCacheService( public IEnumerable GetByContentType(IPublishedContentType contentType) { using ICoreScope scope = _scopeProvider.CreateCoreScope(); - IEnumerable nodes = _databaseCacheRepository.GetContentByContentTypeKey([contentType.Key]); + IEnumerable nodes = _databaseCacheRepository.GetContentByContentTypeKey([contentType.Key], ContentCacheDataSerializerEntityType.Document); scope.Complete(); return nodes @@ -239,11 +240,11 @@ public async Task DeleteItemAsync(IContentBase content) scope.Complete(); } - public void Rebuild(IReadOnlyCollection contentTypeKeys) + public void Rebuild(IReadOnlyCollection contentTypeIds) { using ICoreScope scope = _scopeProvider.CreateCoreScope(); - _databaseCacheRepository.Rebuild(contentTypeKeys.ToList()); - IEnumerable contentByContentTypeKey = _databaseCacheRepository.GetContentByContentTypeKey(contentTypeKeys.Select(x => _idKeyMap.GetKeyForId(x, UmbracoObjectTypes.DocumentType).Result)); + _databaseCacheRepository.Rebuild(contentTypeIds.ToList()); + IEnumerable contentByContentTypeKey = _databaseCacheRepository.GetContentByContentTypeKey(contentTypeIds.Select(x => _idKeyMap.GetKeyForId(x, UmbracoObjectTypes.DocumentType).Result), ContentCacheDataSerializerEntityType.Document); foreach (ContentCacheNode content in contentByContentTypeKey) { diff --git a/src/Umbraco.PublishedCache.HybridCache/Services/IDocumentCacheService.cs b/src/Umbraco.PublishedCache.HybridCache/Services/IDocumentCacheService.cs index 95b710e73904..873551c06b86 100644 --- a/src/Umbraco.PublishedCache.HybridCache/Services/IDocumentCacheService.cs +++ b/src/Umbraco.PublishedCache.HybridCache/Services/IDocumentCacheService.cs @@ -17,7 +17,7 @@ public interface IDocumentCacheService Task DeleteItemAsync(IContentBase content); - void Rebuild(IReadOnlyCollection contentTypeKeys); + void Rebuild(IReadOnlyCollection contentTypeIds); internal IEnumerable GetByContentType(IPublishedContentType contentType); } diff --git a/src/Umbraco.PublishedCache.HybridCache/Services/IMediaCacheService.cs b/src/Umbraco.PublishedCache.HybridCache/Services/IMediaCacheService.cs index bbdf16618988..abaf0f28b57a 100644 --- a/src/Umbraco.PublishedCache.HybridCache/Services/IMediaCacheService.cs +++ b/src/Umbraco.PublishedCache.HybridCache/Services/IMediaCacheService.cs @@ -16,4 +16,6 @@ public interface IMediaCacheService Task DeleteItemAsync(IContentBase media); Task SeedAsync(CancellationToken cancellationToken); + + void Rebuild(IReadOnlyCollection contentTypeIds); } diff --git a/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs b/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs index 70f49f9531ed..78e456dbf0b1 100644 --- a/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs +++ b/src/Umbraco.PublishedCache.HybridCache/Services/MediaCacheService.cs @@ -7,6 +7,7 @@ using Umbraco.Cms.Core.Services; using Umbraco.Cms.Infrastructure.HybridCache.Factories; using Umbraco.Cms.Infrastructure.HybridCache.Persistence; +using Umbraco.Cms.Infrastructure.HybridCache.Serialization; namespace Umbraco.Cms.Infrastructure.HybridCache.Services; @@ -164,6 +165,26 @@ public async Task SeedAsync(CancellationToken cancellationToken) scope.Complete(); } + public void Rebuild(IReadOnlyCollection contentTypeIds) + { + using ICoreScope scope = _scopeProvider.CreateCoreScope(); + _databaseCacheRepository.Rebuild(contentTypeIds.ToList()); + + IEnumerable mediaTypeKeys = contentTypeIds.Select(x => _idKeyMap.GetKeyForId(x, UmbracoObjectTypes.MediaType)) + .Where(x => x.Success) + .Select(x => x.Result); + + IEnumerable mediaCacheNodesByContentTypeKey = + _databaseCacheRepository.GetContentByContentTypeKey(mediaTypeKeys, ContentCacheDataSerializerEntityType.Media); + + foreach (ContentCacheNode media in mediaCacheNodesByContentTypeKey) + { + _hybridCache.RemoveAsync(GetCacheKey(media.Key, false)); + } + + scope.Complete(); + } + private HybridCacheEntryOptions GetSeedEntryOptions() => new() { Expiration = _cacheSettings.SeedCacheDuration, LocalCacheExpiration = _cacheSettings.SeedCacheDuration, diff --git a/tests/Umbraco.Tests.Common/Builders/ContentEditingBaseBuilder.cs b/tests/Umbraco.Tests.Common/Builders/ContentEditingBaseBuilder.cs new file mode 100644 index 000000000000..617ebdc3a6cb --- /dev/null +++ b/tests/Umbraco.Tests.Common/Builders/ContentEditingBaseBuilder.cs @@ -0,0 +1,75 @@ +using Umbraco.Cms.Core.Models.ContentEditing; +using Umbraco.Cms.Tests.Common.Builders.Interfaces; + +namespace Umbraco.Cms.Tests.Common.Builders; + +public abstract class ContentEditingBaseBuilder : BuilderBase, + IWithInvariantNameBuilder, + IWithKeyBuilder, + IWithContentTypeKeyBuilder, + IWithParentKeyBuilder, + IBuildContentTypes + where TCreateModel : ContentCreationModelBase, new() +{ + protected TCreateModel _model = new(); + private List>> _invariantProperties = []; + private List>> _variants = []; + private Guid _contentTypeKey; + private Guid? _parentKey; + private Guid? _key; + private string _invariantName; + + Guid? IWithKeyBuilder.Key + { + get => _key; + set => _key = value; + } + + string IWithInvariantNameBuilder.InvariantName + { + get => _invariantName; + set => _invariantName = value; + } + + Guid? IWithParentKeyBuilder.ParentKey + { + get => _parentKey; + set => _parentKey = value; + } + + Guid IWithContentTypeKeyBuilder.ContentTypeKey + { + get => _contentTypeKey; + set => _contentTypeKey = value; + } + + public ContentEditingPropertyValueBuilder> AddInvariantProperty() + { + var builder = new ContentEditingPropertyValueBuilder>(this); + _invariantProperties.Add(builder); + return builder; + } + + public ContentEditingVariantBuilder> AddVariant() + { + var builder = new ContentEditingVariantBuilder>(this); + _variants.Add(builder); + return builder; + } + + public override TCreateModel Build() + { + if (_parentKey is not null) + { + _model.ParentKey = _parentKey; + } + + _model.InvariantName = _invariantName ?? Guid.NewGuid().ToString(); + _model.ContentTypeKey = _contentTypeKey; + _model.Key = _key ?? Guid.NewGuid(); + _model.InvariantProperties = _invariantProperties.Select(x => x.Build()).ToList(); + _model.Variants = _variants.Select(x => x.Build()).ToList(); + + return _model; + } +} diff --git a/tests/Umbraco.Tests.Common/Builders/ContentEditingBuilder.cs b/tests/Umbraco.Tests.Common/Builders/ContentEditingBuilder.cs index 069a0d82b216..b541c66e6ca5 100644 --- a/tests/Umbraco.Tests.Common/Builders/ContentEditingBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/ContentEditingBuilder.cs @@ -4,65 +4,12 @@ using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Cms.Tests.Common.Builders.Extensions; using Umbraco.Cms.Tests.Common.Builders.Interfaces; -using Umbraco.Cms.Tests.Common.Builders.Interfaces.ContentCreateModel; namespace Umbraco.Cms.Tests.Common.Builders; -public class ContentEditingBuilder - : BuilderBase, - IWithInvariantNameBuilder, - IWithInvariantPropertiesBuilder, - IWithVariantsBuilder, - IWithKeyBuilder, - IWithContentTypeKeyBuilder, - IWithParentKeyBuilder, - IWithTemplateKeyBuilder, - IBuildContentTypes +public class ContentEditingBuilder : ContentEditingBaseBuilder, IWithTemplateKeyBuilder { - private ContentTypeEditingBuilder _contentTypeEditingBuilder; - private IEnumerable _invariantProperties = []; - private IEnumerable _variants = []; - private Guid _contentTypeKey; - private Guid? _parentKey; private Guid? _templateKey; - private Guid? _key; - private string _invariantName; - - Guid? IWithKeyBuilder.Key - { - get => _key; - set => _key = value; - } - - string IWithInvariantNameBuilder.InvariantName - { - get => _invariantName; - set => _invariantName = value; - } - - IEnumerable IWithInvariantPropertiesBuilder.InvariantProperties - { - get => _invariantProperties; - set => _invariantProperties = value; - } - - IEnumerable IWithVariantsBuilder.Variants - { - get => _variants; - set => _variants = value; - } - - Guid? IWithParentKeyBuilder.ParentKey - { - get => _parentKey; - set => _parentKey = value; - } - - Guid IWithContentTypeKeyBuilder.ContentTypeKey - { - get => _contentTypeKey; - set => _contentTypeKey = value; - } Guid? IWithTemplateKeyBuilder.TemplateKey { @@ -70,65 +17,10 @@ Guid IWithContentTypeKeyBuilder.ContentTypeKey set => _templateKey = value; } - public ContentEditingBuilder WithInvariantName(string invariantName) - { - _invariantName = invariantName; - return this; - } - - public ContentEditingBuilder WithInvariantProperty(string alias, object value) - { - var property = new PropertyValueModel { Alias = alias, Value = value }; - _invariantProperties = _invariantProperties.Concat(new[] { property }); - return this; - } - - public ContentEditingBuilder AddVariant(string culture, string segment, string name, IEnumerable properties) - { - var variant = new VariantModel { Culture = culture, Segment = segment, Name = name, Properties = properties }; - _variants = _variants.Concat(new[] { variant }); - return this; - } - - public ContentEditingBuilder WithParentKey(Guid parentKey) - { - _parentKey = parentKey; - return this; - } - - public ContentEditingBuilder WithTemplateKey(Guid templateKey) - { - _templateKey = templateKey; - return this; - } - public override ContentCreateModel Build() { - var key = _key ?? Guid.NewGuid(); - var parentKey = _parentKey; - var templateKey = _templateKey; - var invariantName = _invariantName ?? Guid.NewGuid().ToString(); - var invariantProperties = _invariantProperties; - var variants = _variants; - - var content = new ContentCreateModel(); - content.InvariantName = invariantName; - if (parentKey is not null) - { - content.ParentKey = parentKey; - } - - if (templateKey is not null) - { - content.TemplateKey = templateKey; - } - - content.ContentTypeKey = _contentTypeKey; - content.Key = key; - content.InvariantProperties = invariantProperties; - content.Variants = variants; - - return content; + _model.TemplateKey = _templateKey; + return base.Build(); } public static ContentCreateModel CreateBasicContent(Guid contentTypeKey, Guid? key) => @@ -142,7 +34,10 @@ public static ContentCreateModel CreateSimpleContent(Guid contentTypeKey) => new ContentEditingBuilder() .WithContentTypeKey(contentTypeKey) .WithInvariantName("Home") - .WithInvariantProperty("title", "Welcome to our Home page") + .AddInvariantProperty() + .WithAlias("title") + .WithValue("Welcome to our Home page") + .Done() .Build(); public static ContentCreateModel CreateSimpleContent(Guid contentTypeKey, string name, Guid? parentKey) => @@ -150,20 +45,65 @@ public static ContentCreateModel CreateSimpleContent(Guid contentTypeKey, string .WithContentTypeKey(contentTypeKey) .WithInvariantName(name) .WithParentKey(parentKey) - .WithInvariantProperty("title", "Welcome to our Home page") + .AddInvariantProperty() + .WithAlias("title") + .WithValue("Welcome to our Home page") + .Done() .Build(); public static ContentCreateModel CreateSimpleContent(Guid contentTypeKey, string name) => new ContentEditingBuilder() .WithContentTypeKey(contentTypeKey) .WithInvariantName(name) - .WithInvariantProperty("title", "Welcome to our Home page") + .AddInvariantProperty() + .WithAlias("title") + .WithValue("Welcome to our Home page") + .Done() + .Build(); + + public static ContentCreateModel CreateContentWithTwoInvariantProperties(Guid contentTypeKey, string name, string firstPropertyAlias, string firstPropertyValue, string secondPropertyAlias, string secondPropertyValue, Guid? parentKey) => + new ContentEditingBuilder() + .WithContentTypeKey(contentTypeKey) + .WithInvariantName(name) + .WithParentKey(parentKey) + .AddInvariantProperty() + .WithAlias(firstPropertyAlias) + .WithValue(firstPropertyValue) + .Done() + .AddInvariantProperty() + .WithAlias(secondPropertyAlias) + .WithValue(secondPropertyValue) + .Done() + .Build(); + + public static ContentCreateModel CreateContentWithOneInvariantProperty(Guid contentTypeKey, string name, string propertyAlias, object propertyValue) => + new ContentEditingBuilder() + .WithContentTypeKey(contentTypeKey) + .WithInvariantName(name) + .AddInvariantProperty() + .WithAlias(propertyAlias) + .WithValue(propertyValue) + .Done() .Build(); public static ContentCreateModel CreateContentWithTwoVariantProperties(Guid contentTypeKey, string firstCulture, string secondCulture, string propertyAlias, string propertyName) => new ContentEditingBuilder() .WithContentTypeKey(contentTypeKey) - .AddVariant(firstCulture, null, firstCulture, new[] { new PropertyValueModel { Alias = propertyAlias, Value = propertyName } }) - .AddVariant(secondCulture, null, secondCulture, new[] { new PropertyValueModel { Alias = propertyAlias, Value = propertyName } }) + .AddVariant() + .WithCulture(firstCulture) + .WithName(firstCulture) + .AddProperty() + .WithAlias(propertyAlias) + .WithValue(propertyName) + .Done() + .Done() + .AddVariant() + .WithCulture(secondCulture) + .WithName(secondCulture) + .AddProperty() + .WithAlias(propertyAlias) + .WithValue(propertyName) + .Done() + .Done() .Build(); } diff --git a/tests/Umbraco.Tests.Common/Builders/ContentEditingPropertyValueBuilder.cs b/tests/Umbraco.Tests.Common/Builders/ContentEditingPropertyValueBuilder.cs new file mode 100644 index 000000000000..ee5e2fbb6d8e --- /dev/null +++ b/tests/Umbraco.Tests.Common/Builders/ContentEditingPropertyValueBuilder.cs @@ -0,0 +1,25 @@ +using Umbraco.Cms.Core.Models.ContentEditing; +using Umbraco.Cms.Tests.Common.Builders.Interfaces; + +namespace Umbraco.Cms.Tests.Common.Builders; + +public class ContentEditingPropertyValueBuilder(TParent parentBuilder) + : ChildBuilderBase(parentBuilder), IWithAliasBuilder, IWithValueBuilder +{ + private string _alias; + private object? _value; + + string IWithAliasBuilder.Alias + { + get => _alias; + set => _alias = value; + } + + object? IWithValueBuilder.Value + { + get => _value; + set => _value = value; + } + + public override PropertyValueModel Build() => new() { Alias = _alias, Value = _value }; +} diff --git a/tests/Umbraco.Tests.Common/Builders/ContentEditingVariantBuilder.cs b/tests/Umbraco.Tests.Common/Builders/ContentEditingVariantBuilder.cs new file mode 100644 index 000000000000..797b46b8ace1 --- /dev/null +++ b/tests/Umbraco.Tests.Common/Builders/ContentEditingVariantBuilder.cs @@ -0,0 +1,47 @@ +using Umbraco.Cms.Core.Models.ContentEditing; +using Umbraco.Cms.Tests.Common.Builders.Interfaces; + +namespace Umbraco.Cms.Tests.Common.Builders; + +public class ContentEditingVariantBuilder(TParent parentBuilder) + : ChildBuilderBase(parentBuilder), IWithCultureBuilder, IWithSegmentBuilder, IWithNameBuilder +{ + private string? _culture; + private string? _segment; + private string _name; + private readonly List>> _properties = new(); + + string? IWithCultureBuilder.Culture + { + get => _culture; + set => _culture = value; + } + + string? IWithSegmentBuilder.Segment + { + get => _segment; + set => _segment = value; + } + + string IWithNameBuilder.Name + { + get => _name; + set => _name = value; + } + + public ContentEditingPropertyValueBuilder> AddProperty() + { + var builder = new ContentEditingPropertyValueBuilder>((ContentEditingVariantBuilder)this); + _properties.Add(builder); + return builder; + } + + public override VariantModel Build() => + new() + { + Culture = _culture, + Segment = _segment, + Name = _name, + Properties = _properties.Select(x => x.Build()).ToList(), + }; +} diff --git a/tests/Umbraco.Tests.Common/Builders/ContentTypeBuilder.cs b/tests/Umbraco.Tests.Common/Builders/ContentTypeBuilder.cs index 1bb8c6fab9c0..65c2b85d7936 100644 --- a/tests/Umbraco.Tests.Common/Builders/ContentTypeBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/ContentTypeBuilder.cs @@ -16,7 +16,7 @@ public class ContentTypeBuilder IWithPropertyTypeIdsIncrementingFrom, IBuildPropertyTypes { - private readonly List _allowedContentTypeBuilders = new(); + private readonly List> _allowedContentTypeBuilders = new(); private readonly List> _noGroupPropertyTypeBuilders = new(); private readonly List> _propertyGroupBuilders = new(); private readonly List _templateBuilders = new(); @@ -88,9 +88,9 @@ public TemplateBuilder AddAllowedTemplate() return builder; } - public ContentTypeSortBuilder AddAllowedContentType() + public ContentTypeSortBuilder AddAllowedContentType() { - var builder = new ContentTypeSortBuilder(this); + var builder = new ContentTypeSortBuilder(this); _allowedContentTypeBuilders.Add(builder); return builder; } diff --git a/tests/Umbraco.Tests.Common/Builders/ContentTypeEditingBaseBuilder.cs b/tests/Umbraco.Tests.Common/Builders/ContentTypeEditingBaseBuilder.cs new file mode 100644 index 000000000000..a0bd49f78417 --- /dev/null +++ b/tests/Umbraco.Tests.Common/Builders/ContentTypeEditingBaseBuilder.cs @@ -0,0 +1,113 @@ +using Umbraco.Cms.Core.Models.ContentTypeEditing; +using Umbraco.Cms.Tests.Common.Builders.Interfaces; + +namespace Umbraco.Cms.Tests.Common.Builders; + +public abstract class ContentTypeEditingBaseBuilder : + IWithAliasBuilder, IWithNameBuilder, IWithDescriptionBuilder, IWithIconBuilder, IWithAllowAsRootBuilder, + IWithIsElementBuilder, IWithVariesByCultureBuilder, + IWithVariesBySegmentBuilder + where TBuilder : ContentTypeEditingBaseBuilder + where TCreateModel : ContentTypeEditingModelBase, new() + where TPropertyType : PropertyTypeModelBase, new() + where TPropertyTypeContainer : PropertyTypeContainerModelBase, new() +{ + protected TCreateModel _model = new(); + private string _alias; + private string _name; + private string? _description; + private string _icon; + private bool? _allowedAsRoot; + private bool? _isElement; + private bool? _variesByCulture; + private bool? _variesBySegment; + private readonly List> _propertyTypeBuilders = new(); + private readonly List> _propertyTypeContainerBuilders = new(); + private readonly List> _allowedContentTypeBuilders = new(); + + string IWithAliasBuilder.Alias + { + get => _alias; + set => _alias = value; + } + + string IWithNameBuilder.Name + { + get => _name; + set => _name = value; + } + + string? IWithDescriptionBuilder.Description + { + get => _description; + set => _description = value; + } + + string IWithIconBuilder.Icon + { + get => _icon; + set => _icon = value; + } + + bool? IWithAllowAsRootBuilder.AllowAsRoot + { + get => _allowedAsRoot ?? false; + set => _allowedAsRoot = value; + } + + bool? IWithIsElementBuilder.IsElement + { + get => _isElement ?? false; + set => _isElement = value; + } + + + bool IWithVariesByCultureBuilder.VariesByCulture + { + get => _variesByCulture ?? false; + set => _variesByCulture = value; + } + + bool IWithVariesBySegmentBuilder.VariesBySegment + { + get => _variesBySegment ?? false; + set => _variesBySegment = value; + } + + public PropertyTypeEditingBuilder AddPropertyType() + { + var builder = new PropertyTypeEditingBuilder((TBuilder)this); + _propertyTypeBuilders.Add(builder); + return builder; + } + + public PropertyTypeContainerBuilder AddPropertyGroup() + { + var builder = new PropertyTypeContainerBuilder((TBuilder)this); + _propertyTypeContainerBuilders.Add(builder); + return builder; + } + + public ContentTypeSortBuilder AddAllowedContentType() + { + var builder = new ContentTypeSortBuilder((TBuilder)this); + _allowedContentTypeBuilders.Add(builder); + return builder; + } + + protected virtual TCreateModel Build() + { + _model.Properties = _propertyTypeBuilders.Select(x => x.Build()); + _model.Containers = _propertyTypeContainerBuilders.Select(x => x.Build()); + _model.AllowedContentTypes = _allowedContentTypeBuilders.Select(x => x.Build()); + _model.Alias = _alias ?? "TestName"; + _model.Name = _name ?? "TestName"; + _model.Description = _description; + _model.Icon = _icon ?? _model.Icon; + _model.AllowedAsRoot = _allowedAsRoot ?? false; + _model.IsElement = _isElement ?? _model.IsElement; + _model.VariesByCulture = _variesByCulture ?? _model.VariesByCulture; + _model.VariesBySegment = _variesBySegment ?? _model.VariesBySegment; + return _model; + } +} diff --git a/tests/Umbraco.Tests.Common/Builders/ContentTypeEditingBuilder.cs b/tests/Umbraco.Tests.Common/Builders/ContentTypeEditingBuilder.cs index bcbcbcada04d..c9cdc41552f2 100644 --- a/tests/Umbraco.Tests.Common/Builders/ContentTypeEditingBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/ContentTypeEditingBuilder.cs @@ -1,70 +1,33 @@ using Umbraco.Cms.Core; -using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentTypeEditing; using Umbraco.Cms.Tests.Common.Builders.Extensions; using Umbraco.Cms.Tests.Common.Builders.Interfaces; namespace Umbraco.Cms.Tests.Common.Builders; -public class ContentTypeEditingBuilder - : ContentTypeBaseBuilder, - IBuildPropertyTypes +public class ContentTypeEditingBuilder : ContentTypeEditingBaseBuilder, IWithKeyBuilder, IWithContainerKeyBuilder, IWithDefaultTemplateKeyBuilder { private Guid? _key; private Guid? _containerKey; - private ContentTypeCleanup _cleanup = new(); - private IEnumerable _allowedTemplateKeys; + private IEnumerable _allowedTemplateKeys = Array.Empty(); private Guid? _defaultTemplateKey; - private bool? _allowAtRoot; - private bool? _isElement; - private bool? _variesByCulture; - private bool? _variesBySegment; - private readonly List _propertyTypeBuilders = []; - private readonly List> _propertyTypeContainerBuilders = []; - private readonly List _allowedContentTypeBuilders = []; - public ContentTypeEditingBuilder() - : base(null) + Guid? IWithKeyBuilder.Key { + get => _key; + set => _key = value; } - public ContentTypeEditingBuilder(ContentEditingBuilder parentBuilder) - : base(parentBuilder) + Guid? IWithContainerKeyBuilder.ContainerKey { + get => _containerKey; + set => _containerKey = value; } - public ContentTypeEditingBuilder WithDefaultTemplateKey(Guid templateKey) + Guid? IWithDefaultTemplateKeyBuilder.DefaultTemplateKey { - _defaultTemplateKey = templateKey; - return this; - } - - public ContentTypeEditingBuilder WithIsElement(bool isElement) - { - _isElement = isElement; - return this; - } - - public PropertyTypeContainerBuilder AddPropertyGroup() - { - var builder = new PropertyTypeContainerBuilder(this); - _propertyTypeContainerBuilders.Add(builder); - return builder; - } - - public PropertyTypeEditingBuilder AddPropertyType() - { - var builder = new PropertyTypeEditingBuilder(this); - _propertyTypeBuilders.Add(builder); - return builder; - } - - - public ContentTypeSortBuilder AddAllowedContentType() - { - var builder = new ContentTypeSortBuilder(this); - _allowedContentTypeBuilders.Add(builder); - return builder; + get => _defaultTemplateKey; + set => _defaultTemplateKey = value; } public ContentTypeEditingBuilder AddAllowedTemplateKeys(IEnumerable templateKeys) @@ -73,64 +36,33 @@ public ContentTypeEditingBuilder AddAllowedTemplateKeys(IEnumerable templa return this; } - public ContentTypeEditingBuilder WithAllowAtRoot(bool allowAtRoot) - { - _allowAtRoot = allowAtRoot; - return this; - } - - public ContentTypeEditingBuilder WithVariesByCulture(bool variesByCulture) - { - _variesByCulture = variesByCulture; - return this; - } - - public ContentTypeEditingBuilder WithVariesBySegment(bool variesBySegment) - { - _variesBySegment = variesBySegment; - return this; - } - - public override ContentTypeCreateModel Build() + protected override ContentTypeCreateModel Build() { - ContentTypeCreateModel contentType = new ContentTypeCreateModel(); - contentType.Name = GetName(); - contentType.Alias = GetAlias(); - contentType.Key = GetKey(); - contentType.ContainerKey = _containerKey; - contentType.Cleanup = _cleanup; - contentType.AllowedTemplateKeys = _allowedTemplateKeys ?? Array.Empty(); - contentType.DefaultTemplateKey = _defaultTemplateKey; - contentType.IsElement = _isElement ?? false; - contentType.VariesByCulture = _variesByCulture ?? false; - contentType.VariesBySegment = _variesBySegment ?? false; - contentType.AllowedAsRoot = _allowAtRoot ?? false; - contentType.Properties = _propertyTypeBuilders.Select(x => x.Build()); - contentType.Containers = _propertyTypeContainerBuilders.Select(x => x.Build()); - contentType.AllowedContentTypes = _allowedContentTypeBuilders.Select(x => x.Build()); - - return contentType; + _model.Key = _key ?? Guid.NewGuid(); + _model.ContainerKey = _containerKey; + _model.AllowedTemplateKeys = _allowedTemplateKeys; + _model.DefaultTemplateKey = _defaultTemplateKey; + base.Build(); + return _model; } - public static ContentTypeCreateModel CreateBasicContentType(string alias = "umbTextpage", string name = "TextPage", IContentType parent = null) + public static ContentTypeCreateModel CreateBasicContentType(string alias = "umbTextpage", string name = "TextPage") { var builder = new ContentTypeEditingBuilder(); return (ContentTypeCreateModel)builder .WithAlias(alias) .WithName(name) - .WithParentContentType(parent) .Build(); } - public static ContentTypeCreateModel CreateSimpleContentType(string alias = "umbTextpage", string name = "TextPage", IContentType parent = null, string propertyGroupName = "Content", Guid? defaultTemplateKey = null) + public static ContentTypeCreateModel CreateSimpleContentType(string alias = "umbTextpage", string name = "TextPage", string propertyGroupName = "Content", Guid? defaultTemplateKey = null) { var containerKey = Guid.NewGuid(); var builder = new ContentTypeEditingBuilder(); return (ContentTypeCreateModel)builder .WithAlias(alias) .WithName(name) - .WithAllowAtRoot(true) - .WithParentContentType(parent) + .WithAllowAsRoot(true) .AddPropertyGroup() .WithKey(containerKey) .WithName(propertyGroupName) @@ -155,7 +87,7 @@ public static ContentTypeCreateModel CreateTextPageContentType(string alias = "t return (ContentTypeCreateModel)builder .WithAlias(alias) .WithName(name) - .WithAllowAtRoot(true) + .WithAllowAsRoot(true) .AddPropertyGroup() .WithName("Content") .WithKey(containerKeyOne) @@ -217,7 +149,7 @@ public static ContentTypeCreateModel CreateElementType(string alias = "textEleme .Build(); } - public static ContentTypeCreateModel CreateContentTypeWithDataTypeKey(Guid dataTypeKey, string alias = "textElement", string name = "Text Element" ) + public static ContentTypeCreateModel CreateContentTypeWithDataTypeKey(Guid dataTypeKey, string alias = "textElement", string name = "Text Element") { var containerKey = Guid.NewGuid(); var builder = new ContentTypeEditingBuilder(); @@ -237,4 +169,53 @@ public static ContentTypeCreateModel CreateContentTypeWithDataTypeKey(Guid dataT .Done() .Build(); } + + public static ContentTypeCreateModel CreateContentTypeWithContentPicker(string alias = "test", string name = "TestName", Guid templateKey = default) + { + var containerKey = Guid.NewGuid(); + var builder = new ContentTypeEditingBuilder(); + return (ContentTypeCreateModel)builder + .WithAlias(alias) + .WithName(name) + .WithAllowAsRoot(true) + .AddAllowedTemplateKeys([templateKey]) + .AddPropertyGroup() + .WithName("Content") + .WithKey(containerKey) + .Done() + .AddPropertyType() + .WithAlias("contentPicker") + .WithName("Content Picker") + .WithDataTypeKey(Constants.DataTypes.Guids.ContentPickerGuid) + .WithContainerKey(containerKey) + .Done() + .Build(); + } + + public static ContentTypeCreateModel CreateContentTypeWithTwoPropertiesOneVariantAndOneInvariant(string alias = "test", string name = "TestName", string variantPropertyAlias = "variant", string variantPropertyName = "Variant", string invariantAlias = "invariant", string invariantName = "Invariant") + { + var containerKey = Guid.NewGuid(); + var builder = new ContentTypeEditingBuilder(); + return (ContentTypeCreateModel)builder + .WithAlias(alias) + .WithName(name) + .WithAllowAsRoot(true) + .WithVariesByCulture(true) + .AddPropertyGroup() + .WithName("Content") + .WithKey(containerKey) + .Done() + .AddPropertyType() + .WithAlias(variantPropertyAlias) + .WithName(variantPropertyName) + .WithVariesByCulture(true) + .WithContainerKey(containerKey) + .Done() + .AddPropertyType() + .WithAlias(invariantAlias) + .WithName(invariantName) + .WithContainerKey(containerKey) + .Done() + .Build(); + } } diff --git a/tests/Umbraco.Tests.Common/Builders/ContentTypeSortBuilder.cs b/tests/Umbraco.Tests.Common/Builders/ContentTypeSortBuilder.cs index a63205d4d289..5a26eb4e356f 100644 --- a/tests/Umbraco.Tests.Common/Builders/ContentTypeSortBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/ContentTypeSortBuilder.cs @@ -8,8 +8,8 @@ namespace Umbraco.Cms.Tests.Common.Builders; -public class ContentTypeSortBuilder - : ChildBuilderBase, +public class ContentTypeSortBuilder + : ChildBuilderBase, IWithKeyBuilder, IWithAliasBuilder, IWithSortOrderBuilder @@ -18,21 +18,11 @@ public class ContentTypeSortBuilder private string _alias; private int? _sortOrder; - public ContentTypeSortBuilder() - : base(null) - { - } - - public ContentTypeSortBuilder(ContentTypeBuilder parentBuilder) + public ContentTypeSortBuilder(TBuilder parentBuilder) : base(parentBuilder) { } - public ContentTypeSortBuilder(ContentTypeEditingBuilder parentBuilder) - : base(null) - { - } - string IWithAliasBuilder.Alias { get => _alias; diff --git a/tests/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs b/tests/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs index f4cc7db311c5..a44c5c7ba9ae 100644 --- a/tests/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs +++ b/tests/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Umbraco. // See LICENSE for more details. -using System; using System.Globalization; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Tests.Common.Builders.Interfaces; @@ -233,7 +232,8 @@ public static T WithSupportsPublishing(this T builder, bool supportsPublishin return builder; } - public static T WithPropertyValues(this T builder, object propertyValues, string? culture = null, string? segment = null) + public static T WithPropertyValues(this T builder, object propertyValues, string? culture = null, + string? segment = null) where T : IWithPropertyValues { builder.PropertyValues = propertyValues; @@ -247,4 +247,102 @@ public static T WithDate(this T builder, DateTime date) where T : IWithDateBu builder.Date = date; return builder; } + + public static T WithInvariantName(this T builder, string invariantName) + where T : IWithInvariantNameBuilder + { + builder.InvariantName = invariantName; + return builder; + } + + public static T WithKey(this T builder, Guid? key) + where T : IWithKeyBuilder + { + builder.Key = key; + return builder; + } + + public static T WithContentTypeKey(this T builder, Guid contentTypeKey) + where T : IWithContentTypeKeyBuilder + { + builder.ContentTypeKey = contentTypeKey; + return builder; + } + + public static T WithParentKey(this T builder, Guid? parentKey) + where T : IWithParentKeyBuilder + { + builder.ParentKey = parentKey; + return builder; + } + + public static T WithTemplateKey(this T builder, Guid? templateKey) + where T : IWithTemplateKeyBuilder + { + builder.TemplateKey = templateKey; + return builder; + } + + public static T WithValue(this T builder, object? value) + where T : IWithValueBuilder + { + builder.Value = value; + return builder; + } + + public static T WithCulture(this T builder, string culture) + where T : IWithCultureBuilder + { + builder.Culture = culture; + return builder; + } + + public static T WithAllowAsRoot(this T builder, bool allowAsRoot) + where T : IWithAllowAsRootBuilder + { + builder.AllowAsRoot = allowAsRoot; + return builder; + } + + public static T WithSegment(this T builder, string segment) + where T : IWithSegmentBuilder + { + builder.Segment = segment; + return builder; + } + + public static T WithIsElement(this T builder, bool isElement) + where T : IWithIsElementBuilder + { + builder.IsElement = isElement; + return builder; + } + + public static T WithVariesByCulture(this T builder, bool variesByCulture) + where T : IWithVariesByCultureBuilder + { + builder.VariesByCulture = variesByCulture; + return builder; + } + + public static T WithVariesBySegement(this T builder, bool variesBySegment) + where T : IWithVariesBySegmentBuilder + { + builder.VariesBySegment = variesBySegment; + return builder; + } + + public static T WithDefaultTemplateKey(this T builder, Guid? defaultTemplateKey) + where T : IWithDefaultTemplateKeyBuilder + { + builder.DefaultTemplateKey = defaultTemplateKey; + return builder; + } + + public static T WithContainerKey(this T builder, Guid? containerKey) + where T : IWithContainerKeyBuilder + { + builder.ContainerKey = containerKey; + return builder; + } } diff --git a/tests/Umbraco.Tests.Common/Builders/Extensions/ContentEditingBuilderExtensions.cs b/tests/Umbraco.Tests.Common/Builders/Extensions/ContentEditingBuilderExtensions.cs deleted file mode 100644 index a02c4e5b126a..000000000000 --- a/tests/Umbraco.Tests.Common/Builders/Extensions/ContentEditingBuilderExtensions.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Umbraco.Cms.Core.Models.ContentEditing; -using Umbraco.Cms.Tests.Common.Builders.Interfaces; -using Umbraco.Cms.Tests.Common.Builders.Interfaces.ContentCreateModel; - -namespace Umbraco.Cms.Tests.Common.Builders.Extensions; - -public static class ContentEditingBuilderExtensions -{ - public static T WithInvariantName(this T Builder, string invariantName) - where T : IWithInvariantNameBuilder - { - Builder.InvariantName = invariantName; - return Builder; - } - - public static T WithInvariantProperties(this T Builder, IEnumerable invariantProperties) - where T : IWithInvariantPropertiesBuilder - { - Builder.InvariantProperties = invariantProperties; - return Builder; - } - - public static T WithVariants(this T Builder, IEnumerable variants) - where T : IWithVariantsBuilder - { - Builder.Variants = variants; - return Builder; - } - - public static T WithKey(this T Builder, Guid? key) - where T : IWithKeyBuilder - { - Builder.Key = key; - return Builder; - } - - public static T WithContentTypeKey(this T Builder, Guid contentTypeKey) - where T : IWithContentTypeKeyBuilder - { - Builder.ContentTypeKey = contentTypeKey; - return Builder; - } - - public static T WithParentKey(this T Builder, Guid? parentKey) - where T : IWithParentKeyBuilder - { - Builder.ParentKey = parentKey; - return Builder; - } - - - public static T WithTemplateKey(this T Builder, Guid? templateKey) - where T : IWithTemplateKeyBuilder - { - Builder.TemplateKey = templateKey; - return Builder; - } -} diff --git a/tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithInvariantPropertiesBuilder.cs b/tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithInvariantPropertiesBuilder.cs deleted file mode 100644 index 7320ac6523e2..000000000000 --- a/tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithInvariantPropertiesBuilder.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Umbraco.Cms.Core.Models.ContentEditing; - -namespace Umbraco.Cms.Tests.Common.Builders.Interfaces.ContentCreateModel; - -public interface IWithInvariantPropertiesBuilder -{ - public IEnumerable InvariantProperties { get; set; } -} diff --git a/tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithVariantsBuilder.cs b/tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithVariantsBuilder.cs deleted file mode 100644 index ca4e54f1c480..000000000000 --- a/tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithVariantsBuilder.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Umbraco.Cms.Core.Models.ContentEditing; - -namespace Umbraco.Cms.Tests.Common.Builders.Interfaces.ContentCreateModel; - -public interface IWithVariantsBuilder -{ - public IEnumerable Variants { get; set; } -} diff --git a/tests/Umbraco.Tests.Common/Builders/Interfaces/IWIthContainerKeyBuilder.cs b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithContainerKeyBuilder.cs similarity index 70% rename from tests/Umbraco.Tests.Common/Builders/Interfaces/IWIthContainerKeyBuilder.cs rename to tests/Umbraco.Tests.Common/Builders/Interfaces/IWithContainerKeyBuilder.cs index cc184eea48ff..6b71b52f4fc9 100644 --- a/tests/Umbraco.Tests.Common/Builders/Interfaces/IWIthContainerKeyBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithContainerKeyBuilder.cs @@ -1,6 +1,6 @@ namespace Umbraco.Cms.Tests.Common.Builders.Interfaces; -public interface IWIthContainerKeyBuilder +public interface IWithContainerKeyBuilder { Guid? ContainerKey { get; set; } } diff --git a/tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithContentTypeKeyBuilder.cs b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithContentTypeKeyBuilder.cs similarity index 54% rename from tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithContentTypeKeyBuilder.cs rename to tests/Umbraco.Tests.Common/Builders/Interfaces/IWithContentTypeKeyBuilder.cs index cdb743ca67ac..a22c5fa72a4a 100644 --- a/tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithContentTypeKeyBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithContentTypeKeyBuilder.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Cms.Tests.Common.Builders.Interfaces.ContentCreateModel; +namespace Umbraco.Cms.Tests.Common.Builders.Interfaces; public interface IWithContentTypeKeyBuilder { diff --git a/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithCultureBuilder.cs b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithCultureBuilder.cs new file mode 100644 index 000000000000..66ca1890fd08 --- /dev/null +++ b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithCultureBuilder.cs @@ -0,0 +1,6 @@ +namespace Umbraco.Cms.Tests.Common.Builders.Interfaces; + +public interface IWithCultureBuilder +{ + string? Culture { get; set; } +} diff --git a/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithDefaultTemplateKeyBuilder.cs b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithDefaultTemplateKeyBuilder.cs new file mode 100644 index 000000000000..75c9727437c1 --- /dev/null +++ b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithDefaultTemplateKeyBuilder.cs @@ -0,0 +1,6 @@ +namespace Umbraco.Cms.Tests.Common.Builders.Interfaces; + +public interface IWithDefaultTemplateKeyBuilder +{ + Guid? DefaultTemplateKey { get; set; } +} diff --git a/tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithInvariantNameBuilder.cs b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithInvariantNameBuilder.cs similarity index 54% rename from tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithInvariantNameBuilder.cs rename to tests/Umbraco.Tests.Common/Builders/Interfaces/IWithInvariantNameBuilder.cs index 27698b13951a..ffc466fa980a 100644 --- a/tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithInvariantNameBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithInvariantNameBuilder.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Cms.Tests.Common.Builders.Interfaces.ContentCreateModel; +namespace Umbraco.Cms.Tests.Common.Builders.Interfaces; public interface IWithInvariantNameBuilder { diff --git a/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithIsElementBuilder.cs b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithIsElementBuilder.cs new file mode 100644 index 000000000000..bdc213309143 --- /dev/null +++ b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithIsElementBuilder.cs @@ -0,0 +1,6 @@ +namespace Umbraco.Cms.Tests.Common.Builders.Interfaces; + +public interface IWithIsElementBuilder +{ + bool? IsElement { get; set; } +} diff --git a/tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithParentKeyBuilder.cs b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithParentKeyBuilder.cs similarity index 100% rename from tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithParentKeyBuilder.cs rename to tests/Umbraco.Tests.Common/Builders/Interfaces/IWithParentKeyBuilder.cs diff --git a/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithSegmentBuilder.cs b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithSegmentBuilder.cs new file mode 100644 index 000000000000..76d0d26a2779 --- /dev/null +++ b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithSegmentBuilder.cs @@ -0,0 +1,6 @@ +namespace Umbraco.Cms.Tests.Common.Builders.Interfaces; + +public interface IWithSegmentBuilder +{ + string Segment { get; set; } +} diff --git a/tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithTemplateKeyBuilder.cs b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithTemplateKeyBuilder.cs similarity index 53% rename from tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithTemplateKeyBuilder.cs rename to tests/Umbraco.Tests.Common/Builders/Interfaces/IWithTemplateKeyBuilder.cs index 0b05a70548dd..41e46626fe52 100644 --- a/tests/Umbraco.Tests.Common/Builders/Interfaces/ContentCreateModel/IWithTemplateKeyBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithTemplateKeyBuilder.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Cms.Tests.Common.Builders.Interfaces.ContentCreateModel; +namespace Umbraco.Cms.Tests.Common.Builders.Interfaces; public interface IWithTemplateKeyBuilder { diff --git a/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithValueBuilder.cs b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithValueBuilder.cs new file mode 100644 index 000000000000..d17fbcceb3ab --- /dev/null +++ b/tests/Umbraco.Tests.Common/Builders/Interfaces/IWithValueBuilder.cs @@ -0,0 +1,6 @@ +namespace Umbraco.Cms.Tests.Common.Builders.Interfaces; + +public interface IWithValueBuilder +{ + object? Value { get; set; } +} diff --git a/tests/Umbraco.Tests.Common/Builders/MediaEditingBuilder.cs b/tests/Umbraco.Tests.Common/Builders/MediaEditingBuilder.cs new file mode 100644 index 000000000000..e2b5eddffb49 --- /dev/null +++ b/tests/Umbraco.Tests.Common/Builders/MediaEditingBuilder.cs @@ -0,0 +1,32 @@ +using Umbraco.Cms.Core.Models.ContentEditing; +using Umbraco.Cms.Tests.Common.Builders.Extensions; + +namespace Umbraco.Cms.Tests.Common.Builders; + +public class MediaEditingBuilder : ContentEditingBaseBuilder +{ + public static MediaCreateModel CreateBasicMedia(Guid mediaTypeKey, Guid? key) => + new MediaEditingBuilder() + .WithKey(key) + .WithContentTypeKey(mediaTypeKey) + .WithInvariantName("Media") + .Build(); + + public static MediaCreateModel CreateSimpleMedia(Guid mediaTypeKey, string name, Guid? parentKey) => + new MediaEditingBuilder() + .WithContentTypeKey(mediaTypeKey) + .WithInvariantName(name) + .WithParentKey(parentKey) + .Build(); + + public static MediaCreateModel CreateMediaWithAProperty(Guid mediaTypeKey, string name, Guid? parentKey, string propertyAlias = "testProperty", string propertyValue = "TestValue") => + new MediaEditingBuilder() + .WithContentTypeKey(mediaTypeKey) + .WithInvariantName(name) + .WithParentKey(parentKey) + .AddInvariantProperty() + .WithAlias(propertyAlias) + .WithValue(propertyValue) + .Done() + .Build(); +} diff --git a/tests/Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs b/tests/Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs new file mode 100644 index 000000000000..c1291d64db2f --- /dev/null +++ b/tests/Umbraco.Tests.Common/Builders/MediaTypeEditingBuilder.cs @@ -0,0 +1,76 @@ +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Models.ContentTypeEditing; +using Umbraco.Cms.Tests.Common.Builders.Extensions; +using Umbraco.Cms.Tests.Common.Builders.Interfaces; + +namespace Umbraco.Cms.Tests.Common.Builders; + +public class MediaTypeEditingBuilder : ContentTypeEditingBaseBuilder, IWithKeyBuilder, IWithContainerKeyBuilder +{ + private Guid? _key; + private Guid? _containerKey; + + Guid? IWithKeyBuilder.Key + { + get => _key; + set => _key = value; + } + + Guid? IWithContainerKeyBuilder.ContainerKey + { + get => _containerKey; + set => _containerKey = value; + } + + protected override MediaTypeCreateModel Build() + { + _model.Key = _key ?? Guid.NewGuid(); + _model.ContainerKey = _containerKey; + base.Build(); + return _model; + } + + public static MediaTypeCreateModel CreateBasicMediaType(string alias = "umbImage", string name = "Image") + { + var builder = new MediaTypeEditingBuilder(); + return (MediaTypeCreateModel)builder + .WithAlias(alias) + .WithName(name) + .WithAllowAsRoot(true) + .Build(); + } + + public static MediaTypeCreateModel CreateBasicFolderMediaType(string alias = "basicFolder", + string name = "BasicFolder") + { + var builder = new MediaTypeEditingBuilder(); + return (MediaTypeCreateModel)builder + .WithAlias(alias) + .WithName(name) + .WithIcon("icon-folder") + .WithAllowAsRoot(true) + .Build(); + } + + public static MediaTypeCreateModel CreateMediaTypeWithOneProperty(string alias = "testMediaType", string name = "TestMediaType", string propertyAlias = "testProperty", string propertyName = "TestProperty") + { + var containerKey = Guid.NewGuid(); + var builder = new MediaTypeEditingBuilder(); + return (MediaTypeCreateModel)builder + .WithAlias(alias) + .WithName(name) + .WithAllowAsRoot(true) + .AddPropertyGroup() + .WithName("TestGroup") + .WithKey(containerKey) + .Done() + .AddPropertyType() + .WithAlias(propertyAlias) + .WithName(propertyName) + .WithDataTypeKey(Constants.DataTypes.Guids.TextstringGuid) + .WithContainerKey(containerKey) + .Done() + .Build(); + } +} diff --git a/tests/Umbraco.Tests.Common/Builders/PropertyTypeAppearanceBuilder.cs b/tests/Umbraco.Tests.Common/Builders/PropertyTypeAppearanceBuilder.cs index 4917b2861baf..8cda975f932f 100644 --- a/tests/Umbraco.Tests.Common/Builders/PropertyTypeAppearanceBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/PropertyTypeAppearanceBuilder.cs @@ -3,12 +3,14 @@ namespace Umbraco.Cms.Tests.Common.Builders; -public class PropertyTypeAppearanceBuilder - : ChildBuilderBase, IBuildPropertyTypes, IWithLabelOnTop +public class PropertyTypeAppearanceBuilder + : ChildBuilderBase, PropertyTypeAppearance>, IBuildPropertyTypes, IWithLabelOnTop + where TModel : PropertyTypeModelBase, new() { private bool? _labelOnTop; - public PropertyTypeAppearanceBuilder(PropertyTypeEditingBuilder parentBuilder) : base(parentBuilder) + public PropertyTypeAppearanceBuilder(PropertyTypeEditingBuilder parentBuilder) + : base(parentBuilder) { } diff --git a/tests/Umbraco.Tests.Common/Builders/PropertyTypeContainerBuilder.cs b/tests/Umbraco.Tests.Common/Builders/PropertyTypeContainerBuilder.cs index b5af22eb5003..ee7c3da9805a 100644 --- a/tests/Umbraco.Tests.Common/Builders/PropertyTypeContainerBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/PropertyTypeContainerBuilder.cs @@ -1,14 +1,12 @@ -using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.Models.ContentTypeEditing; +using Umbraco.Cms.Core.Models.ContentTypeEditing; using Umbraco.Cms.Tests.Common.Builders.Interfaces; namespace Umbraco.Cms.Tests.Common.Builders; -public class PropertyTypeContainerBuilder(TParent parentBuilder) - : ChildBuilderBase(parentBuilder), - IBuildPropertyTypes, IWithKeyBuilder, IWithParentKeyBuilder, IWithNameBuilder, IWithTypeBuilder, - IWithSortOrderBuilder +public class PropertyTypeContainerBuilder(TParent parentBuilder) + : ChildBuilderBase(parentBuilder), IWithKeyBuilder, IWithParentKeyBuilder, IWithNameBuilder, IWithTypeBuilder, IWithSortOrderBuilder where TModel : PropertyTypeContainerModelBase, new() { + private readonly TModel _model = new(); private Guid? _key; private Guid? _parentKey; private string _name; @@ -45,22 +43,18 @@ string IWithTypeBuilder.Type set => _sortOrder = value; } - public override ContentTypePropertyContainerModel Build() + public override TModel Build() { - var key = _key ?? Guid.NewGuid(); - var parentKey = _parentKey; - var name = _name ?? "Container"; - var type = _type ?? "Group"; - var sortOrder = _sortOrder ?? 0; + _model.Key = _key ?? Guid.NewGuid(); - - return new ContentTypePropertyContainerModel + if (_parentKey is not null) { - Key = key, - ParentKey = parentKey, - Name = name, - Type = type, - SortOrder = sortOrder, - }; + _model.ParentKey = _parentKey; + } + + _model.Name = _name ?? "Container"; + _model.Type = _type ?? "Group"; + _model.SortOrder = _sortOrder ?? 0; + return _model; } } diff --git a/tests/Umbraco.Tests.Common/Builders/PropertyTypeEditingBuilder.cs b/tests/Umbraco.Tests.Common/Builders/PropertyTypeEditingBuilder.cs index 301d77f37b85..d4e2263e867e 100644 --- a/tests/Umbraco.Tests.Common/Builders/PropertyTypeEditingBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/PropertyTypeEditingBuilder.cs @@ -4,28 +4,30 @@ namespace Umbraco.Cms.Tests.Common.Builders; -public class PropertyTypeEditingBuilder - : ChildBuilderBase, IBuildPropertyTypes, IWithKeyBuilder, - IWIthContainerKeyBuilder, - IWithSortOrderBuilder, IWithAliasBuilder, IWithNameBuilder, IWithDescriptionBuilder, IWithDataTypeKeyBuilder, - IWithVariesByCultureBuilder, IWithVariesBySegmentBuilder +public class PropertyTypeEditingBuilder : ChildBuilderBase, IWithKeyBuilder, + IWithContainerKeyBuilder, IWithSortOrderBuilder, IWithAliasBuilder, IWithNameBuilder, IWithDescriptionBuilder, + IWithDataTypeKeyBuilder, IWithVariesByCultureBuilder, + IWithVariesBySegmentBuilder where TModel : PropertyTypeModelBase, new() { + private TModel _model; private Guid? _key; private Guid? _containerKey; private int? _sortOrder; private string _alias; - private string? _name; + private string _name; private string? _description; private Guid? _dataTypeKey; private bool _variesByCulture; private bool _variesBySegment; - private PropertyTypeValidationEditingBuilder _validationBuilder; - private PropertyTypeAppearanceBuilder _appearanceBuilder; + private PropertyTypeValidationEditingBuilder _validationBuilder; + private PropertyTypeAppearanceBuilder _appearanceBuilder; - public PropertyTypeEditingBuilder(ContentTypeEditingBuilder parentBuilder) : base(parentBuilder) + public PropertyTypeEditingBuilder(TParent parentBuilder) + : base(parentBuilder) { - _validationBuilder = new PropertyTypeValidationEditingBuilder(this); - _appearanceBuilder = new PropertyTypeAppearanceBuilder(this); + _model = new TModel(); + _validationBuilder = new PropertyTypeValidationEditingBuilder(this); + _appearanceBuilder = new PropertyTypeAppearanceBuilder(this); } Guid? IWithKeyBuilder.Key @@ -34,7 +36,7 @@ public PropertyTypeEditingBuilder(ContentTypeEditingBuilder parentBuilder) : bas set => _key = value; } - Guid? IWIthContainerKeyBuilder.ContainerKey + Guid? IWithContainerKeyBuilder.ContainerKey { get => _containerKey; set => _containerKey = value; @@ -58,7 +60,7 @@ string IWithNameBuilder.Name set => _name = value; } - string IWithDescriptionBuilder.Description + string? IWithDescriptionBuilder.Description { get => _description; set => _description = value; @@ -82,95 +84,34 @@ bool IWithVariesBySegmentBuilder.VariesBySegment set => _variesBySegment = value; } - public PropertyTypeValidationEditingBuilder AddValidation() + public PropertyTypeValidationEditingBuilder AddValidation() { - var builder = new PropertyTypeValidationEditingBuilder(this); + var builder = new PropertyTypeValidationEditingBuilder(this); _validationBuilder = builder; return builder; } - public PropertyTypeAppearanceBuilder AddAppearance() + public PropertyTypeAppearanceBuilder AddAppearance() { - var builder = new PropertyTypeAppearanceBuilder(this); + var builder = new PropertyTypeAppearanceBuilder(this); _appearanceBuilder = builder; return builder; } - public PropertyTypeEditingBuilder WithContainerKey(Guid? containerKey) + public override TModel Build() { - _containerKey = containerKey; - return this; - } - - public PropertyTypeEditingBuilder WithSortOrder(int sortOrder) - { - _sortOrder = sortOrder; - return this; - } - - public PropertyTypeEditingBuilder WithAlias(string alias) - { - _alias = alias; - return this; - } - - public PropertyTypeEditingBuilder WithName(string name) - { - _name = name; - return this; - } + _model.Key = _key ?? Guid.NewGuid(); + _model.ContainerKey = _containerKey; + _model.SortOrder = _sortOrder ?? 0; + _model.Alias = _alias ?? "title"; + _model.Name = _name ?? "Title"; + _model.Description = _description; + _model.DataTypeKey = _dataTypeKey ?? Constants.DataTypes.Guids.TextareaGuid; + _model.VariesByCulture = _variesByCulture; + _model.VariesBySegment = _variesBySegment; + _model.Validation = _validationBuilder.Build(); + _model.Appearance = _appearanceBuilder.Build(); - public PropertyTypeEditingBuilder WithDescription(string description) - { - _description = description; - return this; - } - - public PropertyTypeEditingBuilder WithDataTypeKey(Guid dataTypeKey) - { - _dataTypeKey = dataTypeKey; - return this; - } - - public PropertyTypeEditingBuilder WithVariesByCulture(bool variesByCulture) - { - _variesByCulture = variesByCulture; - return this; - } - - public PropertyTypeEditingBuilder WithVariesBySegment(bool variesBySegment) - { - _variesBySegment = variesBySegment; - return this; - } - - public override ContentTypePropertyTypeModel Build() - { - var key = _key ?? Guid.NewGuid(); - var containerKey = _containerKey; - var sortOrder = _sortOrder ?? 0; - var alias = _alias ?? "title"; - var name = _name ?? "Title"; - var description = _description; - var dataTypeKey = _dataTypeKey ?? Constants.DataTypes.Guids.TextareaGuid; - var variesByCulture = _variesByCulture; - var variesBySegment = _variesBySegment; - var validation = _validationBuilder.Build(); - var appearance = _appearanceBuilder.Build(); - - return new ContentTypePropertyTypeModel - { - Key = key, - ContainerKey = containerKey, - SortOrder = sortOrder, - Alias = alias, - Name = name, - Description = description, - DataTypeKey = dataTypeKey, - VariesByCulture = variesByCulture, - VariesBySegment = variesBySegment, - Validation = validation, - Appearance = appearance, - }; + return _model; } } diff --git a/tests/Umbraco.Tests.Common/Builders/PropertyTypeValidationEditingBuilder.cs b/tests/Umbraco.Tests.Common/Builders/PropertyTypeValidationEditingBuilder.cs index 781463c760cc..b9ea485ef9c3 100644 --- a/tests/Umbraco.Tests.Common/Builders/PropertyTypeValidationEditingBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/PropertyTypeValidationEditingBuilder.cs @@ -3,16 +3,22 @@ namespace Umbraco.Cms.Tests.Common.Builders; -public class PropertyTypeValidationEditingBuilder - : ChildBuilderBase, IBuildPropertyTypes, IWithMandatoryBuilder, - IWithMandatoryMessageBuilder, IWithRegularExpressionBuilder, IWithRegularExpressionMessage +public class PropertyTypeValidationEditingBuilder + : ChildBuilderBase, PropertyTypeValidation>, + IBuildPropertyTypes, + IWithMandatoryBuilder, + IWithMandatoryMessageBuilder, + IWithRegularExpressionBuilder, + IWithRegularExpressionMessage + where TModel : PropertyTypeModelBase, new() { private bool? _mandatory; private string? _mandatoryMessage; private string? _regularExpression; private string? _regularExpressionMessage; - public PropertyTypeValidationEditingBuilder(PropertyTypeEditingBuilder parentBuilder) : base(parentBuilder) + public PropertyTypeValidationEditingBuilder(PropertyTypeEditingBuilder parentBuilder) + : base(parentBuilder) { } diff --git a/tests/Umbraco.Tests.Common/TestHelpers/MediaTypeUpdateHelper.cs b/tests/Umbraco.Tests.Common/TestHelpers/MediaTypeUpdateHelper.cs new file mode 100644 index 000000000000..4470ddf846d6 --- /dev/null +++ b/tests/Umbraco.Tests.Common/TestHelpers/MediaTypeUpdateHelper.cs @@ -0,0 +1,75 @@ +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.ContentTypeEditing; +using Umbraco.Extensions; + +namespace Umbraco.Cms.Tests.Common.TestHelpers; + +public class MediaTypeUpdateHelper +{ + public MediaTypeUpdateModel CreateMediaTypeUpdateModel(IMediaType mediaType) + { + var updateModel = new MediaTypeUpdateModel(); + var model = MapBaseProperties(mediaType, updateModel); + return model; + } + + private T MapBaseProperties(IMediaType mediaType, T model) where T : MediaTypeModelBase + { + model.Alias = mediaType.Alias; + model.Name = mediaType.Name; + model.Description = mediaType.Description; + model.Icon = mediaType.Icon; + model.AllowedAsRoot = mediaType.AllowedAsRoot; + model.VariesByCulture = mediaType.VariesByCulture(); + model.VariesBySegment = mediaType.VariesBySegment(); + model.IsElement = mediaType.IsElement; + model.ListView = mediaType.ListView; + model.AllowedContentTypes = mediaType.AllowedContentTypes; + + var tempContainerList = model.Containers.ToList(); + + foreach (var container in mediaType.PropertyGroups) + { + var containerModel = new MediaTypePropertyContainerModel() + { + Key = container.Key, + Name = container.Name, + SortOrder = container.SortOrder, + Type = container.Type.ToString() + }; + tempContainerList.Add(containerModel); + } + + model.Containers = tempContainerList.AsEnumerable(); + + var tempPropertyList = model.Properties.ToList(); + + foreach (var propertyType in mediaType.PropertyTypes) + { + var propertyModel = new MediaTypePropertyTypeModel + { + Key = propertyType.Key, + ContainerKey = mediaType.PropertyGroups.Single(x => x.PropertyTypes.Contains(propertyType)).Key, + SortOrder = propertyType.SortOrder, + Alias = propertyType.Alias, + Name = propertyType.Name, + Description = propertyType.Description, + DataTypeKey = propertyType.DataTypeKey, + VariesByCulture = propertyType.VariesByCulture(), + VariesBySegment = propertyType.VariesBySegment(), + Validation = new PropertyTypeValidation() + { + Mandatory = propertyType.Mandatory, + MandatoryMessage = propertyType.ValidationRegExp, + RegularExpression = propertyType.ValidationRegExp, + RegularExpressionMessage = propertyType.ValidationRegExpMessage, + }, + Appearance = new PropertyTypeAppearance() { LabelOnTop = propertyType.LabelOnTop, } + }; + tempPropertyList.Add(propertyModel); + } + + model.Properties = tempPropertyList.AsEnumerable(); + return model; + } +} diff --git a/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTestWithMediaEditing.cs b/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTestWithMediaEditing.cs new file mode 100644 index 000000000000..eee8ddc4ed47 --- /dev/null +++ b/tests/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTestWithMediaEditing.cs @@ -0,0 +1,155 @@ +using NUnit.Framework; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.ContentEditing; +using Umbraco.Cms.Core.Models.ContentTypeEditing; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Services.ContentTypeEditing; +using Umbraco.Cms.Tests.Common.Builders; +using Umbraco.Cms.Tests.Common.TestHelpers; + +namespace Umbraco.Cms.Tests.Integration.Testing; + +public abstract class UmbracoIntegrationTestWithMediaEditing : UmbracoIntegrationTest +{ + protected IMediaTypeService MediaTypeService => GetRequiredService(); + + protected IMediaEditingService MediaEditingService => GetRequiredService(); + + protected IMediaTypeEditingService MediaTypeEditingService => GetRequiredService(); + + protected MediaCreateModel RootFolder { get; private set; } + + protected int RootFolderId { get; private set; } + + protected MediaCreateModel RootImage { get; private set; } + + protected int RootImageId { get; private set; } + + protected MediaCreateModel SubFolder1 { get; private set; } + + protected int SubFolder1Id { get; private set; } + + protected MediaCreateModel SubFolder2 { get; private set; } + + protected int SubFolder2Id { get; private set; } + + protected MediaCreateModel SubImage { get; private set; } + + protected int SubImageId { get; private set; } + + protected MediaCreateModel SubTestMedia { get; private set; } + + protected int SubTestMediaId { get; private set; } + + protected MediaCreateModel SubSubImage { get; private set; } + + protected int SubSubImageId { get; private set; } + + protected MediaCreateModel SubSubFile { get; private set; } + + protected int SubSubFileId { get; private set; } + + protected MediaTypeCreateModel CustomMediaTypeCreateModel { get; private set; } + + protected IMediaType CustomMediaType { get; private set; } + + [SetUp] + public new void Setup() => CreateTestData(); + + protected async void CreateTestData() + { + CustomMediaTypeCreateModel = MediaTypeEditingBuilder.CreateMediaTypeWithOneProperty(); + var mediaTypeTestAttempt = await MediaTypeEditingService.CreateAsync(CustomMediaTypeCreateModel, Constants.Security.SuperUserKey); + Assert.IsTrue(mediaTypeTestAttempt.Success); + CustomMediaType = mediaTypeTestAttempt.Result; + + // Gets all media types + var folderMediaTypes = await MediaTypeEditingService.GetFolderMediaTypes(0, 10); + var folderMediaType = folderMediaTypes.Items.FirstOrDefault(x => x.Alias == "Folder"); + var mediaTypes = MediaTypeService.GetAll(); + var mediaTypesList = mediaTypes.ToList(); + var imageMediaType = mediaTypesList.FirstOrDefault(x => x.Alias == "Image"); + + // Add CustomMediaType to FolderMediaType AllowedContentTypes + var mediaTypeUpdateHelper = new MediaTypeUpdateHelper(); + var updateModel = mediaTypeUpdateHelper.CreateMediaTypeUpdateModel(folderMediaType); + var folderMediaTypeAllowedContentTypes = updateModel.AllowedContentTypes.ToList(); + folderMediaTypeAllowedContentTypes.Add(new ContentTypeSort(key: mediaTypeTestAttempt.Result.Key, sortOrder: folderMediaTypeAllowedContentTypes.Count, alias: CustomMediaTypeCreateModel.Alias)); + updateModel.AllowedContentTypes = folderMediaTypeAllowedContentTypes; + var updatedFolderMediaTypeAttempt = MediaTypeEditingService.UpdateAsync(folderMediaType, updateModel, Constants.Security.SuperUserKey); + Assert.IsTrue(updatedFolderMediaTypeAttempt.Result.Success); + + // Create and Save RootFolder + RootFolder = MediaEditingBuilder.CreateSimpleMedia(folderMediaType.Key, "RootFolder", null); + var rootFolderAttempt = await MediaEditingService.CreateAsync(RootFolder, Constants.Security.SuperUserKey); + Assert.IsTrue(rootFolderAttempt.Success); + if (rootFolderAttempt.Result.Content != null) + { + RootFolderId = rootFolderAttempt.Result.Content.Id; + } + + // Create and Save RootImage + RootImage = MediaEditingBuilder.CreateSimpleMedia(imageMediaType.Key, "RootImage", null); + var rootImageAttempt = await MediaEditingService.CreateAsync(RootImage, Constants.Security.SuperUserKey); + Assert.IsTrue(rootImageAttempt.Success); + if (rootImageAttempt.Result.Content != null) + { + RootImageId = rootImageAttempt.Result.Content.Id; + } + + // Create and Save SubFolder1 + SubFolder1 = MediaEditingBuilder.CreateSimpleMedia(folderMediaType.Key, "SubFolder1", RootFolder.Key); + var subFolder1Attempt = await MediaEditingService.CreateAsync(SubFolder1, Constants.Security.SuperUserKey); + Assert.IsTrue(subFolder1Attempt.Success); + if (subFolder1Attempt.Result.Content != null) + { + SubFolder1Id = subFolder1Attempt.Result.Content.Id; + } + + // Create and Save SubFolder2 + SubFolder2 = MediaEditingBuilder.CreateSimpleMedia(folderMediaType.Key, "SubFolder2", RootFolder.Key); + var subFolder2Attempt = await MediaEditingService.CreateAsync(SubFolder2, Constants.Security.SuperUserKey); + Assert.IsTrue(subFolder2Attempt.Success); + if (subFolder2Attempt.Result.Content != null) + { + SubFolder2Id = subFolder2Attempt.Result.Content.Id; + } + + // Create and Save SubImage + SubImage = MediaEditingBuilder.CreateSimpleMedia(imageMediaType.Key, "SubImage", RootFolder.Key); + var subImageAttempt = await MediaEditingService.CreateAsync(SubImage, Constants.Security.SuperUserKey); + Assert.IsTrue(subImageAttempt.Success); + if (subImageAttempt.Result.Content != null) + { + SubImageId = subImageAttempt.Result.Content.Id; + } + + // Create and Save SubTestMedia + SubTestMedia = MediaEditingBuilder.CreateMediaWithAProperty(mediaTypeTestAttempt.Result.Key, "SubTestMedia", RootFolder.Key, "testProperty", "This is a test"); + var subTestMediaAttempt = await MediaEditingService.CreateAsync(SubTestMedia, Constants.Security.SuperUserKey); + Assert.IsTrue(subTestMediaAttempt.Success); + if (subTestMediaAttempt.Result.Content != null) + { + SubTestMediaId = subTestMediaAttempt.Result.Content.Id; + } + + // Create and Save SubSubImage + SubSubImage = MediaEditingBuilder.CreateSimpleMedia(imageMediaType.Key, "SubSubImage", SubFolder1.Key); + var subSubImageAttempt = await MediaEditingService.CreateAsync(SubSubImage, Constants.Security.SuperUserKey); + Assert.IsTrue(subSubImageAttempt.Success); + if (subSubImageAttempt.Result.Content != null) + { + SubSubImageId = subSubImageAttempt.Result.Content.Id; + } + + // Create and Save SubSubFile + SubSubFile = MediaEditingBuilder.CreateSimpleMedia(imageMediaType.Key, "SubSubFile", SubFolder1.Key); + var subSubFileAttempt = await MediaEditingService.CreateAsync(SubSubFile, Constants.Security.SuperUserKey); + Assert.IsTrue(subSubFileAttempt.Success); + if (subSubFileAttempt.Result.Content != null) + { + SubSubFileId = subSubFileAttempt.Result.Content.Id; + } + } +} diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheDocumentTypeTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheDocumentTypeTests.cs index 8f25c27e5863..c316b00ae68d 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheDocumentTypeTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheDocumentTypeTests.cs @@ -20,7 +20,7 @@ public class DocumentHybridCacheDocumentTypeTests : UmbracoIntegrationTestWithCo [Test] public async Task Can_Get_Draft_Content_By_Id() { - //Act + // Act await PublishedContentHybridCache.GetByIdAsync(TextpageId, true); ContentType.RemovePropertyType("title"); @@ -48,12 +48,12 @@ public async Task Can_Get_Draft_Content_By_Key() public async Task Content_Gets_Removed_When_DocumentType_Is_Deleted() { // Load into cache - var textpage = await PublishedContentHybridCache.GetByIdAsync(Textpage.Key.Value, preview: true); - Assert.IsNotNull(textpage); + var textPage = await PublishedContentHybridCache.GetByIdAsync(Textpage.Key.Value, preview: true); + Assert.IsNotNull(textPage); - await ContentTypeService.DeleteAsync(textpage.ContentType.Key, Constants.Security.SuperUserKey); + await ContentTypeService.DeleteAsync(textPage.ContentType.Key, Constants.Security.SuperUserKey); - var textpageAgain = await PublishedContentHybridCache.GetByIdAsync(Textpage.Key.Value, preview: true); - Assert.IsNull(textpageAgain); + var textPageAgain = await PublishedContentHybridCache.GetByIdAsync(Textpage.Key.Value, preview: true); + Assert.IsNull(textPageAgain); } } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheMockTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheMockTests.cs index 22740f9eb5b7..b0e3bc6ec7e2 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheMockTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheMockTests.cs @@ -13,6 +13,7 @@ using Umbraco.Cms.Infrastructure.HybridCache.Factories; using Umbraco.Cms.Infrastructure.HybridCache.Persistence; using Umbraco.Cms.Infrastructure.HybridCache.SeedKeyProviders.Document; +using Umbraco.Cms.Infrastructure.HybridCache.Serialization; using Umbraco.Cms.Infrastructure.HybridCache.Services; using Umbraco.Cms.Tests.Common.Testing; using Umbraco.Cms.Tests.Integration.Testing; @@ -86,7 +87,7 @@ public void SetUp() _mockedNucacheRepository.Setup(r => r.GetContentSourceAsync(It.IsAny(), false)) .ReturnsAsync(publishedTestCacheNode); - _mockedNucacheRepository.Setup(r => r.GetContentByContentTypeKey(It.IsAny>())).Returns( + _mockedNucacheRepository.Setup(r => r.GetContentByContentTypeKey(It.IsAny>(), ContentCacheDataSerializerEntityType.Document)).Returns( new List() { draftTestCacheNode, diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCachePropertyTest.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCachePropertyTest.cs index f9ddfb05ba8d..1471234c8dfc 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCachePropertyTest.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCachePropertyTest.cs @@ -9,7 +9,6 @@ using Umbraco.Cms.Core.Services.ContentTypeEditing; using Umbraco.Cms.Core.Services.OperationStatus; 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; @@ -84,7 +83,7 @@ public async Task Can_Get_Value_From_Updated_ContentPicker() updateResult.Result.Content!.Key, new CultureAndScheduleModel() { - CulturesToPublishImmediately = new HashSet {"*"}, + CulturesToPublishImmediately = new HashSet { "*" }, Schedules = new ContentScheduleCollection(), }, Constants.Security.SuperUserKey); @@ -104,35 +103,13 @@ public async Task Can_Get_Value_From_Updated_ContentPicker() private async Task CreateContentPickerDocument(Guid templateKey, Guid textPageKey) { - var builder = new ContentTypeEditingBuilder(); - var pickerContentType = builder - .WithAlias("test") - .WithName("TestName") - .WithAllowAtRoot(true) - .AddAllowedTemplateKeys([templateKey]) - .AddPropertyGroup() - .WithName("Content") - .Done() - .AddPropertyType() - .WithAlias("contentPicker") - .WithName("Content Picker") - .WithDataTypeKey(Constants.DataTypes.Guids.ContentPickerGuid) - .WithSortOrder(16) - .Done() - .Build(); - + var pickerContentType = ContentTypeEditingBuilder.CreateContentTypeWithContentPicker(templateKey: templateKey); await ContentTypeEditingService.CreateAsync(pickerContentType, Constants.Security.SuperUserKey); - - var createOtherModel = new ContentCreateModel - { - ContentTypeKey = pickerContentType.Key.Value, - ParentKey = Constants.System.RootKey, - InvariantName = "Test Create", - InvariantProperties = new[] { new PropertyValueModel { Alias = "contentPicker", Value = textPageKey }, }, - }; - + var createOtherModel = ContentEditingBuilder.CreateContentWithOneInvariantProperty(pickerContentType.Key.Value, + "Test Create", "contentPicker", textPageKey); var result = await ContentEditingService.CreateAsync(createOtherModel, Constants.Security.SuperUserKey); + Assert.IsTrue(result.Success); Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status); @@ -140,11 +117,12 @@ private async Task CreateContentPickerDocument(Guid templateKey, Guid result.Result.Content!.Key, new CultureAndScheduleModel() { - CulturesToPublishImmediately = new HashSet {"*"}, + CulturesToPublishImmediately = new HashSet { "*" }, Schedules = new ContentScheduleCollection(), }, Constants.Security.SuperUserKey); + Assert.IsTrue(publishResult.Success); return result.Result.Content; } @@ -153,26 +131,18 @@ private async Task CreateTextPageDocument(Guid templateKey) var textContentType = ContentTypeEditingBuilder.CreateTextPageContentType(defaultTemplateKey: templateKey); await ContentTypeEditingService.CreateAsync(textContentType, Constants.Security.SuperUserKey); - var createModel = new ContentCreateModel - { - ContentTypeKey = textContentType.Key.Value, - ParentKey = Constants.System.RootKey, - InvariantName = "Root Create", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" }, - new PropertyValueModel { Alias = "bodyText", Value = "The body text" } - }, - }; + var contentCreateModel = ContentEditingBuilder.CreateContentWithTwoInvariantProperties( + textContentType.Key.Value, "Root Create", "title", "The title value", "bodyText", "The body text", + Constants.System.RootKey); - var createResult = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); + var createResult = await ContentEditingService.CreateAsync(contentCreateModel, Constants.Security.SuperUserKey); Assert.IsTrue(createResult.Success); var publishResult = await ContentPublishingService.PublishAsync( createResult.Result.Content!.Key, new CultureAndScheduleModel() { - CulturesToPublishImmediately = new HashSet {"*"}, + CulturesToPublishImmediately = new HashSet { "*" }, Schedules = new ContentScheduleCollection(), }, Constants.Security.SuperUserKey); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheScopeTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheScopeTests.cs index 227ee4f58f4e..070aa96e7b94 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheScopeTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheScopeTests.cs @@ -18,12 +18,12 @@ public class DocumentHybridCacheScopeTests : UmbracoIntegrationTestWithContentEd private IContentPublishingService ContentPublishingService => GetRequiredService(); - private ICoreScopeProvider ICoreScopeProvider => GetRequiredService(); + private ICoreScopeProvider CoreScopeProvider => GetRequiredService(); [Test] public async Task Can_Get_Correct_Content_After_Rollback_With_Id() { - using (ICoreScopeProvider.CreateCoreScope()) + using (CoreScopeProvider.CreateCoreScope()) { await ContentPublishingService.PublishAsync(Textpage.Key.Value, CultureAndSchedule, Constants.Security.SuperUserKey); } @@ -38,7 +38,7 @@ public async Task Can_Get_Correct_Content_After_Rollback_With_Id() [Test] public async Task Can_Get_Correct_Content_After_Rollback_With_Key() { - using (ICoreScopeProvider.CreateCoreScope()) + using (CoreScopeProvider.CreateCoreScope()) { await ContentPublishingService.PublishAsync(Textpage.Key.Value, CultureAndSchedule, Constants.Security.SuperUserKey); } @@ -53,7 +53,7 @@ public async Task Can_Get_Correct_Content_After_Rollback_With_Key() [Test] public async Task Can_Get_Document_After_Scope_Complete_With_Id() { - using (var scope = ICoreScopeProvider.CreateCoreScope()) + using (var scope = CoreScopeProvider.CreateCoreScope()) { await ContentPublishingService.PublishAsync(Textpage.Key.Value, CultureAndSchedule, Constants.Security.SuperUserKey); scope.Complete(); @@ -69,7 +69,7 @@ public async Task Can_Get_Document_After_Scope_Complete_With_Id() [Test] public async Task Can_Get_Document_After_Scope_Completes_With_Key() { - using (var scope = ICoreScopeProvider.CreateCoreScope()) + using (var scope = CoreScopeProvider.CreateCoreScope()) { await ContentPublishingService.PublishAsync(Textpage.Key.Value, CultureAndSchedule, Constants.Security.SuperUserKey); scope.Complete(); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTemplateTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTemplateTests.cs index eb352ff6c8e8..a0873bd983c6 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTemplateTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTemplateTests.cs @@ -1,4 +1,4 @@ -using NUnit.Framework; +using NUnit.Framework; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Cms.Core.PublishedCache; @@ -36,7 +36,6 @@ public async Task Can_Get_Document_After_Removing_Template() // Assert Assert.AreEqual(updateContentResult.Status, ContentEditingOperationStatus.Success); var textPageAfter = await PublishedContentHybridCache.GetByIdAsync(TextpageId, true); - // Should this not be null? Assert.AreEqual(textPageAfter.TemplateId, null); } } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheVariantsTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheVariantsTests.cs index fd13c6678a55..87815fdbeb63 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheVariantsTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheVariantsTests.cs @@ -60,13 +60,7 @@ public async Task Can_Set_Invariant_Title() Culture = _englishIsoCode, Name = "Updated English Name", Properties = - new[] - { - new PropertyValueModel - { - Alias = _variantTitleAlias, Value = updatedVariantTitle - } - }, + new[] { new PropertyValueModel { Alias = _variantTitleAlias, Value = updatedVariantTitle } }, }, new VariantModel { @@ -74,16 +68,14 @@ public async Task Can_Set_Invariant_Title() Name = "Updated Danish Name", Properties = new[] { - new PropertyValueModel - { - Alias = _variantTitleAlias, Value = updatedVariantTitle - }, + new PropertyValueModel { Alias = _variantTitleAlias, Value = updatedVariantTitle }, }, }, }, }; - var result = await ContentEditingService.UpdateAsync(VariantPage.Key, updateModel, Constants.Security.SuperUserKey); + var result = + await ContentEditingService.UpdateAsync(VariantPage.Key, updateModel, Constants.Security.SuperUserKey); Assert.IsTrue(result.Success); // Act @@ -116,10 +108,7 @@ public async Task Can_Set_Invariant_Title_On_One_Culture() Name = "Updated English Name", Properties = new[] { - new PropertyValueModel - { - Alias = _variantTitleAlias, Value = updatedVariantTitle - }, + new PropertyValueModel { Alias = _variantTitleAlias, Value = updatedVariantTitle }, }, }, }, @@ -146,35 +135,18 @@ private async Task CreateTestData() .Build(); await LanguageService.CreateAsync(language, Constants.Security.SuperUserKey); - var groupKey = Guid.NewGuid(); - var contentType = new ContentTypeEditingBuilder() - .WithAlias("cultureVariationTest") - .WithName("Culture Variation Test") - .WithAllowAtRoot(true) - .WithVariesByCulture(true) - .AddPropertyType() - .WithAlias(_variantTitleAlias) - .WithName(_variantTitleName) - .WithVariesByCulture(true) - .WithContainerKey(groupKey) - .Done() - .AddPropertyType() - .WithAlias(_invariantTitleAlias) - .WithName(_invariantTitleName) - .WithContainerKey(groupKey) - .Done() - .AddPropertyGroup() - .WithName("content") - .WithKey(groupKey) - .Done() - .Build(); + var contentType = ContentTypeEditingBuilder.CreateContentTypeWithTwoPropertiesOneVariantAndOneInvariant( + "cultureVariationTest", "Culture Variation Test", _variantTitleAlias, _variantTitleName, + _invariantTitleAlias, _invariantTitleName); var contentTypeAttempt = await ContentTypeEditingService.CreateAsync(contentType, Constants.Security.SuperUserKey); if (!contentTypeAttempt.Success) { throw new Exception("Failed to create content type"); } - var rootContentCreateModel = ContentEditingBuilder.CreateContentWithTwoVariantProperties(contentTypeAttempt.Result.Key, "en-US", "da-DK", _variantTitleAlias, _variantTitleName); + var rootContentCreateModel = + ContentEditingBuilder.CreateContentWithTwoVariantProperties(contentTypeAttempt.Result.Key, "en-US", "da-DK", + _variantTitleAlias, _variantTitleName); var result = await ContentEditingService.CreateAsync(rootContentCreateModel, Constants.Security.SuperUserKey); VariantPage = result.Result.Content; } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheMediaTypeTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheMediaTypeTests.cs new file mode 100644 index 000000000000..728f94016986 --- /dev/null +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheMediaTypeTests.cs @@ -0,0 +1,73 @@ +using NUnit.Framework; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.PublishedCache; +using Umbraco.Cms.Core.Services.ContentTypeEditing; +using Umbraco.Cms.Tests.Common.TestHelpers; +using Umbraco.Cms.Tests.Common.Testing; +using Umbraco.Cms.Tests.Integration.Testing; + +namespace Umbraco.Cms.Tests.Integration.Umbraco.PublishedCache.HybridCache; + +[TestFixture] +[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] +public class MediaHybridCacheMediaTypeTests : UmbracoIntegrationTestWithMediaEditing +{ + private IPublishedMediaCache PublishedMediaHybridCache => GetRequiredService(); + + private new IMediaTypeEditingService MediaTypeEditingService => GetRequiredService(); + + protected override void CustomTestSetup(IUmbracoBuilder builder) => builder.AddUmbracoHybridCache(); + + [Test] + public async Task Cannot_Get_Property_From_Media_After_It_Is_Removed_From_MediaType_By_Id() + { + // Arrange + var oldMedia = await PublishedMediaHybridCache.GetByIdAsync(SubTestMediaId); + Assert.IsNotNull(oldMedia.Value("testProperty")); + MediaTypeUpdateHelper mediaTypeUpdateHelper = new MediaTypeUpdateHelper(); + + // Act + var updateModel = mediaTypeUpdateHelper.CreateMediaTypeUpdateModel(CustomMediaType); + updateModel.Properties = []; + updateModel.Containers = []; + await MediaTypeEditingService.UpdateAsync(CustomMediaType, updateModel, Constants.Security.SuperUserKey); + + // Assert + var newMedia = await PublishedMediaHybridCache.GetByIdAsync(SubTestMediaId); + Assert.IsNull(newMedia.Value("testProperty")); + } + + [Test] + public async Task Cannot_Get_Property_From_Media_After_It_Is_Removed_From_MediaType_By_Key() + { + // Arrange + var oldMedia = await PublishedMediaHybridCache.GetByIdAsync(SubTestMedia.Key.Value); + Assert.IsNotNull(oldMedia.Value("testProperty")); + MediaTypeUpdateHelper mediaTypeUpdateHelper = new MediaTypeUpdateHelper(); + + // Act + var updateModel = mediaTypeUpdateHelper.CreateMediaTypeUpdateModel(CustomMediaType); + updateModel.Properties = []; + updateModel.Containers = []; + await MediaTypeEditingService.UpdateAsync(CustomMediaType, updateModel, Constants.Security.SuperUserKey); + + // Assert + var newMedia = await PublishedMediaHybridCache.GetByIdAsync(SubTestMedia.Key.Value); + Assert.IsNull(newMedia.Value("testProperty")); + } + + [Test] + public async Task Media_Gets_Removed_When_MediaType_Is_Deleted() + { + // Arrange + var media = await PublishedMediaHybridCache.GetByIdAsync(SubTestMedia.Key.Value); + Assert.IsNotNull(media); + + // Act + await MediaTypeService.DeleteAsync(CustomMediaType.Key, Constants.Security.SuperUserKey); + + // Assert + var newMedia = await PublishedMediaHybridCache.GetByIdAsync(SubTestMedia.Key.Value); + Assert.IsNull(newMedia); + } +} diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheScopeTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheScopeTests.cs new file mode 100644 index 000000000000..28865201705c --- /dev/null +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheScopeTests.cs @@ -0,0 +1,90 @@ +using NUnit.Framework; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.PublishedCache; +using Umbraco.Cms.Core.Scoping; +using Umbraco.Cms.Tests.Common.Testing; +using Umbraco.Cms.Tests.Integration.Testing; + +namespace Umbraco.Cms.Tests.Integration.Umbraco.PublishedCache.HybridCache; + +[TestFixture] +[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] +public class MediaHybridCacheScopeTests : UmbracoIntegrationTestWithMediaEditing +{ + protected override void CustomTestSetup(IUmbracoBuilder builder) => builder.AddUmbracoHybridCache(); + + private IPublishedMediaCache PublishedMediaHybridCache => GetRequiredService(); + + private ICoreScopeProvider CoreScopeProvider => GetRequiredService(); + + + [Test] + public async Task Can_Get_Media_After_Delete_Was_Rolled_back_With_Id() + { + // Arrange + using (CoreScopeProvider.CreateCoreScope()) + { + await MediaEditingService.DeleteAsync(SubFolder1.Key.Value, Constants.Security.SuperUserKey); + } + + // Act + var media = await PublishedMediaHybridCache.GetByIdAsync(SubFolder1Id); + + // Assert + // media should still be in cache, as we rolled scope back. + Assert.IsNotNull(media); + } + + [Test] + public async Task Can_Get_Media_After_Delete_Was_Rolled_back_With_Key() + { + // Arrange + using (CoreScopeProvider.CreateCoreScope()) + { + await MediaEditingService.DeleteAsync(SubFolder1.Key.Value, Constants.Security.SuperUserKey); + } + + // Act + var media = await PublishedMediaHybridCache.GetByIdAsync(SubFolder1.Key.Value); + + // Assert + // Media should still be in cache, as we rolled scope back. + Assert.IsNotNull(media); + } + + [Test] + public async Task Can_Not_Get_Deleted_Media_After_Scope_Complete_With_Id() + { + // Arrange + using (var scope = CoreScopeProvider.CreateCoreScope()) + { + await MediaEditingService.DeleteAsync(SubFolder1.Key.Value, Constants.Security.SuperUserKey); + scope.Complete(); + } + + // Act + var media = await PublishedMediaHybridCache.GetByIdAsync(SubFolder1Id); + + // Assert + // Media should not be in cache, as we completed the scope for delete. + Assert.IsNull(media); + } + + [Test] + public async Task Can_Not_Get_Deleted_Media_After_Scope_Complete_With_Key() + { + // Arrange + using (var scope = CoreScopeProvider.CreateCoreScope()) + { + await MediaEditingService.DeleteAsync(SubFolder1.Key.Value, Constants.Security.SuperUserKey); + scope.Complete(); + } + + // Act + var textPage = await PublishedMediaHybridCache.GetByIdAsync(SubFolder1.Key.Value); + + // Assert + // Media should not be in cache, as we completed the scope for delete. + Assert.IsNull(textPage); + } +} diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheTests.cs index 7a9aaa5d0d19..f5edf6576238 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheTests.cs @@ -1,12 +1,7 @@ using NUnit.Framework; using Umbraco.Cms.Core; -using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Cms.Core.PublishedCache; -using Umbraco.Cms.Core.Services; -using Umbraco.Cms.Core.Web; -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; @@ -14,175 +9,161 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.PublishedCache.HybridCache; [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] -public class MediaHybridCacheTests : UmbracoIntegrationTest +public class MediaHybridCacheTests : UmbracoIntegrationTestWithMediaEditing { private IPublishedMediaCache PublishedMediaHybridCache => GetRequiredService(); - private IUmbracoContextFactory UmbracoContextFactory => GetRequiredService(); - - private IMediaTypeService MediaTypeService => GetRequiredService(); - - private IMediaEditingService MediaEditingService => GetRequiredService(); - protected override void CustomTestSetup(IUmbracoBuilder builder) => builder.AddUmbracoHybridCache(); - // TODO: make test with MediaWithCrops - + // Media with crops [Test] - public async Task Can_Get_Media_By_Key() + public async Task Can_Get_Root_Media_By_Id() { - // Arrange - var newMediaType = new MediaTypeBuilder() - .WithAlias("album") - .WithName("Album") - .Build(); + // Act + var media = await PublishedMediaHybridCache.GetByIdAsync(RootFolderId); - newMediaType.AllowedAsRoot = true; - MediaTypeService.Save(newMediaType); + // Assert + Assert.IsNotNull(media); + Assert.AreEqual("RootFolder", media.Name); + Assert.AreEqual(RootFolder.ContentTypeKey, media.ContentType.Key); + } - var createModel = new MediaCreateModel - { - ContentTypeKey = newMediaType.Key, - ParentKey = Constants.System.RootKey, - InvariantName = "Image", - }; + [Test] + public async Task Can_Get_Root_Media_By_Key() + { + var media = await PublishedMediaHybridCache.GetByIdAsync(RootFolder.Key.Value); - var result = await MediaEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); - Assert.IsTrue(result.Success); + // Assert + Assert.IsNotNull(media); + Assert.AreEqual("RootFolder", media.Name); + Assert.AreEqual(RootFolder.ContentTypeKey, media.ContentType.Key); + } + [Test] + public async Task Can_Get_Child_Media_By_Id() + { // Act - var media = await PublishedMediaHybridCache.GetByKeyAsync(result.Result.Content.Key); + var media = await PublishedMediaHybridCache.GetByIdAsync(SubImageId); // Assert Assert.IsNotNull(media); - Assert.AreEqual("Image", media.Name); - Assert.AreEqual(newMediaType.Key, media.ContentType.Key); + Assert.AreEqual("SubImage", media.Name); + Assert.AreEqual(SubImage.ContentTypeKey, media.ContentType.Key); + Assert.AreEqual(SubImage.ParentKey, RootFolder.Key); } + [Test] - public async Task Can_Get_Media_By_Id() + public async Task Can_Get_Child_Media_By_Key() { - // Arrange - var newMediaType = new MediaTypeBuilder() - .WithAlias("album") - .WithName("Album") - .Build(); - - newMediaType.AllowedAsRoot = true; - MediaTypeService.Save(newMediaType); + var media = await PublishedMediaHybridCache.GetByIdAsync(SubImage.Key.Value); - var createModel = new MediaCreateModel - { - ContentTypeKey = newMediaType.Key, - ParentKey = Constants.System.RootKey, - InvariantName = "Image", - }; - - var result = await MediaEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); - Assert.IsTrue(result.Success); + // Assert + Assert.IsNotNull(media); + Assert.AreEqual("SubImage", media.Name); + Assert.AreEqual(SubImage.ContentTypeKey, media.ContentType.Key); + Assert.AreEqual(SubImage.ParentKey, RootFolder.Key); + } + [Test] + public async Task Cannot_Get_Non_Existing_Media_By_Id() + { // Act - var media = await PublishedMediaHybridCache.GetByIdAsync(result.Result.Content.Id); + const int nonExistingId = 124214; + var media = await PublishedMediaHybridCache.GetByIdAsync(nonExistingId); // Assert - Assert.IsNotNull(media); - Assert.AreEqual("Image", media.Name); - Assert.AreEqual(newMediaType.Key, media.ContentType.Key); + Assert.IsNull(media); } [Test] public async Task Cannot_Get_Non_Existing_Media_By_Key() { // Act - var media = await PublishedMediaHybridCache.GetByKeyAsync(Guid.NewGuid()); + var media = await PublishedMediaHybridCache.GetByIdAsync(Guid.NewGuid()); // Assert Assert.IsNull(media); } [Test] - public async Task Cannot_Get_Non_Existing_Media_By_Id() + public async Task Can_Get_Media_Property_By_Id() { // Act - var media = await PublishedMediaHybridCache.GetByIdAsync(124214); + var media = await PublishedMediaHybridCache.GetByIdAsync(SubTestMediaId); // Assert - Assert.IsNull(media); + Assert.IsNotNull(media); + Assert.AreEqual("SubTestMedia", media.Name); + Assert.AreEqual("This is a test", media.Value("testProperty")); } [Test] public async Task Can_Get_Media_Property_By_Key() { - // Arrange - var media = await CreateMedia(); - // Act - var publishedMedia = await PublishedMediaHybridCache.GetByKeyAsync(media.Key); - - UmbracoContextFactory.EnsureUmbracoContext(); + var media = await PublishedMediaHybridCache.GetByIdAsync(SubTestMedia.Key.Value); // Assert Assert.IsNotNull(media); - Assert.AreEqual("Image", media.Name); - Assert.AreEqual("NewTitle", publishedMedia.Value("title")); + Assert.AreEqual("SubTestMedia", media.Name); + Assert.AreEqual("This is a test", media.Value("testProperty")); } [Test] - public async Task Can_Get_Media_Property_By_Id() + public async Task Can_Get_Updated_Media_By_Id() { // Arrange - var media = await CreateMedia(); + const string newName = "NewImageName"; + var media = await PublishedMediaHybridCache.GetByIdAsync(SubImageId); + Assert.AreEqual(media.Name, "SubImage"); - // Act - var publishedMedia = await PublishedMediaHybridCache.GetByKeyAsync(media.Key); + var mediaUpdateModel = new MediaUpdateModel + { + InvariantName = newName, + InvariantProperties = SubImage.InvariantProperties, + Variants = SubImage.Variants, + }; - UmbracoContextFactory.EnsureUmbracoContext(); + // Act + await MediaEditingService.UpdateAsync(SubImage.Key.Value, mediaUpdateModel, Constants.Security.SuperUserKey); + var updatedMedia = await PublishedMediaHybridCache.GetByIdAsync(SubImageId); // Assert - Assert.IsNotNull(publishedMedia); - Assert.AreEqual("Image", publishedMedia.Name); - Assert.AreEqual("NewTitle", publishedMedia.Value("title")); + Assert.IsNotNull(updatedMedia); + Assert.AreEqual(newName, updatedMedia.Name); } [Test] - public async Task Can_Get_Updated_Media() + public async Task Can_Get_Updated_Media_By_Key() { // Arrange - var media = await CreateMedia(); - await PublishedMediaHybridCache.GetByIdAsync(media.Id); + const string newName = "NewImageName"; + var media = await PublishedMediaHybridCache.GetByIdAsync(SubImage.Key.Value); + Assert.AreEqual(media.Name, "SubImage"); - // Act - var updateModel = new MediaUpdateModel() + var mediaUpdateModel = new MediaUpdateModel { - InvariantName = "Update name", - InvariantProperties = new List() - { - new() - { - Alias = "title", - Value = "Updated Title" - } - } + InvariantName = newName, + InvariantProperties = SubImage.InvariantProperties, + Variants = SubImage.Variants, }; - var updateAttempt = await MediaEditingService.UpdateAsync(media.Key, updateModel, Constants.Security.SuperUserKey); - Assert.IsTrue(updateAttempt.Success); - var publishedMedia = await PublishedMediaHybridCache.GetByIdAsync(media.Id); - UmbracoContextFactory.EnsureUmbracoContext(); + // Act + await MediaEditingService.UpdateAsync(SubImage.Key.Value, mediaUpdateModel, Constants.Security.SuperUserKey); + var updatedMedia = await PublishedMediaHybridCache.GetByIdAsync(SubImageId); // Assert - Assert.IsNotNull(publishedMedia); - Assert.AreEqual("Update name", publishedMedia.Name); - Assert.AreEqual("Updated Title", publishedMedia.Value("title")); + Assert.IsNotNull(updatedMedia); + Assert.AreEqual(newName, updatedMedia.Name); } [Test] public async Task Cannot_Get_Deleted_Media_By_Id() { // Arrange - var media = await CreateMedia(); - var publishedMedia = await PublishedMediaHybridCache.GetByIdAsync(media.Id); - Assert.IsNotNull(publishedMedia); + var media = await PublishedMediaHybridCache.GetByIdAsync(SubImageId); + Assert.IsNotNull(media); await MediaEditingService.DeleteAsync(media.Key, Constants.Security.SuperUserKey); @@ -197,42 +178,16 @@ public async Task Cannot_Get_Deleted_Media_By_Id() public async Task Cannot_Get_Deleted_Media_By_Key() { // Arrange - var media = await CreateMedia(); - var publishedMedia = await PublishedMediaHybridCache.GetByKeyAsync(media.Key); - Assert.IsNotNull(publishedMedia); + var media = await PublishedMediaHybridCache.GetByIdAsync(SubImage.Key.Value); + + Assert.IsNotNull(media); await MediaEditingService.DeleteAsync(media.Key, Constants.Security.SuperUserKey); // Act - var deletedMedia = await PublishedMediaHybridCache.GetByKeyAsync(media.Key); + var deletedMedia = await PublishedMediaHybridCache.GetByIdAsync(media.Key); // Assert Assert.IsNull(deletedMedia); } - - private async Task CreateMedia() - { - IMediaType mediaType = MediaTypeBuilder.CreateSimpleMediaType("test", "Test"); - mediaType.AllowedAsRoot = true; - MediaTypeService.Save(mediaType); - - var createModel = new MediaCreateModel - { - ContentTypeKey = mediaType.Key, - ParentKey = Constants.System.RootKey, - InvariantName = "Image", - InvariantProperties = new List() - { - new() - { - Alias = "title", - Value = "NewTitle" - } - } - }; - - var result = await MediaEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); - Assert.IsTrue(result.Success); - return result.Result.Content; - } } diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Models/ContentTypeTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Models/ContentTypeTests.cs index 8956acb83960..8aa6aa252e75 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Models/ContentTypeTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Models/ContentTypeTests.cs @@ -61,7 +61,8 @@ public void Can_Deep_Clone_Content_Type_Sort() private ContentTypeSort BuildContentTypeSort() { - var builder = new ContentTypeSortBuilder(); + ContentTypeBuilder contentTypeBuilder = new ContentTypeBuilder(); + var builder = new ContentTypeSortBuilder(contentTypeBuilder); return builder .WithKey(new Guid("4CAE063E-0BE1-4972-B10C-A3D9BB7DE856")) .WithSortOrder(4)