Skip to content
Merged
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
5 changes: 3 additions & 2 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
"Bash(dotnet build:*)",
"Bash(git checkout:*)",
"Bash(dotnet clean:*)",
"Bash(gh pr:*)"
"Bash(gh pr:*)",
"Bash(dotnet run:*)"
],
"deny": [],
"ask": []
}
}
}
1 change: 1 addition & 0 deletions ConsoleApp/ConsoleApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<LangVersion>11.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
Expand Down
3 changes: 2 additions & 1 deletion ReflectorNet.Tests/ReflectorNet.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
<LangVersion>11.0</LangVersion>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
Expand Down
30 changes: 14 additions & 16 deletions ReflectorNet.Tests/SchemaTests/MethodWrapperTests.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using com.IvanMurzak.ReflectorNet.Model;
using com.IvanMurzak.ReflectorNet;
using com.IvanMurzak.ReflectorNet.Tests.Model;
using Xunit.Abstractions;
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
using System.Reflection;

namespace com.IvanMurzak.ReflectorNet.Tests.SchemaTests
{
Expand Down Expand Up @@ -282,13 +280,13 @@ public async Task MethodWrapper_Enum_Parameter_String_Input()
var wrapper = MethodWrapper.Create(reflector, null, methodInfo);

// Act & Assert - Test with string representation of enum
var parameters = new Dictionary<string, object?>
{
{ "enumValue", "Option2" }
var parameters = new Dictionary<string, object?>
{
{ "enumValue", "Option2" }
};

var result = await wrapper.InvokeDict(parameters);

// Assert
Assert.NotNull(result);
Assert.Equal("Processed enum: Option2", result.ToString());
Expand All @@ -306,14 +304,14 @@ public async Task MethodWrapper_Enum_Parameter_JsonElement_Input()
// Act & Assert - Test with JsonElement containing enum string
var jsonDocument = JsonDocument.Parse("\"Option3\"");
var jsonElement = jsonDocument.RootElement;
var parameters = new Dictionary<string, object?>
{
{ "enumValue", jsonElement }

var parameters = new Dictionary<string, object?>
{
{ "enumValue", jsonElement }
};

var result = await wrapper.InvokeDict(parameters);

// Assert
Assert.NotNull(result);
Assert.Equal("Processed enum: Option3", result.ToString());
Expand All @@ -330,7 +328,7 @@ public async Task MethodWrapper_Enum_Parameter_Default_Value()

// Act & Assert - Test with no parameter (should use default value Option2)
var result = await wrapper.InvokeDict(null);

// Assert
Assert.NotNull(result);
Assert.Equal("Processed enum with default: Option2", result.ToString());
Expand All @@ -346,14 +344,14 @@ public async Task MethodWrapper_Enum_Parameter_Mixed_Types()
var wrapper = MethodWrapper.Create(reflector, null, methodInfo);

// Act & Assert - Test with string and enum parameters
var parameters = new Dictionary<string, object?>
{
var parameters = new Dictionary<string, object?>
{
{ "text", "Hello" },
{ "enumValue", "Option4" }
{ "enumValue", "Option4" }
};

var result = await wrapper.InvokeDict(parameters);

// Assert
Assert.NotNull(result);
Assert.Equal("Text: Hello, Enum: Option4", result.ToString());
Expand Down
32 changes: 24 additions & 8 deletions ReflectorNet.Tests/SchemaTests/ReturnSchemaTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,16 @@ public void GetReturnSchema_TaskNullablePrimitive_UnwrapsWithoutRequired(string
AssertAllRefsDefined(schema!);
}

[Fact]
public void GetReturnSchema_TaskNullableCustomType_UnwrapsToCustomTypeSchemaWithoutRequired()
[Theory]
#if NET5_0_OR_GREATER
[InlineData(false)]
#else
[InlineData(true)]
#endif
public void GetReturnSchema_TaskNullableCustomType_UnwrapsToCustomTypeSchemaWithoutRequired(bool shouldBeRequired)
{
var schema = GetReturnSchemaForMethod(nameof(TaskNullableCustomTypeMethod));
AssertCustomTypeReturnSchema(schema!, new[] { "Name", "Value" }, shouldBeRequired: false);
AssertCustomTypeReturnSchema(schema!, new[] { "Name", "Value" }, shouldBeRequired: shouldBeRequired);
AssertAllRefsDefined(schema!);
}

Expand Down Expand Up @@ -602,7 +607,11 @@ public void GetReturnSchema_NullableStringArray_ReturnsArraySchemaWithoutRequire

[Theory]
[InlineData(nameof(ListComplexTypeMethod), true)]
#if NET5_0_OR_GREATER
[InlineData(nameof(NullableListComplexTypeMethod), false)]
#else
[InlineData(nameof(NullableListComplexTypeMethod), true)] // netstandard2.1 cannot detect List<T>? nullability
#endif
public void GetReturnSchema_ListComplexType_ReturnsArraySchemaWithComplexItems(string methodName, bool shouldBeRequired)
{
var schema = GetReturnSchemaForMethod(methodName);
Expand Down Expand Up @@ -791,14 +800,14 @@ public void GetReturnSchema_NullMethodInfo_ThrowsArgumentNullException()
}

[Theory]
[InlineData(typeof(string), nameof(WrapperClass<string>.Echo), JsonSchema.String, false)] // string is reference type, T is nullable
[InlineData(typeof(string), nameof(WrapperClass<string>.Echo), JsonSchema.String, true)] // string with Echo (T) is non-nullable due to NullableContextAttribute(1)
[InlineData(typeof(int), nameof(WrapperClass<int>.Echo), JsonSchema.Integer, true)] // int is value type, T is non-nullable
[InlineData(typeof(bool), nameof(WrapperClass<bool>.Echo), JsonSchema.Boolean, true)] // bool is value type, T is non-nullable
[InlineData(typeof(double), nameof(WrapperClass<double>.Echo), JsonSchema.Number, true)] // double is value type, T is non-nullable
[InlineData(typeof(string), nameof(WrapperClass<string>.EchoNullable), JsonSchema.String, false)] // string? is nullable reference
[InlineData(typeof(int), nameof(WrapperClass<int>.EchoNullable), JsonSchema.Integer, true)] // int? (Nullable<int>) is itself non-nullable struct
[InlineData(typeof(bool), nameof(WrapperClass<bool>.EchoNullable), JsonSchema.Boolean, true)] // bool? (Nullable<bool>) is itself non-nullable struct
[InlineData(typeof(double), nameof(WrapperClass<double>.EchoNullable), JsonSchema.Number, true)] // double? (Nullable<double>) is itself non-nullable struct
[InlineData(typeof(string), nameof(WrapperClass<string>.EchoNullable), JsonSchema.String, false)] // T? with reference type is nullable
[InlineData(typeof(int), nameof(WrapperClass<int>.EchoNullable), JsonSchema.Integer, false)] // T? with value type is also nullable (int? becomes int, but T? context is nullable)
[InlineData(typeof(bool), nameof(WrapperClass<bool>.EchoNullable), JsonSchema.Boolean, false)] // T? with value type is also nullable (bool? becomes bool, but T? context is nullable)
[InlineData(typeof(double), nameof(WrapperClass<double>.EchoNullable), JsonSchema.Number, false)] // T? with value type is also nullable (double? becomes double, but T? context is nullable)
public void GetReturnSchema_WrapperEchoPrimitive_ReturnsCorrectSchema(Type genericType, string methodName, string expectedType, bool shouldBeRequired)
{
var wrapperType = typeof(WrapperClass<>).MakeGenericType(genericType);
Expand Down Expand Up @@ -855,8 +864,13 @@ public void GetReturnSchema_WrapperEchoArray_ReturnsCorrectSchema(Type genericTy
}

[Theory]
#if NET5_0_OR_GREATER
[InlineData(typeof(string[]), JsonSchema.String, false)]
[InlineData(typeof(int[]), JsonSchema.Integer, false)]
#else
[InlineData(typeof(string[]), JsonSchema.String, true)]
[InlineData(typeof(int[]), JsonSchema.Integer, true)]
#endif
public void GetReturnSchema_WrapperEchoNullableArray_ReturnsCorrectSchema(Type genericType, string expectedItemType, bool shouldBeRequired)
{
var wrapperType = typeof(WrapperClass<>).MakeGenericType(genericType);
Expand All @@ -868,6 +882,8 @@ public void GetReturnSchema_WrapperEchoNullableArray_ReturnsCorrectSchema(Type g
[Fact]
public void GetReturnSchema_WrapperEchoListComplex_ReturnsCorrectSchema()
{
// WrapperClass<T>.Echo has NullableContextAttribute(1), meaning T is non-nullable
// Therefore, WrapperClass<List<ComplexReturnType>>.Echo should return non-nullable List<ComplexReturnType>
var wrapperType = typeof(WrapperClass<List<ComplexReturnType>>);
var schema = GetWrapperMethodReturnSchema(wrapperType, nameof(WrapperClass<List<ComplexReturnType>>.Echo));
AssertComplexListReturnSchema(schema!, shouldBeRequired: true);
Expand Down
4 changes: 4 additions & 0 deletions ReflectorNet.Tests/SchemaTests/SchemaTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ protected void AssertResultRequired(JsonNode schema)
var required = schema[JsonSchema.Required]!.AsArray();
Assert.Contains(required, r => r?.ToString() == JsonSchema.Result);
}
else
{
Assert.Fail("Schema does not contain a required array");
}
}

/// <summary>
Expand Down
Loading