Module::startOutputBuffering()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 6
cts 6
cp 1
rs 9.9332
c 0
b 0
f 0
cc 3
nc 4
nop 0
crap 3
1
<?php
2
3
// phpcs:disable PSR2.Methods.MethodDeclaration -- Method names with underscore are required for codeception module
4
5
namespace Jasny\Codeception;
6
7
use Jasny\RouterInterface;
8
use Jasny\ErrorHandlerInterface;
9
use Codeception\Configuration;
10
use Codeception\Lib\Framework;
11
use Codeception\TestInterface;
12
use Psr\Http\Message\ServerRequestInterface;
13
use Psr\Http\Message\ResponseInterface;
14
use Psr\Container\ContainerInterface;
15
16
/**
17
 * Module for running functional tests using Jasny MVC
18
 */
19
class Module extends Framework
20
{
21
    /**
22
     * Required configuration fields
23
     * @var array
24
     */
25
    protected $requiredFields = ['container'];
26
    
27
    /**
28
     * @var ContainerInterface
29
     */
30
    public $container;
31
    
32
    /**
33
     * @var ServerRequestInterface
34
     */
35
    public $baseRequest;
36
    
37
    /**
38
     * @var ResponseInterface
39
     */
40
    public $baseResponse;
41
    
42
    
43
    /**
44
     * Load the container by including the file.
45
     * @codeCoverageIgnore
46
     *
47
     * @param string $file
48
     * @return ContainerInterface
49
     */
50
    protected function loadContainer($file)
51
    {
52
        return include $file;
53
    }
54
    
55
    /**
56
     * Get the container.
57
     *
58
     * @return ContainerInterface
59
     */
60 7
    protected function initContainer()
61
    {
62 7
        $container = $this->loadContainer(Configuration::projectDir() . $this->config['container']);
63
64 7
        if (!$container instanceof ContainerInterface) {
65 1
            throw new \UnexpectedValueException("Failed to get a container from '{$this->config['container']}'");
66
        }
67
68 6
        return $container;
69
    }
70
    
71
    /**
72
     * Check if the response writes to the output buffer
73
     *
74
     * @return boolean
75
     */
76 7
    protected function usesOutputBuffer()
77
    {
78 7
        return isset($this->baseResponse) && $this->baseResponse->getBody()->getMetadata('uri') === 'php://output';
79
    }
80
    
81
    /**
82
     * Enable output buffering
83
     *
84
     * @throws \RuntimeException
85
     */
86 2
    protected function startOutputBuffering()
87
    {
88 2
        if ($this->obGetLevel() === 0) {
89 2
            $this->obStart();
90
        }
91
92 2
        if ($this->obGetLevel() < 1) {
93 1
            throw new \RuntimeException("Failed to start output buffering");
94
        }
95 1
    }
96
    
97
    /**
98
     * Disable output buffering
99
     */
100 1
    protected function stopOutputBuffering()
101
    {
102 1
        $this->obClean();
103 1
    }
104
105
    /**
106
     * Initialize the module
107
     */
108 7
    public function init()
109
    {
110 7
        $this->container = $this->initContainer();
111
112 6
        if ($this->container->has(ServerRequestInterface::class)) {
113 1
            $this->baseRequest = $this->container->get(ServerRequestInterface::class);
114
        }
115
        
116 6
        if ($this->container->has(ResponseInterface::class)) {
117 1
            $this->baseResponse = $this->container->get(ResponseInterface::class);
118
        }
119 6
    }
120
    
121
    /**
122
     * Call before suite
123
     *
124
     * @param array $settings
125
     */
126 4
    public function _beforeSuite($settings = [])
127
    {
128 4
        parent::_beforeSuite($settings);
129
        
130 4
        if ($this->usesOutputBuffer()) {
131 2
            $this->startOutputBuffering();
132
        }
133 3
    }
134
    
135
    /**
136
     * Call after suite
137
     */
138 3
    public function _afterSuite()
139
    {
140 3
        if ($this->usesOutputBuffer()) {
141 1
            $this->stopOutputBuffering();
142
        }
143
        
144 3
        parent::_afterSuite();
145 3
    }
146
    
147
    /**
148
     * Before each test
149
     *
150
     * @param TestInterface $test
151
     */
152 4
    public function _before(TestInterface $test)
153
    {
154 4
        $this->init();
155
156 4
        $this->client = new Connector();
157 4
        $this->client->setRouter($this->container->get(RouterInterface::class));
158
159 4
        if (isset($this->baseRequest)) {
160 2
            $this->client->setBaseRequest($this->baseRequest);
161
        }
162
        
163 4
        if (isset($this->baseResponse)) {
164 2
            $this->client->setBaseResponse($this->baseResponse);
165
        }
166
167 4
        parent::_before($test);
168 4
    }
169
    
170
    /**
171
     * After each test
172
     *
173
     * @param TestInterface $test
174
     */
175 3
    public function _after(TestInterface $test)
176
    {
177 3
        if ($this->sessionStatus() === PHP_SESSION_ACTIVE) {
178 1
            $this->sessionDestroy();
179
        }
180
181 3
        if (isset($this->client) && $this->client instanceof Connector) {
182 1
            $this->client->reset();
183
            
184 1
            if (isset($this->baseRequest)) {
185 1
                $this->baseRequest = $this->client->getBaseRequest();
186
            }
187
            
188 1
            if (isset($this->baseResponse)) {
189 1
                $this->baseResponse = $this->client->getBaseResponse();
190
            }
191
        }
192
193 3
        parent::_after($test);
194 3
    }
195
    
196
    /**
197
     * Called when test fails
198
     *
199
     * @param TestInterface $test
200
     * @param mixed         $fail
201
     */
202 1
    public function _failed(TestInterface $test, $fail)
203
    {
204 1
        if (isset($this->container) && $this->container->has(ErrorHandlerInterface::class)) {
205 1
            $error = $this->container->get(ErrorHandlerInterface::class)->getError();
206
            
207 1
            if ($error) {
208 1
                $this->debug((string)$error);
209
            }
210
        }
211
212
        
213 1
        parent::_failed($test, $fail);
214 1
    }
215
    
216
    
217
    /**
218
     * Wrapper around `ob_start()`
219
     * @codeCoverageIgnore
220
     */
221
    protected function obStart()
222
    {
223
        ob_start();
224
    }
225
    
226
    /**
227
     * Wrapper around `ob_get_level()`
228
     * @codeCoverageIgnore
229
     *
230
     * @return int
231
     */
232
    protected function obGetLevel()
233
    {
234
        return ob_get_level();
235
    }
236
    
237
    /**
238
     * Wrapper around `ob_clean()`
239
     * @codeCoverageIgnore
240
     */
241
    protected function obClean()
242
    {
243
        ob_clean();
244
    }
245
    
246
    /**
247
     * Wrapper around `session_status()`
248
     * @codeCoverageIgnore
249
     *
250
     * @return int
251
     */
252
    protected function sessionStatus()
253
    {
254
        return session_status();
255
    }
256
    
257
    /**
258
     * Wrapper around `session_unset()` and `session_destroy()`
259
     * @codeCoverageIgnore
260
     */
261
    protected function sessionDestroy()
262
    {
263
        session_unset();
264
        session_destroy();
265
    }
266
}
267