From 90b4d557c91f149b9c87e04752bf38f8a1fac390 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 17 Apr 2020 16:12:04 +1000 Subject: [PATCH] Adds a segment level validation key + updates tests --- .../Web/ModelStateExtensionsTests.cs | 54 +++++++++++++++++-- .../src/common/services/formhelper.service.js | 24 +++++---- .../services/content-editing-helper.spec.js | 8 ++- .../Editors/Filters/ContentModelValidator.cs | 2 +- src/Umbraco.Web/ModelStateExtensions.cs | 6 ++- 5 files changed, 77 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Tests/Web/ModelStateExtensionsTests.cs b/src/Umbraco.Tests/Web/ModelStateExtensionsTests.cs index 3ce43b5fc2..8d285e0375 100644 --- a/src/Umbraco.Tests/Web/ModelStateExtensionsTests.cs +++ b/src/Umbraco.Tests/Web/ModelStateExtensionsTests.cs @@ -63,7 +63,7 @@ namespace Umbraco.Tests.Web ms.AddPropertyError(new ValidationResult("no header image"), "headerImage", null); //invariant property - Assert.AreEqual("_Properties.headerImage.invariant", ms.Keys.First()); + Assert.AreEqual("_Properties.headerImage.invariant.null", ms.Keys.First()); } [Test] @@ -73,9 +73,57 @@ namespace Umbraco.Tests.Web var localizationService = new Mock(); localizationService.Setup(x => x.GetDefaultLanguageIsoCode()).Returns("en-US"); - ms.AddPropertyError(new ValidationResult("no header image"), "headerImage", "en-US"); //invariant property + ms.AddPropertyError(new ValidationResult("no header image"), "headerImage", "en-US"); //variant property - Assert.AreEqual("_Properties.headerImage.en-US", ms.Keys.First()); + Assert.AreEqual("_Properties.headerImage.en-US.null", ms.Keys.First()); + } + + [Test] + public void Add_Invariant_Segment_Property_Error() + { + var ms = new ModelStateDictionary(); + var localizationService = new Mock(); + localizationService.Setup(x => x.GetDefaultLanguageIsoCode()).Returns("en-US"); + + ms.AddPropertyError(new ValidationResult("no header image"), "headerImage", null, "mySegment"); //invariant/segment property + + Assert.AreEqual("_Properties.headerImage.invariant.mySegment", ms.Keys.First()); + } + + [Test] + public void Add_Variant_Segment_Property_Error() + { + var ms = new ModelStateDictionary(); + var localizationService = new Mock(); + localizationService.Setup(x => x.GetDefaultLanguageIsoCode()).Returns("en-US"); + + ms.AddPropertyError(new ValidationResult("no header image"), "headerImage", "en-US", "mySegment"); //variant/segment property + + Assert.AreEqual("_Properties.headerImage.en-US.mySegment", ms.Keys.First()); + } + + [Test] + public void Add_Invariant_Segment_Field_Property_Error() + { + var ms = new ModelStateDictionary(); + var localizationService = new Mock(); + localizationService.Setup(x => x.GetDefaultLanguageIsoCode()).Returns("en-US"); + + ms.AddPropertyError(new ValidationResult("no header image", new[] { "myField" }), "headerImage", null, "mySegment"); //invariant/segment property + + Assert.AreEqual("_Properties.headerImage.invariant.mySegment.myField", ms.Keys.First()); + } + + [Test] + public void Add_Variant_Segment_Field_Property_Error() + { + var ms = new ModelStateDictionary(); + var localizationService = new Mock(); + localizationService.Setup(x => x.GetDefaultLanguageIsoCode()).Returns("en-US"); + + ms.AddPropertyError(new ValidationResult("no header image", new[] { "myField" }), "headerImage", "en-US", "mySegment"); //variant/segment property + + Assert.AreEqual("_Properties.headerImage.en-US.mySegment.myField", ms.Keys.First()); } } } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js index 8391e9250b..46ae0ecb8e 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js @@ -159,9 +159,16 @@ function formHelper(angularHelper, serverValidationManager, notificationsService //the alias in model state can be in dot notation which indicates // * the first part is the content property alias // * the second part is the field to which the valiation msg is associated with - //There will always be at least 3 parts for content properties since all model errors for properties are prefixed with "_Properties" + //There will always be at least 4 parts for content properties since all model errors for properties are prefixed with "_Properties" //If it is not prefixed with "_Properties" that means the error is for a field of the object directly. + // Example: "_Properties.headerImage.en-US.mySegment.myField" + // * it's for a property since it has a _Properties prefix + // * it's for the headerImage property type + // * it's for the en-US culture + // * it's for the mySegment segment + // * it's for the myField html field (optional) + var parts = e.split("."); //Check if this is for content properties - specific to content/media/member editors because those are special @@ -179,21 +186,20 @@ function formHelper(angularHelper, serverValidationManager, notificationsService } } - var htmlFieldReference = ""; - if (parts.length > 3) { - htmlFieldReference = parts[3] || ""; - } - - // SEGMENTS_TODO: Need to investigate wether we have updated validation to handle segments, plus could it be the third parameter, so we leave the HTML Field ref as optional and last? var segment = null; - if (parts.length > 4) { - segment = parts[4]; + if (parts.length > 3) { + segment = parts[3]; //special check in case the string is formatted this way if (segment === "null") { segment = null; } } + var htmlFieldReference = ""; + if (parts.length > 4) { + htmlFieldReference = parts[4] || ""; + } + // add a generic error for the property serverValidationManager.addPropertyError(propertyAlias, culture, segment, htmlFieldReference, modelState[e][0]); diff --git a/src/Umbraco.Web.UI.Client/test/unit/common/services/content-editing-helper.spec.js b/src/Umbraco.Web.UI.Client/test/unit/common/services/content-editing-helper.spec.js index 2ccf9e886a..227a359d1d 100644 --- a/src/Umbraco.Web.UI.Client/test/unit/common/services/content-editing-helper.spec.js +++ b/src/Umbraco.Web.UI.Client/test/unit/common/services/content-editing-helper.spec.js @@ -121,13 +121,15 @@ describe('contentEditingHelper tests', function () { //act //note the null, that's because culture is null - formHelper.handleServerValidation({ "_Properties.bodyText.null.value": ["Required"] }); + formHelper.handleServerValidation({ "_Properties.bodyText.null.null.value": ["Required"] }); //assert expect(serverValidationManager.items.length).toBe(1); expect(serverValidationManager.items[0].fieldName).toBe("value"); expect(serverValidationManager.items[0].errorMsg).toBe("Required"); expect(serverValidationManager.items[0].propertyAlias).toBe("bodyText"); + expect(serverValidationManager.items[0].culture).toBe("invariant"); + expect(serverValidationManager.items[0].segment).toBeNull(); }); it('adds a multiple property and field level server validation errors when they are invalid', function () { @@ -142,7 +144,7 @@ describe('contentEditingHelper tests', function () { "Name": ["Required"], "UpdateDate": ["Invalid date"], //note the null, that's because culture is null - "_Properties.bodyText.null.value": ["Required field"], + "_Properties.bodyText.en-US.mySegment.value": ["Required field"], "_Properties.textarea": ["Invalid format"] }); @@ -157,6 +159,8 @@ describe('contentEditingHelper tests', function () { expect(serverValidationManager.items[2].fieldName).toBe("value"); expect(serverValidationManager.items[2].errorMsg).toBe("Required field"); expect(serverValidationManager.items[2].propertyAlias).toBe("bodyText"); + expect(serverValidationManager.items[2].culture).toBe("en-US"); + expect(serverValidationManager.items[2].segment).toBe("mySegment"); expect(serverValidationManager.items[3].fieldName).toBe(""); expect(serverValidationManager.items[3].errorMsg).toBe("Invalid format"); expect(serverValidationManager.items[3].propertyAlias).toBe("textarea"); diff --git a/src/Umbraco.Web/Editors/Filters/ContentModelValidator.cs b/src/Umbraco.Web/Editors/Filters/ContentModelValidator.cs index 0d77b35528..810c2d1bea 100644 --- a/src/Umbraco.Web/Editors/Filters/ContentModelValidator.cs +++ b/src/Umbraco.Web/Editors/Filters/ContentModelValidator.cs @@ -198,7 +198,7 @@ namespace Umbraco.Web.Editors.Filters r.ErrorMessage = property.ValidationRegExpMessage; } - modelState.AddPropertyError(r, property.Alias, property.Culture); + modelState.AddPropertyError(r, property.Alias, property.Culture, property.Segment); } } } diff --git a/src/Umbraco.Web/ModelStateExtensions.cs b/src/Umbraco.Web/ModelStateExtensions.cs index 00b17781e0..6144d6f9c9 100644 --- a/src/Umbraco.Web/ModelStateExtensions.cs +++ b/src/Umbraco.Web/ModelStateExtensions.cs @@ -49,13 +49,15 @@ namespace Umbraco.Web /// /// The culture for the property, if the property is invariant than this is empty internal static void AddPropertyError(this System.Web.Http.ModelBinding.ModelStateDictionary modelState, - ValidationResult result, string propertyAlias, string culture = "") + ValidationResult result, string propertyAlias, string culture = "", string segment = "") { if (culture == null) culture = ""; modelState.AddValidationError(result, "_Properties", propertyAlias, //if the culture is null, we'll add the term 'invariant' as part of the key - culture.IsNullOrWhiteSpace() ? "invariant" : culture); + culture.IsNullOrWhiteSpace() ? "invariant" : culture, + // if the segment is null, we'll add the term 'null' as part of the key + segment.IsNullOrWhiteSpace() ? "null" : segment); } ///