File: IntegrationTests\ExpandoObjectIntegrationTest.cs
Web Access
Project: src\src\Features\JsonPatch\test\Microsoft.AspNetCore.JsonPatch.Tests.csproj (Microsoft.AspNetCore.JsonPatch.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;
using System.Collections.Generic;
using System.Dynamic;
using Microsoft.AspNetCore.JsonPatch.Exceptions;
using Xunit;
 
namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests;
 
public class ExpandoObjectIntegrationTest
{
    [Fact]
    public void AddNewIntProperty()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.Test = 1;
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Add("NewInt", 1);
 
        // Act
        patchDocument.ApplyTo(targetObject);
 
        // Assert
        Assert.Equal(1, targetObject.NewInt);
        Assert.Equal(1, targetObject.Test);
    }
 
    [Fact]
    public void AddNewProperty_ToTypedObject_InExpandoObject()
    {
        // Arrange
        dynamic dynamicProperty = new ExpandoObject();
        dynamicProperty.StringProperty = "A";
 
        var targetObject = new NestedObject()
        {
            DynamicProperty = dynamicProperty
        };
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Add("DynamicProperty/StringProperty", "B");
 
        // Act
        patchDocument.ApplyTo(targetObject);
 
        // Assert
        Assert.Equal("B", targetObject.DynamicProperty.StringProperty);
    }
 
    [Fact]
    public void AddReplaces_ExistingProperty()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.StringProperty = "A";
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Add("StringProperty", "B");
 
        // Act
        patchDocument.ApplyTo(targetObject);
 
        // Assert
        Assert.Equal("B", targetObject.StringProperty);
    }
 
    [Fact]
    public void AddReplaces_ExistingProperty_InNestedExpandoObject()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.InBetweenFirst = new ExpandoObject();
        targetObject.InBetweenFirst.InBetweenSecond = new ExpandoObject();
        targetObject.InBetweenFirst.InBetweenSecond.StringProperty = "A";
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Add("/InBetweenFirst/InBetweenSecond/StringProperty", "B");
 
        // Act
        patchDocument.ApplyTo(targetObject);
 
        // Assert
        Assert.Equal("B", targetObject.InBetweenFirst.InBetweenSecond.StringProperty);
    }
 
    [Fact]
    public void ShouldNotReplaceProperty_WithDifferentCase()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.StringProperty = "A";
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Add("stringproperty", "B");
 
        // Act
        patchDocument.ApplyTo(targetObject);
 
        // Assert
        Assert.Equal("A", targetObject.StringProperty);
        Assert.Equal("B", targetObject.stringproperty);
    }
 
    [Fact]
    public void TestIntegerProperty_IsSuccessful()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.Test = 1;
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Test("Test", 1);
 
        // Act & Assert
        patchDocument.ApplyTo(targetObject);
    }
 
    [Fact]
    public void TestEmptyProperty_IsSuccessful()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.Test = "";
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Test("Test", "");
 
        // Act & Assert
        patchDocument.ApplyTo(targetObject);
    }
 
    [Fact]
    public void TestValueAgainstEmptyProperty_ThrowsJsonPatchException_IsSuccessful()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.Test = "";
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Test("Test", "TestValue");
 
        // Act
        var exception = Assert.Throws<JsonPatchException>(() =>
        {
            patchDocument.ApplyTo(targetObject);
        });
 
        // Assert
        Assert.Equal("The current value '' at path 'Test' is not equal to the test value 'TestValue'.",
            exception.Message);
    }
 
    [Fact]
    public void TestStringProperty_ThrowsJsonPatchException_IfTestFails()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.Test = "Value";
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Test("Test", "TestValue");
 
        // Act
        var exception = Assert.Throws<JsonPatchException>(() =>
        {
            patchDocument.ApplyTo(targetObject);
        });
 
        // Assert
        Assert.Equal("The current value 'Value' at path 'Test' is not equal to the test value 'TestValue'.",
            exception.Message);
    }
 
    [Fact]
    public void CopyStringProperty_ToAnotherStringProperty()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
 
        targetObject.StringProperty = "A";
        targetObject.AnotherStringProperty = "B";
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Copy("StringProperty", "AnotherStringProperty");
 
        // Act
        patchDocument.ApplyTo(targetObject);
 
        // Assert
        Assert.Equal("A", targetObject.AnotherStringProperty);
    }
 
    [Fact]
    public void CopyNullStringProperty_ToAnotherStringProperty()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
 
        targetObject.StringProperty = null;
        targetObject.AnotherStringProperty = "B";
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Copy("StringProperty", "AnotherStringProperty");
 
        // Act
        patchDocument.ApplyTo(targetObject);
 
        // Assert
        Assert.Null(targetObject.AnotherStringProperty);
    }
 
    [Fact]
    public void MoveIntegerValue_ToAnotherIntegerProperty()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.IntegerValue = 100;
        targetObject.AnotherIntegerValue = 200;
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Move("IntegerValue", "AnotherIntegerValue");
 
        // Act
        patchDocument.ApplyTo(targetObject);
 
        Assert.Equal(100, targetObject.AnotherIntegerValue);
 
        var cont = targetObject as IDictionary<string, object>;
        cont.TryGetValue("IntegerValue", out object valueFromDictionary);
 
        // Assert
        Assert.Null(valueFromDictionary);
    }
 
    [Fact]
    public void Move_ToNonExistingProperty()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.StringProperty = "A";
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Move("StringProperty", "AnotherStringProperty");
 
        // Act
        patchDocument.ApplyTo(targetObject);
 
        Assert.Equal("A", targetObject.AnotherStringProperty);
 
        var cont = targetObject as IDictionary<string, object>;
        cont.TryGetValue("StringProperty", out var valueFromDictionary);
 
        // Assert
        Assert.Null(valueFromDictionary);
    }
 
    [Fact]
    public void RemoveProperty_ShouldFail_IfItDoesntExist()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.Test = 1;
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Remove("NonExisting");
 
        // Act
        var exception = Assert.Throws<JsonPatchException>(() =>
        {
            patchDocument.ApplyTo(targetObject);
        });
 
        // Assert
        Assert.Equal("The target location specified by path segment 'NonExisting' was not found.", exception.Message);
    }
 
    [Fact]
    public void RemoveStringProperty()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.Test = 1;
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Remove("Test");
 
        // Act
        patchDocument.ApplyTo(targetObject);
 
        var cont = targetObject as IDictionary<string, object>;
        cont.TryGetValue("Test", out object valueFromDictionary);
 
        // Assert
        Assert.Null(valueFromDictionary);
    }
 
    [Fact]
    public void RemoveProperty_MixedCase_ThrowsPathNotFoundException()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.Test = 1;
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Remove("test");
 
        // Act
        var exception = Assert.Throws<JsonPatchException>(() =>
        {
            patchDocument.ApplyTo(targetObject);
        });
 
        // Assert
        Assert.Equal("The target location specified by path segment 'test' was not found.", exception.Message);
    }
 
    [Fact]
    public void RemoveNestedProperty()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.Test = new ExpandoObject();
        targetObject.Test.AnotherTest = "A";
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Remove("Test");
 
        // Act
        patchDocument.ApplyTo(targetObject);
 
        var cont = targetObject as IDictionary<string, object>;
        cont.TryGetValue("Test", out object valueFromDictionary);
 
        // Assert
        Assert.Null(valueFromDictionary);
    }
 
    [Fact]
    public void RemoveNestedProperty_MixedCase_ThrowsPathNotFoundException()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.Test = new ExpandoObject();
        targetObject.Test.AnotherTest = "A";
 
        var patchDocument = new JsonPatchDocument();
        patchDocument.Remove("test");
 
        // Act
        var exception = Assert.Throws<JsonPatchException>(() =>
        {
            patchDocument.ApplyTo(targetObject);
        });
 
        // Assert
        Assert.Equal("The target location specified by path segment 'test' was not found.", exception.Message);
    }
 
    [Fact]
    public void ReplaceGuid()
    {
        // Arrange
        dynamic targetObject = new ExpandoObject();
        targetObject.GuidValue = Guid.NewGuid();
 
        var newGuid = Guid.NewGuid();
        var patchDocument = new JsonPatchDocument();
        patchDocument.Replace("GuidValue", newGuid);
 
        // Act
        patchDocument.ApplyTo(targetObject);
 
        // Assert
        Assert.Equal(newGuid, targetObject.GuidValue);
    }
}