diff --git a/app/code/Magento/Backup/Test/Unit/Controller/Adminhtml/Index/RollbackTest.php b/app/code/Magento/Backup/Test/Unit/Controller/Adminhtml/Index/RollbackTest.php new file mode 100644 index 0000000000000..9f306cfc576d8 --- /dev/null +++ b/app/code/Magento/Backup/Test/Unit/Controller/Adminhtml/Index/RollbackTest.php @@ -0,0 +1,288 @@ +objectManagerMock = $this->getMockBuilder(\Magento\Framework\ObjectManagerInterface::class) + ->getMock(); + $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class) + ->setMethods(['initForward', 'setDispatched', 'isAjax']) + ->getMockForAbstractClass(); + $this->responseMock = $this->getMockBuilder(\Magento\Framework\App\ResponseInterface::class) + ->setMethods(['setRedirect', 'representJson']) + ->getMockForAbstractClass(); + $this->backupModelFactoryMock = $this->getMockBuilder(\Magento\Backup\Model\BackupFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->backupModelMock = $this->getMockBuilder(\Magento\Backup\Model\Backup::class) + ->disableOriginalConstructor() + ->setMethods(['getTime', 'exists', 'getSize', 'output', 'validateUserPassword']) + ->getMock(); + $this->backupResourceModelMock = $this->getMockBuilder(\Magento\Backup\Model\ResourceModel\Db::class) + ->disableOriginalConstructor() + ->getMock(); + $this->dataHelperMock = $this->getMockBuilder(\Magento\Backup\Helper\Data::class) + ->disableOriginalConstructor() + ->setMethods(['isRollbackAllowed', 'getBackupsDir', 'invalidateCache']) + ->getMock(); + $this->fileFactoryMock = $this->getMockBuilder(\Magento\Framework\App\Response\Http\FileFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->resultRedirectFactoryMock = + $this->getMockBuilder(\Magento\Backend\Model\View\Result\RedirectFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->resultRedirectMock = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class) + ->disableOriginalConstructor() + ->getMock(); + $this->resultForwardMock = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Forward::class) + ->disableOriginalConstructor() + ->getMock(); + $this->backupFactoryMock = $this->getMockBuilder(\Magento\Framework\Backup\Factory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->backupManagerMock = $this->getMockBuilder(\Magento\Framework\Backup\BackupInterface::class) + ->setMethods(['setName']) + ->getMockForAbstractClass(); + $this->objectManager = new ObjectManager($this); + $this->context = $this->objectManager->getObject( + \Magento\Backend\App\Action\Context::class, + [ + 'objectManager' => $this->objectManagerMock, + 'request' => $this->requestMock, + 'response' => $this->responseMock, + 'resultRedirectFactory' => $this->resultRedirectFactoryMock + ] + ); + $this->rollbackController = $this->objectManager->getObject( + \Magento\Backup\Controller\Adminhtml\Index\Rollback::class, + [ + 'context' => $this->context, + 'backupFactory' => $this->backupFactoryMock, + 'backupModelFactory' => $this->backupModelFactoryMock, + 'fileFactory' => $this->fileFactoryMock + ] + ); + } + + public function testExecuteRollbackDisabled() + { + $rollbackAllowed = false; + + $this->dataHelperMock->expects($this->once()) + ->method('isRollbackAllowed') + ->willReturn($rollbackAllowed); + $this->objectManagerMock->expects($this->once()) + ->method('get') + ->with(\Magento\Backup\Helper\Data::class) + ->willReturn($this->dataHelperMock); + + $this->assertSame($this->responseMock, $this->rollbackController->execute()); + } + + public function testExecuteBackupNotFound() + { + $rollbackAllowed = true; + $isAjax = true; + $time = 0; + $type = 'db'; + $exists = false; + + $this->dataHelperMock->expects($this->once()) + ->method('isRollbackAllowed') + ->willReturn($rollbackAllowed); + $this->objectManagerMock->expects($this->atLeastOnce()) + ->method('get') + ->with(\Magento\Backup\Helper\Data::class) + ->willReturn($this->dataHelperMock); + $this->requestMock->expects($this->once()) + ->method('isAjax') + ->willReturn($isAjax); + $this->backupModelMock->expects($this->atLeastOnce()) + ->method('getTime') + ->willReturn($time); + $this->backupModelMock->expects($this->any()) + ->method('exists') + ->willReturn($exists); + $this->requestMock->expects($this->any()) + ->method('getParam') + ->willReturnMap( + [ + ['time', null, $time], + ['type', null, $type] + ] + ); + $this->backupModelFactoryMock->expects($this->once()) + ->method('create') + ->with($time, $type) + ->willReturn($this->backupModelMock); + + $this->assertSame($this->responseMock, $this->rollbackController->execute()); + } + + public function testExecute() + { + $rollbackAllowed = true; + $isAjax = true; + $time = 1; + $type = 'db'; + $exists = true; + $passwordValid = true; + + $this->dataHelperMock->expects($this->once()) + ->method('isRollbackAllowed') + ->willReturn($rollbackAllowed); + $this->objectManagerMock->expects($this->any()) + ->method('get') + ->with(\Magento\Backup\Helper\Data::class) + ->willReturn($this->dataHelperMock); + $this->requestMock->expects($this->once()) + ->method('isAjax') + ->willReturn($isAjax); + $this->backupModelMock->expects($this->atLeastOnce()) + ->method('getTime') + ->willReturn($time); + $this->backupModelMock->expects($this->any()) + ->method('exists') + ->willReturn($exists); + $this->requestMock->expects($this->any()) + ->method('getParam') + ->willReturnMap( + [ + ['time', null, $time], + ['type', null, $type] + ] + ); + $this->backupModelFactoryMock->expects($this->once()) + ->method('create') + ->with($time, $type) + ->willReturn($this->backupModelMock); + $this->backupManagerMock->expects($this->once()) + ->method('setBackupExtension') + ->willReturn($this->backupManagerMock); + $this->backupManagerMock->expects($this->once()) + ->method('setTime') + ->willReturn($this->backupManagerMock); + $this->backupManagerMock->expects($this->once()) + ->method('setBackupsDir') + ->willReturn($this->backupManagerMock); + $this->backupManagerMock->expects($this->once()) + ->method('setName') + ->willReturn($this->backupManagerMock); + $this->backupManagerMock->expects($this->once()) + ->method('setResourceModel') + ->willReturn($this->backupManagerMock); + $this->backupFactoryMock->expects($this->once()) + ->method('create') + ->with($type) + ->willReturn($this->backupManagerMock); + $this->objectManagerMock->expects($this->at(2)) + ->method('create') + ->with(\Magento\Backup\Model\ResourceModel\Db::class, []) + ->willReturn($this->backupResourceModelMock); + $this->objectManagerMock->expects($this->at(3)) + ->method('create') + ->with(\Magento\Backup\Model\Backup::class, []) + ->willReturn($this->backupModelMock); + $this->backupModelMock->expects($this->once()) + ->method('validateUserPassword') + ->willReturn($passwordValid); + + $this->rollbackController->execute(); + } +} diff --git a/app/code/Magento/Developer/Model/Css/PreProcessor/FileGenerator/PublicationDecorator.php b/app/code/Magento/Developer/Model/Css/PreProcessor/FileGenerator/PublicationDecorator.php index 57af124ba1182..ab7b46ed35d7e 100644 --- a/app/code/Magento/Developer/Model/Css/PreProcessor/FileGenerator/PublicationDecorator.php +++ b/app/code/Magento/Developer/Model/Css/PreProcessor/FileGenerator/PublicationDecorator.php @@ -5,6 +5,9 @@ */ namespace Magento\Developer\Model\Css\PreProcessor\FileGenerator; +use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\App\State; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Filesystem; use Magento\Framework\View\Asset\Repository; use Magento\Framework\App\View\Asset\Publisher; @@ -36,6 +39,11 @@ class PublicationDecorator extends RelatedGenerator */ private $hasRelatedPublishing; + /** + * @var State + */ + private $state; + /** * Constructor * @@ -66,12 +74,27 @@ public function __construct( protected function generateRelatedFile($relatedFileId, LocalInterface $asset) { $relatedAsset = parent::generateRelatedFile($relatedFileId, $asset); - if ($this->hasRelatedPublishing - || WorkflowType::CLIENT_SIDE_COMPILATION === $this->scopeConfig->getValue(WorkflowType::CONFIG_NAME_PATH) - ) { + $isClientSideCompilation = + $this->getState()->getMode() !== State::MODE_PRODUCTION + && WorkflowType::CLIENT_SIDE_COMPILATION === $this->scopeConfig->getValue(WorkflowType::CONFIG_NAME_PATH); + + if ($this->hasRelatedPublishing || $isClientSideCompilation) { $this->assetPublisher->publish($relatedAsset); } return $relatedAsset; } + + /** + * @return State + * @deprecated + */ + private function getState() + { + if (null === $this->state) { + $this->state = ObjectManager::getInstance()->get(State::class); + } + + return $this->state; + } } diff --git a/app/code/Magento/Developer/Model/View/Asset/PreProcessor/PreprocessorStrategy.php b/app/code/Magento/Developer/Model/View/Asset/PreProcessor/PreprocessorStrategy.php index a3051ce443b19..aa40db410a4ce 100644 --- a/app/code/Magento/Developer/Model/View/Asset/PreProcessor/PreprocessorStrategy.php +++ b/app/code/Magento/Developer/Model/View/Asset/PreProcessor/PreprocessorStrategy.php @@ -5,6 +5,9 @@ */ namespace Magento\Developer\Model\View\Asset\PreProcessor; +use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\State; use Magento\Framework\View\Asset\PreProcessor; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Developer\Model\Config\Source\WorkflowType; @@ -31,6 +34,11 @@ class PreprocessorStrategy implements PreProcessorInterface */ private $scopeConfig; + /** + * @var State + */ + private $state; + /** * Constructor * @@ -56,10 +64,26 @@ public function __construct( */ public function process(PreProcessor\Chain $chain) { - if (WorkflowType::CLIENT_SIDE_COMPILATION === $this->scopeConfig->getValue(WorkflowType::CONFIG_NAME_PATH)) { + $isClientSideCompilation = + $this->getState()->getMode() !== State::MODE_PRODUCTION + && WorkflowType::CLIENT_SIDE_COMPILATION === $this->scopeConfig->getValue(WorkflowType::CONFIG_NAME_PATH); + + if ($isClientSideCompilation) { $this->frontendCompilation->process($chain); } else { $this->alternativeSource->process($chain); } } + + /** + * @return State + * @deprecated + */ + private function getState() + { + if (null === $this->state) { + $this->state = ObjectManager::getInstance()->get(State::class); + } + return $this->state; + } } diff --git a/app/code/Magento/Developer/Model/View/Page/Config/RendererFactory.php b/app/code/Magento/Developer/Model/View/Page/Config/RendererFactory.php index c6e68be05acc9..3301d4b553c63 100644 --- a/app/code/Magento/Developer/Model/View/Page/Config/RendererFactory.php +++ b/app/code/Magento/Developer/Model/View/Page/Config/RendererFactory.php @@ -6,6 +6,8 @@ namespace Magento\Developer\Model\View\Page\Config; use Magento\Developer\Model\Config\Source\WorkflowType; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\State; use Magento\Store\Model\ScopeInterface; /** @@ -58,7 +60,9 @@ public function __construct( */ public function create(array $data = []) { - $renderer = $this->scopeConfig->getValue(WorkflowType::CONFIG_NAME_PATH, ScopeInterface::SCOPE_STORE); + $renderer = $this->objectManager->get(State::class)->getMode() === State::MODE_PRODUCTION ? + WorkflowType::SERVER_SIDE_COMPILATION : + $this->scopeConfig->getValue(WorkflowType::CONFIG_NAME_PATH, ScopeInterface::SCOPE_STORE); return $this->objectManager->create( $this->rendererTypes[$renderer], diff --git a/app/code/Magento/Developer/Test/Unit/Model/Css/PreProcessor/FileGenerator/PublicationDecoratorTest.php b/app/code/Magento/Developer/Test/Unit/Model/Css/PreProcessor/FileGenerator/PublicationDecoratorTest.php index cddab4d253acc..8233437cf927f 100644 --- a/app/code/Magento/Developer/Test/Unit/Model/Css/PreProcessor/FileGenerator/PublicationDecoratorTest.php +++ b/app/code/Magento/Developer/Test/Unit/Model/Css/PreProcessor/FileGenerator/PublicationDecoratorTest.php @@ -5,71 +5,131 @@ */ namespace Magento\Developer\Test\Unit\Model\Css\PreProcessor\FileGenerator; +use Magento\Framework\App\State; +use Magento\Framework\App\View\Asset\Publisher; +use Magento\Framework\Css\PreProcessor\Instruction\Import; use Magento\Framework\Filesystem; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Css\PreProcessor\File\Temporary; use Magento\Developer\Model\Css\PreProcessor\FileGenerator\PublicationDecorator; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\View\Asset\File; +use Magento\Framework\View\Asset\LocalInterface; +use Magento\Framework\View\Asset\Repository; /** - * Class PublicationDecoratorTest + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class PublicationDecoratorTest extends \PHPUnit_Framework_TestCase { /** - * Calls generate method to access protected method generateRelatedFile + * @var PublicationDecorator */ - public function testGenerateRelatedFile() + private $model; + + /** + * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject + */ + private $filesystemMock; + + /** + * @var Temporary|\PHPUnit_Framework_MockObject_MockObject + */ + private $temporaryFileMock; + + /** + * @var Publisher|\PHPUnit_Framework_MockObject_MockObject + */ + private $publisherMock; + + /** + * @var Repository|\PHPUnit_Framework_MockObject_MockObject + */ + private $assetRepositoryMock; + + /** + * @var File|\PHPUnit_Framework_MockObject_MockObject + */ + private $relatedAssetMock; + + /** + * @var Import|\PHPUnit_Framework_MockObject_MockObject + */ + private $importGeneratorMock; + + /** + * @var LocalInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $localAssetMock; + + /** + * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $scopeConfigMock; + + /** + * @var State|\PHPUnit_Framework_MockObject_MockObject + */ + private $stateMock; + + protected function setUp() { - $filesystemMock = $this->getMockBuilder(Filesystem::class) + $this->filesystemMock = $this->getMockBuilder(Filesystem::class) ->disableOriginalConstructor() ->getMock(); - $fileTemporaryMock = $this->getMockBuilder(Temporary::class) + $this->temporaryFileMock = $this->getMockBuilder(Temporary::class) ->disableOriginalConstructor() ->getMock(); - - $publisherMock = $this->getMockBuilder(\Magento\Framework\App\View\Asset\Publisher::class) + $this->publisherMock = $this->getMockBuilder(Publisher::class) ->disableOriginalConstructor() ->getMock(); - $assetRepoMock = $this->getMockBuilder(\Magento\Framework\View\Asset\Repository::class) + $this->assetRepositoryMock = $this->getMockBuilder(Repository::class) ->disableOriginalConstructor() ->getMock(); - $relatedAssetMock = $this->getMockBuilder(\Magento\Framework\View\Asset\File::class) + $this->relatedAssetMock = $this->getMockBuilder(File::class) ->disableOriginalConstructor() ->getMock(); - $importGeneratorMock = $this->getMockBuilder(\Magento\Framework\Css\PreProcessor\Instruction\Import::class) + $this->importGeneratorMock = $this->getMockBuilder(Import::class) ->disableOriginalConstructor() ->getMock(); - $localAssetMock = $this->getMockBuilder(\Magento\Framework\View\Asset\LocalInterface::class) + $this->localAssetMock = $this->getMockBuilder(LocalInterface::class) ->disableOriginalConstructor() ->getMock(); - $scopeConfigMock = $this->getMockBuilder(ScopeConfigInterface::class) + $this->scopeConfigMock = $this->getMockBuilder(ScopeConfigInterface::class) ->getMockForAbstractClass(); + $this->stateMock = $this->getMockBuilder(State::class) + ->disableOriginalConstructor() + ->getMock(); - $relatedFileId = 'file_id'; + $this->model = (new ObjectManager($this))->getObject(PublicationDecorator::class, [ + 'filesystem' => $this->filesystemMock, + 'assetRepository' => $this->assetRepositoryMock, + 'temporaryFile' => $this->temporaryFileMock, + 'assetPublisher' => $this->publisherMock, + 'scopeConfig' => $this->scopeConfigMock, + 'state' => $this->stateMock, + 'hasRelatedPublishing' => true + ]); + } - $relatedFiles = [[$relatedFileId, $localAssetMock]]; + /** + * Calls generate method to access protected method generateRelatedFile + */ + public function testGenerateRelatedFile() + { + $relatedFileId = 'file_id'; + $relatedFiles = [[$relatedFileId, $this->localAssetMock]]; - $importGeneratorMock->expects(self::any()) + $this->importGeneratorMock->expects($this->any()) ->method('getRelatedFiles') - ->will(self::onConsecutiveCalls($relatedFiles, [])); - - $assetRepoMock->expects(self::any()) + ->willReturnOnConsecutiveCalls($relatedFiles, []); + $this->assetRepositoryMock->expects($this->any()) ->method('createRelated') - ->willReturn($relatedAssetMock); - - $publisherMock->expects(self::once()) + ->willReturn($this->relatedAssetMock); + $this->publisherMock->expects($this->once()) ->method('publish') - ->with($relatedAssetMock); - - $model = new PublicationDecorator( - $filesystemMock, - $assetRepoMock, - $fileTemporaryMock, - $publisherMock, - $scopeConfigMock, - true - ); - - $model->generate($importGeneratorMock); + ->with($this->relatedAssetMock); + + $this->model->generate($this->importGeneratorMock); } } diff --git a/app/code/Magento/Developer/Test/Unit/Model/View/Asset/PreProcessor/PreprocessorStrategyTest.php b/app/code/Magento/Developer/Test/Unit/Model/View/Asset/PreProcessor/PreprocessorStrategyTest.php index 25fbe112e7dc8..d27fa0642d061 100644 --- a/app/code/Magento/Developer/Test/Unit/Model/View/Asset/PreProcessor/PreprocessorStrategyTest.php +++ b/app/code/Magento/Developer/Test/Unit/Model/View/Asset/PreProcessor/PreprocessorStrategyTest.php @@ -5,6 +5,9 @@ */ namespace Magento\Developer\Test\Unit\Model\View\Asset\PreProcessor; +use Magento\Framework\App\DeploymentConfig; +use Magento\Framework\App\State; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Framework\View\Asset\PreProcessor\Chain; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Developer\Model\Config\Source\WorkflowType; @@ -16,6 +19,7 @@ * Class PreprocessorStrategyTest * * @see \Magento\Developer\Model\View\Asset\PreProcessor\PreprocessorStrategy + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class PreprocessorStrategyTest extends \PHPUnit_Framework_TestCase { @@ -39,6 +43,16 @@ class PreprocessorStrategyTest extends \PHPUnit_Framework_TestCase */ private $scopeConfigMock; + /** + * @var State|\PHPUnit_Framework_MockObject_MockObject + */ + private $stateMock; + + /** + * @var \Magento\Framework\App\ObjectManager|\PHPUnit_Framework_MockObject_MockObject + */ + private $objectMangerMock; + /** * Set up */ @@ -51,12 +65,19 @@ protected function setUp() ->getMock(); $this->scopeConfigMock = $this->getMockBuilder(ScopeConfigInterface::class) ->getMockForAbstractClass(); + $this->stateMock = $this->getMockBuilder(State::class) + ->disableOriginalConstructor() + ->getMock(); + $this->objectMangerMock = $this->getMockBuilder(\Magento\Framework\App\ObjectManager::class) + ->disableOriginalConstructor() + ->getMock(); - $this->preprocessorStrategy = new PreprocessorStrategy( - $this->alternativeSourceMock, - $this->frontendCompilationMock, - $this->scopeConfigMock - ); + $this->preprocessorStrategy = (new ObjectManager($this))->getObject(PreprocessorStrategy::class, [ + 'alternativeSource' => $this->alternativeSourceMock, + 'frontendCompilation' => $this->frontendCompilationMock, + 'scopeConfig' => $this->scopeConfigMock, + 'state' => $this->stateMock, + ]); } /** @@ -70,13 +91,36 @@ public function testProcessClientSideCompilation() ->method('getValue') ->with(WorkflowType::CONFIG_NAME_PATH) ->willReturn(WorkflowType::CLIENT_SIDE_COMPILATION); - $this->frontendCompilationMock->expects(self::once()) ->method('process') ->with($chainMock); + $this->alternativeSourceMock->expects(self::never()) + ->method('process'); + $this->stateMock->expects($this->atLeastOnce()) + ->method('getMode') + ->willReturn(State::MODE_DEVELOPER); + + $this->preprocessorStrategy->process($chainMock); + } + + public function testProcessClientSideCompilationWithDefaultMode() + { + $chainMock = $this->getChainMock(); + $this->scopeConfigMock->expects(self::once()) + ->method('getValue') + ->with(WorkflowType::CONFIG_NAME_PATH) + ->willReturn(WorkflowType::CLIENT_SIDE_COMPILATION); + $this->frontendCompilationMock->expects(self::once()) + ->method('process') + ->with($chainMock); $this->alternativeSourceMock->expects(self::never()) ->method('process'); + $this->stateMock->expects($this->once()) + ->method('getMode') + ->willReturn(State::MODE_DEFAULT); + + \Magento\Framework\App\ObjectManager::setInstance($this->objectMangerMock); $this->preprocessorStrategy->process($chainMock); } @@ -88,17 +132,18 @@ public function testProcessAlternativeSource() { $chainMock = $this->getChainMock(); - $this->scopeConfigMock->expects(self::once()) + $this->scopeConfigMock->expects($this->never()) ->method('getValue') ->with(WorkflowType::CONFIG_NAME_PATH) ->willReturn('off'); - $this->alternativeSourceMock->expects(self::once()) ->method('process') ->with($chainMock); - $this->frontendCompilationMock->expects(self::never()) ->method('process'); + $this->stateMock->expects($this->atLeastOnce()) + ->method('getMode') + ->willReturn(State::MODE_PRODUCTION); $this->preprocessorStrategy->process($chainMock); } diff --git a/app/code/Magento/Developer/Test/Unit/Model/View/Page/Config/RendererFactoryTest.php b/app/code/Magento/Developer/Test/Unit/Model/View/Page/Config/RendererFactoryTest.php index 06ebf3208b017..94305fca9f9aa 100644 --- a/app/code/Magento/Developer/Test/Unit/Model/View/Page/Config/RendererFactoryTest.php +++ b/app/code/Magento/Developer/Test/Unit/Model/View/Page/Config/RendererFactoryTest.php @@ -6,51 +6,82 @@ namespace Magento\Developer\Test\Unit\Model\View\Page\Config; use Magento\Developer\Model\Config\Source\WorkflowType; +use Magento\Developer\Model\View\Page\Config\RendererFactory; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\State; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\View\Page\Config\RendererInterface; use Magento\Store\Model\ScopeInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +/** + * Class RendererFactoryTest + */ class RendererFactoryTest extends \PHPUnit_Framework_TestCase { - const RENDERER_TYPE = 'renderer_type'; + /** + * @var ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $objectManagerMock; - const RENDERER_INSTANCE_NAME = 'renderer'; + /** + * @var RendererInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $rendererMock; - public function testCreate() + /** + * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $configMock; + + /** + * @var State|\PHPUnit_Framework_MockObject_MockObject + */ + private $stateMock; + + /** + * @var RendererFactory + */ + private $model; + + protected function setUp() { - // Set up mocks - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $objectManagerMock = $this->getMockBuilder(\Magento\Framework\ObjectManagerInterface::class) + $this->objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class) + ->getMockForAbstractClass(); + $this->configMock = $this->getMockBuilder(ScopeConfigInterface::class) + ->getMockForAbstractClass(); + $this->rendererMock = $this->getMockBuilder(RendererInterface::class) ->disableOriginalConstructor() ->getMock(); - $configMock = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) + $this->stateMock = $this->getMockBuilder(State::class) ->disableOriginalConstructor() ->getMock(); - $rendererMock = $this->getMockBuilder(\Magento\Framework\View\Page\Config\RendererInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $createArgs = [1,2,3]; - $objectManagerMock->expects($this->once()) + $this->objectManagerMock->expects($this->any()) + ->method('get') + ->with(State::class) + ->willReturn($this->stateMock); + + $this->model = (new ObjectManagerHelper($this))->getObject(RendererFactory::class, [ + 'objectManager' => $this->objectManagerMock, + 'scopeConfig' => $this->configMock, + 'rendererTypes' => ['renderer_type' => 'renderer'], + ]); + } + + public function testCreate() + { + $this->stateMock->expects($this->once()) + ->method('getMode'); + $this->objectManagerMock->expects($this->once()) ->method('create') - ->with(self::RENDERER_INSTANCE_NAME, $createArgs) - ->willReturn($rendererMock); - $configMock->expects($this->once()) + ->with('renderer', []) + ->willReturn($this->rendererMock); + $this->configMock->expects($this->once()) ->method('getValue') ->with(WorkflowType::CONFIG_NAME_PATH, ScopeInterface::SCOPE_STORE) - ->willReturn(self::RENDERER_TYPE); - - // Set up System Under Test - $rendererTypes = [ - self::RENDERER_TYPE => self::RENDERER_INSTANCE_NAME - ]; - $sutArgs = [ - 'objectManager' => $objectManagerMock, - 'scopeConfig' => $configMock, - 'rendererTypes' => $rendererTypes - ]; - - $model = $objectManager->getObject(\Magento\Developer\Model\View\Page\Config\RendererFactory::class, $sutArgs); - - // Test - $this->assertSame($rendererMock, $model->create($createArgs)); + ->willReturn('renderer_type'); + + $this->assertSame($this->rendererMock, $this->model->create()); } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php index 91d722f8ef4eb..d624fafa3143a 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php @@ -8,6 +8,9 @@ use Magento\Mtf\Client\Locator; use Magento\Mtf\Client\Element\SimpleElement; +use Magento\Mtf\Client\DriverInterface; +use Magento\Mtf\Client\ElementInterface; +use Magento\Mtf\System\Event\EventManagerInterface; /** * Catalog product custom attribute element. @@ -15,25 +18,45 @@ class CustomAttribute extends SimpleElement { /** - * Attribute input selector; + * Attribute input selector. * * @var string */ - protected $inputSelector = '[name="product[%s]"]'; + private $inputSelector = '[name="product[%s]"]'; + + /** + * Locator for data grid. + * + * @var string + */ + private $dataGrid = '[data-role="grid"]'; /** * Attribute class to element type reference. * * @var array */ - protected $classReference = [ - 'admin__control-text' => null, - 'textarea' => null, - 'hasDatepicker' => 'datepicker', - 'admin__control-select' => 'select', - 'admin__control-multiselect' => 'multiselect', - 'admin__actions-switch-checkbox' => 'switcher' - ]; + private $classReferences = []; + + /** + * Constructor + * + * @param DriverInterface $driver + * @param EventManagerInterface $eventManager + * @param Locator $locator + * @param ElementInterface $context + * @param array $classReferences + */ + public function __construct( + DriverInterface $driver, + EventManagerInterface $eventManager, + Locator $locator, + ElementInterface $context, + array $classReferences + ) { + parent::__construct($driver, $eventManager, $locator, $context); + $this->classReferences = $classReferences; + } /** * Set attribute value. @@ -48,7 +71,11 @@ public function setValue($data) $element = $this->getElementByClass($this->getElementClass($code)); $value = is_array($data) ? $data['value'] : $data; if ($value !== null) { - $this->find(sprintf($this->inputSelector, $code), Locator::SELECTOR_CSS, $element)->setValue($value); + $this->find( + str_replace('%code%', $code, $element['selector']), + Locator::SELECTOR_CSS, + $element['type'] + )->setValue($value); } } @@ -66,17 +93,17 @@ public function getValue() } /** - * Get element type by class. + * Get element by class. * * @param string $class - * @return string + * @return array|null */ private function getElementByClass($class) { $element = null; - foreach ($this->classReference as $key => $reference) { + foreach (array_keys($this->classReferences) as $key) { if (strpos($class, $key) !== false) { - $element = $reference; + return $this->classReferences[$class]; } } return $element; @@ -90,7 +117,9 @@ private function getElementByClass($class) */ private function getElementClass($code) { - return $this->find(sprintf($this->inputSelector, $code), Locator::SELECTOR_CSS)->getAttribute('class'); + return $this->find($this->dataGrid)->isVisible() + ? 'dynamicRows' + : $this->find(sprintf($this->inputSelector, $code), Locator::SELECTOR_CSS)->getAttribute('class'); } /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomAttribute.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomAttribute.php index a28a65de925a7..f8be03d37846e 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomAttribute.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/CustomAttribute.php @@ -20,7 +20,7 @@ class CustomAttribute extends DataSource * * @var CatalogProductAttribute */ - protected $attribute; + private $attribute; /** * @constructor @@ -54,7 +54,7 @@ public function __construct(FixtureFactory $fixtureFactory, array $params, $data * @param CatalogProductAttribute $attribute * @return string|null */ - protected function getDefaultAttributeValue(CatalogProductAttribute $attribute) + private function getDefaultAttributeValue(CatalogProductAttribute $attribute) { $data = $attribute->getData(); $value = ''; @@ -91,7 +91,7 @@ public function getAttribute() * @param CatalogProductAttribute $attribute * @return string */ - protected function createAttributeCode(CatalogProductAttribute $attribute) + private function createAttributeCode(CatalogProductAttribute $attribute) { $label = $attribute->getFrontendLabel(); return strtolower(preg_replace('@[\W\s]+@', '_', $label)); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml index d61ef9004b2f1..2a94a12c0dbdf 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml @@ -174,6 +174,12 @@ Fixed Product Tax attr_fpt_code_%isolation% Fixed_Product_Tax_Storeview + + United States + 10 + All Websites USD + * + diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/di.xml index 2356222387920..82a7c263b1ca9 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/di.xml @@ -156,4 +156,34 @@ low + + + + + [name="product[%code%]"] + null + + + [name="product[%code%]"] + null + + + [name="product[%code%]"] + datepicker + + + [name="product[%code%]"] + select + + + [name="product[%code%]"] + multiselect + + + [name="product[%code%]"] + switcher + + + + diff --git a/dev/tests/functional/tests/app/Magento/Weee/Test/Block/Adminhtml/Product/Edit/Section/ProductDetails/Fpt.php b/dev/tests/functional/tests/app/Magento/Weee/Test/Block/Adminhtml/Product/Edit/Section/ProductDetails/Fpt.php new file mode 100644 index 0000000000000..e059563ff0fc4 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Weee/Test/Block/Adminhtml/Product/Edit/Section/ProductDetails/Fpt.php @@ -0,0 +1,70 @@ + [ + 'type' => 'select', + 'selector' => '[name$="[country]"]' + ], + 'website' => [ + 'type' => 'select', + 'selector' => '[name$="[website_id]"]' + ], + 'tax' => [ + 'type' => 'input', + 'selector' => '[name$="[value]"]' + ], + 'state' => [ + 'type' => 'select', + 'selector' => '[name$="[state]"]' + ] + ]; + + /** + * Fill Fixed Product Tax form. + * + * @param string|array $value + * @return void + */ + public function setValue($value) + { + if ($this->find($this->buttonFormLocator)->isVisible()) { + $this->find($this->buttonFormLocator)->click(); + } + foreach ((array)$value as $name => $data) { + $element = $this->find( + $this->fields[$name]['selector'], + Locator::SELECTOR_CSS, + $this->fields[$name]['type'] + ); + + if ($element->isVisible()) { + $element->setValue($data); + } + } + } +} diff --git a/dev/tests/functional/tests/app/Magento/Weee/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Weee/Test/etc/di.xml index 2097566cc2463..30be698de32ea 100644 --- a/dev/tests/functional/tests/app/Magento/Weee/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/Weee/Test/etc/di.xml @@ -6,9 +6,19 @@ */ --> - - - high - - + + + high + + + + + + + [data-role="grid"] + \Magento\Weee\Test\Block\Adminhtml\Product\Edit\Section\ProductDetails\Fpt + + + + diff --git a/lib/internal/Magento/Framework/Backup/Filesystem.php b/lib/internal/Magento/Framework/Backup/Filesystem.php index ce1aa07ea37a3..8731e18816aec 100644 --- a/lib/internal/Magento/Framework/Backup/Filesystem.php +++ b/lib/internal/Magento/Framework/Backup/Filesystem.php @@ -7,7 +7,9 @@ // @codingStandardsIgnoreFile namespace Magento\Framework\Backup; + use Magento\Framework\Filesystem\DriverInterface; +use Magento\Framework\App\ObjectManager; /** * Class to work with filesystem backups @@ -58,6 +60,16 @@ class Filesystem extends AbstractBackup */ protected $_ftpPath; + /** + * @var \Magento\Framework\Backup\Filesystem\Rollback\Ftp + */ + protected $rollBackFtp; + + /** + * @var \Magento\Framework\Backup\Filesystem\Rollback\Fs + */ + protected $rollBackFs; + /** * Implementation Rollback functionality for Filesystem * @@ -71,11 +83,7 @@ public function rollback() set_time_limit(0); ignore_user_abort(true); - $rollbackWorker = $this->_useFtp ? new \Magento\Framework\Backup\Filesystem\Rollback\Ftp( - $this - ) : new \Magento\Framework\Backup\Filesystem\Rollback\Fs( - $this - ); + $rollbackWorker = $this->_useFtp ? $this->getRollBackFtp() : $this->getRollBackFs(); $rollbackWorker->run(); $this->_lastOperationSucceed = true; @@ -299,4 +307,36 @@ protected function _getTarTmpPath() $tmpName = '~tmp-' . microtime(true) . '.tar'; return $this->getBackupsDir() . '/' . $tmpName; } + + /** + * @return \Magento\Framework\Backup\Filesystem\Rollback\Ftp + * @deprecated + */ + protected function getRollBackFtp() + { + if (!$this->rollBackFtp) { + $this->rollBackFtp = ObjectManager::getInstance()->create( + \Magento\Framework\Backup\Filesystem\Rollback\Ftp::class, + [$this] + ); + } + + return $this->rollBackFtp; + } + + /** + * @return \Magento\Framework\Backup\Filesystem\Rollback\Fs + * @deprecated + */ + protected function getRollBackFs() + { + if (!$this->rollBackFs) { + $this->rollBackFs = ObjectManager::getInstance()->create( + \Magento\Framework\Backup\Filesystem\Rollback\Fs::class, + [$this] + ); + } + + return $this->rollBackFs; + } } diff --git a/lib/internal/Magento/Framework/Backup/Filesystem/Helper.php b/lib/internal/Magento/Framework/Backup/Filesystem/Helper.php index 355f10226622a..2587cd543818a 100644 --- a/lib/internal/Magento/Framework/Backup/Filesystem/Helper.php +++ b/lib/internal/Magento/Framework/Backup/Filesystem/Helper.php @@ -87,10 +87,12 @@ public function getInfo($path, $infoOptions = self::INFO_ALL, $skipFiles = []) $info = []; if ($infoOptions & self::INFO_READABLE) { $info['readable'] = true; + $info['readableMeta'] = []; } if ($infoOptions & self::INFO_WRITABLE) { $info['writable'] = true; + $info['writableMeta'] = []; } if ($infoOptions & self::INFO_SIZE) { @@ -111,10 +113,12 @@ public function getInfo($path, $infoOptions = self::INFO_ALL, $skipFiles = []) if ($infoOptions & self::INFO_WRITABLE && !$item->isWritable()) { $info['writable'] = false; + $info['writableMeta'][] = $item->getPathname(); } if ($infoOptions & self::INFO_READABLE && !$item->isReadable()) { $info['readable'] = false; + $info['readableMeta'][] = $item->getPathname(); } if ($infoOptions & self::INFO_SIZE && !$item->isDir()) { diff --git a/lib/internal/Magento/Framework/Backup/Filesystem/Rollback/Fs.php b/lib/internal/Magento/Framework/Backup/Filesystem/Rollback/Fs.php index 0339195bbb96a..fe627b3dd59dc 100644 --- a/lib/internal/Magento/Framework/Backup/Filesystem/Rollback/Fs.php +++ b/lib/internal/Magento/Framework/Backup/Filesystem/Rollback/Fs.php @@ -5,6 +5,8 @@ */ namespace Magento\Framework\Backup\Filesystem\Rollback; +use Magento\Framework\App\ObjectManager; + /** * Rollback worker for rolling back via local filesystem * @@ -12,6 +14,11 @@ */ class Fs extends AbstractRollback { + /** + * @var \Magento\Framework\Backup\Filesystem\Helper + */ + private $fsHelper; + /** * Files rollback implementation via local filesystem * @@ -30,7 +37,7 @@ public function run() ); } - $fsHelper = new \Magento\Framework\Backup\Filesystem\Helper(); + $fsHelper = $this->getFsHelper(); $filesInfo = $fsHelper->getInfo( $this->_snapshot->getRootDir(), @@ -39,6 +46,15 @@ public function run() ); if (!$filesInfo['writable']) { + if (!empty($filesInfo['writableMeta'])) { + throw new \Magento\Framework\Backup\Exception\NotEnoughPermissions( + new \Magento\Framework\Phrase( + 'You need write permissions for: %1', + [implode(', ', $filesInfo['writableMeta'])] + ) + ); + } + throw new \Magento\Framework\Backup\Exception\NotEnoughPermissions( new \Magento\Framework\Phrase('Unable to make rollback because not all files are writable') ); @@ -59,4 +75,17 @@ public function run() $fsHelper->rm($this->_snapshot->getRootDir(), $this->_snapshot->getIgnorePaths()); $archiver->unpack($snapshotPath, $this->_snapshot->getRootDir()); } + + /** + * @return \Magento\Framework\Backup\Filesystem\Helper + * @deprecated + */ + private function getFsHelper() + { + if (!$this->fsHelper) { + $this->fsHelper = ObjectManager::getInstance()->get(\Magento\Framework\Backup\Filesystem\Helper::class); + } + + return $this->fsHelper; + } } diff --git a/lib/internal/Magento/Framework/Backup/Test/Unit/Filesystem/Rollback/FsTest.php b/lib/internal/Magento/Framework/Backup/Test/Unit/Filesystem/Rollback/FsTest.php new file mode 100644 index 0000000000000..dbd830a8fc9f2 --- /dev/null +++ b/lib/internal/Magento/Framework/Backup/Test/Unit/Filesystem/Rollback/FsTest.php @@ -0,0 +1,111 @@ +backupPath = '/some/test/path'; + $this->rootDir = '/'; + $this->ignorePaths = []; + + $this->objectManager = new ObjectManager($this); + $this->snapshotMock = $this->getMockBuilder(\Magento\Framework\Backup\Filesystem::class) + ->setMethods(['getBackupPath', 'getRootDir', 'getIgnorePaths']) + ->getMock(); + $this->snapshotMock->expects($this->any()) + ->method('getBackupPath') + ->willReturn($this->backupPath); + $this->snapshotMock->expects($this->any()) + ->method('getRootDir') + ->willReturn($this->rootDir); + $this->snapshotMock->expects($this->any()) + ->method('getIgnorePaths') + ->willReturn($this->ignorePaths); + $this->fsHelperMock = $this->getMockBuilder(\Magento\Framework\Backup\Filesystem\Helper::class) + ->setMethods(['getInfo', 'rm']) + ->getMock(); + $this->fs = $this->objectManager->getObject( + \Magento\Framework\Backup\Filesystem\Rollback\Fs::class, + [ + 'snapshotObject' => $this->snapshotMock, + 'fsHelper' => $this->fsHelperMock + ] + ); + + } + + /** + * @expectedException \Magento\Framework\Backup\Exception\NotEnoughPermissions + * @expectedExceptionMessage You need write permissions for: test1, test2 + */ + public function testRunNotEnoughPermissions() + { + $fsInfo = [ + 'writable' => false, + 'writableMeta' => ['test1', 'test2'] + ]; + + $this->fsHelperMock->expects($this->once()) + ->method('getInfo') + ->willReturn($fsInfo); + $this->fs->run(); + } + + public function testRun() + { + $fsInfo = ['writable' => true]; + + $this->fsHelperMock->expects($this->once()) + ->method('getInfo') + ->willReturn($fsInfo); + $this->fsHelperMock->expects($this->once()) + ->method('rm') + ->with($this->rootDir, $this->ignorePaths); + + $this->fs->run(); + } +} diff --git a/lib/internal/Magento/Framework/Backup/Test/Unit/Filesystem/Rollback/_files/ioMock.php b/lib/internal/Magento/Framework/Backup/Test/Unit/Filesystem/Rollback/_files/ioMock.php new file mode 100644 index 0000000000000..3ac56872e87b9 --- /dev/null +++ b/lib/internal/Magento/Framework/Backup/Test/Unit/Filesystem/Rollback/_files/ioMock.php @@ -0,0 +1,28 @@ +objectManager = new ObjectManager($this); + $this->fsMock = $this->getMockBuilder(\Magento\Framework\Backup\Filesystem\Rollback\Fs::class) + ->disableOriginalConstructor() + ->getMock(); + $this->ftpMock = $this->getMockBuilder(\Magento\Framework\Backup\Filesystem\Rollback\Ftp::class) + ->disableOriginalConstructor() + ->getMock(); + $this->snapshotMock = $this->getMockBuilder(\Magento\Framework\Backup\Filesystem::class) + ->getMock(); + $this->filesystem = $this->objectManager->getObject( + \Magento\Framework\Backup\Filesystem::class, + [ + 'rollBackFtp' => $this->ftpMock, + 'rollBackFs' => $this->fsMock + ] + ); + } + + public function testRollback() + { + $this->assertTrue($this->filesystem->rollback()); + } +} diff --git a/lib/internal/Magento/Framework/Backup/Test/Unit/MediaTest.php b/lib/internal/Magento/Framework/Backup/Test/Unit/MediaTest.php index ef382be2d4b52..a53d3fded0a41 100644 --- a/lib/internal/Magento/Framework/Backup/Test/Unit/MediaTest.php +++ b/lib/internal/Magento/Framework/Backup/Test/Unit/MediaTest.php @@ -5,10 +5,17 @@ */ namespace Magento\Framework\Backup\Test\Unit; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + require_once __DIR__ . '/_files/io.php'; class MediaTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject */ @@ -24,6 +31,11 @@ class MediaTest extends \PHPUnit_Framework_TestCase */ protected $_backupDbMock; + /** + * @var \Magento\Framework\Backup\Filesystem\Rollback\Fs + */ + private $fsMock; + public static function setUpBeforeClass() { require __DIR__ . '/_files/app_dirs.php'; @@ -36,6 +48,7 @@ public static function tearDownAfterClass() protected function setUp() { + $this->objectManager = new ObjectManager($this); $this->_backupDbMock = $this->getMock(\Magento\Framework\Backup\Db::class, [], [], '', false); $this->_backupDbMock->expects($this->any())->method('setBackupExtension')->will($this->returnSelf()); @@ -69,6 +82,8 @@ protected function setUp() )->will( $this->returnValue($this->_backupDbMock) ); + + $this->fsMock = $this->getMock(\Magento\Framework\Backup\Filesystem\Rollback\Fs::class, [], [], '', false); } /** @@ -81,7 +96,14 @@ public function testAction($action) $rootDir = str_replace('\\', '/', TESTS_TEMP_DIR) . '/Magento/Backup/data'; - $model = new \Magento\Framework\Backup\Media($this->_filesystemMock, $this->_backupFactoryMock); + $model = $this->objectManager->getObject( + \Magento\Framework\Backup\Media::class, + [ + 'filesystem' => $this->_filesystemMock, + 'backupFactory' => $this->_backupFactoryMock, + 'rollBackFs' => $this->fsMock + ] + ); $model->setRootDir($rootDir); $model->setBackupsDir($rootDir); $model->{$action}(); diff --git a/lib/internal/Magento/Framework/Backup/Test/Unit/NomediaTest.php b/lib/internal/Magento/Framework/Backup/Test/Unit/NomediaTest.php index 6a045a9974f84..228ea9a5569b3 100644 --- a/lib/internal/Magento/Framework/Backup/Test/Unit/NomediaTest.php +++ b/lib/internal/Magento/Framework/Backup/Test/Unit/NomediaTest.php @@ -5,10 +5,17 @@ */ namespace Magento\Framework\Backup\Test\Unit; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + require_once __DIR__ . '/_files/io.php'; class NomediaTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + private $objectManager; + /** * @var \Magento\Framework\Filesystem */ @@ -24,6 +31,11 @@ class NomediaTest extends \PHPUnit_Framework_TestCase */ protected $_backupDbMock; + /** + * @var \Magento\Framework\Backup\Filesystem\Rollback\Fs + */ + private $fsMock; + public static function setUpBeforeClass() { require __DIR__ . '/_files/app_dirs.php'; @@ -36,6 +48,7 @@ public static function tearDownAfterClass() protected function setUp() { + $this->objectManager = new ObjectManager($this); $this->_backupDbMock = $this->getMock(\Magento\Framework\Backup\Db::class, [], [], '', false); $this->_backupDbMock->expects($this->any())->method('setBackupExtension')->will($this->returnSelf()); @@ -69,6 +82,8 @@ protected function setUp() )->will( $this->returnValue($this->_backupDbMock) ); + + $this->fsMock = $this->getMock(\Magento\Framework\Backup\Filesystem\Rollback\Fs::class, [], [], '', false); } /** @@ -81,7 +96,14 @@ public function testAction($action) $rootDir = TESTS_TEMP_DIR . '/Magento/Backup/data'; - $model = new \Magento\Framework\Backup\Nomedia($this->_filesystemMock, $this->_backupFactoryMock); + $model = $this->objectManager->getObject( + \Magento\Framework\Backup\Nomedia::class, + [ + 'filesystem' => $this->_filesystemMock, + 'backupFactory' => $this->_backupFactoryMock, + 'rollBackFs' => $this->fsMock + ] + ); $model->setRootDir($rootDir); $model->setBackupsDir($rootDir); $model->{$action}(); diff --git a/lib/internal/Magento/Framework/Filesystem/Directory/Write.php b/lib/internal/Magento/Framework/Filesystem/Directory/Write.php index 0a46a17c10b22..25486562257ca 100644 --- a/lib/internal/Magento/Framework/Filesystem/Directory/Write.php +++ b/lib/internal/Magento/Framework/Filesystem/Directory/Write.php @@ -40,7 +40,7 @@ public function __construct( } /** - * Check if directory is writable + * Check if directory or file is writable * * @param string $path * @return void @@ -49,7 +49,9 @@ public function __construct( protected function assertWritable($path) { if ($this->isWritable($path) === false) { - $path = $this->getAbsolutePath($this->path, $path); + $path = (!$this->driver->isFile($path)) + ? $this->getAbsolutePath($this->path, $path) + : $this->getAbsolutePath($path); throw new FileSystemException(new \Magento\Framework\Phrase('The path "%1" is not writable', [$path])); } } @@ -240,12 +242,13 @@ public function isWritable($path = null) * @param string $path * @param string $mode * @return \Magento\Framework\Filesystem\File\WriteInterface + * @throws \Magento\Framework\Exception\FileSystemException */ public function openFile($path, $mode = 'w') { $folder = dirname($path); $this->create($folder); - $this->assertWritable($folder); + $this->assertWritable($this->isExist($path) ? $path : $folder); $absolutePath = $this->driver->getAbsolutePath($this->path, $path); return $this->fileFactory->create($absolutePath, $this->driver, $mode); } diff --git a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Directory/WriteTest.php b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Directory/WriteTest.php index 5c93c890f04de..1a84fb6a69a6e 100644 --- a/lib/internal/Magento/Framework/Filesystem/Test/Unit/Directory/WriteTest.php +++ b/lib/internal/Magento/Framework/Filesystem/Test/Unit/Directory/WriteTest.php @@ -121,6 +121,17 @@ public function testCreateSymlinkTargetDirectoryExists() $this->assertTrue($this->write->createSymlink($sourcePath, $destinationFile, $targetDir)); } + /** + * @expectedException \Magento\Framework\Exception\FileSystemException + */ + public function testOpenFileNonWritable() + { + $targetPath = '/path/to/target.file'; + $this->driver->expects($this->once())->method('isExists')->willReturn(true); + $this->driver->expects($this->once())->method('isWritable')->willReturn(false); + $this->write->openFile($targetPath); + } + /** * Assert is file expectation *