Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions ReflectorNet.Tests.OuterAssembly/src/Model/NestedClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,35 @@ public WrapperClass(T? valueField, T? valueProperty)
/// </summary>
public T? EchoNullable(T? value) => value;
}

public class LevelOne
{
public class LevelTwo
{
public class LevelThree
{
public class LevelFour
{
public string DeepProperty { get; set; } = "deep";
}

public LevelFour? NestedInstance { get; set; }
}

public LevelThree? NestedInstance { get; set; }
}

public LevelTwo? NestedInstance { get; set; }
}

public class GenericOuter<T>
{
public class GenericInner<U>
{
public T? OuterValue { get; set; }
public U? InnerValue { get; set; }
}

public GenericInner<T>? SelfReferencingInner { get; set; }
}
}
203 changes: 203 additions & 0 deletions ReflectorNet.Tests/src/SchemaTests/NestedClassSchemaTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
using System;
using System.Linq;
using System.Reflection;
using System.Text.Json.Nodes;
using com.IvanMurzak.ReflectorNet.OuterAssembly.Model;
using com.IvanMurzak.ReflectorNet.Utils;
using Xunit.Abstractions;

namespace com.IvanMurzak.ReflectorNet.Tests.SchemaTests
{
public class NestedClassSchemaTests : SchemaTestBase
{
public NestedClassSchemaTests(ITestOutputHelper output) : base(output) { }

[Fact]
public void Schema_NestedClass_GeneratesValidSchema()
{
var reflector = new Reflector();
var schema = JsonSchemaValidation(typeof(ParentClass.NestedClass), reflector);

Assert.NotNull(schema);
Assert.Equal(JsonSchema.Object, schema[JsonSchema.Type]?.ToString());
Assert.True(schema.AsObject().ContainsKey(JsonSchema.Properties));

var properties = schema[JsonSchema.Properties]!.AsObject();
Assert.True(properties.ContainsKey("NestedField"));
Assert.True(properties.ContainsKey("NestedProperty"));
Assert.False(properties.ContainsKey("NestedStaticField"));
Assert.False(properties.ContainsKey("NestedStaticProperty"));
}

[Fact]
public void Schema_DeeplyNestedClass_GeneratesValidSchema()
{
var reflector = new Reflector();
var schema = JsonSchemaValidation(typeof(LevelOne.LevelTwo.LevelThree.LevelFour), reflector);

Assert.NotNull(schema);
Assert.Equal(JsonSchema.Object, schema[JsonSchema.Type]?.ToString());
Assert.True(schema.AsObject().ContainsKey(JsonSchema.Properties));

var properties = schema[JsonSchema.Properties]!.AsObject();
Assert.True(properties.ContainsKey("DeepProperty"));
}

[Fact]
public void Schema_DeeplyNestedHierarchy_GeneratesValidSchema()
{
var reflector = new Reflector();
var schema = JsonSchemaValidation(typeof(LevelOne), reflector);

Assert.NotNull(schema);
Assert.Equal(JsonSchema.Object, schema[JsonSchema.Type]?.ToString());
Assert.True(schema.AsObject().ContainsKey(JsonSchema.Properties));

var properties = schema[JsonSchema.Properties]!.AsObject();
Assert.True(properties.ContainsKey("NestedInstance"));

var nestedInstanceSchema = properties["NestedInstance"]!.AsObject();
Assert.True(nestedInstanceSchema.ContainsKey(JsonSchema.Ref) || nestedInstanceSchema.ContainsKey(JsonSchema.Type));

AssertAllRefsDefined(schema);
}

[Fact]
public void Schema_GenericNestedClass_GeneratesValidSchema()
{
var reflector = new Reflector();
var type = typeof(GenericOuter<int>.GenericInner<string>);
var schema = JsonSchemaValidation(type, reflector);

Assert.NotNull(schema);
Assert.Equal(JsonSchema.Object, schema[JsonSchema.Type]?.ToString());
Assert.True(schema.AsObject().ContainsKey(JsonSchema.Properties));

var properties = schema[JsonSchema.Properties]!.AsObject();
Assert.True(properties.ContainsKey("OuterValue"));
Assert.True(properties.ContainsKey("InnerValue"));
}

[Fact]
public void Schema_GenericNestedClass_SelfReferencing_GeneratesValidSchema()
{
var reflector = new Reflector();
var type = typeof(GenericOuter<int>);
var schema = JsonSchemaValidation(type, reflector);

Assert.NotNull(schema);
Assert.Equal(JsonSchema.Object, schema[JsonSchema.Type]?.ToString());
Assert.True(schema.AsObject().ContainsKey(JsonSchema.Properties));

var properties = schema[JsonSchema.Properties]!.AsObject();
Assert.True(properties.ContainsKey("SelfReferencingInner"));

AssertAllRefsDefined(schema);
}

[Fact]
public void Schema_NestedClass_RefsAreDefinedInDefs()
{
var reflector = new Reflector();
var type = typeof(LevelOne);
var schema = reflector.GetSchema(type);

Assert.NotNull(schema);
Assert.True(schema.AsObject().ContainsKey(JsonSchema.Defs), "Schema should contain $defs for nested types");

var defines = schema[JsonSchema.Defs]!.AsObject();
Assert.NotNull(defines);

var levelTwoId = typeof(LevelOne.LevelTwo).GetSchemaTypeId();
var levelThreeId = typeof(LevelOne.LevelTwo.LevelThree).GetSchemaTypeId();
var levelFourId = typeof(LevelOne.LevelTwo.LevelThree.LevelFour).GetSchemaTypeId();

Assert.True(defines.ContainsKey(levelTwoId), $"$defs should contain {levelTwoId}");
Assert.True(defines.ContainsKey(levelThreeId), $"$defs should contain {levelThreeId}");
Assert.True(defines.ContainsKey(levelFourId), $"$defs should contain {levelFourId}");

AssertAllRefsDefined(schema);
}

[Fact]
public void Schema_NestedClass_ReturnSchema_HasValidRefs()
{
var reflector = new Reflector();
var methodInfo = GetType().GetMethod(nameof(NestedClassReturnMethod), BindingFlags.NonPublic | BindingFlags.Instance)!;
var schema = reflector.GetReturnSchema(methodInfo);

Assert.NotNull(schema);
AssertCustomTypeReturnSchema(schema, new[] { "NestedField", "NestedProperty" }, shouldBeRequired: true);
AssertAllRefsDefined(schema);
}

[Fact]
public void Schema_DeeplyNestedClass_ReturnSchema_HasValidRefs()
{
var reflector = new Reflector();
var methodInfo = GetType().GetMethod(nameof(DeeplyNestedClassReturnMethod), BindingFlags.NonPublic | BindingFlags.Instance)!;
var schema = reflector.GetReturnSchema(methodInfo);

Assert.NotNull(schema);
AssertCustomTypeReturnSchema(schema, new[] { "DeepProperty" }, shouldBeRequired: true);
AssertAllRefsDefined(schema);
}

[Fact]
public void Schema_GenericNestedClass_ReturnSchema_HasValidRefs()
{
var reflector = new Reflector();
var methodInfo = GetType().GetMethod(nameof(GenericNestedClassReturnMethod), BindingFlags.NonPublic | BindingFlags.Instance)!;
var schema = reflector.GetReturnSchema(methodInfo);

Assert.NotNull(schema);
AssertCustomTypeReturnSchema(schema, new[] { "OuterValue", "InnerValue" }, shouldBeRequired: true);
AssertAllRefsDefined(schema);
}

[Fact]
public void Schema_NestedClass_Array_ReturnSchema_HasValidRefs()
{
var reflector = new Reflector();
var methodInfo = GetType().GetMethod(nameof(NestedClassArrayReturnMethod), BindingFlags.NonPublic | BindingFlags.Instance)!;
var schema = reflector.GetReturnSchema(methodInfo);

Assert.NotNull(schema);
AssertArrayReturnSchema(schema, JsonSchema.Object, shouldBeRequired: true);
AssertAllRefsDefined(schema);
}

[Fact]
public void Schema_NestedClass_ArgumentSchema_HasValidRefs()
{
var reflector = new Reflector();
var methodInfo = GetType().GetMethod(nameof(NestedClassArgumentMethod), BindingFlags.NonPublic | BindingFlags.Instance)!;
var schema = reflector.GetArgumentsSchema(methodInfo);

Assert.NotNull(schema);
Assert.True(schema.AsObject().ContainsKey(JsonSchema.Defs), "Argument schema should contain $defs");
AssertAllRefsDefined(schema);
}

[Fact]
public void Schema_CrossAssemblyNestedClass_GeneratesValidSchema()
{
var reflector = new Reflector();
var schema = JsonSchemaValidation(typeof(StaticParentClass.NestedClass), reflector);

Assert.NotNull(schema);
Assert.Equal(JsonSchema.Object, schema[JsonSchema.Type]?.ToString());
Assert.True(schema.AsObject().ContainsKey(JsonSchema.Properties));

var properties = schema[JsonSchema.Properties]!.AsObject();
Assert.True(properties.ContainsKey("NestedField"));
Assert.True(properties.ContainsKey("NestedProperty"));
}

private ParentClass.NestedClass NestedClassReturnMethod() => new ParentClass.NestedClass();
private LevelOne.LevelTwo.LevelThree.LevelFour DeeplyNestedClassReturnMethod() => new LevelOne.LevelTwo.LevelThree.LevelFour();
private GenericOuter<int>.GenericInner<string> GenericNestedClassReturnMethod() => new GenericOuter<int>.GenericInner<string>();
private ParentClass.NestedClass[] NestedClassArrayReturnMethod() => new ParentClass.NestedClass[0];
private void NestedClassArgumentMethod(ParentClass.NestedClass nested) { }
}
}
34 changes: 31 additions & 3 deletions ReflectorNet.Tests/src/SchemaTests/TestSchemaTypeId.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using com.IvanMurzak.ReflectorNet.OuterAssembly.Model;
using com.IvanMurzak.ReflectorNet.Utils;
using Xunit.Abstractions;

