Your IP : 127.0.0.1
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\Framework\App\Test\Unit\PageCache;
use Laminas\Http\Header\CacheControl;
use Laminas\Http\Headers;
use Magento\Framework\App\Http\Context;
use Magento\Framework\App\Http\ContextFactory;
use Magento\Framework\App\PageCache\Cache;
use Magento\Framework\App\PageCache\Identifier;
use Magento\Framework\App\PageCache\Kernel;
use Magento\Framework\App\Request\Http;
use Magento\Framework\App\Response\HttpFactory;
use Magento\Framework\Serialize\SerializerInterface;
use Magento\PageCache\Model\Cache\Type;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class KernelTest extends TestCase
{
/** @var Kernel */
protected $kernel;
/** @var Cache|MockObject */
protected $cacheMock;
/** @var Identifier|MockObject */
protected $identifierMock;
/** @var Http|MockObject */
protected $requestMock;
/** @var \Magento\Framework\App\Response\Http|MockObject */
protected $responseMock;
/** @var MockObject|Type */
private $fullPageCacheMock;
/** @var \Magento\Framework\App\Response\Http|MockObject */
private $httpResponseMock;
/** @var ContextFactory|MockObject */
private $contextFactoryMock;
/** @var HttpFactory|MockObject */
private $httpFactoryMock;
/** @var SerializerInterface|MockObject */
private $serializer;
/** @var Context|MockObject */
private $contextMock;
/**
* Setup
*/
protected function setUp(): void
{
$headersMock = $this->createMock(Headers::class);
$this->cacheMock = $this->createMock(Cache::class);
$this->fullPageCacheMock = $this->createMock(Type::class);
$this->contextMock = $this->createMock(Context::class);
$this->httpResponseMock = $this->createMock(\Magento\Framework\App\Response\Http::class);
$this->identifierMock = $this->createMock(Identifier::class);
$this->requestMock = $this->createMock(Http::class);
$this->serializer = $this->getMockForAbstractClass(SerializerInterface::class);
$this->responseMock = $this->createMock(\Magento\Framework\App\Response\Http::class);
$this->contextFactoryMock = $this->createPartialMock(ContextFactory::class, ['create']);
$this->httpFactoryMock = $this->createPartialMock(HttpFactory::class, ['create']);
$this->responseMock->expects($this->any())->method('getHeaders')->willReturn($headersMock);
$this->kernel = new Kernel(
$this->cacheMock,
$this->identifierMock,
$this->requestMock,
$this->contextMock,
$this->contextFactoryMock,
$this->httpFactoryMock,
$this->serializer
);
$reflection = new \ReflectionClass(Kernel::class);
$reflectionProperty = $reflection->getProperty('fullPageCache');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($this->kernel, $this->fullPageCacheMock);
}
/**
* @dataProvider dataProviderForResultWithCachedData
* @param string $id
* @param mixed $cache
* @param bool $isGet
* @param bool $isHead
*/
public function testLoadWithCachedData($id, $cache, $isGet, $isHead)
{
$this->serializer->expects($this->once())
->method('unserialize')
->willReturnCallback(
function ($value) {
return json_decode($value, true);
}
);
$this->contextFactoryMock
->expects($this->once())
->method('create')
->with(
[
'data' => ['context_data'],
'default' => ['context_default_data']
]
)
->willReturn($this->contextMock);
$this->httpFactoryMock
->expects($this->once())
->method('create')
->with(['context' => $this->contextMock])
->willReturn($this->httpResponseMock);
$this->requestMock->expects($this->once())->method('isGet')->willReturn($isGet);
$this->requestMock->expects($this->any())->method('isHead')->willReturn($isHead);
$this->fullPageCacheMock->expects(
$this->any()
)->method(
'load'
)->with(
$id
)->willReturn(
json_encode($cache)
);
$this->httpResponseMock->expects($this->once())->method('setStatusCode')->with($cache['status_code']);
$this->httpResponseMock->expects($this->once())->method('setContent')->with($cache['content']);
$this->httpResponseMock->expects($this->once())->method('setHeader')->with(0, 'header', true);
$this->identifierMock->expects($this->any())->method('getValue')->willReturn($id);
$this->assertEquals($this->httpResponseMock, $this->kernel->load());
}
/**
* @return array
*/
public function dataProviderForResultWithCachedData()
{
$data = [
'context' => [
'data' => ['context_data'],
'default' => ['context_default_data']
],
'status_code' => 'status_code',
'content' => 'content',
'headers' => ['header']
];
return [
['existing key', $data, true, false],
['existing key', $data, false, true],
];
}
/**
* @dataProvider dataProviderForResultWithoutCachedData
* @param string $id
* @param mixed $cache
* @param bool $isGet
* @param bool $isHead
*/
public function testLoadWithoutCachedData($id, $cache, $isGet, $isHead)
{
$this->requestMock->expects($this->once())->method('isGet')->willReturn($isGet);
$this->requestMock->expects($this->any())->method('isHead')->willReturn($isHead);
$this->fullPageCacheMock->expects(
$this->any()
)->method(
'load'
)->with(
$id
)->willReturn(
json_encode($cache)
);
$this->identifierMock->expects($this->any())->method('getValue')->willReturn($id);
$this->assertFalse($this->kernel->load());
}
/**
* @return array
*/
public function dataProviderForResultWithoutCachedData()
{
return [
['existing key', [], false, false],
['non existing key', false, true, false],
['non existing key', false, false, false]
];
}
/**
* @param $httpCode
* @dataProvider testProcessSaveCacheDataProvider
*/
public function testProcessSaveCache($httpCode, $at)
{
$this->serializer->expects($this->once())
->method('serialize')
->willReturnCallback(
function ($value) {
return json_encode($value);
}
);
$cacheControlHeader = CacheControl::fromString(
'Cache-Control: public, max-age=100, s-maxage=100'
);
$this->responseMock->expects(
$this->at(0)
)->method(
'getHeader'
)->with(
'Cache-Control'
)->willReturn(
$cacheControlHeader
);
$this->responseMock->expects(
$this->any()
)->method(
'getHttpResponseCode'
)->willReturn($httpCode);
$this->requestMock->expects($this->once())
->method('isGet')
->willReturn(true);
$this->responseMock->expects($this->once())
->method('setNoCacheHeaders');
$this->responseMock->expects($this->at($at[0]))
->method('getHeader')
->with('X-Magento-Tags');
$this->responseMock->expects($this->at($at[1]))
->method('clearHeader')
->with('Set-Cookie');
$this->responseMock->expects($this->at($at[2]))
->method('clearHeader')
->with('X-Magento-Tags');
$this->fullPageCacheMock->expects($this->once())
->method('save');
$this->kernel->process($this->responseMock);
}
/**
* @return array
*/
public function testProcessSaveCacheDataProvider()
{
return [
[200, [3, 4, 5]],
[404, [4, 5, 6]]
];
}
/**
* @dataProvider processNotSaveCacheProvider
* @param string $cacheControlHeader
* @param int $httpCode
* @param bool $isGet
* @param bool $overrideHeaders
*/
public function testProcessNotSaveCache($cacheControlHeader, $httpCode, $isGet, $overrideHeaders)
{
$header = CacheControl::fromString("Cache-Control: $cacheControlHeader");
$this->responseMock->expects(
$this->once()
)->method(
'getHeader'
)->with(
'Cache-Control'
)->willReturn(
$header
);
$this->responseMock->expects($this->any())->method('getHttpResponseCode')->willReturn($httpCode);
$this->requestMock->expects($this->any())->method('isGet')->willReturn($isGet);
if ($overrideHeaders) {
$this->responseMock->expects($this->once())->method('setNoCacheHeaders');
}
$this->fullPageCacheMock->expects($this->never())->method('save');
$this->kernel->process($this->responseMock);
}
/**
* @return array
*/
public function processNotSaveCacheProvider()
{
return [
['private, max-age=100', 200, true, false],
['private, max-age=100', 200, false, false],
['private, max-age=100', 500, true, false],
['no-store, no-cache, must-revalidate, max-age=0', 200, true, false],
['no-store, no-cache, must-revalidate, max-age=0', 200, false, false],
['no-store, no-cache, must-revalidate, max-age=0', 404, true, false],
['no-store, no-cache, must-revalidate, max-age=0', 500, true, false],
['public, max-age=100, s-maxage=100', 500, true, true],
['public, max-age=100, s-maxage=100', 200, false, true]
];
}
}