V15 QA Hybrid Cache added media cache tests and fixed media cache refreshing (#17160)

* Add cache refresher

* make public as needed for serialization

* Use content type cache to get content type out

* Refactor to use ContentCacheNode model, that goes in the memory cache

* Remove content node kit as its not needed

* Implement tests for ensuring caching

* Implement better asserts

* Implement published property

* Refactor to use mapping

* Rename to document tests

* Update to test properties

* Create more tests

* Refactor mock tests into own file

* Update property test

* Fix published version of content

* Change default cache level to elements

* Refactor to always have draft

* Refactor to not use PublishedModelFactory

* Added tests

* Added and updated tests

* Fixed tests

* Don't return empty object with id

* More tests

* Added key

* Another key

* Refactor CacheService to be responsible for using the hybrid cache

* Use notification handler to remove deleted content from cache

* Add more tests for missing functions

* Implement missing methods

* Remove HasContent as it pertains to routing

* Fik up test

* formatting

* refactor variable names

* Implement variant tests

* Map all the published content properties

* Get item out of cache first, to assert updated

* Implement member cache

* Add member test

* Implement media cache

* Implement property tests for media tests

* Refactor tests to use extension method

* Add more media tests

* Refactor properties to no longer have element caching

* Don't use property cache level

* Start implementing seeding

* Only seed when main

* Add Immutable for performance

* Implement permanent seeding of content

* Implement cache settings

* Implement tests for seeding

* Update package version

* start refactoring nurepo

* Refactor so draft & published nodes are cached individually

* Refactor RefreshContent to take node instead of IContent

* Refactor media to also use cache nodes

* Remove member from repo as it isn't cached

* Refactor media to not include preview, as media has no draft

* create new benchmark project

* POC Integration benchmarks with custom api controllers

* Start implementing content picker tests

* Implement domain cache

* Rework content cache to implement interface

* Start implementing elements cache

* Implement published snapshot service

* Publish snapshot tests

* Use snapshot for elements cache

* Create test proving we don't clear cache when updating content picker

* Clear entire elements cache

* Remove properties from element cache, when content gets updated.

* Rename methods to async

* Refactor to use old cache interfaces instead of new ones

* Remove snapshot, as it is no longer needed

* Fix tests building

* Refactor domaincache to not have snapshots

* Delete benchmarks

* Delete benchmarks

* Add HybridCacheProject to Umbraco

* Add comment to route value transformer

* Implement is draft

* remove snapshot from property

* V15 updated the hybrid caching integration tests to use ContentEditingService (#16947)

* Added builder extension withParentKey

* Created builder with ContentEditingService

* Added usage of the ContentEditingService to SETUP

* Started using ContentEditingService builder in tests

* Updated builder extensions

* Fixed builder

* Clean up

* Clean up, not done

* Added Ids

* Remove entries from cache on delete

* Fix up seeding logic

* Don't register hybrid cache twice

* Change seeded entry options

* Update hybrid cache package

* Fix up published property to work with delivery api again

* Fix dependency injection to work with tests

* Fix naming

* Dont make caches nullable

* Make content node sealed

* Remove path and other unused from content node

* Remove hacky 2 phase ctor

* Refactor to actually set content templates

* Remove umbraco context

* Remove "HasBy" methods

* rename property data

* Delete obsolete legacy stuff

* Add todo for making expiration configurable

* Add todo in UmbracoContext

* Add clarifying comment in content factory

* Remove xml stuff from published property

* Fix according to review

* Make content type cache injectible

* Make content type cache injectible

* Rename to database cache repository

* Rename to document cache

* Add TODO

* Refactor to async

* Rename to async

* Make everything async

* Remove duplicate line from json schema

* Move Hybrid cache project

* Remove leftover file

* Refactor to use keys

* Refactor published content to no longer have content data, as it is on the node itself

* Refactor to member to use proper content node ctor

* Move tests to own folder

* Add immutable objects to property and content data for performance

* Make property data public

* Fix member caching to be singleton

* Obsolete GetContentType

* Remove todo

* Fix naming

* Fix lots of exposed errors due to scope test

* Add final scope tests

* Rename to document cache service

* Rename test files

* Create new doc type tests

* Add ignore to tests

* Start implementing refresh for content type save

* Clear contenttype cache when contenttype is updated

* Fix test

Teh contenttype is not upated unless the property is dirty

* Updated tests

* Added tests

* Use init for ContentSourceDto

* Startup of setup

* Fix get by key in PublishedContentTypeCache

* Remove ContentType from PublishedContentTypeCache when contenttype is deleted

* Created interfaces for the builder with the necessary properties

* Created builder for PropertyTypeContainer

* Created builder for PropertyTypeEditing

* Created builder for PropertyTypeValidationEditing

* Made adjustments to the builder

* Updated name of usage

* Commented out to test

* Cleaned up builders

* Updated integration test setup

* Moved tests

* Added interface

* Add IDocumentSeedKeyProvider and migrate existing logic to seed key provider

* Added functionality to the INavigationQueryService to get root keys

* Fixed issue with navigation

* Created helper to Convert a IContentType to ContentTypeUpdateModel

* Added interfaces

* Added builder

* Cleaned up builders and added fixes

* Added tests for PublishedContentTypeCache

* Applied changes in builder

* Add BreadthFirstKeyProvider

* Use ISet for seedkey providers

* Implement GetContentSource by key

* Seed the cache with keys provided by seed key providers

* Builder updates

* Test setup updates

* Updated tests

* Dont require contenttype keys for seeding

* Fix cache settings

* Don't inject cache settings into SeedingNotificationHandler

* Fix tests

* Use enlistment for setting updated cache item

* Pin seeded nodes for longer

* Fix BreadthFirstKeyProvider

* Fix ContentTypeSeedKeyProvider

* Fix tests

* Only seed published documents

* Only cache published if contentCacheNode is not draft

* Fix incorrect templateId

* Removed unnecessary setup

* initialized value

* Fixed template test

* Removed test

* Updated tests

* Removed code that was not used

* Removed unused cacheSettings

* Re-organize to support media cache seeding

* Add MediaBreadthFirstKeyProvider

* Seed media

* Don't use IdKeyMap when removing content from cache

* Don't clear IdKeyMap in DocumentCacheService

* Add unit tests

* Don't use IdKeyMap when deleting media

* Add default value to timespan

* Use cancellation tokens when doing loop

* Fixed Models Builder error

* Builder testing

* Media test

* Created builders

* Updated method from getByKey to getById to maintain structure

* Updated test setup

* Moved tests

* Cleaned up builders

* Added helper

* Added space

* Updated tests

* Cleaned setup

* Added tests for MediaTypes

* Uncommented tests

* Added builder extensions

* Added interfaces for builder methods

* Updated to use interface pattern

* Updated name

* Used builder

* Cleaned up test

* Added media scope tests

* Removed PropertyTypeModelBuilder

* moved PropertyTypeModelBuilder to PropertyTypeEditingBuilder

* Removed constructor

* Removed duplicate

* Fixed naming

* Reverted

* Removed space

* Added todos

* Removed only run on linux

* Commet out DocumentHybridCacheTemplateTest again

This is fixed in the release branch

* Update media when media type is updated

* Remove todo the tests pass now

---------

Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>
Co-authored-by: Zeegaan <skrivdetud@gmail.com>
Co-authored-by: Sven Geusens <sge@umbraco.dk>
Co-authored-by: nikolajlauridsen <nikolajlauridsen@protonmail.ch>
Co-authored-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
Andreas Zerbst
2024-10-02 13:36:26 +02:00
committed by GitHub
parent c2d83808a5
commit e15b7f2214
51 changed files with 1313 additions and 680 deletions

View File

@@ -18,5 +18,5 @@ public interface IPublishedMediaCache : IPublishedCache
/// <param name="key">The content unique identifier.</param>
/// <returns>The content, or null.</returns>
/// <remarks>Considers published or unpublished content depending on defaults.</remarks>
Task<IPublishedContent?> GetByKeyAsync(Guid key);
Task<IPublishedContent?> GetByIdAsync(Guid key);
}

View File

@@ -65,6 +65,8 @@ public static class UmbracoBuilderExtensions
builder.AddNotificationAsyncHandler<MediaDeletedNotification, CacheRefreshingNotificationHandler>();
builder.AddNotificationAsyncHandler<ContentTypeRefreshedNotification, CacheRefreshingNotificationHandler>();
builder.AddNotificationAsyncHandler<ContentTypeDeletedNotification, CacheRefreshingNotificationHandler>();
builder.AddNotificationAsyncHandler<MediaTypeRefreshedNotification, CacheRefreshingNotificationHandler>();
builder.AddNotificationAsyncHandler<MediaTypeDeletedNotification, CacheRefreshingNotificationHandler>();
builder.AddNotificationAsyncHandler<UmbracoApplicationStartedNotification, SeedingNotificationHandler>();
builder.AddCacheSeeding();
return builder;

View File

@@ -18,17 +18,17 @@ public class MediaCache : IPublishedMediaCache
public async Task<IPublishedContent?> GetByIdAsync(int id) => await _mediaCacheService.GetByIdAsync(id);
public async Task<IPublishedContent?> GetByKeyAsync(Guid key) => await _mediaCacheService.GetByKeyAsync(key);
public async Task<IPublishedContent?> 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);

