6
6
7
7
use Symfony \Component \HttpClient \DataCollector \HttpClientDataCollector ;
8
8
use Symfony \Component \VarDumper \Cloner \Data ;
9
+ use function array_change_key_case ;
10
+ use function array_intersect_key ;
9
11
use function array_key_exists ;
10
- use function is_string ;
12
+ use function in_array ;
13
+ use function is_array ;
14
+ use function is_object ;
15
+ use function method_exists ;
16
+ use function sprintf ;
11
17
12
18
trait HttpClientAssertionsTrait
13
19
{
@@ -31,104 +37,51 @@ trait HttpClientAssertionsTrait
31
37
* @param array<string,string|string[]> $expectedHeaders
32
38
*/
33
39
public function assertHttpClientRequest (
34
- string $ expectedUrl ,
35
- string $ expectedMethod = 'GET ' ,
36
- string |array |null $ expectedBody = null ,
37
- array $ expectedHeaders = [],
38
- string $ httpClientId = 'http_client ' ,
40
+ string $ expectedUrl ,
41
+ string $ expectedMethod = 'GET ' ,
42
+ string |array |null $ expectedBody = null ,
43
+ array $ expectedHeaders = [],
44
+ string $ httpClientId = 'http_client ' ,
39
45
): void {
40
- $ httpClientCollector = $ this ->grabHttpClientCollector (__FUNCTION__ );
41
-
42
- /**
43
- * @var array<string, array{traces: list<array{
44
- * info: array{url: string},
45
- * url: string,
46
- * method: string,
47
- * options: array{body: mixed, json: mixed, headers?: mixed}
48
- * }>} > $clients
49
- */
50
- $ clients = $ httpClientCollector ->getClients ();
51
-
52
- if (!array_key_exists ($ httpClientId , $ clients )) {
53
- $ this ->fail (sprintf ('HttpClient "%s" is not registered. ' , $ httpClientId ));
54
- }
55
-
56
- /**
57
- * @var list<array{
58
- * info: array{url: string},
59
- * url: string,
60
- * method: string,
61
- * options: array{body: mixed, json: mixed, headers?: mixed}
62
- * }> $traces
63
- */
64
- $ traces = $ clients [$ httpClientId ]['traces ' ];
65
-
66
- $ expectedRequestHasBeenFound = false ;
46
+ $ traces = $ this ->getHttpClientTraces ($ httpClientId , __FUNCTION__ );
47
+ $ requestFound = false ;
67
48
68
49
foreach ($ traces as $ trace ) {
69
- if (($ expectedUrl !== $ trace ['info ' ]['url ' ] && $ expectedUrl !== $ trace ['url ' ])
70
- || $ expectedMethod !== $ trace ['method ' ]
71
- ) {
50
+ if (!$ this ->matchesUrlAndMethod ($ trace , $ expectedUrl , $ expectedMethod )) {
72
51
continue ;
73
52
}
74
53
75
- if ($ expectedBody !== null ) {
76
- $ actualBody = null ;
77
-
78
- if (isset ($ trace ['options ' ]['body ' ]) && !isset ($ trace ['options ' ]['json ' ])) {
79
- $ body = $ trace ['options ' ]['body ' ];
80
- $ actualBody = is_string ($ body )
81
- ? $ body
82
- : ($ body instanceof Data ? $ body ->getValue (true ) : null );
83
- }
54
+ $ rawOptions = $ trace ['options ' ] ?? [];
84
55
85
- if (!isset ($ trace ['options ' ]['body ' ]) && isset ($ trace ['options ' ]['json ' ])) {
86
- $ json = $ trace ['options ' ]['json ' ];
87
- $ actualBody = is_string ($ json )
88
- ? $ json
89
- : ($ json instanceof Data ? $ json ->getValue (true ) : null );
90
- }
91
-
92
- if ($ actualBody === null || $ expectedBody !== $ actualBody ) {
56
+ if ($ expectedBody !== null ) {
57
+ $ actualBody = $ this ->extractValue (
58
+ $ rawOptions ['body ' ] ?? $ rawOptions ['json ' ] ?? null
59
+ );
60
+ if ($ expectedBody !== $ actualBody ) {
93
61
continue ;
94
62
}
95
-
96
- if ($ expectedHeaders === []) {
97
- $ expectedRequestHasBeenFound = true ;
98
- break ;
99
- }
100
63
}
101
64
102
65
if ($ expectedHeaders !== []) {
103
- /**
104
- * @var array<string, mixed> $actualHeaders
105
- */
106
- $ actualHeaders = $ trace ['options ' ]['headers ' ] ?? [];
107
-
108
- foreach ($ actualHeaders as $ headerKey => $ actualHeaderValue ) {
109
- if (!array_key_exists ($ headerKey , $ expectedHeaders )) {
110
- continue ;
111
- }
112
-
113
- $ actualHeaderValue = is_object ($ actualHeaderValue ) && method_exists ($ actualHeaderValue , 'getValue ' )
114
- ? $ actualHeaderValue ->getValue (true )
115
- : $ actualHeaderValue ;
116
-
117
- if ($ expectedHeaders [$ headerKey ] === $ actualHeaderValue ) {
118
- $ expectedRequestHasBeenFound = true ;
119
- break 2 ;
120
- }
66
+ $ rawHeaders = $ rawOptions ['headers ' ] ?? [];
67
+ $ actualHeaders = $ this ->extractValue ($ rawHeaders );
68
+ if (!is_array ($ actualHeaders )) {
69
+ continue ;
121
70
}
122
- }
123
71
124
- if ($ expectedBody === null && $ expectedHeaders === []) {
125
- $ expectedRequestHasBeenFound = true ;
126
- break ;
72
+ $ expected = array_change_key_case ($ expectedHeaders );
73
+ $ actual = array_change_key_case ($ actualHeaders );
74
+ if ($ expected !== array_intersect_key ($ actual , $ expected )) {
75
+ continue ;
76
+ }
127
77
}
78
+
79
+ $ requestFound = true ;
80
+ break ;
128
81
}
129
82
130
83
$ this ->assertTrue (
131
- $ expectedRequestHasBeenFound ,
84
+ $ requestFound ,
132
85
sprintf ('The expected request has not been called: "%s" - "%s" ' , $ expectedMethod , $ expectedUrl )
133
86
);
134
87
}
@@ -146,18 +99,8 @@ public function assertHttpClientRequestCount(
146
99
int $ count ,
147
100
string $ httpClientId = 'http_client ' ,
148
101
): void {
149
- $ httpClientCollector = $ this ->grabHttpClientCollector (__FUNCTION__ );
150
-
151
- /**
152
- * @var array<string, array{traces: list<mixed>}> $clients
153
- */
154
- $ clients = $ httpClientCollector ->getClients ();
155
-
156
- if (!array_key_exists ($ httpClientId , $ clients )) {
157
- $ this ->fail (sprintf ('HttpClient "%s" is not registered. ' , $ httpClientId ));
158
- }
159
-
160
- $ this ->assertCount ($ count , $ clients [$ httpClientId ]['traces ' ]);
102
+ $ traces = $ this ->getHttpClientTraces ($ httpClientId , __FUNCTION__ );
103
+ $ this ->assertCount ($ count , $ traces );
161
104
}
162
105
163
106
/**
@@ -173,32 +116,60 @@ public function assertNotHttpClientRequest(
173
116
string $ expectedMethod = 'GET ' ,
174
117
string $ httpClientId = 'http_client ' ,
175
118
): void {
176
- $ httpClientCollector = $ this ->grabHttpClientCollector (__FUNCTION__ );
119
+ $ traces = $ this ->getHttpClientTraces ($ httpClientId , __FUNCTION__ );
120
+
121
+ foreach ($ traces as $ trace ) {
122
+ if ($ this ->matchesUrlAndMethod ($ trace , $ unexpectedUrl , $ expectedMethod )) {
123
+ $ this ->fail (sprintf ('Unexpected URL called: "%s" - "%s" ' , $ expectedMethod , $ unexpectedUrl ));
124
+ }
125
+ }
177
126
178
- /**
179
- * @var array<string, array{traces: list<array{info: array{url: string}, url: string, method: string}>}> $clients
127
+ $ this ->assertTrue (true , 'The unexpected request was not made. ' );
128
+ }
129
+
130
+ /**
131
+ * @return list<array{
132
+ * info: array{url: string},
133
+ * url: string,
134
+ * method: string,
135
+ * options?: array{body?: mixed, json?: mixed, headers?: mixed}
136
+ * }>
137
+ */
138
+ private function getHttpClientTraces (string $ httpClientId , string $ function ): array
139
+ {
140
+ $ httpClientCollector = $ this ->grabHttpClientCollector ($ function );
141
+
142
+ /** @var array<string, array{traces: list<array{
143
+ * info: array{url: string},
144
+ * url: string,
145
+ * method: string,
146
+ * options?: array{body?: mixed, json?: mixed, headers?: mixed}
147
+ * }>}> $clients
180
148
*/
181
149
$ clients = $ httpClientCollector ->getClients ();
182
150
183
151
if (!array_key_exists ($ httpClientId , $ clients )) {
184
152
$ this ->fail (sprintf ('HttpClient "%s" is not registered. ' , $ httpClientId ));
185
153
}
186
154
187
- $ unexpectedUrlHasBeenFound = false ;
155
+ return $ clients [$ httpClientId ]['traces ' ];
156
+ }
188
157
189
- foreach ($ clients [$ httpClientId ]['traces ' ] as $ trace ) {
190
- if (($ unexpectedUrl === $ trace ['info ' ]['url ' ] || $ unexpectedUrl === $ trace ['url ' ])
191
- && $ expectedMethod === $ trace ['method ' ]
192
- ) {
193
- $ unexpectedUrlHasBeenFound = true ;
194
- break ;
195
- }
196
- }
158
+ /** @param array{info: array{url: string}, url: string, method: string} $trace */
159
+ private function matchesUrlAndMethod (array $ trace , string $ expectedUrl , string $ expectedMethod ): bool
160
+ {
161
+ return in_array ($ expectedUrl , [$ trace ['info ' ]['url ' ], $ trace ['url ' ]], true )
162
+ && $ expectedMethod === $ trace ['method ' ];
163
+ }
197
164
198
- $ this ->assertFalse (
199
- $ unexpectedUrlHasBeenFound ,
200
- sprintf ('Unexpected URL called: "%s" - "%s" ' , $ expectedMethod , $ unexpectedUrl )
201
- );
165
+ private function extractValue (mixed $ value ): mixed
166
+ {
167
+ return match (true ) {
168
+ $ value instanceof Data => $ value ->getValue (true ),
169
+ is_object ($ value ) && method_exists ($ value , 'getValue ' ) => $ value ->getValue (true ),
170
+ is_object ($ value ) && method_exists ($ value , '__toString ' ) => (string ) $ value ,
171
+ default => $ value ,
172
+ };
202
173
}
203
174
204
175
protected function grabHttpClientCollector (string $ function ): HttpClientDataCollector
0 commit comments