diff --git a/src/Umbraco.Cms.Api.Management/Factories/ContentEditingPresentationFactory.cs b/src/Umbraco.Cms.Api.Management/Factories/ContentEditingPresentationFactory.cs index dcbf04e03a..eada525749 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 496bc893f3..305d50688a 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 18e874f281..2afa160418 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 e80818fe18..1249b5630d 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 d10fa076b0..9dd1afe0c1 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 ce6b02c6ae..7af5171bc9 100644 --- a/src/Umbraco.Core/Services/ContentBlueprintEditingService.cs +++ b/src/Umbraco.Core/Services/ContentBlueprintEditingService.cs @@ -86,7 +86,7 @@ internal sealed class ContentBlueprintEditingService 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 @@ internal sealed class ContentBlueprintEditingService 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 @@ internal sealed class ContentBlueprintEditingService 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 cb1a2f8ee2..2f746d9a6f 100644 --- a/src/Umbraco.Core/Services/ContentEditingServiceBase.cs +++ b/src/Umbraco.Core/Services/ContentEditingServiceBase.cs @@ -318,7 +318,7 @@ internal abstract class ContentEditingServiceBase 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 @@ internal abstract class ContentEditingServiceBase 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 @@ internal abstract class ContentEditingServiceBase 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 @@ internal abstract class ContentEditingServiceBase 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 @@ internal abstract class ContentEditingServiceBase 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 5f72c36863..98505483a1 100644 --- a/src/Umbraco.Core/Services/ContentPublishingService.cs +++ b/src/Umbraco.Core/Services/ContentPublishingService.cs @@ -238,28 +238,33 @@ internal sealed class ContentPublishingService : IContentPublishingService private 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 03d2590f65..37b32847ad 100644 --- a/src/Umbraco.Core/Services/ContentValidationServiceBase.cs +++ b/src/Umbraco.Core/Services/ContentValidationServiceBase.cs @@ -31,9 +31,17 @@ internal abstract class ContentValidationServiceBase 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 @@ internal abstract class ContentValidationServiceBase } // 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 @@ internal abstract class ContentValidationServiceBase 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 variantPropertyTypes) + 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 cultureAndSegmentVariantPropertyTypes) { foreach (var culture in cultures) { @@ -76,10 +116,8 @@ internal abstract class ContentValidationServiceBase }; 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 9e44c9bb16..720ad80d62 100644 --- a/src/Umbraco.Core/Services/MemberContentEditingService.cs +++ b/src/Umbraco.Core/Services/MemberContentEditingService.cs @@ -123,8 +123,7 @@ internal sealed class MemberContentEditingService 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 a044569d22..974a70254f 100644 --- a/src/Umbraco.Infrastructure/Services/MemberEditingService.cs +++ b/src/Umbraco.Infrastructure/Services/MemberEditingService.cs @@ -77,12 +77,16 @@ internal sealed class MemberEditingService : IMemberEditingService 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 @@ internal sealed class MemberEditingService : IMemberEditingService 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 617ebdc3a6..1341d45f1c 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 abstract class ContentEditingBaseBuilder : BuilderBase 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 ee5e2fbb6d..79776b0fe6 100644 --- a/tests/Umbraco.Tests.Common/Builders/ContentEditingPropertyValueBuilder.cs +++ b/tests/Umbraco.Tests.Common/Builders/ContentEditingPropertyValueBuilder.cs @@ -4,10 +4,11 @@ using Umbraco.Cms.Tests.Common.Builders.Interfaces; 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 @@ public class ContentEditingPropertyValueBuilder(TParent parentBuilder) 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 797b46b8ac..0fa0cb3e89 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 class ContentEditingVariantBuilder(TParent parentBuilder) 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 25873a8dca..f6dbd26463 100644 --- a/tests/Umbraco.Tests.Common/TestHelpers/DocumentUpdateHelper.cs +++ b/tests/Umbraco.Tests.Common/TestHelpers/DocumentUpdateHelper.cs @@ -17,10 +17,11 @@ public static class DocumentUpdateHelper { 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 class DocumentUpdateHelper { 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 b49d00cac4..b41ef5cbc8 100644 --- a/tests/Umbraco.Tests.Integration/ManagementApi/Policies/UpdateDocumentTests.cs +++ b/tests/Umbraco.Tests.Integration/ManagementApi/Policies/UpdateDocumentTests.cs @@ -83,7 +83,7 @@ internal sealed class UpdateDocumentTests : ManagementApiTest(), + 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 @@ public partial class ContentPublishingServiceTests : UmbracoIntegrationTestWithC { 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 c16f5b4fa2..394722f3c3 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 @@ internal sealed partial class DocumentNavigationServiceTests 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 93836955a9..fb79c53e3b 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 @@ internal abstract class DocumentNavigationServiceTestsBase : UmbracoIntegrationT { 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 8bed77aaa3..bc21bc29b6 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 @@ internal sealed class MediaEditingServiceTests : UmbracoIntegrationTest { 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 875f90d495..4339a944f6 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 @@ internal sealed partial class MediaNavigationServiceTests 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 e1e1a16280..f5daa6fd02 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 @@ internal abstract class MediaNavigationServiceTestsBase : UmbracoIntegrationTest { 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 c6f2dff383..5cf95b6046 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 ea2e680293..963c7dd76f 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 @@ internal partial class BlockListElementLevelVariationTests 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 6f92b14e16..fa4a742d67 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 partial class ContentBlueprintEditingServiceTests 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 partial class ContentBlueprintEditingServiceTests { 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 partial class ContentBlueprintEditingServiceTests 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 partial class ContentBlueprintEditingServiceTests { 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 partial class ContentBlueprintEditingServiceTests { 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 partial class ContentBlueprintEditingServiceTests { 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 partial class ContentBlueprintEditingServiceTests { 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 partial class ContentBlueprintEditingServiceTests { 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 partial class ContentBlueprintEditingServiceTests { 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 partial class ContentBlueprintEditingServiceTests 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 d3a99091ed..92f59650b7 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 partial class ContentBlueprintEditingServiceTests { 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 eb0190b83a..7cdfdf56e8 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 partial class ContentBlueprintEditingServiceTests 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 41692e0ea9..5db71e8baa 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 partial class ContentBlueprintEditingServiceTests 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 partial class ContentBlueprintEditingServiceTests 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 partial class ContentBlueprintEditingServiceTests { 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 partial class ContentBlueprintEditingServiceTests // 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 ef559773cd..c15e619409 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 @@ public partial class ContentBlueprintEditingServiceTests : ContentEditingService { 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 @@ public partial class ContentBlueprintEditingServiceTests : ContentEditingService { 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 @@ public partial class ContentBlueprintEditingServiceTests : ContentEditingService 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 @@ public partial class ContentBlueprintEditingServiceTests : ContentEditingService { 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 104fc7ce3c..7d0a12110a 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests { 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 partial class ContentEditingServiceTests { 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 partial class ContentEditingServiceTests { 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 partial class ContentEditingServiceTests { 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 partial class ContentEditingServiceTests { 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests { 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 partial class ContentEditingServiceTests { 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 partial class ContentEditingServiceTests { 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 partial class ContentEditingServiceTests { 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 @@ public partial class ContentEditingServiceTests } [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 partial class ContentEditingServiceTests { 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 partial class ContentEditingServiceTests { 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 @@ public partial class ContentEditingServiceTests } } + [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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests { 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 partial class ContentEditingServiceTests { 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests { 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 partial class ContentEditingServiceTests { 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 fac576544c..6699361ae7 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 partial class ContentEditingServiceTests 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 @@ public partial class ContentEditingServiceTests 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 @@ public partial class ContentEditingServiceTests { 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 4ad29923b5..a834b5f086 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests 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 @@ public partial class ContentEditingServiceTests } [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 @@ public partial class ContentEditingServiceTests } } + [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 partial class ContentEditingServiceTests var updateModel = new ContentUpdateModel { - InvariantName = "Updated Name", + Variants = + [ + new VariantModel { Name = "Updated Name" } + ], TemplateKey = templateTwo.Key }; @@ -203,7 +289,10 @@ public partial class ContentEditingServiceTests var updateModel = new ContentUpdateModel { - InvariantName = "Updated Name", + Variants = + [ + new VariantModel { Name = "Updated Name" } + ], TemplateKey = null }; @@ -228,8 +317,11 @@ public partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests } [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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests 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 13b76aff83..26ddddc089 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests 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 partial class ContentEditingServiceTests 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 67daf08ae5..683ee8134b 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 @@ public partial class ContentEditingServiceTests : ContentEditingServiceTestsBase { 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 @@ public partial class ContentEditingServiceTests : ContentEditingServiceTestsBase 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 0936536cce..001a281a88 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 @@ public abstract class ContentEditingServiceTestsBase : UmbracoIntegrationTestWit { 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 @@ public abstract class ContentEditingServiceTestsBase : UmbracoIntegrationTestWit { 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 @@ public abstract class ContentEditingServiceTestsBase : UmbracoIntegrationTestWit { 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 badcd49917..77c730ae18 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 @@ internal sealed class ContentListViewServiceTests : ContentListViewServiceTestsB 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 @@ internal sealed class ContentListViewServiceTests : ContentListViewServiceTestsB var createModel = new ContentCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Page", + Variants = [new () { Name = "Page" }] }; // Content that serves as a start node @@ -857,7 +857,7 @@ internal sealed class ContentListViewServiceTests : ContentListViewServiceTestsB { 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 @@ internal sealed class ContentListViewServiceTests : ContentListViewServiceTestsB { 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 @@ internal sealed class ContentListViewServiceTests : ContentListViewServiceTestsB { 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 @@ internal sealed class ContentListViewServiceTests : ContentListViewServiceTestsB { ContentTypeKey = childContentType.Key, ParentKey = root.Key, - InvariantName = $"Item {i}", + Variants = [new () { Name = $"Item {i}" }], Key = i.ToGuid(), }; @@ -963,19 +963,18 @@ internal sealed class ContentListViewServiceTests : ContentListViewServiceTestsB 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 @@ internal sealed class ContentListViewServiceTests : ContentListViewServiceTestsB { 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 413b30010a..d991c99ffb 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 @@ internal sealed class ContentValidationServiceTests : UmbracoIntegrationTestWith new ContentCreateModel { ContentTypeKey = setup.DocumentType.Key, - InvariantName = "Test Document", - InvariantProperties = new[] + Variants = [new () { Name = "Test Document" }], + Properties = new[] { new PropertyValueModel { @@ -175,8 +175,8 @@ internal sealed class ContentValidationServiceTests : UmbracoIntegrationTestWith new ContentCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Test Document", - InvariantProperties = new[] + Variants = [new () { Name = "Test Document" }], + Properties = new[] { new PropertyValueModel { @@ -213,8 +213,8 @@ internal sealed class ContentValidationServiceTests : UmbracoIntegrationTestWith new ContentCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Test Document", - InvariantProperties = new[] + Variants = [new () { Name = "Test Document" }], + Properties = new[] { new PropertyValueModel { @@ -250,8 +250,8 @@ internal sealed class ContentValidationServiceTests : UmbracoIntegrationTestWith new ContentCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Test Document", - InvariantProperties = new[] + Variants = [new () { Name = "Test Document" }], + Properties = new[] { new PropertyValueModel { @@ -275,8 +275,8 @@ internal sealed class ContentValidationServiceTests : UmbracoIntegrationTestWith new ContentCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Test Document", - InvariantProperties = new[] + Variants = [new () { Name = "Test Document" }], + Properties = new[] { new PropertyValueModel { @@ -310,8 +310,8 @@ internal sealed class ContentValidationServiceTests : UmbracoIntegrationTestWith new ContentCreateModel { ContentTypeKey = contentType.Key, - InvariantName = "Test Document", - InvariantProperties = new[] + Variants = [new () { Name = "Test Document" }], + Properties = new[] { new PropertyValueModel { @@ -349,18 +349,14 @@ internal sealed class ContentValidationServiceTests : UmbracoIntegrationTestWith 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 @@ internal sealed class ContentValidationServiceTests : UmbracoIntegrationTestWith 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 @@ internal sealed class ContentValidationServiceTests : UmbracoIntegrationTestWith 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 @@ internal sealed class ContentValidationServiceTests : UmbracoIntegrationTestWith 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 @@ internal sealed class ContentValidationServiceTests : UmbracoIntegrationTestWith 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 c5c1b79d7a..8e31abf897 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 @@ internal sealed class MediaListViewServiceTests : ContentListViewServiceTestsBas { 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 @@ internal sealed class MediaListViewServiceTests : ContentListViewServiceTestsBas { 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 031964a96a..6f6b79e649 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 @@ internal sealed class MemberEditingServiceTests : UmbracoIntegrationTest 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 @@ internal sealed class MemberEditingServiceTests : UmbracoIntegrationTest Email = member.Email, Username = member.Username, IsApproved = true, - InvariantName = member.Name, + Variants = [new VariantModel { Name = member.Name }], NewPassword = "NewSuperSecret123" }; @@ -140,7 +140,7 @@ internal sealed class MemberEditingServiceTests : UmbracoIntegrationTest 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 @@ internal sealed class MemberEditingServiceTests : UmbracoIntegrationTest 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 @@ internal sealed class MemberEditingServiceTests : UmbracoIntegrationTest 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 @@ internal sealed class MemberEditingServiceTests : UmbracoIntegrationTest 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 @@ internal sealed class MemberEditingServiceTests : UmbracoIntegrationTest { 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 @@ internal sealed class MemberEditingServiceTests : UmbracoIntegrationTest 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 746da766bf..dc5c7c99fe 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 @@ internal sealed class DocumentHybridCachePropertyTest : UmbracoIntegrationTest // 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 7c5f1950bf..50c0d94a6b 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 @@ internal sealed class DocumentHybridCacheTemplateTests : UmbracoIntegrationTestW 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 f0c335b577..0c4207331a 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 @@ internal sealed class DocumentHybridCacheTests : UmbracoIntegrationTestWithConte 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 40fa91afe1..4e8932b6ad 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 @@ internal sealed class DocumentHybridCacheVariantsTests : UmbracoIntegrationTest 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 @@ internal sealed class DocumentHybridCacheVariantsTests : UmbracoIntegrationTest 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 692904fb52..53a3d9446a 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 @@ internal sealed class MediaHybridCacheTests : UmbracoIntegrationTestWithMediaEdi 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 @@ internal sealed class MediaHybridCacheTests : UmbracoIntegrationTestWithMediaEdi 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 f3754bb5fd..1547d64b76 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 @@ internal sealed class MemberHybridCacheTests : UmbracoIntegrationTest 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());