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
}
@@ -142,22 +95,10 @@ public function assertHttpClientRequest(
142
95
* $I->assertHttpClientRequestCount(3);
143
96
* ```
144
97
*/
145
- public function assertHttpClientRequestCount (
146
- int $ count ,
147
- string $ httpClientId = 'http_client ' ,
148
- ): 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 ' ]);
98
+ public function assertHttpClientRequestCount (int $ count , string $ httpClientId = 'http_client ' ): void
99
+ {
100
+ $ traces = $ this ->getHttpClientTraces ($ httpClientId , __FUNCTION__ );
101
+ $ this ->assertCount ($ count , $ traces );
161
102
}
162
103
163
104
/**
@@ -173,32 +114,60 @@ public function assertNotHttpClientRequest(
173
114
string $ expectedMethod = 'GET ' ,
174
115
string $ httpClientId = 'http_client ' ,
175
116
): void {
176
- $ httpClientCollector = $ this ->grabHttpClientCollector (__FUNCTION__ );
117
+ $ traces = $ this ->getHttpClientTraces ($ httpClientId , __FUNCTION__ );
118
+
119
+ foreach ($ traces as $ trace ) {
120
+ if ($ this ->matchesUrlAndMethod ($ trace , $ unexpectedUrl , $ expectedMethod )) {
121
+ $ this ->fail (sprintf ('Unexpected URL called: "%s" - "%s" ' , $ expectedMethod , $ unexpectedUrl ));
122
+ }
123
+ }
177
124
178
- /**
179
- * @var array<string, array{traces: list<array{info: array{url: string}, url: string, method: string}>}> $clients
125
+ $ this ->assertTrue (true , 'The unexpected request was not made. ' );
126
+ }
127
+
128
+ /**
129
+ * @return list<array{
130
+ * info: array{url: string},
131
+ * url: string,
132
+ * method: string,
133
+ * options?: array{body?: mixed, json?: mixed, headers?: mixed}
134
+ * }>
135
+ */
136
+ private function getHttpClientTraces (string $ httpClientId , string $ function ): array
137
+ {
138
+ $ httpClientCollector = $ this ->grabHttpClientCollector ($ function );
139
+
140
+ /** @var array<string, array{traces: list<array{
141
+ * info: array{url: string},
142
+ * url: string,
143
+ * method: string,
144
+ * options?: array{body?: mixed, json?: mixed, headers?: mixed}
145
+ * }>}> $clients
180
146
*/
181
147
$ clients = $ httpClientCollector ->getClients ();
182
148
183
149
if (!array_key_exists ($ httpClientId , $ clients )) {
184
150
$ this ->fail (sprintf ('HttpClient "%s" is not registered. ' , $ httpClientId ));
185
151
}
186
152
187
- $ unexpectedUrlHasBeenFound = false ;
153
+ return $ clients [$ httpClientId ]['traces ' ];
154
+ }
188
155
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
- }
156
+ /** @param array{info: array{url: string}, url: string, method: string} $trace */
157
+ private function matchesUrlAndMethod (array $ trace , string $ expectedUrl , string $ expectedMethod ): bool
158
+ {
159
+ return in_array ($ expectedUrl , [$ trace ['info ' ]['url ' ], $ trace ['url ' ]], true )
160
+ && $ expectedMethod === $ trace ['method ' ];
161
+ }
197
162
198
- $ this ->assertFalse (
199
- $ unexpectedUrlHasBeenFound ,
200
- sprintf ('Unexpected URL called: "%s" - "%s" ' , $ expectedMethod , $ unexpectedUrl )
201
- );
163
+ private function extractValue (mixed $ value ): mixed
164
+ {
165
+ return match (true ) {
166
+ $ value instanceof Data => $ value ->getValue (true ),
167
+ is_object ($ value ) && method_exists ($ value , 'getValue ' ) => $ value ->getValue (true ),
168
+ is_object ($ value ) && method_exists ($ value , '__toString ' ) => (string ) $ value ,
169
+ default => $ value ,
170
+ };
202
171
}
203
172
204
173
protected function grabHttpClientCollector (string $ function ): HttpClientDataCollector
0 commit comments