• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

api-platform / core / 15133993414

20 May 2025 09:30AM UTC coverage: 26.313% (-1.2%) from 27.493%
15133993414

Pull #7161

github

web-flow
Merge e2c03d45f into 5459ba375
Pull Request #7161: fix(metadata): infer parameter string type from schema

0 of 2 new or added lines in 1 file covered. (0.0%)

11019 existing lines in 363 files now uncovered.

12898 of 49018 relevant lines covered (26.31%)

34.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.0
/src/Symfony/Bundle/Test/Client.php
1
<?php
2

3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <dunglas@gmail.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11

12
declare(strict_types=1);
13

14
namespace ApiPlatform\Symfony\Bundle\Test;
15

16
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
17
use Symfony\Component\BrowserKit\CookieJar;
18
use Symfony\Component\DependencyInjection\ContainerInterface;
19
use Symfony\Component\HttpClient\HttpClientTrait;
20
use Symfony\Component\HttpKernel\KernelInterface;
21
use Symfony\Component\HttpKernel\Profiler\Profile;
22
use Symfony\Component\Security\Core\User\UserInterface;
23
use Symfony\Contracts\HttpClient\HttpClientInterface;
24
use Symfony\Contracts\HttpClient\ResponseInterface;
25
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
26

27
/**
28
 * Convenient test client that makes requests to a Kernel object.
29
 *
30
 * @author Kévin Dunglas <dunglas@gmail.com>
31
 */
