Skip to content

Commit

Permalink
Fix schema generation for C# 9 positional record with no example (#2901)
Browse files Browse the repository at this point in the history
* Add schema filter test for when example tag is not present

* Add datetime to schema filter example tag positive test

* Fix missing example property on record xmldoc param tag causing unexpected empty example string in generated schema
  • Loading branch information
stb-co authored May 16, 2024
1 parent 828b7df commit 76ec39d
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ private void ApplyMemberTags(OpenApiSchema schema, SchemaFilterContext context)
schema.Description = XmlCommentsTextHelper.Humanize(summaryNode);

var example = recordDefaultConstructorProperty.GetAttribute("example", string.Empty);
TrySetExample(schema, context, example);
if (!string.IsNullOrEmpty(example))
{
TrySetExample(schema, context, example);
}
}

if (fieldOrPropertyNode != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
namespace Swashbuckle.AspNetCore.SwaggerGen.Test
{
/// <summary>
/// Summary for XmlAnnotatedType
/// Summary for XmlAnnotatedRecord
/// </summary>
/// <param name="BoolProperty" example="true">Summary for BoolProperty</param>
/// <param name="IntProperty" example="10">Summary for IntProperty</param>
/// <param name="LongProperty" example="4294967295">Summary for LongProperty</param>
/// <param name="FloatProperty" example="1.2">Summary for FloatProperty</param>
/// <param name="DoubleProperty" example="1.25">Summary for DoubleProperty</param>
/// <param name="DateTimeProperty" example="6/22/2022 12:00:00 AM">Summary for DateTimeProperty</param>
/// <param name="EnumProperty" example="2">Summary for EnumProperty</param>
/// <param name="GuidProperty" example="d3966535-2637-48fa-b911-e3c27405ee09">Summary for GuidProperty</param>
/// <param name="StringPropertyWithNullExample" example="null">Summary for Nullable StringPropertyWithNullExample</param>
Expand All @@ -23,6 +24,7 @@ public record XmlAnnotatedRecord(
long LongProperty,
float FloatProperty,
double DoubleProperty,
DateTime DateTimeProperty,
IntEnum EnumProperty,
Guid GuidProperty,
string StringPropertyWithNullExample,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using Swashbuckle.AspNetCore.TestSupport;

namespace Swashbuckle.AspNetCore.SwaggerGen.Test
{
/// <summary>
/// Summary for XmlAnnotatedRecordWithoutExample
/// </summary>
/// <param name="BoolProperty">Summary for BoolProperty</param>
/// <param name="IntProperty">Summary for IntProperty</param>
/// <param name="LongProperty">Summary for LongProperty</param>
/// <param name="FloatProperty">Summary for FloatProperty</param>
/// <param name="DoubleProperty">Summary for DoubleProperty</param>
/// <param name="DateTimeProperty">Summary for DateTimeProperty</param>
/// <param name="EnumProperty">Summary for EnumProperty</param>
/// <param name="GuidProperty">Summary for GuidProperty</param>
/// <param name="StringPropertyWithNullExample">Summary for Nullable StringPropertyWithNullExample</param>
/// <param name="StringProperty">Summary for StringProperty</param>
/// <param name="StringPropertyWithUri">Summary for StringPropertyWithUri</param>
/// <param name="ObjectProperty">Summary for ObjectProperty</param>
public record XmlAnnotatedRecordWithoutExample(
bool BoolProperty,
int IntProperty,
long LongProperty,
float FloatProperty,
double DoubleProperty,
DateTime DateTimeProperty,
IntEnum EnumProperty,
Guid GuidProperty,
string StringPropertyWithNullExample,
string StringProperty,
string StringPropertyWithUri,
object ObjectProperty
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ public class XmlAnnotatedType
/// <example>1.25</example>
public double DoubleProperty { get; set; }

/// <summary>
/// Summary for DateTimeProperty
/// </summary>
/// <example>6/22/2022 12:00:00 AM</example>
public DateTime DateTimeProperty { get; set; }

/// <summary>
/// Summary for EnumProperty
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using Swashbuckle.AspNetCore.TestSupport;

namespace Swashbuckle.AspNetCore.SwaggerGen.Test
{
/// <summary>
/// Summary for XmlAnnotatedTypeWithoutExample
/// </summary>
public class XmlAnnotatedTypeWithoutExample
{
/// <summary>
/// Summary for BoolProperty
/// </summary>
public bool BoolProperty { get; set; }

/// <summary>
/// Summary for IntProperty
/// </summary>
public int IntProperty { get; set; }

/// <summary>
/// Summary for LongProperty
/// </summary>
public long LongProperty { get; set; }

/// <summary>
/// Summary for FloatProperty
/// </summary>
public float FloatProperty { get; set; }

/// <summary>
/// Summary for DoubleProperty
/// </summary>
public double DoubleProperty { get; set; }

/// <summary>
/// Summary for DateTimeProperty
/// </summary>
public DateTime DateTimeProperty { get; set; }

/// <summary>
/// Summary for EnumProperty
/// </summary>
public IntEnum EnumProperty { get; set; }

/// <summary>
/// Summary for GuidProperty
/// </summary>
public Guid GuidProperty { get; set; }

/// <summary>
/// Summary for Nullable StringPropertyWithNullExample
/// </summary>
public string StringPropertyWithNullExample { get; set; }

/// <summary>
/// Summary for StringProperty
/// </summary>
public string StringProperty { get; set; }

/// <summary>
/// Summary for StringPropertyWithUri
/// </summary>
public string StringPropertyWithUri { get; set; }

/// <summary>
/// Summary for ObjectProperty
/// </summary>
public object ObjectProperty { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public void Apply_SetsDescription_FromPropertySummaryTag(
[InlineData(typeof(XmlAnnotatedType), nameof(XmlAnnotatedType.LongProperty), "integer", "4294967295")]
[InlineData(typeof(XmlAnnotatedType), nameof(XmlAnnotatedType.FloatProperty), "number", "1.2")]
[InlineData(typeof(XmlAnnotatedType), nameof(XmlAnnotatedType.DoubleProperty), "number", "1.25")]
[InlineData(typeof(XmlAnnotatedType), nameof(XmlAnnotatedType.DateTimeProperty), "string", "\"6/22/2022 12:00:00 AM\"")]
[InlineData(typeof(XmlAnnotatedType), nameof(XmlAnnotatedType.EnumProperty), "integer", "2")]
[InlineData(typeof(XmlAnnotatedType), nameof(XmlAnnotatedType.GuidProperty), "string", "\"d3966535-2637-48fa-b911-e3c27405ee09\"")]
[InlineData(typeof(XmlAnnotatedType), nameof(XmlAnnotatedType.StringProperty), "string", "\"Example for StringProperty\"")]
Expand All @@ -73,6 +74,7 @@ public void Apply_SetsDescription_FromPropertySummaryTag(
[InlineData(typeof(XmlAnnotatedRecord), nameof(XmlAnnotatedRecord.LongProperty), "integer", "4294967295")]
[InlineData(typeof(XmlAnnotatedRecord), nameof(XmlAnnotatedRecord.FloatProperty), "number", "1.2")]
[InlineData(typeof(XmlAnnotatedRecord), nameof(XmlAnnotatedRecord.DoubleProperty), "number", "1.25")]
[InlineData(typeof(XmlAnnotatedRecord), nameof(XmlAnnotatedRecord.DateTimeProperty), "string", "\"6/22/2022 12:00:00 AM\"")]
[InlineData(typeof(XmlAnnotatedRecord), nameof(XmlAnnotatedRecord.EnumProperty), "integer", "2")]
[InlineData(typeof(XmlAnnotatedRecord), nameof(XmlAnnotatedRecord.GuidProperty), "string", "\"d3966535-2637-48fa-b911-e3c27405ee09\"")]
[InlineData(typeof(XmlAnnotatedRecord), nameof(XmlAnnotatedRecord.StringProperty), "string", "\"Example for StringProperty\"")]
Expand All @@ -96,6 +98,46 @@ public void Apply_SetsExample_FromPropertyExampleTag(
Assert.Equal(expectedExampleAsJson, schema.Example.ToJson());
}

[Theory]
[InlineData(typeof(XmlAnnotatedTypeWithoutExample), nameof(XmlAnnotatedTypeWithoutExample.BoolProperty), "boolean")]
[InlineData(typeof(XmlAnnotatedTypeWithoutExample), nameof(XmlAnnotatedTypeWithoutExample.IntProperty), "integer")]
[InlineData(typeof(XmlAnnotatedTypeWithoutExample), nameof(XmlAnnotatedTypeWithoutExample.LongProperty), "integer")]
[InlineData(typeof(XmlAnnotatedTypeWithoutExample), nameof(XmlAnnotatedTypeWithoutExample.FloatProperty), "number")]
[InlineData(typeof(XmlAnnotatedTypeWithoutExample), nameof(XmlAnnotatedTypeWithoutExample.DoubleProperty), "number")]
[InlineData(typeof(XmlAnnotatedTypeWithoutExample), nameof(XmlAnnotatedTypeWithoutExample.DateTimeProperty), "string")]
[InlineData(typeof(XmlAnnotatedTypeWithoutExample), nameof(XmlAnnotatedTypeWithoutExample.EnumProperty), "integer")]
[InlineData(typeof(XmlAnnotatedTypeWithoutExample), nameof(XmlAnnotatedTypeWithoutExample.GuidProperty), "string")]
[InlineData(typeof(XmlAnnotatedTypeWithoutExample), nameof(XmlAnnotatedTypeWithoutExample.StringProperty), "string")]
[InlineData(typeof(XmlAnnotatedTypeWithoutExample), nameof(XmlAnnotatedTypeWithoutExample.ObjectProperty), "object")]
[InlineData(typeof(XmlAnnotatedTypeWithoutExample), nameof(XmlAnnotatedTypeWithoutExample.StringPropertyWithNullExample), "string")]
[InlineData(typeof(XmlAnnotatedTypeWithoutExample), nameof(XmlAnnotatedTypeWithoutExample.StringPropertyWithUri), "string")]
[InlineData(typeof(XmlAnnotatedRecordWithoutExample), nameof(XmlAnnotatedRecordWithoutExample.BoolProperty), "boolean")]
[InlineData(typeof(XmlAnnotatedRecordWithoutExample), nameof(XmlAnnotatedRecordWithoutExample.IntProperty), "integer")]
[InlineData(typeof(XmlAnnotatedRecordWithoutExample), nameof(XmlAnnotatedRecordWithoutExample.LongProperty), "integer")]
[InlineData(typeof(XmlAnnotatedRecordWithoutExample), nameof(XmlAnnotatedRecordWithoutExample.FloatProperty), "number")]
[InlineData(typeof(XmlAnnotatedRecordWithoutExample), nameof(XmlAnnotatedRecordWithoutExample.DoubleProperty), "number")]
[InlineData(typeof(XmlAnnotatedRecordWithoutExample), nameof(XmlAnnotatedRecordWithoutExample.DateTimeProperty), "string")]
[InlineData(typeof(XmlAnnotatedRecordWithoutExample), nameof(XmlAnnotatedRecordWithoutExample.EnumProperty), "integer")]
[InlineData(typeof(XmlAnnotatedRecordWithoutExample), nameof(XmlAnnotatedRecordWithoutExample.GuidProperty), "string")]
[InlineData(typeof(XmlAnnotatedRecordWithoutExample), nameof(XmlAnnotatedRecordWithoutExample.StringProperty), "string")]
[InlineData(typeof(XmlAnnotatedRecordWithoutExample), nameof(XmlAnnotatedRecordWithoutExample.ObjectProperty), "object")]
[InlineData(typeof(XmlAnnotatedRecordWithoutExample), nameof(XmlAnnotatedRecordWithoutExample.StringPropertyWithNullExample), "string")]
[InlineData(typeof(XmlAnnotatedRecordWithoutExample), nameof(XmlAnnotatedRecordWithoutExample.StringPropertyWithUri), "string")]
[UseInvariantCulture]
public void Apply_DoesNotSetExample_WhenPropertyExampleTagIsNotProvided(
Type declaringType,
string propertyName,
string schemaType)
{
var propertyInfo = declaringType.GetProperty(propertyName);
var schema = new OpenApiSchema { Type = schemaType };
var filterContext = new SchemaFilterContext(propertyInfo.PropertyType, null, null, memberInfo: propertyInfo);

Subject().Apply(schema, filterContext);

Assert.Null(schema.Example);
}

[Theory]
[InlineData("en-US", 1.2F)]
[InlineData("sv-SE", 1.2F)]
Expand Down

0 comments on commit 76ec39d

Please sign in to comment.