226 lines
7.4 KiB
PHP
Executable File
226 lines
7.4 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* Copyright © Magento, Inc. All rights reserved.
|
|
* See COPYING.txt for license details.
|
|
*/
|
|
declare(strict_types=1);
|
|
|
|
namespace Magento\GraphQlCache\Controller;
|
|
|
|
use Magento\Framework\App\DeploymentConfig\Reader;
|
|
use Magento\Framework\App\DeploymentConfig\Writer\PhpFormatter;
|
|
use Magento\Framework\App\Filesystem\DirectoryList;
|
|
use Magento\Framework\App\Request\Http as HttpRequest;
|
|
use Magento\Framework\App\Response\HttpInterface as HttpResponse;
|
|
use Magento\Framework\Config\File\ConfigFilePool;
|
|
use Magento\Framework\Filesystem;
|
|
use Magento\Framework\Registry;
|
|
use Magento\GraphQl\Controller\GraphQl as GraphQlController;
|
|
use Magento\GraphQlCache\Model\CacheableQuery;
|
|
use Magento\GraphQlCache\Model\CacheId\CacheIdCalculator;
|
|
use Magento\PageCache\Model\Cache\Type as PageCache;
|
|
use Magento\TestFramework\Helper\Bootstrap;
|
|
use Magento\TestFramework\ObjectManager;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* Abstract test class for Graphql cache tests
|
|
*
|
|
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
|
*/
|
|
abstract class AbstractGraphqlCacheTest extends TestCase
|
|
{
|
|
/**
|
|
* @var ObjectManager
|
|
*/
|
|
protected $objectManager;
|
|
|
|
/**
|
|
* @var Filesystem
|
|
*/
|
|
private $filesystem;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
private $envConfigPath;
|
|
|
|
/**
|
|
* @var Reader
|
|
*/
|
|
private $envConfigReader;
|
|
|
|
/**
|
|
* @var PhpFormatter
|
|
*/
|
|
private $formatter;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->objectManager = Bootstrap::getObjectManager();
|
|
$this->enablePageCachePlugin();
|
|
$this->enableCachebleQueryTestProxy();
|
|
}
|
|
|
|
/**
|
|
* If the cache id salt didn't exist in env.php before a GraphQL request it gets added. To prevent test failures
|
|
* due to a config getting changed (which is normally illegal), the salt needs to be removed from env.php after
|
|
* a test if it wasn't there before.
|
|
*
|
|
* @see \Magento\TestFramework\Isolation\DeploymentConfig
|
|
*
|
|
* @inheritdoc
|
|
*/
|
|
protected function runTest()
|
|
{
|
|
/** @var Reader $reader */
|
|
if (!$this->envConfigPath) {
|
|
/** @var ConfigFilePool $configFilePool */
|
|
$configFilePool = $this->objectManager->get(ConfigFilePool::class);
|
|
$this->envConfigPath = $configFilePool->getPath(ConfigFilePool::APP_ENV);
|
|
}
|
|
$this->envConfigReader = $this->envConfigReader ?: $this->objectManager->get(Reader::class);
|
|
$initialConfig = $this->envConfigReader->load(ConfigFilePool::APP_ENV);
|
|
|
|
try {
|
|
return parent::runTest();
|
|
} finally {
|
|
$this->formatter = $this->formatter ?: new PhpFormatter();
|
|
$this->filesystem = $this->filesystem ?: $this->objectManager->get(Filesystem::class);
|
|
$cacheSaltPathChunks = explode('/', CacheIdCalculator::SALT_CONFIG_PATH);
|
|
$currentConfig = $this->envConfigReader->load(ConfigFilePool::APP_ENV);
|
|
$resetConfig = $this->resetAddedSection($initialConfig, $currentConfig, $cacheSaltPathChunks);
|
|
$resetFileContents = $this->formatter->format($resetConfig);
|
|
$directoryWrite = $this->filesystem->getDirectoryWrite(DirectoryList::CONFIG);
|
|
$directoryWrite->writeFile($this->envConfigPath, $resetFileContents);
|
|
}
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
$this->disableCacheableQueryTestProxy();
|
|
$this->disablePageCachePlugin();
|
|
$this->flushPageCache();
|
|
}
|
|
|
|
protected function enablePageCachePlugin(): void
|
|
{
|
|
/** @var $registry Registry */
|
|
$registry = $this->objectManager->get(Registry::class);
|
|
$registry->register('use_page_cache_plugin', true, true);
|
|
}
|
|
|
|
protected function disablePageCachePlugin(): void
|
|
{
|
|
/** @var $registry Registry */
|
|
$registry = $this->objectManager->get(Registry::class);
|
|
$registry->unregister('use_page_cache_plugin');
|
|
}
|
|
|
|
protected function flushPageCache(): void
|
|
{
|
|
/** @var PageCache $fullPageCache */
|
|
$fullPageCache = $this->objectManager->get(PageCache::class);
|
|
$fullPageCache->clean();
|
|
}
|
|
|
|
/**
|
|
* Regarding the SuppressWarnings annotation below: the nested class below triggers a false rule match.
|
|
*
|
|
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
|
|
*/
|
|
private function enableCachebleQueryTestProxy(): void
|
|
{
|
|
$cacheableQueryProxy = new class($this->objectManager) extends CacheableQuery {
|
|
/** @var CacheableQuery */
|
|
private $delegate;
|
|
|
|
public function __construct(ObjectManager $objectManager)
|
|
{
|
|
$this->reset($objectManager);
|
|
}
|
|
|
|
public function reset(ObjectManager $objectManager): void
|
|
{
|
|
$this->delegate = $objectManager->create(CacheableQuery::class);
|
|
}
|
|
|
|
public function getCacheTags(): array
|
|
{
|
|
return $this->delegate->getCacheTags();
|
|
}
|
|
|
|
public function addCacheTags(array $cacheTags): void
|
|
{
|
|
$this->delegate->addCacheTags($cacheTags);
|
|
}
|
|
|
|
public function isCacheable(): bool
|
|
{
|
|
return $this->delegate->isCacheable();
|
|
}
|
|
|
|
public function setCacheValidity(bool $cacheable): void
|
|
{
|
|
$this->delegate->setCacheValidity($cacheable);
|
|
}
|
|
|
|
public function shouldPopulateCacheHeadersWithTags(): bool
|
|
{
|
|
return $this->delegate->shouldPopulateCacheHeadersWithTags();
|
|
}
|
|
};
|
|
$this->objectManager->addSharedInstance($cacheableQueryProxy, CacheableQuery::class);
|
|
}
|
|
|
|
private function disableCacheableQueryTestProxy(): void
|
|
{
|
|
$this->resetQueryCacheTags();
|
|
$this->objectManager->removeSharedInstance(CacheableQuery::class);
|
|
}
|
|
|
|
protected function resetQueryCacheTags(): void
|
|
{
|
|
$this->objectManager->get(CacheableQuery::class)->reset($this->objectManager);
|
|
}
|
|
|
|
protected function dispatchGraphQlGETRequest(array $queryParams): HttpResponse
|
|
{
|
|
$this->resetQueryCacheTags();
|
|
|
|
/** @var HttpRequest $request */
|
|
$request = $this->objectManager->get(HttpRequest::class);
|
|
$request->setPathInfo('/graphql');
|
|
$request->setMethod('GET');
|
|
$request->setParams($queryParams);
|
|
|
|
// required for \Magento\Framework\App\PageCache\Identifier to generate the correct cache key
|
|
$request->setUri(implode('?', [$request->getPathInfo(), http_build_query($queryParams)]));
|
|
|
|
return $this->objectManager->create(GraphQlController::class)->dispatch($request);
|
|
}
|
|
|
|
/**
|
|
* Go over the current deployment config and unset a section that was not present in the pre-test deployment config
|
|
*
|
|
* @param array $initial
|
|
* @param array $current
|
|
* @param string[] $chunks
|
|
* @return array
|
|
*/
|
|
private function resetAddedSection(array $initial, array $current, array $chunks): array
|
|
{
|
|
if ($chunks) {
|
|
$chunk = array_shift($chunks);
|
|
if (!isset($initial[$chunk])) {
|
|
if (isset($current[$chunk])) {
|
|
unset($current[$chunk]);
|
|
}
|
|
} elseif (isset($current[$chunk]) && is_array($initial[$chunk]) && is_array($current[$chunk])) {
|
|
$current[$chunk] = $this->resetAddedSection($initial[$chunk], $current[$chunk], $chunks);
|
|
}
|
|
}
|
|
return $current;
|
|
}
|
|
}
|