View File

@@ -19,7 +19,9 @@ internal sealed class CacheRefreshingNotificationHandler :
INotificationAsyncHandler<MediaRefreshNotification>,
INotificationAsyncHandler<MediaDeletedNotification>,
INotificationAsyncHandler<ContentTypeRefreshedNotification>,
INotificationAsyncHandler<ContentTypeDeletedNotification>
INotificationAsyncHandler<ContentTypeDeletedNotification>,
INotificationAsyncHandler<MediaTypeRefreshedNotification>,
INotificationAsyncHandler<MediaTypeDeletedNotification>
{
private readonly IDocumentCacheService _documentCacheService;
private readonly IMediaCacheService _mediaCacheService;
@@ -126,7 +128,7 @@ internal sealed class CacheRefreshingNotificationHandler :
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 @@ internal sealed class CacheRefreshingNotificationHandler :
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;
}
}

View File

@@ -237,7 +237,7 @@ AND cmsContentNu.nodeId IS NULL
return CreateContentNodeKit(dto, serializer, preview);
}
private IEnumerable<ContentSourceDto> GetContentSourceByDocumentTypeKey(IEnumerable<Guid> documentTypeKeys)
private IEnumerable<ContentSourceDto> GetContentSourceByDocumentTypeKey(IEnumerable<Guid> documentTypeKeys, Guid objectType)
{
Guid[] keys = documentTypeKeys.ToArray();
if (keys.Any() is false)
@@ -248,19 +248,27 @@ AND cmsContentNu.nodeId IS NULL
Sql<ISqlContext>? sql = SqlContentSourcesSelect()
.InnerJoin<NodeDto>("n")
.On<NodeDto, ContentDto>((n, c) => n.NodeId == c.ContentTypeId, "n", "umbracoContent")
.Append(SqlObjectTypeNotTrashed(SqlContext, Constants.ObjectTypes.Document))
.Append(SqlObjectTypeNotTrashed(SqlContext, objectType))
.WhereIn<NodeDto>(x => x.UniqueId, keys,"n")
.Append(SqlOrderByLevelIdSortOrder(SqlContext));
return GetContentNodeDtos(sql);
}
public IEnumerable<ContentCacheNode> GetContentByContentTypeKey(IEnumerable<Guid> keys)
public IEnumerable<ContentCacheNode> GetContentByContentTypeKey(IEnumerable<Guid> keys, ContentCacheDataSerializerEntityType entityType)
{
IEnumerable<ContentSourceDto> 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<ContentSourceDto> dtos = GetContentSourceByDocumentTypeKey(keys, objectType);
IContentCacheDataSerializer serializer =
_contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Document);
_contentCacheDataSerializerFactory.Create(entityType);
foreach (ContentSourceDto row in dtos)
{
@@ -269,8 +277,8 @@ AND cmsContentNu.nodeId IS NULL
}
/// <inheritdoc />
public IEnumerable<Guid> GetContentKeysByContentTypeKeys(IEnumerable<Guid> keys, bool published = false)
=> GetContentSourceByDocumentTypeKey(keys).Where(x => x.Published == published).Select(x => x.Key);
public IEnumerable<Guid> GetDocumentKeysByContentTypeKeys(IEnumerable<Guid> keys, bool published = false)
=> GetContentSourceByDocumentTypeKey(keys, Constants.ObjectTypes.Document).Where(x => x.Published == published).Select(x => x.Key);
public async Task<ContentCacheNode?> GetMediaSourceAsync(int id)
{

View File

@@ -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<ContentCacheNode?> GetMediaSourceAsync(Guid key);
IEnumerable<ContentCacheNode> GetContentByContentTypeKey(IEnumerable<Guid> keys);
IEnumerable<ContentCacheNode> GetContentByContentTypeKey(IEnumerable<Guid> keys, ContentCacheDataSerializerEntityType entityType);
/// <summary>
/// Gets all content keys of specific document types
/// </summary>
/// <param name="keys">The document types to find content using.</param>
/// <returns>The keys of all content use specific document types.</returns>
IEnumerable<Guid> GetContentKeysByContentTypeKeys(IEnumerable<Guid> keys, bool published = false);
IEnumerable<Guid> GetDocumentKeysByContentTypeKeys(IEnumerable<Guid> keys, bool published = false);
/// <summary>
/// Refreshes the nucache database row for the given cache node />

View File

@@ -24,7 +24,7 @@ internal sealed class ContentTypeSeedKeyProvider : IDocumentSeedKeyProvider
public ISet<Guid> 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;

View File

@@ -7,6 +7,7 @@ using Umbraco.Cms.Core.Scoping;
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 @@ internal sealed class DocumentCacheService : IDocumentCacheService
public IEnumerable<IPublishedContent> GetByContentType(IPublishedContentType contentType)
{
using ICoreScope scope = _scopeProvider.CreateCoreScope();
IEnumerable<ContentCacheNode> nodes = _databaseCacheRepository.GetContentByContentTypeKey([contentType.Key]);
IEnumerable<ContentCacheNode> nodes = _databaseCacheRepository.GetContentByContentTypeKey([contentType.Key], ContentCacheDataSerializerEntityType.Document);
scope.Complete();
return nodes
@@ -239,11 +240,11 @@ internal sealed class DocumentCacheService : IDocumentCacheService
scope.Complete();
}
public void Rebuild(IReadOnlyCollection<int> contentTypeKeys)
public void Rebuild(IReadOnlyCollection<int> contentTypeIds)
{
using ICoreScope scope = _scopeProvider.CreateCoreScope();
_databaseCacheRepository.Rebuild(contentTypeKeys.ToList());
IEnumerable<ContentCacheNode> contentByContentTypeKey = _databaseCacheRepository.GetContentByContentTypeKey(contentTypeKeys.Select(x => _idKeyMap.GetKeyForId(x, UmbracoObjectTypes.DocumentType).Result));
_databaseCacheRepository.Rebuild(contentTypeIds.ToList());
IEnumerable<ContentCacheNode> contentByContentTypeKey = _databaseCacheRepository.GetContentByContentTypeKey(contentTypeIds.Select(x => _idKeyMap.GetKeyForId(x, UmbracoObjectTypes.DocumentType).Result), ContentCacheDataSerializerEntityType.Document);
foreach (ContentCacheNode content in contentByContentTypeKey)
{

View File

@@ -17,7 +17,7 @@ public interface IDocumentCacheService
Task DeleteItemAsync(IContentBase content);
void Rebuild(IReadOnlyCollection<int> contentTypeKeys);
void Rebuild(IReadOnlyCollection<int> contentTypeIds);
internal IEnumerable<IPublishedContent> GetByContentType(IPublishedContentType contentType);
}

View File

@@ -16,4 +16,6 @@ public interface IMediaCacheService
Task DeleteItemAsync(IContentBase media);
Task SeedAsync(CancellationToken cancellationToken);
void Rebuild(IReadOnlyCollection<int> contentTypeIds);
}

View File

@@ -7,6 +7,7 @@ using Umbraco.Cms.Core.Scoping;
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 @@ internal class MediaCacheService : IMediaCacheService
scope.Complete();
}
public void Rebuild(IReadOnlyCollection<int> contentTypeIds)
{
using ICoreScope scope = _scopeProvider.CreateCoreScope();
_databaseCacheRepository.Rebuild(contentTypeIds.ToList());
IEnumerable<Guid> mediaTypeKeys = contentTypeIds.Select(x => _idKeyMap.GetKeyForId(x, UmbracoObjectTypes.MediaType))
.Where(x => x.Success)
.Select(x => x.Result);
IEnumerable<ContentCacheNode> 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,

View File

@@ -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<TCreateModel> : BuilderBase<TCreateModel>,
IWithInvariantNameBuilder,
IWithKeyBuilder,
IWithContentTypeKeyBuilder,
IWithParentKeyBuilder,
IBuildContentTypes
where TCreateModel : ContentCreationModelBase, new()
{
protected TCreateModel _model = new();
private List<ContentEditingPropertyValueBuilder<ContentEditingBaseBuilder<TCreateModel>>> _invariantProperties = [];
private List<ContentEditingVariantBuilder<ContentEditingBaseBuilder<TCreateModel>>> _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<ContentEditingBaseBuilder<TCreateModel>> AddInvariantProperty()
{
var builder = new ContentEditingPropertyValueBuilder<ContentEditingBaseBuilder<TCreateModel>>(this);
_invariantProperties.Add(builder);
return builder;
}
public ContentEditingVariantBuilder<ContentEditingBaseBuilder<TCreateModel>> AddVariant()
{
var builder = new ContentEditingVariantBuilder<ContentEditingBaseBuilder<TCreateModel>>(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;
}
}

View File

@@ -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<ContentCreateModel>,
IWithInvariantNameBuilder,
IWithInvariantPropertiesBuilder,
IWithVariantsBuilder,
IWithKeyBuilder,
IWithContentTypeKeyBuilder,
IWithParentKeyBuilder,
IWithTemplateKeyBuilder,
IBuildContentTypes
public class ContentEditingBuilder : ContentEditingBaseBuilder<ContentCreateModel>, IWithTemplateKeyBuilder
{
private ContentTypeEditingBuilder _contentTypeEditingBuilder;
private IEnumerable<PropertyValueModel> _invariantProperties = [];
private IEnumerable<VariantModel> _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<PropertyValueModel> IWithInvariantPropertiesBuilder.InvariantProperties
{
get => _invariantProperties;
set => _invariantProperties = value;
}
IEnumerable<VariantModel> 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 @@ public class ContentEditingBuilder
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<PropertyValueModel> 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 class ContentEditingBuilder
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 class ContentEditingBuilder
.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();
}

View File

@@ -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>(TParent parentBuilder)
: ChildBuilderBase<TParent, PropertyValueModel>(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 };
}

View File

@@ -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>(TParent parentBuilder)
: ChildBuilderBase<TParent, VariantModel>(parentBuilder), IWithCultureBuilder, IWithSegmentBuilder, IWithNameBuilder
{
private string? _culture;
private string? _segment;
private string _name;
private readonly List<ContentEditingPropertyValueBuilder<ContentEditingVariantBuilder<TParent>>> _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<ContentEditingVariantBuilder<TParent>> AddProperty()
{
var builder = new ContentEditingPropertyValueBuilder<ContentEditingVariantBuilder<TParent>>((ContentEditingVariantBuilder<TParent>)this);
_properties.Add(builder);
return builder;
}
public override VariantModel Build() =>
new()
{
Culture = _culture,
Segment = _segment,
Name = _name,
Properties = _properties.Select(x => x.Build()).ToList(),
};
}

View File

@@ -16,7 +16,7 @@ public class ContentTypeBuilder
IWithPropertyTypeIdsIncrementingFrom,
IBuildPropertyTypes
{
private readonly List<ContentTypeSortBuilder> _allowedContentTypeBuilders = new();
private readonly List<ContentTypeSortBuilder<ContentTypeBuilder>> _allowedContentTypeBuilders = new();
private readonly List<PropertyTypeBuilder<ContentTypeBuilder>> _noGroupPropertyTypeBuilders = new();
private readonly List<PropertyGroupBuilder<ContentTypeBuilder>> _propertyGroupBuilders = new();
private readonly List<TemplateBuilder> _templateBuilders = new();
@@ -88,9 +88,9 @@ public class ContentTypeBuilder
return builder;
}
public ContentTypeSortBuilder AddAllowedContentType()
public ContentTypeSortBuilder<ContentTypeBuilder> AddAllowedContentType()
{
var builder = new ContentTypeSortBuilder(this);
var builder = new ContentTypeSortBuilder<ContentTypeBuilder>(this);
_allowedContentTypeBuilders.Add(builder);
return builder;
}

View File

@@ -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<TBuilder, TCreateModel, TPropertyType, TPropertyTypeContainer> :
IWithAliasBuilder, IWithNameBuilder, IWithDescriptionBuilder, IWithIconBuilder, IWithAllowAsRootBuilder,
IWithIsElementBuilder, IWithVariesByCultureBuilder,
IWithVariesBySegmentBuilder
where TBuilder : ContentTypeEditingBaseBuilder<TBuilder, TCreateModel, TPropertyType, TPropertyTypeContainer>
where TCreateModel : ContentTypeEditingModelBase<TPropertyType, TPropertyTypeContainer>, 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<PropertyTypeEditingBuilder<TBuilder, TPropertyType>> _propertyTypeBuilders = new();
private readonly List<PropertyTypeContainerBuilder<TBuilder, TPropertyTypeContainer>> _propertyTypeContainerBuilders = new();
private readonly List<ContentTypeSortBuilder<TBuilder>> _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<TBuilder, TPropertyType> AddPropertyType()
{
var builder = new PropertyTypeEditingBuilder<TBuilder, TPropertyType>((TBuilder)this);
_propertyTypeBuilders.Add(builder);
return builder;
}
public PropertyTypeContainerBuilder<TBuilder, TPropertyTypeContainer> AddPropertyGroup()
{
var builder = new PropertyTypeContainerBuilder<TBuilder, TPropertyTypeContainer>((TBuilder)this);
_propertyTypeContainerBuilders.Add(builder);
return builder;
}
public ContentTypeSortBuilder<TBuilder> AddAllowedContentType()
{
var builder = new ContentTypeSortBuilder<TBuilder>((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;
}
}

View File

@@ -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<ContentEditingBuilder, ContentTypeCreateModel>,
IBuildPropertyTypes
public class ContentTypeEditingBuilder : ContentTypeEditingBaseBuilder<ContentTypeEditingBuilder, ContentTypeCreateModel, ContentTypePropertyTypeModel, ContentTypePropertyContainerModel>, IWithKeyBuilder, IWithContainerKeyBuilder, IWithDefaultTemplateKeyBuilder
{
private Guid? _key;
private Guid? _containerKey;
private ContentTypeCleanup _cleanup = new();
private IEnumerable<Guid> _allowedTemplateKeys;
private IEnumerable<Guid> _allowedTemplateKeys = Array.Empty<Guid>();
private Guid? _defaultTemplateKey;
private bool? _allowAtRoot;
private bool? _isElement;
private bool? _variesByCulture;
private bool? _variesBySegment;
private readonly List<PropertyTypeEditingBuilder> _propertyTypeBuilders = [];
private readonly List<PropertyTypeContainerBuilder<ContentTypeEditingBuilder>> _propertyTypeContainerBuilders = [];
private readonly List<ContentTypeSortBuilder> _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<ContentTypeEditingBuilder> AddPropertyGroup()
{
var builder = new PropertyTypeContainerBuilder<ContentTypeEditingBuilder>(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<Guid> templateKeys)
@@ -73,64 +36,33 @@ public class ContentTypeEditingBuilder
return this;
}
public ContentTypeEditingBuilder WithAllowAtRoot(bool allowAtRoot)
protected override ContentTypeCreateModel Build()
{
_allowAtRoot = allowAtRoot;
return this;
_model.Key = _key ?? Guid.NewGuid();
_model.ContainerKey = _containerKey;
_model.AllowedTemplateKeys = _allowedTemplateKeys;
_model.DefaultTemplateKey = _defaultTemplateKey;
base.Build();
return _model;
}
public ContentTypeEditingBuilder WithVariesByCulture(bool variesByCulture)
{
_variesByCulture = variesByCulture;
return this;
}
public ContentTypeEditingBuilder WithVariesBySegment(bool variesBySegment)
{
_variesBySegment = variesBySegment;
return this;
}
public 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<Guid>();
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;
}
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 class ContentTypeEditingBuilder
return (ContentTypeCreateModel)builder
.WithAlias(alias)
.WithName(name)
.WithAllowAtRoot(true)
.WithAllowAsRoot(true)
.AddPropertyGroup()
.WithName("Content")
.WithKey(containerKeyOne)
@@ -237,4 +169,53 @@ public class ContentTypeEditingBuilder
.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();
}
}

