Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend url parameters default formatting #1781

Merged
2 changes: 2 additions & 0 deletions Refit.Tests/API/ApiApprovalTests.Refit.DotNet6_0.verified.txt
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ namespace Refit
public class DefaultUrlParameterFormatter : Refit.IUrlParameterFormatter
{
public DefaultUrlParameterFormatter() { }
public void AddFormat<TParameter>(string format) { }
public void AddFormat<TContainer, TParameter>(string format) { }
public virtual string? Format(object? parameterValue, System.Reflection.ICustomAttributeProvider attributeProvider, System.Type type) { }
}
public class DefaultUrlParameterKeyFormatter : Refit.IUrlParameterKeyFormatter
Expand Down
2 changes: 2 additions & 0 deletions Refit.Tests/API/ApiApprovalTests.Refit.DotNet8_0.verified.txt
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ namespace Refit
public class DefaultUrlParameterFormatter : Refit.IUrlParameterFormatter
{
public DefaultUrlParameterFormatter() { }
public void AddFormat<TParameter>(string format) { }
public void AddFormat<TContainer, TParameter>(string format) { }
public virtual string? Format(object? parameterValue, System.Reflection.ICustomAttributeProvider attributeProvider, System.Type type) { }
}
public class DefaultUrlParameterKeyFormatter : Refit.IUrlParameterKeyFormatter
Expand Down
303 changes: 303 additions & 0 deletions Refit.Tests/DefaultUrlParameterFormatterTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
using System.Globalization;
using System.Reflection;
using Xunit;

namespace Refit.Tests;

