Skip to content

Commit

Permalink
Extend url parameters default formatting (#1781)
Browse files Browse the repository at this point in the history
* Refactor DefaultUrlParameterFormatter

* Extend URL parameters formatting through DefaultUrlParameterFormatter

* Add DefaultUrlParameterFormatterTests

* Rename DefaultUrlParameterFormatterTests test methods

* Union DefaultUrlParameterFormatterTestRequest

* Update API

* Add DefaultUrlParameterFormatter tests with URI building

---------

Co-authored-by: Chris Pulman <chris.pulman@yahoo.com>
  • Loading branch information
MikeAmputer and ChrisPulman authored Aug 17, 2024
1 parent 5259e08 commit 7cfdede
Show file tree
Hide file tree
Showing 4 changed files with 380 additions and 31 deletions.
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

0 comments on commit 7cfdede

Please sign in to comment.