Completed
Push — master ( 8e46af...0fdd41 )
by David
20s queued 12s
created

testPreInvalidateCalled()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 16
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 21
ccs 16
cts 16
cp 1
crap 1
rs 9.7333
1
<?php
2
3
/*
4
 * This file is part of the FOSHttpCache package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.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
namespace FOS\HttpCache\Test;
13
14
use FOS\HttpCache\SymfonyCache\CacheEvent;
15
use FOS\HttpCache\SymfonyCache\CacheInvalidation;
16
use FOS\HttpCache\SymfonyCache\EventDispatchingHttpCache;
17
use FOS\HttpCache\SymfonyCache\Events;
18
use PHPUnit\Framework\MockObject\MockObject;
0 ignored issues
show
Bug introduced by
The type PHPUnit\Framework\MockObject\MockObject 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...
19
use PHPUnit\Framework\TestCase;
0 ignored issues
show
Bug introduced by
The type PHPUnit\Framework\TestCase 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...
20
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
21
use Symfony\Component\HttpFoundation\Request;
22
use Symfony\Component\HttpFoundation\Response;
23
use Symfony\Component\HttpKernel\HttpCache\HttpCache;
24
use Symfony\Component\HttpKernel\HttpCache\StoreInterface;
25
use Symfony\Component\HttpKernel\HttpKernelInterface;
26
27
/**
28
 * This test ensures that the EventDispatchingHttpCache trait is correctly used.
29
 */
