Skip to content

Commit 7cfdede

Browse files
Extend url parameters default formatting (#1781)
* 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>
1 parent 5259e08 commit 7cfdede

4 files changed

Lines changed: 380 additions & 31 deletions

File tree

Refit.Tests/API/ApiApprovalTests.Refit.DotNet6_0.verified.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ namespace Refit
119119
public class DefaultUrlParameterFormatter : Refit.IUrlParameterFormatter
120120
{
121121
public DefaultUrlParameterFormatter() { }
122+
public void AddFormat<TParameter>(string format) { }
123+
public void AddFormat<TContainer, TParameter>(string format) { }
122124
public virtual string? Format(object? parameterValue, System.Reflection.ICustomAttributeProvider attributeProvider, System.Type type) { }
123125
}
124126
public class DefaultUrlParameterKeyFormatter : Refit.IUrlParameterKeyFormatter

Refit.Tests/API/ApiApprovalTests.Refit.DotNet8_0.verified.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ namespace Refit
119119
public class DefaultUrlParameterFormatter : Refit.IUrlParameterFormatter
120120
{
121121
public DefaultUrlParameterFormatter() { }
122+
public void AddFormat<TParameter>(string format) { }
123+
public void AddFormat<TContainer, TParameter>(string format) { }
122124
public virtual string? Format(object? parameterValue, System.Reflection.ICustomAttributeProvider attributeProvider, System.Type type) { }
123125
}
124126
public class DefaultUrlParameterKeyFormatter : Refit.IUrlParameterKeyFormatter
Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
using System.Globalization;
2+
using System.Reflection;
3+
using Xunit;
4+
5+
namespace Refit.Tests;
6+
7+
public class DefaultUrlParameterFormatterTests
8+
{
9+
class DefaultUrlParameterFormatterTestRequest
10+
{
11+
[Query(Format = "yyyy")] public DateTime? DateTimeWithAttributeFormatYear { get; set; }
12+
13+
public DateTime? DateTime { get; set; }
14+
15+
public IEnumerable<DateTime> DateTimeCollection { get; set; }
16+
17+
public IDictionary<int, DateTime> DateTimeDictionary { get; set; }
18+
19+
public IDictionary<DateTime, int> DateTimeKeyedDictionary { get; set; }
20+
}
21+
22+
[Fact]
23+
public void NullParameterValue_ReturnsNull()
24+
{
25+
var parameters = new DefaultUrlParameterFormatterTestRequest
26+
{
27+
DateTime = null
28+
};
29+
30+
var urlParameterFormatter = new DefaultUrlParameterFormatter();
31+
32+
var output = urlParameterFormatter.Format(
33+
parameters.DateTime,
34+
parameters.GetType().GetProperty(nameof(parameters.DateTime))!,
35+
parameters.GetType());
36+
37+
Assert.Null(output);
38+
}
39+
40+
[Fact]
41+
public void NoFormatters_UseDefaultFormat()
42+
{
43+
var parameters = new DefaultUrlParameterFormatterTestRequest
44+
{
45+
DateTime = new DateTime(2023, 8, 21)
46+
};
47+
48+
var urlParameterFormatter = new DefaultUrlParameterFormatter();
49+
50+
var output = urlParameterFormatter.Format(
51+
parameters.DateTime,
52+
parameters.GetType().GetProperty(nameof(parameters.DateTime))!,
53+
parameters.GetType());
54+
55+
Assert.Equal("08/21/2023 00:00:00", output);
56+
}
57+
58+
[Fact]
59+
public void QueryAttributeFormatOnly_UseQueryAttributeFormat()
60+
{
61+
var parameters = new DefaultUrlParameterFormatterTestRequest
62+
{
63+
DateTimeWithAttributeFormatYear = new DateTime(2023, 8, 21)
64+
};
65+
66+
var urlParameterFormatter = new DefaultUrlParameterFormatter();
67+
68+
var output = urlParameterFormatter.Format(
69+
parameters.DateTimeWithAttributeFormatYear,
70+
parameters.GetType().GetProperty(nameof(parameters.DateTimeWithAttributeFormatYear))!,
71+
parameters.GetType());
72+
73+
Assert.Equal("2023", output);
74+
}
75+
76+
[Fact]
77+
public void QueryAttributeAndGeneralFormat_UseQueryAttributeFormat()
78+
{
79+
var parameters = new DefaultUrlParameterFormatterTestRequest
80+
{
81+
DateTimeWithAttributeFormatYear = new DateTime(2023, 8, 21)
82+
};
83+
84+
var urlParameterFormatter = new DefaultUrlParameterFormatter();
85+
urlParameterFormatter.AddFormat<DateTime>("yyyy-MM-dd");
86+
87+
var output = urlParameterFormatter.Format(
88+
parameters.DateTimeWithAttributeFormatYear,
89+
parameters.GetType().GetProperty(nameof(parameters.DateTimeWithAttributeFormatYear))!,
90+
parameters.GetType());
91+
92+
Assert.Equal("2023", output);
93+
}
94+
95+
[Fact]
96+
public void QueryAttributeAndSpecificFormat_UseQueryAttributeFormat()
97+
{
98+
var parameters = new DefaultUrlParameterFormatterTestRequest
99+
{
100+
DateTimeWithAttributeFormatYear = new DateTime(2023, 8, 21)
101+
};
102+
103+
var urlParameterFormatter = new DefaultUrlParameterFormatter();
104+
urlParameterFormatter.AddFormat<DefaultUrlParameterFormatterTestRequest, DateTime>("yyyy-MM-dd");
105+
106+
var output = urlParameterFormatter.Format(
107+
parameters.DateTimeWithAttributeFormatYear,
108+
parameters.GetType().GetProperty(nameof(parameters.DateTimeWithAttributeFormatYear))!,
109+
parameters.GetType());
110+
111+
Assert.Equal("2023", output);
112+
}
113+
114+
[Fact]
115+
public void AllFormats_UseQueryAttributeFormat()
116+
{
117+
var parameters = new DefaultUrlParameterFormatterTestRequest
118+
{
119+
DateTimeWithAttributeFormatYear = new DateTime(2023, 8, 21)
120+
};
121+
122+
var urlParameterFormatter = new DefaultUrlParameterFormatter();
123+
urlParameterFormatter.AddFormat<DateTime>("yyyy-MM-dd");
124+
urlParameterFormatter.AddFormat<DefaultUrlParameterFormatterTestRequest, DateTime>("yyyy-MM-dd");
125+
126+
var output = urlParameterFormatter.Format(
127+
parameters.DateTimeWithAttributeFormatYear,
128+
parameters.GetType().GetProperty(nameof(parameters.DateTimeWithAttributeFormatYear))!,
129+
parameters.GetType());
130+
131+
Assert.Equal("2023", output);
132+
}
133+
134+
[Fact]
135+
public void GeneralFormatOnly_UseGeneralFormat()
136+
{
137+
var parameters = new DefaultUrlParameterFormatterTestRequest
138+
{
139+
DateTime = new DateTime(2023, 8, 21)
140+
};
141+
142+
var urlParameterFormatter = new DefaultUrlParameterFormatter();
143+
urlParameterFormatter.AddFormat<DateTime>("yyyy");
144+
145+
var output = urlParameterFormatter.Format(
146+
parameters.DateTime,
147+
parameters.GetType().GetProperty(nameof(parameters.DateTime))!,
148+
parameters.GetType());
149+
150+
Assert.Equal("2023", output);
151+
}
152+
153+
[Fact]
154+
public void SpecificFormatOnly_UseSpecificFormat()
155+
{
156+
var parameters = new DefaultUrlParameterFormatterTestRequest
157+
{
158+
DateTime = new DateTime(2023, 8, 21)
159+
};
160+
161+
var urlParameterFormatter = new DefaultUrlParameterFormatter();
162+
urlParameterFormatter.AddFormat<DefaultUrlParameterFormatterTestRequest, DateTime>("yyyy");
163+
164+
var output = urlParameterFormatter.Format(
165+
parameters.DateTime,
166+
parameters.GetType().GetProperty(nameof(parameters.DateTime))!,
167+
parameters.GetType());
168+
169+
Assert.Equal("2023", output);
170+
}
171+
172+
[Fact]
173+
public void GeneralAndSpecificFormats_UseSpecificFormat()
174+
{
175+
var parameters = new DefaultUrlParameterFormatterTestRequest
176+
{
177+
DateTime = new DateTime(2023, 8, 21)
178+
};
179+
180+
var urlParameterFormatter = new DefaultUrlParameterFormatter();
181+
urlParameterFormatter.AddFormat<DateTime>("yyyy-MM-dd");
182+
urlParameterFormatter.AddFormat<DefaultUrlParameterFormatterTestRequest, DateTime>("yyyy");
183+
184+
var output = urlParameterFormatter.Format(
185+
parameters.DateTime,
186+
parameters.GetType().GetProperty(nameof(parameters.DateTime))!,
187+
parameters.GetType());
188+
189+
Assert.Equal("2023", output);
190+
}
191+
192+
[Fact]
193+
public void RequestWithPlainDateTimeQueryParameter_ProducesCorrectQueryString()
194+
{
195+
var urlParameterFormatter = new DefaultUrlParameterFormatter();
196+
urlParameterFormatter.AddFormat<DateTime>("yyyy");
197+
198+
var refitSettings = new RefitSettings { UrlParameterFormatter = urlParameterFormatter };
199+
var fixture = new RequestBuilderImplementation<IDummyHttpApi>(refitSettings);
200+
var factory = fixture.BuildRequestFactoryForMethod(
201+
nameof(IDummyHttpApi.PostWithComplexTypeQuery)
202+
);
203+
204+
var parameters = new DefaultUrlParameterFormatterTestRequest
205+
{
206+
DateTime = new DateTime(2023, 8, 21),
207+
};
208+
209+
var output = factory([parameters]);
210+
var uri = new Uri(new Uri("http://api"), output.RequestUri);
211+
212+
Assert.Equal(
213+
"?DateTime=2023",
214+
uri.Query
215+
);
216+
}
217+
218+
[Fact]
219+
public void RequestWithDateTimeCollectionQueryParameter_ProducesCorrectQueryString()
220+
{
221+
var urlParameterFormatter = new DefaultUrlParameterFormatter();
222+
urlParameterFormatter.AddFormat<DateTime>("yyyy");
223+
224+
var refitSettings = new RefitSettings { UrlParameterFormatter = urlParameterFormatter };
225+
var fixture = new RequestBuilderImplementation<IDummyHttpApi>(refitSettings);
226+
var factory = fixture.BuildRequestFactoryForMethod(
227+
nameof(IDummyHttpApi.PostWithComplexTypeQuery)
228+
);
229+
230+
var parameters = new DefaultUrlParameterFormatterTestRequest
231+
{
232+
DateTimeCollection = [new DateTime(2023, 8, 21), new DateTime(2024, 8, 21)],
233+
};
234+
235+
var output = factory([parameters]);
236+
var uri = new Uri(new Uri("http://api"), output.RequestUri);
237+
238+
Assert.Equal(
239+
"?DateTimeCollection=2023%2C2024",
240+
uri.Query
241+
);
242+
}
243+
244+
[Fact]
245+
public void RequestWithDateTimeDictionaryQueryParameter_ProducesCorrectQueryString()
246+
{
247+
var urlParameterFormatter = new DefaultUrlParameterFormatter();
248+
urlParameterFormatter.AddFormat<DateTime>("yyyy");
249+
250+
var refitSettings = new RefitSettings { UrlParameterFormatter = urlParameterFormatter };
251+
var fixture = new RequestBuilderImplementation<IDummyHttpApi>(refitSettings);
252+
var factory = fixture.BuildRequestFactoryForMethod(
253+
nameof(IDummyHttpApi.PostWithComplexTypeQuery)
254+
);
255+
256+
var parameters = new DefaultUrlParameterFormatterTestRequest
257+
{
258+
DateTimeDictionary = new Dictionary<int, DateTime>
259+
{
260+
{ 1, new DateTime(2023, 8, 21) },
261+
{ 2, new DateTime(2024, 8, 21) },
262+
},
263+
};
264+
265+
var output = factory([parameters]);
266+
var uri = new Uri(new Uri("http://api"), output.RequestUri);
267+
268+
Assert.Equal(
269+
"?DateTimeDictionary.1=2023&DateTimeDictionary.2=2024",
270+
uri.Query
271+
);
272+
}
273+
274+
[Fact]
275+
public void RequestWithDateTimeKeyedDictionaryQueryParameter_ProducesCorrectQueryString()
276+
{
277+
var urlParameterFormatter = new DefaultUrlParameterFormatter();
278+
urlParameterFormatter.AddFormat<DateTime>("yyyy");
279+
280+
var refitSettings = new RefitSettings { UrlParameterFormatter = urlParameterFormatter };
281+
var fixture = new RequestBuilderImplementation<IDummyHttpApi>(refitSettings);
282+
var factory = fixture.BuildRequestFactoryForMethod(
283+
nameof(IDummyHttpApi.PostWithComplexTypeQuery)
284+
);
285+
286+
var parameters = new DefaultUrlParameterFormatterTestRequest
287+
{
288+
DateTimeKeyedDictionary = new Dictionary<DateTime, int>
289+
{
290+
{ new DateTime(2023, 8, 21), 1 },
291+
{ new DateTime(2024, 8, 21), 2 },
292+
},
293+
};
294+
295+
var output = factory([parameters]);
296+
var uri = new Uri(new Uri("http://api"), output.RequestUri);
297+
298+
Assert.Equal(
299+
"?DateTimeKeyedDictionary.2023=1&DateTimeKeyedDictionary.2024=2",
300+
uri.Query
301+
);
302+
}
303+
}

0 commit comments

Comments
 (0)