View File

@@ -8,8 +8,8 @@ using Umbraco.Cms.Tests.Common.Builders.Interfaces;
namespace Umbraco.Cms.Tests.Common.Builders;
public class ContentTypeSortBuilder
: ChildBuilderBase<ContentTypeBuilder, ContentTypeSort>,
public class ContentTypeSortBuilder<TBuilder>
: ChildBuilderBase<TBuilder, ContentTypeSort>,
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;

View File

@@ -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 class BuilderExtensions
return builder;
}
public static T WithPropertyValues<T>(this T builder, object propertyValues, string? culture = null, string? segment = null)
public static T WithPropertyValues<T>(this T builder, object propertyValues, string? culture = null,
string? segment = null)
where T : IWithPropertyValues
{
builder.PropertyValues = propertyValues;
@@ -247,4 +247,102 @@ public static class BuilderExtensions
builder.Date = date;
return builder;
}
public static T WithInvariantName<T>(this T builder, string invariantName)
where T : IWithInvariantNameBuilder
{
builder.InvariantName = invariantName;
return builder;
}
public static T WithKey<T>(this T builder, Guid? key)
where T : IWithKeyBuilder
{
builder.Key = key;
return builder;
}
public static T WithContentTypeKey<T>(this T builder, Guid contentTypeKey)
where T : IWithContentTypeKeyBuilder
{
builder.ContentTypeKey = contentTypeKey;
return builder;
}
public static T WithParentKey<T>(this T builder, Guid? parentKey)
where T : IWithParentKeyBuilder
{
builder.ParentKey = parentKey;
return builder;
}
public static T WithTemplateKey<T>(this T builder, Guid? templateKey)
where T : IWithTemplateKeyBuilder
{
builder.TemplateKey = templateKey;
return builder;
}
public static T WithValue<T>(this T builder, object? value)
where T : IWithValueBuilder
{
builder.Value = value;
return builder;
}
public static T WithCulture<T>(this T builder, string culture)
where T : IWithCultureBuilder
{
builder.Culture = culture;
return builder;
}
public static T WithAllowAsRoot<T>(this T builder, bool allowAsRoot)
where T : IWithAllowAsRootBuilder
{
builder.AllowAsRoot = allowAsRoot;
return builder;
}
public static T WithSegment<T>(this T builder, string segment)
where T : IWithSegmentBuilder
{
builder.Segment = segment;
return builder;
}
public static T WithIsElement<T>(this T builder, bool isElement)
where T : IWithIsElementBuilder
{
builder.IsElement = isElement;
return builder;
}
public static T WithVariesByCulture<T>(this T builder, bool variesByCulture)
where T : IWithVariesByCultureBuilder
{
builder.VariesByCulture = variesByCulture;
return builder;
}
public static T WithVariesBySegement<T>(this T builder, bool variesBySegment)
where T : IWithVariesBySegmentBuilder
{
builder.VariesBySegment = variesBySegment;
return builder;
}
public static T WithDefaultTemplateKey<T>(this T builder, Guid? defaultTemplateKey)
where T : IWithDefaultTemplateKeyBuilder
{
builder.DefaultTemplateKey = defaultTemplateKey;
return builder;
}
public static T WithContainerKey<T>(this T builder, Guid? containerKey)
where T : IWithContainerKeyBuilder
{
builder.ContainerKey = containerKey;
return builder;
}
}