32
final class Client implements HttpClientInterface
33
{
34
    use ClientTrait, HttpClientTrait {
35
        ClientTrait::withOptions insteadof HttpClientTrait;
36
    }
37

38
    /**
39
     * @see HttpClientInterface::OPTIONS_DEFAULTS
40
     */
41
    public const API_OPTIONS_DEFAULTS = [
42
        'auth_basic' => null,
43
        'auth_bearer' => null,
44
        'query' => [],
45
        'headers' => ['accept' => ['application/ld+json']],
46
        'body' => '',
47
        'json' => null,
48
        'base_uri' => 'http://localhost',
49
        'extra' => [],
50
    ];
51

52
    private array $defaultOptions = self::API_OPTIONS_DEFAULTS;
53

54
    private ?Response $response = null;
55

56
    /**
57
     * @param array $defaultOptions Default options for the requests
58
     *
59
     * @see HttpClientInterface::OPTIONS_DEFAULTS for available options
60
     */
61
    public function __construct(private readonly KernelBrowser $kernelBrowser, array $defaultOptions = [])
62
    {
UNCOV
63
        $kernelBrowser->followRedirects(false);
237✔
UNCOV
64
        if ($defaultOptions) {
237✔
65
            $this->setDefaultOptions($defaultOptions);
×
66
        }
67
    }
68

69
    /**
70
     * Sets the default options for the requests.
71
     *
72
     * @see HttpClientInterface::OPTIONS_DEFAULTS for available options
73
     */
74
    public function setDefaultOptions(array $defaultOptions): void
75
    {
UNCOV
76
        [, $this->defaultOptions] = self::prepareRequest(null, null, $defaultOptions, self::API_OPTIONS_DEFAULTS);
237✔
77
    }
78

79
    /**
80
     * {@inheritdoc}
81
     */
82
    public function request(string $method, string $url, array $options = []): ResponseInterface
83
    {
UNCOV
84
        $basic = $options['auth_basic'] ?? null;
235✔
UNCOV
85
        [$url, $options] = self::prepareRequest($method, $url, $options, $this->defaultOptions);
235✔
UNCOV
86
        $resolvedUrl = implode('', $url);
235✔
UNCOV
87
        $server = [];
235✔
88

89
        // Convert headers to a $_SERVER-like array
UNCOV
90
        foreach (self::extractHeaders($options) as $key => $value) {
235✔
UNCOV
91
            $normalizedHeaderName = strtoupper(str_replace('-', '_', $key));
235✔
UNCOV
92
            $header = \in_array($normalizedHeaderName, ['CONTENT_TYPE', 'REMOTE_ADDR'], true) ? $normalizedHeaderName : \sprintf('HTTP_%s', $normalizedHeaderName);
235✔
93
            // BrowserKit doesn't support setting several headers with the same name
UNCOV
94
            $server[$header] = $value[0] ?? '';
235✔
95
        }
96

UNCOV
97
        if ($basic) {
235✔
UNCOV
98
            $credentials = \is_array($basic) ? $basic : explode(':', (string) $basic, 2);
3✔
UNCOV
99
            $server['PHP_AUTH_USER'] = $credentials[0];
3✔
UNCOV
100
            $server['PHP_AUTH_PW'] = $credentials[1] ?? '';
3✔
101
        }
102

UNCOV
103
        $info = [
235✔
UNCOV
104
            'response_headers' => [],
235✔
UNCOV
105
            'redirect_count' => 0,
235✔
UNCOV
106
            'redirect_url' => null,
235✔
UNCOV
107
            'start_time' => 0.0,
235✔
UNCOV
108
            'http_method' => $method,
235✔
UNCOV
109
            'http_code' => 0,
235✔
UNCOV
110
            'error' => null,
235✔
UNCOV
111
            'user_data' => $options['user_data'] ?? null,
235✔
UNCOV
112
            'url' => $resolvedUrl,
235✔
UNCOV
113
            'primary_port' => 'http:' === $url['scheme'] ? 80 : 443,
235✔
UNCOV
114
        ];
235✔
UNCOV
115
        $this->kernelBrowser->request($method, $resolvedUrl, $options['extra']['parameters'] ?? [], $options['extra']['files'] ?? [], $server, $options['body'] ?? null);
235✔
116

UNCOV
117
        return $this->response = new Response($this->kernelBrowser->getResponse(), $this->kernelBrowser->getInternalResponse(), $info);
235✔
118
    }
119

120
    /**
121
     * {@inheritdoc}
122
     */
123
    public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterface
124
    {
UNCOV
125
        throw new \LogicException('Not implemented yet');
1✔
126
    }
127

128
    /**
129
     * Gets the latest response.
130
     *
131
     * @internal
132
     */
133
    public function getResponse(): ?Response
134
    {
UNCOV
135
        return $this->response;
73✔
136
    }
137

138
    /**
139
     * Gets the underlying test client.
140
     *
141
     * @internal
142
     */
143
    public function getKernelBrowser(): KernelBrowser
144
    {
UNCOV
145
        return $this->kernelBrowser;
237✔
146
    }
147

148
    // The following methods are proxy methods for KernelBrowser's ones
149

150
    /**
151
     * Returns the container.
152
     *
153
     * @return ContainerInterface|null Returns null when the Kernel has been shutdown or not started yet
154
     */
155
    public function getContainer(): ?ContainerInterface
156
    {
157
        return $this->kernelBrowser->getContainer();
×
158
    }
159

160
    /**
161
     * Returns the CookieJar instance.
162
     */
163
    public function getCookieJar(): CookieJar
164
    {
165
        return $this->kernelBrowser->getCookieJar();
×
166
    }
167

168
    /**
169
     * Returns the kernel.
170
     */
171
    public function getKernel(): KernelInterface
172
    {
UNCOV
173
        return $this->kernelBrowser->getKernel();
1✔
174
    }
175

176
    /**
177
     * Gets the profile associated with the current Response.
178
     *
179
     * @return Profile|false A Profile instance
180
     */
181
    public function getProfile(): Profile|false
182
    {
UNCOV
183
        return $this->kernelBrowser->getProfile();
1✔
184
    }
185

186
    /**
187
     * Enables the profiler for the very next request.
188
     *
189
     * If the profiler is not enabled, the call to this method does nothing.
190
     */
191
    public function enableProfiler(): void
192
    {
UNCOV
193
        $this->kernelBrowser->enableProfiler();
1✔
194
    }
195

196
    /**
197
     * Disables kernel reboot between requests.
198
     *
199
     * By default, the Client reboots the Kernel for each request. This method
200
     * allows to keep the same kernel across requests.
201
     */
202
    public function disableReboot(): void
203
    {
UNCOV
204
        $this->kernelBrowser->disableReboot();
2✔
205
    }
206

207
    /**
208
     * Enables kernel reboot between requests.
209
     */
210
    public function enableReboot(): void
211
    {
UNCOV
212
        $this->kernelBrowser->enableReboot();
2✔
213
    }
214

215
    /**
216
     * Extracts headers depending on the symfony/http-client version being used.
217
     *
218
     * @return array<string, string[]>
219
     */
220
    private static function extractHeaders(array $options): array
221
    {
UNCOV
222
        if (!isset($options['normalized_headers'])) {
235✔
223
            return $options['headers'];
×
224
        }
225

UNCOV
226
        $headers = [];
235✔
227

228
        /** @var string $key */
UNCOV
229
        foreach ($options['normalized_headers'] as $key => $values) {
235✔
UNCOV
230
            foreach ($values as $value) {
235✔
UNCOV
231
                [, $value] = explode(': ', (string) $value, 2);
235✔
UNCOV
232
                $headers[$key][] = $value;
235✔
233
            }
234
        }
235

UNCOV
236
        return $headers;
235✔
237
    }
238

239
    public function loginUser(UserInterface $user, string $firewallContext = 'main'): self
240
    {
UNCOV
241
        $this->kernelBrowser->loginUser($user, $firewallContext);
4✔
242

UNCOV
243
        return $this;
4✔
244
    }
245
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc