@@ -15,101 +15,129 @@ namespace Mockolate.Web;
1515public static class AweXpectItExtensions
1616{
1717 /// <inheritdoc cref="ItExtensions" />
18- extension ( It _ )
18+ extension ( ItExtensions . IHttpContentParameter parameter )
1919 {
2020 /// <summary>
21- /// Expects the <see cref="HttpContent" /> parameter to be a JSON content .
21+ /// Expects the <see cref="HttpContent" /> to have a body equal to the given <paramref name="json" /> .
2222 /// </summary>
23- public static IJsonContentParameter IsJsonContent ( )
24- => new JsonContentParameter ( ) ;
25-
26- /// <summary>
27- /// Expects the <see cref="HttpContent" /> parameter to be a JSON content
28- /// with the given <paramref name="mediaType" />.
29- /// </summary>
30- public static IJsonContentParameter IsJsonContent ( string mediaType )
31- => new JsonContentParameter ( ) . WithMediaType ( mediaType ) ;
32- }
33-
34- /// <summary>
35- /// Further expectations on the JSON <see cref="HttpContent" />.
36- /// </summary>
37- public interface IJsonContentParameter : ItExtensions . IHttpContentParameter < IJsonContentParameter >
38- {
39- /// <summary>
40- /// Expects the <see cref="StringContent" /> to have a body equal to the given <paramref name="json" />.
41- /// </summary>
42- IJsonContentBodyParameter WithBody ( string json , JsonDocumentOptions ? options = null ) ;
23+ public IJsonContentBodyParameter WithJson ( string json , JsonDocumentOptions ? options = null )
24+ {
25+ JsonContentParameter jsonContentParameter = new ( parameter ) ;
26+ jsonContentParameter . WithBody ( json , options ) ;
27+ parameter . WithString ( b => jsonContentParameter . Matches ( b ) ) ;
28+ return jsonContentParameter ;
29+ }
4330
4431 /// <summary>
45- /// Expects the <see cref="StringContent " /> to have a JSON body which matches the <paramref name="expected" /> value.
32+ /// Expects the <see cref="HttpContent " /> to have a JSON body which matches the <paramref name="expected" /> value.
4633 /// </summary>
47- IJsonContentBodyParameter WithBodyMatching ( object ? expected , JsonDocumentOptions ? options = null ) ;
34+ public IJsonContentBodyParameter WithJsonMatching ( object ? expected , JsonDocumentOptions ? options = null )
35+ {
36+ JsonContentParameter jsonContentParameter = new ( parameter ) ;
37+ jsonContentParameter . WithBodyMatching ( expected , options ) ;
38+ parameter . WithString ( b => jsonContentParameter . Matches ( b ) ) ;
39+ return jsonContentParameter ;
40+ }
4841
4942 /// <summary>
50- /// Expects the <see cref="StringContent " /> to have a JSON body which matches the <paramref name="expected" /> value.
43+ /// Expects the <see cref="HttpContent " /> to have a JSON body which matches the <paramref name="expected" /> value.
5144 /// </summary>
52- IJsonContentBodyParameter WithBodyMatching < T > ( IEnumerable < T > expected , JsonDocumentOptions ? options = null ) ;
45+ public IJsonContentBodyParameter WithJsonMatching < T > ( IEnumerable < T > expected ,
46+ JsonDocumentOptions ? options = null )
47+ {
48+ JsonContentParameter jsonContentParameter = new ( parameter ) ;
49+ jsonContentParameter . WithBodyMatching ( expected , options ) ;
50+ parameter . WithString ( b => jsonContentParameter . Matches ( b ) ) ;
51+ return jsonContentParameter ;
52+ }
5353 }
5454
5555 /// <summary>
5656 /// Further expectations on the matching of a JSON body of the <see cref="HttpContent" />.
5757 /// </summary>
58- public interface IJsonContentBodyParameter : IJsonContentParameter
58+ public interface IJsonContentBodyParameter : ItExtensions . IHttpContentParameter
5959 {
6060 /// <summary>
6161 /// Ignores additional properties in JSON objects when comparing.
6262 /// </summary>
6363 IJsonContentBodyParameter IgnoringAdditionalProperties ( bool ignoreAdditionalProperties = true ) ;
6464 }
6565
66- private sealed class JsonContentParameter : HttpContentParameter < IJsonContentParameter > , IJsonContentBodyParameter
66+ private sealed class JsonContentParameter : IJsonContentBodyParameter , IParameter
6767 {
68+ private readonly ItExtensions . IHttpContentParameter _parameter ;
69+
6870 private string ? _body ;
6971 private bool _ignoringAdditionalProperties = true ;
7072 private JsonDocumentOptions ? _jsonDocumentOptions ;
7173
72- /// <inheritdoc cref="HttpContentParameter{TParameter}.GetThis" />
73- protected override IJsonContentParameter GetThis => this ;
74-
75- /// <inheritdoc cref="IJsonContentParameter.WithBody(string, JsonDocumentOptions?)" />
76- public IJsonContentBodyParameter WithBody ( string json ,
77- JsonDocumentOptions ? options = null )
74+ public JsonContentParameter ( ItExtensions . IHttpContentParameter parameter )
7875 {
79- _body = json ;
80- _jsonDocumentOptions = options ;
81- return this ;
76+ _parameter = parameter ;
8277 }
8378
84- /// <inheritdoc cref="IJsonContentParameter.WithBodyMatching(object, JsonDocumentOptions?)" />
85- public IJsonContentBodyParameter WithBodyMatching ( object ? expected ,
86- JsonDocumentOptions ? options = null )
87- => WithBody ( JsonSerializer . Serialize ( expected , JsonSerializerOptions . Default ) , options ) ;
88-
89- public IJsonContentBodyParameter WithBodyMatching < T > ( IEnumerable < T > expected ,
90- JsonDocumentOptions ? options = null )
91- => WithBody ( JsonSerializer . Serialize < object > ( expected , JsonSerializerOptions . Default ) , options ) ;
92-
9379 /// <inheritdoc cref="IJsonContentBodyParameter.IgnoringAdditionalProperties(bool)" />
9480 public IJsonContentBodyParameter IgnoringAdditionalProperties ( bool ignoreAdditionalProperties = true )
9581 {
9682 _ignoringAdditionalProperties = ignoreAdditionalProperties ;
9783 return this ;
9884 }
9985
100- protected override bool Matches ( HttpContent value )
101- {
102- if ( ! base . Matches ( value ) )
103- {
104- return false ;
105- }
86+ public IParameter < HttpContent ? > Do ( Action < HttpContent ? > callback )
87+ => _parameter . Do ( callback ) ;
88+
89+ public ItExtensions . IHttpContentHeaderParameter WithHeaders (
90+ params IEnumerable < ( string Name , HttpHeaderValue Value ) > headers )
91+ => _parameter . WithHeaders ( headers ) ;
92+
93+ public ItExtensions . IHttpContentHeaderParameter WithHeaders ( string headers )
94+ => _parameter . WithHeaders ( headers ) ;
95+
96+ public ItExtensions . IHttpContentHeaderParameter WithHeaders ( string name , HttpHeaderValue value )
97+ => _parameter . WithHeaders ( name , value ) ;
98+
99+ public ItExtensions . IHttpContentParameter WithString ( Func < string , bool > predicate )
100+ => _parameter . WithString ( predicate ) ;
101+
102+ public ItExtensions . IStringContentBodyParameter WithString ( string expected )
103+ => _parameter . WithString ( expected ) ;
104+
105+ public ItExtensions . IStringContentBodyMatchingParameter WithStringMatching ( string pattern )
106+ => _parameter . WithStringMatching ( pattern ) ;
107+
108+ public ItExtensions . IHttpContentParameter WithBytes ( byte [ ] bytes )
109+ => _parameter . WithBytes ( bytes ) ;
110+
111+ public ItExtensions . IHttpContentParameter WithBytes ( Func < byte [ ] , bool > predicate )
112+ => _parameter . WithBytes ( predicate ) ;
113+
114+ public ItExtensions . IFormDataContentParameter WithFormData ( string key , HttpFormDataValue value )
115+ => _parameter . WithFormData ( key , value ) ;
116+
117+ public ItExtensions . IFormDataContentParameter WithFormData (
118+ params IEnumerable < ( string Key , HttpFormDataValue Value ) > values )
119+ => _parameter . WithFormData ( values ) ;
120+
121+ public ItExtensions . IFormDataContentParameter WithFormData ( string values )
122+ => _parameter . WithFormData ( values ) ;
123+
124+ public ItExtensions . IHttpContentParameter WithMediaType ( string ? mediaType )
125+ => _parameter . WithMediaType ( mediaType ) ;
126+
127+ public void InvokeCallbacks ( object ? value )
128+ => ( ( IParameter ) _parameter ) . InvokeCallbacks ( value ) ;
106129
130+ public bool Matches ( object ? value )
131+ => ( ( IParameter ) _parameter ) . Matches ( value ) ;
132+
133+ public bool Matches ( string value )
134+ {
107135 if ( _body is not null )
108136 {
109137 try
110138 {
111139 JsonDocumentOptions options = _jsonDocumentOptions ?? GetDefaultOptions ( ) ;
112- using JsonDocument actualDocument = JsonDocument . Parse ( value . ReadAsStream ( ) , options ) ;
140+ using JsonDocument actualDocument = JsonDocument . Parse ( value , options ) ;
113141 using JsonDocument expectedDocument = JsonDocument . Parse ( _body , options ) ;
114142
115143 if ( ! Compare ( actualDocument . RootElement , expectedDocument . RootElement ,
@@ -127,6 +155,21 @@ protected override bool Matches(HttpContent value)
127155 return true ;
128156 }
129157
158+ public void WithBody ( string json ,
159+ JsonDocumentOptions ? options = null )
160+ {
161+ _body = json ;
162+ _jsonDocumentOptions = options ;
163+ }
164+
165+ public void WithBodyMatching ( object ? expected ,
166+ JsonDocumentOptions ? options = null )
167+ => WithBody ( JsonSerializer . Serialize ( expected , JsonSerializerOptions . Default ) , options ) ;
168+
169+ public void WithBodyMatching < T > ( IEnumerable < T > expected ,
170+ JsonDocumentOptions ? options = null )
171+ => WithBody ( JsonSerializer . Serialize < object > ( expected , JsonSerializerOptions . Default ) , options ) ;
172+
130173 private static JsonDocumentOptions GetDefaultOptions ( ) => new ( )
131174 {
132175 AllowTrailingCommas = true ,
@@ -225,60 +268,6 @@ private static bool CompareJsonNumber(JsonElement actualElement, JsonElement exp
225268 return false ;
226269 }
227270 }
228-
229- private abstract class HttpContentParameter < TParameter >
230- : ItExtensions . IHttpContentParameter < TParameter > , IParameter
231- {
232- private List < Action < HttpContent ? > > ? _callbacks ;
233- private string ? _mediaType ;
234-
235- /// <summary>
236- /// Returns <c>this</c> typed as <typeparamref name="TParameter" /> for fluent API.
237- /// </summary>
238- protected abstract TParameter GetThis { get ; }
239-
240- /// <inheritdoc cref="ItExtensions.IHttpContentParameter{TParameter}.WithMediaType(string?)" />
241- public TParameter WithMediaType ( string ? mediaType )
242- {
243- _mediaType = mediaType ;
244- return GetThis ;
245- }
246-
247- /// <inheritdoc cref="IParameter{T}.Do(Action{T})" />
248- public IParameter < HttpContent ? > Do ( Action < HttpContent ? > callback )
249- {
250- _callbacks ??= [ ] ;
251- _callbacks . Add ( callback ) ;
252- return this ;
253- }
254-
255- /// <inheritdoc cref="IParameter.Matches(object?)" />
256- public bool Matches ( object ? value )
257- => value is HttpContent typedValue && Matches ( typedValue ) ;
258-
259- /// <inheritdoc cref="IParameter.InvokeCallbacks(object?)" />
260- public void InvokeCallbacks ( object ? value )
261- {
262- if ( value is HttpContent httpContent )
263- {
264- _callbacks ? . ForEach ( a => a . Invoke ( httpContent ) ) ;
265- }
266- }
267-
268- /// <summary>
269- /// Checks whether the given <see cref="HttpContent" /> <paramref name="value" /> matches the expectations.
270- /// </summary>
271- protected virtual bool Matches ( HttpContent value )
272- {
273- if ( _mediaType is not null &&
274- value . Headers . ContentType ? . MediaType ? . Equals ( _mediaType , StringComparison . OrdinalIgnoreCase ) != true )
275- {
276- return false ;
277- }
278-
279- return true ;
280- }
281- }
282271}
283272#pragma warning restore S2325 // Methods and properties that don't access instance data should be static
284273#endif
0 commit comments