View File

@@ -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<T>(this T Builder, string invariantName)
where T : IWithInvariantNameBuilder
{
Builder.InvariantName = invariantName;
return Builder;
}
public static T WithInvariantProperties<T>(this T Builder, IEnumerable<PropertyValueModel> invariantProperties)
where T : IWithInvariantPropertiesBuilder
{
Builder.InvariantProperties = invariantProperties;
return Builder;
}
public static T WithVariants<T>(this T Builder, IEnumerable<VariantModel> variants)
where T : IWithVariantsBuilder
{
Builder.Variants = variants;
return Builder;
}
public static T WithKey<T>(this T Builder, Guid? key)
where T : IWithKeyBuilder
{
Builder.Key = key;
return Builder;
}
public static T WithContentTypeKey<T>(this T Builder, Guid contentTypeKey)
where T : IWithContentTypeKeyBuilder
{
Builder.ContentTypeKey = contentTypeKey;
return Builder;
}
public static T WithParentKey<T>(this T Builder, Guid? parentKey)
where T : IWithParentKeyBuilder
{
Builder.ParentKey = parentKey;
return Builder;
}
public static T WithTemplateKey<T>(this T Builder, Guid? templateKey)
where T : IWithTemplateKeyBuilder
{
Builder.TemplateKey = templateKey;
return Builder;
}
}

