123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Config\Console\Command;
- use Magento\Config\Model\Config\Backend\Admin\Custom;
- use Magento\Config\Model\Config\Structure\Converter;
- use Magento\Config\Model\Config\Structure\Data as StructureData;
- use Magento\Directory\Model\Currency;
- use Magento\Framework\App\Config\ConfigPathResolver;
- use Magento\Framework\App\Config\ScopeConfigInterface;
- use Magento\Framework\App\DeploymentConfig\FileReader;
- use Magento\Framework\App\DeploymentConfig\Writer;
- use Magento\Framework\App\Filesystem\DirectoryList;
- use Magento\Framework\Config\File\ConfigFilePool;
- use Magento\Framework\Console\Cli;
- use Magento\Framework\Filesystem;
- use Magento\Framework\ObjectManagerInterface;
- use Magento\Framework\Stdlib\ArrayManager;
- use Magento\Store\Model\ScopeInterface;
- use Magento\TestFramework\Helper\Bootstrap;
- use Magento\Framework\App\Config\ReinitableConfigInterface;
- use PHPUnit_Framework_MockObject_MockObject as Mock;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- /**
- * Tests the different flows of config:set command.
- *
- * @inheritdoc
- * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- * @magentoDbIsolation enabled
- */
- class ConfigSetCommandTest extends \PHPUnit\Framework\TestCase
- {
- /**
- * @var ObjectManagerInterface
- */
- private $objectManager;
- /**
- * @var InputInterface|Mock
- */
- private $inputMock;
- /**
- * @var OutputInterface|Mock
- */
- private $outputMock;
- /**
- * @var ScopeConfigInterface
- */
- private $scopeConfig;
- /**
- * @var FileReader
- */
- private $reader;
- /**
- * @var Filesystem
- */
- private $filesystem;
- /**
- * @var ConfigFilePool
- */
- private $configFilePool;
- /**
- * @var ArrayManager
- */
- private $arrayManager;
- /**
- * @var array
- */
- private $config;
- /**
- * @var ReinitableConfigInterface
- */
- private $appConfig;
- /**
- * @inheritdoc
- */
- protected function setUp()
- {
- Bootstrap::getInstance()->reinitialize();
- $this->objectManager = Bootstrap::getObjectManager();
- $this->extendSystemStructure();
- $this->scopeConfig = $this->objectManager->get(ScopeConfigInterface::class);
- $this->reader = $this->objectManager->get(FileReader::class);
- $this->filesystem = $this->objectManager->get(Filesystem::class);
- $this->configFilePool = $this->objectManager->get(ConfigFilePool::class);
- $this->arrayManager = $this->objectManager->get(ArrayManager::class);
- $this->appConfig = $this->objectManager->get(ReinitableConfigInterface::class);
- // Snapshot of configuration.
- $this->config = $this->loadConfig();
- // Mocks for objects.
- $this->inputMock = $this->getMockBuilder(InputInterface::class)
- ->getMockForAbstractClass();
- $this->outputMock = $this->getMockBuilder(OutputInterface::class)
- ->getMockForAbstractClass();
- }
- /**
- * @inheritdoc
- */
- protected function tearDown()
- {
- $this->filesystem->getDirectoryWrite(DirectoryList::CONFIG)->writeFile(
- $this->configFilePool->getPath(ConfigFilePool::APP_ENV),
- "<?php\n return array();\n"
- );
- /** @var Writer $writer */
- $writer = $this->objectManager->get(Writer::class);
- $writer->saveConfig([ConfigFilePool::APP_ENV => $this->config]);
- $this->appConfig->reinit();
- }
- /**
- * Add test system structure to main system structure
- *
- * @return void
- */
- private function extendSystemStructure()
- {
- $document = new \DOMDocument();
- $document->load(__DIR__ . '/../../_files/system.xml');
- $converter = $this->objectManager->get(Converter::class);
- $systemConfig = $converter->convert($document);
- $structureData = $this->objectManager->get(StructureData::class);
- $structureData->merge($systemConfig);
- }
- /**
- * @return array
- */
- private function loadConfig()
- {
- return $this->reader->load(ConfigFilePool::APP_ENV);
- }
- /**
- * Tests lockable flow.
- * Expects to save value and then error on saving duplicate value.
- *
- * @param string $path
- * @param string $value
- * @param string $scope
- * @param string $scopeCode
- * @magentoDbIsolation enabled
- * @dataProvider runLockDataProvider
- */
- public function testRunLockEnv($path, $value, $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null)
- {
- $this->inputMock->expects($this->any())
- ->method('getArgument')
- ->willReturnMap([
- [ConfigSetCommand::ARG_PATH, $path],
- [ConfigSetCommand::ARG_VALUE, $value]
- ]);
- $this->inputMock->expects($this->any())
- ->method('getOption')
- ->willReturnMap([
- [ConfigSetCommand::OPTION_LOCK_ENV, true],
- [ConfigSetCommand::OPTION_SCOPE, $scope],
- [ConfigSetCommand::OPTION_SCOPE_CODE, $scopeCode]
- ]);
- $this->outputMock->expects($this->exactly(2))
- ->method('writeln')
- ->withConsecutive(
- ['<info>Value was saved in app/etc/env.php and locked.</info>'],
- ['<info>Value was saved in app/etc/env.php and locked.</info>']
- );
- /** @var ConfigSetCommand $command */
- $command = $this->objectManager->create(ConfigSetCommand::class);
- /** @var ConfigPathResolver $resolver */
- $resolver = $this->objectManager->get(ConfigPathResolver::class);
- $status = $command->run($this->inputMock, $this->outputMock);
- $configPath = $resolver->resolve($path, $scope, $scopeCode, 'system');
- $this->assertSame(Cli::RETURN_SUCCESS, $status);
- $this->assertSame($value, $this->arrayManager->get($configPath, $this->loadConfig()));
- $status = $command->run($this->inputMock, $this->outputMock);
- $this->appConfig->reinit();
- $this->assertSame(Cli::RETURN_SUCCESS, $status);
- }
- /**
- * Retrieves variations with path, value, scope and scope code.
- *
- * @return array
- */
- public function runLockDataProvider()
- {
- return [
- ['general/region/display_all', '1'],
- ['general/region/state_required', 'BR,FR', ScopeInterface::SCOPE_WEBSITE, 'base'],
- ['admin/security/use_form_key', '0'],
- ['general/group/subgroup/field', 'default_value'],
- ['general/group/subgroup/field', 'website_value', ScopeInterface::SCOPE_WEBSITE, 'base'],
- ];
- }
- /**
- * Tests the extended flow.
- *
- * @param string $path
- * @param string $value
- * @param string $scope
- * @param string $scopeCode
- * @magentoDbIsolation enabled
- * @dataProvider runExtendedDataProvider
- */
- public function testRunExtended(
- $path,
- $value,
- $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
- $scopeCode = null
- ) {
- $arguments = [
- [ConfigSetCommand::ARG_PATH, $path],
- [ConfigSetCommand::ARG_VALUE, $value]
- ];
- $options = [
- [ConfigSetCommand::OPTION_SCOPE, $scope],
- [ConfigSetCommand::OPTION_SCOPE_CODE, $scopeCode]
- ];
- $optionsLock = array_merge($options, [[ConfigSetCommand::OPTION_LOCK_ENV, true]]);
- /** @var ConfigPathResolver $resolver */
- $resolver = $this->objectManager->get(ConfigPathResolver::class);
- /** @var array $configPath */
- $configPath = $resolver->resolve($path, $scope, $scopeCode, 'system');
- $this->runCommand($arguments, $options, '<info>Value was saved.</info>');
- $this->runCommand($arguments, $options, '<info>Value was saved.</info>');
- $this->assertSame(
- $value,
- $this->scopeConfig->getValue($path, $scope, $scopeCode)
- );
- $this->assertSame(null, $this->arrayManager->get($configPath, $this->loadConfig()));
- $this->runCommand($arguments, $optionsLock, '<info>Value was saved in app/etc/env.php and locked.</info>');
- $this->runCommand($arguments, $optionsLock, '<info>Value was saved in app/etc/env.php and locked.</info>');
- $this->assertSame($value, $this->arrayManager->get($configPath, $this->loadConfig()));
- }
- /**
- * Runs pre-configured command.
- *
- * @param array $arguments
- * @param array $options
- * @param string $expectedMessage
- * @param int $expectedCode
- */
- private function runCommand(
- array $arguments,
- array $options,
- $expectedMessage = '',
- $expectedCode = Cli::RETURN_SUCCESS
- ) {
- $input = clone $this->inputMock;
- $output = clone $this->outputMock;
- $input->expects($this->any())
- ->method('getArgument')
- ->willReturnMap($arguments);
- $input->expects($this->any())
- ->method('getOption')
- ->willReturnMap($options);
- $output->expects($this->once())
- ->method('writeln')
- ->with($expectedMessage);
- /** @var ConfigSetCommand $command */
- $command = $this->objectManager->create(ConfigSetCommand::class);
- $status = $command->run($input, $output);
- $this->appConfig->reinit();
- $this->assertSame($expectedCode, $status);
- }
- /**
- * Retrieves variations with path, value, scope and scope code.
- *
- * @return array
- */
- public function runExtendedDataProvider()
- {
- return $this->runLockDataProvider();
- }
- /**
- * @param string $path Config path
- * @param string $value Value of config is tried to be set
- * @param string $message Message command output
- * @param string $scope
- * @param $scopeCode string|null
- * @dataProvider configSetValidationErrorDataProvider
- * @magentoDbIsolation disabled
- */
- public function testConfigSetValidationError(
- $path,
- $value,
- $message,
- $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
- $scopeCode = null
- ) {
- $this->setConfigFailure($path, $value, $message, $scope, $scopeCode);
- }
- /**
- * Data provider for testConfigSetValidationError
- *
- * @return array
- */
- public function configSetValidationErrorDataProvider()
- {
- return [
- //wrong value for URL - checked by backend model of URL field
- [
- Custom::XML_PATH_UNSECURE_BASE_URL,
- 'value',
- 'Invalid Base URL. Value must be a URL or one of placeholders: {{base_url}}'
- ],
- //set not existed field path
- [
- 'test/test/test',
- 'value',
- 'The "test/test/test" path doesn\'t exist. Verify and try again.'
- ],
- //wrong scope or scope code
- [
- Custom::XML_PATH_GENERAL_LOCALE_CODE,
- 'en_UK',
- 'A scope is missing. Enter a scope and try again.',
- ''
- ],
- [
- Custom::XML_PATH_GENERAL_LOCALE_CODE,
- 'en_UK',
- 'A scope code is missing. Enter a code and try again.',
- ScopeInterface::SCOPE_WEBSITE
- ],
- [
- Custom::XML_PATH_GENERAL_LOCALE_CODE,
- 'en_UK',
- 'A scope code is missing. Enter a code and try again.',
- ScopeInterface::SCOPE_STORE
- ],
- [
- Custom::XML_PATH_GENERAL_LOCALE_CODE,
- 'en_UK',
- 'The "wrong_scope" value doesn\'t exist. Enter another value and try again.',
- 'wrong_scope',
- 'base'
- ],
- [
- Custom::XML_PATH_GENERAL_LOCALE_CODE,
- 'en_UK',
- 'The "wrong_website_code" value doesn\'t exist. Enter another value and try again.',
- ScopeInterface::SCOPE_WEBSITE,
- 'wrong_website_code'
- ],
- [
- Custom::XML_PATH_GENERAL_LOCALE_CODE,
- 'en_UK',
- 'The "wrong_store_code" value doesn\'t exist. Enter another value and try again.',
- ScopeInterface::SCOPE_STORE,
- 'wrong_store_code'
- ],
- [
- Currency::XML_PATH_CURRENCY_DEFAULT,
- 'GBP',
- 'Sorry, the default display currency you selected is not available in allowed currencies.'
- ],
- [
- Currency::XML_PATH_CURRENCY_ALLOW,
- 'GBP',
- 'Default display currency "US Dollar" is not available in allowed currencies.'
- ]
- ];
- }
- /**
- * Saving values with successful validation
- *
- * @magentoDbIsolation enabled
- */
- public function testConfigSetCurrency()
- {
- /**
- * Checking saving currency as they are depend on each other.
- * Default currency can not be changed to new value if this value does not exist in allowed currency
- * that is why allowed currency is changed first by adding necessary value,
- * then old value is removed after changing default currency
- */
- $this->setConfigSuccess(Currency::XML_PATH_CURRENCY_ALLOW, 'USD,GBP');
- $this->setConfigSuccess(Currency::XML_PATH_CURRENCY_DEFAULT, 'GBP');
- $this->setConfigSuccess(Currency::XML_PATH_CURRENCY_ALLOW, 'GBP');
- }
- /**
- * Saving values with successful validation
- *
- * @dataProvider configSetValidDataProvider
- * @magentoDbIsolation enabled
- */
- public function testConfigSetValid()
- {
- $this->setConfigSuccess(Custom::XML_PATH_UNSECURE_BASE_URL, 'http://magento2.local/');
- $this->setConfigSuccess(Custom::XML_PATH_GENERAL_LOCALE_CODE, 'en_UK', ScopeInterface::SCOPE_WEBSITE, 'base');
- $this->setConfigSuccess(Custom::XML_PATH_GENERAL_LOCALE_CODE, 'en_AU', ScopeInterface::SCOPE_STORE, 'default');
- }
- /**
- * Data provider for testConfigSetValid
- *
- * @return array
- */
- public function configSetValidDataProvider()
- {
- return [
- [Custom::XML_PATH_UNSECURE_BASE_URL, 'http://magento2.local/'],
- [Custom::XML_PATH_GENERAL_LOCALE_CODE, 'en_UK', ScopeInterface::SCOPE_WEBSITE, 'base'],
- [Custom::XML_PATH_GENERAL_LOCALE_CODE, 'en_AU', ScopeInterface::SCOPE_STORE, 'default'],
- [Custom::XML_PATH_ADMIN_SECURITY_USEFORMKEY, '0']
- ];
- }
- /**
- * Set configuration and check this value from DB with success message this command should display
- *
- * @param string $path Config path
- * @param string $value Value of config is tried to be set
- * @param string $scope
- * @param string|null $scopeCode
- */
- private function setConfigSuccess(
- $path,
- $value,
- $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
- $scopeCode = null
- ) {
- $status = $this->setConfig($path, $value, '<info>Value was saved.</info>', $scope, $scopeCode);
- $this->assertSame(Cli::RETURN_SUCCESS, $status);
- $this->assertSame(
- $value,
- $this->scopeConfig->getValue($path, $scope, $scopeCode)
- );
- }
- /**
- * Set configuration value with some error
- * and check that this value was not saved to DB and appropriate error message was displayed
- *
- * @param string $path Config path
- * @param string $value Value of config is tried to be set
- * @param string $message Message command output
- * @param string $scope
- * @param string|null $scopeCode
- */
- private function setConfigFailure(
- $path,
- $value,
- $message,
- $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
- $scopeCode = null
- ) {
- $status = $this->setConfig($path, $value, '<error>' . $message . '</error>', $scope, $scopeCode);
- $this->assertSame(Cli::RETURN_FAILURE, $status);
- $this->assertNotSame(
- $value,
- $this->scopeConfig->getValue($path),
- "Values are the same '$value' and '{$this->scopeConfig->getValue($path)}' for $path"
- );
- }
- /**
- * @param string $path Config path
- * @param string $value Value of config is tried to be set
- * @param string $message Message command output
- * @param string $scope
- * @param string|null $scopeCode
- * @return int Status that command returned
- */
- private function setConfig($path, $value, $message, $scope, $scopeCode)
- {
- $input = clone $this->inputMock;
- $output = clone $this->outputMock;
- $input->expects($this->any())
- ->method('getArgument')
- ->willReturnMap([
- [ConfigSetCommand::ARG_PATH, $path],
- [ConfigSetCommand::ARG_VALUE, $value]
- ]);
- $input->expects($this->any())
- ->method('getOption')
- ->willReturnMap([
- [ConfigSetCommand::OPTION_SCOPE, $scope],
- [ConfigSetCommand::OPTION_SCOPE_CODE, $scopeCode]
- ]);
- $output->expects($this->once())
- ->method('writeln')
- ->with($message);
- /** @var ConfigSetCommand $command */
- $command = $this->objectManager->create(ConfigSetCommand::class);
- $status = $command->run($input, $output);
- return $status;
- }
- }
|