File: Dcp\JsonPatchTests.cs
Web Access
Project: src\tests\Aspire.Hosting.Tests\Aspire.Hosting.Tests.csproj (Aspire.Hosting.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Text.Json.Nodes;
using Aspire.Hosting.Dcp;
using k8s;
 
namespace Aspire.Hosting.Tests.Dcp;
 
[Trait("Partition", "4")]
public sealed class JsonPatchTests
{
    [Fact]
    public void Create_ObjectDifferences_CreatesAddRemoveAndReplaceOperations()
    {
        var current = JsonNode.Parse("""{"unchanged":1,"removed":2,"replaced":"before"}""");
        var changed = JsonNode.Parse("""{"unchanged":1,"replaced":"after","added":true}""");
 
        var patch = JsonPatch.Create(current, changed);
 
        Assert.Equal(
            """[{"op":"remove","path":"/removed"},{"op":"replace","path":"/replaced","value":"after"},{"op":"add","path":"/added","value":true}]""",
            KubernetesJson.Serialize(patch, null));
        Assert.True(JsonNode.DeepEquals(changed, JsonPatch.Apply(current, patch)));
    }
 
    [Fact]
    public void Create_ScalarDifference_CreatesRootReplaceOperation()
    {
        var current = JsonValue.Create("before");
        var changed = JsonValue.Create("after");
 
        var patch = JsonPatch.Create(current, changed);
 
        Assert.Equal(
            """[{"op":"replace","path":"","value":"after"}]""",
            KubernetesJson.Serialize(patch, null));
        Assert.True(JsonNode.DeepEquals(changed, JsonPatch.Apply(current, patch)));
    }
 
    [Theory]
    [InlineData(
        """[1,2]""",
        """[1,2,3,4]""",
        """[{"op":"add","path":"/2","value":3},{"op":"add","path":"/3","value":4}]""")]
    [InlineData(
        """[1,2,3,4]""",
        """[1,2]""",
        """[{"op":"remove","path":"/3"},{"op":"remove","path":"/2"}]""")]
    [InlineData(
        """[{"value":"before"},2]""",
        """[{"value":"after"},3]""",
        """[{"op":"replace","path":"/0/value","value":"after"},{"op":"replace","path":"/1","value":3}]""")]
    public void Create_ArrayDifferences_CreatesApplicableOperations(string currentJson, string changedJson, string expectedPatchJson)
    {
        var current = JsonNode.Parse(currentJson);
        var changed = JsonNode.Parse(changedJson);
 
        var patch = JsonPatch.Create(current, changed);
 
        Assert.Equal(expectedPatchJson, KubernetesJson.Serialize(patch, null));
        Assert.True(JsonNode.DeepEquals(changed, JsonPatch.Apply(current, patch)));
    }
 
    [Fact]
    public void Create_PropertyNamesWithJsonPointerCharacters_EscapesPathSegments()
    {
        var current = JsonNode.Parse("""{"a/b":{"m~n":"before"}}""");
        var changed = JsonNode.Parse("""{"a/b":{"m~n":"after"}}""");
 
        var patch = JsonPatch.Create(current, changed);
 
        Assert.Equal(
            """[{"op":"replace","path":"/a~1b/m~0n","value":"after"}]""",
            KubernetesJson.Serialize(patch, null));
        Assert.True(JsonNode.DeepEquals(changed, JsonPatch.Apply(current, patch)));
    }
}