Passed
Pull Request — master (#25)
by Sergei
02:30
created

TestApplicationRunner   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 184
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 71
c 4
b 0
f 0
dl 0
loc 184
ccs 0
cts 82
cp 0
rs 10
wmc 11

6 Methods

Rating   Name   Duplication   Size   Complexity  
A withRequest() 0 23 1
A createContainer() 0 30 5
A addProviders() 0 3 1
A __construct() 0 30 1
A run() 0 39 2
A preloadContainer() 0 11 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Testing;
6
7
use Psr\Container\ContainerInterface;
8
use Psr\Http\Message\ResponseInterface;
9
use Psr\Http\Message\ServerRequestInterface;
10
use Throwable;
11
use Yiisoft\Di\Container;
12
use Yiisoft\Di\ContainerConfig;
13
use Yiisoft\Di\ServiceProviderInterface;
14
use Yiisoft\ErrorHandler\Middleware\ErrorCatcher;
15
use Yiisoft\Yii\Http\Application;
16
use Yiisoft\Yii\Http\Handler\ThrowableHandler;
17
use Yiisoft\Yii\Runner\ApplicationRunner;
18
use Yiisoft\Yii\Runner\Http\ServerRequestFactory;
19
20
final class TestApplicationRunner extends ApplicationRunner
21
{
22
    private array $requestParameters = [];
23
    public ?ContainerInterface $container = null;
24
    /**
25
     * @var ServiceProviderInterface[]
26
     */
27
    private array $providers = [];
28
29
    /**
30
     * @param string $rootPath The absolute path to the project root.
31
     * @param bool $debug Whether the debug mode is enabled.
32
     * @param bool $checkEvents Whether to check events' configuration.
33
     * @param string|null $environment The environment name.
34
     * @param string $bootstrapGroup The bootstrap configuration group name.
35
     * @param string $eventsGroup The events' configuration group name.
36
     * @param string $diGroup The container definitions' configuration group name.
37
     * @param string $diProvidersGroup The container providers' configuration group name.
38
     * @param string $diDelegatesGroup The container delegates' configuration group name.
39
     * @param string $diTagsGroup The container tags' configuration group name.
40
     * @param string $paramsGroup The configuration parameters group name.
41
     * @param array $nestedParamsGroups Configuration group names that included into configuration parameters group.
42
     * This is needed for recursive merging of parameters.
43
     * @param array $nestedEventsGroups Configuration group names that included into events' configuration group. This
44
     * is needed for reverse and recursive merge of events' configurations.
45
     *
46
     * @psalm-param list<string> $nestedParamsGroups
47
     * @psalm-param list<string> $nestedEventsGroups
48
     */
49
    public function __construct(
50
        public ResponseGrabber $responseGrabber,
51
        string $rootPath,
52
        bool $debug = false,
53
        bool $checkEvents = false,
54
        ?string $environment = null,
55
        string $bootstrapGroup = 'bootstrap-web',
56
        string $eventsGroup = 'events-web',
57
        string $diGroup = 'di-web',
58
        string $diProvidersGroup = 'di-providers-web',
59
        string $diDelegatesGroup = 'di-delegates-web',
60
        string $diTagsGroup = 'di-tags-web',
61
        string $paramsGroup = 'params-web',
62
        array $nestedParamsGroups = ['params'],
63
        array $nestedEventsGroups = ['events'],
64
    ) {
65
        parent::__construct(
66
            $rootPath,
67
            $debug,
68
            $checkEvents,
69
            $environment,
70
            $bootstrapGroup,
71
            $eventsGroup,
72
            $diGroup,
73
            $diProvidersGroup,
74
            $diDelegatesGroup,
75
            $diTagsGroup,
76
            $paramsGroup,
77
            $nestedParamsGroups,
78
            $nestedEventsGroups,
79
        );
80
    }
81
82
    /**
83
     * {@inheritDoc}
84
     */
85
    public function run(): void
86
    {
87
        $this->preloadContainer();
88
89
        /** @var ContainerInterface $container */
90
        $container = $this->container;
91
92
        /** @var Application $application */
93
        $application = $container->get(Application::class);
94
95
        /**
96
         * @var ServerRequestInterface
97
         * @psalm-suppress MixedMethodCall
98
         */
99
        $serverRequest = $container
100
            ->get(ServerRequestFactory::class)
101
            ->createFromParameters(
102
                ...$this->requestParameters,
103
            );
104
105
        /**
106
         * @var ResponseInterface|null $response
107
         */
108
        $response = null;
109
        try {
110
            $application->start();
111
            $response = $application->handle($serverRequest);
112
        } catch (Throwable $throwable) {
113
            $handler = new ThrowableHandler($throwable);
114
            /**
115
             * @psalm-suppress MixedMethodCall
116
             */
117
            $response = $container
118
                ->get(ErrorCatcher::class)
119
                ->process($serverRequest, $handler);
120
        } finally {
121
            $application->afterEmit($response ?? null);
122
            $application->shutdown();
123
            $this->responseGrabber->setResponse($response);
124
        }
125
    }
126
127
    public function withRequest(
128
        string $method,
129
        string $url,
130
        array $queryParams = [],
131
        array $postParams = [],
132
        mixed $body = null,
133
        array $headers = [],
134
        array $cookies = [],
135
        array $files = [],
136
    ): void {
137
        $this->requestParameters = [
138
            'server' => [
139
                'SCRIPT_NAME' => '/index.php',
140
                'REQUEST_METHOD' => $method,
141
                'SERVER_PROTOCOL' => '1.1',
142
                'REQUEST_URI' => $url,
143
            ],
144
            'headers' => $headers,
145
            'cookies' => $cookies,
146
            'get' => $queryParams,
147
            'post' => $postParams,
148
            'files' => $files,
149
            'body' => $body,
150
        ];
151
    }
152
153
    public function preloadContainer(): void
154
    {
155
        /**
156
         * @psalm-suppress UnresolvableInclude
157
         */
158
        require_once $this->rootPath . '/autoload.php';
159
160
        $this->container = $this->createContainer();
161
162
        $this->runBootstrap();
163
        $this->checkEvents();
164
    }
165
166
    /**
167
     * @param ServiceProviderInterface[] $providers
168
     */
169
    public function addProviders(array $providers): void
170
    {
171
        $this->providers = array_merge($this->providers, $providers);
172
    }
173
174
    private function createContainer(): Container
175
    {
176
        $containerConfig = ContainerConfig::create()->withValidate($this->debug);
177
178
        $config = $this->getConfig();
179
180
        if (null !== $definitions = $this->getConfiguration($this->diGroup)) {
181
            $containerConfig = $containerConfig->withDefinitions($definitions);
182
        }
183
184
        if (null !== $providers = $this->getConfiguration($this->diProvidersGroup)) {
185
            $providers = array_merge($providers, $this->providers);
186
        } else {
187
            $providers = $this->providers;
188
        }
189
        $containerConfig = $containerConfig->withProviders($providers);
190
191
        if (null !== $delegates = $this->getConfiguration($this->diDelegatesGroup)) {
192
            $containerConfig = $containerConfig->withDelegates($delegates);
193
        }
194
195
        if (null !== $tags = $this->getConfiguration($this->diTagsGroup)) {
196
            $containerConfig = $containerConfig->withTags($tags);
197
        }
198
199
        $containerConfig = $containerConfig->withDefinitions(
200
            array_merge($containerConfig->getDefinitions(), [ConfigInterface::class => $config])
0 ignored issues
show
Bug introduced by
The type Yiisoft\Yii\Testing\ConfigInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
201
        );
202
203
        return new Container($containerConfig);
204
    }
205
}
206