Skip to content

Commit 6e6d709

Browse files
committed
HttpClient PHPStan fix
1 parent e16aeaf commit 6e6d709

File tree

1 file changed

+118
-46
lines changed

1 file changed

+118
-46
lines changed

src/Codeception/Module/Symfony/HttpClientAssertionsTrait.php

Lines changed: 118 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@
55
namespace Codeception\Module\Symfony;
66

77
use Symfony\Component\HttpClient\DataCollector\HttpClientDataCollector;
8+
use Symfony\Component\VarDumper\Cloner\Data;
89
use function array_key_exists;
910
use function is_string;
1011

1112
trait HttpClientAssertionsTrait
1213
{
1314
/**
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.
1719
*
1820
* ```php
1921
* <?php
@@ -24,115 +26,185 @@ trait HttpClientAssertionsTrait
2426
* ['Authorization' => 'Bearer token']
2527
* );
2628
* ```
29+
*
30+
* @param string|array<mixed>|null $expectedBody
31+
* @param array<string,string|string[]> $expectedHeaders
2732
*/
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 {
3040
$httpClientCollector = $this->grabHttpClientCollector(__FUNCTION__);
31-
$expectedRequestHasBeenFound = false;
3241

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)) {
3453
$this->fail(sprintf('HttpClient "%s" is not registered.', $httpClientId));
3554
}
3655

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'])
3970
|| $expectedMethod !== $trace['method']
4071
) {
4172
continue;
4273
}
4374

44-
if (null !== $expectedBody) {
75+
if ($expectedBody !== null) {
4576
$actualBody = null;
4677

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);
4983
}
5084

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);
5390
}
5491

55-
if (!$actualBody) {
92+
if ($actualBody === null || $expectedBody !== $actualBody) {
5693
continue;
5794
}
5895

59-
if ($expectedBody === $actualBody) {
96+
if ($expectedHeaders === []) {
6097
$expectedRequestHasBeenFound = true;
61-
62-
if (!$expectedHeaders) {
63-
break;
64-
}
98+
break;
6599
}
66100
}
67101

68-
if ($expectedHeaders) {
102+
if ($expectedHeaders !== []) {
103+
/**
104+
* @var array<string, mixed> $actualHeaders
105+
*/
69106
$actualHeaders = $trace['options']['headers'] ?? [];
70107

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) {
75118
$expectedRequestHasBeenFound = true;
76119
break 2;
77120
}
78121
}
79122
}
80123

81-
$expectedRequestHasBeenFound = true;
82-
break;
124+
if ($expectedBody === null && $expectedHeaders === []) {
125+
$expectedRequestHasBeenFound = true;
126+
break;
127+
}
83128
}
84129

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+
);
86134
}
87135

88136
/**
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.
91140
*
92141
* ```php
93-
* <?php
94142
* $I->assertHttpClientRequestCount(3);
95143
* ```
96144
*/
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 {
99149
$httpClientCollector = $this->grabHttpClientCollector(__FUNCTION__);
100150

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']);
102161
}
103162

104163
/**
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.
108167
* ```php
109-
* <?php
110168
* $I->assertNotHttpClientRequest('https://example.com/unexpected', 'GET');
111169
* ```
112170
*/
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 {
115176
$httpClientCollector = $this->grabHttpClientCollector(__FUNCTION__);
116-
$unexpectedUrlHasBeenFound = false;
117177

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)) {
119184
$this->fail(sprintf('HttpClient "%s" is not registered.', $httpClientId));
120185
}
121186

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'])
124191
&& $expectedMethod === $trace['method']
125192
) {
126193
$unexpectedUrlHasBeenFound = true;
127194
break;
128195
}
129196
}
130197

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+
);
132202
}
133203

134204
protected function grabHttpClientCollector(string $function): HttpClientDataCollector
135205
{
136-
return $this->grabCollector('http_client', $function);
206+
/** @var HttpClientDataCollector $collector */
207+
$collector = $this->grabCollector('http_client', $function);
208+
return $collector;
137209
}
138210
}

0 commit comments

Comments
 (0)