Expand All @@ -8,6 +9,33 @@ public class TestSchemaTypeId : BaseTest
{
public TestSchemaTypeId(ITestOutputHelper output) : base(output) { }

[Fact]
public void GetSchemaTypeId_NestedClass_ShouldEncodePlusSymbol()
{
var type = typeof(ParentClass.NestedClass);
var result = type.GetSchemaTypeId();
Assert.Equal("com.IvanMurzak.ReflectorNet.OuterAssembly.Model.ParentClass%2BNestedClass", result);
_output.WriteLine($"ParentClass.NestedClass -> {result}");
}

[Fact]
public void GetSchemaTypeId_DeeplyNestedClass_ShouldEncodeAllPlusSymbols()
{
var type = typeof(LevelOne.LevelTwo.LevelThree.LevelFour);
var result = type.GetSchemaTypeId();
Assert.Equal("com.IvanMurzak.ReflectorNet.OuterAssembly.Model.LevelOne%2BLevelTwo%2BLevelThree%2BLevelFour", result);
_output.WriteLine($"LevelOne.LevelTwo.LevelThree.LevelFour -> {result}");
}

[Fact]
public void GetSchemaTypeId_GenericNestedClass_ShouldEncodePlusAndAngleBrackets()
{
var type = typeof(GenericOuter<int>.GenericInner<string>);
var result = type.GetSchemaTypeId();
Assert.Equal("com.IvanMurzak.ReflectorNet.OuterAssembly.Model.GenericOuter%3CSystem.Int32%3E%2BGenericInner%3CSystem.String%3E", result);
_output.WriteLine($"GenericOuter<int>.GenericInner<string> -> {result}");
}

[Fact]
public void GetSchemaTypeId_SimpleArray_ShouldAppendArray()
{
Expand Down Expand Up @@ -116,7 +144,7 @@ public void GetSchemaTypeId_IEnumerableOfInt_ShouldReturnGenericFormat()
var result = type.GetSchemaTypeId();

// Assert
Assert.Equal("System.Collections.Generic.IEnumerable<System.Int32>", result);
Assert.Equal("System.Collections.Generic.IEnumerable%3CSystem.Int32%3E", result);
_output.WriteLine($"IEnumerable<int> -> {result}");
}

Expand All @@ -130,7 +158,7 @@ public void GetSchemaTypeId_ICollectionOfString_ShouldReturnGenericFormat()
var result = type.GetSchemaTypeId();

// Assert
Assert.Equal("System.Collections.Generic.ICollection<System.String>", result);
Assert.Equal("System.Collections.Generic.ICollection%3CSystem.String%3E", result);
_output.WriteLine($"ICollection<string> -> {result}");
}

Expand All @@ -144,7 +172,7 @@ public void GetSchemaTypeId_IListOfInt_ShouldReturnGenericFormat()
var result = type.GetSchemaTypeId();

// Assert
Assert.Equal("System.Collections.Generic.IList<System.Int32>", result);
Assert.Equal("System.Collections.Generic.IList%3CSystem.Int32%3E", result);
_output.WriteLine($"IList<int> -> {result}");
}

Expand Down
Loading