View File

@@ -1,8 +0,0 @@
using Umbraco.Cms.Core.Models.ContentEditing;
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces.ContentCreateModel;
public interface IWithInvariantPropertiesBuilder
{
public IEnumerable<PropertyValueModel> InvariantProperties { get; set; }
}

View File

@@ -1,8 +0,0 @@
using Umbraco.Cms.Core.Models.ContentEditing;
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces.ContentCreateModel;
public interface IWithVariantsBuilder
{
public IEnumerable<VariantModel> Variants { get; set; }
}

View File

@@ -1,6 +1,6 @@
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces;
public interface IWIthContainerKeyBuilder
public interface IWithContainerKeyBuilder
{
Guid? ContainerKey { get; set; }
}

View File

@@ -1,4 +1,4 @@
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces.ContentCreateModel;
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces;
public interface IWithContentTypeKeyBuilder
{

View File

@@ -0,0 +1,6 @@
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces;
public interface IWithCultureBuilder
{
string? Culture { get; set; }
}

View File

@@ -0,0 +1,6 @@
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces;
public interface IWithDefaultTemplateKeyBuilder
{
Guid? DefaultTemplateKey { get; set; }
}

View File

@@ -1,4 +1,4 @@
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces.ContentCreateModel;
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces;
public interface IWithInvariantNameBuilder
{

View File

@@ -0,0 +1,6 @@
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces;
public interface IWithIsElementBuilder
{
bool? IsElement { get; set; }
}

View File

@@ -0,0 +1,6 @@
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces;
public interface IWithSegmentBuilder
{
string Segment { get; set; }
}

View File

@@ -1,4 +1,4 @@
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces.ContentCreateModel;
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces;
public interface IWithTemplateKeyBuilder
{

View File

@@ -0,0 +1,6 @@
namespace Umbraco.Cms.Tests.Common.Builders.Interfaces;
public interface IWithValueBuilder
{
object? Value { get; set; }
}

View File

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

View File

@@ -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<MediaTypeEditingBuilder, MediaTypeCreateModel,
MediaTypePropertyTypeModel, MediaTypePropertyContainerModel>, 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();
}
}

View File

@@ -3,12 +3,14 @@ using Umbraco.Cms.Tests.Common.Builders.Interfaces;
namespace Umbraco.Cms.Tests.Common.Builders;
public class PropertyTypeAppearanceBuilder
: ChildBuilderBase<PropertyTypeEditingBuilder, PropertyTypeAppearance>, IBuildPropertyTypes, IWithLabelOnTop
public class PropertyTypeAppearanceBuilder<TParent, TModel>
: ChildBuilderBase<PropertyTypeEditingBuilder<TParent, TModel>, PropertyTypeAppearance>, IBuildPropertyTypes, IWithLabelOnTop
where TModel : PropertyTypeModelBase, new()
{
private bool? _labelOnTop;
public PropertyTypeAppearanceBuilder(PropertyTypeEditingBuilder parentBuilder) : base(parentBuilder)
public PropertyTypeAppearanceBuilder(PropertyTypeEditingBuilder<TParent, TModel> parentBuilder)
: base(parentBuilder)
{
}

View File

@@ -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>(TParent parentBuilder)
: ChildBuilderBase<TParent, ContentTypePropertyContainerModel>(parentBuilder),
IBuildPropertyTypes, IWithKeyBuilder, IWithParentKeyBuilder, IWithNameBuilder, IWithTypeBuilder,
IWithSortOrderBuilder
public class PropertyTypeContainerBuilder<TParent, TModel>(TParent parentBuilder)
: ChildBuilderBase<TParent, TModel>(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 @@ public class PropertyTypeContainerBuilder<TParent>(TParent parentBuilder)
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;
}
}

View File

@@ -4,28 +4,30 @@ using Umbraco.Cms.Tests.Common.Builders.Interfaces;
namespace Umbraco.Cms.Tests.Common.Builders;
public class PropertyTypeEditingBuilder
: ChildBuilderBase<ContentTypeEditingBuilder, ContentTypePropertyTypeModel>, IBuildPropertyTypes, IWithKeyBuilder,
IWIthContainerKeyBuilder,
IWithSortOrderBuilder, IWithAliasBuilder, IWithNameBuilder, IWithDescriptionBuilder, IWithDataTypeKeyBuilder,
IWithVariesByCultureBuilder, IWithVariesBySegmentBuilder
public class PropertyTypeEditingBuilder<TParent, TModel> : ChildBuilderBase<TParent, TModel>, 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<TParent, TModel> _validationBuilder;
private PropertyTypeAppearanceBuilder<TParent, TModel> _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<TParent, TModel>(this);
_appearanceBuilder = new PropertyTypeAppearanceBuilder<TParent, TModel>(this);
}
Guid? IWithKeyBuilder.Key
@@ -34,7 +36,7 @@ public class PropertyTypeEditingBuilder
set => _key = value;
}
Guid? IWIthContainerKeyBuilder.ContainerKey
Guid? IWithContainerKeyBuilder.ContainerKey
{
get => _containerKey;
set => _containerKey = value;
@@ -58,7 +60,7 @@ public class PropertyTypeEditingBuilder
set => _name = value;
}
string IWithDescriptionBuilder.Description
string? IWithDescriptionBuilder.Description
{
get => _description;
set => _description = value;
@@ -82,95 +84,34 @@ public class PropertyTypeEditingBuilder
set => _variesBySegment = value;
}
public PropertyTypeValidationEditingBuilder AddValidation()
public PropertyTypeValidationEditingBuilder<TParent, TModel> AddValidation()
{
var builder = new PropertyTypeValidationEditingBuilder(this);
var builder = new PropertyTypeValidationEditingBuilder<TParent, TModel>(this);
_validationBuilder = builder;
return builder;
}
public PropertyTypeAppearanceBuilder AddAppearance()
public PropertyTypeAppearanceBuilder<TParent, TModel> AddAppearance()
{
var builder = new PropertyTypeAppearanceBuilder(this);
var builder = new PropertyTypeAppearanceBuilder<TParent, TModel>(this);
_appearanceBuilder = builder;
return builder;
}
public PropertyTypeEditingBuilder WithContainerKey(Guid? containerKey)
public override TModel Build()
{
_containerKey = containerKey;
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 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;
}
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;
}
}

