5
5
namespace Codeception \Module \Symfony ;
6
6
7
7
use Symfony \Component \HttpClient \DataCollector \HttpClientDataCollector ;
8
+ use Symfony \Component \VarDumper \Cloner \Data ;
8
9
use function array_key_exists ;
9
10
use function is_string ;
10
11
11
12
trait HttpClientAssertionsTrait
12
13
{
13
14
/**
14
- * Asserts that the given URL has been called using, if specified, the given method body and headers.
15
- * By default, it will check on the HttpClient, but you can also pass a specific HttpClient ID.
16
- * (It will succeed if the request has been called multiple times.)
15
+ * Asserts that the given URL has been called using, if specified, the given method, body and/or headers.
16
+ * By default, it will inspect the default Symfony HttpClient; you may check a different one by passing its
17
+ * service-id in $httpClientId.
18
+ * It succeeds even if the request was executed multiple times.
17
19
*
18
20
* ```php
19
21
* <?php
@@ -24,115 +26,185 @@ trait HttpClientAssertionsTrait
24
26
* ['Authorization' => 'Bearer token']
25
27
* );
26
28
* ```
29
+ *
30
+ * @param string|array<mixed>|null $expectedBody
31
+ * @param array<string,string|string[]> $expectedHeaders
27
32
*/
28
- public function assertHttpClientRequest (string $ expectedUrl , string $ expectedMethod = 'GET ' , string |array |null $ expectedBody = null , array $ expectedHeaders = [], string $ httpClientId = 'http_client ' ): void
29
- {
33
+ public function assertHttpClientRequest (
34
+ string $ expectedUrl ,
35
+ string $ expectedMethod = 'GET ' ,
36
+ string |array |null $ expectedBody = null ,
37
+ array $ expectedHeaders = [],
38
+ string $ httpClientId = 'http_client ' ,
39
+ ): void {
30
40
$ httpClientCollector = $ this ->grabHttpClientCollector (__FUNCTION__ );
31
- $ expectedRequestHasBeenFound = false ;
32
41
33
- if (!array_key_exists ($ httpClientId , $ httpClientCollector ->getClients ())) {
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 )) {
34
53
$ this ->fail (sprintf ('HttpClient "%s" is not registered. ' , $ httpClientId ));
35
54
}
36
55
37
- foreach ($ httpClientCollector ->getClients ()[$ httpClientId ]['traces ' ] as $ trace ) {
38
- if (($ expectedUrl !== $ trace ['info ' ]['url ' ] && $ expectedUrl !== $ trace ['url ' ])
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 ;
67
+
68
+ foreach ($ traces as $ trace ) {
69
+ if (($ expectedUrl !== $ trace ['info ' ]['url ' ] && $ expectedUrl !== $ trace ['url ' ])
39
70
|| $ expectedMethod !== $ trace ['method ' ]
40
71
) {
41
72
continue ;
42
73
}
43
74
44
- if (null !== $ expectedBody ) {
75
+ if ($ expectedBody !== null ) {
45
76
$ actualBody = null ;
46
77
47
- if (null !== $ trace ['options ' ]['body ' ] && null === $ trace ['options ' ]['json ' ]) {
48
- $ actualBody = is_string ($ trace ['options ' ]['body ' ]) ? $ trace ['options ' ]['body ' ] : $ trace ['options ' ]['body ' ]->getValue (true );
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 );
49
83
}
50
84
51
- if (null === $ trace ['options ' ]['body ' ] && null !== $ trace ['options ' ]['json ' ]) {
52
- $ actualBody = $ trace ['options ' ]['json ' ]->getValue (true );
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 );
53
90
}
54
91
55
- if (! $ actualBody ) {
92
+ if ($ actualBody === null || $ expectedBody !== $ actualBody ) {
56
93
continue ;
57
94
}
58
95
59
- if ($ expectedBody === $ actualBody ) {
96
+ if ($ expectedHeaders === [] ) {
60
97
$ expectedRequestHasBeenFound = true ;
61
-
62
- if (!$ expectedHeaders ) {
63
- break ;
64
- }
98
+ break ;
65
99
}
66
100
}
67
101
68
- if ($ expectedHeaders ) {
102
+ if ($ expectedHeaders !== []) {
103
+ /**
104
+ * @var array<string, mixed> $actualHeaders
105
+ */
69
106
$ actualHeaders = $ trace ['options ' ]['headers ' ] ?? [];
70
107
71
- foreach ($ actualHeaders as $ headerKey => $ actualHeader ) {
72
- if (array_key_exists ($ headerKey , $ expectedHeaders )
73
- && $ expectedHeaders [$ headerKey ] === $ actualHeader ->getValue (true )
74
- ) {
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 ) {
75
118
$ expectedRequestHasBeenFound = true ;
76
119
break 2 ;
77
120
}
78
121
}
79
122
}
80
123
81
- $ expectedRequestHasBeenFound = true ;
82
- break ;
124
+ if ($ expectedBody === null && $ expectedHeaders === []) {
125
+ $ expectedRequestHasBeenFound = true ;
126
+ break ;
127
+ }
83
128
}
84
129
85
- $ this ->assertTrue ($ expectedRequestHasBeenFound , 'The expected request has not been called: " ' . $ expectedMethod . '" - " ' . $ expectedUrl . '" ' );
130
+ $ this ->assertTrue (
131
+ $ expectedRequestHasBeenFound ,
132
+ sprintf ('The expected request has not been called: "%s" - "%s" ' , $ expectedMethod , $ expectedUrl )
133
+ );
86
134
}
87
135
88
136
/**
89
- * Asserts that the given number of requests has been made on the HttpClient.
90
- * By default, it will check on the HttpClient, but you can also pass a specific HttpClient ID.
137
+ * Asserts that exactly $count requests have been executed by the given HttpClient.
138
+ * By default, it will inspect the default Symfony HttpClient; you may check a different one by passing its
139
+ * service-id in $httpClientId.
91
140
*
92
141
* ```php
93
- * <?php
94
142
* $I->assertHttpClientRequestCount(3);
95
143
* ```
96
144
*/
97
- public function assertHttpClientRequestCount (int $ count , string $ httpClientId = 'http_client ' ): void
98
- {
145
+ public function assertHttpClientRequestCount (
146
+ int $ count ,
147
+ string $ httpClientId = 'http_client ' ,
148
+ ): void {
99
149
$ httpClientCollector = $ this ->grabHttpClientCollector (__FUNCTION__ );
100
150
101
- $ this ->assertCount ($ count , $ httpClientCollector ->getClients ()[$ httpClientId ]['traces ' ]);
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
161
}
103
162
104
163
/**
105
- * Asserts that the given URL has not been called using GET or the specified method.
106
- * By default, it will check on the HttpClient, but a HttpClient id can be specified.
107
- *
164
+ * Asserts that the given URL * has not* been requested with the supplied HTTP method.
165
+ * By default, it will inspect the default Symfony HttpClient; you may check a different one by passing its
166
+ * service-id in $httpClientId.
108
167
* ```php
109
- * <?php
110
168
* $I->assertNotHttpClientRequest('https://example.com/unexpected', 'GET');
111
169
* ```
112
170
*/
113
- public function assertNotHttpClientRequest (string $ unexpectedUrl , string $ expectedMethod = 'GET ' , string $ httpClientId = 'http_client ' ): void
114
- {
171
+ public function assertNotHttpClientRequest (
172
+ string $ unexpectedUrl ,
173
+ string $ expectedMethod = 'GET ' ,
174
+ string $ httpClientId = 'http_client ' ,
175
+ ): void {
115
176
$ httpClientCollector = $ this ->grabHttpClientCollector (__FUNCTION__ );
116
- $ unexpectedUrlHasBeenFound = false ;
117
177
118
- if (!array_key_exists ($ httpClientId , $ httpClientCollector ->getClients ())) {
178
+ /**
179
+ * @var array<string, array{traces: list<array{info: array{url: string}, url: string, method: string}>}> $clients
180
+ */
181
+ $ clients = $ httpClientCollector ->getClients ();
182
+
183
+ if (!array_key_exists ($ httpClientId , $ clients )) {
119
184
$ this ->fail (sprintf ('HttpClient "%s" is not registered. ' , $ httpClientId ));
120
185
}
121
186
122
- foreach ($ httpClientCollector ->getClients ()[$ httpClientId ]['traces ' ] as $ trace ) {
123
- if (($ unexpectedUrl === $ trace ['info ' ]['url ' ] || $ unexpectedUrl === $ trace ['url ' ])
187
+ $ unexpectedUrlHasBeenFound = false ;
188
+
189
+ foreach ($ clients [$ httpClientId ]['traces ' ] as $ trace ) {
190
+ if (($ unexpectedUrl === $ trace ['info ' ]['url ' ] || $ unexpectedUrl === $ trace ['url ' ])
124
191
&& $ expectedMethod === $ trace ['method ' ]
125
192
) {
126
193
$ unexpectedUrlHasBeenFound = true ;
127
194
break ;
128
195
}
129
196
}
130
197
131
- $ this ->assertFalse ($ unexpectedUrlHasBeenFound , sprintf ('Unexpected URL called: "%s" - "%s" ' , $ expectedMethod , $ unexpectedUrl ));
198
+ $ this ->assertFalse (
199
+ $ unexpectedUrlHasBeenFound ,
200
+ sprintf ('Unexpected URL called: "%s" - "%s" ' , $ expectedMethod , $ unexpectedUrl )
201
+ );
132
202
}
133
203
134
204
protected function grabHttpClientCollector (string $ function ): HttpClientDataCollector
135
205
{
136
- return $ this ->grabCollector ('http_client ' , $ function );
206
+ /** @var HttpClientDataCollector $collector */
207
+ $ collector = $ this ->grabCollector ('http_client ' , $ function );
208
+ return $ collector ;
137
209
}
138
210
}
0 commit comments