Finally, making some sense out of all this craziness
This commit is contained in:
@@ -98,20 +98,22 @@ namespace Umbraco.Tests.Web.Validation
|
||||
public void TestSerializer()
|
||||
{
|
||||
var nestedLevel2 = new NestedValidationResults();
|
||||
nestedLevel2.AddElementTypeValidationResults(
|
||||
new ValidationResultCollection(
|
||||
new ValidationResult("error2-1", new[] { "level2" }),
|
||||
new ValidationResult("error2-2", new[] { "level2" })));
|
||||
var elementTypeResult2 = new ElementTypeValidationResult("type2");
|
||||
var propertyTypeResult2 = new PropertyTypeValidationResult("prop2");
|
||||
propertyTypeResult2.ValidationResults.Add(new ValidationResult("error2-1", new[] { "level2" }));
|
||||
propertyTypeResult2.ValidationResults.Add(new ValidationResult("error2-2", new[] { "level2" }));
|
||||
elementTypeResult2.ValidationResults.Add(propertyTypeResult2);
|
||||
nestedLevel2.ValidationResults.Add(elementTypeResult2);
|
||||
|
||||
var nestedLevel1 = new NestedValidationResults();
|
||||
nestedLevel1.AddElementTypeValidationResults(
|
||||
new ValidationResultCollection(
|
||||
new ValidationResult("error1-1", new[] { "level1" }),
|
||||
nestedLevel2));
|
||||
var elementTypeResult1 = new ElementTypeValidationResult("type1");
|
||||
var propertyTypeResult1 = new PropertyTypeValidationResult("prop1");
|
||||
propertyTypeResult1.ValidationResults.Add(new ValidationResult("error1-1", new[] { "level1" }));
|
||||
propertyTypeResult1.ValidationResults.Add(nestedLevel2); // This is a nested result within the level 1
|
||||
elementTypeResult1.ValidationResults.Add(propertyTypeResult1);
|
||||
nestedLevel1.ValidationResults.Add(elementTypeResult1);
|
||||
|
||||
var propValidationResult = new PropertyValidationResult(nestedLevel1);
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(propValidationResult, Formatting.Indented, new ValidationResultConverter());
|
||||
var serialized = JsonConvert.SerializeObject(nestedLevel1, Formatting.Indented, new ValidationResultConverter());
|
||||
Console.WriteLine(serialized);
|
||||
}
|
||||
|
||||
@@ -125,36 +127,26 @@ namespace Umbraco.Tests.Web.Validation
|
||||
|
||||
var content = MockedContent.CreateTextpageContent(_contentType, "test", -1);
|
||||
|
||||
// TODO: Ok now test with a 3rd/4th level complex nested editor
|
||||
|
||||
// const string complexValue = @"[{
|
||||
// ""key"": ""c8df5136-d606-41f0-9134-dea6ae0c2fd9"",
|
||||
// ""name"": ""Hello world"",
|
||||
// ""ncContentTypeAlias"": """ + ContentTypeAlias + @""",
|
||||
// ""title"": ""Hello world""
|
||||
// }, {
|
||||
// ""key"": ""f916104a-4082-48b2-a515-5c4bf2230f38"",
|
||||
// ""name"": ""Super nested"",
|
||||
// ""ncContentTypeAlias"": """ + ContentTypeAlias + @""",
|
||||
// ""title"": ""Hi there!""
|
||||
// }
|
||||
//]";
|
||||
// TODO: Ok now test with a 4th level complex nested editor
|
||||
|
||||
const string complexValue = @"[{
|
||||
""key"": ""c8df5136-d606-41f0-9134-dea6ae0c2fd9"",
|
||||
""name"": ""Hello world"",
|
||||
""ncContentTypeAlias"": """ + ContentTypeAlias + @""",
|
||||
""title"": ""Hello world""
|
||||
""title"": ""Hello world"",
|
||||
""bodyText"": ""The world is round""
|
||||
}, {
|
||||
""key"": ""f916104a-4082-48b2-a515-5c4bf2230f38"",
|
||||
""name"": ""Super nested"",
|
||||
""ncContentTypeAlias"": """ + ContentTypeAlias + @""",
|
||||
""title"": ""Hi there!"",
|
||||
""bodyText"": ""Well hello there"",
|
||||
""complex"" : [{
|
||||
""key"": ""77E15DE9-1C79-47B2-BC60-4913BC4D4C6A"",
|
||||
""name"": ""I am a sub nested content"",
|
||||
""ncContentTypeAlias"": """ + ContentTypeAlias + @""",
|
||||
""title"": ""Hello up there :)""
|
||||
""title"": ""Hello up there :)"",
|
||||
""bodyText"": ""Hello way up there on a different level""
|
||||
}]
|
||||
}
|
||||
]";
|
||||
@@ -234,19 +226,50 @@ namespace Umbraco.Tests.Web.Validation
|
||||
var jsonNestedError = JsonConvert.DeserializeObject<JObject>(nestedError.ErrorMessage);
|
||||
Assert.AreEqual(JTokenType.Array, jsonNestedError["nestedValidation"].Type);
|
||||
var nestedValidation = (JArray)jsonNestedError["nestedValidation"];
|
||||
Assert.AreEqual(2, nestedValidation.Count); // there are 2 because there are 2 nested content rows
|
||||
AssertNestedValidation(nestedValidation, 2); // there are 2 because there are 2 nested content rows
|
||||
}
|
||||
|
||||
private void AssertNestedValidation(JArray nestedValidation, int rows)
|
||||
{
|
||||
Assert.AreEqual(rows, nestedValidation.Count);
|
||||
foreach (var rowErrors in nestedValidation)
|
||||
{
|
||||
var elementTypeErrors = (JArray)rowErrors; // this is an array of errors for the nested content row (element type)
|
||||
Assert.AreEqual(2, elementTypeErrors.Count);
|
||||
foreach (var elementTypeErr in elementTypeErrors)
|
||||
Assert.AreEqual(JTokenType.Object, rowErrors.Type);
|
||||
var elementTypeErrors = (JObject)rowErrors; // this is a dictionary of element type alias -> dictionary of errors -> prop alias -> array errors
|
||||
Assert.AreEqual(1, elementTypeErrors.Count); // there is 1 element type in error
|
||||
foreach (var elementTypeAliasToErrors in elementTypeErrors)
|
||||
{
|
||||
Assert.IsNotEmpty(elementTypeErr["errorMessage"].Value<string>());
|
||||
Assert.AreEqual(1, elementTypeErr["memberNames"].Value<JArray>().Count);
|
||||
Assert.AreEqual("textPage", elementTypeAliasToErrors.Key);
|
||||
var propErrors = (JObject)elementTypeAliasToErrors.Value;
|
||||
|
||||
foreach (var propAliasToErrors in propErrors)
|
||||
{
|
||||
Assert.AreEqual(JTokenType.Array, propAliasToErrors.Value.Type);
|
||||
var propTypeErrors = (JArray)propAliasToErrors.Value;
|
||||
|
||||
foreach (var propError in propTypeErrors)
|
||||
{
|
||||
var nested = propError["nestedValidation"];
|
||||
if (nested != null)
|
||||
{
|
||||
// recurse
|
||||
AssertNestedValidation((JArray)nested, 1); // we know this is 1 row
|
||||
continue;
|
||||
}
|
||||
|
||||
Assert.IsNotEmpty(propError["errorMessage"].Value<string>());
|
||||
Assert.AreEqual(1, propError["memberNames"].Value<JArray>().Count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[HideFromTypeFinder]
|
||||
[DataEditor("complexTest", "test", "test")]
|
||||
public class ComplexTestEditor : NestedContentPropertyEditor
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
var result = new NestedValidationResults();
|
||||
foreach(var rowResult in rowResults)
|
||||
{
|
||||
result.AddElementTypeValidationResults(rowResult);
|
||||
result.ValidationResults.Add(rowResult);
|
||||
}
|
||||
return result.Yield();
|
||||
}
|
||||
@@ -55,30 +55,36 @@ namespace Umbraco.Web.PropertyEditors
|
||||
/// </summary>
|
||||
/// <param name="rawValue"></param>
|
||||
/// <returns></returns>
|
||||
protected IEnumerable<ValidationResultCollection> GetNestedValidationResults(IEnumerable<ElementTypeValidationModel> elements)
|
||||
protected IEnumerable<ElementTypeValidationResult> GetNestedValidationResults(IEnumerable<ElementTypeValidationModel> elements)
|
||||
{
|
||||
foreach (var row in elements)
|
||||
{
|
||||
var nestedValidation = new List<ValidationResult>();
|
||||
var elementTypeValidationResult = new ElementTypeValidationResult(row.ElementTypeAlias);
|
||||
|
||||
foreach (var prop in row.PropertyTypeValidation)
|
||||
{
|
||||
var propValidationResult = new PropertyTypeValidationResult(prop.PropertyType.Alias);
|
||||
|
||||
foreach (var validationResult in _propertyValidationService.ValidatePropertyValue(prop.PropertyType, prop.PostedValue))
|
||||
{
|
||||
nestedValidation.Add(validationResult);
|
||||
// add the result to the property results
|
||||
propValidationResult.ValidationResults.Add(validationResult);
|
||||
}
|
||||
|
||||
// add the property results to the element type results
|
||||
elementTypeValidationResult.ValidationResults.Add(propValidationResult);
|
||||
}
|
||||
|
||||
if (nestedValidation.Count > 0)
|
||||
if (elementTypeValidationResult.ValidationResults.Count > 0)
|
||||
{
|
||||
yield return new ValidationResultCollection(nestedValidation.ToArray());
|
||||
yield return elementTypeValidationResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PropertyTypeValidationModel
|
||||
{
|
||||
public PropertyTypeValidationModel(object postedValue, PropertyType propertyType)
|
||||
public PropertyTypeValidationModel(PropertyType propertyType, object postedValue)
|
||||
{
|
||||
PostedValue = postedValue ?? throw new ArgumentNullException(nameof(postedValue));
|
||||
PropertyType = propertyType ?? throw new ArgumentNullException(nameof(propertyType));
|
||||
@@ -90,9 +96,17 @@ namespace Umbraco.Web.PropertyEditors
|
||||
|
||||
public class ElementTypeValidationModel
|
||||
{
|
||||
public ElementTypeValidationModel(string elementTypeAlias)
|
||||
{
|
||||
ElementTypeAlias = elementTypeAlias;
|
||||
}
|
||||
|
||||
private List<PropertyTypeValidationModel> _list = new List<PropertyTypeValidationModel>();
|
||||
|
||||
public IEnumerable<PropertyTypeValidationModel> PropertyTypeValidation => _list;
|
||||
|
||||
public string ElementTypeAlias { get; }
|
||||
|
||||
public void AddPropertyTypeValidation(PropertyTypeValidationModel propValidation) => _list.Add(propValidation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,10 +269,11 @@ namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
foreach (var row in _nestedContentValues.GetPropertyValues(value))
|
||||
{
|
||||
var elementValidation = new ElementTypeValidationModel();
|
||||
var elementValidation = new ElementTypeValidationModel(row.ContentTypeAlias);
|
||||
foreach (var prop in row.PropertyValues)
|
||||
{
|
||||
elementValidation.AddPropertyTypeValidation(new PropertyTypeValidationModel(prop.Value.Value, prop.Value.PropertyType));
|
||||
elementValidation.AddPropertyTypeValidation(
|
||||
new PropertyTypeValidationModel(prop.Value.PropertyType, prop.Value.Value));
|
||||
}
|
||||
yield return elementValidation;
|
||||
}
|
||||
|
||||
@@ -3,15 +3,28 @@ using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors.Validation
|
||||
{
|
||||
public class ValidationResultCollection : ValidationResult
|
||||
public class PropertyTypeValidationResult : ValidationResult
|
||||
{
|
||||
public ValidationResultCollection(params ValidationResult[] nested)
|
||||
public PropertyTypeValidationResult(string propertyTypeAlias)
|
||||
: base(string.Empty)
|
||||
{
|
||||
ValidationResults = new List<ValidationResult>(nested);
|
||||
PropertyTypeAlias = propertyTypeAlias;
|
||||
}
|
||||
|
||||
public IList<ValidationResult> ValidationResults { get; }
|
||||
public IList<ValidationResult> ValidationResults { get; } = new List<ValidationResult>();
|
||||
public string PropertyTypeAlias { get; }
|
||||
}
|
||||
|
||||
public class ElementTypeValidationResult : ValidationResult
|
||||
{
|
||||
public ElementTypeValidationResult(string elementTypeAlias)
|
||||
: base(string.Empty)
|
||||
{
|
||||
ElementTypeAlias = elementTypeAlias;
|
||||
}
|
||||
|
||||
public IList<PropertyTypeValidationResult> ValidationResults { get; } = new List<PropertyTypeValidationResult>();
|
||||
public string ElementTypeAlias { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -27,11 +40,6 @@ namespace Umbraco.Web.PropertyEditors.Validation
|
||||
{
|
||||
}
|
||||
|
||||
public void AddElementTypeValidationResults(ValidationResultCollection resultCollection)
|
||||
{
|
||||
ValidationResults.Add(resultCollection);
|
||||
}
|
||||
|
||||
public IList<ValidationResultCollection> ValidationResults { get; } = new List<ValidationResultCollection>();
|
||||
public IList<ElementTypeValidationResult> ValidationResults { get; } = new List<ElementTypeValidationResult>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,16 +42,25 @@ namespace Umbraco.Web.PropertyEditors.Validation
|
||||
jo.Add("nestedValidation", obj);
|
||||
jo.WriteTo(writer);
|
||||
}
|
||||
else if (validationResult is ValidationResultCollection resultCollection && resultCollection.ValidationResults.Count > 0)
|
||||
else if (validationResult is ElementTypeValidationResult elementTypeValidationResult && elementTypeValidationResult.ValidationResults.Count > 0)
|
||||
{
|
||||
var ja = new JArray();
|
||||
foreach (var result in resultCollection.ValidationResults)
|
||||
{
|
||||
// recurse to write out the ValidationResult
|
||||
var obj = JObject.FromObject(result, camelCaseSerializer);
|
||||
ja.Add(obj);
|
||||
var joElementType = new JObject();
|
||||
var joPropertyType = new JObject();
|
||||
// loop over property validations
|
||||
foreach (var propTypeResult in elementTypeValidationResult.ValidationResults)
|
||||
{
|
||||
var ja = new JArray();
|
||||
foreach (var result in propTypeResult.ValidationResults)
|
||||
{
|
||||
// recurse to get the validation result object and add to the array
|
||||
var obj = JObject.FromObject(result, camelCaseSerializer);
|
||||
ja.Add(obj);
|
||||
}
|
||||
// create a dictionary entry
|
||||
joPropertyType.Add(propTypeResult.PropertyTypeAlias, ja);
|
||||
}
|
||||
ja.WriteTo(writer);
|
||||
joElementType.Add(elementTypeValidationResult.ElementTypeAlias, joPropertyType);
|
||||
joElementType.WriteTo(writer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user