View File

@@ -3,16 +3,22 @@ using Umbraco.Cms.Tests.Common.Builders.Interfaces;
namespace Umbraco.Cms.Tests.Common.Builders;
public class PropertyTypeValidationEditingBuilder
: ChildBuilderBase<PropertyTypeEditingBuilder, PropertyTypeValidation>, IBuildPropertyTypes, IWithMandatoryBuilder,
IWithMandatoryMessageBuilder, IWithRegularExpressionBuilder, IWithRegularExpressionMessage
public class PropertyTypeValidationEditingBuilder<TParent, TModel>
: ChildBuilderBase<PropertyTypeEditingBuilder<TParent, TModel>, 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<TParent, TModel> parentBuilder)
: base(parentBuilder)
{
}

View File

@@ -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<MediaTypeUpdateModel>(mediaType, updateModel);
return model;
}
private T MapBaseProperties<T>(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;
}
}

View File

@@ -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<IMediaTypeService>();
protected IMediaEditingService MediaEditingService => GetRequiredService<IMediaEditingService>();
protected IMediaTypeEditingService MediaTypeEditingService => GetRequiredService<IMediaTypeEditingService>();
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;
}
}
}

View File

@@ -48,12 +48,12 @@ public class DocumentHybridCacheDocumentTypeTests : UmbracoIntegrationTestWithCo
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);
}
}

