diff --git a/app/code/Magento/Braintree/Test/Unit/Model/InstantPurchase/CreditCard/AvailabilityCheckerTest.php b/app/code/Magento/Braintree/Test/Unit/Model/InstantPurchase/CreditCard/AvailabilityCheckerTest.php new file mode 100644 index 0000000000000..2248aab1aad2e --- /dev/null +++ b/app/code/Magento/Braintree/Test/Unit/Model/InstantPurchase/CreditCard/AvailabilityCheckerTest.php @@ -0,0 +1,70 @@ +configMock = $this->createMock(Config::class); + $this->availabilityChecker = new AvailabilityChecker($this->configMock); + } + + /** + * Test isAvailable method + * + * @dataProvider isAvailableDataProvider + * + * @param bool $isVerify3DSecure + * @param bool $expected + * + * @return void + */ + public function testIsAvailable(bool $isVerify3DSecure, bool $expected) + { + $this->configMock->expects($this->once())->method('isVerify3DSecure')->willReturn($isVerify3DSecure); + $actual = $this->availabilityChecker->isAvailable(); + self::assertEquals($expected, $actual); + } + + /** + * Data provider for isAvailable method test + * + * @return array + */ + public function isAvailableDataProvider() + { + return [ + [true, false], + [false, true], + ]; + } +} diff --git a/app/code/Magento/Braintree/Test/Unit/Model/InstantPurchase/CreditCard/TokenFormatterTest.php b/app/code/Magento/Braintree/Test/Unit/Model/InstantPurchase/CreditCard/TokenFormatterTest.php new file mode 100644 index 0000000000000..a5c7cd743d85f --- /dev/null +++ b/app/code/Magento/Braintree/Test/Unit/Model/InstantPurchase/CreditCard/TokenFormatterTest.php @@ -0,0 +1,119 @@ + 'visa', + 'maskedCC' => '1111************9999', + 'expirationDate' => '01-01-2020' + ]; + + /** + * Set Up + * + * @return void + */ + protected function setUp() + { + $this->paymentTokenMock = $this->getMockBuilder(PaymentTokenInterface::class) + ->getMockForAbstractClass(); + + $this->creditCardTokenFormatter = new CreditCardTokenFormatter(); + } + + /** + * Testing the payment format with a known credit card type + * + * @return void + */ + public function testFormatPaymentTokenWithKnownCardType() + { + $this->tokenDetails['type'] = key(CreditCardTokenFormatter::$baseCardTypes); + $this->paymentTokenMock->expects($this->once()) + ->method('getTokenDetails') + ->willReturn(json_encode($this->tokenDetails)); + + $formattedString = sprintf( + '%s: %s, %s: %s (%s: %s)', + __('Credit Card'), + reset(CreditCardTokenFormatter::$baseCardTypes), + __('ending'), + $this->tokenDetails['maskedCC'], + __('expires'), + $this->tokenDetails['expirationDate'] + ); + + self::assertEquals( + $formattedString, + $this->creditCardTokenFormatter->formatPaymentToken($this->paymentTokenMock) + ); + } + + /** + * Testing the payment format with a unknown credit card type + * + * @return void + */ + public function testFormatPaymentTokenWithUnknownCardType() + { + $this->paymentTokenMock->expects($this->once()) + ->method('getTokenDetails') + ->willReturn(json_encode($this->tokenDetails)); + + $formattedString = sprintf( + '%s: %s, %s: %s (%s: %s)', + __('Credit Card'), + $this->tokenDetails['type'], + __('ending'), + $this->tokenDetails['maskedCC'], + __('expires'), + $this->tokenDetails['expirationDate'] + ); + + self::assertEquals( + $formattedString, + $this->creditCardTokenFormatter->formatPaymentToken($this->paymentTokenMock) + ); + } + + /** + * Testing the payment format with wrong card data + * + * @return void + */ + public function testFormatPaymentTokenWithWrongData() + { + unset($this->tokenDetails['type']); + $this->paymentTokenMock->expects($this->once()) + ->method('getTokenDetails') + ->willReturn(json_encode($this->tokenDetails)); + self::expectException('\InvalidArgumentException'); + + $this->creditCardTokenFormatter->formatPaymentToken($this->paymentTokenMock); + } +} diff --git a/app/code/Magento/Braintree/Test/Unit/Model/InstantPurchase/PaymentAdditionalInformationProviderTest.php b/app/code/Magento/Braintree/Test/Unit/Model/InstantPurchase/PaymentAdditionalInformationProviderTest.php new file mode 100644 index 0000000000000..2631fcbe5f5b5 --- /dev/null +++ b/app/code/Magento/Braintree/Test/Unit/Model/InstantPurchase/PaymentAdditionalInformationProviderTest.php @@ -0,0 +1,83 @@ +getPaymentNonceCommandMock = $this->createMock(GetPaymentNonceCommand::class); + $this->paymentTokenMock = $this->createMock(PaymentTokenInterface::class); + $this->arrayResultMock = $this->createMock(ArrayResult::class); + $this->paymentAdditionalInformationProvider = new PaymentAdditionalInformationProvider( + $this->getPaymentNonceCommandMock + ); + } + + /** + * Test getAdditionalInformation method + * + * @return void + */ + public function testGetAdditionalInformation() + { + $customerId = 15; + $publicHash = '3n4b7sn48g'; + $paymentMethodNonce = 'test'; + + $this->paymentTokenMock->expects($this->once())->method('getCustomerId')->willReturn($customerId); + $this->paymentTokenMock->expects($this->once())->method('getPublicHash')->willReturn($publicHash); + $this->getPaymentNonceCommandMock->expects($this->once())->method('execute')->with([ + PaymentTokenInterface::CUSTOMER_ID => $customerId, + PaymentTokenInterface::PUBLIC_HASH => $publicHash, + ])->willReturn($this->arrayResultMock); + $this->arrayResultMock->expects($this->once())->method('get') + ->willReturn(['paymentMethodNonce' => $paymentMethodNonce]); + + $expected = [ + 'payment_method_nonce' => $paymentMethodNonce, + ]; + $actual = $this->paymentAdditionalInformationProvider->getAdditionalInformation($this->paymentTokenMock); + self::assertEquals($expected, $actual); + } +} diff --git a/app/code/Magento/Braintree/Test/Unit/Model/LocaleResolverTest.php b/app/code/Magento/Braintree/Test/Unit/Model/LocaleResolverTest.php new file mode 100644 index 0000000000000..b6ef534c55c29 --- /dev/null +++ b/app/code/Magento/Braintree/Test/Unit/Model/LocaleResolverTest.php @@ -0,0 +1,138 @@ +configMock = $this->createMock(Config::class); + $this->resolverMock = $this->createMock(ResolverInterface::class); + $this->localeResolver = new LocaleResolver($this->resolverMock, $this->configMock); + } + + /** + * Test getDefaultLocalePath method + * + * @return void + */ + public function testGetDefaultLocalePath() + { + $expected = 'general/locale/code'; + $this->resolverMock->expects($this->once())->method('getDefaultLocalePath')->willReturn($expected); + $actual = $this->localeResolver->getDefaultLocalePath(); + self::assertEquals($expected, $actual); + } + + /** + * Test setDefaultLocale method + * + * @return void + */ + public function testSetDefaultLocale() + { + $defaultLocale = 'en_US'; + $this->resolverMock->expects($this->once())->method('setDefaultLocale')->with($defaultLocale); + $this->localeResolver->setDefaultLocale($defaultLocale); + } + + /** + * Test getDefaultLocale method + * + * @return void + */ + public function testGetDefaultLocale() + { + $expected = 'fr_FR'; + $this->resolverMock->expects($this->once())->method('getDefaultLocale')->willReturn($expected); + $actual = $this->localeResolver->getDefaultLocale(); + self::assertEquals($expected, $actual); + } + + /** + * Test setLocale method + * + * @return void + */ + public function testSetLocale() + { + $locale = 'en_GB'; + $this->resolverMock->expects($this->once())->method('setLocale')->with($locale); + $this->localeResolver->setLocale($locale); + } + + /** + * Test getLocale method + * + * @return void + */ + public function testGetLocale() + { + $locale = 'en_TEST'; + $allowedLocales = 'en_US,en_GB,en_AU,da_DK,fr_FR,fr_CA,de_DE,zh_HK,it_IT,nl_NL'; + $this->resolverMock->expects($this->once())->method('getLocale')->willReturn($locale); + $this->configMock->expects($this->once())->method('getValue')->with('supported_locales') + ->willReturn($allowedLocales); + + $expected = 'en_US'; + $actual = $this->localeResolver->getLocale(); + self::assertEquals($expected, $actual); + } + + /** + * Test emulate method + * + * @return void + */ + public function testEmulate() + { + $scopeId = 12; + $this->resolverMock->expects($this->once())->method('emulate')->with($scopeId); + $this->localeResolver->emulate($scopeId); + } + + /** + * Test revert method + * + * @return void + */ + public function testRevert() + { + $this->resolverMock->expects($this->once())->method('revert'); + $this->localeResolver->revert(); + } +} diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index 4c0122694285d..ef2c99c5cb40e 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -514,13 +514,14 @@ protected function processMediaGallery(ProductInterface $product, $mediaGalleryE $newEntries = $mediaGalleryEntries; } + $images = (array)$product->getMediaGallery('images'); + $images = $this->determineImageRoles($product, $images); + $this->getMediaGalleryProcessor()->clearMediaAttribute($product, array_keys($product->getMediaAttributes())); - $images = $product->getMediaGallery('images'); - if ($images) { - foreach ($images as $image) { - if (!isset($image['removed']) && !empty($image['types'])) { - $this->getMediaGalleryProcessor()->setMediaAttribute($product, $image['types'], $image['file']); - } + + foreach ($images as $image) { + if (!isset($image['removed']) && !empty($image['types'])) { + $this->getMediaGalleryProcessor()->setMediaAttribute($product, $image['types'], $image['file']); } } @@ -758,6 +759,32 @@ public function cleanCache() $this->instancesById = null; } + /** + * Ascertain image roles, if they are not set against the gallery entries + * + * @param ProductInterface $product + * @param array $images + * @return array + */ + private function determineImageRoles(ProductInterface $product, array $images) : array + { + $imagesWithRoles = []; + foreach ($images as $image) { + if (!isset($image['types'])) { + $image['types'] = []; + if (isset($image['file'])) { + foreach (array_keys($product->getMediaAttributes()) as $attribute) { + if ($image['file'] == $product->getData($attribute)) { + $image['types'][] = $attribute; + } + } + } + } + $imagesWithRoles[] = $image; + } + return $imagesWithRoles; + } + /** * @return Product\Gallery\Processor */ diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptions.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptions.xml index 8628ae9b99d3a..6e43753220d7c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptions.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontPurchaseProductWithCustomOptions.xml @@ -16,9 +16,7 @@ - - - + diff --git a/app/code/Magento/Catalog/Test/Unit/Cron/DeleteAbandonedStoreFlatTablesTest.php b/app/code/Magento/Catalog/Test/Unit/Cron/DeleteAbandonedStoreFlatTablesTest.php new file mode 100644 index 0000000000000..1a9d7959dda9c --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Cron/DeleteAbandonedStoreFlatTablesTest.php @@ -0,0 +1,51 @@ +indexerMock = $this->createMock(Indexer::class); + $this->deleteAbandonedStoreFlatTables = new DeleteAbandonedStoreFlatTables($this->indexerMock); + } + + /** + * Test execute method + * + * @return void + */ + public function testExecute() + { + $this->indexerMock->expects($this->once())->method('deleteAbandonedStoreFlatTables'); + $this->deleteAbandonedStoreFlatTables->execute(); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Cron/DeleteOutdatedPriceValuesTest.php b/app/code/Magento/Catalog/Test/Unit/Cron/DeleteOutdatedPriceValuesTest.php new file mode 100644 index 0000000000000..f1d0034c29580 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Cron/DeleteOutdatedPriceValuesTest.php @@ -0,0 +1,139 @@ +resourceConnectionMock = $this->createMock(ResourceConnection::class); + $this->attributeRepositoryMock = $this->createMock(AttributeRepository::class); + $this->attributeMock = $this->createMock(Attribute::class); + $this->scopeConfigMock = $this->createMock(ScopeConfig::class); + $this->dbAdapterMock = $this->createMock(AdapterInterface::class); + $this->attributeBackendMock = $this->createMock(BackendInterface::class); + $this->deleteOutdatedPriceValues = new DeleteOutdatedPriceValues( + $this->resourceConnectionMock, + $this->attributeRepositoryMock, + $this->scopeConfigMock + ); + } + + /** + * Test execute method + * + * @return void + */ + public function testExecute() + { + $table = 'catalog_product_entity_decimal'; + $attributeId = 15; + $conditions = ['first', 'second']; + + $this->scopeConfigMock + ->expects($this->once()) + ->method('getValue') + ->with(Store::XML_PATH_PRICE_SCOPE) + ->willReturn(Store::XML_PATH_PRICE_SCOPE); + $this->attributeRepositoryMock + ->expects($this->once()) + ->method('get') + ->with(ProductAttributeInterface::ENTITY_TYPE_CODE, ProductAttributeInterface::CODE_PRICE) + ->willReturn($this->attributeMock); + $this->attributeMock->expects($this->once())->method('getId')->willReturn($attributeId); + $this->attributeMock->expects($this->once())->method('getBackend')->willReturn($this->attributeBackendMock); + $this->attributeBackendMock->expects($this->once())->method('getTable')->willReturn($table); + $this->resourceConnectionMock->expects($this->once()) + ->method('getConnection') + ->willReturn($this->dbAdapterMock); + $this->dbAdapterMock->expects($this->exactly(2))->method('quoteInto')->willReturnMap([ + ['attribute_id = ?', $attributeId, null, null, $conditions[0]], + ['store_id != ?', Store::DEFAULT_STORE_ID, null, null, $conditions[1]], + ]); + $this->dbAdapterMock->expects($this->once())->method('delete')->with($table, $conditions); + $this->deleteOutdatedPriceValues->execute(); + } + + /** + * Test execute method + * The price scope config option is not equal to global value + * + * @return void + */ + public function testExecutePriceConfigIsNotSetToGlobal() + { + $this->scopeConfigMock + ->expects($this->once()) + ->method('getValue') + ->with(Store::XML_PATH_PRICE_SCOPE) + ->willReturn(null); + $this->attributeRepositoryMock + ->expects($this->never()) + ->method('get'); + $this->dbAdapterMock + ->expects($this->never()) + ->method('delete'); + + $this->deleteOutdatedPriceValues->execute(); + } +} diff --git a/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml b/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml index 537932a2d4daa..dafea71f872d0 100644 --- a/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml +++ b/app/code/Magento/Catalog/view/adminhtml/ui_component/category_form.xml @@ -42,7 +42,7 @@ -
+
false