diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php
index 09efe07916521..79a615f542c43 100644
--- a/app/code/Magento/Bundle/Model/Product/Type.php
+++ b/app/code/Magento/Bundle/Model/Product/Type.php
@@ -821,11 +821,11 @@ private function recursiveIntval(array $array)
private function multiToFlatArray(array $array)
{
$flatArray = [];
- foreach ($array as $key => $value) {
+ foreach ($array as $value) {
if (is_array($value)) {
$flatArray = array_merge($flatArray, $this->multiToFlatArray($value));
} else {
- $flatArray[$key] = $value;
+ $flatArray[] = $value;
}
}
diff --git a/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserLoginBackendObserverTest.php b/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserLoginBackendObserverTest.php
new file mode 100644
index 0000000000000..6966bd4cce7f9
--- /dev/null
+++ b/app/code/Magento/Captcha/Test/Unit/Observer/CheckUserLoginBackendObserverTest.php
@@ -0,0 +1,137 @@
+helperMock = $this->createMock(Data::class);
+ $this->messageManagerMock = $this->createMock(ManagerInterface::class);
+ $this->captchaStringResolverMock = $this->createMock(CaptchaStringResolver::class);
+ $this->requestMock = $this->createMock(RequestInterface::class);
+
+ $this->observer = new CheckUserLoginBackendObserver(
+ $this->helperMock,
+ $this->captchaStringResolverMock,
+ $this->requestMock
+ );
+ }
+
+ /**
+ * Test check user login in backend with correct captcha
+ *
+ * @dataProvider requiredCaptchaDataProvider
+ * @param bool $isRequired
+ * @return void
+ */
+ public function testCheckOnBackendLoginWithCorrectCaptcha(bool $isRequired)
+ {
+ $formId = 'backend_login';
+ $login = 'admin';
+ $captchaValue = 'captcha-value';
+
+ /** @var Observer|MockObject $observerMock */
+ $observerMock = $this->createPartialMock(Observer::class, ['getEvent']);
+ $eventMock = $this->createPartialMock(Event::class, ['getUsername']);
+ $captcha = $this->createMock(DefaultModel::class);
+
+ $eventMock->method('getUsername')->willReturn('admin');
+ $observerMock->method('getEvent')->willReturn($eventMock);
+ $captcha->method('isRequired')->with($login)->willReturn($isRequired);
+ $captcha->method('isCorrect')->with($captchaValue)->willReturn(true);
+ $this->helperMock->method('getCaptcha')->with($formId)->willReturn($captcha);
+ $this->captchaStringResolverMock->method('resolve')->with($this->requestMock, $formId)
+ ->willReturn($captchaValue);
+
+ $this->observer->execute($observerMock);
+ }
+
+ /**
+ * @return array
+ */
+ public function requiredCaptchaDataProvider(): array
+ {
+ return [
+ [true],
+ [false]
+ ];
+ }
+
+ /**
+ * Test check user login in backend with wrong captcha
+ *
+ * @return void
+ * @expectedException \Magento\Framework\Exception\Plugin\AuthenticationException
+ */
+ public function testCheckOnBackendLoginWithWrongCaptcha()
+ {
+ $formId = 'backend_login';
+ $login = 'admin';
+ $captchaValue = 'captcha-value';
+
+ /** @var Observer|MockObject $observerMock */
+ $observerMock = $this->createPartialMock(Observer::class, ['getEvent']);
+ $eventMock = $this->createPartialMock(Event::class, ['getUsername']);
+ $captcha = $this->createMock(DefaultModel::class);
+
+ $eventMock->method('getUsername')->willReturn($login);
+ $observerMock->method('getEvent')->willReturn($eventMock);
+ $captcha->method('isRequired')->with($login)->willReturn(true);
+ $captcha->method('isCorrect')->with($captchaValue)->willReturn(false);
+ $this->helperMock->method('getCaptcha')->with($formId)->willReturn($captcha);
+ $this->captchaStringResolverMock->method('resolve')->with($this->requestMock, $formId)
+ ->willReturn($captchaValue);
+
+ $this->observer->execute($observerMock);
+ }
+}
diff --git a/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php
new file mode 100644
index 0000000000000..34e04c107d0a8
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Plugin/SalesRule/Model/Rule/Condition/Product.php
@@ -0,0 +1,64 @@
+getProductToValidate($subject, $model);
+ if ($model->getProduct() !== $product) {
+ // We need to replace product only for validation and keep original product for all other cases.
+ $clone = clone $model;
+ $clone->setProduct($product);
+ $model = $clone;
+ }
+
+ return [$model];
+ }
+
+ /**
+ * @param \Magento\SalesRule\Model\Rule\Condition\Product $subject
+ * @param \Magento\Framework\Model\AbstractModel $model
+ *
+ * @return \Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product
+ */
+ private function getProductToValidate(
+ \Magento\SalesRule\Model\Rule\Condition\Product $subject,
+ \Magento\Framework\Model\AbstractModel $model
+ ) {
+ /** @var \Magento\Catalog\Model\Product $product */
+ $product = $model->getProduct();
+
+ $attrCode = $subject->getAttribute();
+
+ /* Check for attributes which are not available for configurable products */
+ if ($product->getTypeId() == Configurable::TYPE_CODE && !$product->hasData($attrCode)) {
+ /** @var \Magento\Catalog\Model\AbstractModel $childProduct */
+ $childProduct = current($model->getChildren())->getProduct();
+ if ($childProduct->hasData($attrCode)) {
+ $product = $childProduct;
+ }
+ }
+
+ return $product;
+ }
+}
diff --git a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php b/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php
index 62ad21a24ac7e..1ff78a632c3bb 100644
--- a/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php
+++ b/app/code/Magento/ConfigurableProduct/Setup/UpgradeData.php
@@ -7,11 +7,11 @@
use Magento\Catalog\Model\Product;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
-use Magento\Framework\Setup\UpgradeDataInterface;
-use Magento\Framework\Setup\ModuleContextInterface;
-use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
+use Magento\Framework\Setup\ModuleContextInterface;
+use Magento\Framework\Setup\ModuleDataSetupInterface;
+use Magento\Framework\Setup\UpgradeDataInterface;
/**
* Upgrade Data script
@@ -62,6 +62,10 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface
}
}
+ if (version_compare($context->getVersion(), '2.2.2', '<')) {
+ $this->upgradeQuoteItemPrice($setup);
+ }
+
$setup->endSetup();
}
@@ -97,4 +101,30 @@ private function updateRelatedProductTypes(string $attributeId, array $relatedPr
implode(',', $relatedProductTypes)
);
}
+
+ /**
+ * Update 'price' value for quote items without price of configurable products subproducts.
+ *
+ * @param ModuleDataSetupInterface $setup
+ */
+ private function upgradeQuoteItemPrice(ModuleDataSetupInterface $setup)
+ {
+ $connection = $setup->getConnection();
+ $quoteItemTable = $setup->getTable('quote_item');
+ $select = $connection->select();
+ $select->joinLeft(
+ ['qi2' => $quoteItemTable],
+ 'qi1.parent_item_id = qi2.item_id',
+ ['price']
+ )->where(
+ 'qi1.price = 0'
+ . ' AND qi1.parent_item_id IS NOT NULL'
+ . ' AND qi2.product_type = "' . Configurable::TYPE_CODE . '"'
+ );
+ $updateQuoteItem = $setup->getConnection()->updateFromSelect(
+ $select,
+ ['qi1' => $quoteItemTable]
+ );
+ $setup->getConnection()->query($updateQuoteItem);
+ }
}
diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php
new file mode 100644
index 0000000000000..54b7b71dd5ed8
--- /dev/null
+++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Plugin/SalesRule/Model/Rule/Condition/ProductTest.php
@@ -0,0 +1,226 @@
+objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+ $this->validator = $this->createValidator();
+ $this->validatorPlugin = $this->objectManager->getObject(ValidatorPlugin::class);
+ }
+
+ /**
+ * @return \Magento\SalesRule\Model\Rule\Condition\Product
+ */
+ private function createValidator(): SalesRuleProduct
+ {
+ /** @var Context|\PHPUnit_Framework_MockObject_MockObject $contextMock */
+ $contextMock = $this->getMockBuilder(Context::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ /** @var Data|\PHPUnit_Framework_MockObject_MockObject $backendHelperMock */
+ $backendHelperMock = $this->getMockBuilder(Data::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ /** @var Config|\PHPUnit_Framework_MockObject_MockObject $configMock */
+ $configMock = $this->getMockBuilder(Config::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ /** @var ProductFactory|\PHPUnit_Framework_MockObject_MockObject $productFactoryMock */
+ $productFactoryMock = $this->getMockBuilder(ProductFactory::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ /** @var ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject $productRepositoryMock */
+ $productRepositoryMock = $this->getMockBuilder(ProductRepositoryInterface::class)
+ ->getMockForAbstractClass();
+ $attributeLoaderInterfaceMock = $this->getMockBuilder(AbstractEntity::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getAttributesByCode'])
+ ->getMock();
+ $attributeLoaderInterfaceMock
+ ->expects($this->any())
+ ->method('getAttributesByCode')
+ ->willReturn([]);
+ /** @var Product|\PHPUnit_Framework_MockObject_MockObject $productMock */
+ $productMock = $this->getMockBuilder(Product::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['loadAllAttributes', 'getConnection', 'getTable'])
+ ->getMock();
+ $productMock->expects($this->any())
+ ->method('loadAllAttributes')
+ ->willReturn($attributeLoaderInterfaceMock);
+ /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */
+ $collectionMock = $this->getMockBuilder(Collection::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ /** @var FormatInterface|\PHPUnit_Framework_MockObject_MockObject $formatMock */
+ $formatMock = new Format(
+ $this->getMockBuilder(ScopeResolverInterface::class)->disableOriginalConstructor()->getMock(),
+ $this->getMockBuilder(ResolverInterface::class)->disableOriginalConstructor()->getMock(),
+ $this->getMockBuilder(CurrencyFactory::class)->disableOriginalConstructor()->getMock()
+ );
+
+ return new SalesRuleProduct(
+ $contextMock,
+ $backendHelperMock,
+ $configMock,
+ $productFactoryMock,
+ $productRepositoryMock,
+ $productMock,
+ $collectionMock,
+ $formatMock
+ );
+ }
+
+ public function testChildIsUsedForValidation()
+ {
+ $configurableProductMock = $this->createProductMock();
+ $configurableProductMock
+ ->expects($this->any())
+ ->method('getTypeId')
+ ->willReturn(Configurable::TYPE_CODE);
+ $configurableProductMock
+ ->expects($this->any())
+ ->method('hasData')
+ ->with($this->equalTo('special_price'))
+ ->willReturn(false);
+
+ /* @var AbstractItem|\PHPUnit_Framework_MockObject_MockObject $item */
+ $item = $this->getMockBuilder(AbstractItem::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['setProduct', 'getProduct', 'getChildren'])
+ ->getMockForAbstractClass();
+ $item->expects($this->any())
+ ->method('getProduct')
+ ->willReturn($configurableProductMock);
+
+ $simpleProductMock = $this->createProductMock();
+ $simpleProductMock
+ ->expects($this->any())
+ ->method('getTypeId')
+ ->willReturn(Type::TYPE_SIMPLE);
+ $simpleProductMock
+ ->expects($this->any())
+ ->method('hasData')
+ ->with($this->equalTo('special_price'))
+ ->willReturn(true);
+
+ $childItem = $this->getMockBuilder(AbstractItem::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getProduct'])
+ ->getMockForAbstractClass();
+ $childItem->expects($this->any())
+ ->method('getProduct')
+ ->willReturn($simpleProductMock);
+
+ $item->expects($this->any())
+ ->method('getChildren')
+ ->willReturn([$childItem]);
+ $item->expects($this->once())
+ ->method('setProduct')
+ ->with($this->identicalTo($simpleProductMock));
+
+ $this->validator->setAttribute('special_price');
+
+ $this->validatorPlugin->beforeValidate($this->validator, $item);
+ }
+
+ /**
+ * @return Product|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private function createProductMock(): \PHPUnit_Framework_MockObject_MockObject
+ {
+ $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
+ ->disableOriginalConstructor()
+ ->setMethods([
+ 'getAttribute',
+ 'getId',
+ 'setQuoteItemQty',
+ 'setQuoteItemPrice',
+ 'getTypeId',
+ 'hasData',
+ ])
+ ->getMock();
+ $productMock
+ ->expects($this->any())
+ ->method('setQuoteItemQty')
+ ->willReturnSelf();
+ $productMock
+ ->expects($this->any())
+ ->method('setQuoteItemPrice')
+ ->willReturnSelf();
+
+ return $productMock;
+ }
+
+ public function testChildIsNotUsedForValidation()
+ {
+ $simpleProductMock = $this->createProductMock();
+ $simpleProductMock
+ ->expects($this->any())
+ ->method('getTypeId')
+ ->willReturn(Type::TYPE_SIMPLE);
+ $simpleProductMock
+ ->expects($this->any())
+ ->method('hasData')
+ ->with($this->equalTo('special_price'))
+ ->willReturn(true);
+
+ /* @var AbstractItem|\PHPUnit_Framework_MockObject_MockObject $item */
+ $item = $this->getMockBuilder(AbstractItem::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['setProduct', 'getProduct'])
+ ->getMockForAbstractClass();
+ $item->expects($this->any())
+ ->method('getProduct')
+ ->willReturn($simpleProductMock);
+
+ $this->validator->setAttribute('special_price');
+
+ $this->validatorPlugin->beforeValidate($this->validator, $item);
+ }
+}
diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml
index 102ed1314f864..e6e0da721e150 100644
--- a/app/code/Magento/ConfigurableProduct/etc/di.xml
+++ b/app/code/Magento/ConfigurableProduct/etc/di.xml
@@ -228,6 +228,9 @@
+
+
+
diff --git a/app/code/Magento/ConfigurableProduct/etc/module.xml b/app/code/Magento/ConfigurableProduct/etc/module.xml
index 0b971ef775e16..b7d4c92aaa992 100644
--- a/app/code/Magento/ConfigurableProduct/etc/module.xml
+++ b/app/code/Magento/ConfigurableProduct/etc/module.xml
@@ -6,7 +6,7 @@
*/
-->
-
+
diff --git a/app/code/Magento/Quote/Model/Quote/Item/Processor.php b/app/code/Magento/Quote/Model/Quote/Item/Processor.php
index f9dac1779ad27..757b81b984a46 100644
--- a/app/code/Magento/Quote/Model/Quote/Item/Processor.php
+++ b/app/code/Magento/Quote/Model/Quote/Item/Processor.php
@@ -97,6 +97,7 @@ public function prepare(Item $item, DataObject $request, Product $candidate)
$item->addQty($candidate->getCartQty());
$customPrice = $request->getCustomPrice();
+ $item->setPrice($candidate->getFinalPrice());
if (!empty($customPrice)) {
$item->setCustomPrice($customPrice);
$item->setOriginalCustomPrice($customPrice);
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php
index a56de35b70f75..e8cfb05ca89b9 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php
@@ -76,7 +76,8 @@ protected function setUp()
'addQty',
'setCustomPrice',
'setOriginalCustomPrice',
- 'setData'
+ 'setData',
+ 'setprice'
]);
$this->quoteItemFactoryMock->expects($this->any())
->method('create')
@@ -98,7 +99,13 @@ protected function setUp()
$this->productMock = $this->createPartialMock(
\Magento\Catalog\Model\Product::class,
- ['getCustomOptions', '__wakeup', 'getParentProductId', 'getCartQty', 'getStickWithinParent']
+ [
+ 'getCustomOptions',
+ '__wakeup',
+ 'getParentProductId',
+ 'getCartQty',
+ 'getStickWithinParent',
+ 'getFinalPrice']
);
$this->objectMock = $this->createPartialMock(
\Magento\Framework\DataObject::class,
@@ -239,6 +246,7 @@ public function testPrepare()
$customPrice = 400000000;
$itemId = 1;
$requestItemId = 1;
+ $finalPrice = 1000000000;
$this->productMock->expects($this->any())
->method('getCartQty')
@@ -246,6 +254,9 @@ public function testPrepare()
$this->productMock->expects($this->any())
->method('getStickWithinParent')
->will($this->returnValue(false));
+ $this->productMock->expects($this->once())
+ ->method('getFinalPrice')
+ ->will($this->returnValue($finalPrice));
$this->itemMock->expects($this->once())
->method('addQty')
@@ -255,6 +266,9 @@ public function testPrepare()
->will($this->returnValue($itemId));
$this->itemMock->expects($this->never())
->method('setData');
+ $this->itemMock->expects($this->once())
+ ->method('setPrice')
+ ->will($this->returnValue($this->itemMock));
$this->objectMock->expects($this->any())
->method('getCustomPrice')
@@ -282,6 +296,7 @@ public function testPrepareWithResetCountAndStick()
$customPrice = 400000000;
$itemId = 1;
$requestItemId = 1;
+ $finalPrice = 1000000000;
$this->productMock->expects($this->any())
->method('getCartQty')
@@ -289,6 +304,9 @@ public function testPrepareWithResetCountAndStick()
$this->productMock->expects($this->any())
->method('getStickWithinParent')
->will($this->returnValue(true));
+ $this->productMock->expects($this->once())
+ ->method('getFinalPrice')
+ ->will($this->returnValue($finalPrice));
$this->itemMock->expects($this->once())
->method('addQty')
@@ -298,6 +316,9 @@ public function testPrepareWithResetCountAndStick()
->will($this->returnValue($itemId));
$this->itemMock->expects($this->never())
->method('setData');
+ $this->itemMock->expects($this->once())
+ ->method('setPrice')
+ ->will($this->returnValue($this->itemMock));
$this->objectMock->expects($this->any())
->method('getCustomPrice')
@@ -325,6 +346,7 @@ public function testPrepareWithResetCountAndNotStickAndOtherItemId()
$customPrice = 400000000;
$itemId = 1;
$requestItemId = 2;
+ $finalPrice = 1000000000;
$this->productMock->expects($this->any())
->method('getCartQty')
@@ -332,6 +354,9 @@ public function testPrepareWithResetCountAndNotStickAndOtherItemId()
$this->productMock->expects($this->any())
->method('getStickWithinParent')
->will($this->returnValue(false));
+ $this->productMock->expects($this->once())
+ ->method('getFinalPrice')
+ ->will($this->returnValue($finalPrice));
$this->itemMock->expects($this->once())
->method('addQty')
@@ -341,6 +366,9 @@ public function testPrepareWithResetCountAndNotStickAndOtherItemId()
->will($this->returnValue($itemId));
$this->itemMock->expects($this->never())
->method('setData');
+ $this->itemMock->expects($this->once())
+ ->method('setPrice')
+ ->will($this->returnValue($this->itemMock));
$this->objectMock->expects($this->any())
->method('getCustomPrice')
@@ -368,6 +396,7 @@ public function testPrepareWithResetCountAndNotStickAndSameItemId()
$customPrice = 400000000;
$itemId = 1;
$requestItemId = 1;
+ $finalPrice = 1000000000;
$this->objectMock->expects($this->any())
->method('getResetCount')
@@ -386,10 +415,16 @@ public function testPrepareWithResetCountAndNotStickAndSameItemId()
$this->productMock->expects($this->any())
->method('getStickWithinParent')
->will($this->returnValue(false));
+ $this->productMock->expects($this->once())
+ ->method('getFinalPrice')
+ ->will($this->returnValue($finalPrice));
$this->itemMock->expects($this->once())
->method('addQty')
->with($qty);
+ $this->itemMock->expects($this->once())
+ ->method('setPrice')
+ ->will($this->returnValue($this->itemMock));
$this->objectMock->expects($this->any())
->method('getCustomPrice')
diff --git a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php
index c90894febd44b..059177b4066f3 100644
--- a/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php
+++ b/app/code/Magento/SalesRule/Model/Rule/Condition/Product.php
@@ -10,6 +10,8 @@
* Product rule condition data model
*
* @author Magento Core Team
+ *
+ * @method string getAttribute()
*/
class Product extends \Magento\Rule\Model\Condition\Product\AbstractProduct
{
@@ -161,7 +163,9 @@ public function asArray(array $arrAttributes = [])
* Validate Product Rule Condition
*
* @param \Magento\Framework\Model\AbstractModel $model
+ *
* @return bool
+ * @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function validate(\Magento\Framework\Model\AbstractModel $model)
{
diff --git a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php
index 0a3f5eb5f31a3..c18ea47a21eb0 100644
--- a/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php
+++ b/app/code/Magento/Store/Model/Config/Importer/Processor/Create.php
@@ -16,8 +16,6 @@
/**
* The processor for creating of new entities.
- *
- * {@inheritdoc}
*/
class Create implements ProcessorInterface
{
@@ -84,7 +82,9 @@ public function __construct(
/**
* Creates entities in application according to the data set.
*
- * {@inheritdoc}
+ * @param array $data The data to be processed
+ * @return void
+ * @throws RuntimeException If processor was unable to finish execution
*/
public function run(array $data)
{
@@ -176,8 +176,11 @@ private function createGroups(array $items, array $data)
);
$group = $this->groupFactory->create();
+ if (!isset($groupData['root_category_id'])) {
+ $groupData['root_category_id'] = 0;
+ }
+
$group->setData($groupData);
- $group->setRootCategoryId(0);
$group->getResource()->save($group);
$group->getResource()->addCommitCallback(function () use ($data, $group, $website) {
@@ -226,8 +229,7 @@ private function createStores(array $items, array $data)
}
/**
- * Searches through given websites and compares with current websites.
- * Returns found website.
+ * Searches through given websites and compares with current websites and returns found website.
*
* @param array $data The data to be searched in
* @param string $websiteId The website id
@@ -249,8 +251,7 @@ private function detectWebsiteById(array $data, $websiteId)
}
/**
- * Searches through given groups and compares with current websites.
- * Returns found group.
+ * Searches through given groups and compares with current websites and returns found group.
*
* @param array $data The data to be searched in
* @param string $groupId The group id
@@ -272,8 +273,7 @@ private function detectGroupById(array $data, $groupId)
}
/**
- * Searches through given stores and compares with current stores.
- * Returns found store.
+ * Searches through given stores and compares with current stores and returns found store.
*
* @param array $data The data to be searched in
* @param string $storeId The store id
diff --git a/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/CreateTest.php b/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/CreateTest.php
index 2c2b0b00aec43..0fbf7bb7f044b 100644
--- a/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/CreateTest.php
+++ b/app/code/Magento/Store/Test/Unit/Model/Config/Importer/Processor/CreateTest.php
@@ -196,14 +196,30 @@ private function initTestData()
'root_category_id' => '1',
'default_store_id' => '1',
'code' => 'default',
+ ],
+ 2 => [
+ 'group_id' => '1',
+ 'website_id' => '1',
+ 'name' => 'Default1',
+ 'default_store_id' => '1',
+ 'code' => 'default1',
]
];
- $this->trimmedGroup = [
- 'name' => 'Default',
- 'root_category_id' => '1',
- 'code' => 'default',
- 'default_store_id' => '1',
- ];
+ $this->trimmedGroup =
+ [
+ 0 => [
+ 'name' => 'Default',
+ 'root_category_id' => '1',
+ 'code' => 'default',
+ 'default_store_id' => '1',
+ ],
+ 1 => [
+ 'name' => 'Default1',
+ 'root_category_id' => '0',
+ 'code' => 'default1',
+ 'default_store_id' => '1'
+ ]
+ ];
$this->stores = [
'default' => [
'store_id' => '1',
@@ -280,34 +296,34 @@ public function testRunGroup()
[ScopeInterface::SCOPE_GROUPS, $this->groups, $this->groups],
]);
- $this->websiteMock->expects($this->once())
+ $this->websiteMock->expects($this->exactly(2))
->method('getResource')
->willReturn($this->abstractDbMock);
- $this->groupMock->expects($this->once())
+ $this->groupMock->expects($this->exactly(2))
->method('setData')
- ->with($this->trimmedGroup)
- ->willReturnSelf();
- $this->groupMock->expects($this->exactly(3))
+ ->withConsecutive(
+ [$this->equalTo($this->trimmedGroup[0])],
+ [$this->equalTo($this->trimmedGroup[1])]
+ )->willReturnSelf();
+
+ $this->groupMock->expects($this->exactly(6))
->method('getResource')
->willReturn($this->abstractDbMock);
- $this->groupMock->expects($this->once())
- ->method('setRootCategoryId')
- ->with(0);
- $this->groupMock->expects($this->once())
+ $this->groupMock->expects($this->exactly(2))
->method('getDefaultStoreId')
->willReturn($defaultStoreId);
- $this->groupMock->expects($this->once())
+ $this->groupMock->expects($this->exactly(2))
->method('setDefaultStoreId')
->with($storeId);
- $this->groupMock->expects($this->once())
+ $this->groupMock->expects($this->exactly(2))
->method('setWebsite')
->with($this->websiteMock);
- $this->storeMock->expects($this->once())
+ $this->storeMock->expects($this->exactly(2))
->method('getResource')
->willReturn($this->abstractDbMock);
- $this->storeMock->expects($this->once())
+ $this->storeMock->expects($this->exactly(2))
->method('getStoreId')
->willReturn($storeId);
@@ -315,11 +331,11 @@ public function testRunGroup()
->method('load')
->withConsecutive([$this->websiteMock, 'base', 'code'], [$this->storeMock, 'default', 'code'])
->willReturnSelf();
- $this->abstractDbMock->expects($this->exactly(2))
+ $this->abstractDbMock->expects($this->exactly(4))
->method('save')
->with($this->groupMock)
->willReturnSelf();
- $this->abstractDbMock->expects($this->once())
+ $this->abstractDbMock->expects($this->exactly(2))
->method('addCommitCallback')
->willReturnCallback(function ($function) {
return $function();
diff --git a/app/code/Magento/Weee/Test/Unit/Observer/AddPaymentWeeeItemTest.php b/app/code/Magento/Weee/Test/Unit/Observer/AddPaymentWeeeItemTest.php
new file mode 100644
index 0000000000000..d19d6000112ed
--- /dev/null
+++ b/app/code/Magento/Weee/Test/Unit/Observer/AddPaymentWeeeItemTest.php
@@ -0,0 +1,146 @@
+weeeHelperMock = $this->createMock(Data::class);
+ $this->storeManagerMock = $this->createMock(StoreManagerInterface::class);
+
+ $this->observer = new AddPaymentWeeeItem(
+ $this->weeeHelperMock,
+ $this->storeManagerMock
+ );
+ }
+
+ /**
+ * Test execute
+ *
+ * @dataProvider dataProvider
+ * @param bool $isEnabled
+ * @param bool $includeInSubtotal
+ * @return void
+ */
+ public function testExecute(bool $isEnabled, bool $includeInSubtotal)
+ {
+ /** @var Observer|MockObject $observerMock */
+ $observerMock = $this->createMock(Observer::class);
+ $cartModelMock = $this->createMock(Cart::class);
+ $salesModelMock = $this->createMock(SalesModelInterface::class);
+ $itemMock = $this->createPartialMock(Item::class, ['getOriginalItem']);
+ $originalItemMock = $this->createPartialMock(Item::class, ['getParentItem']);
+ $parentItemMock = $this->createMock(Item::class);
+ $eventMock = $this->getMockBuilder(Event::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getCart'])
+ ->getMock();
+
+ $asCustomItem = $this->prepareShouldBeAddedAsCustomItem($isEnabled, $includeInSubtotal);
+ $toBeCalled = 1;
+ if (!$asCustomItem) {
+ $toBeCalled = 0;
+ }
+
+ $eventMock->expects($this->atLeast($toBeCalled))
+ ->method('getCart')
+ ->willReturn($cartModelMock);
+ $observerMock->expects($this->atLeast($toBeCalled))
+ ->method('getEvent')
+ ->willReturn($eventMock);
+ $itemMock->expects($this->atLeast($toBeCalled))
+ ->method('getOriginalItem')
+ ->willReturn($originalItemMock);
+ $originalItemMock->expects($this->atLeast($toBeCalled))
+ ->method('getParentItem')
+ ->willReturn($parentItemMock);
+ $salesModelMock->expects($this->atLeast($toBeCalled))
+ ->method('getAllItems')
+ ->willReturn([$itemMock]);
+ $cartModelMock->expects($this->atLeast($toBeCalled))
+ ->method('getSalesModel')
+ ->willReturn($salesModelMock);
+
+ $this->observer->execute($observerMock);
+ }
+
+ /**
+ * @return array
+ */
+ public function dataProvider(): array
+ {
+ return [
+ [true, false],
+ [true, true],
+ [false, true],
+ [false, false],
+ ];
+ }
+
+ /**
+ * Prepare if FPT should be added to payment cart as custom item or not.
+ *
+ * @param bool $isEnabled
+ * @param bool $includeInSubtotal
+ * @return bool
+ */
+ private function prepareShouldBeAddedAsCustomItem(bool $isEnabled, bool $includeInSubtotal): bool
+ {
+ $storeMock = $this->getMockBuilder(StoreInterface::class)
+ ->setMethods(['getId'])
+ ->getMockForAbstractClass();
+ $storeMock->method('getId')->willReturn(Store::DEFAULT_STORE_ID);
+ $this->storeManagerMock->method('getStore')->willReturn($storeMock);
+ $this->weeeHelperMock->method('isEnabled')->with(Store::DEFAULT_STORE_ID)
+ ->willReturn($isEnabled);
+
+ if ($isEnabled) {
+ $this->weeeHelperMock->method('includeInSubtotal')->with(Store::DEFAULT_STORE_ID)
+ ->willReturn($includeInSubtotal);
+ }
+
+ return $isEnabled && !$includeInSubtotal;
+ }
+}
diff --git a/app/code/Magento/Weee/Test/Unit/Observer/SetWeeeRendererInFormObserverTest.php b/app/code/Magento/Weee/Test/Unit/Observer/SetWeeeRendererInFormObserverTest.php
new file mode 100644
index 0000000000000..f9f39aa8ebf6f
--- /dev/null
+++ b/app/code/Magento/Weee/Test/Unit/Observer/SetWeeeRendererInFormObserverTest.php
@@ -0,0 +1,79 @@
+layoutMock = $this->createMock(LayoutInterface::class);
+ $this->taxModelMock = $this->createMock(Tax::class);
+ $this->observer = new SetWeeeRendererInFormObserver(
+ $this->layoutMock,
+ $this->taxModelMock
+ );
+ }
+
+ /**
+ * Test assigning a custom renderer for product create/edit form weee attribute element
+ *
+ * @return void
+ */
+ public function testExecute()
+ {
+ $attributes = new \ArrayIterator(['element_code_1', 'element_code_2']);
+ /** @var Event|MockObject $eventMock */
+ $eventMock = $this->getMockBuilder(Event::class)->disableOriginalConstructor()
+ ->setMethods(['getForm'])
+ ->getMock();
+
+ /** @var Observer|MockObject $observerMock */
+ $observerMock = $this->createMock(Observer::class);
+ /** @var Form|MockObject $formMock */
+ $formMock = $this->createMock(Form::class);
+
+ $eventMock->method('getForm')->willReturn($formMock);
+ $observerMock->method('getEvent')->willReturn($eventMock);
+ $this->taxModelMock->method('getWeeeAttributeCodes')->willReturn($attributes);
+ $formMock->expects($this->exactly($attributes->count()))->method('getElement')->willReturnSelf();
+
+ $this->observer->execute($observerMock);
+ }
+}
diff --git a/app/code/Magento/Wishlist/Test/Unit/Plugin/Ui/DataProvider/WishlistSettingsTest.php b/app/code/Magento/Wishlist/Test/Unit/Plugin/Ui/DataProvider/WishlistSettingsTest.php
new file mode 100644
index 0000000000000..aa3b956e12153
--- /dev/null
+++ b/app/code/Magento/Wishlist/Test/Unit/Plugin/Ui/DataProvider/WishlistSettingsTest.php
@@ -0,0 +1,59 @@
+helperMock = $this->createMock(Data::class);
+ $this->wishlistSettings = new WishlistSettings($this->helperMock);
+ }
+
+ /**
+ * Test afterGetData method
+ *
+ * @return void
+ */
+ public function testAfterGetData()
+ {
+ /** @var DataProvider|\PHPUnit_Framework_MockObject_MockObject $subjectMock */
+ $subjectMock = $this->createMock(DataProvider::class);
+ $result = [];
+ $isAllow = true;
+ $this->helperMock->expects($this->once())->method('isAllow')->willReturn(true);
+
+ $expected = ['allowWishlist' => $isAllow];
+ $actual = $this->wishlistSettings->afterGetData($subjectMock, $result);
+ self::assertEquals($expected, $actual);
+ }
+}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemRepositoryTest.php
index 18f57515c4d18..268cb72e25f8d 100644
--- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemRepositoryTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/CartItemRepositoryTest.php
@@ -70,6 +70,7 @@ public function testAddProductToCartWithCustomOptions()
'custom_options' => $this->getOptions(),
],
],
+ 'price' => $item->getPrice(),
],
$response
);