30
abstract class EventDispatchingHttpCacheTestCase extends TestCase
31
{
32
    /**
33
     * Specify the CacheInvalidationInterface HttpCache class to test.
34
     *
35
     * @return string Fully qualified class name of the AppCache
36
     */
37
    abstract protected function getCacheClass();
38
39
    /**
40
     * Create a partial mock of the HttpCache to only test some methods.
41
     *
42
     * @param array $mockedMethods List of methods to mock
43
     *
44
     * @return CacheInvalidation|EventDispatchingHttpCache|MockObject
45
     */
46 9
    protected function getHttpCachePartialMock(array $mockedMethods = null)
47
    {
48
        $mock = $this
49 9
            ->getMockBuilder($this->getCacheClass())
50 9
            ->setMethods($mockedMethods)
51 9
            ->disableOriginalConstructor()
52 9
            ->getMock()
53
        ;
54
55 9
        $this->assertInstanceOf(CacheInvalidation::class, $mock);
56
57
        // Force setting options property since we can't use original constructor.
58
        $options = [
59 9
            'debug' => false,
60
            'default_ttl' => 0,
61
            'private_headers' => ['Authorization', 'Cookie'],
62
            'allow_reload' => false,
63
            'allow_revalidate' => false,
64
            'stale_while_revalidate' => 2,
65
            'stale_if_error' => 60,
66
            'trace_level' => 'full',
67
            'trace_header' => 'FOSHttpCache',
68
        ];
69
70 9
        $refHttpCache = new \ReflectionClass(HttpCache::class);
71 9
        $refOptions = $refHttpCache->getProperty('options');
72 9
        $refOptions->setAccessible(true);
73 9
        $refOptions->setValue($mock, $options);
74
75 9
        return $mock;
76
    }
77
78
    /**
79
     * Set the store property on a HttpCache to a StoreInterface expecting one write with request and response.
80
     */
81 2
    protected function setStoreMock(CacheInvalidation $httpCache, Request $request, Response $response)
82
    {
83 2
        $store = $this->createMock(StoreInterface::class);
84
        $store
85 2
            ->expects($this->once())
86 2
            ->method('write')
87 2
            ->with($request, $response)
88
        ;
89 2
        $refHttpCache = new \ReflectionClass(HttpCache::class);
90 2
        $refStore = $refHttpCache->getProperty('store');
91 2
        $refStore->setAccessible(true);
92 2
        $refStore->setValue($httpCache, $store);
93 2
    }
94
95
    /**
96
     * Assert that preHandle and postHandle are called.
97
     */
98 1
    public function testHandleCalled()
99
    {
100 1
        $catch = true;
101 1
        $request = Request::create('/foo', 'GET');
102 1
        $response = new Response();
103
104 1
        $httpCache = $this->getHttpCachePartialMock(['lookup']);
105 1
        $testListener = new TestListener($this, $httpCache, $request);
106 1
        $httpCache->addSubscriber($testListener);
107
        $httpCache
108 1
            ->expects($this->any())
0 ignored issues
show
Bug introduced by
It seems like expects() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

108
            ->/** @scrutinizer ignore-call */ 
109
              expects($this->any())
Loading history...
Bug introduced by
The method expects() does not exist on FOS\HttpCache\SymfonyCache\CacheInvalidation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

108
            ->/** @scrutinizer ignore-call */ 
109
              expects($this->any())

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
109 1
            ->method('lookup')
110 1
            ->with($request)
111 1
            ->will($this->returnValue($response))
112
        ;
113
114 1
        $this->assertSame($response, $httpCache->handle($request, HttpKernelInterface::MASTER_REQUEST, $catch));
0 ignored issues
show
Deprecated Code introduced by
The constant Symfony\Component\HttpKe...terface::MASTER_REQUEST has been deprecated: since symfony/http-kernel 5.3, use MAIN_REQUEST instead. To ease the migration, this constant won't be removed until Symfony 7.0. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

114
        $this->assertSame($response, $httpCache->handle($request, /** @scrutinizer ignore-deprecated */ HttpKernelInterface::MASTER_REQUEST, $catch));

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
115 1
        $this->assertEquals(1, $testListener->preHandleCalls);
116 1
        $this->assertEquals(1, $testListener->postHandleCalls);
117 1
    }
118
119
    /**
120
     * Assert that when preHandle returns a response, that response is used and the normal kernel flow stopped.
121
     *
122
     * @depends testHandleCalled
123
     */
124 1
    public function testPreHandleReturnEarly()
125
    {
126 1
        $catch = true;
127 1
        $request = Request::create('/foo', 'GET');
128 1
        $response = new Response();
129
130 1
        $httpCache = $this->getHttpCachePartialMock(['lookup']);
131 1
        $testListener = new TestListener($this, $httpCache, $request);
132 1
        $testListener->preHandleResponse = $response;
133 1
        $httpCache->addSubscriber($testListener);
134
        $httpCache
135 1
            ->expects($this->never())
136 1
            ->method('lookup')
137
        ;
138
139 1
        $this->assertSame($response, $httpCache->handle($request, HttpKernelInterface::MASTER_REQUEST, $catch));
0 ignored issues
show
Deprecated Code introduced by
The constant Symfony\Component\HttpKe...terface::MASTER_REQUEST has been deprecated: since symfony/http-kernel 5.3, use MAIN_REQUEST instead. To ease the migration, this constant won't be removed until Symfony 7.0. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

139
        $this->assertSame($response, $httpCache->handle($request, /** @scrutinizer ignore-deprecated */ HttpKernelInterface::MASTER_REQUEST, $catch));

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
140 1
        $this->assertEquals(1, $testListener->preHandleCalls);
141 1
        $this->assertEquals(1, $testListener->postHandleCalls);
142 1
    }
143
144
    /**
145
     * Assert that postHandle can update the response.
146
     *
147
     * @depends testHandleCalled
148
     */
149 1
    public function testPostHandleReturn()
150
    {
151 1
        $catch = true;
152 1
        $request = Request::create('/foo', 'GET');
153 1
        $regularResponse = new Response();
154 1
        $postResponse = new Response();
155
156 1
        $httpCache = $this->getHttpCachePartialMock(['lookup']);
157 1
        $testListener = new TestListener($this, $httpCache, $request);
158 1
        $testListener->postHandleResponse = $postResponse;
159 1
        $httpCache->addSubscriber($testListener);
160
        $httpCache
161 1
            ->expects($this->any())
162 1
            ->method('lookup')
163 1
            ->with($request)
164 1
            ->will($this->returnValue($regularResponse))
165
        ;
166
167 1
        $this->assertSame($postResponse, $httpCache->handle($request, HttpKernelInterface::MASTER_REQUEST, $catch));
0 ignored issues
show
Deprecated Code introduced by
The constant Symfony\Component\HttpKe...terface::MASTER_REQUEST has been deprecated: since symfony/http-kernel 5.3, use MAIN_REQUEST instead. To ease the migration, this constant won't be removed until Symfony 7.0. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

167
        $this->assertSame($postResponse, $httpCache->handle($request, /** @scrutinizer ignore-deprecated */ HttpKernelInterface::MASTER_REQUEST, $catch));

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
168 1
        $this->assertEquals(1, $testListener->preHandleCalls);
169 1
        $this->assertEquals(1, $testListener->postHandleCalls);
170 1
    }
171
172
    /**
173
     * Assert that postHandle is called and the response can be updated even when preHandle returned a response.
174
     *
175
     * @depends testHandleCalled
176
     */
177 1
    public function testPostHandleAfterPreHandle()
178
    {
179 1
        $catch = true;
180 1
        $request = Request::create('/foo', 'GET');
181 1
        $preResponse = new Response();
182 1
        $postResponse = new Response();
183
184 1
        $httpCache = $this->getHttpCachePartialMock(['lookup']);
185 1
        $testListener = new TestListener($this, $httpCache, $request);
186 1
        $testListener->preHandleResponse = $preResponse;
187 1
        $testListener->postHandleResponse = $postResponse;
188 1
        $httpCache->addSubscriber($testListener);
189
        $httpCache
190 1
            ->expects($this->never())
191 1
            ->method('lookup')
192
        ;
193
194 1
        $this->assertSame($postResponse, $httpCache->handle($request, HttpKernelInterface::MASTER_REQUEST, $catch));
0 ignored issues
show
Deprecated Code introduced by
The constant Symfony\Component\HttpKe...terface::MASTER_REQUEST has been deprecated: since symfony/http-kernel 5.3, use MAIN_REQUEST instead. To ease the migration, this constant won't be removed until Symfony 7.0. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

194
        $this->assertSame($postResponse, $httpCache->handle($request, /** @scrutinizer ignore-deprecated */ HttpKernelInterface::MASTER_REQUEST, $catch));

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
195 1
        $this->assertEquals(1, $testListener->preHandleCalls);
196 1
        $this->assertEquals(1, $testListener->postHandleCalls);
197 1
    }
198
199
    /**
200
     * Assert that preStore is called.
201
     */
202 1
    public function testPreStoreCalled()
203
    {
204 1
        $request = Request::create('/foo', 'GET');
205 1
        $response = new Response();
206
207 1
        $httpCache = $this->getHttpCachePartialMock();
208 1
        $testListener = new TestListener($this, $httpCache, $request);
209 1
        $httpCache->addSubscriber($testListener);
210
211 1
        $this->setStoreMock($httpCache, $request, $response);
212
213 1
        $refHttpCache = new \ReflectionObject($httpCache);
214 1
        $method = $refHttpCache->getMethod('store');
215 1
        $method->setAccessible(true);
216 1
        $method->invokeArgs($httpCache, [$request, $response]);
217 1
        $this->assertEquals(1, $testListener->preStoreCalls);
218 1
    }
219
220
    /**
221
     * Assert that preStore response is used when provided.
222
     */
223 1
    public function testPreStoreResponse()
224
    {
225 1
        $request = Request::create('/foo', 'GET');
226 1
        $regularResponse = new Response();
227 1
        $preStoreResponse = new Response();
228
229 1
        $httpCache = $this->getHttpCachePartialMock();
230 1
        $testListener = new TestListener($this, $httpCache, $request);
231 1
        $testListener->preStoreResponse = $preStoreResponse;
232 1
        $httpCache->addSubscriber($testListener);
233
234 1
        $this->setStoreMock($httpCache, $request, $preStoreResponse);
235
236 1
        $refHttpCache = new \ReflectionObject($httpCache);
237 1
        $method = $refHttpCache->getMethod('store');
238 1
        $method->setAccessible(true);
239 1
        $method->invokeArgs($httpCache, [$request, $regularResponse]);
240 1
        $this->assertEquals(1, $testListener->preStoreCalls);
241 1
    }
242
243
    /**
244
     * Assert that preInvalidate is called.
245
     */
246 1
    public function testPreInvalidateCalled()
247
    {
248 1
        $catch = true;
249 1
        $request = Request::create('/foo', 'GET');
250 1
        $response = new Response('', 500);
251
252 1
        $httpCache = $this->getHttpCachePartialMock(['pass']);
253 1
        $testListener = new TestListener($this, $httpCache, $request);
254 1
        $httpCache->addSubscriber($testListener);
255
        $httpCache
256 1
            ->expects($this->any())
257 1
            ->method('pass')
258 1
            ->with($request)
259 1
            ->will($this->returnValue($response))
260
        ;
261 1
        $refHttpCache = new \ReflectionObject($httpCache);
262 1
        $method = $refHttpCache->getMethod('invalidate');
263 1
        $method->setAccessible(true);
264
265 1
        $this->assertSame($response, $method->invokeArgs($httpCache, [$request, $catch]));
266 1
        $this->assertEquals(1, $testListener->preInvalidateCalls);
267 1
    }
268
269
    /**
270
     * Assert that when preInvalidate returns a response, that response is used and the normal kernel flow stopped.
271
     *
272
     * @depends testPreInvalidateCalled
273
     */
274 1
    public function testPreInvalidateReturnEarly()
275
    {
276 1
        $catch = true;
277 1
        $request = Request::create('/foo', 'GET');
278 1
        $response = new Response('', 400);
279
280 1
        $httpCache = $this->getHttpCachePartialMock(['pass']);
281 1
        $testListener = new TestListener($this, $httpCache, $request);
282 1
        $testListener->preInvalidateResponse = $response;
283 1
        $httpCache->addSubscriber($testListener);
284
        $httpCache
285 1
            ->expects($this->never())
286 1
            ->method('pass')
287
        ;
288 1
        $refHttpCache = new \ReflectionObject($httpCache);
289 1
        $method = $refHttpCache->getMethod('invalidate');
290 1
        $method->setAccessible(true);
291
292 1
        $this->assertSame($response, $method->invokeArgs($httpCache, [$request, $catch]));
293 1
        $this->assertEquals(1, $testListener->preInvalidateCalls);
294 1
    }
295
296 1
    public function testAddListener()
297
    {
298 1
        $request = Request::create('/foo', 'GET');
299 1
        $response = new Response();
300
301 1
        $httpCache = $this->getHttpCachePartialMock(['lookup']);
302 1
        $simpleListener = new SimpleListener($this, $httpCache, $request);
303 1
        $httpCache->addListener(Events::PRE_HANDLE, [$simpleListener, 'callback']);
304
305
        $httpCache
306 1
            ->expects($this->any())
307 1
            ->method('lookup')
308 1
            ->with($request)
309 1
            ->will($this->returnValue($response))
310
        ;
311
312 1
        $this->assertSame($response, $httpCache->handle($request, HttpKernelInterface::MASTER_REQUEST));
0 ignored issues
show
Deprecated Code introduced by
The constant Symfony\Component\HttpKe...terface::MASTER_REQUEST has been deprecated: since symfony/http-kernel 5.3, use MAIN_REQUEST instead. To ease the migration, this constant won't be removed until Symfony 7.0. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

312
        $this->assertSame($response, $httpCache->handle($request, /** @scrutinizer ignore-deprecated */ HttpKernelInterface::MASTER_REQUEST));

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
313 1
        $this->assertEquals(1, $simpleListener->calls);
314 1
    }
315
}
316
317
class TestListener implements EventSubscriberInterface
318
{
319
    /**
320
     * @var int Count how many times preHandle has been called
321
     */
322
    public $preHandleCalls = 0;
323
324
    /**
325
     * @var int Count how many times postHandle has been called
326
     */
327
    public $postHandleCalls = 0;
328
329
    /**
330
     * @var int Count how many times preStore has been called
331
     */
332
    public $preStoreCalls = 0;
333
334
    /**
335
     * @var int Count how many times preInvalidate has been called
336
     */
337
    public $preInvalidateCalls = 0;
338
339
    /**
340
     * @var Response A response to set during the preHandle
341
     */
342
    public $preHandleResponse;
343
344
    /**
345
     * @var Response A response to set during the postHandle
346
     */
347
    public $postHandleResponse;
348
349
    /**
350
     * @var Response A response to set during the preStore
351
     */
352
    public $preStoreResponse;
353
354
    /**
355
     * @var Response A response to set during the preInvalidate
356
     */
357
    public $preInvalidateResponse;
358
359
    /**
360
     * @var EventDispatchingHttpCacheTestCase To do assertions
361
     */
362
    private $test;
363
364
    /**
365
     * @var CacheInvalidation The kernel to ensure the event carries the correct kernel
366
     */
367
    private $kernel;
368
369
    /**
370
     * @var Request The request to ensure the event carries the correct request
371
     */
372
    private $request;
373
374 8
    public function __construct(
375
        EventDispatchingHttpCacheTestCase $test,
376
        CacheInvalidation $kernel,
377
        Request $request
378
    ) {
379 8
        $this->test = $test;
380 8
        $this->kernel = $kernel;
381 8
        $this->request = $request;
382 8
    }
383
384 8
    public static function getSubscribedEvents(): array
385
    {
386
        return [
387 8
            Events::PRE_HANDLE => 'preHandle',
388 8
            Events::POST_HANDLE => 'postHandle',
389 8
            Events::PRE_STORE => 'preStore',
390 8
            Events::PRE_INVALIDATE => 'preInvalidate',
391
        ];
392
    }
393
394 4
    public function preHandle(CacheEvent $event)
395
    {
396 4
        $this->test->assertSame($this->kernel, $event->getKernel());
397 4
        $this->test->assertSame($this->request, $event->getRequest());
398 4
        if ($this->preHandleResponse) {
399 2
            $event->setResponse($this->preHandleResponse);
400
        }
401 4
        ++$this->preHandleCalls;
402 4
    }
403
404 4
    public function postHandle(CacheEvent $event)
405
    {
406 4
        $this->test->assertSame($this->kernel, $event->getKernel());
407 4
        $this->test->assertSame($this->request, $event->getRequest());
408 4
        if ($this->postHandleResponse) {
409 2
            $event->setResponse($this->postHandleResponse);
410
        }
411 4
        ++$this->postHandleCalls;
412 4
    }
413
414 2
    public function preStore(CacheEvent $event)
415
    {
416 2
        $this->test->assertSame($this->kernel, $event->getKernel());
417 2
        $this->test->assertSame($this->request, $event->getRequest());
418 2
        if ($this->preStoreResponse) {
419 1
            $event->setResponse($this->preStoreResponse);
420
        }
421 2
        ++$this->preStoreCalls;
422 2
    }
423
424 2
    public function preInvalidate(CacheEvent $event)
425
    {
426 2
        $this->test->assertSame($this->kernel, $event->getKernel());
427 2
        $this->test->assertSame($this->request, $event->getRequest());
428 2
        if ($this->preInvalidateResponse) {
429 1
            $event->setResponse($this->preInvalidateResponse);
430
        }
431 2
        ++$this->preInvalidateCalls;
432 2
    }
433
}
434
435
class SimpleListener
436
{
437
    public $calls = 0;
438
439
    /**
440
     * @var EventDispatchingHttpCacheTestCase To do assertions
441
     */
442
    private $test;
443
444
    /**
445
     * @var CacheInvalidation The kernel to ensure the event carries the correct kernel
446
     */
447
    private $kernel;
448
449
    /**
450
     * @var Request The request to ensure the event carries the correct request
451
     */
452
    private $request;
453
454 1
    public function __construct(
455
        EventDispatchingHttpCacheTestCase $test,
456
        CacheInvalidation $kernel,
457
        Request $request
458
    ) {
459 1
        $this->test = $test;
460 1
        $this->kernel = $kernel;
461 1
        $this->request = $request;
462 1
    }
463
464 1
    public function callback(CacheEvent $event)
465
    {
466 1
        $this->test->assertSame($this->kernel, $event->getKernel());
467 1
        $this->test->assertSame($this->request, $event->getRequest());
468 1
        ++$this->calls;
469 1
    }
470
}
471