View File

@@ -13,6 +13,7 @@ using Umbraco.Cms.Infrastructure.HybridCache;
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 class DocumentHybridCacheMockTests : UmbracoIntegrationTestWithContent
_mockedNucacheRepository.Setup(r => r.GetContentSourceAsync(It.IsAny<Guid>(), false))
.ReturnsAsync(publishedTestCacheNode);
_mockedNucacheRepository.Setup(r => r.GetContentByContentTypeKey(It.IsAny<IReadOnlyCollection<Guid>>())).Returns(
_mockedNucacheRepository.Setup(r => r.GetContentByContentTypeKey(It.IsAny<IReadOnlyCollection<Guid>>(), ContentCacheDataSerializerEntityType.Document)).Returns(
new List<ContentCacheNode>()
{
draftTestCacheNode,

View File

@@ -9,7 +9,6 @@ using Umbraco.Cms.Core.Services;
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;
@@ -104,35 +103,13 @@ public class DocumentHybridCachePropertyTest : UmbracoIntegrationTest
private async Task<IContent> 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);
@@ -145,6 +122,7 @@ public class DocumentHybridCachePropertyTest : UmbracoIntegrationTest
},
Constants.Security.SuperUserKey);
Assert.IsTrue(publishResult.Success);
return result.Result.Content;
}
@@ -153,19 +131,11 @@ public class DocumentHybridCachePropertyTest : UmbracoIntegrationTest
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(

View File

@@ -18,12 +18,12 @@ public class DocumentHybridCacheScopeTests : UmbracoIntegrationTestWithContentEd
private IContentPublishingService ContentPublishingService => GetRequiredService<IContentPublishingService>();
private ICoreScopeProvider ICoreScopeProvider => GetRequiredService<ICoreScopeProvider>();
private ICoreScopeProvider CoreScopeProvider => GetRequiredService<ICoreScopeProvider>();
[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 class DocumentHybridCacheScopeTests : UmbracoIntegrationTestWithContentEd
[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 class DocumentHybridCacheScopeTests : UmbracoIntegrationTestWithContentEd
[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 class DocumentHybridCacheScopeTests : UmbracoIntegrationTestWithContentEd
[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();

View File

@@ -6,7 +6,7 @@
// using Umbraco.Cms.Core.Services.OperationStatus;
// using Umbraco.Cms.Tests.Common.Testing;
// using Umbraco.Cms.Tests.Integration.Testing;
// FIXME
// FIXME: This is fixed in the release branch, uncomment this once that's merged in.
// namespace Umbraco.Cms.Tests.Integration.Umbraco.PublishedCache.HybridCache;
//
// [TestFixture]
@@ -37,7 +37,6 @@
// // Assert
// Assert.AreEqual(updateContentResult.Status, ContentEditingOperationStatus.Success);
// var textPageAfter = await PublishedContentHybridCache.GetByIdAsync(TextpageId, true);
// // Should this not be null?
// Assert.AreEqual(textPageAfter.TemplateId, null);
// }
// }

View File

@@ -60,13 +60,7 @@ public class DocumentHybridCacheVariantsTests : UmbracoIntegrationTest
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 class DocumentHybridCacheVariantsTests : UmbracoIntegrationTest
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 class DocumentHybridCacheVariantsTests : UmbracoIntegrationTest
Name = "Updated English Name",
Properties = new[]
{
new PropertyValueModel
{
Alias = _variantTitleAlias, Value = updatedVariantTitle
},
new PropertyValueModel { Alias = _variantTitleAlias, Value = updatedVariantTitle },
},
},
},
@@ -146,35 +135,18 @@ public class DocumentHybridCacheVariantsTests : UmbracoIntegrationTest
.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;
}

View File

@@ -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<IPublishedMediaCache>();
private new IMediaTypeEditingService MediaTypeEditingService => GetRequiredService<IMediaTypeEditingService>();
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);
}
}

View File

@@ -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<IPublishedMediaCache>();
private ICoreScopeProvider CoreScopeProvider => GetRequiredService<ICoreScopeProvider>();
[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);
}
}

View File