public class DefaultUrlParameterFormatterTests
{
class DefaultUrlParameterFormatterTestRequest
{
[Query(Format = "yyyy")] public DateTime? DateTimeWithAttributeFormatYear { get; set; }

public DateTime? DateTime { get; set; }

public IEnumerable<DateTime> DateTimeCollection { get; set; }

public IDictionary<int, DateTime> DateTimeDictionary { get; set; }

public IDictionary<DateTime, int> DateTimeKeyedDictionary { get; set; }
}

[Fact]
public void NullParameterValue_ReturnsNull()
{
var parameters = new DefaultUrlParameterFormatterTestRequest
{
DateTime = null
};

var urlParameterFormatter = new DefaultUrlParameterFormatter();

var output = urlParameterFormatter.Format(
parameters.DateTime,
parameters.GetType().GetProperty(nameof(parameters.DateTime))!,
parameters.GetType());

Assert.Null(output);
}

[Fact]
public void NoFormatters_UseDefaultFormat()
{
var parameters = new DefaultUrlParameterFormatterTestRequest
{
DateTime = new DateTime(2023, 8, 21)
};

var urlParameterFormatter = new DefaultUrlParameterFormatter();

var output = urlParameterFormatter.Format(
parameters.DateTime,
parameters.GetType().GetProperty(nameof(parameters.DateTime))!,
parameters.GetType());

Assert.Equal("08/21/2023 00:00:00", output);
}

[Fact]
public void QueryAttributeFormatOnly_UseQueryAttributeFormat()
{
var parameters = new DefaultUrlParameterFormatterTestRequest
{
DateTimeWithAttributeFormatYear = new DateTime(2023, 8, 21)
};

var urlParameterFormatter = new DefaultUrlParameterFormatter();

var output = urlParameterFormatter.Format(
parameters.DateTimeWithAttributeFormatYear,
parameters.GetType().GetProperty(nameof(parameters.DateTimeWithAttributeFormatYear))!,
parameters.GetType());

Assert.Equal("2023", output);
}

[Fact]
public void QueryAttributeAndGeneralFormat_UseQueryAttributeFormat()
{
var parameters = new DefaultUrlParameterFormatterTestRequest
{
DateTimeWithAttributeFormatYear = new DateTime(2023, 8, 21)
};

var urlParameterFormatter = new DefaultUrlParameterFormatter();
urlParameterFormatter.AddFormat<DateTime>("yyyy-MM-dd");

var output = urlParameterFormatter.Format(
parameters.DateTimeWithAttributeFormatYear,
parameters.GetType().GetProperty(nameof(parameters.DateTimeWithAttributeFormatYear))!,
parameters.GetType());

Assert.Equal("2023", output);
}

[Fact]
public void QueryAttributeAndSpecificFormat_UseQueryAttributeFormat()
{
var parameters = new DefaultUrlParameterFormatterTestRequest
{
DateTimeWithAttributeFormatYear = new DateTime(2023, 8, 21)
};

var urlParameterFormatter = new DefaultUrlParameterFormatter();
urlParameterFormatter.AddFormat<DefaultUrlParameterFormatterTestRequest, DateTime>("yyyy-MM-dd");

var output = urlParameterFormatter.Format(
parameters.DateTimeWithAttributeFormatYear,
parameters.GetType().GetProperty(nameof(parameters.DateTimeWithAttributeFormatYear))!,
parameters.GetType());

Assert.Equal("2023", output);
}

[Fact]
public void AllFormats_UseQueryAttributeFormat()
{
var parameters = new DefaultUrlParameterFormatterTestRequest
{
DateTimeWithAttributeFormatYear = new DateTime(2023, 8, 21)
};

var urlParameterFormatter = new DefaultUrlParameterFormatter();
urlParameterFormatter.AddFormat<DateTime>("yyyy-MM-dd");
urlParameterFormatter.AddFormat<DefaultUrlParameterFormatterTestRequest, DateTime>("yyyy-MM-dd");

var output = urlParameterFormatter.Format(
parameters.DateTimeWithAttributeFormatYear,
parameters.GetType().GetProperty(nameof(parameters.DateTimeWithAttributeFormatYear))!,
parameters.GetType());

Assert.Equal("2023", output);
}

[Fact]
public void GeneralFormatOnly_UseGeneralFormat()
{
var parameters = new DefaultUrlParameterFormatterTestRequest
{
DateTime = new DateTime(2023, 8, 21)
};

var urlParameterFormatter = new DefaultUrlParameterFormatter();
urlParameterFormatter.AddFormat<DateTime>("yyyy");

var output = urlParameterFormatter.Format(
parameters.DateTime,
parameters.GetType().GetProperty(nameof(parameters.DateTime))!,
parameters.GetType());

Assert.Equal("2023", output);
}

[Fact]
public void SpecificFormatOnly_UseSpecificFormat()
{
var parameters = new DefaultUrlParameterFormatterTestRequest
{
DateTime = new DateTime(2023, 8, 21)
};

var urlParameterFormatter = new DefaultUrlParameterFormatter();
urlParameterFormatter.AddFormat<DefaultUrlParameterFormatterTestRequest, DateTime>("yyyy");

var output = urlParameterFormatter.Format(
parameters.DateTime,
parameters.GetType().GetProperty(nameof(parameters.DateTime))!,
parameters.GetType());

Assert.Equal("2023", output);
}

[Fact]
public void GeneralAndSpecificFormats_UseSpecificFormat()
{
var parameters = new DefaultUrlParameterFormatterTestRequest
{
DateTime = new DateTime(2023, 8, 21)
};

var urlParameterFormatter = new DefaultUrlParameterFormatter();
urlParameterFormatter.AddFormat<DateTime>("yyyy-MM-dd");
urlParameterFormatter.AddFormat<DefaultUrlParameterFormatterTestRequest, DateTime>("yyyy");

var output = urlParameterFormatter.Format(
parameters.DateTime,
parameters.GetType().GetProperty(nameof(parameters.DateTime))!,
parameters.GetType());

Assert.Equal("2023", output);
}

[Fact]
public void RequestWithPlainDateTimeQueryParameter_ProducesCorrectQueryString()
{
var urlParameterFormatter = new DefaultUrlParameterFormatter();
urlParameterFormatter.AddFormat<DateTime>("yyyy");

var refitSettings = new RefitSettings { UrlParameterFormatter = urlParameterFormatter };
var fixture = new RequestBuilderImplementation<IDummyHttpApi>(refitSettings);
var factory = fixture.BuildRequestFactoryForMethod(
nameof(IDummyHttpApi.PostWithComplexTypeQuery)
);

var parameters = new DefaultUrlParameterFormatterTestRequest
{
DateTime = new DateTime(2023, 8, 21),
};

var output = factory([parameters]);
var uri = new Uri(new Uri("http://api"), output.RequestUri);

Assert.Equal(
"?DateTime=2023",
uri.Query
);
}

[Fact]
public void RequestWithDateTimeCollectionQueryParameter_ProducesCorrectQueryString()
{
var urlParameterFormatter = new DefaultUrlParameterFormatter();
urlParameterFormatter.AddFormat<DateTime>("yyyy");

var refitSettings = new RefitSettings { UrlParameterFormatter = urlParameterFormatter };
var fixture = new RequestBuilderImplementation<IDummyHttpApi>(refitSettings);
var factory = fixture.BuildRequestFactoryForMethod(
nameof(IDummyHttpApi.PostWithComplexTypeQuery)
);

var parameters = new DefaultUrlParameterFormatterTestRequest
{
DateTimeCollection = [new DateTime(2023, 8, 21), new DateTime(2024, 8, 21)],
};

var output = factory([parameters]);
var uri = new Uri(new Uri("http://api"), output.RequestUri);

Assert.Equal(
"?DateTimeCollection=2023%2C2024",
uri.Query
);
}

[Fact]
public void RequestWithDateTimeDictionaryQueryParameter_ProducesCorrectQueryString()
{
var urlParameterFormatter = new DefaultUrlParameterFormatter();
urlParameterFormatter.AddFormat<DateTime>("yyyy");

var refitSettings = new RefitSettings { UrlParameterFormatter = urlParameterFormatter };
var fixture = new RequestBuilderImplementation<IDummyHttpApi>(refitSettings);
var factory = fixture.BuildRequestFactoryForMethod(
nameof(IDummyHttpApi.PostWithComplexTypeQuery)
);

var parameters = new DefaultUrlParameterFormatterTestRequest
{
DateTimeDictionary = new Dictionary<int, DateTime>
{
{ 1, new DateTime(2023, 8, 21) },
{ 2, new DateTime(2024, 8, 21) },
},
};

var output = factory([parameters]);
var uri = new Uri(new Uri("http://api"), output.RequestUri);

Assert.Equal(
"?DateTimeDictionary.1=2023&DateTimeDictionary.2=2024",
uri.Query
);
}

[Fact]
public void RequestWithDateTimeKeyedDictionaryQueryParameter_ProducesCorrectQueryString()
{
var urlParameterFormatter = new DefaultUrlParameterFormatter();
urlParameterFormatter.AddFormat<DateTime>("yyyy");

var refitSettings = new RefitSettings { UrlParameterFormatter = urlParameterFormatter };
var fixture = new RequestBuilderImplementation<IDummyHttpApi>(refitSettings);
var factory = fixture.BuildRequestFactoryForMethod(
nameof(IDummyHttpApi.PostWithComplexTypeQuery)
);

var parameters = new DefaultUrlParameterFormatterTestRequest
{
DateTimeKeyedDictionary = new Dictionary<DateTime, int>
{
{ new DateTime(2023, 8, 21), 1 },
{ new DateTime(2024, 8, 21), 2 },
},
};

var output = factory([parameters]);
var uri = new Uri(new Uri("http://api"), output.RequestUri);

Assert.Equal(
"?DateTimeKeyedDictionary.2023=1&DateTimeKeyedDictionary.2024=2",
uri.Query
);
}
}
Loading
Loading