private static Difference CompareItems(JArray actual, JArray expected, JPath path) { JEnumerable <JToken> actualChildren = actual.Children(); JEnumerable <JToken> expectedChildren = expected.Children(); if (actualChildren.Count() != expectedChildren.Count()) { return(new Difference(DifferenceKind.DifferentLength, path)); } for (int i = 0; i < actualChildren.Count(); i++) { Difference firstDifference = FindFirstDifference(actualChildren.ElementAt(i), expectedChildren.ElementAt(i), path.AddIndex(i)); if (firstDifference != null) { return(firstDifference); } } return(null); }
private static Difference CompareItems(JArray actual, JArray expected, JPath path) { JToken[] actualChildren = actual.Children().ToArray(); JToken[] expectedChildren = expected.Children().ToArray(); if (actualChildren.Length != expectedChildren.Length) { return(new Difference(DifferenceKind.DifferentLength, path, actualChildren.Length, expectedChildren.Length)); } for (int i = 0; i < actualChildren.Length; i++) { Difference firstDifference = FindFirstDifference(actualChildren[i], expectedChildren[i], path.AddIndex(i), false); if (firstDifference != null) { return(firstDifference); } } return(null); }
private static Difference CompareProperties(IEnumerable <JProperty> actual, IEnumerable <JProperty> expected, JPath path) { var actualDictionary = actual?.ToDictionary(p => p.Name, p => p.Value) ?? new Dictionary <string, JToken>(); var expectedDictionary = expected?.ToDictionary(p => p.Name, p => p.Value) ?? new Dictionary <string, JToken>(); foreach (KeyValuePair <string, JToken> expectedPair in expectedDictionary) { if (!actualDictionary.ContainsKey(expectedPair.Key)) { return(new Difference(DifferenceKind.ActualMissesProperty, path.AddProperty(expectedPair.Key))); } } foreach (KeyValuePair <string, JToken> actualPair in actualDictionary) { if (!expectedDictionary.ContainsKey(actualPair.Key)) { return(new Difference(DifferenceKind.ExpectedMissesProperty, path.AddProperty(actualPair.Key))); } } foreach (KeyValuePair <string, JToken> expectedPair in expectedDictionary) { JToken actualValue = actualDictionary[expectedPair.Key]; Difference firstDifference = FindFirstDifference(actualValue, expectedPair.Value, path.AddProperty(expectedPair.Key)); if (firstDifference != null) { return(firstDifference); } } return(null); }
private static Difference FindJObjectDifference(JObject actual, JToken expected, JPath path) { if (!(expected is JObject expectedObject)) { return(new Difference(DifferenceKind.OtherType, path)); } return(CompareProperties(actual?.Properties(), expectedObject.Properties(), path)); }
private static Difference FindJArrayDifference(JArray actualArray, JToken expected, JPath path) { if (!(expected is JArray expectedArray)) { return(new Difference(DifferenceKind.OtherType, path)); } return(CompareItems(actualArray, expectedArray, path)); }
private static Difference FindFirstDifference(JToken actual, JToken expected, JPath path) { switch (actual) { case JArray actualArray: return(FindJArrayDifference(actualArray, expected, path)); case JObject actualObbject: return(FindJObjectDifference(actualObbject, expected, path)); case JProperty actualProperty: return(FindJPropertyDifference(actualProperty, expected, path)); case JValue actualValue: return(FindValueDifference(actualValue, expected, path)); default: throw new NotSupportedException(); } }
private JPath(JPath existingPath, string extraNode) { nodes.AddRange(existingPath.nodes); nodes.Add(extraNode); }
public Difference(DifferenceKind kind, JPath path) { Kind = kind; Path = path; }
private static Difference FindValueDifference(JValue actualValue, JToken expected, JPath path) { if (!(expected is JValue expectedValue)) { return(new Difference(DifferenceKind.OtherType, path)); } return(CompareValues(actualValue, expectedValue, path)); }
private static Difference FindJPropertyDifference(JProperty actualProperty, JToken expected, JPath path) { if (!(expected is JProperty expectedProperty)) { return(new Difference(DifferenceKind.OtherType, path)); } if (actualProperty.Name != expectedProperty.Name) { return(new Difference(DifferenceKind.OtherName, path)); } return(FindFirstDifference(actualProperty.Value, expectedProperty.Value, path)); }
private static Difference CompareExpectedItems(JArray actual, JArray expected, JPath path) { JToken[] actualChildren = actual.Children().ToArray(); JToken[] expectedChildren = expected.Children().ToArray(); int matchingIndex = 0; for (int expectedIndex = 0; expectedIndex < expectedChildren.Length; expectedIndex++) { var expectedChild = expectedChildren[expectedIndex]; bool match = false; for (int actualIndex = matchingIndex; actualIndex < actualChildren.Length; actualIndex++) { var difference = FindFirstDifference(actualChildren[actualIndex], expectedChild, true); if (difference == null) { match = true; matchingIndex = actualIndex + 1; break; } } if (!match) { if (matchingIndex >= actualChildren.Length) { if (actualChildren.Any(actualChild => FindFirstDifference(actualChild, expectedChild, true) == null)) { return(new Difference(DifferenceKind.WrongOrder, path.AddIndex(expectedIndex))); } return(new Difference(DifferenceKind.ActualMissesElement, path.AddIndex(expectedIndex))); } return(FindFirstDifference(actualChildren[matchingIndex], expectedChild, path.AddIndex(expectedIndex), true)); } } return(null); }
private static Difference FindJArrayDifference(JArray actualArray, JToken expected, JPath path, bool ignoreExtraProperties) { if (!(expected is JArray expectedArray)) { return(new Difference(DifferenceKind.OtherType, path, Describe(actualArray.Type), Describe(expected.Type))); } if (ignoreExtraProperties) { return(CompareExpectedItems(actualArray, expectedArray, path)); } else { return(CompareItems(actualArray, expectedArray, path)); } }
public Difference(DifferenceKind kind, JPath path, object actual, object expected) : this(kind, path) { Actual = actual; Expected = expected; }
private static Difference FindJPropertyDifference(JProperty actualProperty, JToken expected, JPath path, bool ignoreExtraProperties) { if (!(expected is JProperty expectedProperty)) { return(new Difference(DifferenceKind.OtherType, path, Describe(actualProperty.Type), Describe(expected.Type))); } if (actualProperty.Name != expectedProperty.Name) { return(new Difference(DifferenceKind.OtherName, path)); } return(FindFirstDifference(actualProperty.Value, expectedProperty.Value, path, ignoreExtraProperties)); }
private static Difference FindJObjectDifference(JObject actual, JToken expected, JPath path, bool ignoreExtraProperties) { if (!(expected is JObject expectedObject)) { return(new Difference(DifferenceKind.OtherType, path, Describe(actual.Type), Describe(expected.Type))); } return(CompareProperties(actual?.Properties(), expectedObject.Properties(), path, ignoreExtraProperties)); }
private static Difference FindFirstDifference(JToken actual, JToken expected, JPath path, bool ignoreExtraProperties, Func <IJsonAssertionOptions <object>, IJsonAssertionOptions <object> > config) { return(actual switch { JArray actualArray => FindJArrayDifference(actualArray, expected, path, ignoreExtraProperties, config), JObject actualObject => FindJObjectDifference(actualObject, expected, path, ignoreExtraProperties, config), JProperty actualProperty => FindJPropertyDifference(actualProperty, expected, path, ignoreExtraProperties, config), JValue actualValue => FindValueDifference(actualValue, expected, path, config), _ => throw new NotSupportedException(), });