Skip to content
This repository has been archived by the owner on Dec 19, 2019. It is now read-only.

GraphQl-167: Add support for '@magentoConfigFixture' annotation on API-functional tests #351

Merged
merged 6 commits into from
Jul 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\TestFramework\Annotation;

use Magento\Config\Model\Config;
use Magento\Config\Model\ResourceModel\Config as ConfigResource;
use Magento\Config\Model\ResourceModel\Config\Data\CollectionFactory;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\Store\Model\StoreManagerInterface;
use PHPUnit\Framework\TestCase;

/**
* @inheritDoc
*/
class ApiConfigFixture extends ConfigFixture
{
/**
* Original values for global configuration options that need to be restored
*
* @var array
*/
private $_globalConfigValues = [];

/**
* Original values for store-scoped configuration options that need to be restored
*
* @var array
*/
private $_storeConfigValues = [];

/**
* Values need to be deleted form the database
*
* @var array
*/
private $_valuesToDeleteFromDatabase = [];

/**
* Assign required config values and save original ones
*
* @param TestCase $test
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
*/
protected function _assignConfigData(TestCase $test)
{
$annotations = $test->getAnnotations();
if (!isset($annotations['method'][$this->annotation])) {
return;
}
foreach ($annotations['method'][$this->annotation] as $configPathAndValue) {
if (preg_match('/^.+?(?=_store\s)/', $configPathAndValue, $matches)) {
/* Store-scoped config value */
$storeCode = $matches[0] != 'current' ? $matches[0] : null;
$parts = preg_split('/\s+/', $configPathAndValue, 3);
list($configScope, $configPath, $requiredValue) = $parts + ['', '', ''];
$originalValue = $this->_getConfigValue($configPath, $storeCode);
$this->_storeConfigValues[$storeCode][$configPath] = $originalValue;
if ($this->checkIfValueExist($configPath, $storeCode)) {
$this->_valuesToDeleteFromDatabase[$storeCode][$configPath] = $requiredValue;
}
$this->_setConfigValue($configPath, $requiredValue, $storeCode);
} else {
/* Global config value */
list($configPath, $requiredValue) = preg_split('/\s+/', $configPathAndValue, 2);

$originalValue = $this->_getConfigValue($configPath);
$this->_globalConfigValues[$configPath] = $originalValue;
if ($this->checkIfValueExist($configPath)) {
$this->_valuesToDeleteFromDatabase['global'][$configPath] = $requiredValue;
}

$this->_setConfigValue($configPath, $requiredValue);
}
}
}

/**
* Restore original values for changed config options
*/
protected function _restoreConfigData()
{
$configResource = Bootstrap::getObjectManager()->get(ConfigResource::class);

/* Restore global values */
foreach ($this->_globalConfigValues as $configPath => $originalValue) {
if (isset($this->_valuesToDeleteFromDatabase['global'][$configPath])) {
$configResource->deleteConfig($configPath);
} else {
$this->_setConfigValue($configPath, $originalValue);
}
}
$this->_globalConfigValues = [];

/* Restore store-scoped values */
foreach ($this->_storeConfigValues as $storeCode => $originalData) {
foreach ($originalData as $configPath => $originalValue) {
if (empty($storeCode)) {
$storeCode = null;
}
if (isset($this->_valuesToDeleteFromDatabase[$storeCode][$configPath])) {
$scopeId = $this->getStoreIdByCode($storeCode);
$configResource->deleteConfig($configPath, 'stores', $scopeId);
} else {
$this->_setConfigValue($configPath, $originalValue, $storeCode);
}
}
}
$this->_storeConfigValues = [];
}

/**
* Load configs by path and scope
*
* @param string $configPath
* @param string $storeCode
* @return Config[]
*/
private function loadConfigs(string $configPath, string $storeCode = null): array
{
$configCollectionFactory = Bootstrap::getObjectManager()->get(CollectionFactory::class);
$collection = $configCollectionFactory->create();
$scope = $storeCode ? 'stores' : 'default';
$scopeId = $storeCode ? $this->getStoreIdByCode($storeCode) : 0;

$collection->addScopeFilter($scope, $scopeId, $configPath);
return $collection->getItems();
}

/**
* Check if config exist in the database
*
* @param string $configPath
* @param string|null $storeCode
*/
private function checkIfValueExist(string $configPath, string $storeCode = null): bool
{
$configs = $this->loadConfigs($configPath, $storeCode);

return !(bool)$configs;
}

/**
* Returns the store ID by the store code
*
* @param string $storeCode
* @return int
*/
private function getStoreIdByCode(string $storeCode): int
{
$storeManager = Bootstrap::getObjectManager()->get(StoreManagerInterface::class);
$store = $storeManager->getStore($storeCode);
return (int)$store->getId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<?php
/**
* Application configuration object. Used to access configuration when application is installed.
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

declare(strict_types=1);

namespace Magento\TestFramework\App;

use Magento\Framework\App\Config\MutableScopeConfigInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\TestFramework\ObjectManager;

/**
* @inheritdoc
*/
class MutableScopeConfig implements MutableScopeConfigInterface
{
/**
* @var Config
*/
private $testAppConfig;

/**
* @inheritdoc
*/
public function isSetFlag($path, $scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null)
{
return $this->getTestAppConfig()->isSetFlag($path, $scopeType, $scopeCode);
}

/**
* @inheritdoc
*/
public function getValue($path, $scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null)
{
return $this->getTestAppConfig()->getValue($path, $scopeType, $scopeCode);
}

/**
* @inheritdoc
*/
public function setValue(
$path,
$value,
$scopeType = \Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
$scopeCode = null
) {
$this->persistConfig($path, $value, $scopeType, $scopeCode);
return $this->getTestAppConfig()->setValue($path, $value, $scopeType, $scopeCode);
}

/**
* Clean app config cache
*
* @param string|null $type
* @return void
*/
public function clean()
{
$this->getTestAppConfig()->clean();
}

/**
* Retrieve test app config instance
*
* @return \Magento\TestFramework\App\Config
*/
private function getTestAppConfig()
{
if (!$this->testAppConfig) {
$this->testAppConfig = ObjectManager::getInstance()->get(ScopeConfigInterface::class);
}

return $this->testAppConfig;
}

/**
* Persist config in database
*
* @param string $path
* @param string $value
* @param string $scopeType
* @param string|null $scopeCode
*/
private function persistConfig($path, $value, $scopeType, $scopeCode): void
{
$pathParts = explode('/', $path);
$store = '';
if ($scopeType === \Magento\Store\Model\ScopeInterface::SCOPE_STORE) {
if ($scopeCode !== null) {
$store = ObjectManager::getInstance()
->get(\Magento\Store\Api\StoreRepositoryInterface::class)
->get($scopeCode)
->getId();
} else {
$store = ObjectManager::getInstance()
->get(\Magento\Store\Model\StoreManagerInterface::class)
->getStore()
->getId();
}
}
$configData = [
'section' => $pathParts[0],
'website' => '',
'store' => $store,
'groups' => [
$pathParts[1] => [
'fields' => [
$pathParts[2] => [
'value' => $value
]
]
]
]
];
ObjectManager::getInstance()
->get(\Magento\Config\Model\Config\Factory::class)
->create(['data' => $configData])
->save();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,34 @@
*/
namespace Magento\TestFramework\Bootstrap;

use Magento\TestFramework\Annotation\ApiConfigFixture;
use Magento\TestFramework\Annotation\ConfigFixture;

/**
* @inheritdoc
*/
class WebapiDocBlock extends \Magento\TestFramework\Bootstrap\DocBlock
{
/**
* Get list of subscribers. In addition, register <b>magentoApiDataFixture</b> annotation processing.
* Get list of subscribers.
*
* In addition, register magentoApiDataFixture and magentoConfigFixture
* annotation processors
*
* @param \Magento\TestFramework\Application $application
* @return array
*/
protected function _getSubscribers(\Magento\TestFramework\Application $application)
{
$subscribers = parent::_getSubscribers($application);
foreach ($subscribers as $key => $subscriber) {
if (get_class($subscriber) == ConfigFixture::class) {
unset($subscribers[$key]);
}
}
$subscribers[] = new \Magento\TestFramework\Annotation\ApiDataFixture($this->_fixturesBaseDir);
$subscribers[] = new ApiConfigFixture();

return $subscribers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@
*/
class StoreConfigTest extends GraphQlAbstract
{
protected function setUp()
{
$this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/167');
}

/**
* @magentoApiDataFixture Magento/Store/_files/store.php
* @magentoConfigFixture default_store catalog/seo/product_url_suffix test_product_suffix
* @magentoConfigFixture default_store catalog/seo/category_url_suffix test_category_suffix
* @magentoConfigFixture default_store catalog/seo/title_separator ___
* @magentoConfigFixture default_store catalog/frontend/list_mode 2
* @magentoConfigFixture default_store catalog/frontend/grid_per_page_values 16
* @magentoConfigFixture default_store catalog/frontend/list_per_page_values 8
* @magentoConfigFixture default_store catalog/frontend/grid_per_page 16
* @magentoConfigFixture default_store catalog/frontend/list_per_page 8
* @magentoConfigFixture default_store catalog/frontend/default_sort_by asc
*/
public function testGetStoreConfig()
{
Expand All @@ -43,6 +47,14 @@ public function testGetStoreConfig()
$response = $this->graphQlQuery($query);
$this->assertArrayHasKey('storeConfig', $response);

//TODO: provide assertions after unmarking test as incomplete
$this->assertEquals('test_product_suffix', $response['storeConfig']['product_url_suffix']);
$this->assertEquals('test_category_suffix', $response['storeConfig']['category_url_suffix']);
$this->assertEquals('___', $response['storeConfig']['title_separator']);
$this->assertEquals('2', $response['storeConfig']['list_mode']);
$this->assertEquals('16', $response['storeConfig']['grid_per_page_values']);
$this->assertEquals(16, $response['storeConfig']['grid_per_page']);
$this->assertEquals('8', $response['storeConfig']['list_per_page_values']);
$this->assertEquals(8, $response['storeConfig']['list_per_page']);
$this->assertEquals('asc', $response['storeConfig']['catalog_default_sort_by']);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,12 @@ public function testAddProductIfQuantityIsNotAvailable()
/**
* @magentoApiDataFixture Magento/Catalog/_files/products.php
* @magentoApiDataFixture Magento/Checkout/_files/active_quote.php
* @magentoConfigFixture default cataloginventory/item_options/max_sale_qty 5
* @magentoConfigFixture default_store cataloginventory/item_options/max_sale_qty 5
* @expectedException \Exception
* @expectedExceptionMessage The most you may purchase is 5.
*/
public function testAddMoreProductsThatAllowed()
{
$this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/167');

$sku = 'custom-design-simple-product';
$quantity = 7;
$maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

use Magento\TestFramework\TestCase\GraphQlAbstract;

/**
* Test for the product only x left in stock
*/
class ProductOnlyXLeftInStockTest extends GraphQlAbstract
{
/**
Expand Down Expand Up @@ -42,7 +45,6 @@ public function testQueryProductOnlyXLeftInStockDisabled()
*/
public function testQueryProductOnlyXLeftInStockEnabled()
{
$this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/167');
$productSku = 'simple';

$query = <<<QUERY
Expand Down
Loading