@@ -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<IPublishedMediaCache>();
private IUmbracoContextFactory UmbracoContextFactory => GetRequiredService<IUmbracoContextFactory>();
private IMediaTypeService MediaTypeService => GetRequiredService<IMediaTypeService>();
private IMediaEditingService MediaEditingService => GetRequiredService<IMediaEditingService>();
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();
newMediaType.AllowedAsRoot = true;
MediaTypeService.Save(newMediaType);
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);
// Act
var media = await PublishedMediaHybridCache.GetByKeyAsync(result.Result.Content.Key);
var media = await PublishedMediaHybridCache.GetByIdAsync(RootFolderId);
// Assert
Assert.IsNotNull(media);
Assert.AreEqual("Image", media.Name);
Assert.AreEqual(newMediaType.Key, media.ContentType.Key);
Assert.AreEqual("RootFolder", media.Name);
Assert.AreEqual(RootFolder.ContentTypeKey, media.ContentType.Key);
}
[Test]
public async Task Can_Get_Media_By_Id()
public async Task Can_Get_Root_Media_By_Key()
{
// Arrange
var newMediaType = new MediaTypeBuilder()
.WithAlias("album")
.WithName("Album")
.Build();
newMediaType.AllowedAsRoot = true;
MediaTypeService.Save(newMediaType);
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);
// Act
var media = await PublishedMediaHybridCache.GetByIdAsync(result.Result.Content.Id);
var media = await PublishedMediaHybridCache.GetByIdAsync(RootFolder.Key.Value);
// Assert
Assert.IsNotNull(media);
Assert.AreEqual("Image", media.Name);
Assert.AreEqual(newMediaType.Key, media.ContentType.Key);
Assert.AreEqual("RootFolder", media.Name);
Assert.AreEqual(RootFolder.ContentTypeKey, media.ContentType.Key);
}
[Test]
public async Task Cannot_Get_Non_Existing_Media_By_Key()
public async Task Can_Get_Child_Media_By_Id()
{
// Act
var media = await PublishedMediaHybridCache.GetByKeyAsync(Guid.NewGuid());
var media = await PublishedMediaHybridCache.GetByIdAsync(SubImageId);
// Assert
Assert.IsNull(media);
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 Can_Get_Child_Media_By_Key()
{
var media = await PublishedMediaHybridCache.GetByIdAsync(SubImage.Key.Value);
// 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(124214);
const int nonExistingId = 124214;
var media = await PublishedMediaHybridCache.GetByIdAsync(nonExistingId);
// Assert
Assert.IsNull(media);
}
[Test]
public async Task Can_Get_Media_Property_By_Key()
public async Task Cannot_Get_Non_Existing_Media_By_Key()
{
// Arrange
var media = await CreateMedia();
// Act
var publishedMedia = await PublishedMediaHybridCache.GetByKeyAsync(media.Key);
UmbracoContextFactory.EnsureUmbracoContext();
var media = await PublishedMediaHybridCache.GetByIdAsync(Guid.NewGuid());
// Assert
Assert.IsNotNull(media);
Assert.AreEqual("Image", media.Name);
Assert.AreEqual("NewTitle", publishedMedia.Value("title"));
Assert.IsNull(media);
}
[Test]
public async Task Can_Get_Media_Property_By_Id()
{
// Arrange
var media = await CreateMedia();
// Act
var publishedMedia = await PublishedMediaHybridCache.GetByKeyAsync(media.Key);
UmbracoContextFactory.EnsureUmbracoContext();
var media = await PublishedMediaHybridCache.GetByIdAsync(SubTestMediaId);
// Assert
Assert.IsNotNull(publishedMedia);
Assert.AreEqual("Image", publishedMedia.Name);
Assert.AreEqual("NewTitle", publishedMedia.Value("title"));
Assert.IsNotNull(media);
Assert.AreEqual("SubTestMedia", media.Name);
Assert.AreEqual("This is a test", media.Value("testProperty"));
}
[Test]
public async Task Can_Get_Updated_Media()
public async Task Can_Get_Media_Property_By_Key()
{
// Arrange
var media = await CreateMedia();
await PublishedMediaHybridCache.GetByIdAsync(media.Id);
// Act
var updateModel = new MediaUpdateModel()
{
InvariantName = "Update name",
InvariantProperties = new List<PropertyValueModel>()
{
new()
{
Alias = "title",
Value = "Updated Title"
}
}
};
var updateAttempt = await MediaEditingService.UpdateAsync(media.Key, updateModel, Constants.Security.SuperUserKey);
Assert.IsTrue(updateAttempt.Success);
var publishedMedia = await PublishedMediaHybridCache.GetByIdAsync(media.Id);
UmbracoContextFactory.EnsureUmbracoContext();
var media = await PublishedMediaHybridCache.GetByIdAsync(SubTestMedia.Key.Value);
// Assert
Assert.IsNotNull(publishedMedia);
Assert.AreEqual("Update name", publishedMedia.Name);
Assert.AreEqual("Updated Title", publishedMedia.Value("title"));
Assert.IsNotNull(media);
Assert.AreEqual("SubTestMedia", media.Name);
Assert.AreEqual("This is a test", media.Value("testProperty"));
}
[Test]
public async Task Can_Get_Updated_Media_By_Id()
{
// Arrange
const string newName = "NewImageName";
var media = await PublishedMediaHybridCache.GetByIdAsync(SubImageId);
Assert.AreEqual(media.Name, "SubImage");
var mediaUpdateModel = new MediaUpdateModel
{
InvariantName = newName,
InvariantProperties = SubImage.InvariantProperties,
Variants = SubImage.Variants,
};
// Act
await MediaEditingService.UpdateAsync(SubImage.Key.Value, mediaUpdateModel, Constants.Security.SuperUserKey);
var updatedMedia = await PublishedMediaHybridCache.GetByIdAsync(SubImageId);
// Assert
Assert.IsNotNull(updatedMedia);
Assert.AreEqual(newName, updatedMedia.Name);
}
[Test]
public async Task Can_Get_Updated_Media_By_Key()
{
// Arrange
const string newName = "NewImageName";
var media = await PublishedMediaHybridCache.GetByIdAsync(SubImage.Key.Value);
Assert.AreEqual(media.Name, "SubImage");
var mediaUpdateModel = new MediaUpdateModel
{
InvariantName = newName,
InvariantProperties = SubImage.InvariantProperties,
Variants = SubImage.Variants,
};
// Act
await MediaEditingService.UpdateAsync(SubImage.Key.Value, mediaUpdateModel, Constants.Security.SuperUserKey);
var updatedMedia = await PublishedMediaHybridCache.GetByIdAsync(SubImageId);
// Assert
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 class MediaHybridCacheTests : UmbracoIntegrationTest
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<IMedia> 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<PropertyValueModel>()
{
new()
{
Alias = "title",
Value = "NewTitle"
}
}
};
var result = await MediaEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey);
Assert.IsTrue(result.Success);
return result.Result.Content;
}
}

View File

@@ -61,7 +61,8 @@ public class ContentTypeTests
private ContentTypeSort BuildContentTypeSort()
{
var builder = new ContentTypeSortBuilder();
ContentTypeBuilder contentTypeBuilder = new ContentTypeBuilder();
var builder = new ContentTypeSortBuilder<ContentTypeBuilder>(contentTypeBuilder);
return builder
.WithKey(new Guid("4CAE063E-0BE1-4972-B10C-A3D9BB7DE856"))
.WithSortOrder(4)