public void ReducePatch__Given_ArrayPropertyNotEqual__Then_PatchEntireArray(TestJsonObject obj) { // Assemble var original = JObject.FromObject(obj); obj.OtherChildren.First().String = "Updated Value"; var update = JObject.FromObject(obj); var subject = new JsonDiff(); // Act var result = (JObject)subject.ReducePatch(original, update); // Assert Assert.NotNull(result); // All values should be included in array patch Assert.Equal(obj.OtherChildren.Count, result[nameof(obj.OtherChildren)].Count()); var otherChildObj = obj.OtherChildren.First(); var otherChildJson = result[nameof(obj.OtherChildren)][0]; Assert.Equal(otherChildObj.String, otherChildJson["String"].Value <string>()); Assert.Equal(otherChildObj.Guid, otherChildJson["Guid"].Value <Guid>()); Assert.Equal(otherChildObj.Int, otherChildJson["Int"].Value <int>()); Assert.Equal(otherChildObj.Decimal, otherChildJson["Decimal"].Value <decimal>()); Assert.Equal(otherChildObj.Double, otherChildJson["Double"].Value <double>()); Assert.Equal(otherChildObj.DateTime, otherChildJson["DateTime"].Value <DateTime>()); // Other properties should not need patching Assert.Single(result); }
public ShopApiTest() { _jsonDiff = new JsonDiffBuilder() .UseAdditionalProperties() .Use(ExtractAndIgnoreVariables) .Build(); }
public void AssertNotEqual(object oldValue, object newValue) { var old = JToken.FromObject(oldValue); var @new = JToken.FromObject(newValue); var diff = JsonDiff.GetDiffMessage(old, @new); Assert.True(false, $"Received value does not match stored snapshot.\n {diff}"); }
public void AssertNotEqual(object oldValue, object newValue) { var old = JToken.FromObject(oldValue); var @new = JToken.FromObject(newValue); throw new NUnitAsserterException( SnapResults.ValueNotEqualToSnapshot(JsonDiff.GetDiffMessage(old, @new))); }
private static void TestDifference(object object1, object object2, params Difference[] expectedDifferences) { var json1 = JObject.FromObject(object1); var json2 = JObject.FromObject(object2); IEnumerable <Difference> differences = JsonDiff.Diff(json1, json2).ToList(); differences.Should().BeEquivalentTo(expectedDifferences.ToList()); }
private (JToken expected, JToken actual) ExtractAndIgnoreVariables( JToken expected, JToken actual, string name, JsonDiff diff) { if (expected is JValue value && value.Value is string stringValue && stringValue.StartsWith("{") && stringValue.EndsWith("}")) { var variableName = stringValue.Substring(1, stringValue.Length - 2); _variables[variableName] = actual.ToString(); return(expected, expected); } return(expected, actual); }
public void TestOfValuesTrueVsFalse() { var v1 = JsonParse.Parse("true"); var v2 = JsonParse.Parse("false"); var diffs = JsonDiff.OfValues(v1, v2).ToList(); Assert.NotEmpty(diffs); var kindDiff = (Diff.Kind)diffs.Single(); Assert.Equal("$", kindDiff.Item.Path); Assert.Equal(JsonValue.True, kindDiff.Item.Left); Assert.Equal(JsonValue.False, kindDiff.Item.Right); }
public void TestOfDocuments1Vs2() { var v1 = JsonParse.Parse("1"); var v2 = JsonParse.Parse("2"); var diffs = JsonDiff.OfValues(v1, v2).ToList(); Assert.NotEmpty(diffs); var valueDiff = (Diff.Value)diffs.Single(); Assert.Equal("$", valueDiff.Item.Path); Assert.Equal(JsonValue.NewNumber(Tuple.Create <double, string>(1, "1")), valueDiff.Item.Left); Assert.Equal(JsonValue.NewNumber(Tuple.Create <double, string>(2, "2")), valueDiff.Item.Right); }
public void TestOfDocuments1Vs2() { using var d1 = JsonDocument.Parse("1"); using var d2 = JsonDocument.Parse("2"); var diffs = JsonDiff.OfDocuments(d1, d2).ToList(); Assert.NotEmpty(diffs); var valueDiff = (Diff.Value)diffs.Single(); Assert.Equal("$", valueDiff.Item.Path); Assert.Equal(1, valueDiff.Item.Left.GetInt32()); Assert.Equal(2, valueDiff.Item.Right.GetInt32()); }
public void TestOfDocumentsTrueVsFalse() { using var d1 = JsonDocument.Parse("true"); using var d2 = JsonDocument.Parse("false"); var diffs = JsonDiff.OfDocuments(d1, d2).ToList(); Assert.NotEmpty(diffs); var kindDiff = (Diff.Kind)diffs.Single(); Assert.Equal("$", kindDiff.Item.Path); Assert.True(kindDiff.Item.Left.GetBoolean()); Assert.False(kindDiff.Item.Right.GetBoolean()); }
public void ReducePatch__Given_AllEqual__Then_Null(TestJsonObject obj) { // Assemble var original = JObject.FromObject(obj); var update = JObject.FromObject(obj); var subject = new JsonDiff(); // Act var result = subject.ReducePatch(original, update); // Assert Assert.Null(result); }
internal Session( Func <HttpClient> httpClientFactory, IHttpRequestBuilder httpRequestBuilder, ICacheProvider cache, IModelRegistry modelRegistry, JsonSerializerSettings jsonSettings, BundledHttpResponseListener httpResponseListener) { HttpClient = httpClientFactory(); HttpRequestBuilder = httpRequestBuilder; Cache = cache; ModelRegistry = modelRegistry; JsonSettings = jsonSettings; HttpResponseListener = httpResponseListener; JsonDiff = new JsonDiff(); JsonComparer = new LooseJsonEqualityComparer(); }
public void ReducePatch__Given_SinglePropertyNotEqual__Then_PatchProperty(TestJsonObject obj) { // Assemble var original = JObject.FromObject(obj); obj.String = "Updated Value"; var update = JObject.FromObject(obj); var subject = new JsonDiff(); // Act var result = (JObject)subject.ReducePatch(original, update); // Assert Assert.NotNull(result); Assert.Equal(obj.String, result["String"].Value <string>()); // Other properties should not need patching Assert.Single(result); }
private Resource BuildPatch(object model) { var originalResource = ModelRegistry.GetResource(model); var modelRtlns = ModelRegistry.GetRelationshipValues(model) ?? new Dictionary <string, Relationship>(); var originalRtlns = originalResource.Relationships ?? new Dictionary <string, Relationship>(); var patchRtlns = modelRtlns.Where(modelRltn => { originalRtlns.TryGetValue(modelRltn.Key, out var ogRtln); // JToken.DeepEquals does not work here return(!JsonComparer.Equals(ogRtln?.Data, modelRltn.Value?.Data)); }).ToDictionary(x => x.Key, x => x.Value); var modelAttrs = ModelRegistry.GetAttributeValues(model) ?? new JObject(); var originalAttrs = originalResource.Attributes ?? new JObject(); var modelMetas = ModelRegistry.GetMetaValues(model) ?? new JObject(); var originalMetas = originalResource.Meta ?? new JObject(); // Links are not patched var patchAttrs = (JObject)JsonDiff.ReducePatch(originalAttrs, modelAttrs); var patchMetas = (JObject)JsonDiff.ReducePatch(originalMetas, modelMetas); if (patchAttrs == null && !patchRtlns.Any() && patchMetas == null) { // Nothing to update return(null); } return(new Resource { Id = originalResource.Id, Type = originalResource.Type, Attributes = patchAttrs, Relationships = patchRtlns.Any() ? patchRtlns : null, Meta = patchMetas }); }
private static void Main(string[] args) { var output = new StandardOutput(); var addCommand = new Command("add", "Evaluate the reward and insert it into the local DB"); var addMergeCommand = new Command("commit", "Evaluate the reward for a merge commit and insert it into the local DB"); addMergeCommand.AddOption(new Option <DirectoryInfo>(new[] { "--path", "-p" }, "Path to a local repository. E.g. '~/repos/devrating'") { IsRequired = true }.ExistingOnly()); addMergeCommand.AddOption(new Option <string>(new[] { "--merge", "-m" }, "A merge commit. Takes diff of <merge>~ and <merge>") { IsRequired = true }); addMergeCommand.AddOption(new Option <string>(new[] { "--email", "-a" }, "Email of the PR author")); addMergeCommand.AddOption(new Option <string>(new[] { "--link", "-l" }, "A link to the PR, issue or so")); addMergeCommand.AddOption(new Option <string>(new[] { "--org", "-o" }, "Name of the repository owner")); addMergeCommand.AddOption(new Option <string>(new[] { "--name", "-n" }, "Name of the repository")); addMergeCommand.AddOption(new Option <DateTimeOffset>(new[] { "--time", "-t" }, "A moment when the PR was merged")); addMergeCommand.Handler = CommandHandler.Create <DirectoryInfo, string, string?, string?, string?, string?, DateTimeOffset?>( (path, merge, email, link, org, name, time) => { var first = merge + "~"; var second = merge; var diff = new GitProcessDiff( first, second, new GitProcessLastMajorUpdateTag(path.FullName, first).Sha(), path.FullName, name ?? "unnamed", link, org ?? "none", time ?? DateTimeOffset.UtcNow, email ); var app = Application(); app.Save(diff); app.PrintTo(output, diff); } ); addCommand.AddCommand(addMergeCommand); var addDiffCommand = new Command("diff", "Evaluate the reward for diff and insert it into the local DB"); addDiffCommand.AddOption(new Option <DirectoryInfo>(new[] { "--path", "-p" }, "Path to a local repository. E.g. '~/repos/devrating'") { IsRequired = true }.ExistingOnly()); addDiffCommand.AddOption(new Option <string>(new[] { "--base", "-b" }, "The first commit of diff") { IsRequired = true }); addDiffCommand.AddOption(new Option <string>(new[] { "--head", "-e" }, "The second commit of diff") { IsRequired = true }); addDiffCommand.AddOption(new Option <string>(new[] { "--email", "-a" }, "Email of the PR author")); addDiffCommand.AddOption(new Option <string>(new[] { "--link", "-l" }, "A link to the PR, issue or so")); addDiffCommand.AddOption(new Option <string>(new[] { "--org", "-o" }, "Name of the repository owner")); addDiffCommand.AddOption(new Option <string>(new[] { "--name", "-n" }, "Name of the repository")); addDiffCommand.AddOption(new Option <DateTimeOffset>(new[] { "--time", "-t" }, "A moment when the PR was merged")); addDiffCommand.Handler = CommandHandler.Create <DirectoryInfo, string, string, string?, string?, string?, string?, DateTimeOffset?>( (path, @base, head, email, link, org, name, time) => { var diff = new GitProcessDiff( @base, head, new GitProcessLastMajorUpdateTag(path.FullName, @base).Sha(), path.FullName, name ?? "unnamed", link, org ?? "none", time ?? DateTimeOffset.UtcNow, email ); var app = Application(); app.Save(diff); app.PrintTo(output, diff); } ); addCommand.AddCommand(addDiffCommand); var serializeCommand = new Command("serialize", "Serialize diff metadata"); var serializeMergeCommand = new Command("commit", "Serialize merge commit metadata"); serializeMergeCommand.AddOption(new Option <DirectoryInfo>(new[] { "--path", "-p" }, "Path to a local repository. E.g. '~/repos/devrating'") { IsRequired = true }.ExistingOnly()); serializeMergeCommand.AddOption(new Option <string>(new[] { "--merge", "-m" }, "A merge commit. Takes diff of <merge>~ and <merge>") { IsRequired = true }); serializeMergeCommand.AddOption(new Option <string>(new[] { "--email", "-a" }, "Email of the PR author")); serializeMergeCommand.AddOption(new Option <string>(new[] { "--link", "-l" }, "A link to the PR, issue or so")); serializeMergeCommand.AddOption(new Option <string>(new[] { "--org", "-o" }, "Name of the repository owner")); serializeMergeCommand.AddOption(new Option <string>(new[] { "--name", "-n" }, "Name of the repository")); serializeMergeCommand.AddOption(new Option <DateTimeOffset>(new[] { "--time", "-t" }, "A moment when the PR was merged")); serializeMergeCommand.Handler = CommandHandler.Create <DirectoryInfo, string, string?, string?, string?, string?, DateTimeOffset?>( (path, merge, email, link, org, name, time) => { var first = merge + "~"; var second = merge; output.WriteLine( new GitProcessDiff( first, second, new GitProcessLastMajorUpdateTag(path.FullName, first).Sha(), path.FullName, name ?? "unnamed", link, org ?? "none", time ?? DateTimeOffset.UtcNow, email ) .ToJson() ); } ); serializeCommand.AddCommand(serializeMergeCommand); var serializeDiffCommand = new Command("diff", "Serialize diff metadata"); serializeDiffCommand.AddOption(new Option <DirectoryInfo>(new[] { "--path", "-p" }, "Path to a local repository. E.g. '~/repos/devrating'") { IsRequired = true }.ExistingOnly()); serializeDiffCommand.AddOption(new Option <string>(new[] { "--base", "-b" }, "The first commit of diff") { IsRequired = true }); serializeDiffCommand.AddOption(new Option <string>(new[] { "--head", "-e" }, "The second commit of diff") { IsRequired = true }); serializeDiffCommand.AddOption(new Option <string>(new[] { "--email", "-a" }, "Email of the PR author")); serializeDiffCommand.AddOption(new Option <string>(new[] { "--link", "-l" }, "A link to the PR, issue or so")); serializeDiffCommand.AddOption(new Option <string>(new[] { "--org", "-o" }, "Name of the repository owner")); serializeDiffCommand.AddOption(new Option <string>(new[] { "--name", "-n" }, "Name of the repository")); serializeDiffCommand.AddOption(new Option <DateTimeOffset>(new[] { "--time", "-t" }, "A moment when the PR was merged")); serializeDiffCommand.Handler = CommandHandler.Create <DirectoryInfo, string, string, string?, string?, string?, string?, DateTimeOffset?>( (path, @base, head, email, link, org, name, time) => { output.WriteLine( new GitProcessDiff( @base, head, new GitProcessLastMajorUpdateTag(path.FullName, @base).Sha(), path.FullName, name ?? "unnamed", link, org ?? "none", time ?? DateTimeOffset.UtcNow, email ) .ToJson() ); } ); serializeCommand.AddCommand(serializeDiffCommand); var showCommand = new Command("show", "Print the saved reward from the local DB"); showCommand.AddOption(new Option <string>(new[] { "--base", "-b" }, "The first commit of diff") { IsRequired = true }); showCommand.AddOption(new Option <string>(new[] { "--head", "-e" }, "The second commit of diff") { IsRequired = true }); showCommand.AddOption(new Option <string>(new[] { "--org", "-o" }, "Name of the repository owner")); showCommand.AddOption(new Option <string>(new[] { "--name", "-n" }, "Name of the repository")); showCommand.Handler = CommandHandler.Create <string, string, string?, string?>( (@base, head, org, name) => { Application().PrintTo(output, new ThinDiff(org ?? "none", name ?? "unnamed", @base, head)); } ); var applyCommand = new Command("apply", "Deserialize diff metadata, evaluate the reward and insert it into the local DB"); applyCommand.AddOption(new Option <string>(new[] { "--json", "-j" }, "Serialized diff metadata") { IsRequired = true }); applyCommand.Handler = CommandHandler.Create <string>( (json) => { var diff = new JsonDiff(json); var app = Application(); app.Save(diff); app.PrintTo(output, diff); } ); var topCommand = new Command("top", "Print the rating on the stability of code"); topCommand.AddOption(new Option <string>(new[] { "--org", "-o" }, "Name of the repository owner")); topCommand.AddOption(new Option <string>(new[] { "--name", "-n" }, "Name of the repository")); topCommand.Handler = CommandHandler.Create <string?, string?>( (org, name) => { Application().Top(output, org ?? "none", name ?? "unnamed"); } ); var totalCommand = new Command("total", "Print the total rewards for the last 90 days"); totalCommand.AddOption(new Option <string>(new[] { "--org", "-o" }, "Name of the repository owner")); totalCommand.AddOption(new Option <string>(new[] { "--name", "-n" }, "Name of the repository")); totalCommand.Handler = CommandHandler.Create <string?, string?>( (org, name) => { Application().Total(output, org ?? "none", name ?? "unnamed", DateTimeOffset.UtcNow - TimeSpan.FromDays(90)); } ); // Create a root command with some options var rootCommand = new RootCommand("Dev Rating evaluates rewards based on git diff."); rootCommand.AddCommand(addCommand); rootCommand.AddCommand(showCommand); rootCommand.AddCommand(serializeCommand); rootCommand.AddCommand(topCommand); rootCommand.AddCommand(totalCommand); rootCommand.Invoke(args); }
public JsonDiffTest() { this.diff = new JsonDiff(); }