diff --git a/src/Umbraco.Cms.Api.Management/Factories/ContentEditingPresentationFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/ContentEditingPresentationFactory.cs index dcbf04e03aa7..eada525749cd 100644 --- a/src/Umbraco.Cms.Api.Management/Factories/ContentEditingPresentationFactory.cs +++ b/src/Umbraco.Cms.Api.Management/Factories/ContentEditingPresentationFactory.cs @@ -1,6 +1,4 @@ -using Umbraco.Cms.Api.Management.Extensions; -using Umbraco.Cms.Api.Management.ViewModels.Content; -using Umbraco.Cms.Core.Models.ContentEditing; +using Umbraco.Cms.Core.Models.ContentEditing; namespace Umbraco.Cms.Api.Management.Factories; @@ -8,31 +6,22 @@ internal abstract class ContentEditingPresentationFactory(ContentModelBase contentModel) + protected TContentEditingModel MapContentEditingModel( + ContentModelBase contentModel) where TContentEditingModel : ContentEditingModelBase, new() - { - TVariantModel? invariantVariant = contentModel.Variants.FirstOrDefault(variant => variant.DoesNotVaryByCulture() && variant.DoesNotVaryBySegment()); - TValueModel[] invariantProperties = contentModel.Values.Where(value => value.DoesNotVaryByCulture() && value.DoesNotVaryBySegment()).ToArray(); - - PropertyValueModel ToPropertyValueModel(TValueModel valueModel) - => new() { Alias = valueModel.Alias, Value = valueModel.Value }; - - return new TContentEditingModel + => new() { - InvariantName = invariantVariant?.Name, - InvariantProperties = invariantProperties.Select(ToPropertyValueModel).ToArray(), + Properties = contentModel + .Values + .Select(value => new PropertyValueModel + { + Alias = value.Alias, Value = value.Value, Culture = value.Culture, Segment = value.Segment + }).ToArray(), Variants = contentModel .Variants .Select(variant => new VariantModel { - Culture = variant.Culture, - Segment = variant.Segment, - Name = variant.Name, - Properties = contentModel - .Values - .Where(value => value.Culture == variant.Culture && value.Segment == variant.Segment) - .Select(ToPropertyValueModel).ToArray() + Culture = variant.Culture, Segment = variant.Segment, Name = variant.Name }) }; - } } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentEditingModelBase.cs b/src/Umbraco.Core/Models/ContentEditing/ContentEditingModelBase.cs index 496bc893f3b9..305d50688afb 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentEditingModelBase.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentEditingModelBase.cs @@ -2,9 +2,7 @@ public abstract class ContentEditingModelBase { - public string? InvariantName { get; set; } - - public IEnumerable InvariantProperties { get; set; } = Array.Empty(); + public IEnumerable Properties { get; set; } = Array.Empty(); public IEnumerable Variants { get; set; } = Array.Empty(); } diff --git a/src/Umbraco.Core/Models/ContentEditing/PropertyValueModel.cs b/src/Umbraco.Core/Models/ContentEditing/PropertyValueModel.cs index 18e874f281bc..2afa1604183f 100644 --- a/src/Umbraco.Core/Models/ContentEditing/PropertyValueModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/PropertyValueModel.cs @@ -5,4 +5,8 @@ public class PropertyValueModel public required string Alias { get; set; } public required object? Value { get; set; } + + public string? Culture { get; set; } + + public string? Segment { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/VariantModel.cs b/src/Umbraco.Core/Models/ContentEditing/VariantModel.cs index e80818fe1879..1249b5630d7c 100644 --- a/src/Umbraco.Core/Models/ContentEditing/VariantModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/VariantModel.cs @@ -7,6 +7,4 @@ public class VariantModel public string? Segment { get; set; } public required string Name { get; set; } - - public required IEnumerable Properties { get; set; } } diff --git a/src/Umbraco.Core/Models/Validation/PropertyValidationContext.cs b/src/Umbraco.Core/Models/Validation/PropertyValidationContext.cs index d10fa076b04d..9dd1afe0c1b5 100644 --- a/src/Umbraco.Core/Models/Validation/PropertyValidationContext.cs +++ b/src/Umbraco.Core/Models/Validation/PropertyValidationContext.cs @@ -8,7 +8,7 @@ public sealed class PropertyValidationContext public required IEnumerable CulturesBeingValidated { get; init; } - public required IEnumerable SegmentsBeingValidated { get; init; } + public required IEnumerable SegmentsBeingValidated { get; init; } public static PropertyValidationContext Empty() => new() { diff --git a/src/Umbraco.Core/Services/ContentBlueprintEditingService.cs b/src/Umbraco.Core/Services/ContentBlueprintEditingService.cs index ce6b02c6aef5..7af5171bc96b 100644 --- a/src/Umbraco.Core/Services/ContentBlueprintEditingService.cs +++ b/src/Umbraco.Core/Services/ContentBlueprintEditingService.cs @@ -86,7 +86,7 @@ public async Task> C IContent blueprint = result.Result.Content!; - if (ValidateUniqueName(createModel.InvariantName ?? string.Empty, blueprint) is false) + if (ValidateUniqueNames(createModel.Variants, blueprint) is false) { return Attempt.FailWithStatus(ContentEditingOperationStatus.DuplicateName, new ContentCreateResult()); } @@ -133,7 +133,7 @@ public async Task> U return Attempt.FailWithStatus(ContentEditingOperationStatus.NotFound, new ContentUpdateResult()); } - if (ValidateUniqueName(updateModel.InvariantName ?? string.Empty, blueprint) is false) + if (ValidateUniqueNames(updateModel.Variants, blueprint) is false) { return Attempt.FailWithStatus(ContentEditingOperationStatus.DuplicateName, new ContentUpdateResult()); } @@ -249,4 +249,18 @@ private bool ValidateUniqueName(string name, IContent content) IEnumerable existing = ContentService.GetBlueprintsForContentTypes(content.ContentTypeId); return existing.Any(c => c.Name == name && c.Id != content.Id) is false; } + + private bool ValidateUniqueNames(IEnumerable variants, IContent content) + { + IContent[] existing = ContentService.GetBlueprintsForContentTypes(content.ContentTypeId).ToArray(); + foreach (VariantModel variant in variants) + { + if (existing.Any(c => c.GetCultureName(variant.Culture) == variant.Name && c.Id != content.Id)) + { + return false; + } + } + + return true; + } } diff --git a/src/Umbraco.Core/Services/ContentEditingServiceBase.cs b/src/Umbraco.Core/Services/ContentEditingServiceBase.cs index cb1a2f8ee26a..2f746d9a6fa9 100644 --- a/src/Umbraco.Core/Services/ContentEditingServiceBase.cs +++ b/src/Umbraco.Core/Services/ContentEditingServiceBase.cs @@ -318,7 +318,7 @@ protected ContentEditingOperationStatus OperationResultToOperationStatus(Operati return null; } - if (contentType.VariesByNothing() && contentEditingModelBase.InvariantName.IsNullOrWhiteSpace()) + if (contentType.VariesByNothing() && contentEditingModelBase.Variants.Any(v => v.Culture is null && v.Segment is null) is false) { // does not vary by anything and is missing the invariant name = invalid operationStatus = ContentEditingOperationStatus.ContentTypeCultureVarianceMismatch; @@ -341,23 +341,13 @@ protected ContentEditingOperationStatus OperationResultToOperationStatus(Operati var propertyTypesByAlias = contentType.CompositionPropertyTypes.ToDictionary(pt => pt.Alias); var propertyValuesAndVariance = contentEditingModelBase - .InvariantProperties + .Properties .Select(pv => new { - VariesByCulture = false, - VariesBySegment = false, + VariesByCulture = pv.Culture is not null, + VariesBySegment = pv.Segment is not null, PropertyValue = pv }) - .Union(contentEditingModelBase - .Variants - .SelectMany(v => v - .Properties - .Select(vpv => new - { - VariesByCulture = contentType.VariesByCulture(), - VariesBySegment = v.Segment.IsNullOrWhiteSpace() == false, - PropertyValue = vpv - }))) .ToArray(); // verify that all property values are defined as property types @@ -446,7 +436,7 @@ private void UpdateNames(ContentEditingModelBase contentEditingModelBase, TConte else { // this should be validated already so it's OK to throw an exception here - content.Name = contentEditingModelBase.InvariantName + content.Name = contentEditingModelBase.Variants.FirstOrDefault(v => v.Culture is null && v.Segment is null)?.Name ?? throw new ArgumentException("Could not find a culture invariant variant", nameof(contentEditingModelBase)); } } @@ -456,21 +446,14 @@ private async Task UpdateExistingProperties(ContentEditingModelBase contentEditi // create a mapping dictionary for all content type property types by their property aliases Dictionary propertyTypesByAlias = GetPropertyTypesByAlias(contentType); - // flatten the invariant and variant property values from the model into one array, and remove any properties - // that do not exist on the content type - var propertyValues = contentEditingModelBase - .InvariantProperties - .Select(pv => new { Culture = (string?)null, Segment = (string?)null, Alias = pv.Alias, Value = pv.Value }) - .Union(contentEditingModelBase - .Variants - .SelectMany(v => v - .Properties - .Select(vpv => new { Culture = v.Culture, Segment = v.Segment, Alias = vpv.Alias, Value = vpv.Value }))) + // remove any properties that do not exist on the content type + PropertyValueModel[] propertyValues = contentEditingModelBase + .Properties .Where(propertyValue => propertyTypesByAlias.ContainsKey(propertyValue.Alias)) .ToArray(); // update all properties on the content item - foreach (var propertyValue in propertyValues) + foreach (PropertyValueModel propertyValue in propertyValues) { // the following checks should already have been validated by now, so it's OK to throw exceptions here if(propertyTypesByAlias.TryGetValue(propertyValue.Alias, out IPropertyType? propertyType) == false @@ -491,8 +474,8 @@ private void RemoveMissingProperties(ContentEditingModelBase contentEditingModel // create a mapping dictionary for all content type property types by their property aliases Dictionary propertyTypesByAlias = GetPropertyTypesByAlias(contentType); var knownPropertyAliases = contentEditingModelBase - .InvariantProperties.Select(pv => pv.Alias) - .Union(contentEditingModelBase.Variants.SelectMany(v => v.Properties.Select(vpv => vpv.Alias))) + .Properties + .Select(pv => pv.Alias) .Distinct() .ToArray(); diff --git a/src/Umbraco.Core/Services/ContentPublishingService.cs b/src/Umbraco.Core/Services/ContentPublishingService.cs index 5f72c3686312..98505483a1cc 100644 --- a/src/Umbraco.Core/Services/ContentPublishingService.cs +++ b/src/Umbraco.Core/Services/ContentPublishingService.cs @@ -238,28 +238,33 @@ public async Task ValidateCurrentContentAsync(IContent content, string[] cultures) { + IEnumerable effectiveCultures = content.ContentType.VariesByCulture() + ? cultures.Union([null]) + : [null]; + // Would be better to be able to use a mapper/factory, but currently all that functionality is very much presentation logic. var model = new ContentUpdateModel() { - InvariantName = content.Name, // NOTE KJA: this needs redoing; we need to make an informed decision whether to include invariant properties, depending on if editing invariant properties is allowed on all variants, or if the default language is included in cultures - InvariantProperties = content.Properties.Where(x => x.PropertyType.VariesByCulture() is false).Select(x => new PropertyValueModel() - { - Alias = x.Alias, - Value = x.GetValue() - }), + Properties = effectiveCultures.SelectMany(culture => + content.Properties.Select(property => property.PropertyType.VariesByCulture() == (culture is not null) + ? new PropertyValueModel + { + Alias = property.Alias, + Value = property.GetValue(culture: culture, segment: null, published: false), + Culture = culture + } + : null) + .WhereNotNull()) + .ToArray(), Variants = cultures.Select(culture => new VariantModel() { Name = content.GetPublishName(culture) ?? string.Empty, Culture = culture, - Segment = null, - Properties = content.Properties.Where(prop => prop.PropertyType.VariesByCulture()).Select(prop => new PropertyValueModel() - { - Alias = prop.Alias, - Value = prop.GetValue(culture: culture, segment: null, published: false) - }) - }) + Segment = null + }).ToArray() }; + IContentType? contentType = _contentTypeService.Get(content.ContentType.Key)!; ContentValidationResult validationResult = await _contentValidationService.ValidatePropertiesAsync(model, contentType, cultures); return validationResult; diff --git a/src/Umbraco.Core/Services/ContentValidationServiceBase.cs b/src/Umbraco.Core/Services/ContentValidationServiceBase.cs index 03d2590f65ad..37b32847ad80 100644 --- a/src/Umbraco.Core/Services/ContentValidationServiceBase.cs +++ b/src/Umbraco.Core/Services/ContentValidationServiceBase.cs @@ -31,9 +31,17 @@ protected async Task HandlePropertiesValidationAsync( IPropertyType[] contentTypePropertyTypes = contentType.CompositionPropertyTypes.ToArray(); IPropertyType[] invariantPropertyTypes = contentTypePropertyTypes - .Where(propertyType => propertyType.VariesByNothing()) + .Where(propertyType => propertyType.Variations == ContentVariation.Nothing) + .ToArray(); + IPropertyType[] cultureVariantPropertyTypes = contentTypePropertyTypes + .Where(propertyType => propertyType.Variations == ContentVariation.Culture) + .ToArray(); + IPropertyType[] segmentVariantPropertyTypes = contentTypePropertyTypes + .Where(propertyType => propertyType.Variations == ContentVariation.Segment) + .ToArray(); + IPropertyType[] cultureAndSegmentVariantPropertyTypes = contentTypePropertyTypes + .Where(propertyType => propertyType.Variations == ContentVariation.CultureAndSegment) .ToArray(); - IPropertyType[] variantPropertyTypes = contentTypePropertyTypes.Except(invariantPropertyTypes).ToArray(); var cultures = culturesToValidate?.WhereNotNull().Except(["*"]).ToArray(); if (cultures?.Any() is not true) @@ -42,11 +50,14 @@ protected async Task HandlePropertiesValidationAsync( } // we don't have any managed segments, so we have to make do with the ones passed in the model - var segments = contentEditingModelBase.Variants - .Where(variant => variant.Culture is null || cultures.Contains(variant.Culture)) - .DistinctBy(variant => variant.Segment).Select(variant => variant.Segment) - .WhereNotNull() - .ToArray(); + var segments = + new string?[] { null } + .Union(contentEditingModelBase.Variants + .Where(variant => variant.Culture is null || cultures.Contains(variant.Culture)) + .DistinctBy(variant => variant.Segment).Select(variant => variant.Segment) + .WhereNotNull() + ) + .ToArray(); foreach (IPropertyType propertyType in invariantPropertyTypes) { @@ -55,16 +66,45 @@ protected async Task HandlePropertiesValidationAsync( Culture = null, Segment = null, CulturesBeingValidated = cultures, SegmentsBeingValidated = segments }; - PropertyValueModel? propertyValueModel = contentEditingModelBase.InvariantProperties.FirstOrDefault(propertyValue => propertyValue.Alias == propertyType.Alias); + PropertyValueModel? propertyValueModel = contentEditingModelBase + .Properties + .FirstOrDefault(propertyValue => propertyValue.Alias == propertyType.Alias && propertyValue.Culture is null && propertyValue.Segment is null); validationErrors.AddRange(ValidateProperty(propertyType, propertyValueModel, validationContext)); } - if (variantPropertyTypes.Any() is false) + foreach (IPropertyType propertyType in cultureVariantPropertyTypes) { - return new ContentValidationResult { ValidationErrors = validationErrors }; + foreach (var culture in cultures) + { + var validationContext = new PropertyValidationContext + { + Culture = culture, Segment = null, CulturesBeingValidated = cultures, SegmentsBeingValidated = segments + }; + + PropertyValueModel? propertyValueModel = contentEditingModelBase + .Properties + .FirstOrDefault(propertyValue => propertyValue.Alias == propertyType.Alias && propertyValue.Culture.InvariantEquals(culture) && propertyValue.Segment is null); + validationErrors.AddRange(ValidateProperty(propertyType, propertyValueModel, validationContext)); + } + } + + foreach (IPropertyType propertyType in segmentVariantPropertyTypes) + { + foreach (var segment in segments) + { + var validationContext = new PropertyValidationContext + { + Culture = null, Segment = segment, CulturesBeingValidated = cultures, SegmentsBeingValidated = segments + }; + + PropertyValueModel? propertyValueModel = contentEditingModelBase + .Properties + .FirstOrDefault(propertyValue => propertyValue.Alias == propertyType.Alias && propertyValue.Culture is null && propertyValue.Segment.InvariantEquals(segment)); + validationErrors.AddRange(ValidateProperty(propertyType, propertyValueModel, validationContext)); + } } - foreach (IPropertyType propertyType in variantPropertyTypes) + foreach (IPropertyType propertyType in cultureAndSegmentVariantPropertyTypes) { foreach (var culture in cultures) { @@ -76,10 +116,8 @@ protected async Task HandlePropertiesValidationAsync( }; PropertyValueModel? propertyValueModel = contentEditingModelBase - .Variants - .FirstOrDefault(variant => string.Equals(variant.Culture, culture, StringComparison.InvariantCultureIgnoreCase) && string.Equals(segment, variant.Segment, StringComparison.InvariantCultureIgnoreCase))? .Properties - .FirstOrDefault(propertyValue => propertyValue.Alias == propertyType.Alias); + .FirstOrDefault(propertyValue => propertyValue.Alias == propertyType.Alias && propertyValue.Culture.InvariantEquals(culture) && propertyValue.Segment.InvariantEquals(segment)); validationErrors.AddRange(ValidateProperty(propertyType, propertyValueModel, validationContext)); } } diff --git a/src/Umbraco.Core/Services/MemberContentEditingService.cs b/src/Umbraco.Core/Services/MemberContentEditingService.cs index 9e44c9bb16e2..720ad80d622d 100644 --- a/src/Umbraco.Core/Services/MemberContentEditingService.cs +++ b/src/Umbraco.Core/Services/MemberContentEditingService.cs @@ -123,8 +123,7 @@ private bool ValidateAccessToSensitiveProperties(IMember member, IMemberType mem var sensitivePropertyAliases = memberType.GetSensitivePropertyTypeAliases().ToArray(); return updateModel - .InvariantProperties - .Union(updateModel.Variants.SelectMany(variant => variant.Properties)) + .Properties .Select(property => property.Alias) .Intersect(sensitivePropertyAliases, StringComparer.OrdinalIgnoreCase) .Any() is false; diff --git a/src/Umbraco.Infrastructure/Services/MemberEditingService.cs b/src/Umbraco.Infrastructure/Services/MemberEditingService.cs index a044569d2206..974a70254f57 100644 --- a/src/Umbraco.Infrastructure/Services/MemberEditingService.cs +++ b/src/Umbraco.Infrastructure/Services/MemberEditingService.cs @@ -77,12 +77,16 @@ public async Task> CreateAsync( return Attempt.FailWithStatus(status, new MemberCreateResult()); } + // this should be validated already so it's OK to throw an exception here + var memberName = createModel.Variants.FirstOrDefault(v => v.Culture is null && v.Segment is null)?.Name + ?? throw new ArgumentException("Expected an invariant variant for the member name.", nameof(createModel)); + var identityMember = MemberIdentityUser.CreateNew( createModel.Username, createModel.Email, memberType.Alias, createModel.IsApproved, - createModel.InvariantName, + memberName, createModel.Key); IdentityResult createResult = await _memberManager.CreateAsync(identityMember, createModel.Password); @@ -219,7 +223,7 @@ public async Task> UpdateAsync( private async Task ValidateMemberDataAsync(MemberEditingModelBase model, Guid? memberKey, string? password) { - if (model.InvariantName.IsNullOrWhiteSpace()) + if (model.Variants.FirstOrDefault(v => v.Culture is null && v.Segment is null)?.Name.IsNullOrWhiteSpace() is not false) { return MemberEditingOperationStatus.InvalidName; } diff --git a/tests/Umbraco.Tests.Common/Builders/ContentEditingBaseBuilder.cs b/tests/Umbraco.Tests.Common/Builders/ContentEditingBaseBuilder.cs index 617ebdc3a6cb..1341d45f1c39 100644 --- a/tests/Umbraco.Tests.Common/Builders/ContentEditingBaseBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/ContentEditingBaseBuilder.cs @@ -1,5 +1,7 @@ using Umbraco.Cms.Core.Models.ContentEditing; +using Umbraco.Cms.Tests.Common.Builders.Extensions; using Umbraco.Cms.Tests.Common.Builders.Interfaces; +using Umbraco.Extensions; namespace Umbraco.Cms.Tests.Common.Builders; @@ -64,10 +66,23 @@ public override TCreateModel Build() _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.Properties = _invariantProperties + .Select(p => p.Build()) + .Union(_variants.SelectMany(variant => variant.GetProperties().Select(p => p.Build()))) + .ToArray(); + + if (_invariantName.IsNullOrWhiteSpace() is false) + { + if (_variants.Any()) + { + throw new InvalidOperationException("Cannot combine invariant and variant variants."); + } + + AddVariant().WithName(_invariantName); + } + _model.Variants = _variants.Select(x => x.Build()).ToList(); return _model; diff --git a/tests/Umbraco.Tests.Common/Builders/ContentEditingPropertyValueBuilder.cs b/tests/Umbraco.Tests.Common/Builders/ContentEditingPropertyValueBuilder.cs index ee5e2fbb6d8e..79776b0fe6d2 100644 --- a/tests/Umbraco.Tests.Common/Builders/ContentEditingPropertyValueBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/ContentEditingPropertyValueBuilder.cs @@ -4,10 +4,11 @@ namespace Umbraco.Cms.Tests.Common.Builders; public class ContentEditingPropertyValueBuilder(TParent parentBuilder) - : ChildBuilderBase(parentBuilder), IWithAliasBuilder, IWithValueBuilder + : ChildBuilderBase(parentBuilder), IWithAliasBuilder, IWithValueBuilder, IWithCultureBuilder { private string _alias; private object? _value; + private string? _culture; string IWithAliasBuilder.Alias { @@ -21,5 +22,11 @@ string IWithAliasBuilder.Alias set => _value = value; } - public override PropertyValueModel Build() => new() { Alias = _alias, Value = _value }; + string IWithCultureBuilder.Culture + { + get => _culture; + set => _culture = value; + } + + public override PropertyValueModel Build() => new() { Alias = _alias, Value = _value, Culture = _culture }; } diff --git a/tests/Umbraco.Tests.Common/Builders/ContentEditingVariantBuilder.cs b/tests/Umbraco.Tests.Common/Builders/ContentEditingVariantBuilder.cs index 797b46b8ace1..0fa0cb3e89b8 100644 --- a/tests/Umbraco.Tests.Common/Builders/ContentEditingVariantBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/ContentEditingVariantBuilder.cs @@ -1,4 +1,5 @@ using Umbraco.Cms.Core.Models.ContentEditing; +using Umbraco.Cms.Tests.Common.Builders.Extensions; using Umbraco.Cms.Tests.Common.Builders.Interfaces; namespace Umbraco.Cms.Tests.Common.Builders; @@ -36,12 +37,21 @@ public ContentEditingPropertyValueBuilder> return builder; } + public IReadOnlyCollection>> GetProperties() + { + if (_culture is null) + { + throw new InvalidOperationException("Culture must be defined for the variant before building."); + } + + return _properties.Select(property => property.WithCulture(_culture)).ToList(); + } + public override VariantModel Build() => new() { Culture = _culture, Segment = _segment, - Name = _name, - Properties = _properties.Select(x => x.Build()).ToList(), + Name = _name }; } diff --git a/tests/Umbraco.Tests.Common/TestHelpers/DocumentUpdateHelper.cs b/tests/Umbraco.Tests.Common/TestHelpers/DocumentUpdateHelper.cs index 25873a8dca68..f6dbd26463d0 100644 --- a/tests/Umbraco.Tests.Common/TestHelpers/DocumentUpdateHelper.cs +++ b/tests/Umbraco.Tests.Common/TestHelpers/DocumentUpdateHelper.cs @@ -17,10 +17,11 @@ public static UpdateDocumentRequestModel CreateInvariantDocumentUpdateRequestMod { Segment = null, Culture = null, - Name = createModel.InvariantName!, + Name = createModel.Variants.FirstOrDefault(v => v.Culture is null && v.Segment is null)?.Name + ?? throw new ArgumentException("Could not find an invariant variant for the model name", nameof(createModel)), } ]; - updateRequestModel.Values = createModel.InvariantProperties.Select(x => new DocumentValueModel + updateRequestModel.Values = createModel.Properties.Select(x => new DocumentValueModel { Alias = x.Alias, Value = x.Value, @@ -44,10 +45,11 @@ public static CreateDocumentRequestModel CreateDocumentRequestModel(ContentCreat { Segment = null, Culture = null, - Name = createModel.InvariantName!, + Name = createModel.Variants.FirstOrDefault(v => v.Culture is null && v.Segment is null)?.Name + ?? throw new ArgumentException("Could not find an invariant variant for the model name", nameof(createModel)), } ]; - createDocumentRequestModel.Values = createModel.InvariantProperties.Select(x => new DocumentValueModel + createDocumentRequestModel.Values = createModel.Properties.Select(x => new DocumentValueModel { Alias = x.Alias, Value = x.Value, diff --git a/tests/Umbraco.Tests.Integration/ManagementApi/Policies/UpdateDocumentTests.cs b/tests/Umbraco.Tests.Integration/ManagementApi/Policies/UpdateDocumentTests.cs index b49d00cac45b..b41ef5cbc8b0 100644 --- a/tests/Umbraco.Tests.Integration/ManagementApi/Policies/UpdateDocumentTests.cs +++ b/tests/Umbraco.Tests.Integration/ManagementApi/Policies/UpdateDocumentTests.cs @@ -83,7 +83,7 @@ await AuthenticateClientAsync(Client, async userService => var response = await GetManagementApiResponse(model, updateRequestModel); - AssertResponse(response, model, HttpStatusCode.Forbidden, model.InvariantName); + AssertResponse(response, model, HttpStatusCode.Forbidden, model.Variants.Single().Name); } [Test] diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentEditingServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentEditingServiceTests.cs index 33c8190eb90b..b56efc7cfdd3 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentEditingServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentEditingServiceTests.cs @@ -43,33 +43,16 @@ public async Task Only_Supplied_Cultures_Are_Updated() { Key = documentKey, ContentTypeKey = variantTestData.contentType.Key, - Variants = new[] - { - new VariantModel - { - Name = variantTestData.LangEn.CultureName, - Culture = variantTestData.LangEn.IsoCode, - Properties = new[] - { - new PropertyValueModel - { - Alias = propertyAlias, Value = originalPropertyValue - } - } - }, - new VariantModel - { - Name = variantTestData.LangDa.CultureName, - Culture = variantTestData.LangDa.IsoCode, - Properties = new[] - { - new PropertyValueModel - { - Alias = propertyAlias, Value = originalPropertyValue - } - } - } - } + Properties = + [ + new () { Alias = propertyAlias, Value = originalPropertyValue, Culture = variantTestData.LangEn.IsoCode }, + new () { Alias = propertyAlias, Value = originalPropertyValue, Culture = variantTestData.LangDa.IsoCode }, + ], + Variants = + [ + new () { Name = variantTestData.LangEn.CultureName, Culture = variantTestData.LangEn.IsoCode }, + new () { Name = variantTestData.LangDa.CultureName, Culture = variantTestData.LangDa.IsoCode } + ] }; await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -78,15 +61,14 @@ public async Task Only_Supplied_Cultures_Are_Updated() var updateModel = new ContentUpdateModel { - Variants = new[] - { - new VariantModel - { - Name = updatedPropertyValue, - Culture = variantTestData.LangEn.IsoCode, - Properties = new[] { new PropertyValueModel { Alias = propertyAlias, Value = updatedPropertyValue } } - } - } + Properties = + [ + new () { Alias = propertyAlias, Value = updatedPropertyValue, Culture = variantTestData.LangEn.IsoCode }, + ], + Variants = + [ + new () { Name = updatedPropertyValue, Culture = variantTestData.LangEn.IsoCode } + ] }; await ContentEditingService.UpdateAsync(content.Key, updateModel, Constants.Security.SuperUserKey); @@ -94,7 +76,7 @@ public async Task Only_Supplied_Cultures_Are_Updated() var updatedContent = ContentService.GetById(documentKey)!; Assert.AreEqual(originalPropertyValue, updatedContent.GetValue(propertyAlias,variantTestData.LangDa.IsoCode)); - Assert.AreEqual(updatedPropertyValue, updatedContent.GetValue(propertyAlias,variantTestData.LangEn.IsoCode)); + Assert.AreEqual(updatedPropertyValue, updatedContent.GetValue(propertyAlias, variantTestData.LangEn.IsoCode)); Assert.AreEqual(variantTestData.LangDa.CultureName, updatedContent.GetCultureName(variantTestData.LangDa.IsoCode)); Assert.AreEqual(updatedPropertyValue, updatedContent.GetCultureName(variantTestData.LangEn.IsoCode)); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentPublishingServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentPublishingServiceTests.cs index d1d283612cad..1a8ed9cb252f 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentPublishingServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/ContentPublishingServiceTests.cs @@ -91,25 +91,23 @@ private async Task CreateVariantContentAsync(ILanguage langEn, ILangua Key = documentKey, ContentTypeKey = contentType.Key, ParentKey = parentKey, + Properties = [], Variants = [ new VariantModel { Name = langEn.CultureName, - Culture = langEn.IsoCode, - Properties = Enumerable.Empty(), + Culture = langEn.IsoCode }, new VariantModel { Name = langDa.CultureName, - Culture = langDa.IsoCode, - Properties = Enumerable.Empty(), + Culture = langDa.IsoCode }, new VariantModel { Name = langBe.CultureName, - Culture = langBe.IsoCode, - Properties = Enumerable.Empty(), + Culture = langBe.IsoCode } ] }; @@ -163,7 +161,7 @@ private async Task CreateInvariantContentAsync(IContentType contentTyp { Key = documentKey, ContentTypeKey = contentType.Key, - InvariantName = "Test", + Variants = [new () { Name = "Test" }], ParentKey = parentKey, }; diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/DocumentNavigationServiceTests.Update.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/DocumentNavigationServiceTests.Update.cs index c16f5b4fa27b..394722f3c34a 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/DocumentNavigationServiceTests.Update.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/DocumentNavigationServiceTests.Update.cs @@ -21,7 +21,7 @@ public async Task Structure_Does_Not_Update_When_Updating_Content() var updateModel = new ContentUpdateModel { - InvariantName = "Updated Root", + Variants = [new () { Name = "Updated Root" }] }; // Act diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/DocumentNavigationServiceTestsBase.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/DocumentNavigationServiceTestsBase.cs index 93836955a9de..fb79c53e3bc5 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/DocumentNavigationServiceTestsBase.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/DocumentNavigationServiceTestsBase.cs @@ -49,7 +49,7 @@ protected ContentCreateModel CreateContentCreateModel(string name, Guid key, Gui { ContentTypeKey = contentTypeKey ?? ContentType.Key, ParentKey = parentKey ?? Constants.System.RootKey, - InvariantName = name, + Variants = [new () { Name = name }], Key = key, }; diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaEditingServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaEditingServiceTests.cs index 8bed77aaa3ce..bc21bc29b6cf 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaEditingServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaEditingServiceTests.cs @@ -54,7 +54,7 @@ private MediaCreateModel CreateMediaCreateModel(string name, Guid key, Guid medi { ContentTypeKey = mediaTypeKey, ParentKey = Constants.System.RootKey, - InvariantName = name, + Variants = [new () { Name = name }], Key = key, }; } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaNavigationServiceTests.Update.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaNavigationServiceTests.Update.cs index 875f90d49521..4339a944f6ba 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaNavigationServiceTests.Update.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaNavigationServiceTests.Update.cs @@ -21,7 +21,7 @@ public async Task Structure_Does_Not_Update_When_Updating_Media() var updateModel = new MediaUpdateModel { - InvariantName = "Updated Album", + Variants = [new () { Name = "Updated Album" }] }; // Act diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaNavigationServiceTestsBase.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaNavigationServiceTestsBase.cs index e1e1a162803e..f5daa6fd02ba 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaNavigationServiceTestsBase.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/MediaNavigationServiceTestsBase.cs @@ -49,7 +49,7 @@ protected MediaCreateModel CreateMediaCreateModel(string name, Guid key, Guid me { ContentTypeKey = mediaTypeKey, ParentKey = parentKey ?? Constants.System.RootKey, - InvariantName = name, + Variants = [new () { Name = name }], Key = key, }; diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/PropertyEditors/BlockListElementLevelVariationTests.Editing.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/PropertyEditors/BlockListElementLevelVariationTests.Editing.cs index c6f2dff3834f..5cf95b6046c6 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/PropertyEditors/BlockListElementLevelVariationTests.Editing.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/PropertyEditors/BlockListElementLevelVariationTests.Editing.cs @@ -106,15 +106,15 @@ await LanguageService.CreateAsync( var updateModel = new ContentUpdateModel { - InvariantProperties = new[] + Properties = new[] { new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } }, Variants = new[] { - new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US", Properties = [] }, - new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK", Properties = [] }, - new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE", Properties = [] } + new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US" }, + new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK" }, + new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE" } } }; @@ -244,15 +244,15 @@ await LanguageService.CreateAsync( var updateModel = new ContentUpdateModel { - InvariantProperties = new[] + Properties = new[] { new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } }, Variants = new[] { - new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US", Properties = [] }, - new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK", Properties = [] }, - new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE", Properties = [] } + new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US" }, + new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK" }, + new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE" } } }; @@ -397,15 +397,15 @@ await LanguageService.CreateAsync( var updateModel = new ContentUpdateModel { - InvariantProperties = new[] + Properties = new[] { new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } }, Variants = new[] { - new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US", Properties = [] }, - new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK", Properties = [] }, - new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE", Properties = [] } + new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US" }, + new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK" }, + new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE" } } }; @@ -538,16 +538,16 @@ await LanguageService.CreateAsync( var updateModel = new ContentUpdateModel { - InvariantProperties = new[] + Properties = new[] { new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) }, }, Variants = new[] { - new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US", Properties = [] }, - new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK", Properties = [] }, - new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE", Properties = [] }, - }, + new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US" }, + new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK" }, + new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE" } + } }; var result = await ContentEditingService.UpdateAsync(content.Key, updateModel, userKey); @@ -685,15 +685,15 @@ await LanguageService.CreateAsync( var updateModel = new ContentUpdateModel { - InvariantProperties = new[] + Properties = new[] { new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } }, Variants = new[] { - new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US", Properties = [] }, - new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK", Properties = [] }, - new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE", Properties = [] } + new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US" }, + new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK" }, + new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE" } }, }; @@ -842,15 +842,15 @@ await LanguageService.CreateAsync( var updateModel = new ContentUpdateModel { - InvariantProperties = new[] + Properties = new[] { new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } }, Variants = new[] { - new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US", Properties = [] }, - new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK", Properties = [] }, - new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE", Properties = [] } + new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US" }, + new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK" }, + new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE" } }, }; @@ -946,15 +946,15 @@ await LanguageService.CreateAsync( var updateModel = new ContentUpdateModel { - InvariantProperties = new[] + Properties = new[] { new PropertyValueModel { Alias = "blocks", Value = null }, }, Variants = new[] { - new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US", Properties = [] }, - new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK", Properties = [] }, - new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE", Properties = [] }, + new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US" }, + new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK" }, + new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE" }, }, }; @@ -1057,15 +1057,15 @@ await LanguageService.CreateAsync( var updateModel = new ContentUpdateModel { - InvariantProperties = new[] + Properties = new[] { new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } }, Variants = new[] { - new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US", Properties = [] }, - new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK", Properties = [] }, - new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE", Properties = [] } + new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US" }, + new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK" }, + new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE" } }, }; @@ -1216,15 +1216,15 @@ await LanguageService.CreateAsync( var updateModel = new ContentUpdateModel { - InvariantProperties = new[] + Properties = new[] { new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } }, Variants = new[] { - new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US", Properties = [] }, - new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK", Properties = [] }, - new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE", Properties = [] } + new VariantModel { Name = content.GetCultureName("en-US")!, Culture = "en-US" }, + new VariantModel { Name = content.GetCultureName("da-DK")!, Culture = "da-DK" }, + new VariantModel { Name = content.GetCultureName("de-DE")!, Culture = "de-DE" } } }; diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/PropertyEditors/BlockListElementLevelVariationTests.Validation.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/PropertyEditors/BlockListElementLevelVariationTests.Validation.cs index ea2e680293ed..963c7dd76f00 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/PropertyEditors/BlockListElementLevelVariationTests.Validation.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/PropertyEditors/BlockListElementLevelVariationTests.Validation.cs @@ -43,10 +43,10 @@ public async Task Can_Validate_Invalid_Properties() ContentTypeKey = contentType.Key, Variants = [ - new VariantModel { Name = "Name en-US", Properties = [], Culture = "en-US", Segment = null }, - new VariantModel { Name = "Name da-DK", Properties = [], Culture = "da-DK", Segment = null } + new VariantModel { Name = "Name en-US", Culture = "en-US", Segment = null }, + new VariantModel { Name = "Name da-DK", Culture = "da-DK", Segment = null } ], - InvariantProperties = + Properties = [ new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } ] @@ -143,10 +143,10 @@ public async Task Can_Validate_Invalid_Properties_Nested_Blocks() ContentTypeKey = contentType.Key, Variants = [ - new VariantModel { Name = "Name en-US", Properties = [], Culture = "en-US", Segment = null }, - new VariantModel { Name = "Name da-DK", Properties = [], Culture = "da-DK", Segment = null } + new VariantModel { Name = "Name en-US", Culture = "en-US", Segment = null }, + new VariantModel { Name = "Name da-DK", Culture = "da-DK", Segment = null } ], - InvariantProperties = + Properties = [ new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } ] @@ -212,10 +212,10 @@ private async Task Can_Validate_Invalid_Properties_Specific_Culture_Only() ContentTypeKey = contentType.Key, Variants = [ - new VariantModel { Name = "Name en-US", Properties = [], Culture = "en-US", Segment = null }, - new VariantModel { Name = "Name da-DK", Properties = [], Culture = "da-DK", Segment = null } + new VariantModel { Name = "Name en-US", Culture = "en-US", Segment = null }, + new VariantModel { Name = "Name da-DK", Culture = "da-DK", Segment = null } ], - InvariantProperties = + Properties = [ new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } ] @@ -267,10 +267,10 @@ public async Task Can_Validate_Invalid_Properties_With_Wildcard_Culture() ContentTypeKey = contentType.Key, Variants = [ - new VariantModel { Name = "Name en-US", Properties = [], Culture = "en-US", Segment = null }, - new VariantModel { Name = "Name da-DK", Properties = [], Culture = "da-DK", Segment = null } + new VariantModel { Name = "Name en-US", Culture = "en-US", Segment = null }, + new VariantModel { Name = "Name da-DK", Culture = "da-DK", Segment = null } ], - InvariantProperties = + Properties = [ new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } ] @@ -327,10 +327,10 @@ public async Task Can_Validate_Missing_Properties() ContentTypeKey = contentType.Key, Variants = [ - new VariantModel { Name = "Name en-US", Properties = [], Culture = "en-US", Segment = null }, - new VariantModel { Name = "Name da-DK", Properties = [], Culture = "da-DK", Segment = null } + new VariantModel { Name = "Name en-US", Culture = "en-US", Segment = null }, + new VariantModel { Name = "Name da-DK", Culture = "da-DK", Segment = null } ], - InvariantProperties = + Properties = [ new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } ] @@ -455,10 +455,10 @@ private async Task Can_Validate_Missing_Properties_Nested_Blocks_Specific_Cultur ContentTypeKey = contentType.Key, Variants = [ - new VariantModel { Name = "Name en-US", Properties = [], Culture = "en-US", Segment = null }, - new VariantModel { Name = "Name da-DK", Properties = [], Culture = "da-DK", Segment = null } + new VariantModel { Name = "Name en-US", Culture = "en-US", Segment = null }, + new VariantModel { Name = "Name da-DK", Culture = "da-DK", Segment = null } ], - InvariantProperties = + Properties = [ new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } ] @@ -538,10 +538,10 @@ public async Task Does_Not_Validate_Unexposed_Blocks() ContentTypeKey = contentType.Key, Variants = [ - new VariantModel { Name = "Name en-US", Properties = [], Culture = "en-US", Segment = null }, - new VariantModel { Name = "Name da-DK", Properties = [], Culture = "da-DK", Segment = null } + new VariantModel { Name = "Name en-US", Culture = "en-US", Segment = null }, + new VariantModel { Name = "Name da-DK", Culture = "da-DK", Segment = null } ], - InvariantProperties = + Properties = [ new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } ] @@ -590,17 +590,12 @@ public async Task Can_Validate_Properties_Variant_Blocks() ContentTypeKey = contentType.Key, Variants = [ - new VariantModel - { - Name = "Name en-US", - Culture = "en-US", - Segment = null, - Properties = [ - new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } - ] - } + new VariantModel { Name = "Name en-US", Culture = "en-US", Segment = null } ], - InvariantProperties = [] + Properties = + [ + new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue), Culture = "en-US" } + ] }, contentType); @@ -650,17 +645,12 @@ public async Task Can_Validate_Missing_Properties_Variant_Blocks() ContentTypeKey = contentType.Key, Variants = [ - new VariantModel - { - Name = "Name en-US", - Culture = "en-US", - Segment = null, - Properties = [ - new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue) } - ] - } + new VariantModel { Name = "Name en-US", Culture = "en-US", Segment = null } ], - InvariantProperties = [] + Properties = + [ + new PropertyValueModel { Alias = "blocks", Value = JsonSerializer.Serialize(blockListValue), Culture = "en-US" } + ] }, contentType); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.Create.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.Create.cs index 6f92b14e16a3..fa4a742d6734 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.Create.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.Create.cs @@ -17,7 +17,7 @@ public async Task Can_Create_With_Basic_Model() var createModel = new ContentBlueprintCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Test Create Blueprint", + Variants = [new VariantModel { Name = "Test Create Blueprint" }], }; var result = await ContentBlueprintEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -57,11 +57,11 @@ public async Task Can_Create_At_Root() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create Blueprint", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" }, - }, + Variants = [new VariantModel { Name = "Test Create Blueprint" }], + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "The title value" } + ], }; var result = await ContentBlueprintEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -104,11 +104,11 @@ public async Task Can_Create_With_Explicit_Key() Key = key, ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create Blueprint", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" }, - }, + Variants = [new VariantModel { Name = "Test Create Blueprint" }], + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "The title value" } + ], }; var result = await ContentBlueprintEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -141,11 +141,11 @@ public async Task Cannot_Create_With_Duplicate_Name_For_The_Same_Content_Type() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create Blueprint", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" }, - }, + Variants = [new VariantModel { Name = "Test Create Blueprint" }], + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "The title value" } + ], }; var result1 = await ContentBlueprintEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -178,11 +178,11 @@ public async Task Can_Create_With_Different_Name() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create Blueprint 1", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" }, - }, + Variants = [new VariantModel { Name = "Test Create Blueprint 1" }], + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "The title value" } + ], }; var result1 = await ContentBlueprintEditingService.CreateAsync(createModel1, Constants.Security.SuperUserKey); @@ -197,11 +197,11 @@ public async Task Can_Create_With_Different_Name() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create Blueprint 2", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" }, - }, + Variants = [new VariantModel { Name = "Test Create Blueprint 2" }], + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "The title value" } + ], }; // create another blueprint @@ -226,11 +226,11 @@ public async Task Can_Create_With_Duplicate_Name_For_Different_Content_Types() { ContentTypeKey = contentType1.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create Blueprint", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" }, - }, + Variants = [new VariantModel { Name = "Test Create Blueprint" }], + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "The title value" } + ], }; var result1 = await ContentBlueprintEditingService.CreateAsync(createModel1, Constants.Security.SuperUserKey); @@ -247,11 +247,11 @@ public async Task Can_Create_With_Duplicate_Name_For_Different_Content_Types() { ContentTypeKey = contentType2.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create Blueprint", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" }, - }, + Variants = [new VariantModel { Name = "Test Create Blueprint" }], + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "The title value" } + ], }; // create another blueprint @@ -271,7 +271,7 @@ public async Task Cannot_Create_When_Content_Type_Not_Found() { ContentTypeKey = Guid.NewGuid(), ParentKey = Constants.System.RootKey, - InvariantName = "Test Create Blueprint", + Variants = [new VariantModel { Name = "Test Create Blueprint" }], }; var result = await ContentBlueprintEditingService.CreateAsync(createModel1, Constants.Security.SuperUserKey); @@ -309,4 +309,99 @@ public async Task Can_Create_Blueprint_In_A_Folder() Assert.AreEqual(blueprintKey, result.First().Key); }); } + + [Test] + public async Task Can_Create_Variant() + { + var contentType = await CreateVariantContentType(); + + var createModel = new ContentBlueprintCreateModel + { + ContentTypeKey = contentType.Key, + ParentKey = Constants.System.RootKey, + Variants = + [ + new VariantModel { Name = "English Blueprint", Culture = "en-US" }, + new VariantModel { Name = "Danish Blueprint", Culture = "da-DK" } + ], + Properties = + [ + new PropertyValueModel { Alias = "invariantTitle", Value = "The invariant title value" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The English title value", Culture = "en-US" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The Danish title value", Culture = "da-DK" }, + ], + }; + + var result = await ContentBlueprintEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); + + Assert.Multiple(() => + { + Assert.IsTrue(result.Success); + Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status); + }); + VerifyCreate(result.Result.Content); + + // re-get and re-test + VerifyCreate(await ContentBlueprintEditingService.GetAsync(result.Result.Content!.Key)); + + void VerifyCreate(IContent? createdBlueprint) + { + Assert.IsNotNull(createdBlueprint); + Assert.Multiple(() => + { + Assert.AreNotEqual(Guid.Empty, createdBlueprint.Key); + Assert.IsTrue(createdBlueprint.HasIdentity); + Assert.AreEqual("English Blueprint", createdBlueprint.GetCultureName("en-US")); + Assert.AreEqual("Danish Blueprint", createdBlueprint.GetCultureName("da-DK")); + Assert.AreEqual("The invariant title value", createdBlueprint.GetValue("invariantTitle")); + Assert.AreEqual("The English title value", createdBlueprint.GetValue("variantTitle", culture: "en-US")); + Assert.AreEqual("The Danish title value", createdBlueprint.GetValue("variantTitle", culture: "da-DK")); + }); + } + + // ensures it's not found by normal content + var contentFound = await ContentEditingService.GetAsync(result.Result.Content!.Key); + Assert.IsNull(contentFound); + } + + [TestCase("English Blueprint", "Unique Danish Name")] + [TestCase("Unique English Name", "Danish Blueprint")] + [TestCase("English Blueprint", "Danish Blueprint")] + public async Task Cannot_Create_With_Duplicate_Name_For_The_Same_Content_Type_Variant(string secondBlueprintNameInEnglish, string secondBlueprintNameInDanish) + { + var contentType = await CreateVariantContentType(); + + var createModel = new ContentBlueprintCreateModel + { + ContentTypeKey = contentType.Key, + ParentKey = Constants.System.RootKey, + Variants = + [ + new VariantModel { Name = "English Blueprint", Culture = "en-US" }, + new VariantModel { Name = "Danish Blueprint", Culture = "da-DK" } + ], + Properties = [] + }; + + Assert.IsTrue((await ContentBlueprintEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Success); + + createModel = new ContentBlueprintCreateModel + { + ContentTypeKey = contentType.Key, + ParentKey = Constants.System.RootKey, + Variants = + [ + new VariantModel { Name = secondBlueprintNameInEnglish, Culture = "en-US" }, + new VariantModel { Name = secondBlueprintNameInDanish, Culture = "da-DK" } + ], + Properties = [] + }; + var result = await ContentBlueprintEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); + + Assert.Multiple(() => + { + Assert.IsFalse(result.Success); + Assert.AreEqual(ContentEditingOperationStatus.DuplicateName, result.Status); + }); + } } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.CreateFromContent.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.CreateFromContent.cs index d3a99091ed7d..92f59650b722 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.CreateFromContent.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.CreateFromContent.cs @@ -17,11 +17,11 @@ public async Task Can_Create_From_Content() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" }, - }, + Variants = [new VariantModel { Name = "Test Create" }], + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "The title value" } + ], }; var createContentResult = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.GetPagedByContentTypeKey.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.GetPagedByContentTypeKey.cs index eb0190b83a51..7cdfdf56e8b5 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.GetPagedByContentTypeKey.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.GetPagedByContentTypeKey.cs @@ -17,7 +17,7 @@ public async Task Can_Get_Paged() var createModel = new ContentBlueprintCreateModel { ContentTypeKey = contentType.Key, - InvariantName = $"Blueprint {i}", + Variants = [new VariantModel { Name = $"Blueprint {i}" }], }; await ContentBlueprintEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.Update.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.Update.cs index 41692e0ea9e3..5db71e8baa5e 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.Update.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.Update.cs @@ -15,12 +15,12 @@ public async Task Can_Update_Invariant() var updateModel = new ContentBlueprintUpdateModel { - InvariantName = "Updated Blueprint Name", - InvariantProperties = new[] - { + Variants = [new VariantModel { Name = "Updated Blueprint Name" }], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The updated title" }, - new PropertyValueModel { Alias = "text", Value = "The updated text" }, - }, + new PropertyValueModel { Alias = "text", Value = "The updated text" } + ], }; var result = await ContentBlueprintEditingService.UpdateAsync(blueprint.Key, updateModel, Constants.Security.SuperUserKey); @@ -54,30 +54,16 @@ public async Task Can_Update_Variant() var updateModel = new ContentBlueprintUpdateModel { - InvariantProperties = new[] + Properties = new[] { new PropertyValueModel { Alias = "invariantTitle", Value = "The updated blueprint invariant title" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated English title", Culture = "en-US" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated Danish title", Culture = "da-DK" }, }, Variants = new[] { - new VariantModel - { - Culture = "en-US", - Name = "Updated Blueprint English Name", - Properties = new[] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The updated English title" }, - }, - }, - new VariantModel - { - Culture = "da-DK", - Name = "Updated Blueprint Danish Name", - Properties = new[] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The updated Danish title" }, - }, - }, + new VariantModel { Culture = "en-US", Name = "Updated Blueprint English Name" }, + new VariantModel { Culture = "da-DK", Name = "Updated Blueprint Danish Name" }, }, }; @@ -117,11 +103,11 @@ public async Task Cannot_Update_With_Duplicate_Name_For_The_Same_Content_Type() { ContentTypeKey = blueprintToUpdate.ContentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Blueprint", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" }, - }, + Variants = [new VariantModel { Name = "Test Blueprint" }], + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "The title value" } + ], }; var createResult = await ContentBlueprintEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -136,7 +122,7 @@ public async Task Cannot_Update_With_Duplicate_Name_For_The_Same_Content_Type() // update a blueprint with the same name var updateModel = new ContentBlueprintUpdateModel { - InvariantName = "Test Blueprint", + Variants = [new VariantModel { Name = "Test Blueprint" }] }; var updateResult = await ContentBlueprintEditingService.UpdateAsync(blueprintToUpdate.Key, updateModel, Constants.Security.SuperUserKey); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.cs index ef559773cde2..c15e61940933 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentBlueprintEditingServiceTests.cs @@ -25,12 +25,12 @@ private async Task CreateInvariantContentBlueprint() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Initial Blueprint Name", - InvariantProperties = new[] - { + Variants = [new VariantModel { Name = "Initial Blueprint Name" }], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The initial title" }, - new PropertyValueModel { Alias = "text", Value = "The initial text" }, - }, + new PropertyValueModel { Alias = "text", Value = "The initial text" } + ], }; var result = await ContentBlueprintEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -46,31 +46,17 @@ private async Task CreateVariantContentBlueprint() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantProperties = new[] - { + Properties = + [ new PropertyValueModel { Alias = "invariantTitle", Value = "The initial invariant title" }, - }, - Variants = new[] - { - new VariantModel - { - Culture = "en-US", - Name = "Initial Blueprint English Name", - Properties = new[] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The initial English title" }, - }, - }, - new VariantModel - { - Culture = "da-DK", - Name = "Initial Blueprint Danish Name", - Properties = new[] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The initial Danish title" }, - }, - }, - }, + new PropertyValueModel { Alias = "variantTitle", Value = "The initial English title", Culture = "en-US" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The initial Danish title", Culture = "da-DK" } + ], + Variants = + [ + new VariantModel { Culture = "en-US", Name = "Initial Blueprint English Name" }, + new VariantModel { Culture = "da-DK", Name = "Initial Blueprint Danish Name" } + ], }; var result = await ContentBlueprintEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -85,12 +71,12 @@ private ContentBlueprintCreateModel SimpleContentBlueprintCreateModel(Guid bluep Key = blueprintKey, ContentTypeKey = ContentType.Key, ParentKey = containerKey, - InvariantName = "Blueprint #1", - InvariantProperties = new[] - { + Variants = [new VariantModel { Name = "Blueprint #1" }], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The title value" }, new PropertyValueModel { Alias = "author", Value = "The author value" } - } + ] }; return createModel; } @@ -99,12 +85,12 @@ private ContentBlueprintUpdateModel SimpleContentBlueprintUpdateModel() { var createModel = new ContentBlueprintUpdateModel { - InvariantName = "Blueprint #1 updated", - InvariantProperties = new[] - { + Variants = [new VariantModel { Name = "Blueprint #1 updated" }], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The title value updated" }, new PropertyValueModel { Alias = "author", Value = "The author value updated" } - } + ] }; return createModel; } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Create.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Create.cs index 104fc7ce3ce3..7d0a12110ac5 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Create.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Create.cs @@ -28,12 +28,15 @@ public async Task Can_Create_At_Root(bool allowedAtRoot) ContentTypeKey = contentType.Key, TemplateKey = template.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create", - InvariantProperties = new[] - { + Variants = + [ + new VariantModel { Name = "Test Create" } + ], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The title value" }, - new PropertyValueModel { Alias = "bodyText", Value = "The body text" } - } + new PropertyValueModel { Alias = "bodyText", Value = "The body text" } + ] }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -91,7 +94,12 @@ public async Task Can_Create_As_Child(bool allowedAsChild) var rootKey = (await ContentEditingService.CreateAsync( new ContentCreateModel { - ContentTypeKey = rootContentType.Key, InvariantName = "Root", ParentKey = Constants.System.RootKey, + ContentTypeKey = rootContentType.Key, + ParentKey = Constants.System.RootKey, + Variants = + [ + new VariantModel { Name = "Root" } + ], }, Constants.Security.SuperUserKey)).Result.Content!.Key; @@ -100,12 +108,15 @@ public async Task Can_Create_As_Child(bool allowedAsChild) ContentTypeKey = childContentType.Key, TemplateKey = template.Key, ParentKey = rootKey, - InvariantName = "Test Create Child", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The child title value" }, - new PropertyValueModel { Alias = "bodyText", Value = "The child body text" } - } + Variants = + [ + new VariantModel { Name = "Test Create Child" } + ], + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "The child title value" }, + new PropertyValueModel { Alias = "bodyText", Value = "The child body text" } + ] }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -144,11 +155,14 @@ public async Task Can_Create_Without_Template() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" } - } + Variants = + [ + new VariantModel { Name = "Test Create" } + ], + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "The title value" } + ] }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -173,7 +187,10 @@ public async Task Can_Create_Without_Properties() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create" + Variants = + [ + new VariantModel { Name = "Test Create" } + ], }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -204,11 +221,14 @@ public async Task Can_Create_With_Property_Validation(bool addValidProperties) { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create", - InvariantProperties = new[] + Variants = + [ + new VariantModel { Name = "Test Create" } + ], + Properties = new[] { - new PropertyValueModel { Alias = "title", Value = titleValue }, - new PropertyValueModel { Alias = "keywords", Value = keywordsValue } + new PropertyValueModel { Alias = "title", Value = titleValue }, + new PropertyValueModel { Alias = "keywords", Value = keywordsValue } } }; @@ -243,7 +263,10 @@ public async Task Cannot_Create_With_Non_Existing_Parent() { ContentTypeKey = contentType.Key, ParentKey = Guid.NewGuid(), - InvariantName = "Test Create" + Variants = + [ + new VariantModel { Name = "Test Create" } + ], }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -260,7 +283,10 @@ public async Task Cannot_Create_Without_Content_Type() { ContentTypeKey = Guid.NewGuid(), ParentKey = Constants.System.RootKey, - InvariantName = "Test Create", + Variants = + [ + new VariantModel { Name = "Test Create" } + ], }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -285,7 +311,10 @@ public async Task Cannot_Create_With_Invalid_Template() ContentTypeKey = contentType.Key, TemplateKey = template.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create" + Variants = + [ + new VariantModel { Name = "Test Create" } + ], }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -307,7 +336,10 @@ public async Task Cannot_Create_With_Non_Existing_Template() ContentTypeKey = contentType.Key, TemplateKey = Guid.NewGuid(), ParentKey = Constants.System.RootKey, - InvariantName = "Test Create" + Variants = + [ + new VariantModel { Name = "Test Create" } + ], }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -329,12 +361,15 @@ public async Task Cannot_Create_With_Non_Existing_Properties() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" }, - new PropertyValueModel { Alias = "no_such_property", Value = "No such property value" }, - } + Variants = + [ + new VariantModel { Name = "Test Create" } + ], + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "The title value" }, + new PropertyValueModel { Alias = "no_such_property", Value = "No such property value" } + ] }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -356,11 +391,11 @@ public async Task Cannot_Create_Invariant_Content_Without_Name() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = null, - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" } - } + Variants = [], + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "The title value" } + ] }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -383,24 +418,25 @@ public async Task Cannot_Create_With_Variant_Property_Value_For_Invariant_Conten { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create", - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "title", Value = "The title value" } - }, - Variants = new [] - { - new VariantModel + Variants = + [ + new VariantModel { Name = "Test Create" } + ], + Properties = + [ + new PropertyValueModel { + Alias = "title", + Value = "The title value" + }, + new PropertyValueModel + { + Alias = "bodyText", + Value = "The body text value", Culture = contentVariation is ContentVariation.Culture ? "en-US" : null, - Segment = contentVariation is ContentVariation.Segment ? "segment" : null, - Name = "The English Name", - Properties = new [] - { - new PropertyValueModel { Alias = "bodyText", Value = "The body text value" } - } + Segment = contentVariation is ContentVariation.Segment ? "segment" : null } - } + ] }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -419,31 +455,17 @@ public async Task Can_Create_Culture_Variant() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "invariantTitle", Value = "The Invariant Title" } - }, - Variants = new[] - { - new VariantModel - { - Culture = "en-US", - Name = "The English Name", - Properties = new[] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The English Title" } - } - }, - new VariantModel - { - Culture = "da-DK", - Name = "The Danish Name", - Properties = new[] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The Danish Title" } - } - } - } + Properties = + [ + new PropertyValueModel { Alias = "invariantTitle", Value = "The Invariant Title" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The English Title", Culture = "en-US" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The Danish Title", Culture = "da-DK" } + ], + Variants = + [ + new VariantModel { Culture = "en-US", Name = "The English Name" }, + new VariantModel { Culture = "da-DK", Name = "The Danish Name" } + ] }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -467,7 +489,6 @@ void VerifyCreate(IContent? createdContent) } [Test] - [Ignore("Validation for segment-only variants will be fixed in a follow-up PR.")] public async Task Can_Create_Segment_Variant() { var contentType = await CreateVariantContentType(ContentVariation.Segment); @@ -476,39 +497,18 @@ public async Task Can_Create_Segment_Variant() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantProperties = + Properties = [ - new () { Alias = "invariantTitle", Value = "The Invariant Title" } + new () { Alias = "invariantTitle", Value = "The Invariant Title" }, + new () { Alias = "variantTitle", Value = "The Default Title" }, + new () { Alias = "variantTitle", Value = "The Seg-1 Title", Segment = "seg-1" }, + new () { Alias = "variantTitle", Value = "The Seg-2 Title", Segment = "seg-2" } ], Variants = [ - new () - { - Segment = null, - Name = "The Name", - Properties = - [ - new () { Alias = "variantTitle", Value = "The Default Title" } - ] - }, - new () - { - Segment = "seg-1", - Name = "The Name", - Properties = - [ - new () { Alias = "variantTitle", Value = "The Seg-1 Title" } - ] - }, - new () - { - Segment = "seg-2", - Name = "The Name", - Properties = - [ - new () { Alias = "variantTitle", Value = "The Seg-2 Title" } - ] - } + new () { Name = "The Name" }, + new () { Segment = "seg-1", Name = "The Name" }, + new () { Segment = "seg-2", Name = "The Name" } ] }; @@ -544,72 +544,24 @@ public async Task Can_Create_Culture_And_Segment_Variant() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantProperties = + Properties = [ - new () { Alias = "invariantTitle", Value = "The Invariant Title" } + new () { Alias = "invariantTitle", Value = "The Invariant Title" }, + new () { Alias = "variantTitle", Value = "The Default Title in English", Culture = "en-US" }, + new () { Alias = "variantTitle", Value = "The Seg-1 Title in English", Culture = "en-US", Segment = "seg-1" }, + new () { Alias = "variantTitle", Value = "The Seg-2 Title in English", Culture = "en-US", Segment = "seg-2" }, + new () { Alias = "variantTitle", Value = "The Default Title in Danish", Culture = "da-DK" }, + new () { Alias = "variantTitle", Value = "The Seg-1 Title in Danish", Culture = "da-DK", Segment = "seg-1" }, + new () { Alias = "variantTitle", Value = "The Seg-2 Title in Danish", Culture = "da-DK", Segment = "seg-2" } ], Variants = [ - new () - { - Name = "The English Name", - Culture = "en-US", - Segment = null, - Properties = - [ - new () { Alias = "variantTitle", Value = "The Default Title in English" } - ] - }, - new () - { - Name = "The English Name", - Culture = "en-US", - Segment = "seg-1", - Properties = - [ - new () { Alias = "variantTitle", Value = "The Seg-1 Title in English" } - ] - }, - new () - { - Name = "The English Name", - Culture = "en-US", - Segment = "seg-2", - Properties = - [ - new () { Alias = "variantTitle", Value = "The Seg-2 Title in English" } - ] - }, - new () - { - Name = "The Danish Name", - Culture = "da-DK", - Segment = null, - Properties = - [ - new () { Alias = "variantTitle", Value = "The Default Title in Danish" } - ] - }, - new () - { - Name = "The Danish Name", - Culture = "da-DK", - Segment = "seg-1", - Properties = - [ - new () { Alias = "variantTitle", Value = "The Seg-1 Title in Danish" } - ] - }, - new () - { - Name = "The Danish Name", - Culture = "da-DK", - Segment = "seg-2", - Properties = - [ - new () { Alias = "variantTitle", Value = "The Seg-2 Title in Danish" } - ] - } + new () { Name = "The English Name", Culture = "en-US" }, + new () { Name = "The English Name", Culture = "en-US", Segment = "seg-1" }, + new () { Name = "The English Name", Culture = "en-US", Segment = "seg-2" }, + new () { Name = "The Danish Name", Culture = "da-DK" }, + new () { Name = "The Danish Name", Culture = "da-DK", Segment = "seg-1" }, + new () { Name = "The Danish Name", Culture = "da-DK", Segment = "seg-2" } ] }; @@ -640,6 +592,134 @@ void VerifyCreate(IContent? createdContent) } } + [Test] + public async Task Can_Create_Culture_And_Segment_Variant_With_Segment_Only_Variant_Property() + { + var contentType = await CreateVariantContentType(ContentVariation.CultureAndSegment); + var propertyType = contentType.PropertyTypes.First(pt => pt.Alias == "invariantTitle"); + propertyType.Alias = "segmentVariantTitle"; + propertyType.Variations = ContentVariation.Segment; + ContentTypeService.Save(contentType); + + var createModel = new ContentCreateModel + { + ContentTypeKey = contentType.Key, + ParentKey = Constants.System.RootKey, + Properties = + [ + new () { Alias = "segmentVariantTitle", Value = "The Default Segment Variant Title", Segment = null }, + new () { Alias = "segmentVariantTitle", Value = "The Seg-1 Segment Variant Title", Segment = "seg-1" }, + new () { Alias = "segmentVariantTitle", Value = "The Seg-2 Segment Variant Title", Segment = "seg-2" }, + new () { Alias = "variantTitle", Value = "The Default Title in English", Culture = "en-US" }, + new () { Alias = "variantTitle", Value = "The Seg-1 Title in English", Culture = "en-US", Segment = "seg-1" }, + new () { Alias = "variantTitle", Value = "The Seg-2 Title in English", Culture = "en-US", Segment = "seg-2" }, + new () { Alias = "variantTitle", Value = "The Default Title in Danish", Culture = "da-DK" }, + new () { Alias = "variantTitle", Value = "The Seg-1 Title in Danish", Culture = "da-DK", Segment = "seg-1" }, + new () { Alias = "variantTitle", Value = "The Seg-2 Title in Danish", Culture = "da-DK", Segment = "seg-2" } + ], + Variants = + [ + new () { Name = "The English Name", Culture = "en-US" }, + new () { Name = "The English Name", Culture = "en-US", Segment = "seg-1" }, + new () { Name = "The English Name", Culture = "en-US", Segment = "seg-2" }, + new () { Name = "The Danish Name", Culture = "da-DK" }, + new () { Name = "The Danish Name", Culture = "da-DK", Segment = "seg-1" }, + new () { Name = "The Danish Name", Culture = "da-DK", Segment = "seg-2" } + ] + }; + + var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); + Assert.IsTrue(result.Success); + Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status); + Assert.IsNotNull(result.Result.Content); + VerifyCreate(result.Result.Content); + + // re-get and re-test + VerifyCreate(await ContentEditingService.GetAsync(result.Result.Content.Key)); + + void VerifyCreate(IContent? createdContent) + { + Assert.IsNotNull(createdContent); + Assert.Multiple(() => + { + Assert.AreEqual("The English Name", createdContent.GetCultureName("en-US")); + Assert.AreEqual("The Danish Name", createdContent.GetCultureName("da-DK")); + Assert.AreEqual("The Default Segment Variant Title", createdContent.GetValue("segmentVariantTitle")); + Assert.AreEqual("The Seg-1 Segment Variant Title", createdContent.GetValue("segmentVariantTitle", segment: "seg-1")); + Assert.AreEqual("The Seg-2 Segment Variant Title", createdContent.GetValue("segmentVariantTitle", segment: "seg-2")); + Assert.AreEqual("The Default Title in English", createdContent.GetValue("variantTitle", culture: "en-US", segment: null)); + Assert.AreEqual("The Seg-1 Title in English", createdContent.GetValue("variantTitle", culture: "en-US", segment: "seg-1")); + Assert.AreEqual("The Seg-2 Title in English", createdContent.GetValue("variantTitle", culture: "en-US", segment: "seg-2")); + Assert.AreEqual("The Default Title in Danish", createdContent.GetValue("variantTitle", culture: "da-DK", segment: null)); + Assert.AreEqual("The Seg-1 Title in Danish", createdContent.GetValue("variantTitle", culture: "da-DK", segment: "seg-1")); + Assert.AreEqual("The Seg-2 Title in Danish", createdContent.GetValue("variantTitle", culture: "da-DK", segment: "seg-2")); + }); + } + } + + [Test] + public async Task Can_Create_Culture_And_Segment_Variant_With_Culture_Only_Variant_Property() + { + var contentType = await CreateVariantContentType(ContentVariation.CultureAndSegment); + var propertyType = contentType.PropertyTypes.First(pt => pt.Alias == "invariantTitle"); + propertyType.Alias = "cultureVariantTitle"; + propertyType.Variations = ContentVariation.Culture; + ContentTypeService.Save(contentType); + + var createModel = new ContentCreateModel + { + ContentTypeKey = contentType.Key, + ParentKey = Constants.System.RootKey, + Properties = + [ + new () { Alias = "cultureVariantTitle", Value = "The English Culture Variant Title", Culture = "en-US" }, + new () { Alias = "cultureVariantTitle", Value = "The Danish Culture Variant Title", Culture = "da-DK" }, + new () { Alias = "variantTitle", Value = "The Default Title in English", Culture = "en-US" }, + new () { Alias = "variantTitle", Value = "The Seg-1 Title in English", Culture = "en-US", Segment = "seg-1" }, + new () { Alias = "variantTitle", Value = "The Seg-2 Title in English", Culture = "en-US", Segment = "seg-2" }, + new () { Alias = "variantTitle", Value = "The Default Title in Danish", Culture = "da-DK" }, + new () { Alias = "variantTitle", Value = "The Seg-1 Title in Danish", Culture = "da-DK", Segment = "seg-1" }, + new () { Alias = "variantTitle", Value = "The Seg-2 Title in Danish", Culture = "da-DK", Segment = "seg-2" } + ], + Variants = + [ + new () { Name = "The English Name", Culture = "en-US" }, + new () { Name = "The English Name", Culture = "en-US", Segment = "seg-1" }, + new () { Name = "The English Name", Culture = "en-US", Segment = "seg-2" }, + new () { Name = "The Danish Name", Culture = "da-DK" }, + new () { Name = "The Danish Name", Culture = "da-DK", Segment = "seg-1" }, + new () { Name = "The Danish Name", Culture = "da-DK", Segment = "seg-2" } + ] + }; + + var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); + Assert.IsTrue(result.Success); + Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status); + Assert.IsNotNull(result.Result.Content); + VerifyCreate(result.Result.Content); + + // re-get and re-test + VerifyCreate(await ContentEditingService.GetAsync(result.Result.Content.Key)); + + void VerifyCreate(IContent? createdContent) + { + Assert.IsNotNull(createdContent); + Assert.Multiple(() => + { + Assert.AreEqual("The English Name", createdContent.GetCultureName("en-US")); + Assert.AreEqual("The Danish Name", createdContent.GetCultureName("da-DK")); + Assert.AreEqual("The English Culture Variant Title", createdContent.GetValue("cultureVariantTitle", culture: "en-US")); + Assert.AreEqual("The Danish Culture Variant Title", createdContent.GetValue("cultureVariantTitle", culture: "da-DK")); + Assert.AreEqual("The Default Title in English", createdContent.GetValue("variantTitle", culture: "en-US", segment: null)); + Assert.AreEqual("The Seg-1 Title in English", createdContent.GetValue("variantTitle", culture: "en-US", segment: "seg-1")); + Assert.AreEqual("The Seg-2 Title in English", createdContent.GetValue("variantTitle", culture: "en-US", segment: "seg-2")); + Assert.AreEqual("The Default Title in Danish", createdContent.GetValue("variantTitle", culture: "da-DK", segment: null)); + Assert.AreEqual("The Seg-1 Title in Danish", createdContent.GetValue("variantTitle", culture: "da-DK", segment: "seg-1")); + Assert.AreEqual("The Seg-2 Title in Danish", createdContent.GetValue("variantTitle", culture: "da-DK", segment: "seg-2")); + }); + } + } + [Test] public async Task Can_Create_With_Explicit_Key() { @@ -654,11 +734,14 @@ public async Task Can_Create_With_Explicit_Key() Key = key, ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Test Create", - InvariantProperties = new[] - { + Variants = + [ + new () { Name = "Test Create" } + ], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The title value" } - } + ] }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -683,11 +766,15 @@ public async Task Cannot_Create_With_Invariant_Property_Value_For_Variant_Conten { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantProperties = new[] - { + Variants = + [ + new () { Name = "Test Create", Culture = "en-US" } + ], + Properties = + [ new PropertyValueModel { Alias = "invariantTitle", Value = "The Invariant Title" }, new PropertyValueModel { Alias = "variantTitle", Value = "The Variant Title" } - } + ] }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -706,19 +793,14 @@ public async Task Cannot_Create_With_Segment_Variant_Property_Value_For_Culture_ { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantProperties = [ + Properties = + [ new () { Alias = "invariantTitle", Value = "The Invariant Title" }, + new () { Alias = "variantTitle", Value = "The Variant Title", Culture = "en-US", Segment = "segment" } ], - Variants = [ - new () - { - Name = "The name", - Culture = "en-US", - Segment = "segment", - Properties = [ - new () { Alias = "variantTitle", Value = "The Variant Title" } - ] - } + Variants = + [ + new () { Name = "The name", Culture = "en-US", Segment = "segment" } ] }; @@ -743,7 +825,12 @@ public async Task Cannot_Create_Under_Trashed_Parent() var rootKey = (await ContentEditingService.CreateAsync( new ContentCreateModel { - ContentTypeKey = contentType.Key, InvariantName = "Root", ParentKey = Constants.System.RootKey + ContentTypeKey = contentType.Key, + ParentKey = Constants.System.RootKey, + Variants = + [ + new () { Name = "Root" } + ] }, Constants.Security.SuperUserKey)).Result.Content!.Key; @@ -752,7 +839,12 @@ public async Task Cannot_Create_Under_Trashed_Parent() var result = await ContentEditingService.CreateAsync( new ContentCreateModel { - ContentTypeKey = contentType.Key, InvariantName = "Child", ParentKey = rootKey, + ContentTypeKey = contentType.Key, + ParentKey = rootKey, + Variants = + [ + new () { Name = "Child" } + ] }, Constants.Security.SuperUserKey); @@ -771,31 +863,17 @@ public async Task Cannot_Create_Culture_Variant_With_Incorrect_Culture_Casing() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "invariantTitle", Value = "The Invariant Title" } - }, - Variants = new[] - { - new VariantModel - { - Culture = "en-us", - Name = "The English Name", - Properties = new[] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The English Title" } - } - }, - new VariantModel - { - Culture = "da-dk", - Name = "The Danish Name", - Properties = new[] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The Danish Title" } - } - } - } + Properties = + [ + new PropertyValueModel { Alias = "invariantTitle", Value = "The Invariant Title" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The English Title", Culture = "en-us" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The Danish Title", Culture = "da-dk" } + ], + Variants = + [ + new VariantModel { Culture = "en-us", Name = "The English Name" }, + new VariantModel { Culture = "da-dk", Name = "The Danish Name" } + ] }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -812,30 +890,16 @@ public async Task Cannot_Create_Segment_Variant_Without_Default_Segment() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "invariantTitle", Value = "The Invariant Title" } - }, + Properties = + [ + new PropertyValueModel { Alias = "invariantTitle", Value = "The Invariant Title" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The Seg-1 Title", Segment = "seg-1" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The Seg-2 Title", Segment = "seg-2" } + ], Variants = [ - new () - { - Segment = "seg-1", - Name = "The Name", - Properties = - [ - new () { Alias = "variantTitle", Value = "The Seg-1 Title" } - ] - }, - new () - { - Segment = "seg-2", - Name = "The Name", - Properties = - [ - new () { Alias = "variantTitle", Value = "The Seg-2 Title" } - ] - } + new () { Segment = "seg-1", Name = "The Name" }, + new () { Segment = "seg-2", Name = "The Name" } ] }; diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Sort.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Sort.cs index fac576544c14..6699361ae765 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Sort.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Sort.cs @@ -55,7 +55,7 @@ public async Task Can_Sort_Root_Content(bool useRootKeyForSorting) await ContentEditingService.CreateAsync( new ContentCreateModel { - ContentTypeKey = rootContentType.Key, InvariantName = $"Root {i}", ParentKey = Constants.System.RootKey, + ContentTypeKey = rootContentType.Key, Variants = [new () { Name = $"Root {i}" }], ParentKey = Constants.System.RootKey, }, Constants.Security.SuperUserKey); } @@ -130,7 +130,7 @@ private async Task CreateRootContentWithTenChildren() var root = (await ContentEditingService.CreateAsync( new ContentCreateModel { - ContentTypeKey = rootContentType.Key, InvariantName = "Root", ParentKey = Constants.System.RootKey, + ContentTypeKey = rootContentType.Key, Variants = [new () { Name = "Root" }], ParentKey = Constants.System.RootKey, }, Constants.Security.SuperUserKey)).Result.Content!; @@ -140,7 +140,7 @@ private async Task CreateRootContentWithTenChildren() { ContentTypeKey = childContentType.Key, ParentKey = root.Key, - InvariantName = $"Child {i}", + Variants = [new () { Name = $"Child {i}" }] }; await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Update.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Update.cs index 4ad29923b59b..a834b5f08647 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Update.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Update.cs @@ -17,12 +17,15 @@ public async Task Can_Update_Invariant() var updateModel = new ContentUpdateModel { - InvariantName = "Updated Name", - InvariantProperties = new[] - { + Variants = + [ + new VariantModel { Name = "Updated Name" } + ], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The updated title" }, new PropertyValueModel { Alias = "text", Value = "The updated text" } - } + ] }; var result = await ContentEditingService.UpdateAsync(content.Key, updateModel, Constants.Security.SuperUserKey); @@ -49,31 +52,17 @@ public async Task Can_Update_Culture_Variant() var updateModel = new ContentUpdateModel { - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" } - }, - Variants = new [] - { - new VariantModel - { - Culture = "en-US", - Name = "Updated English Name", - Properties = new [] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The updated English title" } - } - }, - new VariantModel - { - Culture = "da-DK", - Name = "Updated Danish Name", - Properties = new [] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The updated Danish title" } - } - } - } + Properties = + [ + new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated English title", Culture = "en-US" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated Danish title", Culture = "da-DK" }, + ], + Variants = + [ + new VariantModel { Culture = "en-US", Name = "Updated English Name" }, + new VariantModel { Culture = "da-DK", Name = "Updated Danish Name" } + ] }; var result = await ContentEditingService.UpdateAsync(content.Key, updateModel, Constants.Security.SuperUserKey); @@ -96,47 +85,25 @@ void VerifyUpdate(IContent? updatedContent) } [Test] - [Ignore("Validation for segment-only variants will be fixed in a follow-up PR.")] public async Task Can_Update_Segment_Variant() { var content = await CreateSegmentVariantContent(); var updateModel = new ContentUpdateModel { - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" } - }, - Variants = new [] - { - new VariantModel - { - Segment = null, - Name = "The Updated Name", - Properties = new [] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The updated default title" } - } - }, - new VariantModel - { - Segment = "seg-1", - Name = "The Updated Name", - Properties = new [] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The updated seg-1 title" } - } - }, - new VariantModel - { - Segment = "seg-2", - Name = "The Updated Name", - Properties = new [] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The updated seg-2 title" } - } - }, - } + Properties = + [ + new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated default title" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated seg-1 title", Segment = "seg-1" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated seg-2 title", Segment = "seg-2" } + ], + Variants = + [ + new VariantModel { Name = "The Updated Name" }, + new VariantModel { Segment = "seg-1", Name = "The Updated Name" }, + new VariantModel { Segment = "seg-2", Name = "The Updated Name" } + ] }; var result = await ContentEditingService.UpdateAsync(content.Key, updateModel, Constants.Security.SuperUserKey); @@ -161,6 +128,122 @@ void VerifyUpdate(IContent? updatedContent) } } + [Test] + public async Task Can_Update_Culture_And_Segment_Variant_With_Culture_Only_Variant_Property() + { + var content = await CreateCultureAndSegmentVariantContent(ContentVariation.Culture); + + var updateModel = new ContentUpdateModel + { + Properties = + [ + new PropertyValueModel { Alias = "variantTitle", Value = "The updated default English title", Culture = "en-US" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated seg-1 English title", Culture = "en-US", Segment = "seg-1" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated seg-2 English title", Culture = "en-US", Segment = "seg-2" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated default Danish title", Culture = "da-DK" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated seg-1 Danish title", Culture = "da-DK", Segment = "seg-1" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated seg-2 Danish title", Culture = "da-DK", Segment = "seg-2" }, + new PropertyValueModel { Alias = "otherTitle", Value = "The updated other English title", Culture = "en-US" }, + new PropertyValueModel { Alias = "otherTitle", Value = "The updated other Danish title", Culture = "da-DK" }, + ], + Variants = + [ + new VariantModel { Name = "The Updated English Default Name", Culture = "en-US" }, + new VariantModel { Name = "The Updated English Seg-1 Name", Culture = "en-US", Segment = "seg-1" }, + new VariantModel { Name = "The Updated English Seg-2 Name", Culture = "en-US", Segment = "seg-2" }, + new VariantModel { Name = "The Updated Danish Default Name", Culture = "da-DK" }, + new VariantModel { Name = "The Updated Danish Seg-1 Name", Culture = "da-DK", Segment = "seg-1" }, + new VariantModel { Name = "The Updated Danish Seg-2 Name", Culture = "da-DK", Segment = "seg-2" }, + ] + }; + + var result = await ContentEditingService.UpdateAsync(content.Key, updateModel, Constants.Security.SuperUserKey); + Assert.IsTrue(result.Success); + Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status); + VerifyUpdate(result.Result.Content); + + // re-get and re-test + VerifyUpdate(await ContentEditingService.GetAsync(content.Key)); + + void VerifyUpdate(IContent? updatedContent) + { + Assert.IsNotNull(updatedContent); + Assert.Multiple(() => + { + // NOTE: names cannot differ between segments, only between culture - should always prefer segment-less names + Assert.AreEqual("The Updated English Default Name", updatedContent.GetCultureName("en-US")); + Assert.AreEqual("The Updated Danish Default Name", updatedContent.GetCultureName("da-DK")); + Assert.AreEqual("The updated default English title", updatedContent.GetValue("variantTitle", culture: "en-US", segment: null)); + Assert.AreEqual("The updated seg-1 English title", updatedContent.GetValue("variantTitle", culture: "en-US", segment: "seg-1")); + Assert.AreEqual("The updated seg-2 English title", updatedContent.GetValue("variantTitle", culture: "en-US", segment: "seg-2")); + Assert.AreEqual("The updated default Danish title", updatedContent.GetValue("variantTitle", culture: "da-DK", segment: null)); + Assert.AreEqual("The updated seg-1 Danish title", updatedContent.GetValue("variantTitle", culture: "da-DK", segment: "seg-1")); + Assert.AreEqual("The updated seg-2 Danish title", updatedContent.GetValue("variantTitle", culture: "da-DK", segment: "seg-2")); + Assert.AreEqual("The updated other English title", updatedContent.GetValue("otherTitle", culture: "en-US", segment: null)); + Assert.AreEqual("The updated other Danish title", updatedContent.GetValue("otherTitle", culture: "da-DK", segment: null)); + }); + } + } + + [Test] + public async Task Can_Update_Culture_And_Segment_Variant_With_Segment_Only_Variant_Property() + { + var content = await CreateCultureAndSegmentVariantContent(ContentVariation.Segment); + + var updateModel = new ContentUpdateModel + { + Properties = + [ + new PropertyValueModel { Alias = "variantTitle", Value = "The updated default English title", Culture = "en-US" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated seg-1 English title", Culture = "en-US", Segment = "seg-1" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated seg-2 English title", Culture = "en-US", Segment = "seg-2" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated default Danish title", Culture = "da-DK" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated seg-1 Danish title", Culture = "da-DK", Segment = "seg-1" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated seg-2 Danish title", Culture = "da-DK", Segment = "seg-2" }, + new PropertyValueModel { Alias = "otherTitle", Value = "The updated other default title", Segment = null }, + new PropertyValueModel { Alias = "otherTitle", Value = "The updated other seg-1 title", Segment = "seg-1" }, + new PropertyValueModel { Alias = "otherTitle", Value = "The updated other seg-2 title", Segment = "seg-2" }, + ], + Variants = + [ + new VariantModel { Name = "The Updated English Default Name", Culture = "en-US" }, + new VariantModel { Name = "The Updated English Seg-1 Name", Culture = "en-US", Segment = "seg-1" }, + new VariantModel { Name = "The Updated English Seg-2 Name", Culture = "en-US", Segment = "seg-2" }, + new VariantModel { Name = "The Updated Danish Default Name", Culture = "da-DK" }, + new VariantModel { Name = "The Updated Danish Seg-1 Name", Culture = "da-DK", Segment = "seg-1" }, + new VariantModel { Name = "The Updated Danish Seg-2 Name", Culture = "da-DK", Segment = "seg-2" }, + ] + }; + + var result = await ContentEditingService.UpdateAsync(content.Key, updateModel, Constants.Security.SuperUserKey); + Assert.IsTrue(result.Success); + Assert.AreEqual(ContentEditingOperationStatus.Success, result.Status); + VerifyUpdate(result.Result.Content); + + // re-get and re-test + VerifyUpdate(await ContentEditingService.GetAsync(content.Key)); + + void VerifyUpdate(IContent? updatedContent) + { + Assert.IsNotNull(updatedContent); + Assert.Multiple(() => + { + // NOTE: names cannot differ between segments, only between culture - should always prefer segment-less names + Assert.AreEqual("The Updated English Default Name", updatedContent.GetCultureName("en-US")); + Assert.AreEqual("The Updated Danish Default Name", updatedContent.GetCultureName("da-DK")); + Assert.AreEqual("The updated default English title", updatedContent.GetValue("variantTitle", culture: "en-US", segment: null)); + Assert.AreEqual("The updated seg-1 English title", updatedContent.GetValue("variantTitle", culture: "en-US", segment: "seg-1")); + Assert.AreEqual("The updated seg-2 English title", updatedContent.GetValue("variantTitle", culture: "en-US", segment: "seg-2")); + Assert.AreEqual("The updated default Danish title", updatedContent.GetValue("variantTitle", culture: "da-DK", segment: null)); + Assert.AreEqual("The updated seg-1 Danish title", updatedContent.GetValue("variantTitle", culture: "da-DK", segment: "seg-1")); + Assert.AreEqual("The updated seg-2 Danish title", updatedContent.GetValue("variantTitle", culture: "da-DK", segment: "seg-2")); + Assert.AreEqual("The updated other default title", updatedContent.GetValue("otherTitle", culture: null, segment: null)); + Assert.AreEqual("The updated other seg-1 title", updatedContent.GetValue("otherTitle", culture: null, segment: "seg-1")); + Assert.AreEqual("The updated other seg-2 title", updatedContent.GetValue("otherTitle", culture: null, segment: "seg-2")); + }); + } + } + [Test] public async Task Can_Update_Template() { @@ -174,7 +257,10 @@ public async Task Can_Update_Template() var updateModel = new ContentUpdateModel { - InvariantName = "Updated Name", + Variants = + [ + new VariantModel { Name = "Updated Name" } + ], TemplateKey = templateTwo.Key }; @@ -203,7 +289,10 @@ public async Task Can_Remove_Template() var updateModel = new ContentUpdateModel { - InvariantName = "Updated Name", + Variants = + [ + new VariantModel { Name = "Updated Name" } + ], TemplateKey = null }; @@ -228,8 +317,11 @@ public async Task Can_Remove_Property_Value() var updateModel = new ContentUpdateModel { - InvariantName = "Updated Name", - InvariantProperties = new[] + Variants = + [ + new VariantModel { Name = "Updated Name" } + ], + Properties = new[] { new PropertyValueModel { Alias = "title", Value = "The updated title" } } @@ -267,8 +359,11 @@ public async Task Can_Update_With_Property_Validation(bool addValidProperties) var updateModel = new ContentUpdateModel { - InvariantName = content.Name, - InvariantProperties = new[] + Variants = + [ + new VariantModel { Name = content.Name } + ], + Properties = new[] { new PropertyValueModel { Alias = "title", Value = titleValue }, new PropertyValueModel { Alias = "text", Value = textValue } @@ -295,35 +390,26 @@ public async Task Can_Update_With_Property_Validation(bool addValidProperties) } [Test] - [Ignore("Validation for segment-only variants will be fixed in a follow-up PR.")] public async Task Cannot_Update_With_Variant_Property_Value_For_Invariant_Content() { var content = await CreateInvariantContent(); var updateModel = new ContentUpdateModel { - InvariantName = "Updated Name", - InvariantProperties = new[] - { + Variants = + [ + new VariantModel { Name = "Updated Name" } + ], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The updated title" }, - }, - Variants = new[] - { - new VariantModel - { - Culture = "en-US", - Name = "Updated English Name", - Properties = new[] - { - new PropertyValueModel { Alias = "text", Value = "The updated text" } - } - } - } + new PropertyValueModel { Alias = "text", Value = "The updated title", Culture = "en-US" } + ] }; var result = await ContentEditingService.UpdateAsync(content.Key, updateModel, Constants.Security.SuperUserKey); Assert.IsFalse(result.Success); - Assert.AreEqual(ContentEditingOperationStatus.ContentTypeCultureVarianceMismatch, result.Status); + Assert.AreEqual(ContentEditingOperationStatus.PropertyTypeNotFound, result.Status); // re-get and validate content = await ContentEditingService.GetAsync(content.Key); @@ -340,8 +426,12 @@ public async Task Cannot_Update_With_Invariant_Property_Value_For_Variant_Conten var updateModel = new ContentUpdateModel { - InvariantName = "Updated Name", - InvariantProperties = new[] + Variants = + [ + new VariantModel { Name = "Updated English Name", Culture = "en-US" }, + new VariantModel { Name = "Updated Danish Name", Culture = "da-DK" }, + ], + Properties = new[] { new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" }, new PropertyValueModel { Alias = "variantTitle", Value = "The updated variant title" } @@ -369,31 +459,17 @@ public async Task Cannot_Update_Variant_With_Incorrect_Culture_Casing() var updateModel = new ContentUpdateModel { - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" } - }, - Variants = new [] - { - new VariantModel - { - Culture = "en-us", - Name = "Updated English Name", - Properties = new [] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The updated English title" } - } - }, - new VariantModel - { - Culture = "da-dk", - Name = "Updated Danish Name", - Properties = new [] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The updated Danish title" } - } - } - } + Properties = + [ + new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated English title", Culture = "en-us" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated Danish title", Culture = "da-dk" } + ], + Variants = + [ + new VariantModel { Culture = "en-us", Name = "Updated English Name" }, + new VariantModel { Culture = "da-dk", Name = "Updated Danish Name" } + ] }; var result = await ContentEditingService.UpdateAsync(content.Key, updateModel, Constants.Security.SuperUserKey); @@ -410,12 +486,15 @@ public async Task Cannot_Update_Invariant_Readonly_Property_Value() var updateModel = new ContentUpdateModel { - InvariantName = "Updated Name", - InvariantProperties = new[] - { + Variants = + [ + new VariantModel { Name = "Updated Name" } + ], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The initial title" }, new PropertyValueModel { Alias = "label", Value = "The updated label value" } - } + ] }; var result = await ContentEditingService.UpdateAsync(content.Key, updateModel, Constants.Security.SuperUserKey); @@ -446,33 +525,27 @@ public async Task Cannot_Update_Variant_Readonly_Property_Value() var updateModel = new ContentUpdateModel { - InvariantProperties = new[] - { - new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" } - }, - Variants = new [] - { + Properties = + [ + new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The initial English title", Culture = "en-US" }, + new PropertyValueModel { Alias = "variantLabel", Value = "The updated English label value", Culture = "en-US" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The initial Danish title", Culture = "da-DK" }, + new PropertyValueModel { Alias = "variantLabel", Value = "The updated Danish label value", Culture = "da-DK" } + ], + Variants = + [ new VariantModel { Culture = "en-US", - Name = "Updated English Name", - Properties = new [] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The initial English title" }, - new PropertyValueModel { Alias = "variantLabel", Value = "The updated English label value" } - } + Name = "Updated English Name" }, new VariantModel { Culture = "da-DK", - Name = "Updated Danish Name", - Properties = new [] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The initial Danish title" }, - new PropertyValueModel { Alias = "variantLabel", Value = "The updated Danish label value" } - } + Name = "Updated Danish Name" } - } + ] }; var result = await ContentEditingService.UpdateAsync(content.Key, updateModel, Constants.Security.SuperUserKey); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Validate.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Validate.cs index 13b76aff83a0..26ddddc08968 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Validate.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.Validate.cs @@ -18,8 +18,11 @@ public async Task Can_Validate_Valid_Invariant_Content() var validateContentUpdateModel = new ValidateContentUpdateModel { - InvariantName = "Updated Name", - InvariantProperties = + Variants = + [ + new () { Name = "Updated Name" } + ], + Properties = [ new PropertyValueModel { Alias = "title", Value = "The updated title" }, new PropertyValueModel { Alias = "text", Value = "The updated text" } @@ -38,8 +41,11 @@ public async Task Will_Fail_Invalid_Invariant_Content() var validateContentUpdateModel = new ValidateContentUpdateModel { - InvariantName = "Updated Name", - InvariantProperties = + Variants = + [ + new () { Name = "Updated Name" } + ], + Properties = [ new PropertyValueModel { Alias = "title", Value = null }, new PropertyValueModel { Alias = "text", Value = "The updated text" } @@ -60,30 +66,16 @@ public async Task Can_Validate_Valid_Variant_Content() var validateContentUpdateModel = new ValidateContentUpdateModel { - InvariantProperties = + Properties = [ - new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" } + new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated English title", Culture = "en-US" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated Danish title", Culture = "da-DK" } ], Variants = [ - new VariantModel - { - Culture = "en-US", - Name = "Updated English Name", - Properties = - [ - new PropertyValueModel { Alias = "variantTitle", Value = "The updated English title" } - ] - }, - new VariantModel - { - Culture = "da-DK", - Name = "Updated Danish Name", - Properties = - [ - new PropertyValueModel { Alias = "variantTitle", Value = "The updated Danish title" } - ] - } + new VariantModel { Culture = "en-US", Name = "Updated English Name" }, + new VariantModel { Culture = "da-DK", Name = "Updated Danish Name" } ], }; @@ -99,30 +91,16 @@ public async Task Will_Fail_Invalid_Variant_Content() var validateContentUpdateModel = new ValidateContentUpdateModel { - InvariantProperties = + Properties = [ - new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" } + new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated English title", Culture = "en-US" }, + new PropertyValueModel { Alias = "variantTitle", Value = null, Culture = "da-DK" } ], Variants = [ - new VariantModel - { - Culture = "en-US", - Name = "Updated English Name", - Properties = - [ - new PropertyValueModel { Alias = "variantTitle", Value = "The updated English title" } - ] - }, - new VariantModel - { - Culture = "da-DK", - Name = "Updated Danish Name", - Properties = - [ - new PropertyValueModel { Alias = "variantTitle", Value = null } - ] - } + new VariantModel { Culture = "en-US", Name = "Updated English Name" }, + new VariantModel { Culture = "da-DK", Name = "Updated Danish Name" } ], }; @@ -142,22 +120,15 @@ public async Task Will_Succeed_For_Invalid_Variant_Content_Without_Access_To_Edi var validateContentUpdateModel = new ValidateContentUpdateModel { - InvariantProperties = + Properties = [ - new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" } + new PropertyValueModel { Alias = "invariantTitle", Value = "The updated invariant title" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The updated English title", Culture = "en-US" }, ], Variants = [ - new VariantModel - { - Culture = "en-US", - Name = "Updated English Name", - Properties = - [ - new PropertyValueModel { Alias = "variantTitle", Value = "The updated English title" } - ] - } - ], + new VariantModel { Culture = "en-US", Name = "Updated English Name" } + ] }; Attempt result = await ContentEditingService.ValidateUpdateAsync(content.Key, validateContentUpdateModel, englishEditor.Key); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.cs index 67daf08ae521..683ee8134bc7 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTests.cs @@ -49,7 +49,7 @@ private async Task CreateTextPageContentTypeAsync() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = rootName + Variants = [new () { Name = rootName }] }; var root = (await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result.Content!; @@ -61,7 +61,7 @@ private async Task CreateTextPageContentTypeAsync() ContentTypeService.Save(contentType); createModel.ParentKey = root.Key; - createModel.InvariantName = childName; + createModel.Variants = [new() { Name = childName }]; var child = (await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey)).Result.Content!; Assert.AreEqual(root.Id, child.ParentId); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTestsBase.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTestsBase.cs index 0936536cce82..001a281a8839 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTestsBase.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEditingServiceTestsBase.cs @@ -117,13 +117,16 @@ protected async Task CreateInvariantContent(params ITemplate[] templat { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Initial Name", + Variants = + [ + new VariantModel { Name = "Initial Name" } + ], TemplateKey = templates.FirstOrDefault()?.Key, - InvariantProperties = new[] - { + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The initial title" }, - new PropertyValueModel { Alias = "text", Value = "The initial text" }, - }, + new PropertyValueModel { Alias = "text", Value = "The initial text" } + ], }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -139,31 +142,17 @@ protected async Task CreateCultureVariantContent() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantProperties = new[] - { + Properties = + [ new PropertyValueModel { Alias = "invariantTitle", Value = "The initial invariant title" }, - }, - Variants = new[] - { - new VariantModel - { - Culture = "en-US", - Name = "Initial English Name", - Properties = new[] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The initial English title" }, - }, - }, - new VariantModel - { - Culture = "da-DK", - Name = "Initial Danish Name", - Properties = new[] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The initial Danish title" }, - }, - }, - }, + new PropertyValueModel { Alias = "variantTitle", Value = "The initial English title", Culture = "en-US" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The initial Danish title", Culture = "da-DK" } + ], + Variants = + [ + new VariantModel { Culture = "en-US", Name = "Initial English Name" }, + new VariantModel { Culture = "da-DK", Name = "Initial Danish Name" } + ] }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -179,40 +168,71 @@ protected async Task CreateSegmentVariantContent() { ContentTypeKey = contentType.Key, ParentKey = Constants.System.RootKey, - InvariantProperties = new[] - { + Properties = + [ new PropertyValueModel { Alias = "invariantTitle", Value = "The initial invariant title" }, - }, - Variants = new[] - { - new VariantModel - { - Segment = null, - Name = "The Name", - Properties = new[] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The initial default title" }, - }, - }, - new VariantModel - { - Segment = "seg-1", - Name = "The Name", - Properties = new[] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The initial seg-1 title" }, - }, - }, - new VariantModel - { - Segment = "seg-2", - Name = "The Name", - Properties = new[] - { - new PropertyValueModel { Alias = "variantTitle", Value = "The initial seg-2 title" }, - }, - }, - }, + new PropertyValueModel { Alias = "variantTitle", Value = "The initial default title" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The initial seg-1 title", Segment = "seg-1" }, + new PropertyValueModel { Alias = "variantTitle", Value = "The initial seg-2 title", Segment = "seg-2" } + ], + Variants = + [ + new VariantModel { Segment = null, Name = "The Name" }, + new VariantModel { Segment = "seg-1", Name = "The Name" }, + new VariantModel { Segment = "seg-2", Name = "The Name" } + ], + }; + + var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); + Assert.IsTrue(result.Success); + return result.Result.Content!; + } + + protected async Task CreateCultureAndSegmentVariantContent(ContentVariation otherTitleVariation) + { + var contentType = await CreateVariantContentType(ContentVariation.CultureAndSegment); + var propertyType = contentType.PropertyTypes.First(pt => pt.Alias == "invariantTitle"); + propertyType.Alias = "otherTitle"; + propertyType.Variations = otherTitleVariation; + ContentTypeService.Save(contentType); + + IEnumerable otherTitleValues = otherTitleVariation switch + { + ContentVariation.Culture => + [ + new PropertyValueModel { Alias = "otherTitle", Value = "The initial other English title", Culture = "en-US" }, + new PropertyValueModel { Alias = "otherTitle", Value = "The initial other Danish title", Culture = "da-DK" }, + ], + ContentVariation.Segment => + [ + new PropertyValueModel { Alias = "otherTitle", Value = "The initial other default title" }, + new PropertyValueModel { Alias = "otherTitle", Value = "The initial other seg-1 title", Segment = "seg-1" }, + new PropertyValueModel { Alias = "otherTitle", Value = "The initial other seg-2 title", Segment = "seg-2" } + ], + _ => throw new ArgumentOutOfRangeException(nameof(otherTitleVariation)) + }; + + var createModel = new ContentCreateModel + { + ContentTypeKey = contentType.Key, + ParentKey = Constants.System.RootKey, + Properties = otherTitleValues.Union([ + new () { Alias = "variantTitle", Value = "The initial title in English", Culture = "en-US" }, + new () { Alias = "variantTitle", Value = "The initial seg-1 title in English", Culture = "en-US", Segment = "seg-1" }, + new () { Alias = "variantTitle", Value = "The initial seg-2 title in English", Culture = "en-US", Segment = "seg-2" }, + new () { Alias = "variantTitle", Value = "The initial title in Danish", Culture = "da-DK" }, + new () { Alias = "variantTitle", Value = "The initial seg-1 title in Danish", Culture = "da-DK", Segment = "seg-1" }, + new () { Alias = "variantTitle", Value = "The initial seg-2 title in Danish", Culture = "da-DK", Segment = "seg-2" } + ]), + Variants = + [ + new VariantModel { Name = "The Name", Culture = "en-US", Segment = null }, + new VariantModel { Name = "The Name", Culture = "en-US", Segment = "seg-1" }, + new VariantModel { Name = "The Name", Culture = "en-US", Segment = "seg-2" }, + new VariantModel { Name = "The Name", Culture = "da-DK", Segment = null }, + new VariantModel { Name = "The Name", Culture = "da-DK", Segment = "seg-1" }, + new VariantModel { Name = "The Name", Culture = "da-DK", Segment = "seg-2" }, + ], }; var result = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentListViewServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentListViewServiceTests.cs index badcd4991706..77c730ae1834 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentListViewServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentListViewServiceTests.cs @@ -66,7 +66,7 @@ public async Task Cannot_Get_List_View_Items_When_Content_Is_Not_Configured_As_L var createModel = new ContentCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Page", + Variants = [new () { Name = "Page" }] }; var createResult = await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -718,7 +718,7 @@ public async Task Cannot_Get_List_View_Items_That_The_User_Does_Not_Have_Access_ var createModel = new ContentCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Page", + Variants = [new () { Name = "Page" }] }; // Content that serves as a start node @@ -857,7 +857,7 @@ private async Task CreateRootContentWithFiveChildrenAndListViewPropert { ContentTypeKey = contentTypeWithListViewPropertyType.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Products", + Variants = [new () { Name = "Products" }] }; var result = await ContentEditingService.CreateAsync(rootContentCreateModel, Constants.Security.SuperUserKey); @@ -869,13 +869,13 @@ private async Task CreateRootContentWithFiveChildrenAndListViewPropert { ContentTypeKey = childContentType.Key, ParentKey = root.Key, - InvariantName = $"Item {i}", + Variants = [new () { Name = $"Item {i}" }], Key = i.ToGuid(), - InvariantProperties = new[] - { + Properties = + [ new PropertyValueModel { Alias = "itemName", Value = $"Item {i}" }, - new PropertyValueModel { Alias = "price", Value = i * 10 }, - }, + new PropertyValueModel { Alias = "price", Value = i * 10 } + ], }; await ContentEditingService.CreateAsync(createModel, Constants.Security.SuperUserKey); @@ -910,7 +910,7 @@ private async Task CreateRootContentWithFiveChildrenAsListViewItems(Gu { ContentTypeKey = contentTypeWithListView.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Products", + Variants = [new () { Name = "Products" }] }; var result = await ContentEditingService.CreateAsync(rootContentCreateModel, Constants.Security.SuperUserKey); @@ -922,7 +922,7 @@ private async Task CreateRootContentWithFiveChildrenAsListViewItems(Gu { ContentTypeKey = childContentType.Key, ParentKey = root.Key, - InvariantName = $"Item {i}", + Variants = [new () { Name = $"Item {i}" }], Key = i.ToGuid(), }; @@ -963,19 +963,18 @@ private async Task CreateVariantRootContentWithFiveChildrenAsListViewI var rootContentCreateModel = new ContentCreateModel { ContentTypeKey = contentTypeWithListView.Key, + Properties = [], Variants = new[] { new VariantModel { Culture = "en-US", Name = "English Page", - Properties = Enumerable.Empty(), }, new VariantModel { Culture = "da-DK", Name = "Danish Page", - Properties = Enumerable.Empty(), }, }, }; @@ -989,19 +988,18 @@ private async Task CreateVariantRootContentWithFiveChildrenAsListViewI { ContentTypeKey = childContentType.Key, ParentKey = root.Key, + Properties = [], Variants = new[] { new VariantModel { Culture = "en-US", Name = $"Child item {i}", - Properties = Enumerable.Empty(), }, new VariantModel { Culture = "da-DK", Name = $"(DA) Child item {5 - i}", - Properties = Enumerable.Empty(), }, }, }; diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentValidationServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentValidationServiceTests.cs index 413b30010ab0..d991c99ffb8a 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentValidationServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentValidationServiceTests.cs @@ -32,8 +32,8 @@ public async Task Can_Validate_Block_List_Nested_In_Block_List() new ContentCreateModel { ContentTypeKey = setup.DocumentType.Key, - InvariantName = "Test Document", - InvariantProperties = new[] + Variants = [new () { Name = "Test Document" }], + Properties = new[] { new PropertyValueModel { @@ -175,8 +175,8 @@ public async Task Can_Validate_RegEx_For_Simple_Property_On_Document(bool valid) new ContentCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Test Document", - InvariantProperties = new[] + Variants = [new () { Name = "Test Document" }], + Properties = new[] { new PropertyValueModel { @@ -213,8 +213,8 @@ public async Task Can_Validate_Mandatory_For_Simple_Property_On_Document(bool va new ContentCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Test Document", - InvariantProperties = new[] + Variants = [new () { Name = "Test Document" }], + Properties = new[] { new PropertyValueModel { @@ -250,8 +250,8 @@ public async Task Can_Validate_Mandatory_For_Property_Not_Present_In_Document() new ContentCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Test Document", - InvariantProperties = new[] + Variants = [new () { Name = "Test Document" }], + Properties = new[] { new PropertyValueModel { @@ -275,8 +275,8 @@ public async Task Uses_Localizaton_Keys_For_Validation_Error_Messages() new ContentCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Test Document", - InvariantProperties = new[] + Variants = [new () { Name = "Test Document" }], + Properties = new[] { new PropertyValueModel { @@ -310,8 +310,8 @@ public async Task Custom_Validation_Error_Messages_Replaces_Localizaton_Keys() new ContentCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Test Document", - InvariantProperties = new[] + Variants = [new () { Name = "Test Document" }], + Properties = new[] { new PropertyValueModel { @@ -349,18 +349,14 @@ public async Task Can_Validate_Culture_Code(string cultureCode, bool expectedRes var result = await ContentValidationService.ValidateCulturesAsync( new ContentCreateModel { - Variants = new [] - { - new VariantModel - { - Culture = cultureCode, - Name = "Whatever", - Properties = new [] - { - new PropertyValueModel { Alias = "title", Value = "Something" } - } - } - } + Properties = + [ + new PropertyValueModel { Alias = "title", Value = "Something", Culture = cultureCode } + ], + Variants = + [ + new VariantModel { Culture = cultureCode, Name = "Whatever" } + ] }); Assert.AreEqual(expectedResult, result); @@ -375,31 +371,24 @@ public async Task Can_Validate_For_All_Languages() new ContentCreateModel { ContentTypeKey = contentType.Key, - Variants = [ + Properties = + [ new() { - Name = "Test Document (EN)", - Culture = "en-US", - Properties = [ - new() - { - Alias = "title", - Value = "Invalid value in English", - } - ] + Alias = "title", + Value = "Invalid value in English", + Culture = "en-US" }, new() { - Name = "Test Document (DA)", - Culture = "da-DK", - Properties = [ - new() - { - Alias = "title", - Value = "Invalid value in Danish", - } - ] + Alias = "title", + Value = "Invalid value in Danish", + Culture = "da-DK" } + ], + Variants = [ + new() { Name = "Test Document (EN)", Culture = "en-US" }, + new() { Name = "Test Document (DA)", Culture = "da-DK" } ] }, contentType); @@ -419,31 +408,24 @@ public async Task Can_Validate_For_Specific_Language(string culture) new ContentCreateModel { ContentTypeKey = contentType.Key, - Variants = [ + Properties = + [ new() { - Name = "Test Document (EN)", - Culture = "en-US", - Properties = [ - new() - { - Alias = "title", - Value = "Invalid value in English", - } - ] + Alias = "title", + Value = "Invalid value in English", + Culture = "en-US" }, new() { - Name = "Test Document (DA)", - Culture = "da-DK", - Properties = [ - new() - { - Alias = "title", - Value = "Invalid value in Danish", - } - ] + Alias = "title", + Value = "Invalid value in Danish", + Culture = "da-DK" } + ], + Variants = [ + new() { Name = "Test Document (EN)", Culture = "en-US" }, + new() { Name = "Test Document (DA)", Culture = "da-DK" } ] }, contentType, @@ -453,6 +435,98 @@ public async Task Can_Validate_For_Specific_Language(string culture) Assert.IsNotNull(validationResult.ValidationErrors.SingleOrDefault(r => r.Alias == "title" && r.Culture == culture && r.JsonPath == string.Empty)); } + [Test] + public async Task Can_Validate_All_Segments_Including_Default() + { + var contentType = await SetupSegmentTest(ContentVariation.Segment); + + var validationResult = await ContentValidationService.ValidatePropertiesAsync( + new ContentCreateModel + { + ContentTypeKey = contentType.Key, + Properties = + [ + new() + { + Alias = "title", + Value = "Invalid default value", + Segment = null + }, + new() + { + Alias = "title", + Value = "Invalid seg-1 value", + Segment = "seg-1" + }, + new() + { + Alias = "title", + Value = "Invalid seg-2 value", + Segment = "seg-2" + } + ], + Variants = [ + new() { Name = "Test Document" }, + new() { Name = "Test Document", Segment = "seg-1" }, + new() { Name = "Test Document", Segment = "seg-2" } + ] + }, + contentType); + + Assert.AreEqual(3, validationResult.ValidationErrors.Count()); + Assert.Multiple(() => + { + Assert.IsNotNull(validationResult.ValidationErrors.SingleOrDefault(r => r.Alias == "title" && r.Segment == null && r.JsonPath == string.Empty)); + Assert.IsNotNull(validationResult.ValidationErrors.SingleOrDefault(r => r.Alias == "title" && r.Segment == "seg-1" && r.JsonPath == string.Empty)); + Assert.IsNotNull(validationResult.ValidationErrors.SingleOrDefault(r => r.Alias == "title" && r.Segment == "seg-2" && r.JsonPath == string.Empty)); + }); + } + + [Test] + public async Task Can_Validate_Single_Invalid_Segment() + { + var contentType = await SetupSegmentTest(ContentVariation.Segment); + + var validationResult = await ContentValidationService.ValidatePropertiesAsync( + new ContentCreateModel + { + ContentTypeKey = contentType.Key, + Properties = + [ + new() + { + Alias = "title", + Value = "Valid default value", + Segment = null + }, + new() + { + Alias = "title", + Value = "Invalid seg-1 value", + Segment = "seg-1" + }, + new() + { + Alias = "title", + Value = "Valid seg-2 value", + Segment = "seg-2" + } + ], + Variants = [ + new() { Name = "Test Document" }, + new() { Name = "Test Document", Segment = "seg-1" }, + new() { Name = "Test Document", Segment = "seg-2" } + ] + }, + contentType); + + Assert.AreEqual(1, validationResult.ValidationErrors.Count()); + Assert.Multiple(() => + { + Assert.IsNotNull(validationResult.ValidationErrors.SingleOrDefault(r => r.Alias == "title" && r.Segment == "seg-1" && r.JsonPath == string.Empty)); + }); + } + private async Task<(IContentType DocumentType, IContentType ElementType)> SetupBlockListTest() { var propertyEditorCollection = GetRequiredService(); @@ -556,4 +630,22 @@ private async Task SetupLanguageTest() return contentType; } + + private async Task SetupSegmentTest(ContentVariation variation) + { + var language = new LanguageBuilder() + .WithCultureInfo("da-DK") + .Build(); + await LanguageService.CreateAsync(language, Constants.Security.SuperUserKey); + + var contentType = ContentTypeBuilder.CreateSimpleContentType("umbMandatory", "Mandatory Doc Type"); + contentType.Variations = variation; + var titlePropertyType = contentType.PropertyTypes.First(pt => pt.Alias == "title"); + titlePropertyType.Variations = variation; + titlePropertyType.ValidationRegExp = "^Valid.*$"; + contentType.AllowedAsRoot = true; + await ContentTypeService.CreateAsync(contentType, Constants.Security.SuperUserKey); + + return contentType; + } } diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/MediaListViewServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/MediaListViewServiceTests.cs index c5c1b79d7a8a..8e31abf897d8 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/MediaListViewServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/MediaListViewServiceTests.cs @@ -222,7 +222,7 @@ private async Task CreateRootMediaWithFiveChildrenAsListViewItems(Guid? { ContentTypeKey = mediaTypeWithListView.Key, ParentKey = Constants.System.RootKey, - InvariantName = "Album", + Variants = [new () { Name = "Album" }] }; var result = await MediaEditingService.CreateAsync(rootContentCreateModel, Constants.Security.SuperUserKey); @@ -234,7 +234,7 @@ private async Task CreateRootMediaWithFiveChildrenAsListViewItems(Guid? { ContentTypeKey = childImageMediaType.Key, ParentKey = root.Key, - InvariantName = $"Image {i}", + Variants = [new () { Name = $"Image {i}" }], Key = i.ToGuid(), }; diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/MemberEditingServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/MemberEditingServiceTests.cs index 031964a96abd..6f6b79e649cc 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/MemberEditingServiceTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/MemberEditingServiceTests.cs @@ -77,12 +77,12 @@ public async Task Can_Update_Member() Email = "test-updated@test.com", Username = "test-updated", IsApproved = false, - InvariantName = "T. Est Updated", - InvariantProperties = new[] - { + Variants = [new VariantModel { Name = "T. Est Updated" }], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The updated title value" }, new PropertyValueModel { Alias = "author", Value = "The updated author value" } - } + ] }; var result = await MemberEditingService.UpdateAsync(member.Key, updateModel, SuperUser()); @@ -112,7 +112,7 @@ public async Task Can_Change_Member_Password() Email = member.Email, Username = member.Username, IsApproved = true, - InvariantName = member.Name, + Variants = [new VariantModel { Name = member.Name }], NewPassword = "NewSuperSecret123" }; @@ -140,7 +140,7 @@ public async Task Can_Change_Member_Roles() Email = member.Email, Username = member.Username, IsApproved = true, - InvariantName = member.Name, + Variants = [new VariantModel { Name = member.Name }], Roles = groups.Select(x => x.Key), }; @@ -193,12 +193,12 @@ public async Task Can_Create_With_Property_Validation(bool addValidProperties) Password = "SuperSecret123", IsApproved = true, ContentTypeKey = memberType.Key, - InvariantName = "T. Est", - InvariantProperties = new[] - { + Variants = [new VariantModel { Name = "T. Est" }], + Properties = + [ new PropertyValueModel { Alias = "title", Value = titleValue }, new PropertyValueModel { Alias = "author", Value = authorValue } - } + ] }; var result = await MemberEditingService.CreateAsync(createModel, SuperUser()); @@ -240,12 +240,12 @@ public async Task Can_Update_With_Property_Validation(bool addValidProperties) Email = member.Email, Username = member.Username, IsApproved = true, - InvariantName = member.Name, - InvariantProperties = new[] - { + Variants = [new VariantModel { Name = member.Name }], + Properties = + [ new PropertyValueModel { Alias = "title", Value = titleValue }, new PropertyValueModel { Alias = "author", Value = authorValue } - } + ] }; var result = await MemberEditingService.UpdateAsync(member.Key, updateModel, SuperUser()); @@ -283,12 +283,12 @@ public async Task Cannot_Update_Sensitive_Properties_Without_Access(bool useSupe Email = "test-updated@test.com", Username = "test-updated", IsApproved = member.IsApproved, - InvariantName = "T. Est Updated", - InvariantProperties = new[] - { + Variants = [new VariantModel { Name = "T. Est Updated" }], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The updated title value" }, new PropertyValueModel { Alias = "author", Value = "The updated author value" } - } + ] }; var result = await MemberEditingService.UpdateAsync(member.Key, updateModel, useSuperUser ? SuperUser() : user); @@ -341,11 +341,11 @@ public async Task Sensitive_Properties_Are_Retained_When_Updating_Without_Access { Email = "test-updated@test.com", Username = "test-updated", - InvariantName = "T. Est Updated", - InvariantProperties = new[] - { + Variants = [new VariantModel { Name = "T. Est Updated" }], + Properties = + [ new PropertyValueModel { Alias = "author", Value = "The updated author value" } - } + ] }; var result = await MemberEditingService.UpdateAsync(member.Key, updateModel, user); @@ -387,12 +387,12 @@ private async Task CreateMemberAsync(Guid? key = null, bool titleIsSens IsApproved = true, ContentTypeKey = memberType.Key, Roles = new [] { group.Key }, - InvariantName = "T. Est", - InvariantProperties = new[] - { + Variants = [new VariantModel { Name = "T. Est" }], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The title value" }, new PropertyValueModel { Alias = "author", Value = "The author value" } - } + ] }; var result = await MemberEditingService.CreateAsync(createModel, SuperUser()); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCachePropertyTest.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCachePropertyTest.cs index 746da766bf9e..dc5c7c99feec 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCachePropertyTest.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCachePropertyTest.cs @@ -76,12 +76,12 @@ public async Task Can_Get_Value_From_Updated_ContentPicker() // Update content var updateModel = new ContentUpdateModel { - InvariantName = "Root Create", - InvariantProperties = new[] - { + Variants = [new() { Name = "Root Create" }], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "Updated title" }, new PropertyValueModel { Alias = "bodyText", Value = "The body text" } - }, + ], }; var updateResult = await ContentEditingService.UpdateAsync(textPage.Key, updateModel, Constants.Security.SuperUserKey); diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTemplateTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTemplateTests.cs index 7c5f1950bf4d..50c0d94a6b17 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTemplateTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTemplateTests.cs @@ -36,7 +36,7 @@ public async Task Can_Get_Document_After_Removing_Template() var updateModel = new ContentUpdateModel(); { updateModel.TemplateKey = null; - updateModel.InvariantName = textPageBefore.Name; + updateModel.Variants = [new() { Name = textPageBefore.Name }]; } // Act diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTests.cs index f0c335b577ad..0c4207331a0e 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheTests.cs @@ -111,11 +111,10 @@ public async Task Can_Get_Draft_Of_Published_Content_By_Key() public async Task Can_Get_Updated_Draft_Content_By_Id() { // Arrange - Textpage.InvariantName = NewName; + Textpage.Variants = [new() { Name = NewName }]; ContentUpdateModel updateModel = new ContentUpdateModel { - InvariantName = NewName, - InvariantProperties = Textpage.InvariantProperties, + Properties = Textpage.Properties, Variants = Textpage.Variants, TemplateKey = Textpage.TemplateKey, }; @@ -132,11 +131,10 @@ public async Task Can_Get_Updated_Draft_Content_By_Id() public async Task Can_Get_Updated_Draft_Content_By_Key() { // Arrange - Textpage.InvariantName = NewName; + Textpage.Variants = [new() { Name = NewName }]; ContentUpdateModel updateModel = new ContentUpdateModel { - InvariantName = NewName, - InvariantProperties = Textpage.InvariantProperties, + Properties = Textpage.Properties, Variants = Textpage.Variants, TemplateKey = Textpage.TemplateKey, }; @@ -156,11 +154,10 @@ public async Task Can_Get_Updated_Draft_Content_By_Key() public async Task Can_Get_Updated_Draft_Published_Content_By_Id(bool preview, bool result) { // Arrange - PublishedTextPage.InvariantName = NewName; + PublishedTextPage.Variants = [new() { Name = NewName }]; ContentUpdateModel updateModel = new ContentUpdateModel { - InvariantName = NewName, - InvariantProperties = PublishedTextPage.InvariantProperties, + Properties = PublishedTextPage.Properties, Variants = PublishedTextPage.Variants, TemplateKey = PublishedTextPage.TemplateKey, }; @@ -180,11 +177,10 @@ public async Task Can_Get_Updated_Draft_Published_Content_By_Id(bool preview, bo public async Task Can_Get_Updated_Draft_Published_Content_By_Key(bool preview, bool result) { // Arrange - PublishedTextPage.InvariantName = NewName; + PublishedTextPage.Variants = [new() { Name = NewName }];; ContentUpdateModel updateModel = new ContentUpdateModel { - InvariantName = NewName, - InvariantProperties = PublishedTextPage.InvariantProperties, + Properties = PublishedTextPage.Properties, Variants = PublishedTextPage.Variants, TemplateKey = PublishedTextPage.TemplateKey, }; @@ -201,7 +197,7 @@ public async Task Can_Get_Updated_Draft_Published_Content_By_Key(bool preview, b public async Task Can_Get_Draft_Content_Property_By_Id() { // Arrange - var titleValue = Textpage.InvariantProperties.First(x => x.Alias == "title").Value; + var titleValue = Textpage.Properties.First(x => x.Alias == "title").Value; // Act var textPage = await PublishedContentHybridCache.GetByIdAsync(TextpageId, true); @@ -214,7 +210,7 @@ public async Task Can_Get_Draft_Content_Property_By_Id() public async Task Can_Get_Draft_Content_Property_By_Key() { // Arrange - var titleValue = Textpage.InvariantProperties.First(x => x.Alias == "title").Value; + var titleValue = Textpage.Properties.First(x => x.Alias == "title").Value; // Act var textPage = await PublishedContentHybridCache.GetByIdAsync(Textpage.Key.Value, true); @@ -227,7 +223,7 @@ public async Task Can_Get_Draft_Content_Property_By_Key() public async Task Can_Get_Published_Content_Property_By_Id() { // Arrange - var titleValue = PublishedTextPage.InvariantProperties.First(x => x.Alias == "title").Value; + var titleValue = PublishedTextPage.Properties.First(x => x.Alias == "title").Value; // Act var textPage = await PublishedContentHybridCache.GetByIdAsync(PublishedTextPageId, true); @@ -240,7 +236,7 @@ public async Task Can_Get_Published_Content_Property_By_Id() public async Task Can_Get_Published_Content_Property_By_Key() { // Arrange - var titleValue = PublishedTextPage.InvariantProperties.First(x => x.Alias == "title").Value; + var titleValue = PublishedTextPage.Properties.First(x => x.Alias == "title").Value; // Act var textPage = await PublishedContentHybridCache.GetByIdAsync(PublishedTextPage.Key.Value, true); @@ -253,7 +249,7 @@ public async Task Can_Get_Published_Content_Property_By_Key() public async Task Can_Get_Draft_Of_Published_Content_Property_By_Id() { // Arrange - var titleValue = PublishedTextPage.InvariantProperties.First(x => x.Alias == "title").Value; + var titleValue = PublishedTextPage.Properties.First(x => x.Alias == "title").Value; // Act var textPage = await PublishedContentHybridCache.GetByIdAsync(PublishedTextPageId, true); @@ -266,7 +262,7 @@ public async Task Can_Get_Draft_Of_Published_Content_Property_By_Id() public async Task Can_Get_Draft_Of_Published_Content_Property_By_Key() { // Arrange - var titleValue = PublishedTextPage.InvariantProperties.First(x => x.Alias == "title").Value; + var titleValue = PublishedTextPage.Properties.First(x => x.Alias == "title").Value; // Act var textPage = await PublishedContentHybridCache.GetByIdAsync(PublishedTextPage.Key.Value, true); @@ -279,11 +275,10 @@ public async Task Can_Get_Draft_Of_Published_Content_Property_By_Key() public async Task Can_Get_Updated_Draft_Content_Property_By_Id() { // Arrange - Textpage.InvariantProperties.First(x => x.Alias == "title").Value = NewTitle; + Textpage.Properties.First(x => x.Alias == "title").Value = NewTitle; ContentUpdateModel updateModel = new ContentUpdateModel { - InvariantName = Textpage.InvariantName, - InvariantProperties = Textpage.InvariantProperties, + Properties = Textpage.Properties, Variants = Textpage.Variants, TemplateKey = Textpage.TemplateKey, }; @@ -300,11 +295,10 @@ public async Task Can_Get_Updated_Draft_Content_Property_By_Id() public async Task Can_Get_Updated_Draft_Content_Property_By_Key() { // Arrange - Textpage.InvariantProperties.First(x => x.Alias == "title").Value = NewTitle; + Textpage.Properties.First(x => x.Alias == "title").Value = NewTitle; ContentUpdateModel updateModel = new ContentUpdateModel { - InvariantName = Textpage.InvariantName, - InvariantProperties = Textpage.InvariantProperties, + Properties = Textpage.Properties, Variants = Textpage.Variants, TemplateKey = Textpage.TemplateKey, }; @@ -321,11 +315,10 @@ public async Task Can_Get_Updated_Draft_Content_Property_By_Key() public async Task Can_Get_Updated_Published_Content_Property_By_Id() { // Arrange - PublishedTextPage.InvariantProperties.First(x => x.Alias == "title").Value = NewTitle; + PublishedTextPage.Properties.First(x => x.Alias == "title").Value = NewTitle; ContentUpdateModel updateModel = new ContentUpdateModel { - InvariantName = PublishedTextPage.InvariantName, - InvariantProperties = PublishedTextPage.InvariantProperties, + Properties = PublishedTextPage.Properties, Variants = PublishedTextPage.Variants, TemplateKey = PublishedTextPage.TemplateKey, }; @@ -343,11 +336,10 @@ public async Task Can_Get_Updated_Published_Content_Property_By_Id() public async Task Can_Get_Updated_Published_Content_Property_By_Key() { // Arrange - PublishedTextPage.InvariantProperties.First(x => x.Alias == "title").Value = NewTitle; + PublishedTextPage.Properties.First(x => x.Alias == "title").Value = NewTitle; ContentUpdateModel updateModel = new ContentUpdateModel { - InvariantName = PublishedTextPage.InvariantName, - InvariantProperties = PublishedTextPage.InvariantProperties, + Properties = PublishedTextPage.Properties, Variants = PublishedTextPage.Variants, TemplateKey = PublishedTextPage.TemplateKey, }; @@ -367,11 +359,10 @@ public async Task Can_Get_Updated_Published_Content_Property_By_Key() public async Task Can_Get_Updated_Draft_Of_Published_Content_Property_By_Id(bool preview, string titleName) { // Arrange - PublishedTextPage.InvariantProperties.First(x => x.Alias == "title").Value = NewTitle; + PublishedTextPage.Properties.First(x => x.Alias == "title").Value = NewTitle; ContentUpdateModel updateModel = new ContentUpdateModel { - InvariantName = PublishedTextPage.InvariantName, - InvariantProperties = PublishedTextPage.InvariantProperties, + Properties = PublishedTextPage.Properties, Variants = PublishedTextPage.Variants, TemplateKey = PublishedTextPage.TemplateKey, }; @@ -390,11 +381,10 @@ public async Task Can_Get_Updated_Draft_Of_Published_Content_Property_By_Id(bool public async Task Can_Get_Updated_Draft_Of_Published_Content_Property_By_Key(bool preview, string titleName) { // Arrange - PublishedTextPage.InvariantProperties.First(x => x.Alias == "title").Value = titleName; + PublishedTextPage.Properties.First(x => x.Alias == "title").Value = titleName; ContentUpdateModel updateModel = new ContentUpdateModel { - InvariantName = PublishedTextPage.InvariantName, - InvariantProperties = PublishedTextPage.InvariantProperties, + Properties = PublishedTextPage.Properties, Variants = PublishedTextPage.Variants, TemplateKey = PublishedTextPage.TemplateKey, }; @@ -477,10 +467,10 @@ private void AssertTextPage(IPublishedContent textPage) Assert.IsNotNull(textPage); Assert.AreEqual(Textpage.Key, textPage.Key); Assert.AreEqual(Textpage.ContentTypeKey, textPage.ContentType.Key); - Assert.AreEqual(Textpage.InvariantName, textPage.Name); + Assert.AreEqual(Textpage.Variants.Single().Name, textPage.Name); }); - AssertProperties(Textpage.InvariantProperties, textPage.Properties); + AssertProperties(Textpage.Properties, textPage.Properties); } private void AssertPublishedTextPage(IPublishedContent textPage) @@ -490,10 +480,10 @@ private void AssertPublishedTextPage(IPublishedContent textPage) Assert.IsNotNull(textPage); Assert.AreEqual(PublishedTextPage.Key, textPage.Key); Assert.AreEqual(PublishedTextPage.ContentTypeKey, textPage.ContentType.Key); - Assert.AreEqual(PublishedTextPage.InvariantName, textPage.Name); + Assert.AreEqual(PublishedTextPage.Variants.Single().Name, textPage.Name); }); - AssertProperties(PublishedTextPage.InvariantProperties, textPage.Properties); + AssertProperties(PublishedTextPage.Properties, textPage.Properties); } private void AssertProperties(IEnumerable propertyCollection, IEnumerable publishedProperties) diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheVariantsTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheVariantsTests.cs index 40fa91afe16c..4e8932b6adce 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheVariantsTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/DocumentHybridCacheVariantsTests.cs @@ -59,27 +59,16 @@ public async Task Can_Set_Invariant_Title() var updateModel = new ContentUpdateModel { - InvariantProperties = - new[] { new PropertyValueModel { Alias = _invariantTitleAlias, Value = updatedInvariantTitle } }, - Variants = new[] - { - new VariantModel - { - Culture = _englishIsoCode, - Name = "Updated English Name", - Properties = - new[] { new PropertyValueModel { Alias = _variantTitleAlias, Value = updatedVariantTitle } }, - }, - new VariantModel - { - Culture = _danishIsoCode, - Name = "Updated Danish Name", - Properties = new[] - { - new PropertyValueModel { Alias = _variantTitleAlias, Value = updatedVariantTitle }, - }, - }, - }, + Properties = [ + new PropertyValueModel { Alias = _invariantTitleAlias, Value = updatedInvariantTitle }, + new PropertyValueModel { Alias = _variantTitleAlias, Value = updatedVariantTitle, Culture = _englishIsoCode }, + new PropertyValueModel { Alias = _variantTitleAlias, Value = updatedVariantTitle, Culture = _danishIsoCode } + ], + Variants = + [ + new VariantModel { Culture = _englishIsoCode, Name = "Updated English Name" }, + new VariantModel { Culture = _danishIsoCode, Name = "Updated Danish Name" } + ], }; var result = @@ -106,20 +95,15 @@ public async Task Can_Set_Invariant_Title_On_One_Culture() var updateModel = new ContentUpdateModel { - InvariantProperties = - new[] { new PropertyValueModel { Alias = _invariantTitleAlias, Value = updatedInvariantTitle } }, - Variants = new[] - { - new VariantModel - { - Culture = _englishIsoCode, - Name = "Updated English Name", - Properties = new[] - { - new PropertyValueModel { Alias = _variantTitleAlias, Value = updatedVariantTitle }, - }, - }, - }, + Properties = + [ + new PropertyValueModel { Alias = _invariantTitleAlias, Value = updatedInvariantTitle }, + new PropertyValueModel { Alias = _variantTitleAlias, Value = updatedVariantTitle, Culture = _englishIsoCode } + ], + Variants = + [ + new VariantModel { Culture = _englishIsoCode, Name = "Updated English Name" } + ], }; var result = diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheTests.cs index 692904fb527f..53a3d9446a29 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MediaHybridCacheTests.cs @@ -128,9 +128,8 @@ public async Task Can_Get_Updated_Media_By_Id() var mediaUpdateModel = new MediaUpdateModel { - InvariantName = newName, - InvariantProperties = SubImage.InvariantProperties, - Variants = SubImage.Variants, + Properties = SubImage.Properties, + Variants = [new VariantModel { Name = newName }] }; // Act @@ -152,9 +151,8 @@ public async Task Can_Get_Updated_Media_By_Key() var mediaUpdateModel = new MediaUpdateModel { - InvariantName = newName, - InvariantProperties = SubImage.InvariantProperties, - Variants = SubImage.Variants, + Properties = SubImage.Properties, + Variants = [new VariantModel { Name = newName }] }; // Act diff --git a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MemberHybridCacheTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MemberHybridCacheTests.cs index f3754bb5fd52..1547d64b76db 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MemberHybridCacheTests.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.PublishedCache.HybridCache/MemberHybridCacheTests.cs @@ -62,12 +62,12 @@ private async Task CreateMemberAsync(Guid? key = null, bool titleIsSens IsApproved = true, ContentTypeKey = memberType.Key, Roles = new [] { group.Key }, - InvariantName = "T. Est", - InvariantProperties = new[] - { + Variants = [new () { Name = "T. Est" }], + Properties = + [ new PropertyValueModel { Alias = "title", Value = "The title value" }, new PropertyValueModel { Alias = "author", Value = "The author value" } - } + ] }; var result = await MemberEditingService.CreateAsync(createModel, SuperUser());