From d11fda51f8fcb4259f0d03e41728810cbb9f3448 Mon Sep 17 00:00:00 2001 From: Alexandr Voronoy Date: Thu, 15 Nov 2018 15:31:21 +0200 Subject: [PATCH 001/224] Access to related/up-sell/cross-sell product fields in graphql --- .../Model/Resolver/Product/Related.php | 43 +++++++++++ .../Product/Related/CrossSellProducts.php | 60 ++++++++++++++++ .../Product/Related/RelatedProducts.php | 71 +++++++++++++++++++ .../Product/Related/UpSellProducts.php | 70 ++++++++++++++++++ .../Related/AbstractDataProvider.php | 70 ++++++++++++++++++ .../Related/CrossSellDataProvider.php | 26 +++++++ .../Related/RelatedDataProvider.php | 18 +++++ .../Related/UpSellDataProvider.php | 25 +++++++ .../CatalogGraphQl/etc/schema.graphqls | 18 ++++- 9 files changed, 398 insertions(+), 3 deletions(-) create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related.php create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/CrossSellProducts.php create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/RelatedProducts.php create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/UpSellProducts.php create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/AbstractDataProvider.php create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/CrossSellDataProvider.php create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/RelatedDataProvider.php create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/UpSellDataProvider.php diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related.php new file mode 100644 index 0000000000000..bd0199db2c2d2 --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related.php @@ -0,0 +1,43 @@ +getName(); + + return [ + 'model' => $product, + 'product_list_type' => $productListType + ]; + } +} diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/CrossSellProducts.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/CrossSellProducts.php new file mode 100644 index 0000000000000..59d619222399a --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/CrossSellProducts.php @@ -0,0 +1,60 @@ +dataProvider = $dataProvider; + } + + /** + * Fetches the data from persistence models and format it according to the GraphQL schema. + * + * @param \Magento\Framework\GraphQl\Config\Element\Field $field + * @param ContextInterface $context + * @param ResolveInfo $info + * @param array|null $value + * @param array|null $args + * @throws \Exception + * @return mixed|Value + */ + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) + { + $product = $value['model']; + $this->dataProvider->addFieldToSelect(self::FIELDS); + $collection = $this->dataProvider->getData($product); + + $count = 0; + foreach ($collection as $item) { + $data[$count] = $item->getData(); + $data[$count]['model'] = $item; + $count++; + } + return $data; + } + +} \ No newline at end of file diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/RelatedProducts.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/RelatedProducts.php new file mode 100644 index 0000000000000..bfaed0279b59c --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/RelatedProducts.php @@ -0,0 +1,71 @@ +dataProvider = $dataProvider; + } + + /** + * Fetches the data from persistence models and format it according to the GraphQL schema. + * + * @param \Magento\Framework\GraphQl\Config\Element\Field $field + * @param ContextInterface $context + * @param ResolveInfo $info + * @param array|null $value + * @param array|null $args + * @throws \Exception + * @return mixed|Value + */ + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) + { + $product = $value['model']; + $this->dataProvider->addFieldToSelect(self::FIELDS); + $collection = $this->dataProvider->getData($product); + + $count = 0; + $data = []; + foreach ($collection as $item) { + $data[$count] = $item->getData(); + $data[$count]['model'] = $item; + $count++; + } + return $data; + } + +} \ No newline at end of file diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/UpSellProducts.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/UpSellProducts.php new file mode 100644 index 0000000000000..82980eb338b47 --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/UpSellProducts.php @@ -0,0 +1,70 @@ +dataProvider = $dataProvider; + } + + /** + * Fetches the data from persistence models and format it according to the GraphQL schema. + * + * @param \Magento\Framework\GraphQl\Config\Element\Field $field + * @param ContextInterface $context + * @param ResolveInfo $info + * @param array|null $value + * @param array|null $args + * @throws \Exception + * @return mixed|Value + */ + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) + { + $product = $value['model']; + $this->dataProvider->addFieldToSelect(self::FIELDS); + $collection = $this->dataProvider->getData($product); + + $count = 0; + $data = []; + foreach ($collection as $item) { + $data[$count] = $item->getData(); + $data[$count]['model'] = $item; + $count++; + } + return $data; + } + +} \ No newline at end of file diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/AbstractDataProvider.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/AbstractDataProvider.php new file mode 100644 index 0000000000000..4dcff69e07aaa --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/AbstractDataProvider.php @@ -0,0 +1,70 @@ +fields = $field; + } + + + /** + * @return array + */ + public function getFields(): array + { + return $this->fields; + } + + /** + * @return mixed + */ + public function getCollection() + { + return $this->collection; + } + + /** + * @param $product + * @return mixed + */ + public function getData($product) + { + $this->prepareCollection($product); + return $this->collection; + + } + + /** + * @param $product + */ + protected function prepareCollection($product): void + { + $this->collection = $product->getRelatedProducts(); + $this->collection->addAttributeToSelect($this->getFields()); + } + + +} \ No newline at end of file diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/CrossSellDataProvider.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/CrossSellDataProvider.php new file mode 100644 index 0000000000000..cc238d1179699 --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/CrossSellDataProvider.php @@ -0,0 +1,26 @@ +collection = $product->getCrossSellProductCollection(); + $this->collection->addAttributeToSelect($this->getFields()); + } + +} \ No newline at end of file diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/RelatedDataProvider.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/RelatedDataProvider.php new file mode 100644 index 0000000000000..3adc193c1c2bb --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/RelatedDataProvider.php @@ -0,0 +1,18 @@ +collection = $product->getRelatedProductCollection(); + $this->collection->addAttributeToSelect($this->getFields()); + } + + +} \ No newline at end of file diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/UpSellDataProvider.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/UpSellDataProvider.php new file mode 100644 index 0000000000000..03bd7793fab32 --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/UpSellDataProvider.php @@ -0,0 +1,25 @@ +collection = $product->getUpSellProductCollection(); + $this->collection->addAttributeToSelect($this->getFields()); + } +} \ No newline at end of file diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index e2eab9121e332..c56bfb4574c6d 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -225,10 +225,10 @@ type ProductPrices @doc(description: "The ProductPrices object contains the regu regularPrice: Price @doc(description: "The base price of a product.") } -type ProductLinks implements ProductLinksInterface @doc(description: "ProductLinks is an implementation of ProductLinksInterface.") { +type Related implements ProductLinksInterface @doc(description: "Related is an implementation of ProductLinksInterface.") { } -interface ProductLinksInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\ProductLinkTypeResolverComposite") @doc(description:"ProductLinks contains information about linked products, including the link type and product type of each item.") { +interface ProductLinksInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\ProductLinkTypeResolverComposite") @doc(description:"Related contains information about linked products, including the link type and product type of each item.") { sku: String @doc(description: "The identifier of the linked product") link_type: String @doc(description: "One of related, associated, upsell, or crosssell") linked_product_sku: String @doc(description: "The SKU of the linked product") @@ -269,8 +269,11 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ country_of_manufacture: String @doc(description: "The product's country of origin") type_id: String @doc(description: "One of simple, virtual, bundle, downloadable, grouped, or configurable") websites: [Website] @doc(description: "An array of websites in which the product is available") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Websites") - product_links: [ProductLinksInterface] @doc(description: "An array of ProductLinks objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\ProductLinks") + product_links: [ProductLinksInterface] @doc(description: "An array of Related objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related") media_gallery_entries: [MediaGalleryEntry] @doc(description: "An array of MediaGalleryEntry objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\MediaGalleryEntries") + related_products: RelatedProduct @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related") + upsell_products: UpsellProduct @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related") + crosssell_products: CrosssellProduct @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related") tier_prices: [ProductTierPrices] @doc(description: "An array of ProductTierPrices objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\TierPrices") price: ProductPrices @doc(description: "A ProductPrices object, indicating the price of an item") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Price") gift_message_available: String @doc(description: "Indicates whether a gift message is available") @@ -526,6 +529,15 @@ type MediaGalleryEntry @doc(description: "MediaGalleryEntry defines characteris content: ProductMediaGalleryEntriesContent @doc(description: "Contains a ProductMediaGalleryEntriesContent object") video_content: ProductMediaGalleryEntriesVideoContent @doc(description: "Contains a ProductMediaGalleryEntriesVideoContent object") } +type RelatedProduct @doc(description: "RelatedProduct"){ + items: [ProductInterface] @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related\\RelatedProducts") +} +type UpsellProduct @doc(description: "UpsellProduct"){ + items: [ProductInterface] @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related\\UpSellProducts") +} +type CrosssellProduct @doc(description: "CrosssellProduct"){ + items: [ProductInterface] @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related\\CrossSellProducts") +} type LayerFilter { name: String @doc(description: "Layered navigation filter name") From 094cf30bf8743808eff4ec228f8e1d2267a23773 Mon Sep 17 00:00:00 2001 From: Alexandr Voronoy Date: Thu, 15 Nov 2018 15:39:23 +0200 Subject: [PATCH 002/224] Fix schema @doc and type --- app/code/Magento/CatalogGraphQl/etc/schema.graphqls | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index c56bfb4574c6d..37641ab023f56 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -225,7 +225,7 @@ type ProductPrices @doc(description: "The ProductPrices object contains the regu regularPrice: Price @doc(description: "The base price of a product.") } -type Related implements ProductLinksInterface @doc(description: "Related is an implementation of ProductLinksInterface.") { +type ProductLinks implements ProductLinksInterface @doc(description: "ProductLinks is an implementation of ProductLinksInterface.") { } interface ProductLinksInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\ProductLinkTypeResolverComposite") @doc(description:"Related contains information about linked products, including the link type and product type of each item.") { @@ -269,7 +269,7 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ country_of_manufacture: String @doc(description: "The product's country of origin") type_id: String @doc(description: "One of simple, virtual, bundle, downloadable, grouped, or configurable") websites: [Website] @doc(description: "An array of websites in which the product is available") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Websites") - product_links: [ProductLinksInterface] @doc(description: "An array of Related objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related") + product_links: [ProductLinksInterface] @doc(description: "An array of ProductLinks objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\ProductLinks") media_gallery_entries: [MediaGalleryEntry] @doc(description: "An array of MediaGalleryEntry objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\MediaGalleryEntries") related_products: RelatedProduct @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related") upsell_products: UpsellProduct @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related") From bbb386bb5ab25c19c302a545f261eca588b0b828 Mon Sep 17 00:00:00 2001 From: Patrick McLain Date: Fri, 14 Dec 2018 02:07:47 -0500 Subject: [PATCH 003/224] Prevent display of token when save for later is not selected This sets the token `isVisible` value to faluse if `VaultConfigProvider::IS_ACTIVE_CODE` is not set in the payment's `additionalInformation` property. The value is not set when placing orders through the admin panel, unless the save for later checkbox is selected. This caused all admin order payment to be visible in the stored payment method section in the storefront. Fixes magento/magento2#19515 Testing on 2.3 depends on magento/magento2#19764 --- .../Observer/AfterPaymentSaveObserver.php | 8 ++--- .../Observer/AfterPaymentSaveObserverTest.php | 31 ++++++++++++++++--- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Vault/Observer/AfterPaymentSaveObserver.php b/app/code/Magento/Vault/Observer/AfterPaymentSaveObserver.php index 49d34091b136a..00aee961d8d3f 100644 --- a/app/code/Magento/Vault/Observer/AfterPaymentSaveObserver.php +++ b/app/code/Magento/Vault/Observer/AfterPaymentSaveObserver.php @@ -77,11 +77,9 @@ public function execute(Observer $observer) $paymentToken->setPaymentMethodCode($payment->getMethod()); $additionalInformation = $payment->getAdditionalInformation(); - if (isset($additionalInformation[VaultConfigProvider::IS_ACTIVE_CODE])) { - $paymentToken->setIsVisible( - (bool) (int) $additionalInformation[VaultConfigProvider::IS_ACTIVE_CODE] - ); - } + $paymentToken->setIsVisible( + (bool) (int) ($additionalInformation[VaultConfigProvider::IS_ACTIVE_CODE] ?? 0) + ); $paymentToken->setPublicHash($this->generatePublicHash($paymentToken)); diff --git a/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php b/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php index 09c17d1e58d98..a6b8502f66a1b 100644 --- a/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php +++ b/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php @@ -15,6 +15,7 @@ use Magento\Sales\Model\Order\Payment; use Magento\Vault\Model\PaymentToken; use Magento\Vault\Model\PaymentTokenManagement; +use Magento\Vault\Model\Ui\VaultConfigProvider; use Magento\Vault\Observer\AfterPaymentSaveObserver; use PHPUnit_Framework_MockObject_MockObject as MockObject; @@ -93,7 +94,7 @@ protected function setUp() // Sales Order Payment Model $this->salesOrderPaymentMock = $this->getMockBuilder(Payment::class) - ->setMethods(null) + ->setMethods(['getAdditionalInformation']) ->disableOriginalConstructor() ->getMock(); $this->salesOrderPaymentMock->setOrder($this->salesOrderMock); @@ -122,9 +123,10 @@ protected function setUp() * @param string $token * @param bool $isActive * @param string $method + * @param array $additionalInformation * @dataProvider positiveCaseDataProvider */ - public function testPositiveCase($customerId, $createdAt, $token, $isActive, $method) + public function testPositiveCase($customerId, $createdAt, $token, $isActive, $method, $additionalInformation) { $this->paymentTokenMock->setGatewayToken($token); $this->paymentTokenMock->setCustomerId($customerId); @@ -136,6 +138,8 @@ public function testPositiveCase($customerId, $createdAt, $token, $isActive, $me ->method('getVaultPaymentToken') ->willReturn($this->paymentTokenMock); + $this->salesOrderPaymentMock->method('getAdditionalInformation')->willReturn($additionalInformation); + if (!empty($token)) { $this->paymentTokenManagementMock->expects($this->once()) ->method('saveTokenWithPaymentLink') @@ -158,6 +162,7 @@ public function testPositiveCase($customerId, $createdAt, $token, $isActive, $me static::assertEquals($token, $paymentToken->getGatewayToken()); static::assertEquals($isActive, $paymentToken->getIsActive()); static::assertEquals($createdAt, $paymentToken->getCreatedAt()); + static::assertEquals($additionalInformation[VaultConfigProvider::IS_ACTIVE_CODE] ?? false, $paymentToken->getIsVisible()); } /** @@ -171,14 +176,32 @@ public function positiveCaseDataProvider() '10\20\2015', 'asdfg', true, - 'paypal' + 'paypal', + [], + ], + [ + 1, + '10\20\2015', + 'asdfg', + true, + 'paypal', + [VaultConfigProvider::IS_ACTIVE_CODE => true], + ], + [ + 1, + '10\20\2015', + 'asdfg', + true, + 'paypal', + [VaultConfigProvider::IS_ACTIVE_CODE => false], ], [ null, null, null, false, - null + null, + [], ], ]; } From d93a9b5c3a01946e29bf87ffea635a45d9bea289 Mon Sep 17 00:00:00 2001 From: Patrick McLain Date: Thu, 27 Dec 2018 12:47:06 -0500 Subject: [PATCH 004/224] Shorten variable name to make codacy happy --- .../Test/Unit/Observer/AfterPaymentSaveObserverTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php b/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php index a6b8502f66a1b..539a4b5c38b34 100644 --- a/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php +++ b/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php @@ -123,10 +123,10 @@ protected function setUp() * @param string $token * @param bool $isActive * @param string $method - * @param array $additionalInformation + * @param array $additionalInfo * @dataProvider positiveCaseDataProvider */ - public function testPositiveCase($customerId, $createdAt, $token, $isActive, $method, $additionalInformation) + public function testPositiveCase($customerId, $createdAt, $token, $isActive, $method, $additionalInfo) { $this->paymentTokenMock->setGatewayToken($token); $this->paymentTokenMock->setCustomerId($customerId); @@ -138,7 +138,7 @@ public function testPositiveCase($customerId, $createdAt, $token, $isActive, $me ->method('getVaultPaymentToken') ->willReturn($this->paymentTokenMock); - $this->salesOrderPaymentMock->method('getAdditionalInformation')->willReturn($additionalInformation); + $this->salesOrderPaymentMock->method('getAdditionalInformation')->willReturn($additionalInfo); if (!empty($token)) { $this->paymentTokenManagementMock->expects($this->once()) @@ -162,7 +162,7 @@ public function testPositiveCase($customerId, $createdAt, $token, $isActive, $me static::assertEquals($token, $paymentToken->getGatewayToken()); static::assertEquals($isActive, $paymentToken->getIsActive()); static::assertEquals($createdAt, $paymentToken->getCreatedAt()); - static::assertEquals($additionalInformation[VaultConfigProvider::IS_ACTIVE_CODE] ?? false, $paymentToken->getIsVisible()); + static::assertEquals($additionalInfo[VaultConfigProvider::IS_ACTIVE_CODE] ?? false, $paymentToken->getIsVisible()); } /** From cb8221093b651f51f543f9c636f3ef6e5a06e7b7 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko Date: Wed, 13 Feb 2019 20:34:06 +0200 Subject: [PATCH 005/224] graphQl-198: refactored upSell crossSell, adjusted tests --- .../CatalogGraphQl/Model/Resolver/Product.php | 49 ++--- .../Product/ProductFieldsSelector.php | 61 ++++++ .../Model/Resolver/Product/Related.php | 43 ----- .../Product/Related/CrossSellProducts.php | 46 ++--- .../Product/Related/RelatedProducts.php | 42 +---- .../Product/Related/UpSellProducts.php | 48 ++--- .../Related/AbstractDataProvider.php | 70 ------- .../Related/CrossSellDataProvider.php | 26 --- .../Products/LinkedProductsDataProvider.php | 56 ++++++ .../Related/RelatedDataProvider.php | 76 +++++++- .../Related/UpSellDataProvider.php | 25 --- .../Magento/CatalogGraphQl/etc/graphql/di.xml | 22 +++ .../CatalogGraphQl/etc/schema.graphqls | 15 +- .../Catalog/ProductRelatedProductsTest.php | 175 ++++++++++++++++++ 14 files changed, 434 insertions(+), 320 deletions(-) create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductFieldsSelector.php delete mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related.php delete mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/AbstractDataProvider.php delete mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/CrossSellDataProvider.php create mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/Products/LinkedProductsDataProvider.php delete mode 100644 app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/UpSellDataProvider.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductRelatedProductsTest.php diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product.php index 40aa54fd93873..b3283883f5561 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product.php @@ -7,14 +7,15 @@ namespace Magento\CatalogGraphQl\Model\Resolver; -use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\CatalogGraphQl\Model\Resolver\Product\ProductFieldsSelector; use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Deferred\Product as ProductDataProvider; +use Magento\Framework\App\ObjectManager; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\FieldTranslator; -use Magento\Framework\GraphQl\Query\Resolver\Value; use Magento\Framework\GraphQl\Query\Resolver\ValueFactory; use Magento\Framework\GraphQl\Query\ResolverInterface; +use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; /** * @inheritdoc @@ -32,23 +33,33 @@ class Product implements ResolverInterface private $valueFactory; /** + * @deprecated * @var FieldTranslator */ private $fieldTranslator; + /** + * @var ProductFieldsSelector + */ + private $productFieldsSelector; + /** * @param ProductDataProvider $productDataProvider * @param ValueFactory $valueFactory * @param FieldTranslator $fieldTranslator + * @param ProductFieldsSelector $productFieldsSelector */ public function __construct( ProductDataProvider $productDataProvider, ValueFactory $valueFactory, - FieldTranslator $fieldTranslator + FieldTranslator $fieldTranslator, + ProductFieldsSelector $productFieldsSelector ) { $this->productDataProvider = $productDataProvider; $this->valueFactory = $valueFactory; $this->fieldTranslator = $fieldTranslator; + $this->productFieldsSelector = $productFieldsSelector + ?? ObjectManager::getInstance()->get(ProductFieldsSelector::class); } /** @@ -60,7 +71,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value throw new GraphQlInputException(__('No child sku found for product link.')); } $this->productDataProvider->addProductSku($value['sku']); - $fields = $this->getProductFields($info); + $fields = $this->productFieldsSelector->getProductFieldsFromInfo($info); $this->productDataProvider->addEavAttributes($fields); $result = function () use ($value) { @@ -86,34 +97,4 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value return $this->valueFactory->create($result); } - - /** - * Return field names for all requested product fields. - * - * @param ResolveInfo $info - * @return string[] - */ - private function getProductFields(ResolveInfo $info) : array - { - $fieldNames = []; - foreach ($info->fieldNodes as $node) { - if ($node->name->value !== 'product') { - continue; - } - foreach ($node->selectionSet->selections as $selectionNode) { - if ($selectionNode->kind === 'InlineFragment') { - foreach ($selectionNode->selectionSet->selections as $inlineSelection) { - if ($inlineSelection->kind === 'InlineFragment') { - continue; - } - $fieldNames[] = $this->fieldTranslator->translate($inlineSelection->name->value); - } - continue; - } - $fieldNames[] = $this->fieldTranslator->translate($selectionNode->name->value); - } - } - - return $fieldNames; - } } diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductFieldsSelector.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductFieldsSelector.php new file mode 100644 index 0000000000000..9ddad4e6451fa --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/ProductFieldsSelector.php @@ -0,0 +1,61 @@ +fieldTranslator = $fieldTranslator; + } + + /** + * Return field names for all requested product fields. + * + * @param ResolveInfo $info + * @param string $productNodeName + * @return string[] + */ + public function getProductFieldsFromInfo(ResolveInfo $info, string $productNodeName = 'product') : array + { + $fieldNames = []; + foreach ($info->fieldNodes as $node) { + if ($node->name->value !== $productNodeName) { + continue; + } + foreach ($node->selectionSet->selections as $selectionNode) { + if ($selectionNode->kind === 'InlineFragment') { + foreach ($selectionNode->selectionSet->selections as $inlineSelection) { + if ($inlineSelection->kind === 'InlineFragment') { + continue; + } + $fieldNames[] = $this->fieldTranslator->translate($inlineSelection->name->value); + } + continue; + } + $fieldNames[] = $this->fieldTranslator->translate($selectionNode->name->value); + } + } + + return $fieldNames; + } +} diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related.php deleted file mode 100644 index bd0199db2c2d2..0000000000000 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related.php +++ /dev/null @@ -1,43 +0,0 @@ -getName(); - - return [ - 'model' => $product, - 'product_list_type' => $productListType - ]; - } -} diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/CrossSellProducts.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/CrossSellProducts.php index 59d619222399a..2ae3d30a2b01f 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/CrossSellProducts.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/CrossSellProducts.php @@ -7,54 +7,38 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Product\Related; -use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\CrossSellDataProvider; +use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\RelatedDataProvider; use Magento\Framework\GraphQl\Config\Element\Field; -use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; -use Magento\Framework\GraphQl\Query\Resolver\Value; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; - +/** + * CrossSell Products Resolver + */ class CrossSellProducts implements ResolverInterface { /** - * Attribute to select fields - */ - public const FIELDS = ['sku', 'name', 'price', 'image', 'url_path', 'url_key']; - /** - * @var CrossSellDataProvider + * @see module di.xml + * @var RelatedDataProvider */ private $dataProvider; - public function __construct(CrossSellDataProvider $dataProvider) - { + /** + * @param RelatedDataProvider $dataProvider + */ + public function __construct( + RelatedDataProvider $dataProvider + ) { $this->dataProvider = $dataProvider; } /** - * Fetches the data from persistence models and format it according to the GraphQL schema. - * - * @param \Magento\Framework\GraphQl\Config\Element\Field $field - * @param ContextInterface $context - * @param ResolveInfo $info - * @param array|null $value - * @param array|null $args - * @throws \Exception - * @return mixed|Value + * @inheritdoc */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { - $product = $value['model']; - $this->dataProvider->addFieldToSelect(self::FIELDS); - $collection = $this->dataProvider->getData($product); + $data = $this->dataProvider->getProducts($info, $value); - $count = 0; - foreach ($collection as $item) { - $data[$count] = $item->getData(); - $data[$count]['model'] = $item; - $count++; - } return $data; } - -} \ No newline at end of file +} diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/RelatedProducts.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/RelatedProducts.php index bfaed0279b59c..cb437a2202c88 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/RelatedProducts.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/RelatedProducts.php @@ -7,65 +7,37 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Product\Related; - use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\RelatedDataProvider; use Magento\Framework\GraphQl\Config\Element\Field; -use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; -use Magento\Framework\GraphQl\Query\Resolver\Value; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; - /** - * Class RelatedProducts - * @package Magento\CatalogGraphQl\Model\Resolver\Product\Related + * Related Products Resolver */ class RelatedProducts implements ResolverInterface { - - /** - * Attribute to select fields - */ - public const FIELDS = ['sku', 'name', 'price', 'image', 'url_path', 'url_key']; /** * @var RelatedDataProvider */ private $dataProvider; /** - * RelatedProducts constructor. * @param RelatedDataProvider $dataProvider */ - public function __construct(RelatedDataProvider $dataProvider) - { + public function __construct( + RelatedDataProvider $dataProvider + ) { $this->dataProvider = $dataProvider; } /** - * Fetches the data from persistence models and format it according to the GraphQL schema. - * - * @param \Magento\Framework\GraphQl\Config\Element\Field $field - * @param ContextInterface $context - * @param ResolveInfo $info - * @param array|null $value - * @param array|null $args - * @throws \Exception - * @return mixed|Value + * @inheritdoc */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { - $product = $value['model']; - $this->dataProvider->addFieldToSelect(self::FIELDS); - $collection = $this->dataProvider->getData($product); + $data = $this->dataProvider->getProducts($info, $value); - $count = 0; - $data = []; - foreach ($collection as $item) { - $data[$count] = $item->getData(); - $data[$count]['model'] = $item; - $count++; - } return $data; } - -} \ No newline at end of file +} diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/UpSellProducts.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/UpSellProducts.php index 82980eb338b47..e43e0fe57de4b 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/UpSellProducts.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/UpSellProducts.php @@ -7,64 +7,38 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Product\Related; - -use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\UpSellDataProvider; +use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\RelatedDataProvider; use Magento\Framework\GraphQl\Config\Element\Field; -use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; -use Magento\Framework\GraphQl\Query\Resolver\Value; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; - /** - * Class UpSellProducts - * @package Magento\CatalogGraphQl\Model\Resolver\Product\Related + * UpSell Products Resolver */ class UpSellProducts implements ResolverInterface { /** - * Attribute to select fields - */ - public const FIELDS = ['sku', 'name', 'price', 'image', 'url_path', 'url_key']; - /** - * @var UpSellDataProvider + * @see module di.xml + * @var RelatedDataProvider */ private $dataProvider; /** - * UpSellProducts constructor. - * @param UpSellDataProvider $dataProvider + * @param RelatedDataProvider $dataProvider */ - public function __construct(UpSellDataProvider $dataProvider) - { + public function __construct( + RelatedDataProvider $dataProvider + ) { $this->dataProvider = $dataProvider; } /** - * Fetches the data from persistence models and format it according to the GraphQL schema. - * - * @param \Magento\Framework\GraphQl\Config\Element\Field $field - * @param ContextInterface $context - * @param ResolveInfo $info - * @param array|null $value - * @param array|null $args - * @throws \Exception - * @return mixed|Value + * @inheritdoc */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { - $product = $value['model']; - $this->dataProvider->addFieldToSelect(self::FIELDS); - $collection = $this->dataProvider->getData($product); + $data = $this->dataProvider->getProducts($info, $value); - $count = 0; - $data = []; - foreach ($collection as $item) { - $data[$count] = $item->getData(); - $data[$count]['model'] = $item; - $count++; - } return $data; } - -} \ No newline at end of file +} diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/AbstractDataProvider.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/AbstractDataProvider.php deleted file mode 100644 index 4dcff69e07aaa..0000000000000 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/AbstractDataProvider.php +++ /dev/null @@ -1,70 +0,0 @@ -fields = $field; - } - - - /** - * @return array - */ - public function getFields(): array - { - return $this->fields; - } - - /** - * @return mixed - */ - public function getCollection() - { - return $this->collection; - } - - /** - * @param $product - * @return mixed - */ - public function getData($product) - { - $this->prepareCollection($product); - return $this->collection; - - } - - /** - * @param $product - */ - protected function prepareCollection($product): void - { - $this->collection = $product->getRelatedProducts(); - $this->collection->addAttributeToSelect($this->getFields()); - } - - -} \ No newline at end of file diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/CrossSellDataProvider.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/CrossSellDataProvider.php deleted file mode 100644 index cc238d1179699..0000000000000 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/CrossSellDataProvider.php +++ /dev/null @@ -1,26 +0,0 @@ -collection = $product->getCrossSellProductCollection(); - $this->collection->addAttributeToSelect($this->getFields()); - } - -} \ No newline at end of file diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/Products/LinkedProductsDataProvider.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/Products/LinkedProductsDataProvider.php new file mode 100644 index 0000000000000..d2daefd128129 --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/Products/LinkedProductsDataProvider.php @@ -0,0 +1,56 @@ +linkFactory = $linkFactory; + } + + /** + * Get Related Products by Product and Link Type + * + * @param Product $product + * @param array $fields + * @param int $linkType + * @return Product[] + */ + public function getRelatedProducts(Product $product, array $fields, int $linkType): array + { + /** @var Link $link */ + $link = $this->linkFactory->create([ 'data' => [ + 'link_type_id' => $linkType + ]]); + + $collection = $link->getProductCollection(); + $collection->setIsStrongMode(); + foreach ($fields as $field) { + $collection->addAttributeToSelect($field); + } + $collection->setProduct($product); + + return $collection->getItems(); + } +} diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/RelatedDataProvider.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/RelatedDataProvider.php index 3adc193c1c2bb..8f42cc8411a72 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/RelatedDataProvider.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/RelatedDataProvider.php @@ -1,18 +1,80 @@ collection = $product->getRelatedProductCollection(); - $this->collection->addAttributeToSelect($this->getFields()); + /** + * @var int + */ + private $linkType; + + /** + * @var string + */ + private $schemaNodeName; + + /** + * @param LinkedProductsDataProvider $dataProvider + * @param ProductFieldsSelector $productFieldsSelector + * @param int $linkType + * @param string $schemaNodeName + */ + public function __construct( + LinkedProductsDataProvider $dataProvider, + ProductFieldsSelector $productFieldsSelector, + int $linkType = Link::LINK_TYPE_RELATED, + string $schemaNodeName = 'related_products' + ) { + $this->dataProvider = $dataProvider; + $this->productFieldsSelector = $productFieldsSelector; + $this->linkType = $linkType; + $this->schemaNodeName = $schemaNodeName; } + /** + * Related Products Data + * + * @param ResolveInfo $info + * @param array $value + * @return array + */ + public function getProducts(ResolveInfo $info, array $value): array + { + $product = $value['model']; + $fields = $this->productFieldsSelector->getProductFieldsFromInfo($info, $this->schemaNodeName); + $products = $this->dataProvider->getRelatedProducts($product, $fields, $this->linkType); + + $data = []; + foreach ($products as $key => $product) { + $data[$key] = $product->getData(); + $data[$key]['model'] = $product; + } -} \ No newline at end of file + return $data; + } +} diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/UpSellDataProvider.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/UpSellDataProvider.php deleted file mode 100644 index 03bd7793fab32..0000000000000 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/UpSellDataProvider.php +++ /dev/null @@ -1,25 +0,0 @@ -collection = $product->getUpSellProductCollection(); - $this->collection->addAttributeToSelect($this->getFields()); - } -} \ No newline at end of file diff --git a/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml b/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml index 7e18ac34f0fcc..db27e356784ac 100644 --- a/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml @@ -74,4 +74,26 @@ + + + Magento\Catalog\Model\Product\Link::LINK_TYPE_CROSSSELL + crosssell_products + + + + + Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\CrossSellDataProvider + + + + + Magento\Catalog\Model\Product\Link::LINK_TYPE_UPSELL + upsell_products + + + + + Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\UpSellDataProvider + + diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 4c457333dec92..4b255afd3c67b 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -271,9 +271,9 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ websites: [Website] @doc(description: "An array of websites in which the product is available") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Websites") product_links: [ProductLinksInterface] @doc(description: "An array of ProductLinks objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\ProductLinks") media_gallery_entries: [MediaGalleryEntry] @doc(description: "An array of MediaGalleryEntry objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\MediaGalleryEntries") - related_products: RelatedProduct @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related") - upsell_products: UpsellProduct @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related") - crosssell_products: CrosssellProduct @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related") + related_products: [ProductInterface] @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related\\RelatedProducts") + upsell_products: [ProductInterface] @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related\\UpSellProducts") + crosssell_products: [ProductInterface] @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related\\CrossSellProducts") tier_prices: [ProductTierPrices] @doc(description: "An array of ProductTierPrices objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\TierPrices") price: ProductPrices @doc(description: "A ProductPrices object, indicating the price of an item") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Price") gift_message_available: String @doc(description: "Indicates whether a gift message is available") @@ -530,15 +530,6 @@ type MediaGalleryEntry @doc(description: "MediaGalleryEntry defines characteris content: ProductMediaGalleryEntriesContent @doc(description: "Contains a ProductMediaGalleryEntriesContent object") video_content: ProductMediaGalleryEntriesVideoContent @doc(description: "Contains a ProductMediaGalleryEntriesVideoContent object") } -type RelatedProduct @doc(description: "RelatedProduct"){ - items: [ProductInterface] @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related\\RelatedProducts") -} -type UpsellProduct @doc(description: "UpsellProduct"){ - items: [ProductInterface] @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related\\UpSellProducts") -} -type CrosssellProduct @doc(description: "CrosssellProduct"){ - items: [ProductInterface] @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related\\CrossSellProducts") -} type LayerFilter { name: String @doc(description: "Layered navigation filter name") diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductRelatedProductsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductRelatedProductsTest.php new file mode 100644 index 0000000000000..2cc3f0c8530a8 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductRelatedProductsTest.php @@ -0,0 +1,175 @@ +graphQlQuery($query); + + $this->assertArrayHasKey('products', $response); + $this->assertArrayHasKey('items', $response['products']); + $this->assertEquals(1, count($response['products']['items'])); + $this->assertArrayHasKey(0, $response['products']['items']); + $this->assertArrayHasKey('related_products', $response['products']['items'][0]); + $relatedProducts = $response['products']['items'][0]['related_products']; + $this->assertCount(2, $relatedProducts); + $this->assertRelatedProducts($relatedProducts); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_crosssell.php + */ + public function testQueryCrossSellProducts() + { + $productSku = 'simple_with_cross'; + + $query = <<graphQlQuery($query); + + $this->assertArrayHasKey('products', $response); + $this->assertArrayHasKey('items', $response['products']); + $this->assertEquals(1, count($response['products']['items'])); + $this->assertArrayHasKey(0, $response['products']['items']); + $this->assertArrayHasKey('crosssell_products', $response['products']['items'][0]); + $crossSellProducts = $response['products']['items'][0]['crosssell_products']; + $this->assertCount(1, $crossSellProducts); + $crossSellProduct = $crossSellProducts[0]; + $this->assertArrayHasKey('sku', $crossSellProduct); + $this->assertArrayHasKey('name', $crossSellProduct); + $this->assertArrayHasKey('url_key', $crossSellProduct); + $this->assertArrayHasKey('id', $crossSellProduct); + $this->assertArrayHasKey('created_at', $crossSellProduct); + $this->assertEquals($crossSellProduct['sku'], 'simple'); + $this->assertEquals($crossSellProduct['name'], 'Simple Cross Sell'); + $this->assertEquals($crossSellProduct['url_key'], 'simple-cross-sell'); + $this->assertNotEmpty($crossSellProduct['created_at']); + $this->assertNotEmpty($crossSellProduct['id']); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_upsell.php + */ + public function testQueryUpSellProducts() + { + $productSku = 'simple_with_upsell'; + + $query = <<graphQlQuery($query); + + $this->assertArrayHasKey('products', $response); + $this->assertArrayHasKey('items', $response['products']); + $this->assertEquals(1, count($response['products']['items'])); + $this->assertArrayHasKey(0, $response['products']['items']); + $this->assertArrayHasKey('upsell_products', $response['products']['items'][0]); + $upSellProducts = $response['products']['items'][0]['upsell_products']; + $this->assertCount(1, $upSellProducts); + $upSellProduct = $upSellProducts[0]; + $this->assertArrayHasKey('sku', $upSellProduct); + $this->assertArrayHasKey('name', $upSellProduct); + $this->assertArrayHasKey('url_key', $upSellProduct); + $this->assertArrayHasKey('id', $upSellProduct); + $this->assertArrayHasKey('created_at', $upSellProduct); + $this->assertEquals($upSellProduct['sku'], 'simple'); + $this->assertEquals($upSellProduct['name'], 'Simple Up Sell'); + $this->assertEquals($upSellProduct['url_key'], 'simple-up-sell'); + $this->assertNotEmpty($upSellProduct['created_at']); + $this->assertNotEmpty($upSellProduct['id']); + } + + /** + * @param array $relatedProducts + */ + private function assertRelatedProducts(array $relatedProducts): void + { + $expectedData = [ + 'simple' => [ + 'name' => 'Simple Related Product', + 'url_key' => 'simple-related-product', + + ], + 'simple_with_cross_two' => [ + 'name' => 'Simple Product With Related Product Two', + 'url_key' => 'simple-product-with-related-product-two', + ] + ]; + + foreach ($relatedProducts as $product) { + $this->assertArrayHasKey('sku', $product); + $this->assertArrayHasKey('name', $product); + $this->assertArrayHasKey('url_key', $product); + $this->assertArrayHasKey('id', $product); + $this->assertArrayHasKey('created_at', $product); + + $this->assertArrayHasKey($product['sku'], $expectedData); + $productExpectedData = $expectedData[$product['sku']]; + + $this->assertEquals($product['name'], $productExpectedData['name']); + $this->assertEquals($product['url_key'], $productExpectedData['url_key']); + $this->assertNotEmpty($product['created_at']); + $this->assertNotEmpty($product['id']); + } + } +} From 7a83977ff56f2c820c97752c927e96a46cc162ff Mon Sep 17 00:00:00 2001 From: John S Date: Sun, 3 Mar 2019 21:03:06 -0600 Subject: [PATCH 006/224] MC-4431: Convert DeleteCatalogPriceRuleEntityTest to MFTF - Adding new Catalog page selectors. - Adding new Cart Summary selectors. - Adding new Product page selectors. - Adding new Catalog Price Rule data. - Adding Test variation 1. --- .../StorefrontCategoryProductSection.xml | 2 + .../Test/Mftf/Data/CatalogRuleData.xml | 17 ++++ .../Test/DeleteCatalogPriceRuleEntityTest.xml | 82 +++++++++++++++++++ .../Section/CheckoutCartProductSection.xml | 3 + .../Section/CheckoutCartSummarySection.xml | 1 + 5 files changed, 105 insertions(+) create mode 100644 app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml index f35eb63ee0e0a..4c11f5afecc0e 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontCategoryProductSection.xml @@ -21,6 +21,8 @@ + + diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml b/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml index 5b75708d1ae0a..b235189181a49 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml @@ -94,4 +94,21 @@ by_percent 10 + + + Active Catalog Rule with conditions + Rule Description + 1 + + 0 + 1 + 2 + 3 + + + 1 + + by_percent + 10 + diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml new file mode 100644 index 0000000000000..758c1be9462ab --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml @@ -0,0 +1,82 @@ + + + + + + + + + <description value="Assert that Catalog Price Rule is not applied for simple product"/> + <testCaseId value="MC-14073"/> + <severity value="CRITICAL"/> + <group value="CatalogRule"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="Simple_US_Customer" stepKey="createCustomer1"/> + <createData entity="_defaultCategory" stepKey="createCategory1"/> + <createData entity="SimpleProduct" stepKey="createProduct1"> + <requiredEntity createDataKey="createCategory1"/> + </createData> + + <createData entity="ActiveCatalogPriceRuleWithConditions" stepKey="createCatalogRule1"/> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> + </before> + <after> + <actionGroup ref="logout" stepKey="logoutOfAdmin1"/> + + <deleteData createDataKey="createCustomer1" stepKey="deleteCustomer1"/> + <deleteData createDataKey="createProduct1" stepKey="deleteSimpleProduct1"/> + <deleteData createDataKey="createCategory1" stepKey="deleteCategoryFirst1"/> + </after> + + <!-- delete the simple product and catalog price rule --> + <amOnPage url="admin/catalog_rule/promo_catalog/" stepKey="goToPriceRulePage1"/> + <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule1"> + <argument name="name" value="$$createCatalogRule1.name$$"/> + <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> + </actionGroup> + <waitForPageLoad time="30" stepKey="waitForPageLoad1"/> + + <!-- assert that the Success message is present after the delete --> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="You deleted the rule." stepKey="seeDeletedRuleMessage1"/> + + <!-- assert that the Grid Empty message is present after deleting --> + <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="assertDataGridEmptyMessage1"/> + + <!-- reindex --> + <magentoCLI command="indexer:reindex" stepKey="reindex1"/> + + <!-- assert that the rule isn't present on the Category page --> + <amOnPage url="$$createCategory1.name$$.html" stepKey="goToStorefrontCategoryPage1"/> + <waitForPageLoad stepKey="waitForPageLoad3"/> + <dontSee selector="{{StorefrontCategoryProductSection.ProductCatalogRulePriceTitleByName($$createProduct1.name$$)}}" userInput="Regular Price" stepKey="dontSeeRegularPriceText1"/> + <dontSeeElement selector="{{StorefrontCategoryProductSection.ProductCatalogRuleSpecialPriceTitleByName($$createProduct1.name$$)}}" stepKey="dontSeeSpecialPrice1"/> + + <!-- assert that the rule isn't present on the Product page --> + <amOnPage url="$$createProduct1.name$$.html" stepKey="goToStorefrontProductPage1"/> + <waitForPageLoad stepKey="waitForPageLoad4"/> + <dontSee selector="{{StorefrontProductInfoMainSection.oldPriceTag}}" userInput="Regular Price" stepKey="dontSeeRegularPRiceText2"/> + <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="$$createProduct1.price$$" stepKey="seeTrueProductPrice1"/> + + <!-- assert that the rule isn't present in the Shopping Cart --> + <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProductToShoppingCart1"> + <argument name="productName" value="$$createProduct1.name$$"/> + </actionGroup> + <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="openMiniShoppingCart1"/> + <see selector="{{StorefrontMinicartSection.productPriceByName($$createProduct1.name$$)}}" userInput="$$createProduct1.price$$" stepKey="seeCorrectProductPrice1"/> + + <!-- assert that the rule --> + <click selector="{{StorefrontMiniCartSection.goToCheckout}}" stepKey="goToCheckout1"/> + <conditionalClick selector="{{CheckoutCartSummarySection.expandShoppingCartSummary}}" dependentSelector="{{CheckoutCartSummarySection.expandShoppingCartSummary}}" visible="true" stepKey="expandShoppingCartSummary1"/> + <see selector="{{CheckoutCartProductSection.ProductRegularPriceByName($$createProduct1.name$$)}}" userInput="$$createProduct1.price$$" stepKey="seeCorrectProductPriceOnCheckout1"/> + </test> +</tests> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml index dcfb12fd4e965..f472b0965d80f 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml @@ -15,6 +15,9 @@ <element name="ProductPriceByName" type="text" selector="//main//table[@id='shopping-cart-table']//tbody//tr[..//strong[contains(@class, 'product-item-name')]//a/text()='{{var1}}'][1]//td[contains(@class, 'price')]//span[@class='price']" parameterized="true"/> + <element name="ProductRegularPriceByName" type="text" + selector="//div[descendant::*[contains(text(), '{{var1}}')]]//*[contains(@class, 'subtotal')]" + parameterized="true"/> <element name="ProductImageByName" type="text" selector="//main//table[@id='shopping-cart-table']//tbody//tr//img[contains(@class, 'product-image-photo') and @alt='{{var1}}']" parameterized="true"/> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml index 8d14a9a561900..0f254206491fc 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartSummarySection.xml @@ -9,6 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="CheckoutCartSummarySection"> + <element name="expandShoppingCartSummary" type="button" selector="//*[contains(@class, 'items-in-cart')][not(contains(@class, 'active'))]"/> <element name="elementPosition" type="text" selector=".data.table.totals > tbody tr:nth-of-type({{value}}) > th" parameterized="true"/> <element name="subtotal" type="text" selector="//*[@id='cart-totals']//tr[@class='totals sub']//td//span[@class='price']"/> <element name="shippingMethodForm" type="text" selector="#co-shipping-method-form"/> From 0f2ba44ae24c634296e82a0d12838a82a5fbf5ac Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Mon, 4 Mar 2019 15:46:45 -0600 Subject: [PATCH 007/224] MC-4431: Convert UpdateCustomerBackendEntityTest to MFTF - Adding the 2nd variation of the Test for a Configurable Product. --- .../Test/DeleteCatalogPriceRuleEntityTest.xml | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml index 758c1be9462ab..635eb833d2e0a 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml @@ -79,4 +79,114 @@ <conditionalClick selector="{{CheckoutCartSummarySection.expandShoppingCartSummary}}" dependentSelector="{{CheckoutCartSummarySection.expandShoppingCartSummary}}" visible="true" stepKey="expandShoppingCartSummary1"/> <see selector="{{CheckoutCartProductSection.ProductRegularPriceByName($$createProduct1.name$$)}}" userInput="$$createProduct1.price$$" stepKey="seeCorrectProductPriceOnCheckout1"/> </test> + + <test name="DeleteCatalogPriceRuleEntityTest2"> + <annotations> + <stories value="Delete Catalog Price Rule"/> + <title value="Delete Catalog Price Rule for Configurable Product"/> + <description value="Assert that Catalog Price Rule is not applied for configurable product"/> + <testCaseId value="MC-14073"/> + <severity value="CRITICAL"/> + <group value="CatalogRule"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <createData entity="Simple_US_Customer" stepKey="createCustomer1"/> + <createData entity="CatalogRuleByFixed" stepKey="createCatalogRule1"/> + <createData entity="SimpleSubCategory" stepKey="createCategory1"/> + + <!-- Create the configurable product based on the data in the /data folder --> + <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct1"> + <requiredEntity createDataKey="createCategory1"/> + </createData> + + <!-- Make the configurable product have two options, that are children of the default attribute set --> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute1"/> + <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute1"/> + </createData> + <createData entity="productAttributeOption2" stepKey="createConfigProductAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute1"/> + </createData> + <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> + <requiredEntity createDataKey="createConfigProductAttribute1"/> + </createData> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption1"> + <requiredEntity createDataKey="createConfigProductAttribute1"/> + </getData> + <getData entity="ProductAttributeOptionGetter" index="2" stepKey="getConfigAttributeOption2"> + <requiredEntity createDataKey="createConfigProductAttribute1"/> + </getData> + + <!-- Create the 2 children that will be a part of the configurable product --> + <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct1"> + <requiredEntity createDataKey="createConfigProductAttribute1"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + </createData> + <createData entity="ApiSimpleTwo" stepKey="createConfigChildProduct2"> + <requiredEntity createDataKey="createConfigProductAttribute1"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + </createData> + + <!-- Assign the two products to the configurable product --> + <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption1"> + <requiredEntity createDataKey="createConfigProduct1"/> + <requiredEntity createDataKey="createConfigProductAttribute1"/> + <requiredEntity createDataKey="getConfigAttributeOption1"/> + <requiredEntity createDataKey="getConfigAttributeOption2"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild1"> + <requiredEntity createDataKey="createConfigProduct1"/> + <requiredEntity createDataKey="createConfigChildProduct1"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild2"> + <requiredEntity createDataKey="createConfigProduct1"/> + <requiredEntity createDataKey="createConfigChildProduct2"/> + </createData> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> + </before> + <after> + <actionGroup ref="logout" stepKey="logoutOfAdmin1"/> + + <deleteData createDataKey="createCustomer1" stepKey="deleteCustomer"/> + </after> + + <!-- delete the simple product and catalog price rule --> + <amOnPage url="admin/catalog_rule/promo_catalog/" stepKey="goToPriceRulePage1"/> + <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule1"> + <argument name="name" value="$$createCatalogRule1.name$$"/> + <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> + </actionGroup> + + <!-- assert that the Success message is present after the delete --> + <see selector="{{AdminMessagesSection.successMessage}}" userInput="You deleted the rule." stepKey="seeDeletedRuleMessage1"/> + + <!-- assert that the Grid Empty message is present --> + <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="assertDataGridEmptyMessage1"/> + + <!-- reindex --> + <magentoCLI command="indexer:reindex" stepKey="reindex1"/> + + <!-- assert that the rule isn't present on the Category page --> + <amOnPage url="$$createCategory1.name$$.html" stepKey="goToStorefrontCategoryPage1"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + <see selector="{{StorefrontCategoryProductSection.ProductPriceByName($$createConfigProduct1.name$$)}}" userInput="$$createConfigChildProduct1.price$$" stepKey="seeRegularPriceText1"/> + + <!-- assert that the rule isn't present on the Product page --> + <amOnPage url="{{StorefrontProductPage.url($$createConfigProduct1.custom_attributes[url_key]$$)}}" stepKey="goToStorefrontProductPage1"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + <dontSee selector="{{StorefrontProductInfoMainSection.oldPriceTag}}" userInput="Regular Price" stepKey="dontSeeRegularPriceText2"/> + <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="$$createConfigChildProduct1.price$$" stepKey="seeTrueProductPrice1"/> + + <!-- assert that the rule isn't present in the Shopping Cart --> + <selectOption selector="{{StorefrontProductInfoMainSection.productAttributeOptionsSelectButton}}" userInput="option1" stepKey="selectOption1"/> + <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addToCart1"/> + <waitForPageLoad time="30" stepKey="waitForPageLoad3"/> + <see selector="{{StorefrontMessagesSection.success}}" userInput="You added $$createConfigProduct1.name$ to your shopping cart." stepKey="seeAddToCartSuccessMessage"/> + <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="openMiniShoppingCart1"/> + <waitForPageLoad time="30" stepKey="waitForPageLoad4"/> + <see selector="{{StorefrontMinicartSection.productPriceByName($$createConfigProduct1.name$$)}}" userInput="$$createConfigProduct1.price$$" stepKey="seeCorrectProductPrice1"/> + </test> </tests> From cafea50ab568d7cb23301c39bed388dd2dc18dc4 Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Tue, 5 Mar 2019 08:52:06 -0600 Subject: [PATCH 008/224] MC-4431: Convert UpdateCustomerBackendEntityTest to MFTF - Skipping the MTF tests that were converted. --- .../Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml | 1 + .../Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml index 738e9422fd910..3862d01007699 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml @@ -17,6 +17,7 @@ <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> <data name="shipping/shipping_method" xsi:type="string">Fixed</data> <data name="payment/method" xsi:type="string">checkmo</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleSuccessDeleteMessage" /> <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleNotInGrid" /> <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleNotAppliedCatalogPage" /> diff --git a/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml b/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml index dd332ead13a9d..d7d0c9e8b35d4 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/CatalogRuleConfigurable/Test/TestCase/DeleteCatalogPriceRuleEntityTest.xml @@ -11,6 +11,7 @@ <data name="catalogPriceRule/dataset" xsi:type="string">active_catalog_price_rule_with_conditions</data> <data name="product" xsi:type="string">configurableProduct::two_options_by_one_dollar</data> <data name="productPrice/0/regular" xsi:type="string">1</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleSuccessDeleteMessage" /> <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleNotInGrid" /> <constraint name="Magento\CatalogRule\Test\Constraint\AssertCatalogPriceRuleNotAppliedCatalogPage" /> From ad4efb807a6cff1a00ce138ad0726590a70217bd Mon Sep 17 00:00:00 2001 From: Yogesh Suhagiya <yksuhagiya@gmail.com> Date: Wed, 6 Mar 2019 16:22:04 +0530 Subject: [PATCH 009/224] Fixed internal server error for query urlResolver --- .../UrlRewriteGraphQl/Model/Resolver/EntityUrl.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php index 1c25ffd1e9ff7..71b31d112668b 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php @@ -8,6 +8,7 @@ namespace Magento\UrlRewriteGraphQl\Model\Resolver; use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; @@ -73,6 +74,11 @@ public function resolve( $url = $customUrl ?: $url; $urlRewrite = $this->findCanonicalUrl($url); if ($urlRewrite) { + if (!$urlRewrite->getEntityId()) { + throw new GraphQlNoSuchEntityException( + __('No such entity found with matching URL key: %url', ['url' => $url]) + ); + } $result = [ 'id' => $urlRewrite->getEntityId(), 'canonical_url' => $urlRewrite->getTargetPath(), @@ -99,6 +105,9 @@ private function findCanonicalUrl(string $requestPath) : ?\Magento\UrlRewrite\Se if (!$urlRewrite) { $urlRewrite = $this->findUrlFromTargetPath($requestPath); } + if (!$urlRewrite->getEntityId() && !$urlRewrite->getIsAutogenerated()) { + $urlRewrite = $this->findUrlFromTargetPath($urlRewrite->getTargetPath()); + } return $urlRewrite; } From 5e1b6ee688ff9e91ca924e71a686503d3b137902 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Fri, 8 Mar 2019 13:38:33 -0600 Subject: [PATCH 010/224] MC-4431: Convert DeleteCatalogPriceRuleEntityTest to MFTF - Fix first wave of code review feedback --- .../Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml index 635eb833d2e0a..9f796cb91cf64 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml @@ -39,7 +39,8 @@ </after> <!-- delete the simple product and catalog price rule --> - <amOnPage url="admin/catalog_rule/promo_catalog/" stepKey="goToPriceRulePage1"/> + <amOnPage url="{{CatalogRulePage.url}}" stepKey="goToPriceRulePage1"/> + <waitForPageLoad stepKey="waitForPriceRulePage"/> <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule1"> <argument name="name" value="$$createCatalogRule1.name$$"/> <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> @@ -85,7 +86,7 @@ <stories value="Delete Catalog Price Rule"/> <title value="Delete Catalog Price Rule for Configurable Product"/> <description value="Assert that Catalog Price Rule is not applied for configurable product"/> - <testCaseId value="MC-14073"/> + <testCaseId value="MC-14074"/> <severity value="CRITICAL"/> <group value="CatalogRule"/> <group value="mtf_migrated"/> @@ -151,10 +152,16 @@ <actionGroup ref="logout" stepKey="logoutOfAdmin1"/> <deleteData createDataKey="createCustomer1" stepKey="deleteCustomer"/> + <deleteData createDataKey="createCategory1" stepKey="deleteCategory1"/> + <deleteData createDataKey="createConfigProduct1" stepKey="deleteConfigProduct1"/> + <deleteData createDataKey="createConfigChildProduct1" stepKey="deleteConfigChildProduct1"/> + <deleteData createDataKey="createConfigChildProduct2" stepKey="deleteConfigChildProduct2"/> + <deleteData createDataKey="createConfigProductAttribute1" stepKey="deleteConfigProductAttribute1"/> </after> <!-- delete the simple product and catalog price rule --> - <amOnPage url="admin/catalog_rule/promo_catalog/" stepKey="goToPriceRulePage1"/> + <amOnPage url="{{CatalogRulePage.url}}" stepKey="goToPriceRulePage1"/> + <waitForPageLoad stepKey="waitForPriceRulePage"/> <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule1"> <argument name="name" value="$$createCatalogRule1.name$$"/> <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> From 8b39eccc987fcbc8da26b7a5069fa4d63f05ae66 Mon Sep 17 00:00:00 2001 From: Yogesh Suhagiya <yksuhagiya@gmail.com> Date: Sat, 9 Mar 2019 14:20:21 +0530 Subject: [PATCH 011/224] Added testGetNonExistentUrlRewrite Test case to cover custom type URL rewrite rule --- .../Model/Resolver/EntityUrl.php | 2 +- .../GraphQl/UrlRewrite/UrlResolverTest.php | 39 +++++++++++++++++++ .../_files/product_with_category.php | 13 +++++++ .../_files/product_with_category_rollback.php | 6 +++ 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php index 1577aca50121a..6e6c915959a16 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php @@ -106,7 +106,7 @@ private function findCanonicalUrl(string $requestPath) : ?\Magento\UrlRewrite\Se if (!$urlRewrite) { $urlRewrite = $this->findUrlFromTargetPath($requestPath); } - if (!$urlRewrite->getEntityId() && !$urlRewrite->getIsAutogenerated()) { + if ($urlRewrite && !$urlRewrite->getEntityId() && !$urlRewrite->getIsAutogenerated()) { $urlRewrite = $this->findUrlFromTargetPath($urlRewrite->getTargetPath()); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php index 370121a1dad78..cce26e145e454 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php @@ -15,6 +15,7 @@ use Magento\Cms\Helper\Page as PageHelper; use Magento\Store\Model\ScopeInterface; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\UrlRewrite\Model\UrlRewrite; /** * Test the GraphQL endpoint's URLResolver query to verify canonical URL's are correctly returned. @@ -355,4 +356,42 @@ public function testResolveSlash() $this->assertEquals($targetPath, $response['urlResolver']['relative_url']); $this->assertEquals('CMS_PAGE', $response['urlResolver']['type']); } + + /** + * Test for custom type which point to the valid product/category/cms page. + * + * @magentoApiDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php + */ + public function testGetNonExistentUrlRewrite() + { + $urlPath = 'non-exist-product.html'; + /** @var UrlRewrite $urlRewrite */ + $urlRewrite = $this->objectManager->create(UrlRewrite::class); + $urlRewrite->load($urlPath, 'request_path'); + + /** @var UrlFinderInterface $urlFinder */ + $urlFinder = $this->objectManager->get(UrlFinderInterface::class); + $actualUrls = $urlFinder->findOneByData( + [ + 'request_path' => $urlPath, + 'store_id' => 1 + ] + ); + $targetPath = $actualUrls->getTargetPath(); + + $query = <<<QUERY +{ + urlResolver(url:"{$urlPath}") + { + id + relative_url + type + } +} +QUERY; + $response = $this->graphQlQuery($query); + $this->assertArrayHasKey('urlResolver', $response); + $this->assertEquals('PRODUCT', $response['urlResolver']['type']); + $this->assertEquals($targetPath, $response['urlResolver']['relative_url']); + } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogUrlRewrite/_files/product_with_category.php b/dev/tests/integration/testsuite/Magento/CatalogUrlRewrite/_files/product_with_category.php index 2f3d4ea4c3e7f..3c03318942167 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogUrlRewrite/_files/product_with_category.php +++ b/dev/tests/integration/testsuite/Magento/CatalogUrlRewrite/_files/product_with_category.php @@ -14,6 +14,7 @@ use Magento\Framework\Indexer\IndexerRegistry; use Magento\Store\Model\StoreManagerInterface; use Magento\TestFramework\Helper\Bootstrap; +use Magento\UrlRewrite\Model\UrlRewrite; /** * @var \Magento\Store\Model\Store $store @@ -80,3 +81,15 @@ /** @var CategoryLinkManagementInterface $linkManagement */ $linkManagement = $objectManager->get(CategoryLinkManagementInterface::class); $linkManagement->assignProductToCategories($product->getSku(), [Category::TREE_ROOT_ID, $category->getEntityId()]); + +/** @var UrlRewrite $urlRewrite */ +$urlRewrite = $objectManager->create(UrlRewrite::class); +$urlRewrite->setEntityType('custom') + ->setRequestPath('non-exist-product.html') + ->setTargetPath('catalog/product/view/id/' . $product->getId()) + ->setRedirectType(0) + ->setStoreId(1) + ->setDescription(null) + ->setIsAutogenerated(0); + +$urlRewrite->save(); diff --git a/dev/tests/integration/testsuite/Magento/CatalogUrlRewrite/_files/product_with_category_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogUrlRewrite/_files/product_with_category_rollback.php index 2598dd6693500..3a1e379213342 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogUrlRewrite/_files/product_with_category_rollback.php +++ b/dev/tests/integration/testsuite/Magento/CatalogUrlRewrite/_files/product_with_category_rollback.php @@ -9,6 +9,7 @@ use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\TestFramework\Helper\Bootstrap; +use Magento\UrlRewrite\Model\UrlRewrite; $objectManager = Bootstrap::getObjectManager(); /** @var \Magento\Framework\Registry $registry */ @@ -41,6 +42,11 @@ $categoryRepository->delete($category); } +/** @var UrlRewrite $urlRewrite */ +$urlRewrite = $objectManager->create(UrlRewrite::class); +$urlRewrite->load('non-exist-product.html', 'request_path'); +$urlRewrite->delete(); + $registry->unregister('isSecureArea'); $registry->register('isSecureArea', false); From 8ea824edd0376a2dc77e2e1cf89fb0d2a8271ce5 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <svizev.igor@gmail.com> Date: Thu, 14 Mar 2019 12:54:55 +0200 Subject: [PATCH 012/224] Custom option type select - Allow modify list of single selection option types --- .../Model/Product/Option/Type/Select.php | 20 +++++++++++++------ app/code/Magento/Catalog/etc/di.xml | 8 ++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php b/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php index d88dd58362896..ca506fd451fb3 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php @@ -30,23 +30,35 @@ class Select extends \Magento\Catalog\Model\Product\Option\Type\DefaultType */ protected $string; + /** + * @var array + */ + private $singleSelectionTypes; + /** * @param \Magento\Checkout\Model\Session $checkoutSession * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Framework\Stdlib\StringUtils $string * @param \Magento\Framework\Escaper $escaper * @param array $data + * @param array $singleSelectionTypes */ public function __construct( \Magento\Checkout\Model\Session $checkoutSession, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Framework\Stdlib\StringUtils $string, \Magento\Framework\Escaper $escaper, - array $data = [] + array $data = [], + array $singleSelectionTypes = [] ) { $this->string = $string; $this->_escaper = $escaper; parent::__construct($checkoutSession, $scopeConfig, $data); + + $this->singleSelectionTypes = $singleSelectionTypes ?: [ + \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_DROP_DOWN, + \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_RADIO, + ]; } /** @@ -310,10 +322,6 @@ public function getOptionSku($optionValue, $skuDelimiter) */ protected function _isSingleSelection() { - $single = [ - \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_DROP_DOWN, - \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_RADIO, - ]; - return in_array($this->getOption()->getType(), $single); + return in_array($this->getOption()->getType(), $this->singleSelectionTypes, true); } } diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index 7d2c3699ee2c2..1ece6b999111d 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -1164,4 +1164,12 @@ </argument> </arguments> </type> + <type name="Magento\Catalog\Model\Product\Option\Type\Select"> + <arguments> + <argument name="singleSelectionTypes" xsi:type="array"> + <item name="drop_down" xsi:type="const">Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_DROP_DOWN</item> + <item name="radio" xsi:type="const">Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_RADIO</item> + </argument> + </arguments> + </type> </config> From 17b7c0a4b0c3f0732e51595fa9b53820e3b73f32 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 20 Mar 2019 17:00:47 +0200 Subject: [PATCH 013/224] graphQl-309: added agreement coverage --- .../Model/Resolver/CheckoutAgreements.php | 48 +++++++++++++ .../DataProvider/CheckoutAgreements.php | 68 +++++++++++++++++++ .../CheckoutAgreementsGraphQl/README.md | 4 ++ .../CheckoutAgreementsGraphQl/composer.json | 26 +++++++ .../CheckoutAgreementsGraphQl/etc/module.xml | 14 ++++ .../etc/schema.graphqls | 15 ++++ .../registration.php | 10 +++ composer.json | 1 + composer.lock | 3 +- .../Api/CheckoutAgreementsListTest.php | 43 ++++++++++++ 10 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php create mode 100644 app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php create mode 100644 app/code/Magento/CheckoutAgreementsGraphQl/README.md create mode 100644 app/code/Magento/CheckoutAgreementsGraphQl/composer.json create mode 100644 app/code/Magento/CheckoutAgreementsGraphQl/etc/module.xml create mode 100644 app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls create mode 100644 app/code/Magento/CheckoutAgreementsGraphQl/registration.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php new file mode 100644 index 0000000000000..985c30182886a --- /dev/null +++ b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php @@ -0,0 +1,48 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CheckoutAgreementsGraphQl\Model\Resolver; + +use Magento\CheckoutAgreementsGraphQl\Model\Resolver\DataProvider\CheckoutAgreements as CheckoutAgreementsDataProvider; +use Magento\Framework\GraphQl\Config\Element\Field; +use Magento\Framework\GraphQl\Query\ResolverInterface; +use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; + +/** + * CMS page field resolver, used for GraphQL request processing + */ +class CheckoutAgreements implements ResolverInterface +{ + /** + * @var CheckoutAgreementsDataProvider + */ + private $checkoutAgreementsDataProvider; + + /** + * @param CheckoutAgreementsDataProvider $checkoutAgreementsDataProvider + */ + public function __construct( + CheckoutAgreementsDataProvider $checkoutAgreementsDataProvider + ) { + $this->checkoutAgreementsDataProvider = $checkoutAgreementsDataProvider; + } + + /** + * @inheritdoc + */ + public function resolve( + Field $field, + $context, + ResolveInfo $info, + array $value = null, + array $args = null + ) { + $checkoutAgreementsData = $this->checkoutAgreementsDataProvider->getData(); + + return $checkoutAgreementsData; + } +} diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php new file mode 100644 index 0000000000000..e8efde95ee380 --- /dev/null +++ b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CheckoutAgreementsGraphQl\Model\Resolver\DataProvider; + +use Magento\CheckoutAgreements\Api\CheckoutAgreementsListInterface; +use Magento\CheckoutAgreements\Api\Data\AgreementInterface; +use Magento\Cms\Api\Data\PageInterface; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\Exception\NoSuchEntityException; + +/** + * Checkout Agreements data provider + */ +class CheckoutAgreements +{ + /** + * @var SearchCriteriaBuilder + */ + private $searchCriteriaBuilder; + + /** + * @var CheckoutAgreementsListInterface + */ + private $checkoutAgreementsList; + + /** + * @param CheckoutAgreementsListInterface $checkoutAgreementsList + * @param SearchCriteriaBuilder $searchCriteriaBuilder + */ + public function __construct( + CheckoutAgreementsListInterface $checkoutAgreementsList, + SearchCriteriaBuilder $searchCriteriaBuilder + ) { + $this->checkoutAgreementsList = $checkoutAgreementsList; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; + } + + /** + * Get All Active Checkout Agreements Data + * + * @return array + */ + public function getData(): array + { + $this->searchCriteriaBuilder->addFilter(AgreementInterface::IS_ACTIVE, true); + $searchCriteria = $this->searchCriteriaBuilder->create(); + $checkoutAgreements = $this->checkoutAgreementsList->getList($searchCriteria); + + $checkoutAgreementData = []; + foreach ($checkoutAgreements as $checkoutAgreement) { + $checkoutAgreementData[] = [ + AgreementInterface::AGREEMENT_ID => $checkoutAgreement->getAgreementId(), + AgreementInterface::CONTENT => $checkoutAgreement->getContent(), + AgreementInterface::NAME => $checkoutAgreement->getName(), + AgreementInterface::CONTENT_HEIGHT => $checkoutAgreement->getContentHeight(), + AgreementInterface::CHECKBOX_TEXT => $checkoutAgreement->getCheckboxText(), + AgreementInterface::IS_HTML => $checkoutAgreement->getIsHtml(), + ]; + } + + return $checkoutAgreementData; + } +} diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/README.md b/app/code/Magento/CheckoutAgreementsGraphQl/README.md new file mode 100644 index 0000000000000..3ef735e3937f5 --- /dev/null +++ b/app/code/Magento/CheckoutAgreementsGraphQl/README.md @@ -0,0 +1,4 @@ +# CheckoutAgreementsGraphQl + +**CheckoutAgreementsGraphQl** provides type information for the GraphQl module +to generate Checkout Agreements fields for Checkout Agreements information endpoints. diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/composer.json b/app/code/Magento/CheckoutAgreementsGraphQl/composer.json new file mode 100644 index 0000000000000..b4196a3008e54 --- /dev/null +++ b/app/code/Magento/CheckoutAgreementsGraphQl/composer.json @@ -0,0 +1,26 @@ +{ + "name": "magento/module-checkout-agreements-graph-ql", + "description": "N/A", + "type": "magento2-module", + "require": { + "php": "~7.1.3||~7.2.0", + "magento/framework": "*", + "magento/module-checkout-agreements": "*" + }, + "suggest": { + "magento/module-graph-ql": "*", + "magento/module-store-graph-ql": "*" + }, + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "autoload": { + "files": [ + "registration.php" + ], + "psr-4": { + "Magento\\CheckoutAgreementsGraphQl\\": "" + } + } +} diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/etc/module.xml b/app/code/Magento/CheckoutAgreementsGraphQl/etc/module.xml new file mode 100644 index 0000000000000..55f09ccf7daee --- /dev/null +++ b/app/code/Magento/CheckoutAgreementsGraphQl/etc/module.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> + <module name="Magento_CheckoutAgreementsGraphQl"> + <sequence> + <module name="Magento_GraphQl"/> + </sequence> + </module> +</config> diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls b/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls new file mode 100644 index 0000000000000..24bf75e2c379b --- /dev/null +++ b/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls @@ -0,0 +1,15 @@ +# Copyright © Magento, Inc. All rights reserved. +# See COPYING.txt for license details. + +type Query { + checkoutAgreements: [CheckoutAgreement] @resolver(class: "Magento\\CheckoutAgreementsGraphQl\\Model\\Resolver\\CheckoutAgreements") @doc(description: "The Checkout Agreements query returns information about a Checkout Agreements") +} + +type CheckoutAgreement @doc(description: "Defines all Checkout Agreement information") { + agreement_id: Int @doc(description: "Checkout Agreement identifier") + name: String @doc(description: "Checkout Agreement name") + content: String @doc(description: "Checkout Agreement content") + content_height: String @doc(description: "Checkout Agreement content height") + checkbox_text: String @doc(description: "Checkout Agreement checkbox tex") + is_html: Boolean @doc(description: "Is Checkout Agreement content in HTML format") +} diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/registration.php b/app/code/Magento/CheckoutAgreementsGraphQl/registration.php new file mode 100644 index 0000000000000..b0b4839f33d1f --- /dev/null +++ b/app/code/Magento/CheckoutAgreementsGraphQl/registration.php @@ -0,0 +1,10 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +use Magento\Framework\Component\ComponentRegistrar; + +ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_CheckoutAgreementsGraphQl', __DIR__); diff --git a/composer.json b/composer.json index 50b22238e0d01..d9de29e931967 100644 --- a/composer.json +++ b/composer.json @@ -126,6 +126,7 @@ "magento/module-catalog-widget": "*", "magento/module-checkout": "*", "magento/module-checkout-agreements": "*", + "magento/module-checkout-agreements-graph-ql": "*", "magento/module-cms": "*", "magento/module-cms-url-rewrite": "*", "magento/module-config": "*", diff --git a/composer.lock b/composer.lock index a7131f4a16eec..8747ecc6d8d28 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "60007664938710edf52eadddd7551867", + "content-hash": "7d2484d86d4d31622f2427d46724ca6f", "packages": [ { "name": "braintree/braintree_php", @@ -7842,7 +7842,6 @@ "mock", "xunit" ], - "abandoned": true, "time": "2018-08-09T05:50:03+00:00" }, { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php new file mode 100644 index 0000000000000..8e743674c38d1 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\GraphQL\CheckoutAgreements\Api; + +use Magento\TestFramework\TestCase\GraphQlAbstract; + +class CheckoutAgreementsListTest extends GraphQlAbstract +{ + /** + * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_active_with_html_content.php + * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_inactive_with_text_content.php + */ + public function testGetActiveAgreement() + { + $query = + <<<QUERY +{ + checkoutAgreements { + agreement_id + name + content + content_height + checkbox_text + is_html + } +} +QUERY; + + $response = $this->graphQlQuery($query); + $this->assertArrayHasKey('checkoutAgreements', $response); + $agreements = $response['checkoutAgreements']; + $this->assertEquals(1, count($agreements)); + $this->assertEquals('Checkout Agreement (active)', $agreements[0]['name']); + $this->assertEquals('Checkout agreement content: <b>HTML</b>', $agreements[0]['content']); + $this->assertEquals('200px', $agreements[0]['content_height']); + $this->assertEquals('Checkout agreement checkbox text.', $agreements[0]['checkbox_text']); + $this->assertEquals(true, $agreements[0]['is_html']); + } +} From d3190fe74f44646f5e01ca64a5b1df026e491026 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Thu, 21 Mar 2019 09:30:38 +0200 Subject: [PATCH 014/224] graphQl-309: static fixes --- .../Model/Resolver/DataProvider/CheckoutAgreements.php | 2 -- .../CheckoutAgreements/Api/CheckoutAgreementsListTest.php | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php index e8efde95ee380..2a8ac45ed65cc 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php +++ b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php @@ -9,9 +9,7 @@ use Magento\CheckoutAgreements\Api\CheckoutAgreementsListInterface; use Magento\CheckoutAgreements\Api\Data\AgreementInterface; -use Magento\Cms\Api\Data\PageInterface; use Magento\Framework\Api\SearchCriteriaBuilder; -use Magento\Framework\Exception\NoSuchEntityException; /** * Checkout Agreements data provider diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php index 8e743674c38d1..4b419d939c183 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php @@ -3,8 +3,9 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); -namespace Magento\GraphQL\CheckoutAgreements\Api; +namespace Magento\GraphQl\CheckoutAgreements\Api; use Magento\TestFramework\TestCase\GraphQlAbstract; From 407d73c3f7b3003cad3bdbcad6a62008d0afeaab Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sat, 23 Mar 2019 17:01:53 +0100 Subject: [PATCH 015/224] Convert LockCustomerOnLoginPageTest to MFTF --- ...omerLoginInvalidCredentialsActionGroup.xml | 23 ++++++++ .../StorefrontLockCustomerOnLoginPageTest.xml | 57 +++++++++++++++++++ ...frontLoginWithIncorrectCredentialsTest.xml | 10 ++-- .../TestCase/LockCustomerOnLoginPageTest.xml | 1 + 4 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLoginInvalidCredentialsActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/Test/StorefrontLockCustomerOnLoginPageTest.xml diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLoginInvalidCredentialsActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLoginInvalidCredentialsActionGroup.xml new file mode 100644 index 0000000000000..6a2d4d2aec2d5 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLoginInvalidCredentialsActionGroup.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontCustomerLoginInvalidCredentialsActionGroup"> + <arguments> + <argument name="customerEmail" type="string" /> + <argument name="customerPassword" type="string" /> + </arguments> + <amOnPage stepKey="amOnSignInPage" url="{{StorefrontCustomerSignInPage.url}}"/> + <fillField stepKey="fillEmail" userInput="{{customerEmail}}" selector="{{StorefrontCustomerSignInFormSection.emailField}}"/> + <fillField stepKey="fillPassword" userInput="{{customerPassword}}INVALID" selector="{{StorefrontCustomerSignInFormSection.passwordField}}"/> + <click stepKey="clickSignInAccountButton" selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}"/> + <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" stepKey="waitForFailMessage" /> + <see stepKey="seeErrorMessage" selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later."/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLockCustomerOnLoginPageTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLockCustomerOnLoginPageTest.xml new file mode 100644 index 0000000000000..6e8dd5f47d4e4 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLockCustomerOnLoginPageTest.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontLockCustomerOnLoginPageTest"> + <annotations> + <features value="Customer"/> + <title value="Lock customer on Storefront with after many attempts to log in with incorrect credentials"/> + <description value="Lock customer on Storefront with after many attempts to log in with incorrect credentials"/> + <group value="Customer"/> + <group value="security"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <magentoCLI command="config:set customer/captcha/enable 0" stepKey="disableCaptcha"/> + <magentoCLI command="config:set customer/password/lockout_failures 5" stepKey="setInvalidAttemptsCount"/> + <createData stepKey="customer" entity="Simple_US_Customer"/> + </before> + <after> + <deleteData stepKey="deleteCustomer" createDataKey="customer" /> + </after> + <!-- Perform 5 attempts to log in with invalid credentials --> + <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt1"> + <argument name="customerEmail" value="$$customer.email$$"/> + <argument name="customerPassword" value="$$customer.password$$"/> + </actionGroup> + <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt2"> + <argument name="customerEmail" value="$$customer.email$$"/> + <argument name="customerPassword" value="$$customer.password$$"/> + </actionGroup> + <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt3"> + <argument name="customerEmail" value="$$customer.email$$"/> + <argument name="customerPassword" value="$$customer.password$$"/> + </actionGroup> + <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt4"> + <argument name="customerEmail" value="$$customer.email$$"/> + <argument name="customerPassword" value="$$customer.password$$"/> + </actionGroup> + <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt5"> + <argument name="customerEmail" value="$$customer.email$$"/> + <argument name="customerPassword" value="$$customer.password$$"/> + </actionGroup> + <!-- Make sure that the customer is locked --> + <amOnPage stepKey="amOnSignInPage" url="{{StorefrontCustomerSignInPage.url}}"/> + <fillField stepKey="fillEmail" userInput="$$customer.email$$" selector="{{StorefrontCustomerSignInFormSection.emailField}}"/> + <fillField stepKey="fillPassword" userInput="$$customer.password$$" selector="{{StorefrontCustomerSignInFormSection.passwordField}}"/> + <click stepKey="clickSignInAccountButton" selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}"/> + <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" stepKey="waitForFailMessage" /> + <see stepKey="seeErrorMessage" selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later."/> + </test> +</tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLoginWithIncorrectCredentialsTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLoginWithIncorrectCredentialsTest.xml index 104b5d56314ba..f46dadb947f9b 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLoginWithIncorrectCredentialsTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLoginWithIncorrectCredentialsTest.xml @@ -25,11 +25,9 @@ <after> <deleteData stepKey="deleteCustomer" createDataKey="customer" /> </after> - - <amOnPage stepKey="amOnSignInPage" url="{{StorefrontCustomerSignInPage.url}}"/> - <fillField stepKey="fillEmail" userInput="$$customer.email$$" selector="{{StorefrontCustomerSignInFormSection.emailField}}"/> - <fillField stepKey="fillPassword" userInput="$$customer.password$$INVALID" selector="{{StorefrontCustomerSignInFormSection.passwordField}}"/> - <click stepKey="clickSignInAccountButton" selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}"/> - <see stepKey="seeErrorMessage" selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later."/> + <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt1"> + <argument name="customerEmail" value="$$customer.email$$"/> + <argument name="customerPassword" value="$$customer.password$$"/> + </actionGroup> </test> </tests> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockCustomerOnLoginPageTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockCustomerOnLoginPageTest.xml index 7c043a36708b6..4a9c5d63b6808 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockCustomerOnLoginPageTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockCustomerOnLoginPageTest.xml @@ -13,6 +13,7 @@ <data name="initialCustomer/dataset" xsi:type="string">default</data> <data name="incorrectPassword" xsi:type="string">incorrect password</data> <data name="attempts" xsi:type="string">6</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertCustomerIsLocked" /> </variation> </testCase> From 1c41128b3f7cbbf2fbddb4e94c61672e39ef3bbc Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sat, 23 Mar 2019 17:08:08 +0100 Subject: [PATCH 016/224] Minor refactoring --- .../Mftf/Test/StorefrontLoginWithIncorrectCredentialsTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLoginWithIncorrectCredentialsTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLoginWithIncorrectCredentialsTest.xml index f46dadb947f9b..228c23eac63e8 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLoginWithIncorrectCredentialsTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLoginWithIncorrectCredentialsTest.xml @@ -25,7 +25,7 @@ <after> <deleteData stepKey="deleteCustomer" createDataKey="customer" /> </after> - <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt1"> + <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt"> <argument name="customerEmail" value="$$customer.email$$"/> <argument name="customerPassword" value="$$customer.password$$"/> </actionGroup> From 4164dfcba3349a389312d9502ef8219bb2280e2f Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sat, 23 Mar 2019 19:32:40 +0100 Subject: [PATCH 017/224] Convert CreateExistingCustomerFrontendEntity to MFTF --- ...SignUpNewUserFromStorefrontActionGroup.xml | 9 +++++- .../Customer/Test/Mftf/Data/CustomerData.xml | 3 ++ .../StorefrontCreateExistingCustomerTest.xml | 32 +++++++++++++++++++ .../CreateExistingCustomerFrontendEntity.xml | 1 + 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateExistingCustomerTest.xml diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml index ef956293d367b..ff5288531d9a4 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml @@ -57,7 +57,7 @@ <arguments> <argument name="Address"/> </arguments> - + <amOnPage url="customer/address/new/" stepKey="goToAddressPage"/> <waitForPageLoad stepKey="waitForAddressPage"/> <fillField stepKey="fillFirstName" selector="{{StorefrontCustomerAddressSection.firstName}}" userInput="{{Address.firstname}}"/> @@ -154,4 +154,11 @@ <waitForPageLoad stepKey="waitForRegistered" after="clickCreateAccountButton"/> <remove keyForRemoval="seeThankYouMessage"/> </actionGroup> + + <actionGroup name="SignUpNewCustomerNoAssertions" extends="SignUpNewUserFromStorefrontActionGroup"> + <remove keyForRemoval="seeThankYouMessage"/> + <remove keyForRemoval="seeFirstName"/> + <remove keyForRemoval="seeLastName"/> + <remove keyForRemoval="seeEmail"/> + </actionGroup> </actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml index 06c23a2864984..54a5c03020ef7 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml @@ -33,6 +33,9 @@ <data key="disable_auto_group_change">0</data> <!--requiredEntity type="extension_attribute">ExtensionAttributeSimple</requiredEntity--> </entity> + <entity name="CustomerEntityOneNotUniqueEmail" extends="CustomerEntityOne" type="customer"> + <data key="email">test@email.com</data> + </entity> <entity name="Simple_US_Customer" type="customer"> <data key="group_id">1</data> <data key="default_billing">true</data> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateExistingCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateExistingCustomerTest.xml new file mode 100644 index 0000000000000..68f1e056138a5 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateExistingCustomerTest.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="StorefrontCreateExistingCustomerTest"> + <annotations> + <features value="Customer"/> + <title value="Attempt to register customer on storefront with existing email"/> + <description value="Attempt to register customer on storefront with existing email"/> + <group value="customers"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <createData stepKey="customer" entity="CustomerEntityOneNotUniqueEmail"/> + </before> + <after> + <deleteData stepKey="deleteCustomer" createDataKey="customer" /> + </after> + + <actionGroup ref="SignUpNewCustomerNoAssertions" stepKey="SignUpNewUser"> + <argument name="Customer" value="CustomerEntityOneNotUniqueEmail"/> + </actionGroup> + <waitForElementVisible selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="waitForErrorMessage" /> + <see stepKey="seeErrorMessage" userInput="There is already an account with this email address." selector="{{StorefrontCustomerMessagesSection.errorMessage}}"/> + </test> +</tests> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateExistingCustomerFrontendEntity.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateExistingCustomerFrontendEntity.xml index 92f8d7c32eaeb..3865b6acd5b5a 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateExistingCustomerFrontendEntity.xml +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateExistingCustomerFrontendEntity.xml @@ -14,6 +14,7 @@ <data name="customer/data/password" xsi:type="string">123123q#</data> <data name="customer/data/password_confirmation" xsi:type="string">123123q#</data> <data name="customer/data/website_id/dataset" xsi:type="string">default</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Customer\Test\Constraint\AssertCustomerFailRegisterMessage" /> </variation> </testCase> From d4dbbc4a0af97648c17f5075181baf09d8853148 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Mon, 25 Mar 2019 15:55:59 +0100 Subject: [PATCH 018/224] Convert LoginAfterJSMinificationTest to MFTF --- .../AdminLoginAfterJSMinificationTest.xml | 27 +++++++++++++++++++ .../TestCase/LoginAfterJSMinificationTest.xml | 1 + 2 files changed, 28 insertions(+) create mode 100644 app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml new file mode 100644 index 0000000000000..8d2a1fa374be0 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminLoginAfterJSMinificationTest"> + <annotations> + <features value="Backend"/> + <title value="Admin panel should be accessible with JS minification enabled"/> + <description value="Admin panel should be accessible with JS minification enabled"/> + <group value="backend"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <magentoCLI command="config:set dev/js/minify_files 1" stepKey="enableJsMinification"/> + <magentoCLI command="cache:clean config" stepKey="cleanCache"/> + </before> + + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <see userInput="Dashboard" selector="{{AdminHeaderSection.pageTitle}}" stepKey="seeDashboardTitle"/> + </test> +</tests> diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/LoginAfterJSMinificationTest.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/LoginAfterJSMinificationTest.xml index 4519655395ff9..1177b02241101 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/LoginAfterJSMinificationTest.xml +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/LoginAfterJSMinificationTest.xml @@ -12,6 +12,7 @@ <data name="configData" xsi:type="string">minify_js_files</data> <data name="menuItem" xsi:type="string">Dashboard</data> <data name="pageTitle" xsi:type="string">Dashboard</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Backend\Test\Constraint\AssertBackendPageIsAvailable" /> </variation> </testCase> From 48e9760fb83d9c8136753814c9d913bf77cf940f Mon Sep 17 00:00:00 2001 From: RomanKis <roman.kis.y@gmail.com> Date: Thu, 28 Mar 2019 10:21:37 +0200 Subject: [PATCH 019/224] #21473 Form element validation is not triggered when validation rules change --- app/code/Magento/Ui/view/base/web/js/form/element/abstract.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js b/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js index ca3d383accca1..9fac2c5adfbb3 100755 --- a/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js @@ -296,7 +296,7 @@ define([ this.validation[rule] = options; } - changed = utils.compare(rules, this.validation).equal; + changed = !(utils.compare(rules, this.validation).equal); if (changed) { this.required(!!rules['required-entry']); From 9ca1a7b360c5ab814fcf63da05dc1fc3d15ff07e Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Thu, 28 Mar 2019 23:52:44 +0200 Subject: [PATCH 020/224] Convert LockAdminUserWhenCreatingNewRoleTest to MFTF --- .../Test/Mftf/Page/AdminNewRolePage.xml | 14 +++++ .../Mftf/Section/AdminLoginFormSection.xml | 1 + .../Test/Mftf/Section/AdminNewRoleSection.xml | 17 ++++++ ...eInvalidCurrentUserPasswordActionGroup.xml | 16 +++++ .../Security/Test/Mftf/Data/AdminRoleData.xml | 14 +++++ .../LockAdminUserWhenCreatingNewRoleTest.xml | 60 +++++++++++++++++++ .../LockAdminUserWhenCreatingNewRoleTest.xml | 1 + 7 files changed, 123 insertions(+) create mode 100644 app/code/Magento/Backend/Test/Mftf/Page/AdminNewRolePage.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminNewRoleSection.xml create mode 100644 app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewRoleInvalidCurrentUserPasswordActionGroup.xml create mode 100644 app/code/Magento/Security/Test/Mftf/Data/AdminRoleData.xml create mode 100644 app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewRoleTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Page/AdminNewRolePage.xml b/app/code/Magento/Backend/Test/Mftf/Page/AdminNewRolePage.xml new file mode 100644 index 0000000000000..a89eb272b11a1 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Page/AdminNewRolePage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="AdminNewRolePage" url="admin/user_role/editrole/" area="admin" module="Backend"> + <section name="AdminNewRoleSection"/> + </page> +</pages> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml index 3b10fac7bb9dc..58efb66747b15 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminLoginFormSection.xml @@ -12,5 +12,6 @@ <element name="username" type="input" selector="#username"/> <element name="password" type="input" selector="#login"/> <element name="signIn" type="button" selector=".actions .action-primary" timeout="30"/> + <element name="error" type="text" selector=".message.message-error.error"/> </section> </sections> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminNewRoleSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminNewRoleSection.xml new file mode 100644 index 0000000000000..8d76cb78086eb --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminNewRoleSection.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminNewRoleSection"> + <element name="roleName" type="input" selector="#role_name"/> + <element name="currentPassword" type="input" selector="#current_password"/> + <element name="pageActionButton" type="button" selector="//div[contains(@class, 'page-actions-buttons')]//button[contains(., '{{button}}')]" + parameterized="true"/> + </section> +</sections> diff --git a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewRoleInvalidCurrentUserPasswordActionGroup.xml b/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewRoleInvalidCurrentUserPasswordActionGroup.xml new file mode 100644 index 0000000000000..a8ad1cabdad0c --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewRoleInvalidCurrentUserPasswordActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminNewRoleInvalidCurrentUserPasswordActionGroup"> + <fillField selector="{{AdminNewRoleSection.roleName}}" userInput="{{AdminRoleData.roleName}}" stepKey="fillRoleName"/> + <fillField selector="{{AdminNewRoleSection.currentPassword}}" userInput="PasswordINVALID" stepKey="fillCurrentUserPassword"/> + <click selector="{{AdminNewRoleSection.pageActionButton('Save Role')}}" stepKey="saveNewRole"/> + <waitForPageLoad stepKey="waitForSaveResultLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Security/Test/Mftf/Data/AdminRoleData.xml b/app/code/Magento/Security/Test/Mftf/Data/AdminRoleData.xml new file mode 100644 index 0000000000000..88327fa5e94f7 --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/Data/AdminRoleData.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="AdminRoleData" type="admin"> + <data key="roleName" unique="prefix">role</data> + </entity> +</entities> diff --git a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewRoleTest.xml b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewRoleTest.xml new file mode 100644 index 0000000000000..db28e8365871f --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewRoleTest.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="LockAdminUserWhenCreatingNewRoleTest"> + <annotations> + <features value="Security"/> + <stories value="Runs Lock admin user when creating new admin role test."/> + <title value="Lock admin user when creating new admin role"/> + <description value="Runs Lock admin user when creating new admin role test."/> + <severity value="MAJOR"/> + <group value="security"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Log in to Admin Panel --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!-- Unlock Admin user --> + <magentoCLI command="admin:user:unlock {{_ENV.MAGENTO_ADMIN_USERNAME}}" stepKey="unlockAdminUser"/> + </after> + + <!-- Open Admin New Role Page --> + <amOnPage url="{{AdminNewRolePage.url}}" stepKey="amOnNewAdminRolePage"/> + <waitForPageLoad stepKey="waitForNewAdminRolePageLoad"/> + + <!-- Perform add new role 6 specified number of times. --> + <actionGroup ref="AdminNewRoleInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveRoleFirstAttempt"> + </actionGroup> + <see selector="{{AdminMessagesSection.error}}" userInput="The password entered for the current user is invalid. Verify the password and try again." + stepKey="seeInvalidPasswordError"/> + <actionGroup ref="AdminNewRoleInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveRoleSecondAttempt"> + </actionGroup> + <actionGroup ref="AdminNewRoleInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveRoleThirdAttempt"> + </actionGroup> + <actionGroup ref="AdminNewRoleInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveRoleFourthAttempt"> + </actionGroup> + <actionGroup ref="AdminNewRoleInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveRoleFifthAttempt"> + </actionGroup> + <actionGroup ref="AdminNewRoleInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveRoleSixthAttempt"> + </actionGroup> + + <!-- Check Error that account has been locked --> + <waitForPageLoad stepKey="waitForSaveResultLoad"/> + <see selector="{{AdminLoginFormSection.error}}" userInput="Your account is temporarily disabled. Please try again later." stepKey="seeLockUserError"/> + + <!-- Try to login as admin and check error --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> + <waitForPageLoad stepKey="waitForError"/> + <see selector="{{AdminLoginFormSection.error}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later" + stepKey="seeLoginAdminError"/> + </test> +</tests> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.xml index 73a2a71b7c342..767f149946034 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.xml @@ -15,6 +15,7 @@ <data name="role/data/current_password" xsi:type="string">incorrect password</data> <data name="role/data/resource_access" xsi:type="string">All</data> <data name="attempts" xsi:type="string">4</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertUserIsLocked" /> </variation> </testCase> From d3e37b826ec887353e328e699780c32bdf9ef2e1 Mon Sep 17 00:00:00 2001 From: RomanKis <roman.kis.y@gmail.com> Date: Mon, 1 Apr 2019 12:37:59 +0300 Subject: [PATCH 021/224] #21473 Form element validation is not triggered when validation rules change --- app/code/Magento/Ui/view/base/web/js/form/element/abstract.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js b/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js index 9fac2c5adfbb3..c7fab7da4567e 100755 --- a/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js @@ -296,7 +296,7 @@ define([ this.validation[rule] = options; } - changed = !(utils.compare(rules, this.validation).equal); + changed = !utils.compare(rules, this.validation).equal; if (changed) { this.required(!!rules['required-entry']); From 3ac6fbde539b88c085bb94d45cac8341ff61afcc Mon Sep 17 00:00:00 2001 From: --global <v.vygovskyi@atwix.com> Date: Wed, 3 Apr 2019 17:35:36 +0300 Subject: [PATCH 022/224] #623 Convert CmsPageMassActionTest to MFTF --- .../AssertCMSPageInGridActionGroup.xml | 16 ++++++ .../Section/CmsPagesPageActionsSection.xml | 3 ++ .../Mftf/Test/AdminCmsPageMassActionTest.xml | 53 +++++++++++++++++++ .../Test/TestCase/CmsPageMassActionTest.xml | 1 + 4 files changed, 73 insertions(+) create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageInGridActionGroup.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageInGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageInGridActionGroup.xml new file mode 100644 index 0000000000000..6b27234c9ad78 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageInGridActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertCMSPageInGrid" extends="navigateToCreatedCMSPage"> + <remove keyForRemoval="navigateToCreatedCMSPage"/> + <remove keyForRemoval="waitForPageLoad3"/> + <remove keyForRemoval="clickExpandContentTabForPage"/> + <remove keyForRemoval="waitForLoadingMaskOfStagingSection"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml b/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml index 11d8bb23313fb..4d0ae671ca05e 100644 --- a/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml +++ b/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml @@ -27,5 +27,8 @@ <element name="savePageSuccessMessage" type="text" selector=".message-success"/> <element name="delete" type="button" selector="//div[text()='{{var1}}']/parent::td//following-sibling::td[@class='data-grid-actions-cell']//a[text()='Delete']" parameterized="true"/> <element name="deleteConfirm" type="button" selector=".action-primary.action-accept" timeout="60"/> + <element name="pageRowCheckboxByIdentifier" type="block" selector="//td[count(../../..//th[./*[.='URL Key']]/preceding-sibling::th) + 1][./*[.='{{identifier}}']]/../td//input[@data-action='select-row']" parameterized="true" /> + <element name="massActionsButton" type="button" selector="div.admin__data-grid-header-row.row div.action-select-wrap button.action-select"/> + <element name="massActionsOption" type="button" selector="//div[contains(@class,'admin__data-grid-header-row') and contains(@class, 'row')]//div[contains(@class, 'action-select-wrap')]//ul/li/span[text() = '{{label}}']" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml new file mode 100644 index 0000000000000..3422bd562bde2 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="CmsPageMassActionTest"> + <annotations> + <features value="Cms"/> + <title value="Create two CMS Pages and perform mass disable action"/> + <description value="Admin should be able to perform mass actions to CMS pages"/> + <group value="backend"/> + <group value="cMSContent"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <createData entity="_defaultCmsPage" stepKey="firstCMSPage" /> + <createData entity="_duplicatedCMSPage" stepKey="secondCMSPage" /> + </before> + <after> + <deleteData createDataKey="firstCMSPage" stepKey="deleteFirstCMSPage" /> + <deleteData createDataKey="secondCMSPage" stepKey="deleteSecondCMSPage" /> + <actionGroup ref="logout" stepKey="logout"/> + </after> + <!--Go to Grid page--> + <amOnPage url="{{CmsPagesPage.url}}" stepKey="navigateToCMSPagesGrid"/> + <!--Select pages in Grid--> + <checkOption selector="{{CmsPagesPageActionsSection.pageRowCheckboxByIdentifier($$firstCMSPage.identifier$$)}}" stepKey="selectFirstPage"/> + <checkOption selector="{{CmsPagesPageActionsSection.pageRowCheckboxByIdentifier($$secondCMSPage.identifier$$)}}" stepKey="selectSecondPage"/> + <!-- Disable Pages--> + <click selector="{{CmsPagesPageActionsSection.massActionsButton}}" stepKey="clickMassActionDropdown"/> + <click selector="{{CmsPagesPageActionsSection.massActionsOption('Disable')}}" stepKey="clickDisableAction"/> + <waitForPageLoad stepKey="waitForPageToReload"/> + <!--Verify pages in Grid--> + <actionGroup ref="AssertCMSPageInGrid" stepKey="VerifyFirstPageinGrid"> + <argument name="CMSPage" value="$$firstCMSPage$$"/> + </actionGroup> + <actionGroup ref="AssertCMSPageInGrid" stepKey="VerifySecondPageinGrid"> + <argument name="CMSPage" value="$$secondCMSPage$$"/> + </actionGroup> + <!--Verify Pages are disabled on Frontend--> + <amOnPage url="{{StorefrontHomePage.url}}/{{$$firstCMSPage.identifier$$}}" stepKey="amOnFirstPageOnFrontend"/> + <waitForPageLoad stepKey="waitForFirstPageLoadOnFrontend"/> + <see userInput="Whoops, our bad..." stepKey="seePageErrorForFirstPage"/> + <amOnPage url="{{StorefrontHomePage.url}}/{{$$secondCMSPage.identifier$$}}" stepKey="amOnSecondPageOnFrontend"/> + <waitForPageLoad stepKey="waitForSecondPageLoadOnFrontend"/> + <see userInput="Whoops, our bad..." stepKey="seePageErrorForSecondPage"/> + </test> +</tests> \ No newline at end of file diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/CmsPageMassActionTest.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/CmsPageMassActionTest.xml index d032ef47823e8..68cdf5ba7b4c2 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/CmsPageMassActionTest.xml +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/CmsPageMassActionTest.xml @@ -12,6 +12,7 @@ <data name="cmsPages/1" xsi:type="string">3_column_template</data> <data name="action" xsi:type="string">Disable</data> <data name="expectedStatus" xsi:type="string">Disabled</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Cms\Test\Constraint\AssertCmsPagesInGrid" /> <constraint name="Magento\Cms\Test\Constraint\AssertCmsPagesDisabledOnFrontend" /> </variation> From 43ba611c12bbfa99ba691c96ed33594c9220cca2 Mon Sep 17 00:00:00 2001 From: Yogesh Suhagiya <yksuhagiya@gmail.com> Date: Thu, 4 Apr 2019 12:15:20 +0530 Subject: [PATCH 023/224] Covered testNonExistentEntityUrlRewrite case --- .../GraphQl/UrlRewrite/UrlResolverTest.php | 26 +++++++++++++++++++ .../url_rewrite_not_existing_entity.php | 25 ++++++++++++++++++ ...l_rewrite_not_existing_entity_rollback.php | 15 +++++++++++ 3 files changed, 66 insertions(+) create mode 100644 dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrite_not_existing_entity.php create mode 100644 dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrite_not_existing_entity_rollback.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php index cce26e145e454..8eaf33483531d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php @@ -394,4 +394,30 @@ public function testGetNonExistentUrlRewrite() $this->assertEquals('PRODUCT', $response['urlResolver']['type']); $this->assertEquals($targetPath, $response['urlResolver']['relative_url']); } + + /** + * Test for custom type which point to the invalid product/category/cms page. + * + * @magentoApiDataFixture Magento/UrlRewrite/_files/url_rewrite_not_existing_entity.php + */ + public function testNonExistentEntityUrlRewrite() + { + $urlPath = 'non-exist-entity.html'; + + $query = <<<QUERY +{ + urlResolver(url:"{$urlPath}") + { + id + relative_url + type + } +} +QUERY; + + $this->expectExceptionMessage( + "No such entity found with matching URL key: " . $urlPath + ); + $this->graphQlQuery($query); + } } diff --git a/dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrite_not_existing_entity.php b/dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrite_not_existing_entity.php new file mode 100644 index 0000000000000..052eac6f79d48 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrite_not_existing_entity.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\TestFramework\Helper\Bootstrap; +use Magento\UrlRewrite\Model\UrlRewrite; + +$objectManager = Bootstrap::getObjectManager(); + +/** @var int Product Id */ +$productId = 708579; + +/** @var UrlRewrite $urlRewrite */ +$urlRewrite = $objectManager->create(UrlRewrite::class); +$urlRewrite->setEntityType('custom') + ->setRequestPath('non-exist-entity.html') + ->setTargetPath('catalog/product/view/id/' . $productId) + ->setRedirectType(0) + ->setStoreId(1) + ->setDescription(null) + ->setIsAutogenerated(0); + +$urlRewrite->save(); diff --git a/dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrite_not_existing_entity_rollback.php b/dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrite_not_existing_entity_rollback.php new file mode 100644 index 0000000000000..12cbd2c704bfb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/UrlRewrite/_files/url_rewrite_not_existing_entity_rollback.php @@ -0,0 +1,15 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\TestFramework\Helper\Bootstrap; +use Magento\UrlRewrite\Model\UrlRewrite; + +$objectManager = Bootstrap::getObjectManager(); + +/** @var UrlRewrite $urlRewrite */ +$urlRewrite = $objectManager->create(UrlRewrite::class); +$urlRewrite->load('non-exist-entity.html', 'request_path'); +$urlRewrite->delete(); From 6c2962e6f1b2a387d114089e17dbcc257ea726c1 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Thu, 4 Apr 2019 18:45:35 +0300 Subject: [PATCH 024/224] MAGETWO-98832: Multistore Allowed Countries List Problem --- .../Customer/Model/AccountManagement.php | 29 +++++++++++++++- app/code/Magento/Quote/Model/Quote.php | 34 +++++++++++++++++-- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 673300369fe06..ea0dae9b72ea7 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -17,8 +17,10 @@ use Magento\Customer\Model\Config\Share as ConfigShare; use Magento\Customer\Model\Customer as CustomerModel; use Magento\Customer\Model\Customer\CredentialsValidator; +use Magento\Customer\Model\Data\Address as DataAddress; use Magento\Customer\Model\Metadata\Validator; use Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory; +use Magento\Directory\Model\AllowedCountries; use Magento\Eav\Model\Validator\Attribute\Backend; use Magento\Framework\Api\ExtensibleDataObjectConverter; use Magento\Framework\Api\SearchCriteriaBuilder; @@ -339,6 +341,11 @@ class AccountManagement implements AccountManagementInterface */ private $addressRegistry; + /** + * @var AllowedCountries + */ + private $allowedCountriesReader; + /** * @param CustomerFactory $customerFactory * @param ManagerInterface $eventManager @@ -405,7 +412,8 @@ public function __construct( SaveHandlerInterface $saveHandler = null, CollectionFactory $visitorCollectionFactory = null, SearchCriteriaBuilder $searchCriteriaBuilder = null, - AddressRegistry $addressRegistry = null + AddressRegistry $addressRegistry = null, + AllowedCountries $allowedCountriesReader = null ) { $this->customerFactory = $customerFactory; $this->eventManager = $eventManager; @@ -445,6 +453,8 @@ public function __construct( ?: ObjectManager::getInstance()->get(SearchCriteriaBuilder::class); $this->addressRegistry = $addressRegistry ?: ObjectManager::getInstance()->get(AddressRegistry::class); + $this->allowedCountriesReader = $allowedCountriesReader + ?: ObjectManager::getInstance()->get(AllowedCountries::class); } /** @@ -895,6 +905,9 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash } try { foreach ($customerAddresses as $address) { + if (!$this->isAddressAllowedForWebsite($address, (int)$customer->getStoreId())) { + continue; + } if ($address->getId()) { $newAddress = clone $address; $newAddress->setId(null); @@ -1601,4 +1614,18 @@ private function setIgnoreValidationFlag($customer) { $customer->setData('ignore_validation_flag', true); } + + /** + * Check is address allowed for store + * + * @param DataAddress $address + * @param int $storeId + * @return bool + */ + private function isAddressAllowedForWebsite(DataAddress $address, int $storeId): bool + { + $allowedCountries = $this->allowedCountriesReader->getAllowedCountries(ScopeInterface::SCOPE_STORE, $storeId); + + return in_array($address->getCountryId(), $allowedCountries); + } } diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php index b1f68d0411cf0..1bd965bf5463c 100644 --- a/app/code/Magento/Quote/Model/Quote.php +++ b/app/code/Magento/Quote/Model/Quote.php @@ -7,6 +7,7 @@ use Magento\Customer\Api\Data\CustomerInterface; use Magento\Customer\Api\Data\GroupInterface; +use Magento\Directory\Model\AllowedCountries; use Magento\Framework\Api\AttributeValueFactory; use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface; use Magento\Framework\Model\AbstractExtensibleModel; @@ -14,6 +15,7 @@ use Magento\Quote\Model\Quote\Address; use Magento\Quote\Model\Quote\Address\Total as AddressTotal; use Magento\Sales\Model\Status; +use Magento\Store\Model\ScopeInterface; use Magento\Framework\App\ObjectManager; /** @@ -359,6 +361,11 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C */ private $orderIncrementIdChecker; + /** + * @var AllowedCountries + */ + private $allowedCountriesReader; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -444,7 +451,8 @@ public function __construct( \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [], - \Magento\Sales\Model\OrderIncrementIdChecker $orderIncrementIdChecker = null + \Magento\Sales\Model\OrderIncrementIdChecker $orderIncrementIdChecker = null, + AllowedCountries $allowedCountriesReader = null ) { $this->quoteValidator = $quoteValidator; $this->_catalogProduct = $catalogProduct; @@ -481,6 +489,8 @@ public function __construct( $this->shippingAssignmentFactory = $shippingAssignmentFactory; $this->orderIncrementIdChecker = $orderIncrementIdChecker ?: ObjectManager::getInstance() ->get(\Magento\Sales\Model\OrderIncrementIdChecker::class); + $this->allowedCountriesReader = $allowedCountriesReader + ?: ObjectManager::getInstance()->get(AllowedCountries::class); parent::__construct( $context, $registry, @@ -941,7 +951,9 @@ public function assignCustomerWithAddressChange( /** @var \Magento\Quote\Model\Quote\Address $billingAddress */ $billingAddress = $this->_quoteAddressFactory->create(); $billingAddress->importCustomerAddressData($defaultBillingAddress); - $this->setBillingAddress($billingAddress); + if($this->isAddressAllowedForWebsite($billingAddress, (int)$this->getStoreId())) { + $this->setBilliphpngAddress($billingAddress); + } } } @@ -959,7 +971,9 @@ public function assignCustomerWithAddressChange( $shippingAddress = $this->_quoteAddressFactory->create(); } } - $this->setShippingAddress($shippingAddress); + if ($this->isAddressAllowedForWebsite($shippingAddress, (int)$this->getStoreId())) { + $this->setShippingAddress($shippingAddress); + } } return $this; @@ -2596,4 +2610,18 @@ public function setExtensionAttributes(\Magento\Quote\Api\Data\CartExtensionInte { return $this->_setExtensionAttributes($extensionAttributes); } + + /** + * Check is address allowed for store + * + * @param Address $address + * @param int $storeId + * @return bool + */ + private function isAddressAllowedForWebsite(Address $address, int $storeId): bool + { + $allowedCountries = $this->allowedCountriesReader->getAllowedCountries(ScopeInterface::SCOPE_STORE, $storeId); + + return in_array($address->getCountryId(), $allowedCountries); + } } From 3a71e2afc609f2aa7b2189836b55ec0da2c783d4 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Thu, 4 Apr 2019 19:31:49 +0300 Subject: [PATCH 025/224] MAGETWO-98832: Multistore Allowed Countries List Problem --- app/code/Magento/Quote/Model/Quote.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php index 1bd965bf5463c..964a6d57f2ae5 100644 --- a/app/code/Magento/Quote/Model/Quote.php +++ b/app/code/Magento/Quote/Model/Quote.php @@ -952,7 +952,7 @@ public function assignCustomerWithAddressChange( $billingAddress = $this->_quoteAddressFactory->create(); $billingAddress->importCustomerAddressData($defaultBillingAddress); if($this->isAddressAllowedForWebsite($billingAddress, (int)$this->getStoreId())) { - $this->setBilliphpngAddress($billingAddress); + $this->setBillingAddress($billingAddress); } } } From f5342dc0426b86bf95bff1639395b6cd3d5168bd Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Fri, 5 Apr 2019 20:21:26 +0300 Subject: [PATCH 026/224] MAGETWO-98832: Multistore Allowed Countries List Problem --- .../Customer/Model/AccountManagement.php | 5 +- .../Test/Unit/Model/AccountManagementTest.php | 49 ++++++++++++++++- .../Customer/Model/AccountManagementTest.php | 53 +++++++++++++++++++ .../Magento/Quote/Model/QuoteTest.php | 48 ++++++++++++++++- 4 files changed, 150 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index ea0dae9b72ea7..872fa9528626e 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -17,7 +17,6 @@ use Magento\Customer\Model\Config\Share as ConfigShare; use Magento\Customer\Model\Customer as CustomerModel; use Magento\Customer\Model\Customer\CredentialsValidator; -use Magento\Customer\Model\Data\Address as DataAddress; use Magento\Customer\Model\Metadata\Validator; use Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory; use Magento\Directory\Model\AllowedCountries; @@ -1618,11 +1617,11 @@ private function setIgnoreValidationFlag($customer) /** * Check is address allowed for store * - * @param DataAddress $address + * @param AddressInterface $address * @param int $storeId * @return bool */ - private function isAddressAllowedForWebsite(DataAddress $address, int $storeId): bool + private function isAddressAllowedForWebsite(AddressInterface $address, int $storeId): bool { $allowedCountries = $this->allowedCountriesReader->getAllowedCountries(ScopeInterface::SCOPE_STORE, $storeId); diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 22c9d90c086dc..71ce1947d9621 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -12,6 +12,7 @@ use Magento\Customer\Model\AuthenticationInterface; use Magento\Customer\Model\Data\Customer; use Magento\Customer\Model\EmailNotificationInterface; +use Magento\Directory\Model\AllowedCountries; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\App\Area; use Magento\Framework\Exception\NoSuchEntityException; @@ -155,6 +156,11 @@ class AccountManagementTest extends \PHPUnit\Framework\TestCase */ private $searchCriteriaBuilderMock; + /** + * @var AllowedCountries|\PHPUnit_Framework_MockObject_MockObject + */ + private $allowedCountriesReader; + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -193,6 +199,7 @@ protected function setUp() $this->extensibleDataObjectConverter = $this->createMock( \Magento\Framework\Api\ExtensibleDataObjectConverter::class ); + $this->allowedCountriesReader = $this->createMock(AllowedCountries::class); $this->authenticationMock = $this->getMockBuilder(AuthenticationInterface::class) ->disableOriginalConstructor() ->getMock(); @@ -256,6 +263,7 @@ protected function setUp() 'visitorCollectionFactory' => $this->visitorCollectionFactory, 'searchCriteriaBuilder' => $this->searchCriteriaBuilderMock, 'addressRegistry' => $this->addressRegistryMock, + 'allowedCountriesReader' => $this->allowedCountriesReader, ] ); $this->objectManagerHelper->setBackwardCompatibleProperty( @@ -551,7 +559,14 @@ public function testCreateAccountWithPasswordHashWithAddressException() ->expects($this->once()) ->method('delete') ->with($customer); - + $this->allowedCountriesReader + ->expects($this->atLeastOnce()) + ->method('getAllowedCountries') + ->willReturn(['US' => 'US']); + $address + ->expects($this->atLeastOnce()) + ->method('getCountryId') + ->willReturn('US'); $this->accountManagement->createAccountWithPasswordHash($customer, $hash); } @@ -725,6 +740,14 @@ public function testCreateAccountWithoutPassword() $this->emailNotificationMock->expects($this->once()) ->method('newAccount') ->willReturnSelf(); + $this->allowedCountriesReader + ->expects($this->atLeastOnce()) + ->method('getAllowedCountries') + ->willReturn(['US' => 'US']); + $address + ->expects($this->atLeastOnce()) + ->method('getCountryId') + ->willReturn('US'); $this->accountManagement->createAccount($customer); } @@ -970,6 +993,14 @@ public function testCreateAccountWithPassword() $this->emailNotificationMock->expects($this->once()) ->method('newAccount') ->willReturnSelf(); + $this->allowedCountriesReader + ->expects($this->atLeastOnce()) + ->method('getAllowedCountries') + ->willReturn(['US' => 'US']); + $address + ->expects($this->atLeastOnce()) + ->method('getCountryId') + ->willReturn('US'); $this->accountManagement->createAccount($customer, $password); } @@ -1954,6 +1985,14 @@ public function testCreateAccountWithPasswordHashWithCustomerAddresses() ->method('getWebsite') ->with($websiteId) ->willReturn($website); + $this->allowedCountriesReader + ->expects($this->atLeastOnce()) + ->method('getAllowedCountries') + ->willReturn(['US' => 'US']); + $existingAddress + ->expects($this->atLeastOnce()) + ->method('getCountryId') + ->willReturn('US'); $this->assertSame($customer, $this->accountManagement->createAccountWithPasswordHash($customer, $hash)); } @@ -2081,6 +2120,14 @@ public function testCreateAccountUnexpectedValueException(): void ->method('newAccount') ->willThrowException($exception); $this->logger->expects($this->once())->method('error')->with($exception); + $this->allowedCountriesReader + ->expects($this->atLeastOnce()) + ->method('getAllowedCountries') + ->willReturn(['US' => 'US']); + $address + ->expects($this->atLeastOnce()) + ->method('getCountryId') + ->willReturn('US'); $this->accountManagement->createAccount($customer); } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php index 4810b6c28caef..a170d737bad37 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php @@ -14,6 +14,7 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Exception\State\ExpiredException; use Magento\Framework\Reflection\DataObjectProcessor; +use Magento\Store\Model\StoreManagerInterface; use Magento\TestFramework\Helper\Bootstrap; /** @@ -53,6 +54,9 @@ class AccountManagementTest extends \PHPUnit\Framework\TestCase /** @var \Magento\Framework\Api\ExtensibleDataObjectConverter */ private $extensibleDataObjectConverter; + /** @var StoreManagerInterface */ + private $storeManager; + /** @var \Magento\Framework\Api\DataObjectHelper */ protected $dataObjectHelper; @@ -114,6 +118,9 @@ protected function setUp() $this->extensibleDataObjectConverter = $this->objectManager ->create(\Magento\Framework\Api\ExtensibleDataObjectConverter::class); + + $this->storeManager = $this->objectManager + ->create(StoreManagerInterface::class); } /** @@ -844,6 +851,52 @@ public function testCreateNewCustomerWithPasswordHash() ); } + /** + * Customer has two addresses one of it is allowed in website and second is not + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_two_addresses.php + * @magentoDataFixture Magento/Store/_files/websites_different_countries.php + * @magentoConfigFixture fixture_second_store_store general/country/allow UA + * @return void + */ + public function testCreateNewCustomerWithPasswordHashWithNotAllowedCountry() + { + /** Preconditions: + * Customer with two addresses created + * Two websites with different allowed country configured + */ + $customerRepository = $this->objectManager->create( + CustomerRepositoryInterface::class + ); + $fixtureCustomerId = 1; + $allowedCountryIdForSecondWebsite = 'UA'; + /** @var \Magento\Customer\Model\Customer $customer */ + $store =$this->storeManager->getStore('fixture_second_store'); + $customerData = $customerRepository->getById($fixtureCustomerId); + $customerData->getAddresses()[1]->setRegion(null)->setCountryId($allowedCountryIdForSecondWebsite) + ->setRegionId(null); + $customerData->setStoreId($store->getId())->setWebsiteId($store->getWebsiteId())->setId(null); + $encryptor = $this->objectManager->get(\Magento\Framework\Encryption\EncryptorInterface::class); + /** @var \Magento\Framework\Math\Random $mathRandom */ + $password = $this->objectManager->get(\Magento\Framework\Math\Random::class)->getRandomString(8); + $passwordHash = $encryptor->getHash($password, true); + $savedCustomer = $this->accountManagement->createAccountWithPasswordHash( + $customerData, + $passwordHash + ); + $this->assertCount( + 1, + $savedCustomer->getAddresses(), + 'The wrong address quantity was saved' + ); + $this->assertSame( + 'UA', + $savedCustomer->getAddresses()[0]->getCountryId(), + 'The address with the disallowed country was saved' + ); + } + /** * @magentoAppArea frontend * @magentoDataFixture Magento/Customer/_files/customer.php diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php index 15f555a67e722..3510e8fca2bea 100644 --- a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php @@ -19,7 +19,9 @@ use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Quote\Api\CartRepositoryInterface; use Magento\Framework\Api\ExtensibleDataInterface; - +use Magento\Framework\App\Config\ConfigResource\ConfigInterface; +use Magento\Framework\App\Config\ReinitableConfigInterface; +use Magento\Store\Model\StoreManagerInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ @@ -30,12 +32,23 @@ class QuoteTest extends \PHPUnit\Framework\TestCase */ private $objectManager; + /** + * @var ConfigInterface + */ + private $config; + + /** + * @var string + */ + private $allowedCountriesConfigPath = 'general/country/allow'; + /** * @inheritdoc */ protected function setUp() { $this->objectManager = Bootstrap::getObjectManager(); + $this->config = Bootstrap::getObjectManager()->get(ConfigInterface::class); } /** @@ -330,6 +343,39 @@ public function testAssignCustomerWithAddressChange(): void } } + /** + * Customer has address with country which not allowed in website + * + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_address.php + * @return void + */ + public function testAssignCustomerWithAddressChangeWithNotAllowedCountry() + { + /** Preconditions: + * Customer with address is created + */ + $this->config->saveConfig( + $this->allowedCountriesConfigPath, + 'FR' + ); + Bootstrap::getObjectManager()->get(ReinitableConfigInterface::class)->reinit(); + Bootstrap::getObjectManager()->create(StoreManagerInterface::class)->reinitStores(); + + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $customerData = $this->_prepareQuoteForTestAssignCustomerWithAddressChange($quote); + + /** Execute SUT */ + $quote->assignCustomerWithAddressChange($customerData); + + /** Check that addresses are empty */ + $this->assertNull($quote->getBillingAddress()->getCountryId()); + $this->assertNull($quote->getShippingAddress()->getCountryId()); + + $this->config->deleteConfig($this->allowedCountriesConfigPath); + } + /** * @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php * @return void From 5595d4e609e1c835ffe7f525c58db2387d8c8a4c Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Mon, 8 Apr 2019 12:17:26 +0300 Subject: [PATCH 027/224] MAGETWO-98832: Multistore Allowed Countries List Problem --- .../Test/Unit/Model/AccountManagementTest.php | 12 +++--------- app/code/Magento/Quote/Model/Quote.php | 2 ++ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 71ce1947d9621..176260fca917a 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -2120,15 +2120,9 @@ public function testCreateAccountUnexpectedValueException(): void ->method('newAccount') ->willThrowException($exception); $this->logger->expects($this->once())->method('error')->with($exception); - $this->allowedCountriesReader - ->expects($this->atLeastOnce()) - ->method('getAllowedCountries') - ->willReturn(['US' => 'US']); - $address - ->expects($this->atLeastOnce()) - ->method('getCountryId') - ->willReturn('US'); - + $this->allowedCountriesReader->expects($this->atLeastOnce()) + ->method('getAllowedCountries')->willReturn(['US' => 'US']); + $address->expects($this->atLeastOnce())->method('getCountryId')->willReturn('US'); $this->accountManagement->createAccount($customer); } diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php index 964a6d57f2ae5..f50ac58208fbc 100644 --- a/app/code/Magento/Quote/Model/Quote.php +++ b/app/code/Magento/Quote/Model/Quote.php @@ -409,6 +409,7 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C * @param array $data * @param \Magento\Sales\Model\OrderIncrementIdChecker|null $orderIncrementIdChecker * @SuppressWarnings(PHPMD.ExcessiveParameterList) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function __construct( \Magento\Framework\Model\Context $context, @@ -929,6 +930,7 @@ public function assignCustomer(\Magento\Customer\Api\Data\CustomerInterface $cus * @param \Magento\Customer\Api\Data\CustomerInterface $customer * @param Address $billingAddress Quote billing address * @param Address $shippingAddress Quote shipping address + * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @return $this */ public function assignCustomerWithAddressChange( From 79bb73c59c4aead56f6834773bb7ec5c8e09e456 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Tue, 9 Apr 2019 00:51:52 +0300 Subject: [PATCH 028/224] MAGETWO-98832: Multistore Allowed Countries List Problem --- app/code/Magento/Customer/Model/AccountManagement.php | 1 + app/code/Magento/Quote/Model/Quote.php | 4 +++- .../integration/testsuite/Magento/Quote/Model/QuoteTest.php | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 872fa9528626e..cd7d497c43b29 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -377,6 +377,7 @@ class AccountManagement implements AccountManagementInterface * @param CollectionFactory|null $visitorCollectionFactory * @param SearchCriteriaBuilder|null $searchCriteriaBuilder * @param AddressRegistry|null $addressRegistry + * @param AllowedCountries|null $allowedCountriesReader * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.NPathComplexity) */ diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php index f50ac58208fbc..b8a4e2a0c00d2 100644 --- a/app/code/Magento/Quote/Model/Quote.php +++ b/app/code/Magento/Quote/Model/Quote.php @@ -408,6 +408,7 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection * @param array $data * @param \Magento\Sales\Model\OrderIncrementIdChecker|null $orderIncrementIdChecker + * @param AllowedCountries|null $allowedCountriesReader * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ @@ -953,7 +954,8 @@ public function assignCustomerWithAddressChange( /** @var \Magento\Quote\Model\Quote\Address $billingAddress */ $billingAddress = $this->_quoteAddressFactory->create(); $billingAddress->importCustomerAddressData($defaultBillingAddress); - if($this->isAddressAllowedForWebsite($billingAddress, (int)$this->getStoreId())) { + + if ($this->isAddressAllowedForWebsite($billingAddress, (int)$this->getStoreId())) { $this->setBillingAddress($billingAddress); } } diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php index 3510e8fca2bea..76963be90c6ed 100644 --- a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php @@ -22,6 +22,7 @@ use Magento\Framework\App\Config\ConfigResource\ConfigInterface; use Magento\Framework\App\Config\ReinitableConfigInterface; use Magento\Store\Model\StoreManagerInterface; + /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ From 702405412b7de4523f200136d785d540be39109b Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Tue, 9 Apr 2019 04:40:12 +0300 Subject: [PATCH 029/224] MAGETWO-98832: Multistore Allowed Countries List Problem --- .../Customer/Model/AccountManagement.php | 6 ++-- app/code/Magento/Quote/Model/Quote.php | 32 ++++++++++++------- .../Customer/Model/AccountManagementTest.php | 11 ++----- .../Magento/Quote/Model/QuoteTest.php | 5 --- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index cd7d497c43b29..9e9859b068b32 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -905,7 +905,7 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash } try { foreach ($customerAddresses as $address) { - if (!$this->isAddressAllowedForWebsite($address, (int)$customer->getStoreId())) { + if (!$this->isAddressAllowedForWebsite($address, (string)$customer->getStoreId())) { continue; } if ($address->getId()) { @@ -1619,10 +1619,10 @@ private function setIgnoreValidationFlag($customer) * Check is address allowed for store * * @param AddressInterface $address - * @param int $storeId + * @param string $storeId * @return bool */ - private function isAddressAllowedForWebsite(AddressInterface $address, int $storeId): bool + private function isAddressAllowedForWebsite(AddressInterface $address, string $storeId): bool { $allowedCountries = $this->allowedCountriesReader->getAllowedCountries(ScopeInterface::SCOPE_STORE, $storeId); diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php index b8a4e2a0c00d2..142fdcb086b37 100644 --- a/app/code/Magento/Quote/Model/Quote.php +++ b/app/code/Magento/Quote/Model/Quote.php @@ -410,7 +410,6 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C * @param \Magento\Sales\Model\OrderIncrementIdChecker|null $orderIncrementIdChecker * @param AllowedCountries|null $allowedCountriesReader * @SuppressWarnings(PHPMD.ExcessiveParameterList) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function __construct( \Magento\Framework\Model\Context $context, @@ -931,7 +930,6 @@ public function assignCustomer(\Magento\Customer\Api\Data\CustomerInterface $cus * @param \Magento\Customer\Api\Data\CustomerInterface $customer * @param Address $billingAddress Quote billing address * @param Address $shippingAddress Quote shipping address - * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @return $this */ public function assignCustomerWithAddressChange( @@ -954,10 +952,7 @@ public function assignCustomerWithAddressChange( /** @var \Magento\Quote\Model\Quote\Address $billingAddress */ $billingAddress = $this->_quoteAddressFactory->create(); $billingAddress->importCustomerAddressData($defaultBillingAddress); - - if ($this->isAddressAllowedForWebsite($billingAddress, (int)$this->getStoreId())) { - $this->setBillingAddress($billingAddress); - } + $this->assignAddress($billingAddress); } } @@ -975,9 +970,8 @@ public function assignCustomerWithAddressChange( $shippingAddress = $this->_quoteAddressFactory->create(); } } - if ($this->isAddressAllowedForWebsite($shippingAddress, (int)$this->getStoreId())) { - $this->setShippingAddress($shippingAddress); - } + + $this->assignAddress($shippingAddress, false); } return $this; @@ -2619,13 +2613,29 @@ public function setExtensionAttributes(\Magento\Quote\Api\Data\CartExtensionInte * Check is address allowed for store * * @param Address $address - * @param int $storeId + * @param string $storeId * @return bool */ - private function isAddressAllowedForWebsite(Address $address, int $storeId): bool + private function isAddressAllowedForWebsite(Address $address, string $storeId): bool { $allowedCountries = $this->allowedCountriesReader->getAllowedCountries(ScopeInterface::SCOPE_STORE, $storeId); return in_array($address->getCountryId(), $allowedCountries); } + + /** + * Assign address to quote + * + * @param Address $address + * @param bool $billingAddress + * @return void + */ + private function assignAddress(Address $address, bool $billingAddress = true): void + { + if ($this->isAddressAllowedForWebsite($address, (string) $this->getStoreId())) { + $billingAddress + ? $this->setBillingAddress($address) + : $this->setShippingAddress($address); + } + } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php index a170d737bad37..cbf90b411c1e3 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php @@ -862,18 +862,11 @@ public function testCreateNewCustomerWithPasswordHash() */ public function testCreateNewCustomerWithPasswordHashWithNotAllowedCountry() { - /** Preconditions: - * Customer with two addresses created - * Two websites with different allowed country configured - */ - $customerRepository = $this->objectManager->create( - CustomerRepositoryInterface::class - ); $fixtureCustomerId = 1; $allowedCountryIdForSecondWebsite = 'UA'; /** @var \Magento\Customer\Model\Customer $customer */ - $store =$this->storeManager->getStore('fixture_second_store'); - $customerData = $customerRepository->getById($fixtureCustomerId); + $store = $this->storeManager->getStore('fixture_second_store'); + $customerData = $this->customerRepository->getById($fixtureCustomerId); $customerData->getAddresses()[1]->setRegion(null)->setCountryId($allowedCountryIdForSecondWebsite) ->setRegionId(null); $customerData->setStoreId($store->getId())->setWebsiteId($store->getWebsiteId())->setId(null); diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php index 76963be90c6ed..b0d2c24be2e57 100644 --- a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php @@ -353,16 +353,11 @@ public function testAssignCustomerWithAddressChange(): void */ public function testAssignCustomerWithAddressChangeWithNotAllowedCountry() { - /** Preconditions: - * Customer with address is created - */ $this->config->saveConfig( $this->allowedCountriesConfigPath, 'FR' ); Bootstrap::getObjectManager()->get(ReinitableConfigInterface::class)->reinit(); - Bootstrap::getObjectManager()->create(StoreManagerInterface::class)->reinitStores(); - /** @var Quote $quote */ $quote = $this->objectManager->create(Quote::class); $customerData = $this->_prepareQuoteForTestAssignCustomerWithAddressChange($quote); From 90d1b8e437724f001be580ca9c3ad470fe756243 Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Tue, 9 Apr 2019 10:19:49 -0500 Subject: [PATCH 030/224] MC-4431: Convert UpdateCustomerBackendEntityTest to MFTF - Updating entity reference. --- .../Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml index 9f796cb91cf64..68206caae121a 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml @@ -94,7 +94,7 @@ <before> <createData entity="Simple_US_Customer" stepKey="createCustomer1"/> - <createData entity="CatalogRuleByFixed" stepKey="createCatalogRule1"/> + <createData entity="ActiveCatalogPriceRuleWithConditions" stepKey="createCatalogRule1"/> <createData entity="SimpleSubCategory" stepKey="createCategory1"/> <!-- Create the configurable product based on the data in the /data folder --> From df5d9142964c3d664854a78b1b165cb585483b61 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Tue, 9 Apr 2019 23:01:20 +0300 Subject: [PATCH 031/224] MAGETWO-98832: Multistore Allowed Countries List Problem --- .../Magento/Customer/Model/AccountManagement.php | 6 +++--- app/code/Magento/Quote/Model/Quote.php | 12 ++++++------ .../Backend/_files/allowed_countries_fr.php | 16 ++++++++++++++++ .../_files/allowed_countries_fr_rollback.php | 16 ++++++++++++++++ .../Customer/Model/AccountManagementTest.php | 5 ++--- .../testsuite/Magento/Quote/Model/QuoteTest.php | 10 +--------- 6 files changed, 44 insertions(+), 21 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Backend/_files/allowed_countries_fr.php create mode 100644 dev/tests/integration/testsuite/Magento/Backend/_files/allowed_countries_fr_rollback.php diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 9e9859b068b32..ce9204837b4ea 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -905,7 +905,7 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash } try { foreach ($customerAddresses as $address) { - if (!$this->isAddressAllowedForWebsite($address, (string)$customer->getStoreId())) { + if (!$this->isAddressAllowedForWebsite($address, $customer->getStoreId())) { continue; } if ($address->getId()) { @@ -1619,10 +1619,10 @@ private function setIgnoreValidationFlag($customer) * Check is address allowed for store * * @param AddressInterface $address - * @param string $storeId + * @param int|null $storeId * @return bool */ - private function isAddressAllowedForWebsite(AddressInterface $address, string $storeId): bool + private function isAddressAllowedForWebsite(AddressInterface $address, $storeId): bool { $allowedCountries = $this->allowedCountriesReader->getAllowedCountries(ScopeInterface::SCOPE_STORE, $storeId); diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php index 142fdcb086b37..6ee81c8680dcd 100644 --- a/app/code/Magento/Quote/Model/Quote.php +++ b/app/code/Magento/Quote/Model/Quote.php @@ -2613,10 +2613,10 @@ public function setExtensionAttributes(\Magento\Quote\Api\Data\CartExtensionInte * Check is address allowed for store * * @param Address $address - * @param string $storeId + * @param int|null $storeId * @return bool */ - private function isAddressAllowedForWebsite(Address $address, string $storeId): bool + private function isAddressAllowedForWebsite(Address $address, $storeId): bool { $allowedCountries = $this->allowedCountriesReader->getAllowedCountries(ScopeInterface::SCOPE_STORE, $storeId); @@ -2627,13 +2627,13 @@ private function isAddressAllowedForWebsite(Address $address, string $storeId): * Assign address to quote * * @param Address $address - * @param bool $billingAddress + * @param bool $isBillingAddress * @return void */ - private function assignAddress(Address $address, bool $billingAddress = true): void + private function assignAddress(Address $address, bool $isBillingAddress = true): void { - if ($this->isAddressAllowedForWebsite($address, (string) $this->getStoreId())) { - $billingAddress + if ($this->isAddressAllowedForWebsite($address, $this->getStoreId())) { + $isBillingAddress ? $this->setBillingAddress($address) : $this->setShippingAddress($address); } diff --git a/dev/tests/integration/testsuite/Magento/Backend/_files/allowed_countries_fr.php b/dev/tests/integration/testsuite/Magento/Backend/_files/allowed_countries_fr.php new file mode 100644 index 0000000000000..4bce8d95dafa6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Backend/_files/allowed_countries_fr.php @@ -0,0 +1,16 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types = 1); + +use Magento\Framework\App\Config\ConfigResource\ConfigInterface; +use Magento\Framework\App\Config\ReinitableConfigInterface; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ConfigInterface $config */ +$config = $objectManager->get(ConfigInterface::class); +$config->saveConfig('general/country/allow', 'FR'); +$objectManager->get(ReinitableConfigInterface::class)->reinit(); diff --git a/dev/tests/integration/testsuite/Magento/Backend/_files/allowed_countries_fr_rollback.php b/dev/tests/integration/testsuite/Magento/Backend/_files/allowed_countries_fr_rollback.php new file mode 100644 index 0000000000000..711d985786329 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Backend/_files/allowed_countries_fr_rollback.php @@ -0,0 +1,16 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types = 1); + +use Magento\Framework\App\Config\ConfigResource\ConfigInterface; +use Magento\Framework\App\Config\ReinitableConfigInterface; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); +/** @var ConfigInterface $config */ +$config = $objectManager->get(ConfigInterface::class); +$config->deleteConfig('general/country/allow'); +$objectManager->get(ReinitableConfigInterface::class)->reinit(); diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php index cbf90b411c1e3..754c949747d61 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php @@ -862,11 +862,10 @@ public function testCreateNewCustomerWithPasswordHash() */ public function testCreateNewCustomerWithPasswordHashWithNotAllowedCountry() { - $fixtureCustomerId = 1; + $customerId = 1; $allowedCountryIdForSecondWebsite = 'UA'; - /** @var \Magento\Customer\Model\Customer $customer */ $store = $this->storeManager->getStore('fixture_second_store'); - $customerData = $this->customerRepository->getById($fixtureCustomerId); + $customerData = $this->customerRepository->getById($customerId); $customerData->getAddresses()[1]->setRegion(null)->setCountryId($allowedCountryIdForSecondWebsite) ->setRegionId(null); $customerData->setStoreId($store->getId())->setWebsiteId($store->getWebsiteId())->setId(null); diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php index b0d2c24be2e57..bb8c322702249 100644 --- a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php @@ -349,27 +349,19 @@ public function testAssignCustomerWithAddressChange(): void * * @magentoDataFixture Magento/Customer/_files/customer.php * @magentoDataFixture Magento/Customer/_files/customer_address.php + * @magentoDataFixture Magento/Backend/_files/allowed_countries_fr.php * @return void */ public function testAssignCustomerWithAddressChangeWithNotAllowedCountry() { - $this->config->saveConfig( - $this->allowedCountriesConfigPath, - 'FR' - ); - Bootstrap::getObjectManager()->get(ReinitableConfigInterface::class)->reinit(); /** @var Quote $quote */ $quote = $this->objectManager->create(Quote::class); $customerData = $this->_prepareQuoteForTestAssignCustomerWithAddressChange($quote); - - /** Execute SUT */ $quote->assignCustomerWithAddressChange($customerData); /** Check that addresses are empty */ $this->assertNull($quote->getBillingAddress()->getCountryId()); $this->assertNull($quote->getShippingAddress()->getCountryId()); - - $this->config->deleteConfig($this->allowedCountriesConfigPath); } /** From d69e3ead132f354e6b7d02a690002a4265ae99af Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Wed, 10 Apr 2019 00:55:05 +0300 Subject: [PATCH 032/224] MAGETWO-98832: Multistore Allowed Countries List Problem --- .../testsuite/Magento/Quote/Model/QuoteTest.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php index bb8c322702249..3667f4cc37fab 100644 --- a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php @@ -19,9 +19,6 @@ use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Quote\Api\CartRepositoryInterface; use Magento\Framework\Api\ExtensibleDataInterface; -use Magento\Framework\App\Config\ConfigResource\ConfigInterface; -use Magento\Framework\App\Config\ReinitableConfigInterface; -use Magento\Store\Model\StoreManagerInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -33,23 +30,12 @@ class QuoteTest extends \PHPUnit\Framework\TestCase */ private $objectManager; - /** - * @var ConfigInterface - */ - private $config; - - /** - * @var string - */ - private $allowedCountriesConfigPath = 'general/country/allow'; - /** * @inheritdoc */ protected function setUp() { $this->objectManager = Bootstrap::getObjectManager(); - $this->config = Bootstrap::getObjectManager()->get(ConfigInterface::class); } /** From aca26706cacd277789c8977813ec33fe183cae9d Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Wed, 10 Apr 2019 02:11:46 +0300 Subject: [PATCH 033/224] MAGETWO-98832: Multistore Allowed Countries List Problem --- app/code/Magento/Customer/Model/AccountManagement.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index ce9204837b4ea..733e5362aee3e 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -380,6 +380,7 @@ class AccountManagement implements AccountManagementInterface * @param AllowedCountries|null $allowedCountriesReader * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function __construct( CustomerFactory $customerFactory, From 7a905997efa240d577cdba6cdea9ff3aacd2ee34 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 10 Apr 2019 14:48:14 +0300 Subject: [PATCH 034/224] magento/graphql-ce#387: Test coverage of getting IDs of CMS page/blocks by GraphQL API --- .../Model/Resolver/DataProvider/Page.php | 51 ++++++++++-- .../CmsGraphQl/Model/Resolver/Page.php | 45 ++++++++-- .../Magento/CmsGraphQl/etc/schema.graphqls | 2 + .../Magento/GraphQl/Cms/CmsPageTest.php | 82 ++++++++++++++++++- 4 files changed, 165 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php index 22009824452be..0745296822c3c 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php @@ -8,8 +8,10 @@ namespace Magento\CmsGraphQl\Model\Resolver\DataProvider; use Magento\Cms\Api\Data\PageInterface; +use Magento\Cms\Api\GetPageByIdentifierInterface; use Magento\Cms\Api\PageRepositoryInterface; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Store\Model\StoreManagerInterface; use Magento\Widget\Model\Template\FilterEmulate; /** @@ -18,9 +20,9 @@ class Page { /** - * @var FilterEmulate + * @var GetPageByIdentifierInterface */ - private $widgetFilter; + private $pageByIdentifier; /** * @var PageRepositoryInterface @@ -28,14 +30,30 @@ class Page private $pageRepository; /** - * @param PageRepositoryInterface $pageRepository + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var FilterEmulate + */ + private $widgetFilter; + + /** + * @param GetPageByIdentifierInterface $getPageByIdentifier * @param FilterEmulate $widgetFilter + * @param PageRepositoryInterface $pageRepository + * @param StoreManagerInterface $storeManager */ public function __construct( + GetPageByIdentifierInterface $getPageByIdentifier, + FilterEmulate $widgetFilter, PageRepositoryInterface $pageRepository, - FilterEmulate $widgetFilter + StoreManagerInterface $storeManager ) { + $this->pageByIdentifier = $getPageByIdentifier; $this->pageRepository = $pageRepository; + $this->storeManager = $storeManager; $this->widgetFilter = $widgetFilter; } @@ -44,10 +62,32 @@ public function __construct( * @return array * @throws NoSuchEntityException */ - public function getData(int $pageId): array + public function getDataByPageId(int $pageId): array { $page = $this->pageRepository->getById($pageId); + return $this->convertPageData($page); + } + + /** + * @param string $pageIdentifier + * @return array + */ + public function getDataByPageIdentifier(string $pageIdentifier): array + { + $storeId = (int)$this->storeManager->getStore()->getId(); + $page = $this->pageByIdentifier->execute($pageIdentifier, $storeId); + + return $this->convertPageData($page); + } + + /** + * @param PageInterface $page + * @return array + * @throws NoSuchEntityException + */ + private function convertPageData(PageInterface $page) + { if (false === $page->isActive()) { throw new NoSuchEntityException(); } @@ -56,6 +96,7 @@ public function getData(int $pageId): array $pageData = [ 'url_key' => $page->getIdentifier(), + PageInterface::PAGE_ID => $page->getId(), PageInterface::TITLE => $page->getTitle(), PageInterface::CONTENT => $renderedContent, PageInterface::CONTENT_HEADING => $page->getContentHeading(), diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php index 1077ab81551c2..41712889a1bfd 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php @@ -26,6 +26,7 @@ class Page implements ResolverInterface private $pageDataProvider; /** + * * @param PageDataProvider $pageDataProvider */ public function __construct( @@ -44,8 +45,15 @@ public function resolve( array $value = null, array $args = null ) { - $pageId = $this->getPageId($args); - $pageData = $this->getPageData($pageId); + if (!isset($args['id']) && !isset($args['identifier'])) { + throw new GraphQlInputException(__('"Page id/identifier should be specified')); + } + + if (isset($args['id'])) { + $pageData = $this->getPageDataById($this->getPageId($args)); + } elseif (isset($args['identifier'])) { + $pageData = $this->getPageDataByIdentifier($this->getPageIdentifier($args)); + } return $pageData; } @@ -53,15 +61,19 @@ public function resolve( /** * @param array $args * @return int - * @throws GraphQlInputException */ private function getPageId(array $args): int { - if (!isset($args['id'])) { - throw new GraphQlInputException(__('"Page id should be specified')); - } + return isset($args['id']) ? (int)$args['id'] : 0; + } - return (int)$args['id']; + /** + * @param array $args + * @return string + */ + private function getPageIdentifier(array $args): string + { + return isset($args['identifier']) ? (string)$args['identifier'] : ''; } /** @@ -69,10 +81,25 @@ private function getPageId(array $args): int * @return array * @throws GraphQlNoSuchEntityException */ - private function getPageData(int $pageId): array + private function getPageDataById(int $pageId): array + { + try { + $pageData = $this->pageDataProvider->getDataByPageId($pageId); + } catch (NoSuchEntityException $e) { + throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); + } + return $pageData; + } + + /** + * @param string $pageIdentifier + * @return array + * @throws GraphQlNoSuchEntityException + */ + private function getPageDataByIdentifier(string $pageIdentifier): array { try { - $pageData = $this->pageDataProvider->getData($pageId); + $pageData = $this->pageDataProvider->getDataByPageIdentifier($pageIdentifier); } catch (NoSuchEntityException $e) { throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); } diff --git a/app/code/Magento/CmsGraphQl/etc/schema.graphqls b/app/code/Magento/CmsGraphQl/etc/schema.graphqls index e8abd2201b886..765e58849fc96 100644 --- a/app/code/Magento/CmsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CmsGraphQl/etc/schema.graphqls @@ -13,6 +13,7 @@ type StoreConfig @doc(description: "The type contains information about a store type Query { cmsPage ( id: Int @doc(description: "Id of the CMS page") + identifier: String @doc(description: "Identifier of the CMS page") ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") cmsBlocks ( identifiers: [String] @doc(description: "Identifiers of the CMS blocks") @@ -20,6 +21,7 @@ type Query { } type CmsPage @doc(description: "CMS page defines all CMS page information") { + page_id: Int @doc(description: "Entity ID of CMS page") url_key: String @doc(description: "URL key of CMS page") title: String @doc(description: "CMS page title") content: String @doc(description: "CMS page content") diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsPageTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsPageTest.php index 86145fafa62f1..8abcee8f22403 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsPageTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsPageTest.php @@ -50,6 +50,32 @@ public function testGetCmsPageById() $this->assertEquals($cmsPageData['meta_keywords'], $response['cmsPage']['meta_keywords']); } + /** + * Verify the fields of CMS Page selected by page_id + * + * @magentoApiDataFixture Magento/Cms/_files/pages.php + */ + public function testGetCmsPageByIdentifier() + { + $cmsPageIdentifier = 'page100'; + $storeId = 0; + + $cmsPage = ObjectManager::getInstance()->get(GetPageByIdentifier::class)->execute($cmsPageIdentifier, $storeId); + $pageId = $cmsPage->getPageId(); + + $query = + <<<QUERY +{ + cmsPage(identifier: "$cmsPageIdentifier") { + page_id + } +} +QUERY; + + $response = $this->graphQlQuery($query); + $this->assertEquals($pageId, $response['cmsPage']['page_id']); + } + /** * Verify the message when page_id is not specified. */ @@ -72,7 +98,7 @@ public function testGetCmsPageWithoutId() QUERY; $this->expectException(\Exception::class); - $this->expectExceptionMessage('Page id should be specified'); + $this->expectExceptionMessage('Page id/identifier should be specified'); $this->graphQlQuery($query); } @@ -102,6 +128,32 @@ public function testGetCmsPageByNonExistentId() $this->graphQlQuery($query); } + /** + * Verify the message when identifier does not exist. + * + * @expectedException \Exception + * @expectedExceptionMessage The CMS page with the "" ID doesn't exist. + */ + public function testGetCmsPageByNonExistentIdentifier() + { + $query = + <<<QUERY +{ + cmsPage(identifier: "") { + url_key + title + content + content_heading + page_layout + meta_title + meta_description + meta_keywords + } +} +QUERY; + $this->graphQlQuery($query); + } + /** * Verify the message when CMS Page selected by page_id is disabled * @@ -130,4 +182,32 @@ public function testGetDisabledCmsPageById() $this->expectExceptionMessage('No such entity.'); $this->graphQlQuery($query); } + + /** + * Verify the message when CMS Page selected by identifier is disabled + * + * @magentoApiDataFixture Magento/Cms/_files/noroute.php + * @expectedException \Exception + * @expectedExceptionMessage The CMS page with the "no-route" ID doesn't exist. + */ + public function testGetDisabledCmsPageByIdentifier() + { + $cmsPageIdentifier = 'no-route'; + $query = + <<<QUERY +{ + cmsPage(identifier: "$cmsPageIdentifier") { + url_key + title + content + content_heading + page_layout + meta_title + meta_description + meta_keywords + } +} +QUERY; + $this->graphQlQuery($query); + } } From 8a5b3b7bf87959c6ed9118fcd213cdc34c563ed7 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 10 Apr 2019 15:11:08 +0300 Subject: [PATCH 035/224] magento/graphql-ce#387: Test coverage of getting IDs of CMS page/blocks by GraphQL API --- .../Model/Resolver/DataProvider/Block.php | 1 + .../Magento/CmsGraphQl/etc/schema.graphqls | 1 + .../Magento/GraphQl/Cms/CmsBlockTest.php | 38 +++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php index 47a2439c4fad0..fa4944381b858 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php @@ -59,6 +59,7 @@ public function getData(string $blockIdentifier): array $renderedContent = $this->widgetFilter->filter($block->getContent()); $blockData = [ + BlockInterface::BLOCK_ID => $block->getId(), BlockInterface::IDENTIFIER => $block->getIdentifier(), BlockInterface::TITLE => $block->getTitle(), BlockInterface::CONTENT => $renderedContent, diff --git a/app/code/Magento/CmsGraphQl/etc/schema.graphqls b/app/code/Magento/CmsGraphQl/etc/schema.graphqls index 765e58849fc96..5504c42b339f9 100644 --- a/app/code/Magento/CmsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CmsGraphQl/etc/schema.graphqls @@ -37,6 +37,7 @@ type CmsBlocks @doc(description: "CMS blocks information") { } type CmsBlock @doc(description: "CMS block defines all CMS block information") { + block_id: Int @doc(description: "Entity ID of CMS block") identifier: String @doc(description: "CMS block identifier") title: String @doc(description: "CMS block title") content: String @doc(description: "CMS block content") diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsBlockTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsBlockTest.php index 57f526b1cb2f7..6e07f8cd7876a 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsBlockTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsBlockTest.php @@ -47,6 +47,7 @@ public function testGetCmsBlock() { cmsBlocks(identifiers: "enabled_block") { items { + block_id identifier title content @@ -59,6 +60,43 @@ public function testGetCmsBlock() self::assertArrayHasKey('cmsBlocks', $response); self::assertArrayHasKey('items', $response['cmsBlocks']); + self::assertEquals($cmsBlockData['block_id'], $response['cmsBlocks']['items'][0]['block_id']); + self::assertEquals($cmsBlockData['identifier'], $response['cmsBlocks']['items'][0]['identifier']); + self::assertEquals($cmsBlockData['title'], $response['cmsBlocks']['items'][0]['title']); + self::assertEquals($renderedContent, $response['cmsBlocks']['items'][0]['content']); + } + + /** + * Verify the fields of CMS Block selected by block_id + * + * @magentoApiDataFixture Magento/Cms/_files/blocks.php + */ + public function testGetCmsBlockByBlockId() + { + $cmsBlock = $this->blockRepository->getById('enabled_block'); + $cmsBlockData = $cmsBlock->getData(); + $blockId = $cmsBlockData['block_id']; + $renderedContent = $this->filterEmulate->setUseSessionInUrl(false)->filter($cmsBlock->getContent()); + + $query = + <<<QUERY +{ + cmsBlocks(identifiers: "$blockId") { + items { + block_id + identifier + title + content + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey('cmsBlocks', $response); + self::assertArrayHasKey('items', $response['cmsBlocks']); + + self::assertEquals($blockId, $response['cmsBlocks']['items'][0]['block_id']); self::assertEquals($cmsBlockData['identifier'], $response['cmsBlocks']['items'][0]['identifier']); self::assertEquals($cmsBlockData['title'], $response['cmsBlocks']['items'][0]['title']); self::assertEquals($renderedContent, $response['cmsBlocks']['items'][0]['content']); From b8d93d8533ba09e5d83cc119f3c7ab1dea5925b4 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Thu, 11 Apr 2019 09:42:39 +0300 Subject: [PATCH 036/224] magento/graphql-ce#387: Test coverage of getting IDs of CMS page/blocks by GraphQL API 1. Set hard dependency --- app/code/Magento/CmsGraphQl/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/CmsGraphQl/composer.json b/app/code/Magento/CmsGraphQl/composer.json index 6a2e3950f93d0..bea7ee1356d80 100644 --- a/app/code/Magento/CmsGraphQl/composer.json +++ b/app/code/Magento/CmsGraphQl/composer.json @@ -6,6 +6,7 @@ "php": "~7.1.3||~7.2.0", "magento/framework": "*", "magento/module-cms": "*", + "magento/module-store": "*", "magento/module-widget": "*" }, "suggest": { From c025cc6ce9eab1ee9bedf78ccde6433d5598e16d Mon Sep 17 00:00:00 2001 From: Volodymyr Vygovskyi <v.vygovskyi@atwix.com> Date: Thu, 11 Apr 2019 17:35:03 +0300 Subject: [PATCH 037/224] refactored according to best practices --- ...minCMSPageMassActionDisableActionGroup.xml | 15 ++++++++ .../AdminNavigateToCMSPageGridActionGroup.xml | 13 +++++++ .../AdminSelectCMSPageInGridActionGroup.xml | 16 +++++++++ .../AssertCMSPageInGridActionGroup.xml | 19 +++++++--- ...ssertCMSPageNotFoundOnFrontActionGroup.xml | 18 ++++++++++ .../Mftf/Test/AdminCmsPageMassActionTest.xml | 36 ++++++++++--------- 6 files changed, 95 insertions(+), 22 deletions(-) create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionDisableActionGroup.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminNavigateToCMSPageGridActionGroup.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnFrontActionGroup.xml diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionDisableActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionDisableActionGroup.xml new file mode 100644 index 0000000000000..031dab84d6c37 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionDisableActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCMSPageMassActionDisable"> + <click selector="{{CmsPagesPageActionsSection.massActionsButton}}" stepKey="clickMassActionDropdown"/> + <click selector="{{CmsPagesPageActionsSection.massActionsOption('Disable')}}" stepKey="clickDisableAction"/> + <waitForPageLoad stepKey="waitForPageToReload"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminNavigateToCMSPageGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminNavigateToCMSPageGridActionGroup.xml new file mode 100644 index 0000000000000..8e9f4dc816c8a --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminNavigateToCMSPageGridActionGroup.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminNavigateToCMSPageGrid"> + <amOnPage url="{{CmsPagesPage.url}}" stepKey="navigateToCMSPagesGrid"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml new file mode 100644 index 0000000000000..b7525566c9eda --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminSelectCMSPageInGrid"> + <arguments> + <argument name="identifier" type="string"/> + </arguments> + <checkOption selector="{{CmsPagesPageActionsSection.pageRowCheckboxByIdentifier(identifier)}}" stepKey="selectCmsPageInGrid"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageInGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageInGridActionGroup.xml index 6b27234c9ad78..607e0676a0412 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageInGridActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageInGridActionGroup.xml @@ -7,10 +7,19 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertCMSPageInGrid" extends="navigateToCreatedCMSPage"> - <remove keyForRemoval="navigateToCreatedCMSPage"/> - <remove keyForRemoval="waitForPageLoad3"/> - <remove keyForRemoval="clickExpandContentTabForPage"/> - <remove keyForRemoval="waitForLoadingMaskOfStagingSection"/> + <actionGroup name="AssertCMSPageInGrid"> + <arguments> + <argument name="identifier" defaultValue=""/> + </arguments> + <amOnPage url="{{CmsPagesPage.url}}" stepKey="navigateToCMSPagesGrid"/> + <waitForPageLoad stepKey="waitForPageLoad1"/> + <conditionalClick selector="{{CmsPagesPageActionsSection.clearAllButton}}" dependentSelector="{{CmsPagesPageActionsSection.activeFilters}}" stepKey="clickToResetFilter" visible="true"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> + <conditionalClick selector="//div[contains(@data-role, 'grid-wrapper')]/table/thead/tr/th/span[contains(text(), 'ID')]" dependentSelector="//span[contains(text(), 'ID')]/parent::th[not(contains(@class, '_descend'))]/parent::tr/parent::thead/parent::table/parent::div[contains(@data-role, 'grid-wrapper')]" stepKey="clickToAttemptSortByIdDescending" visible="true"/> + <waitForLoadingMaskToDisappear stepKey="waitForFirstIdSortDescendingToFinish" /> + <!-- Conditional Click again in case it goes from default state to ascending on first click --> + <conditionalClick selector="//div[contains(@data-role, 'grid-wrapper')]/table/thead/tr/th/span[contains(text(), 'ID')]" dependentSelector="//span[contains(text(), 'ID')]/parent::th[not(contains(@class, '_descend'))]/parent::tr/parent::thead/parent::table/parent::div[contains(@data-role, 'grid-wrapper')]" stepKey="secondClickToAttemptSortByIdDescending" visible="true"/> + <waitForLoadingMaskToDisappear stepKey="waitForSecondIdSortDescendingToFinish" /> + <click selector="{{CmsPagesPageActionsSection.select(identifier)}}" stepKey="clickSelectCMSPage" /> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnFrontActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnFrontActionGroup.xml new file mode 100644 index 0000000000000..0938b5215cad2 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnFrontActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertCMSPageNotFoundOnFront"> + <arguments> + <argument name="identifier" type="string"/> + </arguments> + <amOnPage url="{{StorefrontHomePage.url}}/{{identifier}}" stepKey="amOnFirstPageOnFrontend"/> + <waitForPageLoad stepKey="waitForFirstPageLoadOnFrontend"/> + <see userInput="Whoops, our bad..." stepKey="seePageErrorForFirstPage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml index 3422bd562bde2..627c4331b0d57 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="CmsPageMassActionTest"> + <test name="AdminCmsPageMassActionTest"> <annotations> <features value="Cms"/> <title value="Create two CMS Pages and perform mass disable action"/> @@ -27,27 +27,29 @@ <actionGroup ref="logout" stepKey="logout"/> </after> <!--Go to Grid page--> - <amOnPage url="{{CmsPagesPage.url}}" stepKey="navigateToCMSPagesGrid"/> + <actionGroup ref="AdminNavigateToCMSPageGrid" stepKey="navigateToCMSPageGrid"/> <!--Select pages in Grid--> - <checkOption selector="{{CmsPagesPageActionsSection.pageRowCheckboxByIdentifier($$firstCMSPage.identifier$$)}}" stepKey="selectFirstPage"/> - <checkOption selector="{{CmsPagesPageActionsSection.pageRowCheckboxByIdentifier($$secondCMSPage.identifier$$)}}" stepKey="selectSecondPage"/> + <actionGroup ref="AdminSelectCMSPageInGrid" stepKey="selectFirstCMSPage"> + <argument name="identifier" value="$$firstCMSPage.identifier$$"/> + </actionGroup> + <actionGroup ref="AdminSelectCMSPageInGrid" stepKey="selectSecondCMSPage"> + <argument name="identifier" value="$$secondCMSPage.identifier$$"/> + </actionGroup> <!-- Disable Pages--> - <click selector="{{CmsPagesPageActionsSection.massActionsButton}}" stepKey="clickMassActionDropdown"/> - <click selector="{{CmsPagesPageActionsSection.massActionsOption('Disable')}}" stepKey="clickDisableAction"/> - <waitForPageLoad stepKey="waitForPageToReload"/> + <actionGroup ref="AdminCMSPageMassActionDisable" stepKey="disablePages"/> <!--Verify pages in Grid--> - <actionGroup ref="AssertCMSPageInGrid" stepKey="VerifyFirstPageinGrid"> - <argument name="CMSPage" value="$$firstCMSPage$$"/> + <actionGroup ref="AssertCMSPageInGrid" stepKey="verifyFirstPageinGrid"> + <argument name="identifier" value="$$firstCMSPage.identifier$$$$"/> </actionGroup> - <actionGroup ref="AssertCMSPageInGrid" stepKey="VerifySecondPageinGrid"> - <argument name="CMSPage" value="$$secondCMSPage$$"/> + <actionGroup ref="AssertCMSPageInGrid" stepKey="verifySecondPageinGrid"> + <argument name="identifier" value="$$secondCMSPage.identifier$$$$"/> </actionGroup> <!--Verify Pages are disabled on Frontend--> - <amOnPage url="{{StorefrontHomePage.url}}/{{$$firstCMSPage.identifier$$}}" stepKey="amOnFirstPageOnFrontend"/> - <waitForPageLoad stepKey="waitForFirstPageLoadOnFrontend"/> - <see userInput="Whoops, our bad..." stepKey="seePageErrorForFirstPage"/> - <amOnPage url="{{StorefrontHomePage.url}}/{{$$secondCMSPage.identifier$$}}" stepKey="amOnSecondPageOnFrontend"/> - <waitForPageLoad stepKey="waitForSecondPageLoadOnFrontend"/> - <see userInput="Whoops, our bad..." stepKey="seePageErrorForSecondPage"/> + <actionGroup ref="AssertCMSPageNotFoundOnFront" stepKey="checkFirstPageNotFoundOnFront"> + <argument name="identifier" value="$$firstCMSPage.identifier$$"/> + </actionGroup> + <actionGroup ref="AssertCMSPageNotFoundOnFront" stepKey="checkSecondPageNotFoundOnFront"> + <argument name="identifier" value="$$secondCMSPage.identifier$$"/> + </actionGroup> </test> </tests> \ No newline at end of file From 031ce1bd85d53cff2bc15fd614d0c98a368e4e60 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Thu, 11 Apr 2019 20:15:01 +0300 Subject: [PATCH 038/224] Refactoring --- .../AssertAdminNotSuccessLoginActionGroup.xml | 19 ++++++ .../Test/Mftf/Page/AdminNewRolePage.xml | 14 ---- ...eInvalidCurrentUserPasswordActionGroup.xml | 16 ----- .../Security/Test/Mftf/Data/AdminRoleData.xml | 14 ---- ...inLockAdminUserWhenCreatingNewRoleTest.xml | 64 +++++++++++++++++++ .../LockAdminUserWhenCreatingNewRoleTest.xml | 60 ----------------- ...minCreateRoleRequiredFieldsActionGroup.xml | 30 +++++++++ .../LockAdminUserWhenCreatingNewRoleTest.xml | 2 +- 8 files changed, 114 insertions(+), 105 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminNotSuccessLoginActionGroup.xml delete mode 100644 app/code/Magento/Backend/Test/Mftf/Page/AdminNewRolePage.xml delete mode 100644 app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewRoleInvalidCurrentUserPasswordActionGroup.xml delete mode 100644 app/code/Magento/Security/Test/Mftf/Data/AdminRoleData.xml create mode 100644 app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewRoleTest.xml delete mode 100644 app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewRoleTest.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateRoleRequiredFieldsActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminNotSuccessLoginActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminNotSuccessLoginActionGroup.xml new file mode 100644 index 0000000000000..f932924edbd72 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminNotSuccessLoginActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertAdminNotSuccessLoginActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later"/> + </arguments> + <waitForPageLoad stepKey="waitForPageReload"/> + <see selector="{{AdminLoginFormSection.error}}" userInput="{{message}}" + stepKey="seeLoginAdminError"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Page/AdminNewRolePage.xml b/app/code/Magento/Backend/Test/Mftf/Page/AdminNewRolePage.xml deleted file mode 100644 index a89eb272b11a1..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/Page/AdminNewRolePage.xml +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> - <page name="AdminNewRolePage" url="admin/user_role/editrole/" area="admin" module="Backend"> - <section name="AdminNewRoleSection"/> - </page> -</pages> diff --git a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewRoleInvalidCurrentUserPasswordActionGroup.xml b/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewRoleInvalidCurrentUserPasswordActionGroup.xml deleted file mode 100644 index a8ad1cabdad0c..0000000000000 --- a/app/code/Magento/Security/Test/Mftf/ActionGroup/AdminNewRoleInvalidCurrentUserPasswordActionGroup.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminNewRoleInvalidCurrentUserPasswordActionGroup"> - <fillField selector="{{AdminNewRoleSection.roleName}}" userInput="{{AdminRoleData.roleName}}" stepKey="fillRoleName"/> - <fillField selector="{{AdminNewRoleSection.currentPassword}}" userInput="PasswordINVALID" stepKey="fillCurrentUserPassword"/> - <click selector="{{AdminNewRoleSection.pageActionButton('Save Role')}}" stepKey="saveNewRole"/> - <waitForPageLoad stepKey="waitForSaveResultLoad"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Security/Test/Mftf/Data/AdminRoleData.xml b/app/code/Magento/Security/Test/Mftf/Data/AdminRoleData.xml deleted file mode 100644 index 88327fa5e94f7..0000000000000 --- a/app/code/Magento/Security/Test/Mftf/Data/AdminRoleData.xml +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> - <entity name="AdminRoleData" type="admin"> - <data key="roleName" unique="prefix">role</data> - </entity> -</entities> diff --git a/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewRoleTest.xml b/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewRoleTest.xml new file mode 100644 index 0000000000000..4839272a4aaa4 --- /dev/null +++ b/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewRoleTest.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminLockAdminUserWhenCreatingNewRoleTest"> + <annotations> + <features value="Security"/> + <stories value="Runs Lock admin user when creating new admin role test."/> + <title value="Lock admin user when creating new admin role"/> + <description value="Runs Lock admin user when creating new admin role test."/> + <severity value="MAJOR"/> + <group value="security"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Log in to Admin Panel --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!-- Unlock Admin user --> + <magentoCLI command="admin:user:unlock {{_ENV.MAGENTO_ADMIN_USERNAME}}" stepKey="unlockAdminUser"/> + </after> + <!-- Perform add new role 6 specified number of times. --> + <actionGroup ref="AdminCreateRoleRequiredFieldsActionGroup" stepKey="failedSaveRoleFirstAttempt"> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + </actionGroup> + <actionGroup ref="AdminCreateRoleRequiredFieldsActionGroup" stepKey="failedSaveRoleSecondAttempt"> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + </actionGroup> + <actionGroup ref="AdminCreateRoleRequiredFieldsActionGroup" stepKey="failedSaveRoleThirdAttempt"> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + </actionGroup> + <actionGroup ref="AdminCreateRoleRequiredFieldsActionGroup" stepKey="failedSaveRoleFourthAttempt"> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + </actionGroup> + <actionGroup ref="AdminCreateRoleRequiredFieldsActionGroup" stepKey="failedSaveRoleFifthAttempt"> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> + <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> + </actionGroup> + <actionGroup ref="AdminCreateRoleRequiredFieldsActionGroup" stepKey="failedSaveRoleSixthAttempt"> + <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> + <argument name="messageSelector" value="{{AdminLoginFormSection.error}}" /> + <argument name="message" value="Your account is temporarily disabled. Please try again later." /> + </actionGroup> + <!-- Try to login as admin and check error --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> + <actionGroup ref="AssertAdminNotSuccessLoginActionGroup" stepKey="checkLoginError"/> + </test> +</tests> diff --git a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewRoleTest.xml b/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewRoleTest.xml deleted file mode 100644 index db28e8365871f..0000000000000 --- a/app/code/Magento/Security/Test/Mftf/Test/LockAdminUserWhenCreatingNewRoleTest.xml +++ /dev/null @@ -1,60 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="LockAdminUserWhenCreatingNewRoleTest"> - <annotations> - <features value="Security"/> - <stories value="Runs Lock admin user when creating new admin role test."/> - <title value="Lock admin user when creating new admin role"/> - <description value="Runs Lock admin user when creating new admin role test."/> - <severity value="MAJOR"/> - <group value="security"/> - <group value="mtf_migrated"/> - </annotations> - <before> - <!-- Log in to Admin Panel --> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - </before> - <after> - <!-- Unlock Admin user --> - <magentoCLI command="admin:user:unlock {{_ENV.MAGENTO_ADMIN_USERNAME}}" stepKey="unlockAdminUser"/> - </after> - - <!-- Open Admin New Role Page --> - <amOnPage url="{{AdminNewRolePage.url}}" stepKey="amOnNewAdminRolePage"/> - <waitForPageLoad stepKey="waitForNewAdminRolePageLoad"/> - - <!-- Perform add new role 6 specified number of times. --> - <actionGroup ref="AdminNewRoleInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveRoleFirstAttempt"> - </actionGroup> - <see selector="{{AdminMessagesSection.error}}" userInput="The password entered for the current user is invalid. Verify the password and try again." - stepKey="seeInvalidPasswordError"/> - <actionGroup ref="AdminNewRoleInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveRoleSecondAttempt"> - </actionGroup> - <actionGroup ref="AdminNewRoleInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveRoleThirdAttempt"> - </actionGroup> - <actionGroup ref="AdminNewRoleInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveRoleFourthAttempt"> - </actionGroup> - <actionGroup ref="AdminNewRoleInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveRoleFifthAttempt"> - </actionGroup> - <actionGroup ref="AdminNewRoleInvalidCurrentUserPasswordActionGroup" stepKey="failedSaveRoleSixthAttempt"> - </actionGroup> - - <!-- Check Error that account has been locked --> - <waitForPageLoad stepKey="waitForSaveResultLoad"/> - <see selector="{{AdminLoginFormSection.error}}" userInput="Your account is temporarily disabled. Please try again later." stepKey="seeLockUserError"/> - - <!-- Try to login as admin and check error --> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> - <waitForPageLoad stepKey="waitForError"/> - <see selector="{{AdminLoginFormSection.error}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later" - stepKey="seeLoginAdminError"/> - </test> -</tests> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateRoleRequiredFieldsActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateRoleRequiredFieldsActionGroup.xml new file mode 100644 index 0000000000000..cb4a009b2e14a --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateRoleRequiredFieldsActionGroup.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminCreateRoleRequiredFieldsActionGroup"> + <arguments> + <argument name="roleName" type="string" defaultValue="{{adminRole.name}}"/> + <argument name="currentAdminPassword" type="string" defaultValue="{{_ENV.MAGENTO_ADMIN_PASSWORD}}"/> + <argument name="message" type="string" defaultValue="You saved the role." /> + <argument name="messageSelector" type="string" defaultValue="{{AdminMessagesSection.success}}" /> + </arguments> + + <!-- Open Admin New Role Page --> + <amOnPage url="{{AdminEditRolePage.url}}" stepKey="amOnNewAdminRolePage"/> + <waitForPageLoad stepKey="waitForNewAdminRolePageLoad"/> + + <!-- Fill required fields --> + <fillField selector="{{AdminCreateRoleSection.name}}" userInput="{{roleName}}" stepKey="fillRoleName"/> + <fillField selector="{{AdminCreateRoleSection.password}}" userInput="{{currentAdminPassword}}" stepKey="fillCurrentUserPassword"/> + <click selector="{{AdminCreateRoleSection.save}}" stepKey="saveNewRole"/> + <waitForPageLoad stepKey="waitForSaveResultLoad"/> + + <see userInput="{{message}}" selector="{{messageSelector}}" stepKey="verifyMessage" /> + </actionGroup> +</actionGroups> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.xml index 767f149946034..783321dc84e1c 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Security\Test\TestCase\LockAdminUserWhenCreatingNewRoleTest" summary="Lock admin user after entering incorrect password while creating new role"> <variation name="LockAdminUserWhenCreatingNewRoleTestVariation1"> - <data name="tag" xsi:type="string">severity:S2</data> + <data name="tag" xsi:type="string">severity:S2, mftf_migrated:yes</data> <data name="configData" xsi:type="string">user_lockout_failures</data> <data name="customAdmin/dataset" xsi:type="string">custom_admin_with_default_role</data> <data name="role/data/rolename" xsi:type="string">AdminRole%isolation%</data> From 61baafc5b9f6a395f51660dbb98b35699aa1e296 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Thu, 11 Apr 2019 20:24:01 +0300 Subject: [PATCH 039/224] Refactoring --- .../Test/Mftf/Section/AdminNewRoleSection.xml | 17 ----------------- .../LockAdminUserWhenCreatingNewRoleTest.xml | 1 - 2 files changed, 18 deletions(-) delete mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminNewRoleSection.xml diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminNewRoleSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminNewRoleSection.xml deleted file mode 100644 index 8d76cb78086eb..0000000000000 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminNewRoleSection.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> - <section name="AdminNewRoleSection"> - <element name="roleName" type="input" selector="#role_name"/> - <element name="currentPassword" type="input" selector="#current_password"/> - <element name="pageActionButton" type="button" selector="//div[contains(@class, 'page-actions-buttons')]//button[contains(., '{{button}}')]" - parameterized="true"/> - </section> -</sections> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.xml index 783321dc84e1c..0e4c33f7371e6 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockAdminUserWhenCreatingNewRoleTest.xml @@ -15,7 +15,6 @@ <data name="role/data/current_password" xsi:type="string">incorrect password</data> <data name="role/data/resource_access" xsi:type="string">All</data> <data name="attempts" xsi:type="string">4</data> - <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertUserIsLocked" /> </variation> </testCase> From c305e119e45bd05345f009bca8bfc5b8f16972cc Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Thu, 11 Apr 2019 22:12:53 +0300 Subject: [PATCH 040/224] Refactoring --- .../AssertMessageOnBackendActionGroup.xml | 18 ++++++++ .../Mftf/Section/AdminMessagesSection.xml | 1 + ...inLockAdminUserWhenCreatingNewRoleTest.xml | 46 +++++++++++-------- ...dminFillRoleRequiredFieldsActionGroup.xml} | 12 +---- .../AdminOpenCreateRolePageActionGroup.xml | 14 ++++++ .../ActionGroup/AssertSaveRoleActionGroup.xml | 14 ++++++ 6 files changed, 76 insertions(+), 29 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnBackendActionGroup.xml rename app/code/Magento/User/Test/Mftf/ActionGroup/{AdminCreateRoleRequiredFieldsActionGroup.xml => AdminFillRoleRequiredFieldsActionGroup.xml} (65%) create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenCreateRolePageActionGroup.xml create mode 100644 app/code/Magento/User/Test/Mftf/ActionGroup/AssertSaveRoleActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnBackendActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnBackendActionGroup.xml new file mode 100644 index 0000000000000..b75fcd47c61bd --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertMessageOnBackendActionGroup.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertMessageOnBackendActionGroup"> + <arguments> + <argument name="message" type="string" defaultValue="The password entered for the current user is invalid. Verify the password and try again." /> + <argument name="messageType" type="string" defaultValue="error" /> + </arguments> + <see userInput="{{message}}" selector="{{AdminMessagesSection.messageByType(messageType)}}" stepKey="verifyMessage" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminMessagesSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminMessagesSection.xml index 88e740d689cdd..be3ef92acf0ac 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminMessagesSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminMessagesSection.xml @@ -13,5 +13,6 @@ <element name="nthSuccess" type="text" selector=".message.message-success.success:nth-of-type({{n}})>div" parameterized="true"/> <element name="error" type="text" selector="#messages div.message-error"/> <element name="notice" type="text" selector=".message.message-notice.notice"/> + <element name="messageByType" type="text" selector="#messages div.message-{{messageType}}" parameterized="true" /> </section> </sections> diff --git a/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewRoleTest.xml b/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewRoleTest.xml index 4839272a4aaa4..b1070a233345f 100644 --- a/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewRoleTest.xml +++ b/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewRoleTest.xml @@ -27,36 +27,46 @@ <magentoCLI command="admin:user:unlock {{_ENV.MAGENTO_ADMIN_USERNAME}}" stepKey="unlockAdminUser"/> </after> <!-- Perform add new role 6 specified number of times. --> - <actionGroup ref="AdminCreateRoleRequiredFieldsActionGroup" stepKey="failedSaveRoleFirstAttempt"> + <actionGroup ref="AdminOpenCreateRolePageActionGroup" stepKey="openCreateRolePage"/> + + <actionGroup ref="AdminFillRoleRequiredFieldsActionGroup" stepKey="fillFieldFirstAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> - <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> </actionGroup> - <actionGroup ref="AdminCreateRoleRequiredFieldsActionGroup" stepKey="failedSaveRoleSecondAttempt"> + <actionGroup ref="AssertSaveRoleActionGroup" stepKey="saveRoleFirstAttempt"/> + <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkFirstSaveRoleError"/> + + <actionGroup ref="AdminFillRoleRequiredFieldsActionGroup" stepKey="fillFieldSecondAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> - <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> </actionGroup> - <actionGroup ref="AdminCreateRoleRequiredFieldsActionGroup" stepKey="failedSaveRoleThirdAttempt"> + <actionGroup ref="AssertSaveRoleActionGroup" stepKey="saveRoleSecondAttempt"/> + <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkSecondSaveRoleError"/> + + <actionGroup ref="AdminFillRoleRequiredFieldsActionGroup" stepKey="fillFieldThirdAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> - <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> </actionGroup> - <actionGroup ref="AdminCreateRoleRequiredFieldsActionGroup" stepKey="failedSaveRoleFourthAttempt"> + <actionGroup ref="AssertSaveRoleActionGroup" stepKey="saveRoleThirdAttempt"/> + <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkThirdSaveRoleError"/> + + <actionGroup ref="AdminFillRoleRequiredFieldsActionGroup" stepKey="fillFieldFourthAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> - <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> </actionGroup> - <actionGroup ref="AdminCreateRoleRequiredFieldsActionGroup" stepKey="failedSaveRoleFifthAttempt"> + <actionGroup ref="AssertSaveRoleActionGroup" stepKey="saveRoleFourthAttempt"/> + <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkFourthSaveRoleError"/> + + <actionGroup ref="AdminFillRoleRequiredFieldsActionGroup" stepKey="fillFieldFifthAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> - <argument name="messageSelector" value="{{AdminMessagesSection.error}}" /> - <argument name="message" value="The password entered for the current user is invalid. Verify the password and try again." /> </actionGroup> - <actionGroup ref="AdminCreateRoleRequiredFieldsActionGroup" stepKey="failedSaveRoleSixthAttempt"> + <actionGroup ref="AssertSaveRoleActionGroup" stepKey="saveRoleFifthAttempt"/> + <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkFifthSaveRoleError"/> + + <actionGroup ref="AdminFillRoleRequiredFieldsActionGroup" stepKey="fillFieldSixthAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> - <argument name="messageSelector" value="{{AdminLoginFormSection.error}}" /> - <argument name="message" value="Your account is temporarily disabled. Please try again later." /> </actionGroup> + <actionGroup ref="AssertSaveRoleActionGroup" stepKey="saveRoleSixthAttempt"/> + <actionGroup ref="AssertAdminNotSuccessLoginActionGroup" stepKey="checkFifthError"> + <argument name="message" value="Your account is temporarily disabled. Please try again later."/> + </actionGroup> + <!-- Try to login as admin and check error --> <actionGroup ref="LoginAsAdmin" stepKey="loginAsLockedAdmin"/> <actionGroup ref="AssertAdminNotSuccessLoginActionGroup" stepKey="checkLoginError"/> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateRoleRequiredFieldsActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillRoleRequiredFieldsActionGroup.xml similarity index 65% rename from app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateRoleRequiredFieldsActionGroup.xml rename to app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillRoleRequiredFieldsActionGroup.xml index cb4a009b2e14a..60fc560ed0a04 100644 --- a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminCreateRoleRequiredFieldsActionGroup.xml +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminFillRoleRequiredFieldsActionGroup.xml @@ -7,24 +7,14 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminCreateRoleRequiredFieldsActionGroup"> + <actionGroup name="AdminFillRoleRequiredFieldsActionGroup"> <arguments> <argument name="roleName" type="string" defaultValue="{{adminRole.name}}"/> <argument name="currentAdminPassword" type="string" defaultValue="{{_ENV.MAGENTO_ADMIN_PASSWORD}}"/> <argument name="message" type="string" defaultValue="You saved the role." /> <argument name="messageSelector" type="string" defaultValue="{{AdminMessagesSection.success}}" /> </arguments> - - <!-- Open Admin New Role Page --> - <amOnPage url="{{AdminEditRolePage.url}}" stepKey="amOnNewAdminRolePage"/> - <waitForPageLoad stepKey="waitForNewAdminRolePageLoad"/> - - <!-- Fill required fields --> <fillField selector="{{AdminCreateRoleSection.name}}" userInput="{{roleName}}" stepKey="fillRoleName"/> <fillField selector="{{AdminCreateRoleSection.password}}" userInput="{{currentAdminPassword}}" stepKey="fillCurrentUserPassword"/> - <click selector="{{AdminCreateRoleSection.save}}" stepKey="saveNewRole"/> - <waitForPageLoad stepKey="waitForSaveResultLoad"/> - - <see userInput="{{message}}" selector="{{messageSelector}}" stepKey="verifyMessage" /> </actionGroup> </actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenCreateRolePageActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenCreateRolePageActionGroup.xml new file mode 100644 index 0000000000000..4581449a321a4 --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminOpenCreateRolePageActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminOpenCreateRolePageActionGroup"> + <amOnPage url="{{AdminEditRolePage.url}}" stepKey="amOnNewAdminRolePage"/> + <waitForPageLoad stepKey="waitForNewAdminRolePageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AssertSaveRoleActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AssertSaveRoleActionGroup.xml new file mode 100644 index 0000000000000..8ce91e216a3ae --- /dev/null +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AssertSaveRoleActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertSaveRoleActionGroup"> + <click selector="{{AdminCreateRoleSection.save}}" stepKey="saveRole"/> + <waitForPageLoad stepKey="waitForSaveResultLoad"/> + </actionGroup> +</actionGroups> From ece60627af1b7950b1d837bea4872a0243025027 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Thu, 11 Apr 2019 14:25:25 -0500 Subject: [PATCH 041/224] MAGETWO-98801: Catalog cache gets flushed after Import --- app/code/Magento/Catalog/Block/Product/View.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Product/View.php b/app/code/Magento/Catalog/Block/Product/View.php index 8055d17a64a84..f3557a2b78853 100644 --- a/app/code/Magento/Catalog/Block/Product/View.php +++ b/app/code/Magento/Catalog/Block/Product/View.php @@ -323,10 +323,7 @@ public function getQuantityValidators() public function getIdentities() { $identities = $this->getProduct()->getIdentities(); - $category = $this->_coreRegistry->registry('current_category'); - if ($category) { - $identities[] = Category::CACHE_TAG . '_' . $category->getId(); - } + return $identities; } From 2bab0b463fe6a5254789047dc5a4645e31716baf Mon Sep 17 00:00:00 2001 From: Volodymyr Vygovskyi <v.vygovskyi@atwix.com> Date: Fri, 12 Apr 2019 14:32:26 +0300 Subject: [PATCH 042/224] refactoring, update action group names --- ...l => AdminCMSPageNavigateToGridActionGroup.xml} | 2 +- ...xml => AdminCMSPageSelectInGridActionGroup.xml} | 2 +- .../AssertCMSPageNotFoundOnFrontActionGroup.xml | 6 +++--- .../Test/Mftf/Test/AdminCmsPageMassActionTest.xml | 14 +++++++------- 4 files changed, 12 insertions(+), 12 deletions(-) rename app/code/Magento/Cms/Test/Mftf/ActionGroup/{AdminNavigateToCMSPageGridActionGroup.xml => AdminCMSPageNavigateToGridActionGroup.xml} (89%) rename app/code/Magento/Cms/Test/Mftf/ActionGroup/{AdminSelectCMSPageInGridActionGroup.xml => AdminCMSPageSelectInGridActionGroup.xml} (92%) diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminNavigateToCMSPageGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageNavigateToGridActionGroup.xml similarity index 89% rename from app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminNavigateToCMSPageGridActionGroup.xml rename to app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageNavigateToGridActionGroup.xml index 8e9f4dc816c8a..ad7af07201dd5 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminNavigateToCMSPageGridActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageNavigateToGridActionGroup.xml @@ -7,7 +7,7 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminNavigateToCMSPageGrid"> + <actionGroup name="AdminCMSPageNavigateToGrid"> <amOnPage url="{{CmsPagesPage.url}}" stepKey="navigateToCMSPagesGrid"/> </actionGroup> </actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageSelectInGridActionGroup.xml similarity index 92% rename from app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml rename to app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageSelectInGridActionGroup.xml index b7525566c9eda..cfe24fdd5b7c7 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageSelectInGridActionGroup.xml @@ -7,7 +7,7 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminSelectCMSPageInGrid"> + <actionGroup name="AdminCMSPageSelectInGrid"> <arguments> <argument name="identifier" type="string"/> </arguments> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnFrontActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnFrontActionGroup.xml index 0938b5215cad2..77a8a8884cabf 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnFrontActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnFrontActionGroup.xml @@ -11,8 +11,8 @@ <arguments> <argument name="identifier" type="string"/> </arguments> - <amOnPage url="{{StorefrontHomePage.url}}/{{identifier}}" stepKey="amOnFirstPageOnFrontend"/> - <waitForPageLoad stepKey="waitForFirstPageLoadOnFrontend"/> - <see userInput="Whoops, our bad..." stepKey="seePageErrorForFirstPage"/> + <amOnPage url="{{StorefrontHomePage.url}}/{{identifier}}" stepKey="amOnPageOnStorefront"/> + <waitForPageLoad stepKey="waitForPageLoadOnStorefront"/> + <see userInput="Whoops, our bad..." stepKey="seePageErrorNotFound"/> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml index 627c4331b0d57..04fb9d97a9175 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml @@ -27,22 +27,22 @@ <actionGroup ref="logout" stepKey="logout"/> </after> <!--Go to Grid page--> - <actionGroup ref="AdminNavigateToCMSPageGrid" stepKey="navigateToCMSPageGrid"/> + <actionGroup ref="AdminCMSPageNavigateToGrid" stepKey="navigateToCMSPageGrid"/> <!--Select pages in Grid--> - <actionGroup ref="AdminSelectCMSPageInGrid" stepKey="selectFirstCMSPage"> + <actionGroup ref="AdminCMSPageSelectInGrid" stepKey="selectFirstCMSPage"> <argument name="identifier" value="$$firstCMSPage.identifier$$"/> </actionGroup> - <actionGroup ref="AdminSelectCMSPageInGrid" stepKey="selectSecondCMSPage"> + <actionGroup ref="AdminCMSPageSelectInGrid" stepKey="selectSecondCMSPage"> <argument name="identifier" value="$$secondCMSPage.identifier$$"/> </actionGroup> <!-- Disable Pages--> <actionGroup ref="AdminCMSPageMassActionDisable" stepKey="disablePages"/> <!--Verify pages in Grid--> - <actionGroup ref="AssertCMSPageInGrid" stepKey="verifyFirstPageinGrid"> - <argument name="identifier" value="$$firstCMSPage.identifier$$$$"/> + <actionGroup ref="AssertCMSPageInGrid" stepKey="verifyFirstPageInGrid"> + <argument name="identifier" value="$$firstCMSPage.identifier$$"/> </actionGroup> - <actionGroup ref="AssertCMSPageInGrid" stepKey="verifySecondPageinGrid"> - <argument name="identifier" value="$$secondCMSPage.identifier$$$$"/> + <actionGroup ref="AssertCMSPageInGrid" stepKey="verifySecondPageInGrid"> + <argument name="identifier" value="$$secondCMSPage.identifier$$"/> </actionGroup> <!--Verify Pages are disabled on Frontend--> <actionGroup ref="AssertCMSPageNotFoundOnFront" stepKey="checkFirstPageNotFoundOnFront"> From 996cb1a70e25b663d8e3ee587649512fa3fa3139 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 12 Apr 2019 15:44:42 +0300 Subject: [PATCH 043/224] Fix static tests. --- app/code/Magento/Catalog/Model/Product/Option/Type/Select.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php b/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php index ca506fd451fb3..9c4a917926b59 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php @@ -10,6 +10,8 @@ /** * Catalog product option select type + * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ class Select extends \Magento\Catalog\Model\Product\Option\Type\DefaultType { From b98ba3ddb1ab7fc89380965e6631ffca62a3d8a2 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Fri, 12 Apr 2019 10:16:41 -0500 Subject: [PATCH 044/224] MAGETWO-98801: Catalog cache gets flushed after Import --- app/code/Magento/Catalog/Block/Product/View.php | 4 ++-- .../Magento/Catalog/Test/Unit/Block/Product/ViewTest.php | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Product/View.php b/app/code/Magento/Catalog/Block/Product/View.php index f3557a2b78853..8b53223de0b9f 100644 --- a/app/code/Magento/Catalog/Block/Product/View.php +++ b/app/code/Magento/Catalog/Block/Product/View.php @@ -169,8 +169,7 @@ public function getAddToCartUrl($product, $additional = []) } /** - * Get JSON encoded configuration array which can be used for JS dynamic - * price calculation depending on product options + * Get JSON encoded configuration which can be used for JS dynamic price calculation depending on product options * * @return string */ @@ -262,6 +261,7 @@ public function isStartCustomization() /** * Get default qty - either as preconfigured, or as 1. + * * Also restricts it by minimal qty. * * @param null|\Magento\Catalog\Model\Product $product diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/ViewTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/ViewTest.php index af208c016c7e3..bcb5540f14817 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Product/ViewTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/ViewTest.php @@ -65,24 +65,19 @@ public function testGetIdentities() { $productTags = ['cat_p_1']; $product = $this->createMock(\Magento\Catalog\Model\Product::class); - $category = $this->createMock(\Magento\Catalog\Model\Category::class); $product->expects($this->once()) ->method('getIdentities') ->will($this->returnValue($productTags)); - $category->expects($this->once()) - ->method('getId') - ->will($this->returnValue(1)); $this->registryMock->expects($this->any()) ->method('registry') ->will( $this->returnValueMap( [ ['product', $product], - ['current_category', $category], ] ) ); - $this->assertEquals(['cat_p_1', 'cat_c_1'], $this->view->getIdentities()); + $this->assertEquals($productTags, $this->view->getIdentities()); } } From b2976a75d44edd43849479cdaca1a88a142199f7 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Fri, 12 Apr 2019 10:54:13 -0500 Subject: [PATCH 045/224] MAGETWO-98801: Catalog cache gets flushed after Import --- .../Catalog/Test/Unit/Block/Product/ViewTest.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/ViewTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/ViewTest.php index bcb5540f14817..6563bdeb149e1 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Product/ViewTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/ViewTest.php @@ -8,6 +8,9 @@ namespace Magento\Catalog\Test\Unit\Block\Product; +/** + * Class ViewTest + */ class ViewTest extends \PHPUnit\Framework\TestCase { /** @@ -25,6 +28,9 @@ class ViewTest extends \PHPUnit\Framework\TestCase */ protected $registryMock; + /** + * @inheritDoc + */ protected function setUp() { $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -36,6 +42,9 @@ protected function setUp() ); } + /** + * @return void + */ public function testShouldRenderQuantity() { $productMock = $this->createMock(\Magento\Catalog\Model\Product::class); @@ -61,6 +70,9 @@ public function testShouldRenderQuantity() $this->assertEquals(false, $this->view->shouldRenderQuantity()); } + /** + * @return void + */ public function testGetIdentities() { $productTags = ['cat_p_1']; From ce6a31a9405ef5391d15ece15a91d302069aa7e1 Mon Sep 17 00:00:00 2001 From: Yurii Sapiha <yurasapiga93@gmail.com> Date: Sat, 13 Apr 2019 02:49:59 +0300 Subject: [PATCH 046/224] MAGETWO-99123: Shared catalog configurable product with out of stock options and instock options loads with empty drop down for non logged in customers --- .../Mftf/Data/CatalogInventoryConfigData.xml | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 app/code/Magento/CatalogInventory/Test/Mftf/Data/CatalogInventoryConfigData.xml diff --git a/app/code/Magento/CatalogInventory/Test/Mftf/Data/CatalogInventoryConfigData.xml b/app/code/Magento/CatalogInventory/Test/Mftf/Data/CatalogInventoryConfigData.xml new file mode 100644 index 0000000000000..e14c36446fc2b --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Mftf/Data/CatalogInventoryConfigData.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="StockOptionsDisplayOutOfStockProductsEnable"> + <data key="path">cataloginventory/options/show_out_of_stock</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="StockOptionsDisplayOutOfStockProductsDisable"> + <data key="path">cataloginventory/options/show_out_of_stock</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> +</entities> From f2e6fdd551645986a264dc369ae31f815edfe8ae Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Mon, 15 Apr 2019 18:08:31 -0500 Subject: [PATCH 047/224] MAGETWO-93522: Custom customer attributes don't show in admin unless they're configured to show on frontend --- .../Customer/Model/Customer/DataProvider.php | 36 +++---------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/app/code/Magento/Customer/Model/Customer/DataProvider.php b/app/code/Magento/Customer/Model/Customer/DataProvider.php index 5bad0a41aadc3..0b7c618e6a18b 100644 --- a/app/code/Magento/Customer/Model/Customer/DataProvider.php +++ b/app/code/Magento/Customer/Model/Customer/DataProvider.php @@ -307,45 +307,17 @@ protected function getAttributesMeta(Type $entityType) return $meta; } - /** - * Check whether the specific attribute can be shown in form: customer registration, customer edit, etc... - * - * @param Attribute $customerAttribute - * @return bool - */ - private function canShowAttributeInForm(AbstractAttribute $customerAttribute) - { - $isRegistration = $this->context->getRequestParam($this->getRequestFieldName()) === null; - - if ($customerAttribute->getEntityType()->getEntityTypeCode() === 'customer') { - return is_array($customerAttribute->getUsedInForms()) && - ( - (in_array('customer_account_create', $customerAttribute->getUsedInForms()) && $isRegistration) || - (in_array('customer_account_edit', $customerAttribute->getUsedInForms()) && !$isRegistration) - ); - } else { - return is_array($customerAttribute->getUsedInForms()) && - in_array('customer_address_edit', $customerAttribute->getUsedInForms()); - } - } - /** * Detect can we show attribute on specific form or not * * @param Attribute $customerAttribute * @return bool */ - private function canShowAttribute(AbstractAttribute $customerAttribute) + private function canShowAttribute(AbstractAttribute $customerAttribute): bool { - $userDefined = (bool) $customerAttribute->getIsUserDefined(); - if (!$userDefined) { - return $customerAttribute->getIsVisible(); - } - - $canShowOnForm = $this->canShowAttributeInForm($customerAttribute); - - return ($this->allowToShowHiddenAttributes && $canShowOnForm) || - (!$this->allowToShowHiddenAttributes && $canShowOnForm && $customerAttribute->getIsVisible()); + return $this->allowToShowHiddenAttributes && (bool) $customerAttribute->getIsUserDefined() + ? true + : (bool) $customerAttribute->getIsVisible(); } /** From d604aeaf166da2968db2e5ee01b26a0e102625d4 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Tue, 16 Apr 2019 09:16:17 +0300 Subject: [PATCH 048/224] MAGETWO-99152: Special Prices cannot save over 4 characters in Japanese Yen - The comma separator seems to be the issue --- .../Magento/Framework/Locale/Format.php | 31 ++++++++++++++++++- .../Framework/Locale/Test/Unit/FormatTest.php | 16 +++++++--- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/lib/internal/Magento/Framework/Locale/Format.php b/lib/internal/Magento/Framework/Locale/Format.php index adcffe01b910e..1daa6e9ff9ee4 100644 --- a/lib/internal/Magento/Framework/Locale/Format.php +++ b/lib/internal/Magento/Framework/Locale/Format.php @@ -25,6 +25,11 @@ class Format implements \Magento\Framework\Locale\FormatInterface */ protected $currencyFactory; + /** + * @var array + */ + private $groupSeparatorByLocale = []; + /** * @param \Magento\Framework\App\ScopeResolverInterface $scopeResolver * @param ResolverInterface $localeResolver @@ -81,7 +86,13 @@ public function getNumber($value) $value = str_replace(',', '', $value); } } elseif ($separatorComa !== false) { - $value = str_replace(',', '.', $value); + $locale = $this->_localeResolver->getLocale(); + $groupSeparator = $this->retrieveLocaleGroupSeparator($locale); + if ($groupSeparator === ',') { + $value = str_replace(',', '', $value); + } else { + $value = str_replace(',', '.', $value); + } } return (float)$value; @@ -149,4 +160,22 @@ public function getPriceFormat($localeCode = null, $currencyCode = null) return $result; } + + /** + * Retrieve group separator symbol by locale + * + * @param $locale string + * @return string + */ + private function retrieveLocaleGroupSeparator(string $locale): string + { + if (!array_key_exists($locale, $this->groupSeparatorByLocale)) { + $formatter = new \NumberFormatter($locale, \NumberFormatter::DECIMAL); + $this->groupSeparatorByLocale[$locale] = $formatter->getSymbol( + \NumberFormatter::GROUPING_SEPARATOR_SYMBOL + ); + } + + return $this->groupSeparatorByLocale[$locale]; + } } diff --git a/lib/internal/Magento/Framework/Locale/Test/Unit/FormatTest.php b/lib/internal/Magento/Framework/Locale/Test/Unit/FormatTest.php index 73a029a5a1411..659d9e495ce7e 100644 --- a/lib/internal/Magento/Framework/Locale/Test/Unit/FormatTest.php +++ b/lib/internal/Magento/Framework/Locale/Test/Unit/FormatTest.php @@ -103,10 +103,14 @@ public function getPriceFormatDataProvider(): array * * @param mixed $value * @param float $expected + * @param string $locale * @dataProvider provideNumbers */ - public function testGetNumber($value, $expected): void + public function testGetNumber(string $value, float $expected, string $locale = null): void { + if ($locale !== null) { + $this->localeResolver->method('getLocale')->willReturn($locale); + } $this->assertEquals($expected, $this->formatModel->getNumber($value)); } @@ -122,11 +126,15 @@ public function provideNumbers(): array ['12343', 12343], ['-9456km', -9456], ['0', 0], - ['2 054,10', 2054.1], - ['2046,45', 2046.45], + ['2 054,10', 205410, 'en_US'], + ['2 054,10', 2054.1, 'de_DE'], + ['2046,45', 204645, 'en_US'], + ['2046,45', 2046.45, 'de_DE'], ['2 054.52', 2054.52], - ['2,46 GB', 2.46], + ['2,46 GB', 246, 'en_US'], + ['2,46 GB', 2.46, 'de_DE'], ['2,054.00', 2054], + ['2,000', 2000, 'ja_JP'], ]; } } From 263588a28f1b529ce225f62cc87b4d4639614e39 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Tue, 16 Apr 2019 09:22:28 +0300 Subject: [PATCH 049/224] magento/graphql-ce#387: Test coverage of getting IDs of CMS page/blocks by GraphQL API --- .../Model/Resolver/DataProvider/Page.php | 54 ++------- .../DataProvider/PageDataProvider.php | 110 ++++++++++++++++++ .../CmsGraphQl/Model/Resolver/Page.php | 2 +- 3 files changed, 119 insertions(+), 47 deletions(-) create mode 100644 app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php index 0745296822c3c..e943ba0c2fd5e 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php @@ -8,21 +8,22 @@ namespace Magento\CmsGraphQl\Model\Resolver\DataProvider; use Magento\Cms\Api\Data\PageInterface; -use Magento\Cms\Api\GetPageByIdentifierInterface; use Magento\Cms\Api\PageRepositoryInterface; use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Store\Model\StoreManagerInterface; use Magento\Widget\Model\Template\FilterEmulate; /** + * @deprecated + * @see Magento\CmsGraphQl\Model\Resolver\DataProvider\PageDataProvider + * * Cms page data provider */ class Page { /** - * @var GetPageByIdentifierInterface + * @var FilterEmulate */ - private $pageByIdentifier; + private $widgetFilter; /** * @var PageRepositoryInterface @@ -30,30 +31,14 @@ class Page private $pageRepository; /** - * @var StoreManagerInterface - */ - private $storeManager; - - /** - * @var FilterEmulate - */ - private $widgetFilter; - - /** - * @param GetPageByIdentifierInterface $getPageByIdentifier - * @param FilterEmulate $widgetFilter * @param PageRepositoryInterface $pageRepository - * @param StoreManagerInterface $storeManager + * @param FilterEmulate $widgetFilter */ public function __construct( - GetPageByIdentifierInterface $getPageByIdentifier, - FilterEmulate $widgetFilter, PageRepositoryInterface $pageRepository, - StoreManagerInterface $storeManager + FilterEmulate $widgetFilter ) { - $this->pageByIdentifier = $getPageByIdentifier; $this->pageRepository = $pageRepository; - $this->storeManager = $storeManager; $this->widgetFilter = $widgetFilter; } @@ -62,32 +47,10 @@ public function __construct( * @return array * @throws NoSuchEntityException */ - public function getDataByPageId(int $pageId): array + public function getData(int $pageId): array { $page = $this->pageRepository->getById($pageId); - return $this->convertPageData($page); - } - - /** - * @param string $pageIdentifier - * @return array - */ - public function getDataByPageIdentifier(string $pageIdentifier): array - { - $storeId = (int)$this->storeManager->getStore()->getId(); - $page = $this->pageByIdentifier->execute($pageIdentifier, $storeId); - - return $this->convertPageData($page); - } - - /** - * @param PageInterface $page - * @return array - * @throws NoSuchEntityException - */ - private function convertPageData(PageInterface $page) - { if (false === $page->isActive()) { throw new NoSuchEntityException(); } @@ -96,7 +59,6 @@ private function convertPageData(PageInterface $page) $pageData = [ 'url_key' => $page->getIdentifier(), - PageInterface::PAGE_ID => $page->getId(), PageInterface::TITLE => $page->getTitle(), PageInterface::CONTENT => $renderedContent, PageInterface::CONTENT_HEADING => $page->getContentHeading(), diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php new file mode 100644 index 0000000000000..7391f736e95e6 --- /dev/null +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php @@ -0,0 +1,110 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\CmsGraphQl\Model\Resolver\DataProvider; + +use Magento\Cms\Api\Data\PageInterface; +use Magento\Cms\Api\GetPageByIdentifierInterface; +use Magento\Cms\Api\PageRepositoryInterface; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Widget\Model\Template\FilterEmulate; + +/** + * Cms page data provider + */ +class PageDataProvider +{ + /** + * @var GetPageByIdentifierInterface + */ + private $pageByIdentifier; + + /** + * @var PageRepositoryInterface + */ + private $pageRepository; + + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var FilterEmulate + */ + private $widgetFilter; + + /** + * @param GetPageByIdentifierInterface $getPageByIdentifier + * @param FilterEmulate $widgetFilter + * @param PageRepositoryInterface $pageRepository + * @param StoreManagerInterface $storeManager + */ + public function __construct( + GetPageByIdentifierInterface $getPageByIdentifier, + FilterEmulate $widgetFilter, + PageRepositoryInterface $pageRepository, + StoreManagerInterface $storeManager + ) { + $this->pageByIdentifier = $getPageByIdentifier; + $this->pageRepository = $pageRepository; + $this->storeManager = $storeManager; + $this->widgetFilter = $widgetFilter; + } + + /** + * @param int $pageId + * @return array + * @throws NoSuchEntityException + */ + public function getDataByPageId(int $pageId): array + { + $page = $this->pageRepository->getById($pageId); + + return $this->convertPageData($page); + } + + /** + * @param string $pageIdentifier + * @return array + */ + public function getDataByPageIdentifier(string $pageIdentifier): array + { + $storeId = (int)$this->storeManager->getStore()->getId(); + $page = $this->pageByIdentifier->execute($pageIdentifier, $storeId); + + return $this->convertPageData($page); + } + + /** + * @param PageInterface $page + * @return array + * @throws NoSuchEntityException + */ + private function convertPageData(PageInterface $page) + { + if (false === $page->isActive()) { + throw new NoSuchEntityException(); + } + + $renderedContent = $this->widgetFilter->filter($page->getContent()); + + $pageData = [ + 'url_key' => $page->getIdentifier(), + PageInterface::PAGE_ID => $page->getId(), + PageInterface::TITLE => $page->getTitle(), + PageInterface::CONTENT => $renderedContent, + PageInterface::CONTENT_HEADING => $page->getContentHeading(), + PageInterface::PAGE_LAYOUT => $page->getPageLayout(), + PageInterface::META_TITLE => $page->getMetaTitle(), + PageInterface::META_DESCRIPTION => $page->getMetaDescription(), + PageInterface::META_KEYWORDS => $page->getMetaKeywords(), + ]; + return $pageData; + } +} diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php index 41712889a1bfd..544a09c780070 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php @@ -7,7 +7,7 @@ namespace Magento\CmsGraphQl\Model\Resolver; -use Magento\CmsGraphQl\Model\Resolver\DataProvider\Page as PageDataProvider; +use Magento\CmsGraphQl\Model\Resolver\DataProvider\PageDataProvider as PageDataProvider; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Exception\GraphQlInputException; From 81984dc80fa1f436aecc752222efd588090d5a37 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Tue, 16 Apr 2019 09:32:51 +0300 Subject: [PATCH 050/224] magento/graphql-ce#387: Test coverage of getting IDs of CMS page/blocks by GraphQL API --- .../CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php | 1 + app/code/Magento/CmsGraphQl/etc/schema.graphqls | 1 + 2 files changed, 2 insertions(+) diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php index 7391f736e95e6..fdcd0c88cd60c 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php @@ -97,6 +97,7 @@ private function convertPageData(PageInterface $page) $pageData = [ 'url_key' => $page->getIdentifier(), PageInterface::PAGE_ID => $page->getId(), + PageInterface::IDENTIFIER => $page->getIdentifier(), PageInterface::TITLE => $page->getTitle(), PageInterface::CONTENT => $renderedContent, PageInterface::CONTENT_HEADING => $page->getContentHeading(), diff --git a/app/code/Magento/CmsGraphQl/etc/schema.graphqls b/app/code/Magento/CmsGraphQl/etc/schema.graphqls index 5504c42b339f9..8c0cb80f34269 100644 --- a/app/code/Magento/CmsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CmsGraphQl/etc/schema.graphqls @@ -22,6 +22,7 @@ type Query { type CmsPage @doc(description: "CMS page defines all CMS page information") { page_id: Int @doc(description: "Entity ID of CMS page") + identifier: String @doc(description: "Identifier of the CMS page") url_key: String @doc(description: "URL key of CMS page") title: String @doc(description: "CMS page title") content: String @doc(description: "CMS page content") From b8f2b4f9ce2b0f505e805ebc596f02a9d7501ac1 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Tue, 16 Apr 2019 10:35:41 +0300 Subject: [PATCH 051/224] MAGETWO-99152: Special Prices cannot save over 4 characters in Japanese Yen - The comma separator seems to be the issue --- lib/internal/Magento/Framework/Locale/Format.php | 2 +- lib/internal/Magento/Framework/Locale/Test/Unit/FormatTest.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Locale/Format.php b/lib/internal/Magento/Framework/Locale/Format.php index 1daa6e9ff9ee4..a66f14260c9cb 100644 --- a/lib/internal/Magento/Framework/Locale/Format.php +++ b/lib/internal/Magento/Framework/Locale/Format.php @@ -164,7 +164,7 @@ public function getPriceFormat($localeCode = null, $currencyCode = null) /** * Retrieve group separator symbol by locale * - * @param $locale string + * @param string $locale * @return string */ private function retrieveLocaleGroupSeparator(string $locale): string diff --git a/lib/internal/Magento/Framework/Locale/Test/Unit/FormatTest.php b/lib/internal/Magento/Framework/Locale/Test/Unit/FormatTest.php index 659d9e495ce7e..432b7fb3ce3d7 100644 --- a/lib/internal/Magento/Framework/Locale/Test/Unit/FormatTest.php +++ b/lib/internal/Magento/Framework/Locale/Test/Unit/FormatTest.php @@ -6,6 +6,9 @@ namespace Magento\Framework\Locale\Test\Unit; +/** + * Tests class for Number locale format + */ class FormatTest extends \PHPUnit\Framework\TestCase { /** From 89c00bde43a437f6c5e067d18735cbc6449e0ed1 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Tue, 16 Apr 2019 09:07:58 -0500 Subject: [PATCH 052/224] MAGETWO-93522: Custom customer attributes don't show in admin unless they're configured to show on frontend --- .../Unit/Model/Customer/DataProviderTest.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php b/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php index ac87e2e336e3d..3cbcbdf80b2a1 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Customer/DataProviderTest.php @@ -1087,16 +1087,15 @@ public function testGetDataWithVisibleAttributesWithAccountEdit() $meta = $dataProvider->getMeta(); $this->assertNotEmpty($meta); - $this->assertEquals($this->getExpectationForVisibleAttributes(false), $meta); + $this->assertEquals($this->getExpectationForVisibleAttributes(), $meta); } /** * Retrieve all customer variations of attributes with all variations of visibility * - * @param bool $isRegistration * @return array */ - private function getCustomerAttributeExpectations($isRegistration) + private function getCustomerAttributeExpectations() { return [ self::ATTRIBUTE_CODE . "_1" => [ @@ -1106,7 +1105,7 @@ private function getCustomerAttributeExpectations($isRegistration) 'dataType' => 'frontend_input', 'formElement' => 'frontend_input', 'options' => 'test-options', - 'visible' => !$isRegistration, + 'visible' => true, 'required' => 'is_required', 'label' => __('frontend_label'), 'sortOrder' => 'sort_order', @@ -1143,7 +1142,7 @@ private function getCustomerAttributeExpectations($isRegistration) 'config' => [ 'dataType' => 'frontend_input', 'formElement' => 'frontend_input', - 'visible' => $isRegistration, + 'visible' => true, 'required' => 'is_required', 'label' => __('frontend_label'), 'sortOrder' => 'sort_order', @@ -1166,7 +1165,7 @@ private function getCustomerAttributeExpectations($isRegistration) 'config' => [ 'dataType' => 'frontend_input', 'formElement' => 'frontend_input', - 'visible' => $isRegistration, + 'visible' => true, 'required' => 'is_required', 'label' => __('frontend_label'), 'sortOrder' => 'sort_order', @@ -1189,14 +1188,13 @@ private function getCustomerAttributeExpectations($isRegistration) /** * Retrieve all variations of attributes with all variations of visibility * - * @param bool $isRegistration * @return array */ - private function getExpectationForVisibleAttributes($isRegistration = true) + private function getExpectationForVisibleAttributes() { return [ 'customer' => [ - 'children' => $this->getCustomerAttributeExpectations($isRegistration), + 'children' => $this->getCustomerAttributeExpectations(), ], 'address' => [ 'children' => [ From 4bf89791ce1725c39ba2542bc2164d701eb4e6ce Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Wed, 17 Apr 2019 11:53:44 +0200 Subject: [PATCH 053/224] Refactoring. Use action groups and config data --- ...omerLoginInvalidCredentialsActionGroup.xml | 23 ------ ...rLoginFormWithWrongPasswordActionGroup.xml | 15 ++++ .../Test/Mftf/Data/CustomerConfigData.xml | 13 ++++ .../StorefrontLockCustomerOnLoginPageTest.xml | 78 +++++++++++++------ ...frontLoginWithIncorrectCredentialsTest.xml | 10 ++- .../TestCase/LockCustomerOnLoginPageTest.xml | 3 +- 6 files changed, 90 insertions(+), 52 deletions(-) delete mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLoginInvalidCredentialsActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillCustomerLoginFormWithWrongPasswordActionGroup.xml diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLoginInvalidCredentialsActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLoginInvalidCredentialsActionGroup.xml deleted file mode 100644 index 6a2d4d2aec2d5..0000000000000 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontCustomerLoginInvalidCredentialsActionGroup.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="StorefrontCustomerLoginInvalidCredentialsActionGroup"> - <arguments> - <argument name="customerEmail" type="string" /> - <argument name="customerPassword" type="string" /> - </arguments> - <amOnPage stepKey="amOnSignInPage" url="{{StorefrontCustomerSignInPage.url}}"/> - <fillField stepKey="fillEmail" userInput="{{customerEmail}}" selector="{{StorefrontCustomerSignInFormSection.emailField}}"/> - <fillField stepKey="fillPassword" userInput="{{customerPassword}}INVALID" selector="{{StorefrontCustomerSignInFormSection.passwordField}}"/> - <click stepKey="clickSignInAccountButton" selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}"/> - <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" stepKey="waitForFailMessage" /> - <see stepKey="seeErrorMessage" selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later."/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillCustomerLoginFormWithWrongPasswordActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillCustomerLoginFormWithWrongPasswordActionGroup.xml new file mode 100644 index 0000000000000..16d7fd197b52f --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontFillCustomerLoginFormWithWrongPasswordActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontFillCustomerLoginFormWithWrongPasswordActionGroup" extends="StorefrontFillCustomerLoginFormActionGroup"> + <remove keyForRemoval="fillPassword"/> + <fillField userInput="{{customer.password}}_INCORRECT" selector="{{StorefrontCustomerSignInFormSection.passwordField}}" stepKey="fillPassword"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerConfigData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerConfigData.xml index 11a47459ab7b3..870bd929eea9a 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerConfigData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerConfigData.xml @@ -28,4 +28,17 @@ <entity name="CustomerAccountSharingInherit" type="account_share_scope_inherit"> <data key="inherit">true</data> </entity> + <entity name="StorefrontCustomerLockoutFailuresDefaultConfigData"> + <!-- Magento default value --> + <data key="path">customer/password/lockout_failures</data> + <data key="scope_id">0</data> + <data key="label">10</data> + <data key="value">10</data> + </entity> + <entity name="StorefrontCustomerLockoutFailures5ConfigData"> + <data key="path">customer/password/lockout_failures</data> + <data key="scope_id">0</data> + <data key="label">5</data> + <data key="value">5</data> + </entity> </entities> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLockCustomerOnLoginPageTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLockCustomerOnLoginPageTest.xml index 6e8dd5f47d4e4..092800af43025 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLockCustomerOnLoginPageTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLockCustomerOnLoginPageTest.xml @@ -18,40 +18,72 @@ <group value="mtf_migrated"/> </annotations> <before> - <magentoCLI command="config:set customer/captcha/enable 0" stepKey="disableCaptcha"/> - <magentoCLI command="config:set customer/password/lockout_failures 5" stepKey="setInvalidAttemptsCount"/> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaDisableConfigData.path}} {{StorefrontCustomerCaptchaDisableConfigData.value}}" stepKey="disableCaptcha"/> + <magentoCLI command="config:set {{StorefrontCustomerLockoutFailures5ConfigData.path}} {{StorefrontCustomerLockoutFailures5ConfigData.value}}" stepKey="setInvalidAttemptsCountConfigTo5"/> <createData stepKey="customer" entity="Simple_US_Customer"/> </before> <after> + <magentoCLI command="config:set {{StorefrontCustomerCaptchaEnableConfigData.path}} {{StorefrontCustomerCaptchaEnableConfigData.value}}" stepKey="enableCaptcha"/> + <magentoCLI command="config:set {{StorefrontCustomerLockoutFailuresDefaultConfigData.path}} {{StorefrontCustomerLockoutFailuresDefaultConfigData.value}}" stepKey="revertInvalidAttemptsCountConfig"/> <deleteData stepKey="deleteCustomer" createDataKey="customer" /> </after> + + <actionGroup ref="StorefrontOpenCustomerLoginPageActionGroup" stepKey="goToSignInPage" /> + <!-- Perform 5 attempts to log in with invalid credentials --> - <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt1"> - <argument name="customerEmail" value="$$customer.email$$"/> - <argument name="customerPassword" value="$$customer.password$$"/> + <actionGroup ref="StorefrontFillCustomerLoginFormWithWrongPasswordActionGroup" stepKey="fillLoginFormFirstAttempt"> + <argument name="customer" value="$$customer$$"/> + </actionGroup> + <actionGroup ref="StorefrontClickSignOnCustomerLoginFormActionGroup" stepKey="clickSignInAccountButtonFirstAttempt"/> + <actionGroup ref="AssertMessageCustomerLoginActionGroup" stepKey="seeErrorMessageAfterFirstAttempt"> + <argument name="messageType" value="error"/> + <argument name="message" value="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later"/> + </actionGroup> + + <actionGroup ref="StorefrontFillCustomerLoginFormWithWrongPasswordActionGroup" stepKey="fillLoginFormSecondAttempt"> + <argument name="customer" value="$$customer$$"/> + </actionGroup> + <actionGroup ref="StorefrontClickSignOnCustomerLoginFormActionGroup" stepKey="clickSignInAccountButtonSecondAttempt"/> + <actionGroup ref="AssertMessageCustomerLoginActionGroup" stepKey="seeErrorMessageAfterSecondAttempt"> + <argument name="messageType" value="error"/> + <argument name="message" value="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later"/> + </actionGroup> + + <actionGroup ref="StorefrontFillCustomerLoginFormWithWrongPasswordActionGroup" stepKey="fillLoginFormThirdAttempt"> + <argument name="customer" value="$$customer$$"/> + </actionGroup> + <actionGroup ref="StorefrontClickSignOnCustomerLoginFormActionGroup" stepKey="clickSignInAccountButtonThirdAttempt"/> + <actionGroup ref="AssertMessageCustomerLoginActionGroup" stepKey="seeErrorMessageAfterThirdAttempt"> + <argument name="messageType" value="error"/> + <argument name="message" value="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later"/> </actionGroup> - <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt2"> - <argument name="customerEmail" value="$$customer.email$$"/> - <argument name="customerPassword" value="$$customer.password$$"/> + + <actionGroup ref="StorefrontFillCustomerLoginFormWithWrongPasswordActionGroup" stepKey="fillLoginFormFourthAttempt"> + <argument name="customer" value="$$customer$$"/> </actionGroup> - <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt3"> - <argument name="customerEmail" value="$$customer.email$$"/> - <argument name="customerPassword" value="$$customer.password$$"/> + <actionGroup ref="StorefrontClickSignOnCustomerLoginFormActionGroup" stepKey="clickSignInAccountButtonFourthAttempt"/> + <actionGroup ref="AssertMessageCustomerLoginActionGroup" stepKey="seeErrorMessageAfterFourthAttempt"> + <argument name="messageType" value="error"/> + <argument name="message" value="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later"/> </actionGroup> - <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt4"> - <argument name="customerEmail" value="$$customer.email$$"/> - <argument name="customerPassword" value="$$customer.password$$"/> + + <actionGroup ref="StorefrontFillCustomerLoginFormWithWrongPasswordActionGroup" stepKey="fillLoginFormFifthAttempt"> + <argument name="customer" value="$$customer$$"/> </actionGroup> - <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt5"> - <argument name="customerEmail" value="$$customer.email$$"/> - <argument name="customerPassword" value="$$customer.password$$"/> + <actionGroup ref="StorefrontClickSignOnCustomerLoginFormActionGroup" stepKey="clickSignInAccountButtonFifthAttempt"/> + <actionGroup ref="AssertMessageCustomerLoginActionGroup" stepKey="seeErrorMessageAfterFifthAttempt"> + <argument name="messageType" value="error"/> + <argument name="message" value="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later"/> </actionGroup> + <!-- Make sure that the customer is locked --> - <amOnPage stepKey="amOnSignInPage" url="{{StorefrontCustomerSignInPage.url}}"/> - <fillField stepKey="fillEmail" userInput="$$customer.email$$" selector="{{StorefrontCustomerSignInFormSection.emailField}}"/> - <fillField stepKey="fillPassword" userInput="$$customer.password$$" selector="{{StorefrontCustomerSignInFormSection.passwordField}}"/> - <click stepKey="clickSignInAccountButton" selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}"/> - <waitForElementVisible selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" stepKey="waitForFailMessage" /> - <see stepKey="seeErrorMessage" selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later."/> + <actionGroup ref="StorefrontFillCustomerLoginFormActionGroup" stepKey="fillLoginFormWithCorrectCredentials"> + <argument name="customer" value="$$customer$$"/> + </actionGroup> + <actionGroup ref="StorefrontClickSignOnCustomerLoginFormActionGroup" stepKey="clickSignInAccountButtonWithCorrectCredentials"/> + <actionGroup ref="AssertMessageCustomerLoginActionGroup" stepKey="seeLockoutErrorMessage"> + <argument name="messageType" value="error"/> + <argument name="message" value="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later."/> + </actionGroup> </test> </tests> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLoginWithIncorrectCredentialsTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLoginWithIncorrectCredentialsTest.xml index 228c23eac63e8..104b5d56314ba 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLoginWithIncorrectCredentialsTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLoginWithIncorrectCredentialsTest.xml @@ -25,9 +25,11 @@ <after> <deleteData stepKey="deleteCustomer" createDataKey="customer" /> </after> - <actionGroup ref="StorefrontCustomerLoginInvalidCredentialsActionGroup" stepKey="failedLoginAttempt"> - <argument name="customerEmail" value="$$customer.email$$"/> - <argument name="customerPassword" value="$$customer.password$$"/> - </actionGroup> + + <amOnPage stepKey="amOnSignInPage" url="{{StorefrontCustomerSignInPage.url}}"/> + <fillField stepKey="fillEmail" userInput="$$customer.email$$" selector="{{StorefrontCustomerSignInFormSection.emailField}}"/> + <fillField stepKey="fillPassword" userInput="$$customer.password$$INVALID" selector="{{StorefrontCustomerSignInFormSection.passwordField}}"/> + <click stepKey="clickSignInAccountButton" selector="{{StorefrontCustomerSignInFormSection.signInAccountButton}}"/> + <see stepKey="seeErrorMessage" selector="{{StorefrontCustomerLoginMessagesSection.errorMessage}}" userInput="The account sign-in was incorrect or your account is disabled temporarily. Please wait and try again later."/> </test> </tests> diff --git a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockCustomerOnLoginPageTest.xml b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockCustomerOnLoginPageTest.xml index 4a9c5d63b6808..07976ad01bd96 100644 --- a/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockCustomerOnLoginPageTest.xml +++ b/dev/tests/functional/tests/app/Magento/Security/Test/TestCase/LockCustomerOnLoginPageTest.xml @@ -8,12 +8,11 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Security\Test\TestCase\LockCustomerOnLoginPageTest" summary="Lock customer on login page"> <variation name="LockCustomerOnLoginPageTestVariation1"> - <data name="tag" xsi:type="string">severity:S1</data> + <data name="tag" xsi:type="string">severity:S1,mftf_migrated:yes</data> <data name="configData" xsi:type="string">customer_max_login_failures_number,captcha_storefront_disable</data> <data name="initialCustomer/dataset" xsi:type="string">default</data> <data name="incorrectPassword" xsi:type="string">incorrect password</data> <data name="attempts" xsi:type="string">6</data> - <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Security\Test\Constraint\AssertCustomerIsLocked" /> </variation> </testCase> From 85a0235882b8087eec52a5bce0392367121915ce Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Wed, 17 Apr 2019 12:29:40 +0200 Subject: [PATCH 054/224] Refactoring. Use action groups and config data --- .../SignUpNewUserFromStorefrontActionGroup.xml | 9 +-------- .../Customer/Test/Mftf/Data/CustomerData.xml | 3 --- .../StorefrontCreateExistingCustomerTest.xml | 16 ++++++++++------ 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml index ff5288531d9a4..2e2b1892774c0 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml @@ -154,11 +154,4 @@ <waitForPageLoad stepKey="waitForRegistered" after="clickCreateAccountButton"/> <remove keyForRemoval="seeThankYouMessage"/> </actionGroup> - - <actionGroup name="SignUpNewCustomerNoAssertions" extends="SignUpNewUserFromStorefrontActionGroup"> - <remove keyForRemoval="seeThankYouMessage"/> - <remove keyForRemoval="seeFirstName"/> - <remove keyForRemoval="seeLastName"/> - <remove keyForRemoval="seeEmail"/> - </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml index 54a5c03020ef7..06c23a2864984 100644 --- a/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml +++ b/app/code/Magento/Customer/Test/Mftf/Data/CustomerData.xml @@ -33,9 +33,6 @@ <data key="disable_auto_group_change">0</data> <!--requiredEntity type="extension_attribute">ExtensionAttributeSimple</requiredEntity--> </entity> - <entity name="CustomerEntityOneNotUniqueEmail" extends="CustomerEntityOne" type="customer"> - <data key="email">test@email.com</data> - </entity> <entity name="Simple_US_Customer" type="customer"> <data key="group_id">1</data> <data key="default_billing">true</data> diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateExistingCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateExistingCustomerTest.xml index 68f1e056138a5..323174777c265 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateExistingCustomerTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateExistingCustomerTest.xml @@ -17,16 +17,20 @@ <group value="mtf_migrated"/> </annotations> <before> - <createData stepKey="customer" entity="CustomerEntityOneNotUniqueEmail"/> + <createData entity="Simple_US_Customer" stepKey="customer"/> </before> <after> - <deleteData stepKey="deleteCustomer" createDataKey="customer" /> + <deleteData createDataKey="customer" stepKey="deleteCustomer"/> </after> - <actionGroup ref="SignUpNewCustomerNoAssertions" stepKey="SignUpNewUser"> - <argument name="Customer" value="CustomerEntityOneNotUniqueEmail"/> + <actionGroup ref="StorefrontOpenCustomerAccountCreatePageActionGroup" stepKey="openCreateAccountPage"/> + <actionGroup ref="StorefrontFillCustomerAccountCreationFormActionGroup" stepKey="fillCreateAccountForm"> + <argument name="customer" value="$$customer$$"/> + </actionGroup> + <actionGroup ref="StorefrontClickCreateAnAccountCustomerAccountCreationFormActionGroup" stepKey="submitCreateAccountForm"/> + <actionGroup ref="AssertMessageCustomerCreateAccountActionGroup" stepKey="seeErrorMessage"> + <argument name="messageType" value="error"/> + <argument name="message" value="There is already an account with this email address."/> </actionGroup> - <waitForElementVisible selector="{{StorefrontCustomerMessagesSection.errorMessage}}" stepKey="waitForErrorMessage" /> - <see stepKey="seeErrorMessage" userInput="There is already an account with this email address." selector="{{StorefrontCustomerMessagesSection.errorMessage}}"/> </test> </tests> From 6a8c89ba4a791bb32a82e77463ec0f4d1f7cfcf0 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 17 Apr 2019 16:27:07 +0300 Subject: [PATCH 055/224] graphQl-309: checkout agreements support multistore --- .../Model/Resolver/CheckoutAgreements.php | 2 +- .../DataProvider/CheckoutAgreements.php | 34 ++--- .../CheckoutAgreementsGraphQl/etc/module.xml | 6 +- .../etc/schema.graphqls | 2 +- .../Api/CheckoutAgreementsListTest.php | 124 ++++++++++++++++-- 5 files changed, 135 insertions(+), 33 deletions(-) diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php index 985c30182886a..7009e1e2d85e6 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php +++ b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php @@ -13,7 +13,7 @@ use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; /** - * CMS page field resolver, used for GraphQL request processing + * Checkout Agreements resolver, used for GraphQL request processing */ class CheckoutAgreements implements ResolverInterface { diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php index 2a8ac45ed65cc..c235d348375c5 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php +++ b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php @@ -7,9 +7,10 @@ namespace Magento\CheckoutAgreementsGraphQl\Model\Resolver\DataProvider; -use Magento\CheckoutAgreements\Api\CheckoutAgreementsListInterface; use Magento\CheckoutAgreements\Api\Data\AgreementInterface; -use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\CheckoutAgreements\Model\Agreement; +use Magento\CheckoutAgreements\Model\ResourceModel\Agreement\CollectionFactory; +use Magento\Store\Model\StoreManagerInterface; /** * Checkout Agreements data provider @@ -17,25 +18,25 @@ class CheckoutAgreements { /** - * @var SearchCriteriaBuilder + * @var CollectionFactory */ - private $searchCriteriaBuilder; + private $agreementCollectionFactory; /** - * @var CheckoutAgreementsListInterface + * @var StoreManagerInterface */ - private $checkoutAgreementsList; + private $storeManager; /** - * @param CheckoutAgreementsListInterface $checkoutAgreementsList - * @param SearchCriteriaBuilder $searchCriteriaBuilder + * @param CollectionFactory $agreementCollectionFactory + * @param StoreManagerInterface $storeManager */ public function __construct( - CheckoutAgreementsListInterface $checkoutAgreementsList, - SearchCriteriaBuilder $searchCriteriaBuilder + CollectionFactory $agreementCollectionFactory, + StoreManagerInterface $storeManager ) { - $this->checkoutAgreementsList = $checkoutAgreementsList; - $this->searchCriteriaBuilder = $searchCriteriaBuilder; + $this->agreementCollectionFactory = $agreementCollectionFactory; + $this->storeManager = $storeManager; } /** @@ -45,12 +46,13 @@ public function __construct( */ public function getData(): array { - $this->searchCriteriaBuilder->addFilter(AgreementInterface::IS_ACTIVE, true); - $searchCriteria = $this->searchCriteriaBuilder->create(); - $checkoutAgreements = $this->checkoutAgreementsList->getList($searchCriteria); + $agreementsCollection = $this->agreementCollectionFactory->create(); + $agreementsCollection->addStoreFilter($this->storeManager->getStore()->getId()); // TODO: store should be get from query context + $agreementsCollection->addFieldToFilter('is_active', 1); $checkoutAgreementData = []; - foreach ($checkoutAgreements as $checkoutAgreement) { + /** @var Agreement $checkoutAgreement */ + foreach ($agreementsCollection->getItems() as $checkoutAgreement) { $checkoutAgreementData[] = [ AgreementInterface::AGREEMENT_ID => $checkoutAgreement->getAgreementId(), AgreementInterface::CONTENT => $checkoutAgreement->getContent(), diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/etc/module.xml b/app/code/Magento/CheckoutAgreementsGraphQl/etc/module.xml index 55f09ccf7daee..d18e8ee17d097 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/etc/module.xml +++ b/app/code/Magento/CheckoutAgreementsGraphQl/etc/module.xml @@ -6,9 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> - <module name="Magento_CheckoutAgreementsGraphQl"> - <sequence> - <module name="Magento_GraphQl"/> - </sequence> - </module> + <module name="Magento_CheckoutAgreementsGraphQl" /> </config> diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls b/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls index 24bf75e2c379b..e63368bb3c884 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls @@ -2,7 +2,7 @@ # See COPYING.txt for license details. type Query { - checkoutAgreements: [CheckoutAgreement] @resolver(class: "Magento\\CheckoutAgreementsGraphQl\\Model\\Resolver\\CheckoutAgreements") @doc(description: "The Checkout Agreements query returns information about a Checkout Agreements") + checkoutAgreements: [CheckoutAgreement] @resolver(class: "Magento\\CheckoutAgreementsGraphQl\\Model\\Resolver\\CheckoutAgreements") @doc(description: "The Checkout Agreements information") } type CheckoutAgreement @doc(description: "Defines all Checkout Agreement information") { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php index 4b419d939c183..38498fb016f3c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php @@ -7,17 +7,111 @@ namespace Magento\GraphQl\CheckoutAgreements\Api; +use Magento\CheckoutAgreements\Api\Data\AgreementInterface; +use Magento\CheckoutAgreements\Model\Agreement as AgreementModel; +use Magento\CheckoutAgreements\Model\AgreementFactory; +use Magento\CheckoutAgreements\Model\ResourceModel\Agreement; +use Magento\Framework\ObjectManagerInterface; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; class CheckoutAgreementsListTest extends GraphQlAbstract { + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + protected function setUp() + { + parent::setUp(); + $this->objectManager = Bootstrap::getObjectManager(); + } + /** * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_active_with_html_content.php * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_inactive_with_text_content.php */ public function testGetActiveAgreement() { - $query = + $query = $this->getQuery(); + + $response = $this->graphQlQuery($query); + + $this->assertArrayHasKey('checkoutAgreements', $response); + $agreements = $response['checkoutAgreements']; + $this->assertCount(1, $agreements); + $this->assertEquals('Checkout Agreement (active)', $agreements[0]['name']); + $this->assertEquals('Checkout agreement content: <b>HTML</b>', $agreements[0]['content']); + $this->assertEquals('200px', $agreements[0]['content_height']); + $this->assertEquals('Checkout agreement checkbox text.', $agreements[0]['checkbox_text']); + $this->assertEquals(true, $agreements[0]['is_html']); + } + + /** + * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_active_with_html_content.php + * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_inactive_with_text_content.php + * @magentoApiDataFixture Magento/Store/_files/second_store.php + */ + public function testGetActiveAgreementOnSecondStore() + { + $secondStoreCode = 'fixture_second_store'; + $agreementsName = 'Checkout Agreement (active)'; + + $query = $this->getQuery(); + $this->assignAgreementsToStore($secondStoreCode, $agreementsName); + + $headerMap['Store'] = $secondStoreCode; + $response = $this->graphQlQuery($query, [], '', $headerMap); + + $this->assertArrayHasKey('checkoutAgreements', $response); + $agreements = $response['checkoutAgreements']; + $this->assertCount(1, $agreements); + $this->assertEquals($agreementsName, $agreements[0]['name']); + $this->assertEquals('Checkout agreement content: <b>HTML</b>', $agreements[0]['content']); + $this->assertEquals('200px', $agreements[0]['content_height']); + $this->assertEquals('Checkout agreement checkbox text.', $agreements[0]['checkbox_text']); + $this->assertEquals(true, $agreements[0]['is_html']); + } + + /** + * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_active_with_html_content.php + * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_inactive_with_text_content.php + * @magentoApiDataFixture Magento/Store/_files/second_store.php + */ + public function testGetActiveAgreementFromSecondStoreOnDefaultStore() + { + $secondStoreCode = 'fixture_second_store'; + $agreementsName = 'Checkout Agreement (active)'; + + $query = $this->getQuery(); + $this->assignAgreementsToStore($secondStoreCode, $agreementsName); + + $response = $this->graphQlQuery($query); + + $this->assertArrayHasKey('checkoutAgreements', $response); + $agreements = $response['checkoutAgreements']; + $this->assertCount(0, $agreements); + } + + public function testGetAgreementNotSet() + { + $query = $this->getQuery(); + + $response = $this->graphQlQuery($query); + + $this->assertArrayHasKey('checkoutAgreements', $response); + $agreements = $response['checkoutAgreements']; + $this->assertCount(0, $agreements); + } + + /** + * @return string + */ + private function getQuery(): string + { + return <<<QUERY { checkoutAgreements { @@ -30,15 +124,25 @@ public function testGetActiveAgreement() } } QUERY; + } - $response = $this->graphQlQuery($query); - $this->assertArrayHasKey('checkoutAgreements', $response); - $agreements = $response['checkoutAgreements']; - $this->assertEquals(1, count($agreements)); - $this->assertEquals('Checkout Agreement (active)', $agreements[0]['name']); - $this->assertEquals('Checkout agreement content: <b>HTML</b>', $agreements[0]['content']); - $this->assertEquals('200px', $agreements[0]['content_height']); - $this->assertEquals('Checkout agreement checkbox text.', $agreements[0]['checkbox_text']); - $this->assertEquals(true, $agreements[0]['is_html']); + /** + * @param string $storeCode + * @param string $agreementsName + * @return void + */ + private function assignAgreementsToStore(string $storeCode, string $agreementsName): void + { + $agreementsFactory = $this->objectManager->get(AgreementFactory::class); + /** @var Agreement $agreementsResource */ + $agreementsResource = $this->objectManager->get(Agreement::class); + /** @var StoreManagerInterface $storeManager */ + $storeManager = $this->objectManager->get(StoreManagerInterface::class); + $store = $storeManager->getStore($storeCode); + /** @var AgreementModel $agreements */ + $agreements = $agreementsFactory->create(); + $agreementsResource->load($agreements, $agreementsName, AgreementInterface::NAME); + $agreements->setData('stores', [$store->getId()]); + $agreementsResource->save($agreements); } } From 03cfa3706f6fb3c48a926f7ed8b19334bb1992f4 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Wed, 17 Apr 2019 17:12:38 +0300 Subject: [PATCH 056/224] Custom option type select - Allow modify list of single selection options type Make associative array as a default value in constructor --- app/code/Magento/Catalog/Model/Product/Option/Type/Select.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php b/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php index 9c4a917926b59..31e178f0bd9b4 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/Select.php @@ -58,8 +58,8 @@ public function __construct( parent::__construct($checkoutSession, $scopeConfig, $data); $this->singleSelectionTypes = $singleSelectionTypes ?: [ - \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_DROP_DOWN, - \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_RADIO, + 'drop_down' => \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_DROP_DOWN, + 'radio' => \Magento\Catalog\Api\Data\ProductCustomOptionInterface::OPTION_TYPE_RADIO, ]; } From f90a6201fa294844ac9a06daf3187bf0ae9c8224 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 17 Apr 2019 19:07:58 +0300 Subject: [PATCH 057/224] graphQl-309: checkout agreements support config --- .../DataProvider/CheckoutAgreements.php | 15 ++- .../Api/CheckoutAgreementsListTest.php | 91 +++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php index c235d348375c5..3dab845627261 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php +++ b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php @@ -10,6 +10,8 @@ use Magento\CheckoutAgreements\Api\Data\AgreementInterface; use Magento\CheckoutAgreements\Model\Agreement; use Magento\CheckoutAgreements\Model\ResourceModel\Agreement\CollectionFactory; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\ScopeInterface; use Magento\Store\Model\StoreManagerInterface; /** @@ -27,16 +29,24 @@ class CheckoutAgreements */ private $storeManager; + /** + * @var ScopeConfigInterface + */ + private $scopeConfig; + /** * @param CollectionFactory $agreementCollectionFactory * @param StoreManagerInterface $storeManager + * @param ScopeConfigInterface $scopeConfig */ public function __construct( CollectionFactory $agreementCollectionFactory, - StoreManagerInterface $storeManager + StoreManagerInterface $storeManager, + ScopeConfigInterface $scopeConfig ) { $this->agreementCollectionFactory = $agreementCollectionFactory; $this->storeManager = $storeManager; + $this->scopeConfig = $scopeConfig; } /** @@ -46,6 +56,9 @@ public function __construct( */ public function getData(): array { + if (!$this->scopeConfig->isSetFlag('checkout/options/enable_agreements', ScopeInterface::SCOPE_STORE)) { + return []; + } $agreementsCollection = $this->agreementCollectionFactory->create(); $agreementsCollection->addStoreFilter($this->storeManager->getStore()->getId()); // TODO: store should be get from query context $agreementsCollection->addFieldToFilter('is_active', 1); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php index 38498fb016f3c..17fa58be72fa2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php @@ -11,22 +11,37 @@ use Magento\CheckoutAgreements\Model\Agreement as AgreementModel; use Magento\CheckoutAgreements\Model\AgreementFactory; use Magento\CheckoutAgreements\Model\ResourceModel\Agreement; +use Magento\Config\Model\ResourceModel\Config; +use Magento\Framework\App\Config\ReinitableConfigInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\ObjectManagerInterface; +use Magento\Store\Api\Data\StoreInterface; +use Magento\Store\Model\ScopeInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; class CheckoutAgreementsListTest extends GraphQlAbstract { + private $agreementsXmlConfigPath = 'checkout/options/enable_agreements'; + /** * @var ObjectManagerInterface */ private $objectManager; + /** + * @var Config + */ + private $config; + protected function setUp() { parent::setUp(); + $this->objectManager = Bootstrap::getObjectManager(); + $this->config = $this->objectManager->get(Config::class); + $this->saveAgreementConfig(1); } /** @@ -106,6 +121,34 @@ public function testGetAgreementNotSet() $this->assertCount(0, $agreements); } + /** + * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_active_with_html_content.php + * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_inactive_with_text_content.php + * @magentoApiDataFixture Magento/Store/_files/second_store.php + */ + public function testDisabledAgreements() + { + $secondStoreCode = 'fixture_second_store'; + $agreementsName = 'Checkout Agreement (active)'; + + $query = $this->getQuery(); + $this->assignAgreementsToStore($secondStoreCode, $agreementsName); + + /** @var StoreManagerInterface $storeManager */ + $storeManager = $this->objectManager->get(StoreManagerInterface::class); + $store = $storeManager->getStore($secondStoreCode); + $this->saveAgreementConfig(0, $store); + + $headerMap['Store'] = $secondStoreCode; + $response = $this->graphQlQuery($query, [], '', $headerMap); + + $this->assertArrayHasKey('checkoutAgreements', $response); + $agreements = $response['checkoutAgreements']; + $this->assertCount(0, $agreements); + + $this->deleteAgreementConfig($store); + } + /** * @return string */ @@ -145,4 +188,52 @@ private function assignAgreementsToStore(string $storeCode, string $agreementsNa $agreements->setData('stores', [$store->getId()]); $agreementsResource->save($agreements); } + + protected function tearDown() + { + parent::tearDown(); + + $this->deleteAgreementConfig(); + } + + /** + * @param int $value + * @param StoreInterface $store + */ + private function saveAgreementConfig(int $value, ?StoreInterface $store = null): void + { + $scopeId = $store ? $store->getId() : 0; + $scope = $store ? ScopeInterface::SCOPE_STORE : ScopeConfigInterface::SCOPE_TYPE_DEFAULT; + $this->config->saveConfig( + $this->agreementsXmlConfigPath, + $value, + $scope, + $scopeId + ); + + $this->reinitConfig(); + } + + /** + * @param StoreInterface $store + */ + private function deleteAgreementConfig(?StoreInterface $store = null): void + { + $scopeId = $store ? $store->getId() : 0; + $scope = $store ? ScopeInterface::SCOPE_STORE : ScopeConfigInterface::SCOPE_TYPE_DEFAULT; + $this->config->deleteConfig( + $this->agreementsXmlConfigPath, + $scope, + $scopeId + ); + + $this->reinitConfig(); + } + + private function reinitConfig(): void + { + /** @var ReinitableConfigInterface $config */ + $config = $this->objectManager->get(ReinitableConfigInterface::class); + $config->reinit(); + } } From 0a64fbdb76c25563852ab2deb003d69681447b1c Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Wed, 17 Apr 2019 11:28:37 -0500 Subject: [PATCH 058/224] MAGETWO-93522: Custom customer attributes don't show in admin unless they're configured to show on frontend --- .../Customer/Model/Address/DataProvider.php | 4 +- .../Model/AttributeMetadataResolver.php | 43 ++----------------- .../DataProviderWithDefaultAddresses.php | 3 +- 3 files changed, 7 insertions(+), 43 deletions(-) diff --git a/app/code/Magento/Customer/Model/Address/DataProvider.php b/app/code/Magento/Customer/Model/Address/DataProvider.php index e1dd68207cae5..e7f9fce021709 100644 --- a/app/code/Magento/Customer/Model/Address/DataProvider.php +++ b/app/code/Magento/Customer/Model/Address/DataProvider.php @@ -19,6 +19,7 @@ /** * Dataprovider of customer addresses for customer address grid. + * * @property \Magento\Customer\Model\ResourceModel\Address\Collection $collection */ class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider @@ -222,8 +223,7 @@ private function getAttributesMeta(Type $entityType): array $meta[$attribute->getAttributeCode()] = $this->attributeMetadataResolver->getAttributesMeta( $attribute, $entityType, - $this->allowToShowHiddenAttributes, - $this->getRequestFieldName() + $this->allowToShowHiddenAttributes ); } $this->attributeMetadataResolver->processWebsiteMeta($meta); diff --git a/app/code/Magento/Customer/Model/AttributeMetadataResolver.php b/app/code/Magento/Customer/Model/AttributeMetadataResolver.php index c22cc9a4f23f4..979730eb1c9c2 100644 --- a/app/code/Magento/Customer/Model/AttributeMetadataResolver.php +++ b/app/code/Magento/Customer/Model/AttributeMetadataResolver.php @@ -101,15 +101,13 @@ public function __construct( * @param AbstractAttribute $attribute * @param Type $entityType * @param bool $allowToShowHiddenAttributes - * @param string $requestFieldName * @return array * @throws \Magento\Framework\Exception\LocalizedException */ public function getAttributesMeta( AbstractAttribute $attribute, Type $entityType, - bool $allowToShowHiddenAttributes, - string $requestFieldName + bool $allowToShowHiddenAttributes ): array { $meta = $this->modifyBooleanAttributeMeta($attribute); // use getDataUsingMethod, since some getters are defined and apply additional processing of returning value @@ -138,7 +136,6 @@ public function getAttributesMeta( $meta['arguments']['data']['config']['componentType'] = Field::NAME; $meta['arguments']['data']['config']['visible'] = $this->canShowAttribute( $attribute, - $requestFieldName, $allowToShowHiddenAttributes ); @@ -155,48 +152,16 @@ public function getAttributesMeta( * Detect can we show attribute on specific form or not * * @param AbstractAttribute $customerAttribute - * @param string $requestFieldName * @param bool $allowToShowHiddenAttributes * @return bool */ private function canShowAttribute( AbstractAttribute $customerAttribute, - string $requestFieldName, bool $allowToShowHiddenAttributes ) { - $userDefined = (bool)$customerAttribute->getIsUserDefined(); - if (!$userDefined) { - return $customerAttribute->getIsVisible(); - } - - $canShowOnForm = $this->canShowAttributeInForm($customerAttribute, $requestFieldName); - - return ($allowToShowHiddenAttributes && $canShowOnForm) || - (!$allowToShowHiddenAttributes && $canShowOnForm && $customerAttribute->getIsVisible()); - } - - /** - * Check whether the specific attribute can be shown in form: customer registration, customer edit, etc... - * - * @param AbstractAttribute $customerAttribute - * @param string $requestFieldName - * @return bool - */ - private function canShowAttributeInForm(AbstractAttribute $customerAttribute, string $requestFieldName): bool - { - $isRegistration = $this->context->getRequestParam($requestFieldName) === null; - - if ($customerAttribute->getEntityType()->getEntityTypeCode() === 'customer') { - return \is_array($customerAttribute->getUsedInForms()) && - ( - (\in_array('customer_account_create', $customerAttribute->getUsedInForms(), true) - && $isRegistration) || - (\in_array('customer_account_edit', $customerAttribute->getUsedInForms(), true) - && !$isRegistration) - ); - } - return \is_array($customerAttribute->getUsedInForms()) && - \in_array('customer_address_edit', $customerAttribute->getUsedInForms(), true); + return $allowToShowHiddenAttributes && (bool) $customerAttribute->getIsUserDefined() + ? true + : (bool) $customerAttribute->getIsVisible(); } /** diff --git a/app/code/Magento/Customer/Model/Customer/DataProviderWithDefaultAddresses.php b/app/code/Magento/Customer/Model/Customer/DataProviderWithDefaultAddresses.php index 4d1bb2e6b9e99..e72e53809c79e 100644 --- a/app/code/Magento/Customer/Model/Customer/DataProviderWithDefaultAddresses.php +++ b/app/code/Magento/Customer/Model/Customer/DataProviderWithDefaultAddresses.php @@ -189,8 +189,7 @@ private function getAttributesMeta(Type $entityType): array $meta[$attribute->getAttributeCode()] = $this->attributeMetadataResolver->getAttributesMeta( $attribute, $entityType, - $this->allowToShowHiddenAttributes, - $this->getRequestFieldName() + $this->allowToShowHiddenAttributes ); } $this->attributeMetadataResolver->processWebsiteMeta($meta); From 6b930331a8bc720d5e225f04a7aa25e5ed6ac01e Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 17 Apr 2019 21:43:54 +0300 Subject: [PATCH 059/224] graphQl-309: fixed tests --- composer.lock | 33 +++++++++++++++- .../Api/CheckoutAgreementsListTest.php | 39 +++++++------------ 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/composer.lock b/composer.lock index 8747ecc6d8d28..db753d6de6cff 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7d2484d86d4d31622f2427d46724ca6f", + "content-hash": "d5945e7c615def5bc906a9e876235934", "packages": [ { "name": "braintree/braintree_php", @@ -6618,6 +6618,36 @@ ], "time": "2018-02-14T22:37:14+00:00" }, + { + "name": "magento/magento-coding-standard", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/magento/magento-coding-standard.git", + "reference": "f7de26fb6add389d1b42286f67ee87424588a868" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/magento/magento-coding-standard/zipball/f7de26fb6add389d1b42286f67ee87424588a868", + "reference": "f7de26fb6add389d1b42286f67ee87424588a868", + "shasum": "" + }, + "require": { + "php": ">=5.6.0", + "squizlabs/php_codesniffer": "~3.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "description": "A set of Magento specific PHP CodeSniffer rules.", + "time": "2019-04-05T19:05:17+00:00" + }, { "name": "magento/magento2-functional-testing-framework", "version": "2.3.14", @@ -7842,6 +7872,7 @@ "mock", "xunit" ], + "abandoned": true, "time": "2018-08-09T05:50:03+00:00" }, { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php index 17fa58be72fa2..62491e5e8376b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php @@ -16,7 +16,6 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\ObjectManagerInterface; use Magento\Store\Api\Data\StoreInterface; -use Magento\Store\Model\ScopeInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -40,6 +39,8 @@ protected function setUp() parent::setUp(); $this->objectManager = Bootstrap::getObjectManager(); + + // TODO: remove usage of the Config, use ConfigFixture instead https://github.com/magento/graphql-ce/issues/167 $this->config = $this->objectManager->get(Config::class); $this->saveAgreementConfig(1); } @@ -124,29 +125,17 @@ public function testGetAgreementNotSet() /** * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_active_with_html_content.php * @magentoApiDataFixture Magento/CheckoutAgreements/_files/agreement_inactive_with_text_content.php - * @magentoApiDataFixture Magento/Store/_files/second_store.php */ public function testDisabledAgreements() { - $secondStoreCode = 'fixture_second_store'; - $agreementsName = 'Checkout Agreement (active)'; - $query = $this->getQuery(); - $this->assignAgreementsToStore($secondStoreCode, $agreementsName); + $this->saveAgreementConfig(0); - /** @var StoreManagerInterface $storeManager */ - $storeManager = $this->objectManager->get(StoreManagerInterface::class); - $store = $storeManager->getStore($secondStoreCode); - $this->saveAgreementConfig(0, $store); - - $headerMap['Store'] = $secondStoreCode; - $response = $this->graphQlQuery($query, [], '', $headerMap); + $response = $this->graphQlQuery($query); $this->assertArrayHasKey('checkoutAgreements', $response); $agreements = $response['checkoutAgreements']; $this->assertCount(0, $agreements); - - $this->deleteAgreementConfig($store); } /** @@ -200,31 +189,29 @@ protected function tearDown() * @param int $value * @param StoreInterface $store */ - private function saveAgreementConfig(int $value, ?StoreInterface $store = null): void + private function saveAgreementConfig(int $value): void { - $scopeId = $store ? $store->getId() : 0; - $scope = $store ? ScopeInterface::SCOPE_STORE : ScopeConfigInterface::SCOPE_TYPE_DEFAULT; $this->config->saveConfig( $this->agreementsXmlConfigPath, $value, - $scope, - $scopeId + ScopeConfigInterface::SCOPE_TYPE_DEFAULT, + 0 ); $this->reinitConfig(); } /** - * @param StoreInterface $store + * Delete config + * + * @return void */ - private function deleteAgreementConfig(?StoreInterface $store = null): void + private function deleteAgreementConfig(): void { - $scopeId = $store ? $store->getId() : 0; - $scope = $store ? ScopeInterface::SCOPE_STORE : ScopeConfigInterface::SCOPE_TYPE_DEFAULT; $this->config->deleteConfig( $this->agreementsXmlConfigPath, - $scope, - $scopeId + ScopeConfigInterface::SCOPE_TYPE_DEFAULT, + 0 ); $this->reinitConfig(); From cc5e2170467bb676e83e1fbad121f2ff51a7fb96 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Thu, 18 Apr 2019 08:38:20 +0300 Subject: [PATCH 060/224] graphQl-309: fixed dependency --- app/code/Magento/CheckoutAgreementsGraphQl/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/composer.json b/app/code/Magento/CheckoutAgreementsGraphQl/composer.json index b4196a3008e54..064e8f7c2ec94 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/composer.json +++ b/app/code/Magento/CheckoutAgreementsGraphQl/composer.json @@ -5,6 +5,7 @@ "require": { "php": "~7.1.3||~7.2.0", "magento/framework": "*", + "magento/module-store": "*", "magento/module-checkout-agreements": "*" }, "suggest": { From fa2a219fd38929bedfee3ace8bd5ed21ff0ad7bc Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Thu, 18 Apr 2019 11:53:11 +0300 Subject: [PATCH 061/224] MAGETWO-99152: Special Prices cannot save over 4 characters in Japanese Yen - The comma separator seems to be the issue --- .../Magento/Framework/Locale/Format.php | 42 ++++++------------- .../Framework/Locale/Test/Unit/FormatTest.php | 12 +++--- 2 files changed, 18 insertions(+), 36 deletions(-) diff --git a/lib/internal/Magento/Framework/Locale/Format.php b/lib/internal/Magento/Framework/Locale/Format.php index a66f14260c9cb..935586147b728 100644 --- a/lib/internal/Magento/Framework/Locale/Format.php +++ b/lib/internal/Magento/Framework/Locale/Format.php @@ -10,6 +10,11 @@ */ class Format implements \Magento\Framework\Locale\FormatInterface { + /** + * Japan locale code + */ + private const JAPAN_LOCALE_CODE = 'ja_JP'; + /** * @var \Magento\Framework\App\ScopeResolverInterface */ @@ -25,11 +30,6 @@ class Format implements \Magento\Framework\Locale\FormatInterface */ protected $currencyFactory; - /** - * @var array - */ - private $groupSeparatorByLocale = []; - /** * @param \Magento\Framework\App\ScopeResolverInterface $scopeResolver * @param ResolverInterface $localeResolver @@ -87,12 +87,14 @@ public function getNumber($value) } } elseif ($separatorComa !== false) { $locale = $this->_localeResolver->getLocale(); - $groupSeparator = $this->retrieveLocaleGroupSeparator($locale); - if ($groupSeparator === ',') { - $value = str_replace(',', '', $value); - } else { - $value = str_replace(',', '.', $value); - } + /** + * It's hard code for Japan locale. + * Comma separator uses as group separator: 4,000 saves as 4,000.00 + */ + $value = str_replace( + ',', + $locale === self::JAPAN_LOCALE_CODE ? '' : '.', + $value); } return (float)$value; @@ -160,22 +162,4 @@ public function getPriceFormat($localeCode = null, $currencyCode = null) return $result; } - - /** - * Retrieve group separator symbol by locale - * - * @param string $locale - * @return string - */ - private function retrieveLocaleGroupSeparator(string $locale): string - { - if (!array_key_exists($locale, $this->groupSeparatorByLocale)) { - $formatter = new \NumberFormatter($locale, \NumberFormatter::DECIMAL); - $this->groupSeparatorByLocale[$locale] = $formatter->getSymbol( - \NumberFormatter::GROUPING_SEPARATOR_SYMBOL - ); - } - - return $this->groupSeparatorByLocale[$locale]; - } } diff --git a/lib/internal/Magento/Framework/Locale/Test/Unit/FormatTest.php b/lib/internal/Magento/Framework/Locale/Test/Unit/FormatTest.php index 432b7fb3ce3d7..69ff02beb8d17 100644 --- a/lib/internal/Magento/Framework/Locale/Test/Unit/FormatTest.php +++ b/lib/internal/Magento/Framework/Locale/Test/Unit/FormatTest.php @@ -129,15 +129,13 @@ public function provideNumbers(): array ['12343', 12343], ['-9456km', -9456], ['0', 0], - ['2 054,10', 205410, 'en_US'], - ['2 054,10', 2054.1, 'de_DE'], - ['2046,45', 204645, 'en_US'], - ['2046,45', 2046.45, 'de_DE'], + ['2 054,10', 2054.1], + ['2046,45', 2046.45], ['2 054.52', 2054.52], - ['2,46 GB', 246, 'en_US'], - ['2,46 GB', 2.46, 'de_DE'], + ['2,46 GB', 2.46], ['2,054.00', 2054], - ['2,000', 2000, 'ja_JP'], + ['4,000', 4000.0, 'ja_JP'], + ['4,000', 4.0, 'en_US'], ]; } } From 6cda3a734e7d2377544b62af049d95534702ba9b Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Thu, 18 Apr 2019 13:17:41 +0300 Subject: [PATCH 062/224] MAGETWO-99152: Special Prices cannot save over 4 characters in Japanese Yen - The comma separator seems to be the issue --- lib/internal/Magento/Framework/Locale/Format.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Locale/Format.php b/lib/internal/Magento/Framework/Locale/Format.php index 935586147b728..934c9638c7392 100644 --- a/lib/internal/Magento/Framework/Locale/Format.php +++ b/lib/internal/Magento/Framework/Locale/Format.php @@ -94,7 +94,8 @@ public function getNumber($value) $value = str_replace( ',', $locale === self::JAPAN_LOCALE_CODE ? '' : '.', - $value); + $value + ); } return (float)$value; From 84f120f7a8f2ea5656fca4cc50643b4c812b6972 Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Thu, 18 Apr 2019 10:45:35 -0500 Subject: [PATCH 063/224] MQE-4431: Convert DeleteCatalogPriceRuleEntityTest to MFTF - Adding new Action Group. - Adding new Test data. - Renaming Test files. --- .../CatalogPriceRuleActionGroup.xml | 21 +++++++- .../Test/Mftf/Data/CatalogRuleData.xml | 18 +++++++ ...AdminDeleteCatalogPriceRuleEntityTest.xml} | 48 +++++++++++++------ 3 files changed, 72 insertions(+), 15 deletions(-) rename app/code/Magento/CatalogRule/Test/Mftf/Test/{DeleteCatalogPriceRuleEntityTest.xml => AdminDeleteCatalogPriceRuleEntityTest.xml} (85%) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml index 90f4f22bcf631..61e84ebdc4cf2 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml @@ -13,6 +13,7 @@ <arguments> <argument name="catalogRule" defaultValue="_defaultCatalogRule"/> </arguments> + <!-- Go to the admin Catalog rule grid and add a new one --> <amOnPage stepKey="goToPriceRulePage" url="{{CatalogRulePage.url}}"/> <waitForPageLoad stepKey="waitForPriceRulePage"/> @@ -36,7 +37,6 @@ <waitForPageLoad stepKey="waitForApplied"/> </actionGroup> - <actionGroup name="createCatalogPriceRule"> <arguments> <argument name="catalogRule" defaultValue="_defaultCatalogRule"/> @@ -53,6 +53,24 @@ <waitForPageLoad stepKey="waitForApplied"/> </actionGroup> + <actionGroup name="CreateCatalogPriceRuleViaTheUi"> + <arguments> + <argument name="catalogRule" defaultValue="_defaultCatalogRule"/> + </arguments> + + <fillField selector="{{AdminNewCatalogPriceRule.ruleName}}" userInput="{{catalogRule.name}}" stepKey="fillName1"/> + <fillField selector="{{AdminNewCatalogPriceRule.description}}" userInput="{{catalogRule.description}}" stepKey="fillDescription1"/> + <selectOption selector="{{AdminNewCatalogPriceRule.websites}}" userInput="{{catalogRule.website_ids[0]}}" stepKey="selectWebSite1"/> + <selectOption selector="{{AdminNewCatalogPriceRule.customerGroups}}" userInput="General" stepKey="selectCustomerGroup1"/> + <scrollTo selector="{{AdminNewCatalogPriceRule.actionsTab}}" stepKey="scrollToActionTab1"/> + <click selector="{{AdminNewCatalogPriceRule.actionsTab}}" stepKey="openActionDropdown1"/> + <selectOption selector="{{AdminNewCatalogPriceRuleActions.apply}}" userInput="{{catalogRule.simple_action}}" stepKey="discountType1"/> + <fillField selector="{{AdminNewCatalogPriceRuleActions.discountAmount}}" userInput="{{catalogRule.discount_amount}}" stepKey="fillDiscountValue1"/> + <selectOption selector="{{AdminNewCatalogPriceRuleActions.disregardRules}}" userInput="Yes" stepKey="discardSubsequentRules1"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + <scrollToTopOfPage stepKey="scrollToTop1"/> + </actionGroup> + <actionGroup name="CreateCatalogPriceRuleConditionWithAttribute"> <arguments> <argument name="attributeName" type="string"/> @@ -70,6 +88,7 @@ <click selector="{{AdminNewCatalogPriceRule.fromDateButton}}" stepKey="clickFromCalender"/> <click selector="{{AdminNewCatalogPriceRule.todayDate}}" stepKey="clickFromToday"/> </actionGroup> + <!-- Apply all of the saved catalog price rules --> <actionGroup name="applyCatalogPriceRules"> <amOnPage stepKey="goToPriceRulePage" url="{{CatalogRulePage.url}}"/> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml b/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml index 6ed71d6a5cf95..5c6ea970d3b7a 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Data/CatalogRuleData.xml @@ -139,4 +139,22 @@ <data key="simple_action">by_percent</data> <data key="discount_amount">10</data> </entity> + + <!-- DO NOT USE IN OTHER TESTS AS IT WILL BREAK THE EXISTING TESTS --> + <entity name="DeleteActiveCatalogPriceRuleWithConditions" type="catalogRule"> + <data key="name" unique="suffix">Delete Active Catalog Rule with conditions </data> + <data key="description">Rule Description</data> + <data key="is_active">1</data> + <array key="customer_group_ids"> + <item>0</item> + <item>1</item> + <item>2</item> + <item>3</item> + </array> + <array key="website_ids"> + <item>1</item> + </array> + <data key="simple_action">by_percent</data> + <data key="discount_amount">10</data> + </entity> </entities> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml similarity index 85% rename from app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml rename to app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml index 68206caae121a..14d8b7fe35df7 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/DeleteCatalogPriceRuleEntityTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml @@ -8,11 +8,11 @@ <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> - <test name="DeleteCatalogPriceRuleEntityTest1"> + <test name="AdminDeleteCatalogPriceRuleEntityFromSimpleProductTest"> <annotations> <stories value="Delete Catalog Price Rule"/> <title value="Delete Catalog Price Rule for Simple Product"/> - <description value="Assert that Catalog Price Rule is not applied for simple product"/> + <description value="Assert that Catalog Price Rule is not applied for simple product."/> <testCaseId value="MC-14073"/> <severity value="CRITICAL"/> <group value="CatalogRule"/> @@ -26,9 +26,18 @@ <requiredEntity createDataKey="createCategory1"/> </createData> - <createData entity="ActiveCatalogPriceRuleWithConditions" stepKey="createCatalogRule1"/> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> + + <amOnPage url="{{AdminNewCatalogPriceRulePage.url}}" stepKey="openNewCatalogPriceRulePage"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + + <actionGroup ref="CreateCatalogPriceRuleViaTheUi" stepKey="createCatalogPriceRuleViaTheUi1"> + <argument name="catalogRule" value="DeleteActiveCatalogPriceRuleWithConditions"/> + </actionGroup> + + <click selector="{{AdminNewCatalogPriceRule.save}}" stepKey="saveTheCatalogRule"/> + <waitForPageLoad stepKey="waitForPageToLoad3"/> + <see selector="{{AdminNewCatalogPriceRule.successMessage}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> </before> <after> <actionGroup ref="logout" stepKey="logoutOfAdmin1"/> @@ -42,7 +51,7 @@ <amOnPage url="{{CatalogRulePage.url}}" stepKey="goToPriceRulePage1"/> <waitForPageLoad stepKey="waitForPriceRulePage"/> <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule1"> - <argument name="name" value="$$createCatalogRule1.name$$"/> + <argument name="name" value="{{DeleteActiveCatalogPriceRuleWithConditions.name}}"/> <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> </actionGroup> <waitForPageLoad time="30" stepKey="waitForPageLoad1"/> @@ -54,6 +63,7 @@ <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="assertDataGridEmptyMessage1"/> <!-- reindex --> + <magentoCLI command="cache:flush" stepKey="flushCache1"/> <magentoCLI command="indexer:reindex" stepKey="reindex1"/> <!-- assert that the rule isn't present on the Category page --> @@ -81,7 +91,7 @@ <see selector="{{CheckoutCartProductSection.ProductRegularPriceByName($$createProduct1.name$$)}}" userInput="$$createProduct1.price$$" stepKey="seeCorrectProductPriceOnCheckout1"/> </test> - <test name="DeleteCatalogPriceRuleEntityTest2"> + <test name="AdminDeleteCatalogPriceRuleEntityFromConfigurableProductTest"> <annotations> <stories value="Delete Catalog Price Rule"/> <title value="Delete Catalog Price Rule for Configurable Product"/> @@ -94,7 +104,6 @@ <before> <createData entity="Simple_US_Customer" stepKey="createCustomer1"/> - <createData entity="ActiveCatalogPriceRuleWithConditions" stepKey="createCatalogRule1"/> <createData entity="SimpleSubCategory" stepKey="createCategory1"/> <!-- Create the configurable product based on the data in the /data folder --> @@ -147,6 +156,17 @@ </createData> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> + + <amOnPage url="{{AdminNewCatalogPriceRulePage.url}}" stepKey="openNewCatalogPriceRulePage"/> + <waitForPageLoad stepKey="waitForPageToLoad1"/> + + <actionGroup ref="CreateCatalogPriceRuleViaTheUi" stepKey="createCatalogPriceRuleViaTheUi1"> + <argument name="catalogRule" value="DeleteActiveCatalogPriceRuleWithConditions"/> + </actionGroup> + + <click selector="{{AdminNewCatalogPriceRule.save}}" stepKey="saveTheCatalogRule"/> + <waitForPageLoad stepKey="waitForPageToLoad3"/> + <see selector="{{AdminNewCatalogPriceRule.successMessage}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> </before> <after> <actionGroup ref="logout" stepKey="logoutOfAdmin1"/> @@ -163,37 +183,37 @@ <amOnPage url="{{CatalogRulePage.url}}" stepKey="goToPriceRulePage1"/> <waitForPageLoad stepKey="waitForPriceRulePage"/> <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule1"> - <argument name="name" value="$$createCatalogRule1.name$$"/> + <argument name="name" value="{{DeleteActiveCatalogPriceRuleWithConditions.name}}"/> <argument name="searchInput" value="{{AdminSecondaryGridSection.catalogRuleIdentifierSearch}}"/> </actionGroup> - - <!-- assert that the Success message is present after the delete --> + <waitForPageLoad time="30" stepKey="waitForPageLoad1"/> <see selector="{{AdminMessagesSection.successMessage}}" userInput="You deleted the rule." stepKey="seeDeletedRuleMessage1"/> <!-- assert that the Grid Empty message is present --> <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="assertDataGridEmptyMessage1"/> <!-- reindex --> + <magentoCLI command="cache:flush" stepKey="flushCache1"/> <magentoCLI command="indexer:reindex" stepKey="reindex1"/> <!-- assert that the rule isn't present on the Category page --> <amOnPage url="$$createCategory1.name$$.html" stepKey="goToStorefrontCategoryPage1"/> - <waitForPageLoad stepKey="waitForPageLoad1"/> + <waitForPageLoad stepKey="waitForPageLoad2"/> <see selector="{{StorefrontCategoryProductSection.ProductPriceByName($$createConfigProduct1.name$$)}}" userInput="$$createConfigChildProduct1.price$$" stepKey="seeRegularPriceText1"/> <!-- assert that the rule isn't present on the Product page --> <amOnPage url="{{StorefrontProductPage.url($$createConfigProduct1.custom_attributes[url_key]$$)}}" stepKey="goToStorefrontProductPage1"/> - <waitForPageLoad stepKey="waitForPageLoad2"/> + <waitForPageLoad stepKey="waitForPageLoad3"/> <dontSee selector="{{StorefrontProductInfoMainSection.oldPriceTag}}" userInput="Regular Price" stepKey="dontSeeRegularPriceText2"/> <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="$$createConfigChildProduct1.price$$" stepKey="seeTrueProductPrice1"/> <!-- assert that the rule isn't present in the Shopping Cart --> <selectOption selector="{{StorefrontProductInfoMainSection.productAttributeOptionsSelectButton}}" userInput="option1" stepKey="selectOption1"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addToCart1"/> - <waitForPageLoad time="30" stepKey="waitForPageLoad3"/> + <waitForPageLoad time="30" stepKey="waitForPageLoad4"/> <see selector="{{StorefrontMessagesSection.success}}" userInput="You added $$createConfigProduct1.name$ to your shopping cart." stepKey="seeAddToCartSuccessMessage"/> <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="openMiniShoppingCart1"/> - <waitForPageLoad time="30" stepKey="waitForPageLoad4"/> + <waitForPageLoad time="30" stepKey="waitForPageLoad5"/> <see selector="{{StorefrontMinicartSection.productPriceByName($$createConfigProduct1.name$$)}}" userInput="$$createConfigProduct1.price$$" stepKey="seeCorrectProductPrice1"/> </test> </tests> From 2b60b9fad8d06b47ef0dca54fa321cb35aab2f42 Mon Sep 17 00:00:00 2001 From: Sudhanshu Bajaj <sudhanshu.b@lsretail.com> Date: Fri, 19 Apr 2019 15:47:42 +0800 Subject: [PATCH 064/224] Store view specific labels cut in left navigation menu #22406 --- .../web/css/source/module/main/_store-scope.less | 2 +- app/design/adminhtml/Magento/backend/web/css/styles-old.less | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_store-scope.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_store-scope.less index 05e6350c88d8e..cd73d4955d176 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_store-scope.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_store-scope.less @@ -37,7 +37,7 @@ .store-scope { .admin__legend { .admin__field-tooltip { - margin-left: -@indent__base; + margin-left: 0; margin-top: .5rem; } } diff --git a/app/design/adminhtml/Magento/backend/web/css/styles-old.less b/app/design/adminhtml/Magento/backend/web/css/styles-old.less index 2dbe68ef96eec..50dd5c3a859e7 100644 --- a/app/design/adminhtml/Magento/backend/web/css/styles-old.less +++ b/app/design/adminhtml/Magento/backend/web/css/styles-old.less @@ -1366,7 +1366,7 @@ font-size: 14px; font-weight: 600; line-height: 3.2rem; - padding: 0 30px 0 0; + padding: 0 30px 0 30px; white-space: nowrap; word-wrap: break-word; From 04b0e5830c0bfc1952ac9ec7b23005e06f823f38 Mon Sep 17 00:00:00 2001 From: Mastiuhin Olexandr <mastiuhin.olexandr@transoftgroup.com> Date: Fri, 19 Apr 2019 20:13:27 +0300 Subject: [PATCH 065/224] MAGETWO-98187: [Magento Cloud] Grouped Products lose the associated SKUs after scheduled update expires --- .../AdminGroupedProductActionGroup.xml | 18 ++++++++++++++++++ ...resenceOnGroupedProductPageActionGroup.xml | 19 +++++++++++++++++++ .../AdminAddProductsToGroupPanelSection.xml | 1 + .../StorefrontProductInfoMainSection.xml | 14 ++++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 app/code/Magento/GroupedProduct/Test/Mftf/ActionGroup/AssertLinkPresenceOnGroupedProductPageActionGroup.xml create mode 100644 app/code/Magento/GroupedProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/ActionGroup/AdminGroupedProductActionGroup.xml b/app/code/Magento/GroupedProduct/Test/Mftf/ActionGroup/AdminGroupedProductActionGroup.xml index 9360ed6e42792..e246612bc6c99 100644 --- a/app/code/Magento/GroupedProduct/Test/Mftf/ActionGroup/AdminGroupedProductActionGroup.xml +++ b/app/code/Magento/GroupedProduct/Test/Mftf/ActionGroup/AdminGroupedProductActionGroup.xml @@ -52,4 +52,22 @@ </arguments> <fillField selector="{{AdminAddedProductsToGroupGrid.inputByProductName(productName)}}" userInput="{{qty}}" stepKey="fillDefaultQtyForLinkedProduct"/> </actionGroup> + + <!-- Assign Specified Product To Grouped Product --> + <!-- Assumes web client is on grouped product edit page --> + <actionGroup name="AdminAssignProductToGroup"> + <arguments> + <argument name="product"/> + </arguments> + + <scrollTo selector="{{AdminProductFormGroupedProductsSection.toggleGroupedProduct}}" x="0" y="-100" stepKey="scrollToGroupedSection"/> + <conditionalClick selector="{{AdminProductFormGroupedProductsSection.toggleGroupedProduct}}" dependentSelector="{{AdminProductFormGroupedProductsSection.addProductsToGroup}}" visible="false" stepKey="openGroupedProductsSection"/> + <click selector="{{AdminProductFormGroupedProductsSection.addProductsToGroup}}" stepKey="clickAddProductsToGroup"/> + <conditionalClick selector="{{AdminAddProductsToGroupPanel.clearFilters}}" dependentSelector="{{AdminAddProductsToGroupPanel.clearFilters}}" visible="true" stepKey="clearExistingFilters"/> + <click selector="{{AdminAddProductsToGroupPanel.filters}}" stepKey="showFiltersPanel"/> + <fillField userInput="{{product.name}}" selector="{{AdminAddProductsToGroupPanel.nameFilter}}" stepKey="fillNameFilter"/> + <click selector="{{AdminAddProductsToGroupPanel.applyFilters}}" stepKey="clickApplyFilters"/> + <click selector="{{AdminAddProductsToGroupPanel.firstCheckbox}}" stepKey="selectProduct"/> + <click selector="{{AdminAddProductsToGroupPanel.addSelectedProducts}}" stepKey="clickAddSelectedGroupProducts"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/ActionGroup/AssertLinkPresenceOnGroupedProductPageActionGroup.xml b/app/code/Magento/GroupedProduct/Test/Mftf/ActionGroup/AssertLinkPresenceOnGroupedProductPageActionGroup.xml new file mode 100644 index 0000000000000..bce78f8bf9961 --- /dev/null +++ b/app/code/Magento/GroupedProduct/Test/Mftf/ActionGroup/AssertLinkPresenceOnGroupedProductPageActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <!-- Check for the product link. --> + <!-- Assumes web client is on Grouped Product Page --> + <actionGroup name="AssertLinkPresenceOnGroupedProductPage"> + <arguments> + <argument name="productName" type="string"/> + </arguments> + <see selector="{{StorefrontProductInfoMainSection.groupedProductsTable}}" userInput="{{productName}}" stepKey="seeFirstStagedGroupedProduct"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Section/AdminAddProductsToGroupPanelSection.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Section/AdminAddProductsToGroupPanelSection.xml index e2c4286135d2e..f71bb49aea10a 100644 --- a/app/code/Magento/GroupedProduct/Test/Mftf/Section/AdminAddProductsToGroupPanelSection.xml +++ b/app/code/Magento/GroupedProduct/Test/Mftf/Section/AdminAddProductsToGroupPanelSection.xml @@ -15,6 +15,7 @@ <element name="nameFilter" type="input" selector=".product_form_product_form_grouped_grouped_products_modal [name='name']"/> <element name="firstCheckbox" type="input" selector="tr[data-repeat-index='0'] .admin__control-checkbox"/> <element name="nThCheckbox" type="input" selector="tr[data-repeat-index='{{n}}'] .admin__control-checkbox" parameterized="true"/> + <element name="clearFilters" type="button" selector=".product_form_product_form_grouped_grouped_products_modal [data-action='grid-filter-reset']" timeout="30"/> </section> <section name="AdminAddedProductsToGroupGrid"> diff --git a/app/code/Magento/GroupedProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml b/app/code/Magento/GroupedProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml new file mode 100644 index 0000000000000..45d8e63343734 --- /dev/null +++ b/app/code/Magento/GroupedProduct/Test/Mftf/Section/StorefrontProductInfoMainSection.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontProductInfoMainSection"> + <element name="groupedProductsTable" type="text" selector="#super-product-table .product-item-name"/> + </section> +</sections> From bd8928e6c8f4ba1a92308a700a6d864b7de455af Mon Sep 17 00:00:00 2001 From: Roman Zhupanyn <roma.dj.elf@gmail.com> Date: Mon, 22 Apr 2019 14:37:33 +0300 Subject: [PATCH 066/224] MAGETWO-98256: Restricted admin user cannot assess mass update actions --- .../Test/Mftf/Section/AdminEditProductAttributesSection.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminEditProductAttributesSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminEditProductAttributesSection.xml index 63bdcd52cdd20..b243fbfd6034a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminEditProductAttributesSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminEditProductAttributesSection.xml @@ -21,5 +21,6 @@ <element name="ProductDataMayBeLostModal" type="button" selector="//aside[contains(@class,'_show')]//header[contains(.,'Product data may be lost')]"/> <element name="ProductDataMayBeLostConfirmButton" type="button" selector="//aside[contains(@class,'_show')]//button[.='Change Input Type']"/> <element name="defaultLabel" type="text" selector="//td[contains(text(), '{{attributeName}}')]/following-sibling::td[contains(@class, 'col-frontend_label')]" parameterized="true"/> + <element name="formByStoreId" type="block" selector="//form[contains(@action,'store/{{store_id}}')]" parameterized="true"/> </section> </sections> From 2f2ee2a076c111563e86192077dd3246eb385508 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Mon, 22 Apr 2019 10:23:20 -0500 Subject: [PATCH 067/224] MC-11063: Add Product to Cart, Backorder Allowed --- .../Mftf/Data/CatalogInventoryConfigData.xml | 33 ++++++++++++ .../Catalog/Test/Mftf/Data/ProductData.xml | 12 +++++ .../Data/ProductExtensionAttributeData.xml | 3 ++ .../Catalog/Test/Mftf/Data/StockItemData.xml | 4 ++ ...inBackorderAllowedAddProductToCartTest.xml | 52 +++++++++++++++++++ 5 files changed, 104 insertions(+) create mode 100644 app/code/Magento/Catalog/Test/Mftf/Data/CatalogInventoryConfigData.xml create mode 100644 app/code/Magento/Catalog/Test/Mftf/Test/AdminBackorderAllowedAddProductToCartTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/CatalogInventoryConfigData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/CatalogInventoryConfigData.xml new file mode 100644 index 0000000000000..c9b67e0db4398 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Data/CatalogInventoryConfigData.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="CatalogInventoryOptionsShowOutOfStockEnable"> + <data key="path">cataloginventory/options/show_out_of_stock</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="CatalogInventoryOptionsShowOutOfStockDisable"> + <!-- Magento default value --> + <data key="path">cataloginventory/options/show_out_of_stock</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="CatalogInventoryItemOptionsBackordersEnable"> + <data key="path">cataloginventory/item_options/backorders</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="CatalogInventoryItemOptionsBackordersDisable"> + <!-- Magento default value --> + <data key="path">cataloginventory/item_options/backorders</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> +</entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml index fcfca073cb484..5ac1c0e90062f 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml @@ -153,6 +153,18 @@ <data key="status">1</data> <data key="quantity">0</data> </entity> + <entity name="SimpleProductInStockQuantityZero" type="product"> + <data key="sku" unique="suffix">testSku</data> + <data key="type_id">simple</data> + <data key="attribute_set_id">4</data> + <data key="visibility">4</data> + <data key="name" unique="suffix">SimpleProductInStockQuantityZero</data> + <data key="price">123.00</data> + <data key="urlKey" unique="suffix">SimpleProductInStockQuantityZero</data> + <data key="status">1</data> + <data key="quantity">0</data> + <requiredEntity type="product_extension_attribute">EavStock0</requiredEntity> + </entity> <!-- Simple Product Disabled --> <entity name="SimpleProductOffline" type="product2"> <data key="sku" unique="suffix">testSku</data> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductExtensionAttributeData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductExtensionAttributeData.xml index e9e9e43752365..c507c6c08da0a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductExtensionAttributeData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductExtensionAttributeData.xml @@ -20,4 +20,7 @@ <entity name="EavStock1" type="product_extension_attribute"> <requiredEntity type="stock_item">Qty_1</requiredEntity> </entity> + <entity name="EavStock0" type="product_extension_attribute"> + <requiredEntity type="stock_item">Qty_0</requiredEntity> + </entity> </entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/StockItemData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/StockItemData.xml index 7cba4c3c76fe9..4372867268f54 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Data/StockItemData.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Data/StockItemData.xml @@ -32,4 +32,8 @@ <data key="qty">1</data> <data key="is_in_stock">true</data> </entity> + <entity name="Qty_0" type="stock_item"> + <data key="qty">0</data> + <data key="is_in_stock">true</data> + </entity> </entities> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminBackorderAllowedAddProductToCartTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminBackorderAllowedAddProductToCartTest.xml new file mode 100644 index 0000000000000..9d8839621a0e3 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminBackorderAllowedAddProductToCartTest.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminBackorderAllowedAddProductToCartTest"> + <annotations> + <stories value="Manage products"/> + <title value="Add Product to Cart, Backorder Allowed"/> + <description value="Customer should be able to add products to cart when that products quantity is zero"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-11063"/> + <group value="mtf_migrated"/> + </annotations> + + <before> + <!-- Create a product that is "In Stock" but has quantity zero --> + <createData entity="SimpleProductInStockQuantityZero" stepKey="createProduct"/> + + <!-- Configure Magento to show out of stock products and to allow backorders --> + <magentoCLI command="config:set {{CatalogInventoryOptionsShowOutOfStockEnable.path}} {{CatalogInventoryOptionsShowOutOfStockEnable.value}}" stepKey="setConfigShowOutOfStockTrue"/> + <magentoCLI command="config:set {{CatalogInventoryItemOptionsBackordersEnable.path}} {{CatalogInventoryItemOptionsBackordersEnable.value}}" stepKey="setConfigAllowBackordersTrue"/> + </before> + + <after> + <!-- Set Magento back to default configuration --> + <magentoCLI command="config:set {{CatalogInventoryOptionsShowOutOfStockDisable.path}} {{CatalogInventoryOptionsShowOutOfStockDisable.value}}" stepKey="setConfigShowOutOfStockFalse"/> + <magentoCLI command="config:set {{CatalogInventoryItemOptionsBackordersDisable.path}} {{CatalogInventoryItemOptionsBackordersDisable.value}}" stepKey="setConfigAllowBackordersFalse"/> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + </after> + + <!-- Go to the storefront and add the product to the cart --> + <actionGroup ref="AddSimpleProductToCart" stepKey="gotoAndAddProductToCart"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + + <!-- Go to the cart page and verify we see the product --> + <amOnPage url="{{CheckoutCartPage.url}}" stepKey="gotoCart"/> + <waitForPageLoad stepKey="waitForCartLoad"/> + <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertProductItemInCheckOutCart"> + <argument name="productName" value="$$createProduct.name$$"/> + <argument name="productPrice" value="$$createProduct.price$$"/> + <argument name="subtotal" value="$$createProduct.price$$" /> + <argument name="qty" value="1"/> + </actionGroup> + </test> +</tests> From 86b7d1c346c49db184e65344dea4666f620814fb Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Tue, 23 Apr 2019 10:26:37 -0500 Subject: [PATCH 068/224] MC-4760: Convert CreateInvoiceEntityTest to MFTF --- ...tOrderGraphImageOnDashboardActionGroup.xml | 15 ++ .../Test/Mftf/Page/AdminDashboardPage.xml | 1 + .../Mftf/Section/AdminDashboardSection.xml | 15 ++ .../StorefrontCustomerOrderSection.xml | 1 + .../Mftf/Data/PaymentMethodConfigData.xml | 47 +++++ .../AdminApplyCouponToOrderActionGroup.xml | 20 ++ .../ActionGroup/AdminInvoiceActionGroup.xml | 7 + .../ActionGroup/AdminOrderActionGroup.xml | 30 +++ .../AdminSubmitOrderActionGroup.xml | 15 ++ ...FilterShipmentGridByOrderIdActionGroup.xml | 21 +++ .../Sales/Test/Mftf/Data/ConfigData.xml | 23 +++ .../Test/Mftf/Page/AdminInvoicesPage.xml | 1 + .../Test/Mftf/Page/AdminShipmentPage.xml | 14 ++ .../Mftf/Section/AdminInvoiceTotalSection.xml | 4 + .../Mftf/Section/AdminInvoicesGridSection.xml | 1 + .../AdminOrderDetailsMainActionsSection.xml | 4 + .../Section/AdminOrderFormItemsSection.xml | 2 + .../Section/AdminOrderFormPaymentSection.xml | 4 + .../Section/AdminOrderInvoiceViewSection.xml | 15 ++ .../Section/AdminOrderInvoicesTabSection.xml | 6 + .../Section/AdminOrderShipmentsTabSection.xml | 6 + .../Section/AdminShipmentsFilterSection.xml | 15 ++ .../Section/AdminShipmentsGridSection.xml | 15 ++ .../StorefrontOrderInvoicesSection.xml | 15 ++ .../CreateInvoiceAndCheckInvoiceOrderTest.xml | 149 +++++++++++++++ ...iceWithCashOnDeliveryPaymentMethodTest.xml | 115 +++++++++++ ...oiceWithPurchaseOrderPaymentMethodTest.xml | 38 ++++ ...eWithShipmentAndCheckInvoicedOrderTest.xml | 178 ++++++++++++++++++ ...ateInvoiceWithZeroSubtotalCheckoutTest.xml | 122 ++++++++++++ .../Test/TestCase/CreateInvoiceEntityTest.xml | 5 + 30 files changed, 904 insertions(+) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertOrderGraphImageOnDashboardActionGroup.xml create mode 100644 app/code/Magento/Backend/Test/Mftf/Section/AdminDashboardSection.xml create mode 100644 app/code/Magento/Payment/Test/Mftf/Data/PaymentMethodConfigData.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminApplyCouponToOrderActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminSubmitOrderActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/FilterShipmentGridByOrderIdActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Data/ConfigData.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Page/AdminShipmentPage.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/AdminOrderInvoiceViewSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/AdminShipmentsFilterSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/AdminShipmentsGridSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderInvoicesSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceAndCheckInvoiceOrderTest.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithCashOnDeliveryPaymentMethodTest.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithPurchaseOrderPaymentMethodTest.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithShipmentAndCheckInvoicedOrderTest.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithZeroSubtotalCheckoutTest.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertOrderGraphImageOnDashboardActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertOrderGraphImageOnDashboardActionGroup.xml new file mode 100644 index 0000000000000..3e3b0bc6a8a43 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertOrderGraphImageOnDashboardActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertOrderGraphImageOnDashboardActionGroup"> + <click selector="{{AdminDashboardSection.ordersTab}}" stepKey="clickOrdersBtn"/> + <seeElement selector="{{AdminDashboardSection.ordersChart}}" stepKey="seeGraphImage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Page/AdminDashboardPage.xml b/app/code/Magento/Backend/Test/Mftf/Page/AdminDashboardPage.xml index ed30395406f7d..0e95d5c139a1b 100644 --- a/app/code/Magento/Backend/Test/Mftf/Page/AdminDashboardPage.xml +++ b/app/code/Magento/Backend/Test/Mftf/Page/AdminDashboardPage.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> <page name="AdminDashboardPage" url="admin/dashboard/" area="admin" module="Magento_Backend"> <section name="AdminMenuSection"/> + <section name="AdminDashboardSection"/> </page> </pages> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminDashboardSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminDashboardSection.xml new file mode 100644 index 0000000000000..b9db3142cccc3 --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminDashboardSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminDashboardSection"> + <element name="ordersTab" type="button" selector="#diagram_tab_orders"/> + <element name="ordersChart" type="button" selector="#diagram_tab_orders_content .dashboard-diagram-image img"/> + </section> +</sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml index e8b11b27ddc70..6a7361bf3dcce 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml @@ -13,5 +13,6 @@ <element name="productCustomOptions" type="text" selector="//strong[contains(@class, 'product-item-name') and normalize-space(.)='{{var1}}']/following-sibling::*[contains(@class, 'item-options')]/dt[normalize-space(.)='{{var2}}']/following-sibling::dd[normalize-space(.)='{{var3}}']" parameterized="true"/> <element name="productCustomOptionsFile" type="text" selector="//strong[contains(@class, 'product-item-name') and normalize-space(.)='{{var1}}']/following-sibling::*[contains(@class, 'item-options')]/dt[normalize-space(.)='{{var2}}']/following-sibling::dd[contains(.,'{{var3}}')]" parameterized="true"/> <element name="productCustomOptionsLink" type="text" selector="//strong[contains(@class, 'product-item-name') and normalize-space(.)='{{var1}}']/following-sibling::*[contains(@class, 'item-options')]/dt[normalize-space(.)='{{var2}}']/following-sibling::dd//a[text() = '{{var3}}']" parameterized="true"/> + <element name="viewOrder" type="button" selector="//td[@class='col actions']/a[@class='action view']"/> </section> </sections> diff --git a/app/code/Magento/Payment/Test/Mftf/Data/PaymentMethodConfigData.xml b/app/code/Magento/Payment/Test/Mftf/Data/PaymentMethodConfigData.xml new file mode 100644 index 0000000000000..3fd2d1b068b36 --- /dev/null +++ b/app/code/Magento/Payment/Test/Mftf/Data/PaymentMethodConfigData.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="BankTransferEnableConfigData"> + <data key="path">payment/banktransfer/active</data> + <data key="scope_id">1</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="BankTransferDisabledConfigData"> + <data key="path">payment/banktransfer/active</data> + <data key="scope_id">1</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="PurchaseOrderEnableConfigData"> + <data key="path">payment/purchaseorder/active</data> + <data key="scope_id">1</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="PurchaseOrderDisabledConfigData"> + <data key="path">payment/purchaseorder/active</data> + <data key="scope_id">1</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="CashOnDeliveryEnableConfigData"> + <data key="path">payment/cashondelivery/active</data> + <data key="scope_id">1</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="CashOnDeliveryDisabledConfigData"> + <data key="path">payment/cashondelivery/active</data> + <data key="scope_id">1</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> +</entities> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminApplyCouponToOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminApplyCouponToOrderActionGroup.xml new file mode 100644 index 0000000000000..72ab22f80fab2 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminApplyCouponToOrderActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminApplyCouponToOrderActionGroup"> + <arguments> + <argument name="couponCode" type="string"/> + </arguments> + <fillField selector="{{AdminOrderFormItemsSection.couponCode}}" userInput="{{couponCode}}" stepKey="fillCouponCode"/> + <click selector="{{AdminOrderFormItemsSection.applyCoupon}}" stepKey="applyCoupon"/> + <waitForPageLoad stepKey="waitForApplyingCoupon"/> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The coupon code has been accepted." stepKey="seeSuccessMessage"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml index b90bac7e0881b..71a979d085dc5 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminInvoiceActionGroup.xml @@ -80,4 +80,11 @@ <click selector="{{AdminInvoicesFiltersSection.applyFilters}}" stepKey="clickApplyFilters"/> <waitForPageLoad stepKey="waitForFiltersApply"/> </actionGroup> + + <actionGroup name="FilterInvoiceGridByOrderIdWithCleanFiltersActionGroup" extends="filterInvoiceGridByOrderId"> + <arguments> + <argument name="orderId" type="string"/> + </arguments> + <conditionalClick selector="{{AdminInvoicesGridSection.clearFilters}}" dependentSelector="{{AdminInvoicesGridSection.clearFilters}}" visible="true" stepKey="clearFilters" after="goToInvoices"/> + </actionGroup> </actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml index 0e09f3933c1aa..ccd7f676cd2b2 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml @@ -111,6 +111,14 @@ <wait time="5" stepKey="waitForOptionsToLoad"/> </actionGroup> + <actionGroup name="AddSimpleProductWithQtyToOrderActionGroup" extends="addSimpleProductToOrder"> + <arguments> + <argument name="product" defaultValue="_defaultProduct" type="entity"/> + <argument name="productQty" type="string"/> + </arguments> + <fillField selector="{{AdminOrderFormItemsSection.rowQty('1')}}" userInput="{{productQty}}" stepKey="fillProductQty"/> + </actionGroup> + <!--Add configurable product to order --> <actionGroup name="addConfigurableProductToOrder"> <arguments> @@ -368,6 +376,28 @@ <conditionalClick selector="{{AdminOrderFormPaymentSection.checkMoneyOption}}" dependentSelector="{{AdminOrderFormPaymentSection.checkMoneyOption}}" visible="true" stepKey="checkCheckMoneyOption"/> </actionGroup> + <!--Select Bank Transfer payment method--> + <actionGroup name="SelectBankTransferPaymentMethodActionGroup" extends="SelectCheckMoneyPaymentMethod"> + <remove keyForRemoval="checkCheckMoneyOption"/> + <conditionalClick selector="{{AdminOrderFormPaymentSection.bankTransferOption}}" dependentSelector="{{AdminOrderFormPaymentSection.bankTransferOption}}" visible="true" stepKey="checkBankTransferOption" after="waitForPaymentOptions"/> + </actionGroup> + + <!--Select Cash on Delivery payment method--> + <actionGroup name="SelectCashOnDeliveryPaymentMethodActionGroup" extends="SelectCheckMoneyPaymentMethod"> + <remove keyForRemoval="checkCheckMoneyOption"/> + <conditionalClick selector="{{AdminOrderFormPaymentSection.cashOnDelivery}}" dependentSelector="{{AdminOrderFormPaymentSection.cashOnDelivery}}" visible="true" stepKey="checkCashOnDeliveryOption" after="waitForPaymentOptions"/> + </actionGroup> + + <!--Select Purchase Order payment method--> + <actionGroup name="SelectPurchaseOrderPaymentMethodActionGroup" extends="SelectCheckMoneyPaymentMethod"> + <arguments> + <argument name="purchaseOrderNumber" type="string"/> + </arguments> + <remove keyForRemoval="checkCheckMoneyOption"/> + <conditionalClick selector="{{AdminOrderFormPaymentSection.purchaseOrder}}" dependentSelector="{{AdminOrderFormPaymentSection.purchaseOrder}}" visible="true" stepKey="checkPurchaseOrderOption" after="waitForPaymentOptions"/> + <fillField selector="{{AdminOrderFormPaymentSection.purchaseOrderNumber}}" userInput="{{purchaseOrderNumber}}" stepKey="fillPurchaseOrderNumber"/> + </actionGroup> + <!-- Create Order --> <actionGroup name="CreateOrderActionGroup"> <arguments> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminSubmitOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminSubmitOrderActionGroup.xml new file mode 100644 index 0000000000000..56e81da1e55a0 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminSubmitOrderActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminSubmitOrderActionGroup"> + <click selector="{{OrdersGridSection.submitOrder}}" stepKey="submitOrder"/> + <see stepKey="seeSuccessMessageForOrder" userInput="You created the order."/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/FilterShipmentGridByOrderIdActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/FilterShipmentGridByOrderIdActionGroup.xml new file mode 100644 index 0000000000000..437601d6eba9e --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/FilterShipmentGridByOrderIdActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="FilterShipmentGridByOrderIdActionGroup"> + <arguments> + <argument name="orderId" type="string"/> + </arguments> + <amOnPage url="{{AdminShipmentPage.url}}" stepKey="goToShipments"/> + <click selector="{{AdminShipmentGridSection.filter}}" stepKey="clickFilter"/> + <fillField selector="{{AdminShipmentsFilterSection.orderNum}}" userInput="{{orderId}}" stepKey="fillOrderIdForFilter"/> + <click selector="{{AdminShipmentsFilterSection.applyFilters}}" stepKey="clickApplyFilters"/> + <waitForPageLoad stepKey="waitForFiltersApply"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Data/ConfigData.xml b/app/code/Magento/Sales/Test/Mftf/Data/ConfigData.xml new file mode 100644 index 0000000000000..730bebc047f93 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Data/ConfigData.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="AdminEnableDashboardCharts"> + <data key="path">admin/dashboard/enable_charts</data> + <data key="scope_id">1</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="AdminDisableDashboardCharts"> + <data key="path">admin/dashboard/enable_charts</data> + <data key="scope_id">1</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> +</entities> diff --git a/app/code/Magento/Sales/Test/Mftf/Page/AdminInvoicesPage.xml b/app/code/Magento/Sales/Test/Mftf/Page/AdminInvoicesPage.xml index 3dda74adb9c0f..fe574ddabd9bf 100644 --- a/app/code/Magento/Sales/Test/Mftf/Page/AdminInvoicesPage.xml +++ b/app/code/Magento/Sales/Test/Mftf/Page/AdminInvoicesPage.xml @@ -11,5 +11,6 @@ <page name="AdminInvoicesPage" url="sales/invoice/" area="admin" module="Magento_Sales"> <section name="AdminInvoicesGridSection"/> <section name="AdminInvoicesFiltersSection"/> + <section name="AdminOrderInvoiceViewSection"/> </page> </pages> diff --git a/app/code/Magento/Sales/Test/Mftf/Page/AdminShipmentPage.xml b/app/code/Magento/Sales/Test/Mftf/Page/AdminShipmentPage.xml new file mode 100644 index 0000000000000..d35a8ab5c4538 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Page/AdminShipmentPage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="AdminShipmentPage" url="sales/shipment/" area="admin" module="Magento_Sales"> + <section name="AdminShipmentGridSection"/> + </page> +</pages> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceTotalSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceTotalSection.xml index f66412c876709..1a78e920d41ba 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceTotalSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceTotalSection.xml @@ -12,5 +12,9 @@ <element name="subtotalRow" type="text" selector=".order-subtotal-table tbody > tr:nth-of-type({{row}}) td span.price" parameterized="true"/> <element name="total" type="text" selector="//table[contains(@class,'order-subtotal-table')]/tbody/tr/td[contains(text(), '{{total}}')]/following-sibling::td/span/span[contains(@class, 'price')]" parameterized="true"/> <element name="grandTotal" type="text" selector=".order-subtotal-table tfoot tr.col-0>td span.price"/> + <element name="invoiceComment" type="textarea" selector="[name='invoice[comment_text]']" timeout="30"/> + <element name="itemQty" type="text" selector="td.col-qty"/> + <element name="itemName" type="text" selector=".col-product .product-title"/> + <element name="itemTotalPrice" type="text" selector=".col-total .price"/> </section> </sections> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoicesGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoicesGridSection.xml index b8cc79a84db1a..d4c4a9a0106ef 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoicesGridSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoicesGridSection.xml @@ -12,5 +12,6 @@ <element name="spinner" type="button" selector=".spinner"/> <element name="filter" type="button" selector="#container > div > div.admin__data-grid-header > div:nth-child(1) > div.data-grid-filters-actions-wrap > div > button"/> <element name="firstRow" type="button" selector="tr.data-row:nth-of-type(1)"/> + <element name="clearFilters" type="button" selector="button.action-clear" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml index 6fa5d9a9a3787..2c100c31c4b83 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml @@ -15,9 +15,13 @@ <element name="creditMemo" type="button" selector="#order_creditmemo" timeout="30"/> <element name="hold" type="button" selector="#order-view-hold-button" timeout="30"/> <element name="invoice" type="button" selector="#order_invoice" timeout="30"/> + <element name="invoiceTab" type="button" selector="#sales_order_view_tabs_order_invoices" timeout="30"/> <element name="ship" type="button" selector="#order_ship" timeout="30"/> <element name="reorder" type="button" selector="#order_reorder" timeout="30"/> <element name="edit" type="button" selector="#order_edit" timeout="30"/> <element name="modalOk" type="button" selector=".action-accept"/> + <element name="invoiceBtn" type="button" selector="//button[@title='Invoice']"/> + <element name="shipBtn" type="button" selector="//button[@title='Ship']"/> + <element name="shipmentsTab" type="button" selector="#sales_order_view_tabs_order_shipments"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsSection.xml index d7af13c394fb2..a8b499ca7b02a 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormItemsSection.xml @@ -33,5 +33,7 @@ <element name="updateItemsAndQuantities" type="button" selector="//span[contains(text(),'Update Items and Quantities')]"/> <element name="creditMemo" type="input" selector="#order_creditmemo"/> <element name="configure" type="button" selector=".product-configure-block button.action-default.scalable" timeout="30"/> + <element name="couponCode" type="input" selector="#order-coupons input" timeout="30"/> + <element name="applyCoupon" type="button" selector="#order-coupons button"/> </section> </sections> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormPaymentSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormPaymentSection.xml index 1a12a68a6874a..9c9825e73b319 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormPaymentSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderFormPaymentSection.xml @@ -15,6 +15,10 @@ <element name="shippingError" type="text" selector="#order[has_shipping]-error"/> <element name="freeShippingOption" type="radio" selector="#s_method_freeshipping_freeshipping" timeout="30"/> <element name="checkMoneyOption" type="radio" selector="#p_method_checkmo" timeout="30"/> + <element name="bankTransferOption" type="radio" selector="#p_method_banktransfer" timeout="30"/> + <element name="cashOnDelivery" type="radio" selector="#p_method_cashondelivery" timeout="30"/> + <element name="purchaseOrder" type="radio" selector="#p_method_purchaseorder"/> + <element name="purchaseOrderNumber" type="input" selector="#po_number" timeout="30"/> <element name="paymentBlock" type="text" selector="#order-billing_method" /> <element name="paymentError" type="text" selector="#payment[method]-error"/> </section> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderInvoiceViewSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderInvoiceViewSection.xml new file mode 100644 index 0000000000000..0d2c4f366f115 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderInvoiceViewSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminOrderInvoiceViewSection"> + <element name="invoiceQty" type="input" selector=".input-text.admin__control-text.qty-input" timeout="30"/> + <element name="updateInvoiceBtn" type="button" selector=".update-button" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderInvoicesTabSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderInvoicesTabSection.xml index 4ebce4de6b383..f63979c4ac54b 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderInvoicesTabSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderInvoicesTabSection.xml @@ -13,5 +13,11 @@ <element name="gridRow" type="text" selector="#sales_order_view_tabs_order_invoices_content .data-grid tbody > tr:nth-of-type({{row}})" parameterized="true"/> <element name="viewGridRow" type="button" selector="#sales_order_view_tabs_order_invoices_content .data-grid tbody > tr:nth-of-type({{row}}) a[href*='order_invoice/view']" parameterized="true"/> <element name="viewInvoice" type="button" selector="//div[@class='admin__data-grid-wrap']//a[@class='action-menu-item']"/> + <element name="clearFilters" type="button" selector="//div[@id='sales_order_view_tabs_order_invoices_content']//button[@data-action='grid-filter-reset']" timeout="30"/> + <element name="filters" type="button" selector="//div[@id='sales_order_view_tabs_order_invoices_content']//button[@data-action='grid-filter-expand']" timeout="30"/> + <element name="applyFilters" type="button" selector="//div[@id='sales_order_view_tabs_order_invoices_content']//button[@data-action='grid-filter-apply']" timeout="30"/> + <element name="invoiceId" type="input" selector="//div[@id='sales_order_view_tabs_order_invoices_content']//input[@name='increment_id']" timeout="30"/> + <element name="amountFrom" type="input" selector="[name='grand_total[from]']" timeout="30"/> + <element name="amountTo" type="input" selector="[name='grand_total[to]']" timeout="30"/> </section> </sections> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml index 70d413d733b8e..e471fcfe18114 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderShipmentsTabSection.xml @@ -12,5 +12,11 @@ <element name="spinner" type="text" selector="[data-role='spinner'][data-component*='sales_order_view_shipment']"/> <element name="gridRow" type="text" selector="#sales_order_view_tabs_order_shipments_content .data-grid tbody > tr:nth-of-type({{row}})" parameterized="true"/> <element name="viewGridRow" type="button" selector="#sales_order_view_tabs_order_shipments_content .data-grid tbody > tr:nth-of-type({{row}}) a[href*='order_shipment/view']" parameterized="true"/> + <element name="filters" type="button" selector="//div[@id='sales_order_view_tabs_order_shipments_content']//button[@data-action='grid-filter-expand']" timeout="30"/> + <element name="clearFilters" type="button" selector="//div[@id='sales_order_view_tabs_order_shipments_content']//button[@data-action='grid-filter-reset']" timeout="30"/> + <element name="applyFilters" type="button" selector="//div[@id='sales_order_view_tabs_order_shipments_content']//button[@data-action='grid-filter-apply']" timeout="30"/> + <element name="shipmentId" type="input" selector="//div[@id='sales_order_view_tabs_order_shipments_content']//input[@name='increment_id']" timeout="30"/> + <element name="totalQtyFrom" type="input" selector="[name='total_qty[from]']" timeout="30"/> + <element name="totalQtyTo" type="input" selector="[name='total_qty[to]']" timeout="30"/> </section> </sections> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminShipmentsFilterSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminShipmentsFilterSection.xml new file mode 100644 index 0000000000000..b912e16cdd66b --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminShipmentsFilterSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminShipmentsFilterSection"> + <element name="orderNum" type="input" selector="input[name='order_increment_id']"/> + <element name="applyFilters" type="button" selector="button[data-action='grid-filter-apply']" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminShipmentsGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminShipmentsGridSection.xml new file mode 100644 index 0000000000000..5edee241a4971 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminShipmentsGridSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminShipmentGridSection"> + <element name="filter" type="button" selector="[data-action='grid-filter-expand']"/> + <element name="firstRow" type="button" selector="tr.data-row:nth-of-type(1)"/> + </section> +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderInvoicesSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderInvoicesSection.xml new file mode 100644 index 0000000000000..c7a1e67822c61 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderInvoicesSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontOrderInvoicesSection"> + <element name="invoiceTab" type="button" selector="//li[@class='nav item']/a[text()='Invoices']"/> + <element name="grandTotalPrice" type="text" selector="[data-th='Grand Total'] .price"/> + </section> +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceAndCheckInvoiceOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceAndCheckInvoiceOrderTest.xml new file mode 100644 index 0000000000000..45953b7b584f2 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceAndCheckInvoiceOrderTest.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="CreateInvoiceAndCheckInvoiceOrderTest"> + <annotations> + <stories value="Create Invoice for Offline Payment Methods"/> + <title value="Create invoice and check invoice order test"/> + <description value="Create invoice for offline payment methods and check invoice order on admin dashboard"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-15868"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + + <!-- Create customer --> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <!-- Create simple product --> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"> + <field key="price">100</field> + </createData> + + <!-- Enable payment method --> + <magentoCLI command="config:set {{BankTransferEnableConfigData.path}} {{BankTransferEnableConfigData.value}}" stepKey="enableBankTransfer"/> + </before> + <after> + <!-- Disable payment method --> + <magentoCLI command="config:set {{BankTransferDisabledConfigData.path}} {{BankTransferDisabledConfigData.value}}" stepKey="enableBankTransfer"/> + + <!-- Logout customer --> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogoutStorefront"/> + + <!-- Delete customer --> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + + <!-- Delete product --> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create order --> + <actionGroup ref="navigateToNewOrderPageExistingCustomer" stepKey="goToCreateOrderPage"> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Add product to order --> + <actionGroup ref="AddSimpleProductWithQtyToOrderActionGroup" stepKey="addProductToOrder"> + <argument name="product" value="$$createSimpleProduct$$"/> + <argument name="productQty" value="2"/> + </actionGroup> + + <!-- Select bank transfer payment method --> + <actionGroup ref="SelectBankTransferPaymentMethodActionGroup" stepKey="selectPaymentMethod"/> + + <!-- Select shipping method --> + <click selector="{{AdminInvoicePaymentShippingSection.getShippingMethodAndRates}}" stepKey="openShippingMethod"/> + <waitForPageLoad stepKey="waitForShippingMethods"/> + <click selector="{{AdminInvoicePaymentShippingSection.shippingMethod}}" stepKey="chooseShippingMethod"/> + <waitForPageLoad stepKey="waitForShippingMethodLoad"/> + + <!-- Submit order --> + <actionGroup ref="AdminSubmitOrderActionGroup" stepKey="submitOrder"/> + + <!-- Grab order id --> + <grabTextFrom selector="|Order # (\d+)|" stepKey="getOrderId"/> + + <!-- Open created order --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrdersPage"/> + <waitForPageLoad stepKey="waitForOrdersPageLoad"/> + <actionGroup ref="filterOrderGridById" stepKey="filterOrdersGridById"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <click selector="{{AdminDataGridTableSection.firstRow}}" stepKey="clickCreatedOrderInGrid"/> + + <!-- Go to invoice tab and fill data --> + <click selector="{{AdminOrderDetailsMainActionsSection.invoice}}" stepKey="clickInvoiceAction"/> + <fillField selector="{{AdminOrderInvoiceViewSection.invoiceQty}}" userInput="1" stepKey="fillInvoiceQuantity"/> + <click selector="{{AdminOrderInvoiceViewSection.updateInvoiceBtn}}" stepKey="clickUpdateQtyInvoiceBtn"/> + <fillField selector="{{AdminInvoiceTotalSection.invoiceComment}}" userInput="comment" stepKey="writeComment"/> + <click selector="{{AdminInvoiceMainActionsSection.submitInvoice}}" stepKey="clickSubmitInvoice"/> + + <!-- Assert invoice with shipment success message --> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The invoice has been created." stepKey="seeSuccessMessage"/> + + <!-- Assert invoice in invoices grid --> + <actionGroup ref="FilterInvoiceGridByOrderIdWithCleanFiltersActionGroup" stepKey="filterInvoiceGridByOrderId"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <click selector="{{AdminInvoicesGridSection.firstRow}}" stepKey="opeCreatedInvoice"/> + <waitForPageLoad stepKey="waitForInvoiceDetailsPageToLoad"/> + <grabFromCurrentUrl regex="~/invoice_id/(\d+)/~" stepKey="grabInvoiceId"/> + + <!-- Assert invoice in invoices tab --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> + <waitForPageLoad stepKey="waitForOrdersLoad"/> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridByIdForAssertingInvoiceBtn"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <click selector="{{AdminDataGridTableSection.firstRow}}" stepKey="clickOrderInGrid"/> + <click selector="{{AdminOrderDetailsMainActionsSection.invoiceTab}}" stepKey="clickInvoicesTabOrdersPage"/> + <conditionalClick selector="{{AdminOrderInvoicesTabSection.clearFilters}}" dependentSelector="{{AdminOrderInvoicesTabSection.clearFilters}}" visible="true" stepKey="clearInvoiceFilters"/> + <click selector="{{AdminOrderInvoicesTabSection.filters}}" stepKey="openOrderInvoicesGridFilters"/> + <fillField selector="{{AdminOrderInvoicesTabSection.invoiceId}}" userInput="$grabInvoiceId" stepKey="fillInvoiceIdFilter"/> + <fillField selector="{{AdminOrderInvoicesTabSection.amountFrom}}" userInput="110.00" stepKey="fillAmountFromFilter"/> + <fillField selector="{{AdminOrderInvoicesTabSection.amountTo}}" userInput="110.00" stepKey="fillAmountToFilter"/> + <click selector="{{AdminOrderInvoicesTabSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> + <dontSeeElement selector="{{AdminDataGridTableSection.dataGridEmpty}}" stepKey="assertThatInvoiceGridNotEmpty"/> + + <!-- Assert invoice items --> + <actionGroup ref="FilterInvoiceGridByOrderIdWithCleanFiltersActionGroup" stepKey="filterInvoiceByOrderId"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <click selector="{{AdminInvoicesGridSection.firstRow}}" stepKey="openInvoice"/> + <waitForPageLoad stepKey="waitForInvoicePageToLoad"/> + <see selector="{{AdminInvoiceTotalSection.itemName}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductNameInInvoiceItems"/> + <see selector="{{AdminInvoiceTotalSection.itemQty}}" userInput="1" stepKey="seeProductQtyInInvoiceItems"/> + <see selector="{{AdminInvoiceTotalSection.itemTotalPrice}}" userInput="$$createSimpleProduct.price$$" stepKey="seeProductTotalPriceInInvoiceItems"/> + + <!-- Login as customer --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + <waitForPageLoad stepKey="waitForCustomerLogin"/> + + <!-- Open My Account > My Orders --> + <amOnPage stepKey="goToMyAccountPage" url="{{StorefrontCustomerDashboardPage.url}}"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <actionGroup ref="StorefrontCustomerGoToSidebarMenu" stepKey="goToSidebarMenu"> + <argument name="menu" value="My Orders"/> + </actionGroup> + + <!-- Assert invoiced amount on frontend --> + <click selector="{{StorefrontCustomerOrderSection.viewOrder}}" stepKey="clickViewOrder"/> + <click selector="{{StorefrontOrderInvoicesSection.invoiceTab}}" stepKey="clickInvoiceTabOnStorefront"/> + <see selector="{{StorefrontOrderInvoicesSection.grandTotalPrice}}" userInput="$110.00" stepKey="seePrice"/> + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithCashOnDeliveryPaymentMethodTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithCashOnDeliveryPaymentMethodTest.xml new file mode 100644 index 0000000000000..ef194028a4367 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithCashOnDeliveryPaymentMethodTest.xml @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="CreateInvoiceWithCashOnDeliveryPaymentMethodTest"> + <annotations> + <stories value="Create Invoice for Offline Payment Methods"/> + <title value="Create invoice with cash on delivery payment method test"/> + <description value="Create invoice with cash on delivery payment method"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-15869"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + + <!-- Create customer --> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <!-- Create simple product --> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"> + <field key="price">100</field> + </createData> + + <!-- Enable payment method --> + <magentoCLI command="config:set {{CashOnDeliveryEnableConfigData.path}} {{CashOnDeliveryEnableConfigData.value}}" stepKey="enablePaymentMethod"/> + </before> + <after> + <!-- Disable payment method --> + <magentoCLI command="config:set {{CashOnDeliveryDisabledConfigData.path}} {{CashOnDeliveryDisabledConfigData.value}}" stepKey="disablePaymentMethod"/> + + <!-- Logout customer --> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogoutStorefront"/> + + <!-- Delete customer --> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + + <!-- Delete product --> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create order --> + <actionGroup ref="navigateToNewOrderPageExistingCustomer" stepKey="goToCreateOrderPage"> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Add product to order --> + <actionGroup ref="AddSimpleProductWithQtyToOrderActionGroup" stepKey="addProductToOrder"> + <argument name="product" value="$$createSimpleProduct$$"/> + <argument name="productQty" value="2"/> + </actionGroup> + + <!-- Select shipping method --> + <click selector="{{AdminInvoicePaymentShippingSection.getShippingMethodAndRates}}" stepKey="openShippingMethod"/> + <waitForPageLoad stepKey="waitForShippingMethods"/> + <click selector="{{AdminInvoicePaymentShippingSection.shippingMethod}}" stepKey="chooseShippingMethod"/> + <waitForPageLoad stepKey="waitForShippingMethodLoad"/> + + <!-- Select cash on delivery payment method --> + <actionGroup ref="SelectCashOnDeliveryPaymentMethodActionGroup" stepKey="selectPaymentMethod"/> + + <!-- Submit order --> + <actionGroup ref="AdminSubmitOrderActionGroup" stepKey="submitOrder"/> + + <!-- Grab order id --> + <grabTextFrom selector="|Order # (\d+)|" stepKey="getOrderId"/> + + <!-- Open created order --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrdersPage"/> + <waitForPageLoad stepKey="waitForOrdersPageLoad"/> + <actionGroup ref="filterOrderGridById" stepKey="filterOrdersGridById"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <click selector="{{AdminDataGridTableSection.firstRow}}" stepKey="clickCreatedOrderInGrid"/> + + <!-- Go to invoice tab and fill data --> + <click selector="{{AdminOrderDetailsMainActionsSection.invoice}}" stepKey="clickInvoiceAction"/> + <fillField selector="{{AdminOrderInvoiceViewSection.invoiceQty}}" userInput="1" stepKey="fillInvoiceQuantity"/> + <click selector="{{AdminOrderInvoiceViewSection.updateInvoiceBtn}}" stepKey="clickUpdateQtyInvoiceBtn"/> + <fillField selector="{{AdminInvoiceTotalSection.invoiceComment}}" userInput="comment" stepKey="writeComment"/> + <click selector="{{AdminInvoiceMainActionsSection.submitInvoice}}" stepKey="clickSubmitInvoice"/> + + <!-- Assert invoice with shipment success message --> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The invoice has been created." stepKey="seeSuccessMessage"/> + + <!-- Login as customer --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + <waitForPageLoad stepKey="waitForCustomerLogin"/> + + <!-- Open My Account > My Orders --> + <amOnPage stepKey="goToMyAccountPage" url="{{StorefrontCustomerDashboardPage.url}}"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <actionGroup ref="StorefrontCustomerGoToSidebarMenu" stepKey="goToSidebarMenu"> + <argument name="menu" value="My Orders"/> + </actionGroup> + + <!-- Assert invoiced amount on frontend --> + <click selector="{{StorefrontCustomerOrderSection.viewOrder}}" stepKey="clickViewOrder"/> + <click selector="{{StorefrontOrderInvoicesSection.invoiceTab}}" stepKey="clickInvoiceTabOnStorefront"/> + <see selector="{{StorefrontOrderInvoicesSection.grandTotalPrice}}" userInput="$110.00" stepKey="seePrice"/> + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithPurchaseOrderPaymentMethodTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithPurchaseOrderPaymentMethodTest.xml new file mode 100644 index 0000000000000..1c393b6ffb586 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithPurchaseOrderPaymentMethodTest.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="CreateInvoiceWithPurchaseOrderPaymentMethodTest" extends="CreateInvoiceWithCashOnDeliveryPaymentMethodTest"> + <annotations> + <stories value="Create Invoice for Offline Payment Methods"/> + <title value="Create invoice with purchase order payment method test"/> + <description value="Create invoice with purchase order payment method"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-15870"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Enable payment method --> + <magentoCLI command="config:set {{PurchaseOrderEnableConfigData.path}} {{PurchaseOrderEnableConfigData.value}}" stepKey="enablePaymentMethod"/> + </before> + <after> + <!-- Disable payment method --> + <magentoCLI command="config:set {{PurchaseOrderDisabledConfigData.path}} {{PurchaseOrderDisabledConfigData.value}}" stepKey="disablePaymentMethod"/> + </after> + + <!-- Select purchase order payment method --> + <actionGroup ref="SelectPurchaseOrderPaymentMethodActionGroup" stepKey="selectPaymentMethod"> + <argument name="purchaseOrderNumber" value="12345"/> + </actionGroup> + + <click selector="{{AdminOrderFormPaymentSection.header}}" stepKey="unfocus" after="selectPaymentMethod"/> + <waitForPageLoad stepKey="waitForJavascriptToFinish" after="unfocus"/> + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithShipmentAndCheckInvoicedOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithShipmentAndCheckInvoicedOrderTest.xml new file mode 100644 index 0000000000000..11f8bf519661c --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithShipmentAndCheckInvoicedOrderTest.xml @@ -0,0 +1,178 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="CreateInvoiceWithShipmentAndCheckInvoicedOrderTest"> + <annotations> + <stories value="Create Invoice for Offline Payment Methods"/> + <title value="Create invoice with shipment and check invoiced order test"/> + <description value="Create invoice with shipment for offline payment methods and check invoiced order on admin dashboard"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-15867"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + + <!-- Create customer --> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <!-- Create simple product --> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"/> + + <!-- Enable charts --> + <magentoCLI command="config:set {{AdminEnableDashboardCharts.path}} {{AdminEnableDashboardCharts.value}}" stepKey="enableDashboardCharts"/> + </before> + <after> + <!-- Disable charts --> + <magentoCLI command="config:set {{AdminDisableDashboardCharts.path}} {{AdminDisableDashboardCharts.value}}" stepKey="disableDashboardCharts"/> + + <!-- Logout customer --> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogoutStorefront"/> + + <!-- Delete customer --> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + + <!-- Delete product --> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create order--> + <actionGroup ref="navigateToNewOrderPageExistingCustomer" stepKey="goToCreateOrderPage"> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Add product to order --> + <actionGroup ref="addSimpleProductToOrder" stepKey="addProductToOrder"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + + <!-- Select shipping method --> + <click selector="{{AdminInvoicePaymentShippingSection.getShippingMethodAndRates}}" stepKey="openShippingMethod"/> + <waitForPageLoad stepKey="waitForShippingMethods"/> + <click selector="{{AdminInvoicePaymentShippingSection.shippingMethod}}" stepKey="chooseShippingMethod"/> + <waitForPageLoad stepKey="waitForShippingMethodLoad"/> + + <!-- Submit order --> + <actionGroup ref="AdminSubmitOrderActionGroup" stepKey="submitOrder"/> + + <!-- Grab order id --> + <grabTextFrom selector="|Order # (\d+)|" stepKey="getOrderId"/> + + <!-- Open created order --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrdersPage"/> + <waitForPageLoad stepKey="waitForOrdersPageLoad"/> + <actionGroup ref="filterOrderGridById" stepKey="filterOrdersGridById"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <click selector="{{AdminDataGridTableSection.firstRow}}" stepKey="clickCreatedOrderInGrid"/> + + <!-- Go to invoice tab and fill data --> + <click selector="{{AdminOrderDetailsMainActionsSection.invoice}}" stepKey="clickInvoiceAction"/> + <click selector="{{AdminInvoicePaymentShippingSection.CreateShipment}}" stepKey="createShipment"/> + <fillField selector="{{AdminInvoiceTotalSection.invoiceComment}}" userInput="comment" stepKey="writeComment"/> + <click selector="{{AdminInvoiceMainActionsSection.submitInvoice}}" stepKey="clickSubmitInvoice"/> + + <!-- Assert invoice with shipment success message --> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="You created the invoice and shipment." stepKey="seeSuccessMessage"/> + + <!-- Assert order graph image is visible on admin dashboard --> + <amOnPage url="{{AdminDashboardPage.url}}" stepKey="amOnDashboardPage"/> + <waitForPageLoad stepKey="waitForDashboardPageLoad"/> + <actionGroup ref="AssertOrderGraphImageOnDashboardActionGroup" stepKey="seeOrderGraphImage"/> + + <!-- Assert invoice in invoices grid --> + <actionGroup ref="FilterInvoiceGridByOrderIdWithCleanFiltersActionGroup" stepKey="filterInvoiceGridByOrderId"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <click selector="{{AdminInvoicesGridSection.firstRow}}" stepKey="opeCreatedInvoice"/> + <waitForPageLoad stepKey="waitForInvoiceDetailsPageToLoad"/> + <grabFromCurrentUrl regex="~/invoice_id/(\d+)/~" stepKey="grabInvoiceId"/> + + <!-- Assert no invoice button --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/> + <waitForPageLoad stepKey="waitForOrdersLoad"/> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridByIdForAssertingInvoiceBtn"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <click selector="{{AdminDataGridTableSection.firstRow}}" stepKey="clickOrderInGrid"/> + <dontSeeElement selector="{{AdminOrderDetailsMainActionsSection.invoiceBtn}}" stepKey="dontSeeInvoiceBtn"/> + + <!-- Assert invoice in invoices tab --> + <click selector="{{AdminOrderDetailsMainActionsSection.invoiceTab}}" stepKey="clickInvoicesTabOrdersPage"/> + <conditionalClick selector="{{AdminOrderInvoicesTabSection.clearFilters}}" dependentSelector="{{AdminOrderInvoicesTabSection.clearFilters}}" visible="true" stepKey="clearInvoiceFilters"/> + <click selector="{{AdminOrderInvoicesTabSection.filters}}" stepKey="openOrderInvoicesGridFilters"/> + <fillField selector="{{AdminOrderInvoicesTabSection.invoiceId}}" userInput="$grabInvoiceId" stepKey="fillInvoiceIdFilter"/> + <fillField selector="{{AdminOrderInvoicesTabSection.amountFrom}}" userInput="128.00" stepKey="fillAmountFromFilter"/> + <fillField selector="{{AdminOrderInvoicesTabSection.amountTo}}" userInput="128.00" stepKey="fillAmountToFilter"/> + <click selector="{{AdminOrderInvoicesTabSection.applyFilters}}" stepKey="clickOrderApplyFilters"/> + <dontSeeElement selector="{{AdminDataGridTableSection.dataGridEmpty}}" stepKey="assertThatInvoiceGridNotEmpty"/> + + <!-- Login as customer --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + <waitForPageLoad stepKey="waitForCustomerLogin"/> + + <!-- Open My Account > My Orders --> + <amOnPage stepKey="goToMyAccountPage" url="{{StorefrontCustomerDashboardPage.url}}"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <actionGroup ref="StorefrontCustomerGoToSidebarMenu" stepKey="goToSidebarMenu"> + <argument name="menu" value="My Orders"/> + </actionGroup> + + <!-- Assert invoiced amount on frontend --> + <click selector="{{StorefrontCustomerOrderSection.viewOrder}}" stepKey="clickViewOrder"/> + <click selector="{{StorefrontOrderInvoicesSection.invoiceTab}}" stepKey="clickInvoiceTabOnStorefront"/> + <see selector="{{StorefrontOrderInvoicesSection.grandTotalPrice}}" userInput="128.00" stepKey="seePrice"/> + + <!-- Assert shipment in grid --> + <actionGroup ref="FilterShipmentGridByOrderIdActionGroup" stepKey="filterShipmentGridByOrderId"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <click selector="{{AdminShipmentGridSection.firstRow}}" stepKey="openCreatedShipment"/> + <waitForPageLoad stepKey="waitForShipmentDetailsPageToLoad"/> + <grabFromCurrentUrl regex="~/shipment_id/(\d+)/~" stepKey="grabShipmentId"/> + + <!-- Assert no ship button --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToAdminOrdersPage"/> + <waitForPageLoad stepKey="waitForOrdersPageToLoad"/> + <actionGroup ref="filterOrderGridById" stepKey="filterOrderGridByIdForAssertingShipBtn"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <click selector="{{AdminDataGridTableSection.firstRow}}" stepKey="selectOrderInGrid"/> + <dontSeeElement selector="{{AdminOrderDetailsMainActionsSection.shipBtn}}" stepKey="dontSeeShipBtn"/> + + <!-- Assert shipment in shipments tab --> + <click selector="{{AdminOrderDetailsMainActionsSection.shipmentsTab}}" stepKey="clickShipmentsTab"/> + <waitForPageLoad stepKey="waitOrderShipTabToLoad"/> + <conditionalClick selector="{{AdminOrderShipmentsTabSection.clearFilters}}" dependentSelector="{{AdminOrderShipmentsTabSection.clearFilters}}" visible="true" stepKey="clearShipmentsFilters"/> + <click selector="{{AdminOrderShipmentsTabSection.filters}}" stepKey="openOrderShipmentsGridFilters"/> + <fillField selector="{{AdminOrderShipmentsTabSection.shipmentId}}" userInput="$grabShipmentId" stepKey="fillShipmentsIdFilter"/> + <fillField selector="{{AdminOrderShipmentsTabSection.totalQtyFrom}}" userInput="1.0000" stepKey="fillTotalQtyFromFilter"/> + <fillField selector="{{AdminOrderShipmentsTabSection.totalQtyTo}}" userInput="1.0000" stepKey="fillTotalQtyToFilter"/> + <click selector="{{AdminOrderShipmentsTabSection.applyFilters}}" stepKey="clickApplyFilters"/> + <dontSeeElement selector="{{AdminDataGridTableSection.dataGridEmpty}}" stepKey="assertThatShipmentGridNotEmpty"/> + + <!-- Assert invoice items --> + <actionGroup ref="FilterInvoiceGridByOrderIdWithCleanFiltersActionGroup" stepKey="filterInvoiceByOrderId"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <click selector="{{AdminInvoicesGridSection.firstRow}}" stepKey="openInvoice"/> + <waitForPageLoad stepKey="waitForInvoicePageToLoad"/> + <see selector="{{AdminInvoiceTotalSection.itemName}}" userInput="$$createSimpleProduct.name$$" stepKey="seeProductNameInInvoiceItems"/> + <see selector="{{AdminInvoiceTotalSection.itemQty}}" userInput="1" stepKey="seeProductQtyInInvoiceItems"/> + <see selector="{{AdminInvoiceTotalSection.itemTotalPrice}}" userInput="$$createSimpleProduct.price$$" stepKey="seeProductTotalPriceInInvoiceItems"/> + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithZeroSubtotalCheckoutTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithZeroSubtotalCheckoutTest.xml new file mode 100644 index 0000000000000..4b8e5d88cdf49 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithZeroSubtotalCheckoutTest.xml @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="CreateInvoiceWithZeroSubtotalCheckoutTest"> + <annotations> + <stories value="Create Invoice for Offline Payment Methods"/> + <title value="Create invoice with zero subtotal checkout test"/> + <description value="Create invoice with with zero subtotal checkout"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-15871"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="LoginAsAdmin"/> + + <!-- Create customer --> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <!-- Create simple product --> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"> + <field key="price">10</field> + </createData> + + <!-- Create sales rule with coupon --> + <createData entity="SalesRuleSpecificCouponWithFixedDiscount" stepKey="createCartPriceRule"/> + <createData entity="SimpleSalesRuleCoupon" stepKey="createCouponForCartPriceRule"> + <requiredEntity createDataKey="createCartPriceRule"/> + </createData> + + <!-- Enable free shipping method --> + <createData entity="FreeShippinMethodConfig" stepKey="enableFreeShippingMethod"/> + <createData entity="setFreeShippingSubtotal" stepKey="setFreeShippingSubtotal"/> + </before> + <after> + <!-- Disable free shipping method --> + <createData entity="FreeShippinMethodDefault" stepKey="disableFreeShippingMethod"/> + <createData entity="setFreeShippingSubtotalToDefault" stepKey="setFreeShippingSubtotalToDefault"/> + + <!-- Logout customer --> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogoutStorefront"/> + + <!-- Delete sales rule --> + <deleteData createDataKey="createCartPriceRule" stepKey="deleteCartPriceRule"/> + + <!-- Delete customer --> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + + <!-- Delete product --> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create order --> + <actionGroup ref="navigateToNewOrderPageExistingCustomer" stepKey="goToCreateOrderPage"> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Add product to order --> + <actionGroup ref="addSimpleProductToOrder" stepKey="addProductToOrder"> + <argument name="product" value="$$createSimpleProduct$$"/> + </actionGroup> + + <!-- Apply coupon to the order --> + <actionGroup ref="AdminApplyCouponToOrderActionGroup" stepKey="applyCoupon"> + <argument name="couponCode" value="$$createCouponForCartPriceRule.code$$"/> + </actionGroup> + + <!-- Select Free shipping --> + <actionGroup ref="orderSelectFreeShipping" stepKey="selectFreeShippingOption"/> + + <!-- Submit order --> + <actionGroup ref="AdminSubmitOrderActionGroup" stepKey="submitOrder"/> + + <!-- Grab order id --> + <grabTextFrom selector="|Order # (\d+)|" stepKey="getOrderId"/> + + <!-- Open created order --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrdersPage"/> + <waitForPageLoad stepKey="waitForOrdersPageLoad"/> + <actionGroup ref="filterOrderGridById" stepKey="filterOrdersGridById"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <click selector="{{AdminDataGridTableSection.firstRow}}" stepKey="clickCreatedOrderInGrid"/> + + <!-- Go to invoice tab and fill data --> + <click selector="{{AdminOrderDetailsMainActionsSection.invoice}}" stepKey="clickInvoiceAction"/> + <fillField selector="{{AdminInvoiceTotalSection.invoiceComment}}" userInput="comment" stepKey="writeComment"/> + <click selector="{{AdminInvoiceMainActionsSection.submitInvoice}}" stepKey="clickSubmitInvoice"/> + + <!-- Assert invoice with shipment success message --> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The invoice has been created." stepKey="seeSuccessMessage"/> + + <!-- Login as customer --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + <waitForPageLoad stepKey="waitForCustomerLogin"/> + + <!-- Open My Account > My Orders --> + <amOnPage stepKey="goToMyAccountPage" url="{{StorefrontCustomerDashboardPage.url}}"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <actionGroup ref="StorefrontCustomerGoToSidebarMenu" stepKey="goToSidebarMenu"> + <argument name="menu" value="My Orders"/> + </actionGroup> + + <!-- Assert invoiced amount on frontend --> + <click selector="{{StorefrontCustomerOrderSection.viewOrder}}" stepKey="clickViewOrder"/> + <click selector="{{StorefrontOrderInvoicesSection.invoiceTab}}" stepKey="clickInvoiceTabOnStorefront"/> + <see selector="{{StorefrontOrderInvoicesSection.grandTotalPrice}}" userInput="$0.00" stepKey="seePrice"/> + </test> +</tests> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateInvoiceEntityTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateInvoiceEntityTest.xml index 3d967fdea299b..a6a1d61d0d6e9 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateInvoiceEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateInvoiceEntityTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Sales\Test\TestCase\CreateInvoiceEntityTest" summary="Create Invoice for Offline Payment Methods" ticketId="MAGETWO-28209, MAGETWO-45491"> <variation name="CreateInvoiceEntityTestVariation1" summary="Create Invoice for Offline Payment Methods and check invoiced order on admin dashboard" ticketId="MAGETWO-28209, MAGETWO-45491"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="order/dataset" xsi:type="string">default</data> <data name="order/data/price/dataset" xsi:type="string">full_invoice</data> <data name="order/data/total_qty_ordered/0" xsi:type="string">1</data> @@ -34,6 +35,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertInvoiceItems" /> </variation> <variation name="CreateInvoiceEntityTestVariation2"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="order/dataset" xsi:type="string">default</data> <data name="order/data/price/dataset" xsi:type="string">partial_invoice</data> <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::product_100_dollar</data> @@ -60,6 +62,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertInvoicedAmountOnFrontend" /> </variation> <variation name="CreateInvoiceEntityTestVariationWithCashOnDeliveryPaymentMethod"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="order/dataset" xsi:type="string">default</data> <data name="order/data/price/dataset" xsi:type="string">partial_invoice</data> <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::product_100_dollar</data> @@ -83,6 +86,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertInvoicedAmountOnFrontend" /> </variation> <variation name="CreateInvoiceEntityTestVariationWithPurchaseOrderPaymentMethod"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="order/dataset" xsi:type="string">default</data> <data name="order/data/price/dataset" xsi:type="string">partial_invoice</data> <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::product_100_dollar</data> @@ -107,6 +111,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertInvoicedAmountOnFrontend" /> </variation> <variation name="CreateInvoiceEntityTestVariationWithZeroSubtotalCheckout"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="order/dataset" xsi:type="string">default</data> <data name="order/data/price/dataset" xsi:type="string">free_invoice</data> <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::product_10_dollar</data> From f4a4a340b4983ad80a5ede504993ed8d753c5f9d Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 24 Apr 2019 12:31:05 +0300 Subject: [PATCH 069/224] magento/graphql-ce#387: Test coverage of getting IDs of CMS page/blocks by GraphQL API --- .../CmsGraphQl/Model/Resolver/DataProvider/Block.php | 1 - .../Model/Resolver/DataProvider/PageDataProvider.php | 1 - app/code/Magento/CmsGraphQl/etc/schema.graphqls | 4 +--- .../testsuite/Magento/GraphQl/Cms/CmsBlockTest.php | 5 ----- .../testsuite/Magento/GraphQl/Cms/CmsPageTest.php | 8 ++------ 5 files changed, 3 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php index fa4944381b858..47a2439c4fad0 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php @@ -59,7 +59,6 @@ public function getData(string $blockIdentifier): array $renderedContent = $this->widgetFilter->filter($block->getContent()); $blockData = [ - BlockInterface::BLOCK_ID => $block->getId(), BlockInterface::IDENTIFIER => $block->getIdentifier(), BlockInterface::TITLE => $block->getTitle(), BlockInterface::CONTENT => $renderedContent, diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php index fdcd0c88cd60c..47fa4c08a9c31 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php @@ -96,7 +96,6 @@ private function convertPageData(PageInterface $page) $pageData = [ 'url_key' => $page->getIdentifier(), - PageInterface::PAGE_ID => $page->getId(), PageInterface::IDENTIFIER => $page->getIdentifier(), PageInterface::TITLE => $page->getTitle(), PageInterface::CONTENT => $renderedContent, diff --git a/app/code/Magento/CmsGraphQl/etc/schema.graphqls b/app/code/Magento/CmsGraphQl/etc/schema.graphqls index 8c0cb80f34269..85bff91dea8a2 100644 --- a/app/code/Magento/CmsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CmsGraphQl/etc/schema.graphqls @@ -12,7 +12,7 @@ type StoreConfig @doc(description: "The type contains information about a store type Query { cmsPage ( - id: Int @doc(description: "Id of the CMS page") + id: Int @doc(description: "Id of the CMS page") @deprecated(reason: "Use `identifier`") @doc(description: "The CMS page query returns information about a CMS page") identifier: String @doc(description: "Identifier of the CMS page") ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") cmsBlocks ( @@ -21,7 +21,6 @@ type Query { } type CmsPage @doc(description: "CMS page defines all CMS page information") { - page_id: Int @doc(description: "Entity ID of CMS page") identifier: String @doc(description: "Identifier of the CMS page") url_key: String @doc(description: "URL key of CMS page") title: String @doc(description: "CMS page title") @@ -38,7 +37,6 @@ type CmsBlocks @doc(description: "CMS blocks information") { } type CmsBlock @doc(description: "CMS block defines all CMS block information") { - block_id: Int @doc(description: "Entity ID of CMS block") identifier: String @doc(description: "CMS block identifier") title: String @doc(description: "CMS block title") content: String @doc(description: "CMS block content") diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsBlockTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsBlockTest.php index 6e07f8cd7876a..542b00d434db0 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsBlockTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsBlockTest.php @@ -47,7 +47,6 @@ public function testGetCmsBlock() { cmsBlocks(identifiers: "enabled_block") { items { - block_id identifier title content @@ -60,7 +59,6 @@ public function testGetCmsBlock() self::assertArrayHasKey('cmsBlocks', $response); self::assertArrayHasKey('items', $response['cmsBlocks']); - self::assertEquals($cmsBlockData['block_id'], $response['cmsBlocks']['items'][0]['block_id']); self::assertEquals($cmsBlockData['identifier'], $response['cmsBlocks']['items'][0]['identifier']); self::assertEquals($cmsBlockData['title'], $response['cmsBlocks']['items'][0]['title']); self::assertEquals($renderedContent, $response['cmsBlocks']['items'][0]['content']); @@ -83,7 +81,6 @@ public function testGetCmsBlockByBlockId() { cmsBlocks(identifiers: "$blockId") { items { - block_id identifier title content @@ -95,8 +92,6 @@ public function testGetCmsBlockByBlockId() self::assertArrayHasKey('cmsBlocks', $response); self::assertArrayHasKey('items', $response['cmsBlocks']); - - self::assertEquals($blockId, $response['cmsBlocks']['items'][0]['block_id']); self::assertEquals($cmsBlockData['identifier'], $response['cmsBlocks']['items'][0]['identifier']); self::assertEquals($cmsBlockData['title'], $response['cmsBlocks']['items'][0]['title']); self::assertEquals($renderedContent, $response['cmsBlocks']['items'][0]['content']); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsPageTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsPageTest.php index 8abcee8f22403..53e47185c9866 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsPageTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsPageTest.php @@ -58,22 +58,18 @@ public function testGetCmsPageById() public function testGetCmsPageByIdentifier() { $cmsPageIdentifier = 'page100'; - $storeId = 0; - - $cmsPage = ObjectManager::getInstance()->get(GetPageByIdentifier::class)->execute($cmsPageIdentifier, $storeId); - $pageId = $cmsPage->getPageId(); $query = <<<QUERY { cmsPage(identifier: "$cmsPageIdentifier") { - page_id + identifier } } QUERY; $response = $this->graphQlQuery($query); - $this->assertEquals($pageId, $response['cmsPage']['page_id']); + $this->assertEquals($cmsPageIdentifier, $response['cmsPage']['identifier']); } /** From 4dbdc8340eef6f77f6ee63184d1ef4a7f96c2730 Mon Sep 17 00:00:00 2001 From: Leandry <leandry@atwix.com> Date: Wed, 24 Apr 2019 19:08:06 +0300 Subject: [PATCH 070/224] Refactoring --- .../AdminLockAdminUserWhenCreatingNewRoleTest.xml | 12 ++++++------ ...eActionGroup.xml => AdminSaveRoleActionGroup.xml} | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) rename app/code/Magento/User/Test/Mftf/ActionGroup/{AssertSaveRoleActionGroup.xml => AdminSaveRoleActionGroup.xml} (90%) diff --git a/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewRoleTest.xml b/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewRoleTest.xml index b1070a233345f..9138221faf411 100644 --- a/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewRoleTest.xml +++ b/app/code/Magento/Security/Test/Mftf/Test/AdminLockAdminUserWhenCreatingNewRoleTest.xml @@ -32,37 +32,37 @@ <actionGroup ref="AdminFillRoleRequiredFieldsActionGroup" stepKey="fillFieldFirstAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AssertSaveRoleActionGroup" stepKey="saveRoleFirstAttempt"/> + <actionGroup ref="AdminSaveRoleActionGroup" stepKey="saveRoleFirstAttempt"/> <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkFirstSaveRoleError"/> <actionGroup ref="AdminFillRoleRequiredFieldsActionGroup" stepKey="fillFieldSecondAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AssertSaveRoleActionGroup" stepKey="saveRoleSecondAttempt"/> + <actionGroup ref="AdminSaveRoleActionGroup" stepKey="saveRoleSecondAttempt"/> <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkSecondSaveRoleError"/> <actionGroup ref="AdminFillRoleRequiredFieldsActionGroup" stepKey="fillFieldThirdAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AssertSaveRoleActionGroup" stepKey="saveRoleThirdAttempt"/> + <actionGroup ref="AdminSaveRoleActionGroup" stepKey="saveRoleThirdAttempt"/> <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkThirdSaveRoleError"/> <actionGroup ref="AdminFillRoleRequiredFieldsActionGroup" stepKey="fillFieldFourthAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AssertSaveRoleActionGroup" stepKey="saveRoleFourthAttempt"/> + <actionGroup ref="AdminSaveRoleActionGroup" stepKey="saveRoleFourthAttempt"/> <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkFourthSaveRoleError"/> <actionGroup ref="AdminFillRoleRequiredFieldsActionGroup" stepKey="fillFieldFifthAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AssertSaveRoleActionGroup" stepKey="saveRoleFifthAttempt"/> + <actionGroup ref="AdminSaveRoleActionGroup" stepKey="saveRoleFifthAttempt"/> <actionGroup ref="AssertMessageOnBackendActionGroup" stepKey="checkFifthSaveRoleError"/> <actionGroup ref="AdminFillRoleRequiredFieldsActionGroup" stepKey="fillFieldSixthAttempt"> <argument name="currentAdminPassword" value="{{_ENV.MAGENTO_ADMIN_PASSWORD}}INVALID" /> </actionGroup> - <actionGroup ref="AssertSaveRoleActionGroup" stepKey="saveRoleSixthAttempt"/> + <actionGroup ref="AdminSaveRoleActionGroup" stepKey="saveRoleSixthAttempt"/> <actionGroup ref="AssertAdminNotSuccessLoginActionGroup" stepKey="checkFifthError"> <argument name="message" value="Your account is temporarily disabled. Please try again later."/> </actionGroup> diff --git a/app/code/Magento/User/Test/Mftf/ActionGroup/AssertSaveRoleActionGroup.xml b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminSaveRoleActionGroup.xml similarity index 90% rename from app/code/Magento/User/Test/Mftf/ActionGroup/AssertSaveRoleActionGroup.xml rename to app/code/Magento/User/Test/Mftf/ActionGroup/AdminSaveRoleActionGroup.xml index 8ce91e216a3ae..2bc1261c2bae8 100644 --- a/app/code/Magento/User/Test/Mftf/ActionGroup/AssertSaveRoleActionGroup.xml +++ b/app/code/Magento/User/Test/Mftf/ActionGroup/AdminSaveRoleActionGroup.xml @@ -7,7 +7,7 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertSaveRoleActionGroup"> + <actionGroup name="AdminSaveRoleActionGroup"> <click selector="{{AdminCreateRoleSection.save}}" stepKey="saveRole"/> <waitForPageLoad stepKey="waitForSaveResultLoad"/> </actionGroup> From e99dac362a1a7afbd84c4056fda9d7206b7f7c49 Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko <lytvynen@adobe.com> Date: Wed, 24 Apr 2019 15:45:30 -0500 Subject: [PATCH 071/224] MAGETWO-99370: Shopping cart does not show all four digits of quantity. --- .../luma/Magento_Checkout/web/css/source/module/_cart.less | 2 +- .../luma/Magento_Checkout/web/css/source/module/_minicart.less | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_cart.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_cart.less index 71814cd0f0422..460a961830b43 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_cart.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_cart.less @@ -210,7 +210,7 @@ height: 36px; margin-top: -7px; text-align: center; - width: 45px; + width: 60px; } } diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less index 5ca3322403102..af94dd7b97bbb 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less @@ -371,7 +371,7 @@ .item-qty { margin-right: @indent__s; text-align: center; - width: 45px; + width: 60px; } .update-cart-item { From 0cf0e2e5de579a0ab0efeb256fc7d6c68fa1ff22 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Thu, 25 Apr 2019 11:06:18 +0300 Subject: [PATCH 072/224] MAGETWO-99152: Special Prices cannot save over 4 characters in Japanese Yen - The comma separator seems to be the issue --- .../Backend/TierPrice/UpdateHandler.php | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/UpdateHandler.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/UpdateHandler.php index 663b7facf4257..f1943bc108878 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/UpdateHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/UpdateHandler.php @@ -7,8 +7,9 @@ namespace Magento\Catalog\Model\Product\Attribute\Backend\TierPrice; -use Magento\Framework\EntityManager\Operation\ExtensionInterface; use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Locale\FormatInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\Catalog\Api\ProductAttributeRepositoryInterface; use Magento\Customer\Api\GroupManagementInterface; @@ -40,19 +41,26 @@ class UpdateHandler extends AbstractHandler */ private $tierPriceResource; + /** + * @var FormatInterface + */ + private $localeFormat; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository * @param \Magento\Customer\Api\GroupManagementInterface $groupManagement * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool * @param \Magento\Catalog\Model\ResourceModel\Product\Attribute\Backend\Tierprice $tierPriceResource + * @param FormatInterface|null $localeFormat */ public function __construct( StoreManagerInterface $storeManager, ProductAttributeRepositoryInterface $attributeRepository, GroupManagementInterface $groupManagement, MetadataPool $metadataPool, - Tierprice $tierPriceResource + Tierprice $tierPriceResource, + FormatInterface $localeFormat = null ) { parent::__construct($groupManagement); @@ -60,6 +68,7 @@ public function __construct( $this->attributeRepository = $attributeRepository; $this->metadataPoll = $metadataPool; $this->tierPriceResource = $tierPriceResource; + $this->localeFormat = $localeFormat ?: ObjectManager::getInstance()->get(FormatInterface::class); } /** @@ -125,8 +134,9 @@ private function updateValues(array $valuesToUpdate, array $oldValues): bool { $isChanged = false; foreach ($valuesToUpdate as $key => $value) { - if ((!empty($value['value']) && (float)$oldValues[$key]['price'] !== (float)$value['value']) - || $this->getPercentage($oldValues[$key]) !== $this->getPercentage($value) + if ((!empty($value['value']) + && (float)$oldValues[$key]['price'] !== $this->localeFormat->getNumber($value['value']) + ) || $this->getPercentage($oldValues[$key]) !== $this->getPercentage($value) ) { $price = new \Magento\Framework\DataObject( [ From aa6677f64388cafd9cebfbc3319855f320d6b297 Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Thu, 25 Apr 2019 12:01:05 -0500 Subject: [PATCH 073/224] MQE-4431: Convert DeleteCatalogPriceRuleEntityTest to MFTF - Adding arguments to the Action Group. - Updating Tests to include new arguments. --- .../Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml | 6 ++++-- .../Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml index 61e84ebdc4cf2..9f1467ccc3a91 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml @@ -56,17 +56,19 @@ <actionGroup name="CreateCatalogPriceRuleViaTheUi"> <arguments> <argument name="catalogRule" defaultValue="_defaultCatalogRule"/> + <argument name="customerGroup" defaultValue="General"/> + <argument name="disregardRules" defaultValue="Yes"/> </arguments> <fillField selector="{{AdminNewCatalogPriceRule.ruleName}}" userInput="{{catalogRule.name}}" stepKey="fillName1"/> <fillField selector="{{AdminNewCatalogPriceRule.description}}" userInput="{{catalogRule.description}}" stepKey="fillDescription1"/> <selectOption selector="{{AdminNewCatalogPriceRule.websites}}" userInput="{{catalogRule.website_ids[0]}}" stepKey="selectWebSite1"/> - <selectOption selector="{{AdminNewCatalogPriceRule.customerGroups}}" userInput="General" stepKey="selectCustomerGroup1"/> + <selectOption selector="{{AdminNewCatalogPriceRule.customerGroups}}" userInput="{{customerGroup}}" stepKey="selectCustomerGroup1"/> <scrollTo selector="{{AdminNewCatalogPriceRule.actionsTab}}" stepKey="scrollToActionTab1"/> <click selector="{{AdminNewCatalogPriceRule.actionsTab}}" stepKey="openActionDropdown1"/> <selectOption selector="{{AdminNewCatalogPriceRuleActions.apply}}" userInput="{{catalogRule.simple_action}}" stepKey="discountType1"/> <fillField selector="{{AdminNewCatalogPriceRuleActions.discountAmount}}" userInput="{{catalogRule.discount_amount}}" stepKey="fillDiscountValue1"/> - <selectOption selector="{{AdminNewCatalogPriceRuleActions.disregardRules}}" userInput="Yes" stepKey="discardSubsequentRules1"/> + <selectOption selector="{{AdminNewCatalogPriceRuleActions.disregardRules}}" userInput="{{disregardRules}}" stepKey="discardSubsequentRules1"/> <waitForPageLoad stepKey="waitForPageToLoad1"/> <scrollToTopOfPage stepKey="scrollToTop1"/> </actionGroup> diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml index 14d8b7fe35df7..19ffdfe65ba48 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml @@ -33,6 +33,8 @@ <actionGroup ref="CreateCatalogPriceRuleViaTheUi" stepKey="createCatalogPriceRuleViaTheUi1"> <argument name="catalogRule" value="DeleteActiveCatalogPriceRuleWithConditions"/> + <argument name="customerGroup" value="General"/> + <argument name="disregardRules" value="Yes"/> </actionGroup> <click selector="{{AdminNewCatalogPriceRule.save}}" stepKey="saveTheCatalogRule"/> @@ -162,6 +164,8 @@ <actionGroup ref="CreateCatalogPriceRuleViaTheUi" stepKey="createCatalogPriceRuleViaTheUi1"> <argument name="catalogRule" value="DeleteActiveCatalogPriceRuleWithConditions"/> + <argument name="customerGroup" value="General"/> + <argument name="disregardRules" value="Yes"/> </actionGroup> <click selector="{{AdminNewCatalogPriceRule.save}}" stepKey="saveTheCatalogRule"/> From 72051c9434962dfc09642fc958b97ef78efb05ff Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Thu, 25 Apr 2019 12:29:02 -0500 Subject: [PATCH 074/224] MQE-4431: Convert DeleteCatalogPriceRuleEntityTest to MFTF - Removing unnecessary assertion. - Completing unfinished comment. --- .../AdminDeleteCatalogPriceRuleEntityTest.xml | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml index 19ffdfe65ba48..02539110dc1a9 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleEntityTest.xml @@ -49,7 +49,7 @@ <deleteData createDataKey="createCategory1" stepKey="deleteCategoryFirst1"/> </after> - <!-- delete the simple product and catalog price rule --> + <!-- Delete the simple product and catalog price rule --> <amOnPage url="{{CatalogRulePage.url}}" stepKey="goToPriceRulePage1"/> <waitForPageLoad stepKey="waitForPriceRulePage"/> <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule1"> @@ -58,36 +58,33 @@ </actionGroup> <waitForPageLoad time="30" stepKey="waitForPageLoad1"/> - <!-- assert that the Success message is present after the delete --> + <!-- Assert that the Success message is present after the delete --> <see selector="{{AdminMessagesSection.successMessage}}" userInput="You deleted the rule." stepKey="seeDeletedRuleMessage1"/> - <!-- assert that the Grid Empty message is present after deleting --> - <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="assertDataGridEmptyMessage1"/> - - <!-- reindex --> + <!-- Reindex --> <magentoCLI command="cache:flush" stepKey="flushCache1"/> <magentoCLI command="indexer:reindex" stepKey="reindex1"/> - <!-- assert that the rule isn't present on the Category page --> + <!-- Assert that the rule isn't present on the Category page --> <amOnPage url="$$createCategory1.name$$.html" stepKey="goToStorefrontCategoryPage1"/> <waitForPageLoad stepKey="waitForPageLoad3"/> <dontSee selector="{{StorefrontCategoryProductSection.ProductCatalogRulePriceTitleByName($$createProduct1.name$$)}}" userInput="Regular Price" stepKey="dontSeeRegularPriceText1"/> <dontSeeElement selector="{{StorefrontCategoryProductSection.ProductCatalogRuleSpecialPriceTitleByName($$createProduct1.name$$)}}" stepKey="dontSeeSpecialPrice1"/> - <!-- assert that the rule isn't present on the Product page --> + <!-- Assert that the rule isn't present on the Product page --> <amOnPage url="$$createProduct1.name$$.html" stepKey="goToStorefrontProductPage1"/> <waitForPageLoad stepKey="waitForPageLoad4"/> <dontSee selector="{{StorefrontProductInfoMainSection.oldPriceTag}}" userInput="Regular Price" stepKey="dontSeeRegularPRiceText2"/> <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="$$createProduct1.price$$" stepKey="seeTrueProductPrice1"/> - <!-- assert that the rule isn't present in the Shopping Cart --> + <!-- Assert that the rule isn't present in the Shopping Cart --> <actionGroup ref="addToCartFromStorefrontProductPage" stepKey="addProductToShoppingCart1"> <argument name="productName" value="$$createProduct1.name$$"/> </actionGroup> <click selector="{{StorefrontMinicartSection.showCart}}" stepKey="openMiniShoppingCart1"/> <see selector="{{StorefrontMinicartSection.productPriceByName($$createProduct1.name$$)}}" userInput="$$createProduct1.price$$" stepKey="seeCorrectProductPrice1"/> - <!-- assert that the rule --> + <!-- Assert that the rule isn't present on the Checkout page --> <click selector="{{StorefrontMiniCartSection.goToCheckout}}" stepKey="goToCheckout1"/> <conditionalClick selector="{{CheckoutCartSummarySection.expandShoppingCartSummary}}" dependentSelector="{{CheckoutCartSummarySection.expandShoppingCartSummary}}" visible="true" stepKey="expandShoppingCartSummary1"/> <see selector="{{CheckoutCartProductSection.ProductRegularPriceByName($$createProduct1.name$$)}}" userInput="$$createProduct1.price$$" stepKey="seeCorrectProductPriceOnCheckout1"/> @@ -183,7 +180,7 @@ <deleteData createDataKey="createConfigProductAttribute1" stepKey="deleteConfigProductAttribute1"/> </after> - <!-- delete the simple product and catalog price rule --> + <!-- Delete the simple product and catalog price rule --> <amOnPage url="{{CatalogRulePage.url}}" stepKey="goToPriceRulePage1"/> <waitForPageLoad stepKey="waitForPriceRulePage"/> <actionGroup ref="deleteEntitySecondaryGrid" stepKey="deletePriceRule1"> @@ -193,25 +190,22 @@ <waitForPageLoad time="30" stepKey="waitForPageLoad1"/> <see selector="{{AdminMessagesSection.successMessage}}" userInput="You deleted the rule." stepKey="seeDeletedRuleMessage1"/> - <!-- assert that the Grid Empty message is present --> - <see selector="{{AdminDataGridTableSection.dataGridEmpty}}" userInput="We couldn't find any records." stepKey="assertDataGridEmptyMessage1"/> - - <!-- reindex --> + <!-- Reindex --> <magentoCLI command="cache:flush" stepKey="flushCache1"/> <magentoCLI command="indexer:reindex" stepKey="reindex1"/> - <!-- assert that the rule isn't present on the Category page --> + <!-- Assert that the rule isn't present on the Category page --> <amOnPage url="$$createCategory1.name$$.html" stepKey="goToStorefrontCategoryPage1"/> <waitForPageLoad stepKey="waitForPageLoad2"/> <see selector="{{StorefrontCategoryProductSection.ProductPriceByName($$createConfigProduct1.name$$)}}" userInput="$$createConfigChildProduct1.price$$" stepKey="seeRegularPriceText1"/> - <!-- assert that the rule isn't present on the Product page --> + <!-- Assert that the rule isn't present on the Product page --> <amOnPage url="{{StorefrontProductPage.url($$createConfigProduct1.custom_attributes[url_key]$$)}}" stepKey="goToStorefrontProductPage1"/> <waitForPageLoad stepKey="waitForPageLoad3"/> <dontSee selector="{{StorefrontProductInfoMainSection.oldPriceTag}}" userInput="Regular Price" stepKey="dontSeeRegularPriceText2"/> <see selector="{{StorefrontProductInfoMainSection.productPrice}}" userInput="$$createConfigChildProduct1.price$$" stepKey="seeTrueProductPrice1"/> - <!-- assert that the rule isn't present in the Shopping Cart --> + <!-- Assert that the rule isn't present in the Shopping Cart --> <selectOption selector="{{StorefrontProductInfoMainSection.productAttributeOptionsSelectButton}}" userInput="option1" stepKey="selectOption1"/> <click selector="{{StorefrontProductActionSection.addToCart}}" stepKey="addToCart1"/> <waitForPageLoad time="30" stepKey="waitForPageLoad4"/> From d87f852191f5f681823ad2bd77665436d2c5534c Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Fri, 26 Apr 2019 09:24:00 +0300 Subject: [PATCH 075/224] MAGETWO-98656: Purchasing a downloadable product as guest then creating an account on the onepagesuccess step doesn't link product with account --- ...tIsPresentInCustomerAccountActionGroup.xml | 20 +++++ ...ustomerFromOrderSuccessPageActionGroup.xml | 21 +++++ ...efrontCustomerDownloadableProductsPage.xml | 13 ++++ ...ontCustomerDownloadableProductsSection.xml | 14 ++++ .../Observer/UpdateLinkPurchasedObserver.php | 77 ++++++++++--------- .../Test/Mftf/Data/CatalogConfigData.xml | 21 +++++ ...loadableProductFromGuestToCustomerTest.xml | 65 ++++++++++++++++ 7 files changed, 194 insertions(+), 37 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAssertDownloadableProductIsPresentInCustomerAccountActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontRegisterCustomerFromOrderSuccessPageActionGroup.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDownloadableProductsPage.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Data/CatalogConfigData.xml create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Test/LinkDownloadableProductFromGuestToCustomerTest.xml diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAssertDownloadableProductIsPresentInCustomerAccountActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAssertDownloadableProductIsPresentInCustomerAccountActionGroup.xml new file mode 100644 index 0000000000000..2e4afbd803205 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAssertDownloadableProductIsPresentInCustomerAccountActionGroup.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontAssertDownloadableProductIsPresentInCustomerAccount"> + <arguments> + <argument name="product"/> + </arguments> + <amOnPage url="{{StorefrontCustomerDashboardPage.url}}" stepKey="goToMyAccountPage"/> + <click selector="{{StorefrontCustomerSidebarSection.sidebarTab('My Downloadable Products')}}" stepKey="clickDownloadableProducts"/> + <waitForPageLoad stepKey="waitForDownloadableProductsPageLoad" /> + <seeElement selector="{{StorefrontCustomerDownloadableProductsSection.productName(product.name)}}" stepKey="seeStorefontDownloadableProductsProductName" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontRegisterCustomerFromOrderSuccessPageActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontRegisterCustomerFromOrderSuccessPageActionGroup.xml new file mode 100644 index 0000000000000..5e24592bf017f --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontRegisterCustomerFromOrderSuccessPageActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontRegisterCustomerFromOrderSuccessPage"> + <arguments> + <argument name="customer" /> + </arguments> + <click selector="{{CheckoutSuccessRegisterSection.createAccountButton}}" stepKey="clickCreateAccountButton"/> + <fillField selector="{{StorefrontCustomerCreateFormSection.passwordField}}" userInput="{{customer.password}}" stepKey="typePassword"/> + <fillField selector="{{StorefrontCustomerCreateFormSection.confirmPasswordField}}" userInput="{{customer.password}}" stepKey="typeConfirmationPassword"/> + <click selector="{{StorefrontCustomerCreateFormSection.createAccountButton}}" stepKey="clickOnCreateAccount"/> + <see selector="{{StorefrontMessagesSection.success}}" userInput="Thank you for registering" stepKey="verifyAccountCreated"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDownloadableProductsPage.xml b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDownloadableProductsPage.xml new file mode 100644 index 0000000000000..9972ab576253f --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDownloadableProductsPage.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> + <page name="StorefrontCustomerDownloadableProductsPage" url="downloadable/customer/products/" area="storefront" module="Magento_Customer"> + <section name="StorefrontCustomerDownloadableProductsSection"/> + </page> +</pages> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml new file mode 100644 index 0000000000000..d45a774077ba0 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontCustomerDownloadableProductsSection"> + <element name="productName" type="text" selector="//table[@id='my-downloadable-products-table']//strong[contains(@class, 'product-name') and normalize-space(.)='{{productName}}']" parameterized="true"/> + </section> +</sections> diff --git a/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php b/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php index db391ccda6866..45add4eb0427c 100644 --- a/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php +++ b/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php @@ -3,78 +3,81 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -declare(strict_types=1); namespace Magento\Downloadable\Observer; +use Magento\Downloadable\Model\ResourceModel\Link\Purchased\Collection as PurchasedCollection; +use Magento\Downloadable\Model\ResourceModel\Link\Purchased\CollectionFactory; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; /** - * Assign Downloadable links to customer created after issuing guest order. + * Update link purchased observer */ class UpdateLinkPurchasedObserver implements ObserverInterface { /** * Core store config - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * + * @var ScopeConfigInterface */ private $scopeConfig; /** - * @var \Magento\Downloadable\Model\ResourceModel\Link\Purchased\CollectionFactory - */ - private $purchasedFactory; - - /** - * @var \Magento\Framework\DataObject\Copy + * Purchased links collection factory + * + * @var CollectionFactory */ - private $objectCopyService; + private $purchasedCollectionFactory; /** - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param \Magento\Downloadable\Model\ResourceModel\Link\Purchased\CollectionFactory $purchasedFactory - * @param \Magento\Framework\DataObject\Copy $objectCopyService + * @param ScopeConfigInterface $scopeConfig + * @param CollectionFactory $purchasedCollectionFactory */ public function __construct( - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\Downloadable\Model\ResourceModel\Link\Purchased\CollectionFactory $purchasedFactory, - \Magento\Framework\DataObject\Copy $objectCopyService + ScopeConfigInterface $scopeConfig, + CollectionFactory $purchasedCollectionFactory ) { $this->scopeConfig = $scopeConfig; - $this->purchasedFactory = $purchasedFactory; - $this->objectCopyService = $objectCopyService; + $this->purchasedCollectionFactory = $purchasedCollectionFactory; } /** - * Re-save order data after order update. + * Link customer_id to downloadable link purchased after update order * - * @param \Magento\Framework\Event\Observer $observer + * @param Observer $observer * @return $this */ - public function execute(\Magento\Framework\Event\Observer $observer) + public function execute(Observer $observer) { $order = $observer->getEvent()->getOrder(); - - if (!$order->getId()) { - //order not saved in the database + $orderId = $order->getId(); + $customerId = $order->getCustomerId(); + if (!$orderId || !$customerId) { return $this; } + $purchasedLinksCollection = $this->getPurchasedCollection((int)$orderId); + foreach ($purchasedLinksCollection as $linkPurchased) { + $linkPurchased->setCustomerId($customerId)->save(); + } - $purchasedLinks = $this->purchasedFactory->create()->addFieldToFilter( + return $this; + } + + /** + * Get purchased collection by order id + * + * @param int $orderId + * @return PurchasedCollection + */ + private function getPurchasedCollection(int $orderId): PurchasedCollection + { + $purchasedCollection = $this->purchasedCollectionFactory->create()->addFieldToFilter( 'order_id', - ['eq' => $order->getId()] + ['eq' => $orderId] ); - foreach ($purchasedLinks as $linkPurchased) { - $this->objectCopyService->copyFieldsetToTarget( - \downloadable_sales_copy_order::class, - 'to_downloadable', - $order, - $linkPurchased - ); - $linkPurchased->save(); - } - - return $this; + return $purchasedCollection; } } diff --git a/app/code/Magento/Downloadable/Test/Mftf/Data/CatalogConfigData.xml b/app/code/Magento/Downloadable/Test/Mftf/Data/CatalogConfigData.xml new file mode 100644 index 0000000000000..8bb81f9c7579d --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Data/CatalogConfigData.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="EnableGuestCheckoutWithDownloadableItems"> + <data key="path">catalog/downloadable/disable_guest_checkout</data> + <data key="scope_id">0</data> + <data key="value">0</data> + </entity> + <entity name="DisableGuestCheckoutWithDownloadableItems"> + <data key="path">catalog/downloadable/disable_guest_checkout</data> + <data key="scope_id">0</data> + <data key="value">1</data> + </entity> +</entities> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/LinkDownloadableProductFromGuestToCustomerTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/LinkDownloadableProductFromGuestToCustomerTest.xml new file mode 100644 index 0000000000000..21b69b292c2f3 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/LinkDownloadableProductFromGuestToCustomerTest.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="LinkDownloadableProductFromGuestToCustomerTest"> + <annotations> + <stories value="Customer Account"/> + <title value="Customer should see downloadable products after place order as guest and registering after that"/> + <description value="Verify that in 'My Downloadable Products' section in customer account user can see products."/> + <severity value="AVERAGE"/> + <testCaseId value="MC-16011"/> + </annotations> + <before> + <magentoCLI command="config:set {{EnableGuestCheckoutWithDownloadableItems.path}} {{EnableGuestCheckoutWithDownloadableItems.value}}" stepKey="enableGuestCheckoutWithDownloadableItems" /> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="DownloadableProductWithOneLink" stepKey="createProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="downloadableLink1" stepKey="addDownloadableLink"> + <requiredEntity createDataKey="createProduct"/> + </createData> + </before> + <after> + <magentoCLI command="config:set {{DisableGuestCheckoutWithDownloadableItems.path}} {{DisableGuestCheckoutWithDownloadableItems.value}}" stepKey="disableGuestCheckoutWithDownloadableItems" /> + <deleteData stepKey="deleteProduct" createDataKey="createProduct"/> + <deleteData stepKey="deleteCategory" createDataKey="createCategory"/> + </after> + <!--Step 1: Go to Storefront as Guest--> + <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> + <!--Step 2: Add virtual product to shopping cart--> + <amOnPage url="{{StorefrontProductPage.url($$createProduct.name$$)}}" stepKey="amOnStorefrontProductPage"/> + <actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="addProductToCart"> + <argument name="product" value="$$createProduct$$"/> + <argument name="productCount" value="1"/> + </actionGroup> + <!--Step 3: Go to checkout--> + <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart" /> + <!--Step 4: Checkout select Check/Money Order payment, fill required fields and click Update and Place Order--> + <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyOrderPayment"/> + <actionGroup ref="GuestCheckoutSelectPaymentAndFillNewBillingAddressActionGroup" stepKey="changeAddress"> + <argument name="customerVar" value="Simple_US_Customer_NY"/> + <argument name="customerAddressVar" value="US_Address_NY"/> + <argument name="paymentMethod" value="Check / Money order"/> + </actionGroup> + <click selector="{{CheckoutShippingSection.updateAddress}}" stepKey="saveAddress"/> + <actionGroup ref="CheckoutPlaceOrderActionGroup" stepKey="placeOrder"> + <argument name="orderNumberMessage" value="CONST.successGuestCheckoutOrderNumberMessage"/> + <argument name="emailYouMessage" value="CONST.successCheckoutEmailYouMessage" /> + </actionGroup> + <!--Step 5: Create customer account after placing order--> + <actionGroup ref="StorefrontRegisterCustomerFromOrderSuccessPage" stepKey="createCustomerAfterPlaceOrder"> + <argument name="customer" value="CustomerEntityOne"/> + </actionGroup> + <!--Step 6: Go To My Account -> My Downloadable Products and check if downloadable product link exist--> + <actionGroup ref="StorefrontAssertDownloadableProductIsPresentInCustomerAccount" stepKey="seeStorefontMyDownloadableProductsProductName"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + </test> +</tests> From 068a4ac279ba67f73a8ca29ed5b5993e186f0dea Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Fri, 26 Apr 2019 09:34:06 +0300 Subject: [PATCH 076/224] MAGETWO-98656: Purchasing a downloadable product as guest then creating an account on the onepagesuccess step doesn't link product with account --- .../Downloadable/Observer/UpdateLinkPurchasedObserver.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php b/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php index 45add4eb0427c..223a3ad66b3d3 100644 --- a/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php +++ b/app/code/Magento/Downloadable/Observer/UpdateLinkPurchasedObserver.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Downloadable\Observer; @@ -13,7 +14,7 @@ use Magento\Framework\Event\ObserverInterface; /** - * Update link purchased observer + * Assign Downloadable links to customer created after issuing guest order. */ class UpdateLinkPurchasedObserver implements ObserverInterface { From b502108760a0549dccbf76111352a2521f67af2e Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Fri, 26 Apr 2019 13:16:55 +0300 Subject: [PATCH 077/224] MAGETWO-98656: Purchasing a downloadable product as guest then creating an account on the onepagesuccess step doesn't link product with account --- ...roductIsPresentInCustomerAccountActionGroup.xml | 0 .../StorefrontCustomerDownloadableProductsPage.xml | 2 +- ...orefrontCustomerDownloadableProductsSection.xml | 14 ++++++++++++++ ...kDownloadableProductFromGuestToCustomerTest.xml | 8 +++++--- 4 files changed, 20 insertions(+), 4 deletions(-) rename app/code/Magento/{Customer => Downloadable}/Test/Mftf/ActionGroup/StorefrontAssertDownloadableProductIsPresentInCustomerAccountActionGroup.xml (100%) rename app/code/Magento/{Customer => Downloadable}/Test/Mftf/Page/StorefrontCustomerDownloadableProductsPage.xml (96%) create mode 100644 app/code/Magento/Downloadable/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAssertDownloadableProductIsPresentInCustomerAccountActionGroup.xml b/app/code/Magento/Downloadable/Test/Mftf/ActionGroup/StorefrontAssertDownloadableProductIsPresentInCustomerAccountActionGroup.xml similarity index 100% rename from app/code/Magento/Customer/Test/Mftf/ActionGroup/StorefrontAssertDownloadableProductIsPresentInCustomerAccountActionGroup.xml rename to app/code/Magento/Downloadable/Test/Mftf/ActionGroup/StorefrontAssertDownloadableProductIsPresentInCustomerAccountActionGroup.xml diff --git a/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDownloadableProductsPage.xml b/app/code/Magento/Downloadable/Test/Mftf/Page/StorefrontCustomerDownloadableProductsPage.xml similarity index 96% rename from app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDownloadableProductsPage.xml rename to app/code/Magento/Downloadable/Test/Mftf/Page/StorefrontCustomerDownloadableProductsPage.xml index 9972ab576253f..eafb37111fda2 100644 --- a/app/code/Magento/Customer/Test/Mftf/Page/StorefrontCustomerDownloadableProductsPage.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Page/StorefrontCustomerDownloadableProductsPage.xml @@ -7,7 +7,7 @@ --> <pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd"> - <page name="StorefrontCustomerDownloadableProductsPage" url="downloadable/customer/products/" area="storefront" module="Magento_Customer"> + <page name="StorefrontCustomerDownloadableProductsPage" url="downloadable/customer/products/" area="storefront" module="Magento_Downloadable"> <section name="StorefrontCustomerDownloadableProductsSection"/> </page> </pages> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml b/app/code/Magento/Downloadable/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml new file mode 100644 index 0000000000000..d45a774077ba0 --- /dev/null +++ b/app/code/Magento/Downloadable/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="StorefrontCustomerDownloadableProductsSection"> + <element name="productName" type="text" selector="//table[@id='my-downloadable-products-table']//strong[contains(@class, 'product-name') and normalize-space(.)='{{productName}}']" parameterized="true"/> + </section> +</sections> diff --git a/app/code/Magento/Downloadable/Test/Mftf/Test/LinkDownloadableProductFromGuestToCustomerTest.xml b/app/code/Magento/Downloadable/Test/Mftf/Test/LinkDownloadableProductFromGuestToCustomerTest.xml index 21b69b292c2f3..b960d15b2fdf1 100644 --- a/app/code/Magento/Downloadable/Test/Mftf/Test/LinkDownloadableProductFromGuestToCustomerTest.xml +++ b/app/code/Magento/Downloadable/Test/Mftf/Test/LinkDownloadableProductFromGuestToCustomerTest.xml @@ -14,6 +14,7 @@ <title value="Customer should see downloadable products after place order as guest and registering after that"/> <description value="Verify that in 'My Downloadable Products' section in customer account user can see products."/> <severity value="AVERAGE"/> + <useCaseId value="MAGETWO-98656"/> <testCaseId value="MC-16011"/> </annotations> <before> @@ -33,15 +34,15 @@ </after> <!--Step 1: Go to Storefront as Guest--> <amOnPage url="{{StorefrontHomePage.url}}" stepKey="amOnStorefrontPage"/> - <!--Step 2: Add virtual product to shopping cart--> - <amOnPage url="{{StorefrontProductPage.url($$createProduct.name$$)}}" stepKey="amOnStorefrontProductPage"/> + <!--Step 2: Add downloadable product to shopping cart--> + <amOnPage url="{{StorefrontProductPage.url($$createProduct.custom_attributes[url_key]$$)}}" stepKey="amOnStorefrontProductPage"/> <actionGroup ref="StorefrontAddProductToCartActionGroup" stepKey="addProductToCart"> <argument name="product" value="$$createProduct$$"/> <argument name="productCount" value="1"/> </actionGroup> <!--Step 3: Go to checkout--> <actionGroup ref="GoToCheckoutFromMinicartActionGroup" stepKey="goToCheckoutFromMinicart" /> - <!--Step 4: Checkout select Check/Money Order payment, fill required fields and click Update and Place Order--> + <!--Step 4: Select Check/Money Order payment, fill required fields and click Update and Place Order--> <actionGroup ref="CheckoutSelectCheckMoneyOrderPaymentActionGroup" stepKey="selectCheckMoneyOrderPayment"/> <actionGroup ref="GuestCheckoutSelectPaymentAndFillNewBillingAddressActionGroup" stepKey="changeAddress"> <argument name="customerVar" value="Simple_US_Customer_NY"/> @@ -49,6 +50,7 @@ <argument name="paymentMethod" value="Check / Money order"/> </actionGroup> <click selector="{{CheckoutShippingSection.updateAddress}}" stepKey="saveAddress"/> + <waitForPageLoad stepKey="waitUpdateAddress"/> <actionGroup ref="CheckoutPlaceOrderActionGroup" stepKey="placeOrder"> <argument name="orderNumberMessage" value="CONST.successGuestCheckoutOrderNumberMessage"/> <argument name="emailYouMessage" value="CONST.successCheckoutEmailYouMessage" /> From 7fc0a4daedc5e3db42d9f106edbfb9a0c2aeee08 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Fri, 26 Apr 2019 08:27:56 -0500 Subject: [PATCH 078/224] MC-4757: Convert MoveShoppingCartProductsOnOrderPageTest to MFTF --- .../Mftf/Test/AdminDeleteAttributeSetTest.xml | 2 +- ...nCustomerActivitiesShoppingCartSection.xml | 16 +++ .../AdminCustomerCreateNewOrderSection.xml | 17 +++ .../AdminCustomerMainActionsSection.xml | 1 + ...ableProductToOrderFromShoppingCartTest.xml | 117 ++++++++++++++++++ ...mpleProductToOrderFromShoppingCartTest.xml | 80 ++++++++++++ ...oveShoppingCartProductsOnOrderPageTest.xml | 4 +- 7 files changed, 234 insertions(+), 3 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesShoppingCartSection.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/AddSimpleProductToOrderFromShoppingCartTest.xml diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteAttributeSetTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteAttributeSetTest.xml index 4d28ccbd44d2c..87768fc23fbca 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteAttributeSetTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminDeleteAttributeSetTest.xml @@ -12,7 +12,7 @@ <features value="Catalog"/> <title value="Delete Attribute Set"/> <description value="Admin should be able to delete an attribute set"/> - <testCaseId value="MC-4413"/> + <testCaseId value="MC-10889"/> <severity value="CRITICAL"/> <group value="mtf_migrated"/> </annotations> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesShoppingCartSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesShoppingCartSection.xml new file mode 100644 index 0000000000000..fb8d05f4274cc --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesShoppingCartSection.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminCustomerActivitiesShoppingCartSection"> + <element name="productName" type="text" selector="//div[@id='sidebar_data_cart']//td[@class='col-item']"/> + <element name="productPrice" type="text" selector="//div[@id='sidebar_data_cart']//td[@class='col-price']"/> + <element name="addToOrder" type="checkbox" selector="//input[contains(@id, 'sidebar-add_cart_item')]"/> + </section> +</sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml new file mode 100644 index 0000000000000..79ec38cef0d0c --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminCustomerCreateNewOrderSection"> + <element name="updateChangesBtn" type="button" selector=".order-sidebar .actions .action-default.scalable" timeout="30"/> + <element name="productName" type="text" selector="#order-items_grid span[id*=order_item]"/> + <element name="productPrice" type="text" selector=".even td[class=col-price] span[class=price]"/> + <element name="productQty" type="input" selector="td[class=col-qty] input"/> + </section> +</sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerMainActionsSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerMainActionsSection.xml index 304068d89b729..18bc26bfd4987 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerMainActionsSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerMainActionsSection.xml @@ -13,5 +13,6 @@ <element name="saveAndContinue" type="button" selector="#save_and_continue" timeout="30"/> <element name="resetPassword" type="button" selector="#resetPassword" timeout="30"/> <element name="manageShoppingCart" type="button" selector="#manage_quote" timeout="30"/> + <element name="createOrderBtn" type="button" selector="#order" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml new file mode 100644 index 0000000000000..6d9f35efc7903 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/AddConfigurableProductToOrderFromShoppingCartTest.xml @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AddConfigurableProductToOrderFromShoppingCartTest"> + <annotations> + <features value="Sales"/> + <stories value="Add Products to Order from Shopping Cart"/> + <title value="Add configurable product to order from shopping cart test"/> + <description value="Add configurable product to order from shopping cart"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-16008"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create customer --> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <!-- Create category --> + <createData entity="_defaultCategory" stepKey="createCategory"/> + + <!-- Create configurable product --> + <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption"/> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct"/> + </createData> + </before> + <after> + <!-- Admin log out --> + <actionGroup ref="logout" stepKey="logout"/> + + <!-- Customer log out --> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> + + <!-- Delete customer --> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + + <!-- Delete configurable product data --> + <deleteData createDataKey="createConfigChildProduct" stepKey="deleteConfigChildProduct"/> + <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + + <!-- Delete category --> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + </after> + + <!-- Login as customer --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Add configurable product to the cart --> + <actionGroup ref="StorefrontAddConfigurableProductToTheCartActionGroup" stepKey="addConfigurableProductToCart"> + <argument name="urlKey" value="$$createConfigProduct.custom_attributes[url_key]$$" /> + <argument name="productAttribute" value="$$createConfigProductAttribute.default_value$$"/> + <argument name="productOption" value="$$getConfigAttributeOption.value$$"/> + <argument name="qty" value="1"/> + </actionGroup> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Search and open customer --> + <actionGroup ref="AdminFilterCustomerByEmail" stepKey="filterCreatedCustomer"> + <argument name="email" value="$$createCustomer.email$$"/> + </actionGroup> + <click selector="{{AdminCustomerGridSection.firstRowEditLink}}" stepKey="clickEditButton"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + + <!-- Click create order --> + <click selector="{{AdminCustomerMainActionsSection.createOrderBtn}}" stepKey="clickCreateOrder"/> + + <!-- Check product in customer's activities in shopping cart section --> + <see selector="{{AdminCustomerActivitiesShoppingCartSection.productName}}" userInput="$$createConfigProduct.name$$" stepKey="seeProductNameInShoppingCartSection"/> + <see selector="{{AdminCustomerActivitiesShoppingCartSection.productPrice}}" userInput="$$createConfigProduct.price$$" stepKey="seeProductPriceInShoppingCartSection"/> + + <!-- Click update changes --> + <checkOption selector="{{AdminCustomerActivitiesShoppingCartSection.addToOrder}}" stepKey="checkOptionAddToOrder"/> + <click selector="{{AdminCustomerCreateNewOrderSection.updateChangesBtn}}" stepKey="clickUpdateChangesBtn"/> + <waitForPageLoad stepKey="waitForOrderUpdating"/> + + <!-- Assert product in items ordered grid --> + <see selector="{{AdminCustomerCreateNewOrderSection.productName}}" userInput="$$createConfigProduct.name$$" stepKey="seeProductName"/> + <see selector="{{AdminCustomerCreateNewOrderSection.productPrice}}" userInput="$$createConfigProduct.price$$" stepKey="seeProductPrice"/> + <seeInField selector="{{AdminCustomerCreateNewOrderSection.productQty}}" userInput="{{ApiSimpleSingleQty.quantity}}" stepKey="seeProductQty"/> + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AddSimpleProductToOrderFromShoppingCartTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AddSimpleProductToOrderFromShoppingCartTest.xml new file mode 100644 index 0000000000000..76be3a1094327 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/AddSimpleProductToOrderFromShoppingCartTest.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AddSimpleProductToOrderFromShoppingCartTest"> + <annotations> + <features value="Sales"/> + <stories value="Add Products to Order from Shopping Cart"/> + <title value="Add simple product to order from shopping cart test"/> + <description value="Add simple product to order from shopping cart"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-16007"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create customer --> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <!-- Create product --> + <createData entity="SimpleProduct2" stepKey="createProduct"/> + </before> + <after> + <!-- Admin log out --> + <actionGroup ref="logout" stepKey="logout"/> + + <!-- Customer log out --> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> + + <!-- Delete customer --> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + + <!-- Delete product --> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + </after> + + <!-- Login as customer --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Add product to cart --> + <actionGroup ref="AddSimpleProductToCart" stepKey="addProductToCart"> + <argument name="product" value="$$createProduct$$"/> + </actionGroup> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Search and open customer --> + <actionGroup ref="AdminFilterCustomerByEmail" stepKey="filterCreatedCustomer"> + <argument name="email" value="$$createCustomer.email$$"/> + </actionGroup> + <click selector="{{AdminCustomerGridSection.firstRowEditLink}}" stepKey="clickEditButton"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + + <!-- Click create order --> + <click selector="{{AdminCustomerMainActionsSection.createOrderBtn}}" stepKey="clickCreateOrder"/> + + <!-- Check product in customer's activities in shopping cart section --> + <see selector="{{AdminCustomerActivitiesShoppingCartSection.productName}}" userInput="$$createProduct.name$$" stepKey="seeProductNameInShoppingCartSection"/> + <see selector="{{AdminCustomerActivitiesShoppingCartSection.productPrice}}" userInput="$$createProduct.price$$" stepKey="seeProductPriceInShoppingCartSection"/> + + <!-- Click update changes --> + <checkOption selector="{{AdminCustomerActivitiesShoppingCartSection.addToOrder}}" stepKey="checkOptionAddToOrder"/> + <click selector="{{AdminCustomerCreateNewOrderSection.updateChangesBtn}}" stepKey="clickUpdateChangesBtn"/> + <waitForPageLoad stepKey="waitForOrderUpdating"/> + + <!-- Assert product in items ordered grid --> + <see selector="{{AdminCustomerCreateNewOrderSection.productName}}" userInput="$$createProduct.name$$" stepKey="seeProductName"/> + <see selector="{{AdminCustomerCreateNewOrderSection.productPrice}}" userInput="$$createProduct.price$$" stepKey="seeProductPrice"/> + <seeInField selector="{{AdminCustomerCreateNewOrderSection.productQty}}" userInput="{{ApiSimpleSingleQty.quantity}}" stepKey="seeProductQty"/> + </test> +</tests> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveShoppingCartProductsOnOrderPageTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveShoppingCartProductsOnOrderPageTest.xml index f10ef041d4066..df84045585049 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveShoppingCartProductsOnOrderPageTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveShoppingCartProductsOnOrderPageTest.xml @@ -8,12 +8,12 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Sales\Test\TestCase\MoveShoppingCartProductsOnOrderPageTest" summary="Add Products to Order from Shopping Cart " ticketId="MAGETWO-28540"> <variation name="MoveShoppingCartProductsOnOrderPageTestVariation1"> - <data name="tag" xsi:type="string">stable:no</data> + <data name="tag" xsi:type="string">stable:no, mftf_migrated:yes</data> <data name="product" xsi:type="string">catalogProductSimple::default</data> <constraint name="Magento\Sales\Test\Constraint\AssertProductInItemsOrderedGrid" /> </variation> <variation name="MoveShoppingCartProductsOnOrderPageTestVariation2" firstConstraint="Magento\ConfigurableProduct\Test\Constraint\AssertConfigurableProductInItemsOrderedGrid" method="test"> - <data name="tag" xsi:type="string">stable:no</data> + <data name="tag" xsi:type="string">stable:no, mftf_migrated:yes</data> <data name="product" xsi:type="string">configurableProduct::configurable_with_qty_1</data> <constraint name="Magento\Sales\Test\Constraint\AssertProductInItemsOrderedGrid" /> </variation> From 4155016a5ac0331c8f17670c982cf3e31e3f7578 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Fri, 26 Apr 2019 11:44:21 -0500 Subject: [PATCH 079/224] MC-4760: Convert CreateInvoiceEntityTest to MFTF --- .../Test/Mftf/Section/StorefrontCustomerOrderSection.xml | 2 +- .../Mftf/ActionGroup/FilterShipmentGridByOrderIdActionGroup.xml | 2 ++ .../Sales/Test/Mftf/Section/StorefrontOrderInvoicesSection.xml | 2 +- .../Test/CreateInvoiceWithShipmentAndCheckInvoicedOrderTest.xml | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml index 6a7361bf3dcce..0d45c9810a68f 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml @@ -13,6 +13,6 @@ <element name="productCustomOptions" type="text" selector="//strong[contains(@class, 'product-item-name') and normalize-space(.)='{{var1}}']/following-sibling::*[contains(@class, 'item-options')]/dt[normalize-space(.)='{{var2}}']/following-sibling::dd[normalize-space(.)='{{var3}}']" parameterized="true"/> <element name="productCustomOptionsFile" type="text" selector="//strong[contains(@class, 'product-item-name') and normalize-space(.)='{{var1}}']/following-sibling::*[contains(@class, 'item-options')]/dt[normalize-space(.)='{{var2}}']/following-sibling::dd[contains(.,'{{var3}}')]" parameterized="true"/> <element name="productCustomOptionsLink" type="text" selector="//strong[contains(@class, 'product-item-name') and normalize-space(.)='{{var1}}']/following-sibling::*[contains(@class, 'item-options')]/dt[normalize-space(.)='{{var2}}']/following-sibling::dd//a[text() = '{{var3}}']" parameterized="true"/> - <element name="viewOrder" type="button" selector="//td[@class='col actions']/a[@class='action view']"/> + <element name="viewOrder" type="button" selector="//td[contains(concat(' ',normalize-space(@class),' '),' col actions ')]/a[contains(concat(' ',normalize-space(@class),' '),' action view ')]"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/FilterShipmentGridByOrderIdActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/FilterShipmentGridByOrderIdActionGroup.xml index 437601d6eba9e..020ada06276c0 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/FilterShipmentGridByOrderIdActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/FilterShipmentGridByOrderIdActionGroup.xml @@ -13,6 +13,8 @@ <argument name="orderId" type="string"/> </arguments> <amOnPage url="{{AdminShipmentPage.url}}" stepKey="goToShipments"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + <conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearOrderFilters"/> <click selector="{{AdminShipmentGridSection.filter}}" stepKey="clickFilter"/> <fillField selector="{{AdminShipmentsFilterSection.orderNum}}" userInput="{{orderId}}" stepKey="fillOrderIdForFilter"/> <click selector="{{AdminShipmentsFilterSection.applyFilters}}" stepKey="clickApplyFilters"/> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderInvoicesSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderInvoicesSection.xml index c7a1e67822c61..cbf9993b6a6c5 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderInvoicesSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderInvoicesSection.xml @@ -9,7 +9,7 @@ <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="StorefrontOrderInvoicesSection"> - <element name="invoiceTab" type="button" selector="//li[@class='nav item']/a[text()='Invoices']"/> + <element name="invoiceTab" type="button" selector="//a[contains(text(), 'Invoices')]"/> <element name="grandTotalPrice" type="text" selector="[data-th='Grand Total'] .price"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithShipmentAndCheckInvoicedOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithShipmentAndCheckInvoicedOrderTest.xml index 11f8bf519661c..30ca1f5175576 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithShipmentAndCheckInvoicedOrderTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/CreateInvoiceWithShipmentAndCheckInvoicedOrderTest.xml @@ -139,7 +139,7 @@ <!-- Assert shipment in grid --> <actionGroup ref="FilterShipmentGridByOrderIdActionGroup" stepKey="filterShipmentGridByOrderId"> - <argument name="orderId" value="$getOrderId"/> + <argument name="orderId" value="$getOrderId"/> </actionGroup> <click selector="{{AdminShipmentGridSection.firstRow}}" stepKey="openCreatedShipment"/> <waitForPageLoad stepKey="waitForShipmentDetailsPageToLoad"/> From be2a0c1513c6f7b2d6068646ee4bb971ed971853 Mon Sep 17 00:00:00 2001 From: Kavitha <kanair@adobe.com> Date: Fri, 26 Apr 2019 17:02:41 -0500 Subject: [PATCH 080/224] MC-4519: Convert PaymentMethodCompanyCreditTest to MFTF --- ...frontCheckoutCustomerSignInActionGroup.xml | 22 +++++++++ .../Mftf/Section/CheckoutShippingSection.xml | 3 ++ ...StorefrontCheckoutPaymentMethodSection.xml | 3 ++ .../Test/Mftf/Data/PaymentConfigData.xml | 47 +++++++++++++++++++ .../AdminInvoiceOrderInformationSection.xml | 1 + .../AdminOrderDetailsInformationSection.xml | 1 + .../Mftf/Section/AdminOrdersGridSection.xml | 1 + 7 files changed, 78 insertions(+) create mode 100644 app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCustomerSignInActionGroup.xml create mode 100644 app/code/Magento/Payment/Test/Mftf/Data/PaymentConfigData.xml diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCustomerSignInActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCustomerSignInActionGroup.xml new file mode 100644 index 0000000000000..8449f41741bfb --- /dev/null +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/StorefrontCheckoutCustomerSignInActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="StorefrontCheckoutCustomerSignInActionGroup"> + <arguments> + <argument name="customerEmail" type="string" defaultValue="$$createCustomer.email$$"/> + <argument name="password" type="string" defaultValue="$$createCustomer.password$$"/> + </arguments> + <fillField selector="{{CheckoutShippingSection.emailAddress}}" userInput="{{customerEmail}}" stepKey="fillEmailAddress"/> + <waitForElementVisible selector="{{CheckoutShippingSection.password}}" stepKey="waitForPasswordFieldToBeVisible"/> + <fillField selector="{{CheckoutShippingSection.password}}" userInput="{{password}}" stepKey="fillPassword"/> + <click selector="{{CheckoutShippingSection.loginButton}}" stepKey="clickLoginButton"/> + <waitForPageLoad stepKey="waitForLoginPageToLoad"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml index d825e10395145..f6578b7829438 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml @@ -36,5 +36,8 @@ <element name="stateInput" type="input" selector="input[name=region]"/> <element name="regionOptions" type="select" selector="select[name=region_id] option"/> <element name="editActiveAddress" type="button" selector="//div[@class='shipping-address-item selected-item']//span[text()='Edit']" timeout="30"/> + <element name="password" type="input" selector="#customer-password"/> + <element name="loginButton" type="button" selector="//button[@data-action='checkout-method-login']" timeout="30"/> + <element name="emailAddress" type="input" selector="#checkout-customer-email"/> </section> </sections> diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutPaymentMethodSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutPaymentMethodSection.xml index 9d9a96d2ea5e6..40214b9c11fb0 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutPaymentMethodSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontCheckoutPaymentMethodSection.xml @@ -13,5 +13,8 @@ <element name="checkPaymentMethodByName" type="radio" selector="//div[@id='checkout-payment-method-load']//div[@class='payment-method']//label//span[contains(., '{{methodName}}')]/../..//input" parameterized="true"/> <element name="billingAddressSameAsShipping" type="checkbox" selector=".payment-method._active [name='billing-address-same-as-shipping']"/> <element name="billingAddressSameAsShippingShared" type="checkbox" selector="#billing-address-same-as-shipping-shared"/> + <element name="paymentOnAccount" type="radio" selector="#companycredit"/> + <element name="paymentOnAccountLabel" type="text" selector="//span[text()='Payment on Account']"/> + <element name="purchaseOrderNumber" type="input" selector="#po_number"/> </section> </sections> diff --git a/app/code/Magento/Payment/Test/Mftf/Data/PaymentConfigData.xml b/app/code/Magento/Payment/Test/Mftf/Data/PaymentConfigData.xml new file mode 100644 index 0000000000000..706414fa86eb7 --- /dev/null +++ b/app/code/Magento/Payment/Test/Mftf/Data/PaymentConfigData.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="EnablePaymentCheckMOConfigData"> + <data key="path">payment/checkmo/active</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="DisablePaymentCheckMOConfigData"> + <data key="path">payment/checkmo/active</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="EnablePaymentBankTransferConfigData"> + <data key="path">payment/banktransfer/active</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="DisablePaymentBankTransferConfigData"> + <data key="path">payment/banktransfer/active</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="EnablePaymentCashOnDeliveryData"> + <data key="path">payment/cashondelivery/active</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> + <entity name="DisablePaymentCashOnDeliveryData"> + <data key="path">payment/cashondelivery/active</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> +</entities> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceOrderInformationSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceOrderInformationSection.xml index 38ca7e683fe56..f05baf248ed69 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceOrderInformationSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminInvoiceOrderInformationSection.xml @@ -16,5 +16,6 @@ <element name="customerName" type="text" selector=".order-account-information table tr:first-of-type > td span"/> <element name="customerEmail" type="text" selector=".order-account-information table tr:nth-of-type(2) > td a"/> <element name="customerGroup" type="text" selector=".order-account-information table tr:nth-of-type(3) > td"/> + <element name="invoiceNoteComment" type="text" selector="div.note-list-comment"/> </section> </sections> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml index a531f423d134c..4d37479a8cd18 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsInformationSection.xml @@ -19,5 +19,6 @@ <element name="billingAddress" type="text" selector=".order-billing-address"/> <element name="shippingAddress" type="text" selector=".order-shipping-address"/> <element name="itemsOrdered" type="text" selector=".edit-order-table"/> + <element name="paymentInformation" type="text" selector="//div[@class='order-payment-method-title']"/> </section> </sections> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml index 53a6cbffcdac6..c87a1b70cb8fb 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml @@ -31,5 +31,6 @@ <element name="viewColumnCheckbox" type="checkbox" selector="//div[contains(@class,'admin__data-grid-action-columns')]//div[contains(@class, 'admin__field-option')]//label[text() = '{{column}}']/preceding-sibling::input" parameterized="true"/> <element name="customerInOrdersSection" type="button" selector="(//td[contains(text(),'{{customer}}')])[1]" parameterized="true"/> <element name="productForOrder" type="button" selector="//td[contains(text(),'{{var}}')]" parameterized="true"/> + <element name="viewLink" type="text" selector="//td/div[contains(.,'{{orderID}}')]/../..//a[@class='action-menu-item']" parameterized="true"/> </section> </sections> From 5255dac7acc5720751662b16f072ece82761210c Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza <enarc@atwix.com> Date: Sun, 28 Apr 2019 14:22:56 +0300 Subject: [PATCH 081/224] Refactoring. Use action groups and config data --- .../AssertAdminPageIsNot404ActionGroup.xml | 14 ++++++++++++++ .../Test/Mftf/Section/AdminHeaderSection.xml | 2 ++ .../Test/AdminLoginAfterJSMinificationTest.xml | 12 ++++++++---- .../Config/Test/Mftf/Data/SystemConfigData.xml | 15 +++++++++++++++ .../TestCase/LoginAfterJSMinificationTest.xml | 3 +-- 5 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminPageIsNot404ActionGroup.xml diff --git a/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminPageIsNot404ActionGroup.xml b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminPageIsNot404ActionGroup.xml new file mode 100644 index 0000000000000..eaf7c7cd8a6ab --- /dev/null +++ b/app/code/Magento/Backend/Test/Mftf/ActionGroup/AssertAdminPageIsNot404ActionGroup.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertAdminPageIsNot404ActionGroup"> + <dontSee userInput="404 Error" selector="{{AdminHeaderSection.pageHeading}}" stepKey="dontSee404PageHeading"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Backend/Test/Mftf/Section/AdminHeaderSection.xml b/app/code/Magento/Backend/Test/Mftf/Section/AdminHeaderSection.xml index 5b517c7be8a79..6475d0a3c8166 100644 --- a/app/code/Magento/Backend/Test/Mftf/Section/AdminHeaderSection.xml +++ b/app/code/Magento/Backend/Test/Mftf/Section/AdminHeaderSection.xml @@ -11,5 +11,7 @@ <section name="AdminHeaderSection"> <element name="pageTitle" type="text" selector=".page-header h1.page-title"/> <element name="adminUserAccountText" type="text" selector=".page-header .admin-user-account-text" /> + <!-- Legacy heading section. Mostly used for admin 404 and 403 pages --> + <element name="pageHeading" type="text" selector=".page-content .page-heading"/> </section> </sections> diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml index 8d2a1fa374be0..4be6d18d92020 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml @@ -17,11 +17,15 @@ <group value="mtf_migrated"/> </annotations> <before> - <magentoCLI command="config:set dev/js/minify_files 1" stepKey="enableJsMinification"/> - <magentoCLI command="cache:clean config" stepKey="cleanCache"/> + <magentoCLI command="config:set {{MinifyJavaScriptFilesEnableConfigData.path}} {{MinifyJavaScriptFilesEnableConfigData.value}}" stepKey="enableJsMinification"/> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> </before> + <after> + <magentoCLI command="config:set {{MinifyJavaScriptFilesDisableConfigData.path}} {{MinifyJavaScriptFilesDisableConfigData.value}}" stepKey="disableJsMinification"/> + <actionGroup ref="logout" stepKey="logout"/> + </after> - <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <see userInput="Dashboard" selector="{{AdminHeaderSection.pageTitle}}" stepKey="seeDashboardTitle"/> + <actionGroup ref="AssertAdminSuccessLoginActionGroup" stepKey="loggedInSuccessfully"/> + <actionGroup ref="AssertAdminPageIsNot404ActionGroup" stepKey="dontSee404Page"/> </test> </tests> diff --git a/app/code/Magento/Config/Test/Mftf/Data/SystemConfigData.xml b/app/code/Magento/Config/Test/Mftf/Data/SystemConfigData.xml index 85188eb6e04cb..7b838dffd7661 100644 --- a/app/code/Magento/Config/Test/Mftf/Data/SystemConfigData.xml +++ b/app/code/Magento/Config/Test/Mftf/Data/SystemConfigData.xml @@ -20,4 +20,19 @@ <entity name="DisableAdminAccountSharing" type="admin_account_sharing_config"> <requiredEntity type="admin_account_sharing_value">AdminAccountSharingNo</requiredEntity> </entity> + <entity name="MinifyJavaScriptFilesDisableConfigData"> + <!-- Default value --> + <data key="path">dev/js/minify_files</data> + <data key="scope">admin</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="MinifyJavaScriptFilesEnableConfigData"> + <data key="path">dev/js/minify_files</data> + <data key="scope">admin</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> </entities> diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/LoginAfterJSMinificationTest.xml b/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/LoginAfterJSMinificationTest.xml index 1177b02241101..e63efd4db9900 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/LoginAfterJSMinificationTest.xml +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/LoginAfterJSMinificationTest.xml @@ -8,11 +8,10 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Backend\Test\TestCase\LoginAfterJSMinificationTest" summary="Verify login is successful after JS minification is enabled"> <variation name="LoginAfterJSMinificationEnabledVariation1" summary="Verify login is successful after JS minification" ticketId="MAGETWO-71416"> - <data name="tag" xsi:type="string">severity:S1</data> + <data name="tag" xsi:type="string">severity:S1,mftf_migrated:yes</data> <data name="configData" xsi:type="string">minify_js_files</data> <data name="menuItem" xsi:type="string">Dashboard</data> <data name="pageTitle" xsi:type="string">Dashboard</data> - <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Backend\Test\Constraint\AssertBackendPageIsAvailable" /> </variation> </testCase> From 33c322ba0f05fc1f3258d95ed1a8a746e6dbca0b Mon Sep 17 00:00:00 2001 From: Oscar Recio <osrecio@gmail.com> Date: Mon, 29 Apr 2019 12:07:10 +0200 Subject: [PATCH 082/224] #628 Check if email or password are empty --- .../Model/Resolver/GenerateCustomerToken.php | 4 +- .../Customer/GenerateCustomerTokenTest.php | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CustomerGraphQl/Model/Resolver/GenerateCustomerToken.php b/app/code/Magento/CustomerGraphQl/Model/Resolver/GenerateCustomerToken.php index 1bd77fe1cde8f..2a7cb8a734a50 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Resolver/GenerateCustomerToken.php +++ b/app/code/Magento/CustomerGraphQl/Model/Resolver/GenerateCustomerToken.php @@ -44,11 +44,11 @@ public function resolve( array $value = null, array $args = null ) { - if (!isset($args['email'])) { + if (!isset($args['email']) || empty($args['email'])) { throw new GraphQlInputException(__('Specify the "email" value.')); } - if (!isset($args['password'])) { + if (!isset($args['password']) || empty($args['password'])) { throw new GraphQlInputException(__('Specify the "password" value.')); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php index 88eaeaa8f9dd5..e13c1974e3067 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/GenerateCustomerTokenTest.php @@ -68,4 +68,54 @@ public function testGenerateCustomerTokenWithInvalidCredentials() 'was incorrect or your account is disabled temporarily. Please wait and try again later.'); $this->graphQlMutation($mutation); } + + /** + * Verify customer with empty email + */ + public function testGenerateCustomerTokenWithEmptyEmail() + { + $email = ''; + $password = 'bad-password'; + + $mutation + = <<<MUTATION +mutation { + generateCustomerToken( + email: "{$email}" + password: "{$password}" + ) { + token + } +} +MUTATION; + + $this->expectException(\Exception::class); + $this->expectExceptionMessage('GraphQL response contains errors: Specify the "email" value.'); + $this->graphQlMutation($mutation); + } + + /** + * Verify customer with empty password + */ + public function testGenerateCustomerTokenWithEmptyPassword() + { + $email = 'customer@example.com'; + $password = ''; + + $mutation + = <<<MUTATION +mutation { + generateCustomerToken( + email: "{$email}" + password: "{$password}" + ) { + token + } +} +MUTATION; + + $this->expectException(\Exception::class); + $this->expectExceptionMessage('GraphQL response contains errors: Specify the "password" value.'); + $this->graphQlMutation($mutation); + } } From 601cd319e53ba109b430eecb04dc877085732dfc Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy <dpoperechnyy@magento.com> Date: Mon, 29 Apr 2019 15:52:09 -0500 Subject: [PATCH 083/224] MC-16046: Leverage the font-display CSS feature to ensure text is user-visible while webfonts are loading --- .../Magento/blank/web/css/source/_icons.less | 3 ++- .../Magento/blank/web/css/source/_typography.less | 12 ++++++++---- lib/web/css/source/lib/_typography.less | 4 +++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/app/design/frontend/Magento/blank/web/css/source/_icons.less b/app/design/frontend/Magento/blank/web/css/source/_icons.less index 7d1ceaca73c72..52ae8a0e8c707 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_icons.less +++ b/app/design/frontend/Magento/blank/web/css/source/_icons.less @@ -8,6 +8,7 @@ @family-name: @icons__font-name, @font-path: @icons__font-path, @font-weight: normal, - @font-style: normal + @font-style: normal, + @font-display: swap ); } diff --git a/app/design/frontend/Magento/blank/web/css/source/_typography.less b/app/design/frontend/Magento/blank/web/css/source/_typography.less index 8ce76fad97902..6807c0f692af8 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_typography.less +++ b/app/design/frontend/Magento/blank/web/css/source/_typography.less @@ -12,28 +12,32 @@ @family-name: @font-family-name__base, @font-path: '@{baseDir}fonts/opensans/light/opensans-300', @font-weight: 300, - @font-style: normal + @font-style: normal, + @font-display: swap ); .lib-font-face( @family-name: @font-family-name__base, @font-path: '@{baseDir}fonts/opensans/regular/opensans-400', @font-weight: 400, - @font-style: normal + @font-style: normal, + @font-display: swap ); .lib-font-face( @family-name: @font-family-name__base, @font-path: '@{baseDir}fonts/opensans/semibold/opensans-600', @font-weight: 600, - @font-style: normal + @font-style: normal, + @font-display: swap ); .lib-font-face( @family-name: @font-family-name__base, @font-path: '@{baseDir}fonts/opensans/bold/opensans-700', @font-weight: 700, - @font-style: normal + @font-style: normal, + @font-display: swap ); } diff --git a/lib/web/css/source/lib/_typography.less b/lib/web/css/source/lib/_typography.less index 62529fe08d1c8..2b8065b634d41 100644 --- a/lib/web/css/source/lib/_typography.less +++ b/lib/web/css/source/lib/_typography.less @@ -11,7 +11,8 @@ @family-name, @font-path, @font-weight: normal, - @font-style: normal + @font-style: normal, + @font-display: swap ) { @font-face { font-family: @family-name; @@ -19,6 +20,7 @@ url('@{font-path}.woff') format('woff'); font-weight: @font-weight; font-style: @font-style; + font-display: @font-display; } } From a2fc3b98bf52ff7741579d16042b9c6376ecebfc Mon Sep 17 00:00:00 2001 From: Grzegorz Bogusz <grz.bogusz@gmail.com> Date: Tue, 30 Apr 2019 11:57:28 +0200 Subject: [PATCH 084/224] Additional condition in getRegion() method Added additional condition in getRegion() method to prevent Magento from throwing error in VatValidator::validate method. --- app/code/Magento/Customer/Model/Address/AbstractAddress.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php index d8d0646b30bb8..158461b4d9c17 100644 --- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php +++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php @@ -375,6 +375,8 @@ public function getRegion() } } elseif (is_string($region)) { $this->setData('region', $region); + } elseif (!$regionId && is_array($region)) { + $this->setData('region', $regionId); } return $this->getData('region'); From 175f6591b806847c2b2064ee4887f290e9102973 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Tue, 30 Apr 2019 15:22:44 +0300 Subject: [PATCH 085/224] MAGETWO-98832: Multistore Allowed Countries List Problem --- .../Magento/Customer/Model/AccountManagement.php | 1 + app/code/Magento/Quote/Model/Quote.php | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index ca90a32159354..9a197a37fb483 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -1085,6 +1085,7 @@ public function validate(CustomerInterface $customer) $result = $this->getEavValidator()->isValid($customerModel); if ($result === false && is_array($this->getEavValidator()->getMessages())) { return $validationResults->setIsValid(false)->setMessages( + // phpcs:ignore Magento2.Functions.DiscouragedFunction call_user_func_array( 'array_merge', $this->getEavValidator()->getMessages() diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php index 6ee81c8680dcd..82b7913446fd0 100644 --- a/app/code/Magento/Quote/Model/Quote.php +++ b/app/code/Magento/Quote/Model/Quote.php @@ -1386,7 +1386,7 @@ public function addShippingAddress(\Magento\Quote\Api\Data\AddressInterface $add * Retrieve quote items collection * * @param bool $useCache - * @return \Magento\Eav\Model\Entity\Collection\AbstractCollection + * @return \Magento\Eav\Model\Entity\Collection\AbstractCollection */ public function getItemsCollection($useCache = true) { @@ -1441,7 +1441,7 @@ public function getAllVisibleItems() */ public function hasItems() { - return sizeof($this->getAllItems()) > 0; + return count($this->getAllItems()) > 0; } /** @@ -1500,7 +1500,7 @@ public function getItemById($itemId) /** * Delete quote item. If it does not have identifier then it will be only removed from collection * - * @param \Magento\Quote\Model\Quote\Item $item + * @param \Magento\Quote\Model\Quote\Item $item * @return $this */ public function deleteItem(\Magento\Quote\Model\Quote\Item $item) @@ -1530,7 +1530,7 @@ public function deleteItem(\Magento\Quote\Model\Quote\Item $item) /** * Remove quote item by item identifier * - * @param int $itemId + * @param int $itemId * @return $this */ public function removeItem($itemId) @@ -1581,7 +1581,7 @@ public function removeAllItems() /** * Adding new item to quote * - * @param \Magento\Quote\Model\Quote\Item $item + * @param \Magento\Quote\Model\Quote\Item $item * @return $this * @throws \Magento\Framework\Exception\LocalizedException */ @@ -2375,7 +2375,7 @@ public function hasVirtualItems() /** * Merge quotes * - * @param Quote $quote + * @param Quote $quote * @return $this */ public function merge(Quote $quote) @@ -2613,7 +2613,7 @@ public function setExtensionAttributes(\Magento\Quote\Api\Data\CartExtensionInte * Check is address allowed for store * * @param Address $address - * @param int|null $storeId + * @param int|null $storeId * @return bool */ private function isAddressAllowedForWebsite(Address $address, $storeId): bool From b6adea76f2f965f68fc874bc9f8c4b2f3de5e299 Mon Sep 17 00:00:00 2001 From: sathakur <sathakur@adobe.com> Date: Tue, 30 Apr 2019 08:55:28 -0500 Subject: [PATCH 086/224] MC-4761: Convert UnassignCustomOrderStatusTest to MFTF --- .../AdminAssignOrderStatusToStateSection.xml | 15 +++++ .../Section/AdminOrderStatusGridSection.xml | 3 + .../AdminUnassignCustomOrderStatusTest.xml | 66 +++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/AdminAssignOrderStatusToStateSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminAssignOrderStatusToStateSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminAssignOrderStatusToStateSection.xml new file mode 100644 index 0000000000000..42a870e41f453 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminAssignOrderStatusToStateSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminAssignOrderStatusToStateSection"> + <element name="orderStatus" type="select" selector="#container [name=status]"/> + <element name="orderState" type="select" selector="#container [name=state]"/> + <element name="saveStatusAssignment" type="button" selector="#save" timeout="30"/> + </section> +</sections> \ No newline at end of file diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderStatusGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderStatusGridSection.xml index b624639281187..050035840bfcb 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderStatusGridSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderStatusGridSection.xml @@ -12,5 +12,8 @@ <element name="statusCodeFilterField" type="input" selector="[data-role=filter-form] [name=status]"/> <element name="statusCodeDataColumn" type="input" selector="[data-role=row] [data-column=status]"/> <element name="statusLabelDataColumn" type="input" selector="[data-role=row] [data-column=label]"/> + <element name="stateCodeAndTitleDataColumn" type="input" selector="[data-role=row] [data-column=state]"/> + <element name="assignStatusToStateButton" type="button" selector="#assign" timeout="30"/> + <element name="unassign" type="text" selector="[data-role=row] [data-column=unassign]"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml new file mode 100644 index 0000000000000..ed8a487159ec3 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminUnassignCustomOrderStatusTest"> + <annotations> + <stories value="UnassignCustomOrderStatus"/> + <title value="Admin Unassign Custom Order Status Test"/> + <description value="Test log in to Sales and Unassign Custom Order Status Test"/> + <testCaseId value="MC-16060"/> + <severity value="CRITICAL"/> + <group value="Sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <!--Go to new order status page--> + <amOnPage url="{{AdminOrderStatusPage.url}}" stepKey="goToOrderStatusPage"/> + <click selector="{{AdminMainActionsSection.add}}" stepKey="clickCreateNewStatus"/> + <!--Fill the form and validate save success message--> + <actionGroup ref="AdminOrderStatusFormFillAndSave" stepKey="fillFormAndClickSave"> + <argument name="status" value="{{defaultOrderStatus.status}}"/> + <argument name="label" value="{{defaultOrderStatus.label}}"/> + </actionGroup> + <actionGroup ref="AssertOrderStatusFormSaveSuccess" stepKey="seeFormSaveSuccess"/> + </before> + <after> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!--Open the created order status in grid page and change the order state to Pending and verify save message--> + <actionGroup ref="AssertOrderStatusExistsInGrid" stepKey="searchCreatedOrderStatus"> + <argument name="status" value="{{defaultOrderStatus.status}}"/> + <argument name="label" value="{{defaultOrderStatus.label}}"/> + </actionGroup> + <click selector="{{AdminOrderStatusGridSection.assignStatusToStateButton}}" stepKey="clickAssignStatusToStateButton"/> + <waitForPageLoad stepKey="waitForAssignOrderStatusToStateLoad"/> + <selectOption selector="{{AdminAssignOrderStatusToStateSection.orderStatus}}" userInput="{{defaultOrderStatus.label}}" stepKey="selectOrderStatus"/> + <waitForPageLoad stepKey="waitForOrderStatusLoad"/> + <selectOption selector="{{AdminAssignOrderStatusToStateSection.orderState}}" userInput="Pending" stepKey="selectPendingInOrderState"/> + <click selector="{{AdminAssignOrderStatusToStateSection.saveStatusAssignment}}" stepKey="clickSaveStatusAssignmentButton"/> + + <!--Verify the order status grid page shows the updated order status--> + <actionGroup ref="AssertOrderStatusExistsInGrid" stepKey="searchUpdatedOrderStatus"> + <argument name="status" value="{{defaultOrderStatus.status}}"/> + <argument name="label" value="{{defaultOrderStatus.label}}"/> + </actionGroup> + <!--Click unassign and verify AssertOrderStatusSuccessUnassignMessage--> + <click selector="{{AdminOrderStatusGridSection.unassign}}" stepKey="clickUnassign"/> + <see selector="{{AdminMessagesSection.success}}" userInput="You have unassigned the order status." stepKey="seeAssertOrderStatusSuccessUnassignMessage"/> + + <!--Verify the order status grid page shows the updated order status and verify AssertOrderStatusInGrid--> + <actionGroup ref="AssertOrderStatusExistsInGrid" stepKey="seeAssertOrderStatusInGrid"> + <argument name="status" value="{{defaultOrderStatus.status}}"/> + <argument name="label" value="{{defaultOrderStatus.label}}"/> + </actionGroup> + <!--Verify the order status grid page shows the updated order status and verify AssertOrderStatusNotAssigned--> + <dontSee selector="{{AdminOrderStatusGridSection.stateCodeAndTitleDataColumn}}" stepKey="seeEmptyStateCodeAndTitleValue"/> + <dontSee selector="{{AdminOrderStatusGridSection.unassign}}" stepKey="seeAssertOrderStatusNotAssigned"/> + </test> +</tests> \ No newline at end of file From 81daba855c0e741b3659fb109556115638e15f5d Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Fri, 22 Mar 2019 14:53:44 +0200 Subject: [PATCH 087/224] Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../Model/Cart/AddSimpleProductToCart.php | 18 +++++++++++++++++- app/code/Magento/QuoteGraphQl/etc/di.xml | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index ad730288e5cc2..36a31642e5139 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -15,6 +15,7 @@ use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\Stdlib\ArrayManager; use Magento\Quote\Model\Quote; +use phpDocumentor\Reflection\Types\Mixed_; /** * Add simple product to cart @@ -140,7 +141,9 @@ private function extractCustomizableOptions(array $cartItemData): array $customizableOptionsData = []; foreach ($customizableOptions as $customizableOption) { - $customizableOptionsData[$customizableOption['id']] = $customizableOption['value']; + $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptions( + $customizableOption['value'] + ); } return $customizableOptionsData; } @@ -161,4 +164,17 @@ private function createBuyRequest(float $quantity, array $customOptions): DataOb ], ]); } + + /** + * @param string $value + * @return string|array + */ + private function convertCustomOptions(string $value) + { + if (substr($value, 0, 1) === "[" || + substr($value, strlen($value) - 1, 1) === "]") { + return explode(',', substr($value, 1, -1)); + } + return $value; + } } diff --git a/app/code/Magento/QuoteGraphQl/etc/di.xml b/app/code/Magento/QuoteGraphQl/etc/di.xml index 0697761a2a2a6..32b8b12987ffa 100644 --- a/app/code/Magento/QuoteGraphQl/etc/di.xml +++ b/app/code/Magento/QuoteGraphQl/etc/di.xml @@ -26,7 +26,7 @@ <item name="area" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Text</item> <item name="drop_down" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Dropdown</item> <item name="radio" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Dropdown</item> - <item name="checkbox" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Dropdown</item> + <item name="checkbox" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Multiple</item> <item name="multiple" xsi:type="string">Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Multiple</item> </argument> </arguments> From 742e6a79c733819744c6afa75dd1cde1dac2824c Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Thu, 28 Mar 2019 08:31:35 +0200 Subject: [PATCH 088/224] Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../Model/Cart/AddSimpleProductToCart.php | 1 - .../CatalogInventory/AddProductToCartTest.php | 83 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index 36a31642e5139..cf65393b08997 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -15,7 +15,6 @@ use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\Stdlib\ArrayManager; use Magento\Quote\Model\Quote; -use phpDocumentor\Reflection\Types\Mixed_; /** * Add simple product to cart diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 6f27693eeb4a7..c2fbfc1418dbf 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -46,6 +46,89 @@ public function testAddProductIfQuantityIsNotAvailable() $this->graphQlMutation($query); } + /** + * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + * @expectedException \Exception + * @expectedExceptionMessage The product's required option(s) weren't entered. Make sure the options are entered and try again. + */ + public function testAddProductWithoutRequiredCustomOPtions() + { + $sku = 'simple_with_custom_options'; + $qty = 1; + + $maskedQuoteId = $this->getMaskedQuoteId(); + $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php + * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php + */ + public function testAddProductWithRequiredCustomOPtions() + { + $sku = 'simple_with_custom_options'; + $qty = 1; + $productCustomOptions = Bootstrap::getObjectManager() + ->get(\Magento\Catalog\Api\ProductCustomOptionRepositoryInterface::class) + ->getList($sku); + $customizableOptions = ''; + foreach ($productCustomOptions as $option) { + $value = $option->getValues() ? + '[' . key($option->getValues()) . ']' : + 'Test'; + $customizableOptions .= ' { + id: ' . $option->getId() . ' + value: "' . $value . '" + }'; + } + + $maskedQuoteId = $this->getMaskedQuoteId(); + $query = <<<QUERY +mutation { + addSimpleProductsToCart( + input: { + cart_id: "{$maskedQuoteId}" + cartItems: { + data: { + qty: {$qty} + sku: "{$sku}" + } + customizable_options: [ + {$customizableOptions} + ] + } + } + ) +{ + cart { + items { + product { + sku + } + ... on SimpleCartItem { + customizable_options { + id + is_required + sort_order + } + } + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); + + self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); + self::assertEquals( + 1, + $response['addSimpleProductsToCart']['cart']['items'][0]['customizable_options'][0]['is_required'] + ); + } + /** * @magentoApiDataFixture Magento/Catalog/_files/products.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php From 30bc7b764590cb030eb57a4af3011fae77b5ddf4 Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Wed, 3 Apr 2019 09:10:08 +0300 Subject: [PATCH 089/224] Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index cf65393b08997..bd81a15307e31 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -170,7 +170,7 @@ private function createBuyRequest(float $quantity, array $customOptions): DataOb */ private function convertCustomOptions(string $value) { - if (substr($value, 0, 1) === "[" || + if (substr($value, 0, 1) === "[" && substr($value, strlen($value) - 1, 1) === "]") { return explode(',', substr($value, 1, -1)); } From 733ddf969f840a0a787a459c96c97869c7f58ad1 Mon Sep 17 00:00:00 2001 From: Ievgenii Gryshkun <i.gryshkun@gmail.com> Date: Sat, 27 Apr 2019 12:26:29 +0300 Subject: [PATCH 090/224] Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 1 - .../Magento/GraphQl/CatalogInventory/AddProductToCartTest.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index e2d29e93db574..0b6b392c2ed9b 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -325,7 +325,6 @@ type SelectedCustomizableOptionValue { label: String! value: String! price: CartItemSelectedOptionValuePrice! - sort_order: Int! } type CartItemSelectedOptionValuePrice { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index c2fbfc1418dbf..708e034a4626b 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -52,7 +52,7 @@ public function testAddProductIfQuantityIsNotAvailable() * @expectedException \Exception * @expectedExceptionMessage The product's required option(s) weren't entered. Make sure the options are entered and try again. */ - public function testAddProductWithoutRequiredCustomOPtions() + public function testAddProductWithoutRequiredCustomOptions() { $sku = 'simple_with_custom_options'; $qty = 1; @@ -66,7 +66,7 @@ public function testAddProductWithoutRequiredCustomOPtions() * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testAddProductWithRequiredCustomOPtions() + public function testAddProductWithRequiredCustomOptions() { $sku = 'simple_with_custom_options'; $qty = 1; From 1315577e2099637207f02deec48607d81f7cde46 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 11:33:53 -0500 Subject: [PATCH 091/224] GraphQL-474: Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../Model/Cart/AddSimpleProductToCart.php | 52 ++++++------- .../Magento/QuoteGraphQl/etc/schema.graphqls | 7 +- ...mpleProductWithCustomOptionsToCartTest.php | 75 +++++++------------ ...tualProductWithCustomOptionsToCartTest.php | 75 +++++++------------ 4 files changed, 84 insertions(+), 125 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index bd81a15307e31..251f17619c2a8 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -13,21 +13,13 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; -use Magento\Framework\Stdlib\ArrayManager; use Magento\Quote\Model\Quote; /** * Add simple product to cart - * - * TODO: should be replaced for different types resolver */ class AddSimpleProductToCart { - /** - * @var ArrayManager - */ - private $arrayManager; - /** * @var DataObjectFactory */ @@ -39,16 +31,13 @@ class AddSimpleProductToCart private $productRepository; /** - * @param ArrayManager $arrayManager * @param DataObjectFactory $dataObjectFactory * @param ProductRepositoryInterface $productRepository */ public function __construct( - ArrayManager $arrayManager, DataObjectFactory $dataObjectFactory, ProductRepositoryInterface $productRepository ) { - $this->arrayManager = $arrayManager; $this->dataObjectFactory = $dataObjectFactory; $this->productRepository = $productRepository; } @@ -67,11 +56,6 @@ public function execute(Quote $cart, array $cartItemData): void { $sku = $this->extractSku($cartItemData); $quantity = $this->extractQuantity($cartItemData); - if ($quantity <= 0) { - throw new GraphQlInputException( - __('Please enter a number greater than 0 in this field.') - ); - } $customizableOptions = $this->extractCustomizableOptions($cartItemData); try { @@ -105,11 +89,10 @@ public function execute(Quote $cart, array $cartItemData): void */ private function extractSku(array $cartItemData): string { - $sku = $this->arrayManager->get('data/sku', $cartItemData); - if (!isset($sku)) { - throw new GraphQlInputException(__('Missing key "sku" in cart item data')); + if (!isset($cartItemData['data']['sku']) || empty($cartItemData['data']['sku'])) { + throw new GraphQlInputException(__('Missed "sku" in cart item data')); } - return (string)$sku; + return (string)$cartItemData['data']['sku']; } /** @@ -121,11 +104,17 @@ private function extractSku(array $cartItemData): string */ private function extractQuantity(array $cartItemData): float { - $quantity = $this->arrayManager->get('data/quantity', $cartItemData); - if (!isset($quantity)) { - throw new GraphQlInputException(__('Missing key "quantity" in cart item data')); + if (!isset($cartItemData['data']['quantity'])) { + throw new GraphQlInputException(__('Missed "qty" in cart item data')); } - return (float)$quantity; + $quantity = (float)$cartItemData['data']['quantity']; + + if ($quantity <= 0) { + throw new GraphQlInputException( + __('Please enter a number greater than 0 in this field.') + ); + } + return $quantity; } /** @@ -136,13 +125,17 @@ private function extractQuantity(array $cartItemData): float */ private function extractCustomizableOptions(array $cartItemData): array { - $customizableOptions = $this->arrayManager->get('customizable_options', $cartItemData, []); + if (!isset($cartItemData['customizable_options']) || empty($cartItemData['customizable_options'])) { + return []; + } $customizableOptionsData = []; - foreach ($customizableOptions as $customizableOption) { - $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptions( - $customizableOption['value'] - ); + foreach ($cartItemData['customizable_options'] as $customizableOption) { + if (isset($customizableOption['value_string'])) { + $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptions( + $customizableOption['value_string'] + ); + } } return $customizableOptionsData; } @@ -170,6 +163,7 @@ private function createBuyRequest(float $quantity, array $customOptions): DataOb */ private function convertCustomOptions(string $value) { + $value = trim($value); if (substr($value, 0, 1) === "[" && substr($value, strlen($value) - 1, 1) === "]") { return explode(',', substr($value, 1, -1)); diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 0b6b392c2ed9b..c2b92034c3294 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -52,7 +52,7 @@ input CartItemInput { input CustomizableOptionInput { id: Int! - value: String! + value_string: String! } input ApplyCouponToCartInput { @@ -314,8 +314,7 @@ interface CartItemInterface @typeResolver(class: "Magento\\QuoteGraphQl\\Model\\ type SelectedCustomizableOption { id: Int! label: String! - type: String! - is_required: Int! + is_required: Boolean! values: [SelectedCustomizableOptionValue!]! sort_order: Int! } @@ -323,7 +322,7 @@ type SelectedCustomizableOption { type SelectedCustomizableOptionValue { id: Int! label: String! - value: String! + value: String price: CartItemSelectedOptionValuePrice! } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php index 63546298304b0..d64c51354129d 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php @@ -50,41 +50,11 @@ public function testAddSimpleProductWithOptions() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $customOptionsValues = $this->getCustomOptionsValuesForQuery($sku); - /* Generate customizable options fragment for GraphQl request */ - $queryCustomizableOptions = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); + $queryCustomizableOptionValues = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); - $query = <<<QUERY -mutation { - addSimpleProductsToCart( - input: { - cart_id: "{$maskedQuoteId}", - cartItems: [ - { - data: { - quantity: $quantity - sku: "$sku" - }, - customizable_options: $queryCustomizableOptions - } - ] - } - ) { - cart { - items { - ... on SimpleCartItem { - customizable_options { - label - values { - value - } - } - } - } - } - } -} -QUERY; + $customizableOptions = "customizable_options: {$queryCustomizableOptionValues}"; + $query = $this->getQuery($maskedQuoteId, $sku, $quantity, $customizableOptions); $response = $this->graphQlMutation($query); @@ -95,7 +65,7 @@ public function testAddSimpleProductWithOptions() $assignedOptionsCount = count($customOptionsValues); for ($counter = 0; $counter < $assignedOptionsCount; $counter++) { self::assertEquals( - $customOptionsValues[$counter]['value'], + $customOptionsValues[$counter]['value_string'], $customizableOptionsOutput[$counter]['values'][0]['value'] ); } @@ -107,13 +77,31 @@ public function testAddSimpleProductWithOptions() * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_options.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testAddSimpleProductWithNoRequiredOptionsSet() + public function testAddSimpleProductWithMissedRequiredOptionsSet() { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $sku = 'simple'; $quantity = 1; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); + $customizableOptions = ''; - $query = <<<QUERY + $query = $this->getQuery($maskedQuoteId, $sku, $quantity, $customizableOptions); + + self::expectExceptionMessage( + 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' + ); + $this->graphQlMutation($query); + } + + /** + * @param string $maskedQuoteId + * @param string $sku + * @param float $quantity + * @param string $customizableOptions + * @return string + */ + private function getQuery(string $maskedQuoteId, string $sku, float $quantity, string $customizableOptions): string + { + return <<<QUERY mutation { addSimpleProductsToCart( input: { @@ -124,6 +112,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() quantity: $quantity sku: "$sku" } + {$customizableOptions} } ] } @@ -134,7 +123,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() customizable_options { label values { - value + value } } } @@ -143,12 +132,6 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() } } QUERY; - - self::expectExceptionMessage( - 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' - ); - - $this->graphQlMutation($query); } /** @@ -168,13 +151,13 @@ private function getCustomOptionsValuesForQuery(string $sku): array if ($optionType == 'field' || $optionType == 'area') { $customOptionsValues[] = [ 'id' => (int) $customOption->getOptionId(), - 'value' => 'test' + 'value_string' => 'test' ]; } elseif ($optionType == 'drop_down') { $optionSelectValues = $customOption->getValues(); $customOptionsValues[] = [ 'id' => (int) $customOption->getOptionId(), - 'value' => reset($optionSelectValues)->getOptionTypeId() + 'value_string' => reset($optionSelectValues)->getOptionTypeId() ]; } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php index 94ac11ad8e0b1..55542919cc098 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php @@ -50,41 +50,11 @@ public function testAddVirtualProductWithOptions() $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $customOptionsValues = $this->getCustomOptionsValuesForQuery($sku); - /* Generate customizable options fragment for GraphQl request */ - $queryCustomizableOptions = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); + $queryCustomizableOptionValues = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues)); - $query = <<<QUERY -mutation { - addVirtualProductsToCart( - input: { - cart_id: "{$maskedQuoteId}", - cartItems: [ - { - data: { - quantity: $quantity - sku: "$sku" - }, - customizable_options: $queryCustomizableOptions - } - ] - } - ) { - cart { - items { - ... on VirtualCartItem { - customizable_options { - label - values { - value - } - } - } - } - } - } -} -QUERY; + $customizableOptions = "customizable_options: {$queryCustomizableOptionValues}"; + $query = $this->getQuery($maskedQuoteId, $sku, $quantity, $customizableOptions); $response = $this->graphQlMutation($query); @@ -95,7 +65,7 @@ public function testAddVirtualProductWithOptions() $assignedOptionsCount = count($customOptionsValues); for ($counter = 0; $counter < $assignedOptionsCount; $counter++) { self::assertEquals( - $customOptionsValues[$counter]['value'], + $customOptionsValues[$counter]['value_string'], $customizableOptionsOutput[$counter]['values'][0]['value'] ); } @@ -107,13 +77,31 @@ public function testAddVirtualProductWithOptions() * @magentoApiDataFixture Magento/Catalog/_files/product_virtual_with_options.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php */ - public function testAddVirtualProductWithNoRequiredOptionsSet() + public function testAddSimpleProductWithMissedRequiredOptionsSet() { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); $sku = 'virtual'; $quantity = 1; - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); + $customizableOptions = ''; - $query = <<<QUERY + $query = $this->getQuery($maskedQuoteId, $sku, $quantity, $customizableOptions); + + self::expectExceptionMessage( + 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' + ); + $this->graphQlMutation($query); + } + + /** + * @param string $maskedQuoteId + * @param string $sku + * @param float $quantity + * @param string $customizableOptions + * @return string + */ + private function getQuery(string $maskedQuoteId, string $sku, float $quantity, string $customizableOptions): string + { + return <<<QUERY mutation { addVirtualProductsToCart( input: { @@ -124,6 +112,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() quantity: $quantity sku: "$sku" } + {$customizableOptions} } ] } @@ -134,7 +123,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() customizable_options { label values { - value + value } } } @@ -143,12 +132,6 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() } } QUERY; - - self::expectExceptionMessage( - 'The product\'s required option(s) weren\'t entered. Make sure the options are entered and try again.' - ); - - $this->graphQlMutation($query); } /** @@ -168,13 +151,13 @@ private function getCustomOptionsValuesForQuery(string $sku): array if ($optionType == 'field' || $optionType == 'area') { $customOptionsValues[] = [ 'id' => (int) $customOption->getOptionId(), - 'value' => 'test' + 'value_string' => 'test' ]; } elseif ($optionType == 'drop_down') { $optionSelectValues = $customOption->getValues(); $customOptionsValues[] = [ 'id' => (int) $customOption->getOptionId(), - 'value' => reset($optionSelectValues)->getOptionTypeId() + 'value_string' => reset($optionSelectValues)->getOptionTypeId() ]; } } From b115f1c546d5f09e67c7f369ec8b239c1b0a2984 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 11:53:24 -0500 Subject: [PATCH 092/224] GraphQL-474: Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../CatalogInventory/AddProductToCartTest.php | 83 ------------------- 1 file changed, 83 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 708e034a4626b..6f27693eeb4a7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -46,89 +46,6 @@ public function testAddProductIfQuantityIsNotAvailable() $this->graphQlMutation($query); } - /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php - * @expectedException \Exception - * @expectedExceptionMessage The product's required option(s) weren't entered. Make sure the options are entered and try again. - */ - public function testAddProductWithoutRequiredCustomOptions() - { - $sku = 'simple_with_custom_options'; - $qty = 1; - - $maskedQuoteId = $this->getMaskedQuoteId(); - $query = $this->getAddSimpleProductQuery($maskedQuoteId, $sku, $qty); - $this->graphQlQuery($query); - } - - /** - * @magentoApiDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php - */ - public function testAddProductWithRequiredCustomOptions() - { - $sku = 'simple_with_custom_options'; - $qty = 1; - $productCustomOptions = Bootstrap::getObjectManager() - ->get(\Magento\Catalog\Api\ProductCustomOptionRepositoryInterface::class) - ->getList($sku); - $customizableOptions = ''; - foreach ($productCustomOptions as $option) { - $value = $option->getValues() ? - '[' . key($option->getValues()) . ']' : - 'Test'; - $customizableOptions .= ' { - id: ' . $option->getId() . ' - value: "' . $value . '" - }'; - } - - $maskedQuoteId = $this->getMaskedQuoteId(); - $query = <<<QUERY -mutation { - addSimpleProductsToCart( - input: { - cart_id: "{$maskedQuoteId}" - cartItems: { - data: { - qty: {$qty} - sku: "{$sku}" - } - customizable_options: [ - {$customizableOptions} - ] - } - } - ) -{ - cart { - items { - product { - sku - } - ... on SimpleCartItem { - customizable_options { - id - is_required - sort_order - } - } - } - } - } -} -QUERY; - $response = $this->graphQlQuery($query); - self::assertArrayHasKey('cart', $response['addSimpleProductsToCart']); - - self::assertEquals($sku, $response['addSimpleProductsToCart']['cart']['items'][0]['product']['sku']); - self::assertEquals( - 1, - $response['addSimpleProductsToCart']['cart']['items'][0]['customizable_options'][0]['is_required'] - ); - } - /** * @magentoApiDataFixture Magento/Catalog/_files/products.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php From c4bbfb489f6e1cb5767ba1da466f4cb8adb8cf59 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Tue, 30 Apr 2019 12:29:34 -0500 Subject: [PATCH 093/224] MC-4776: Convert AssignCustomOrderStatusTest to MFTF --- .../StorefrontCustomerOrderSection.xml | 1 + ...erOrderStatusByLabelAndCodeActionGroup.xml | 22 +++ .../SelectActionForOrdersActionGroup.xml | 19 +++ .../Sales/Test/Mftf/Data/OrderActionsData.xml | 21 +++ .../Sales/Test/Mftf/Data/OrderStateData.xml | 21 +++ .../Test/Mftf/Data/OrderStatusConfigData.xml | 18 +++ .../AdminAssignOrderStatusToStateSection.xml | 18 +++ .../Section/AdminOrderStatusGridSection.xml | 7 + .../Mftf/Section/AdminOrdersGridSection.xml | 3 + .../StorefrontOrderInformationMainSection.xml | 1 + ...mOrderStatusNotVisibleOnStorefrontTest.xml | 134 ++++++++++++++++++ ...stomOrderStatusVisibleOnStorefrontTest.xml | 30 ++++ .../TestCase/AssignCustomOrderStatusTest.xml | 2 + 13 files changed, 297 insertions(+) create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/FilterOrderStatusByLabelAndCodeActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/SelectActionForOrdersActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Data/OrderActionsData.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Data/OrderStateData.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Data/OrderStatusConfigData.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Section/AdminAssignOrderStatusToStateSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusVisibleOnStorefrontTest.xml diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml index e8b11b27ddc70..678ffc5368de6 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml @@ -13,5 +13,6 @@ <element name="productCustomOptions" type="text" selector="//strong[contains(@class, 'product-item-name') and normalize-space(.)='{{var1}}']/following-sibling::*[contains(@class, 'item-options')]/dt[normalize-space(.)='{{var2}}']/following-sibling::dd[normalize-space(.)='{{var3}}']" parameterized="true"/> <element name="productCustomOptionsFile" type="text" selector="//strong[contains(@class, 'product-item-name') and normalize-space(.)='{{var1}}']/following-sibling::*[contains(@class, 'item-options')]/dt[normalize-space(.)='{{var2}}']/following-sibling::dd[contains(.,'{{var3}}')]" parameterized="true"/> <element name="productCustomOptionsLink" type="text" selector="//strong[contains(@class, 'product-item-name') and normalize-space(.)='{{var1}}']/following-sibling::*[contains(@class, 'item-options')]/dt[normalize-space(.)='{{var2}}']/following-sibling::dd//a[text() = '{{var3}}']" parameterized="true"/> + <element name="status" type="text" selector="//td[contains(concat(' ',normalize-space(@class),' '),' col status ')]"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/FilterOrderStatusByLabelAndCodeActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/FilterOrderStatusByLabelAndCodeActionGroup.xml new file mode 100644 index 0000000000000..96e562cb95c6f --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/FilterOrderStatusByLabelAndCodeActionGroup.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> + <actionGroup name="FilterOrderStatusByLabelAndCodeActionGroup"> + <arguments> + <argument name="statusLabel" type="string"/> + <argument name="statusCode" type="string"/> + </arguments> + <conditionalClick selector="{{AdminOrderStatusGridSection.resetFilter}}" dependentSelector="{{AdminOrderStatusGridSection.resetFilter}}" visible="true" stepKey="clearOrderStatusFilters" /> + <fillField selector="{{AdminOrderStatusGridSection.statusLabel}}" userInput="{{statusLabel}}" stepKey="fillStatusLabel"/> + <fillField selector="{{AdminOrderStatusGridSection.statusCode}}" userInput="{{statusCode}}" stepKey="fillStatusCode"/> + <click selector="{{AdminOrderStatusGridSection.search}}" stepKey="clickSearch"/> + <waitForPageLoad stepKey="waitForSearch"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/SelectActionForOrdersActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/SelectActionForOrdersActionGroup.xml new file mode 100644 index 0000000000000..073eb03b11bfa --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/SelectActionForOrdersActionGroup.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> + <actionGroup name="SelectActionForOrdersActionGroup"> + <arguments> + <argument name="action" type="string"/> + </arguments> + <checkOption selector="{{AdminOrdersGridSection.checkOrder}}" stepKey="checkOrder"/> + <click selector="{{AdminOrdersGridSection.orderActions}}" stepKey="clickOrderActions"/> + <click selector="{{AdminOrdersGridSection.changeOrderStatus(action)}}" stepKey="changeOrdersAction"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Data/OrderActionsData.xml b/app/code/Magento/Sales/Test/Mftf/Data/OrderActionsData.xml new file mode 100644 index 0000000000000..64502f5632fc2 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Data/OrderActionsData.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="OrderActions" type="orderActions"> + <data key="cancel">Cancel</data> + <data key="hold">Hold</data> + <data key="unhold">Unhold</data> + <data key="printInvoices">Print Invoices</data> + <data key="printPackingSlips">Print Packing Slips</data> + <data key="printCreditMemos">Print Credit Memos</data> + <data key="printAll">Print All</data> + <data key="printShippingLabels">Print Shipping Labels</data> + </entity> +</entities> diff --git a/app/code/Magento/Sales/Test/Mftf/Data/OrderStateData.xml b/app/code/Magento/Sales/Test/Mftf/Data/OrderStateData.xml new file mode 100644 index 0000000000000..9493124fd6e40 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Data/OrderStateData.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="OrderState" type="state"> + <data key="canceled">Canceled</data> + <data key="closed">Closed</data> + <data key="complete">Complete</data> + <data key="payment_review">Payment Review</data> + <data key="processing">Processing</data> + <data key="holded">On Hold</data> + <data key="new">Pending</data> + <data key="pending_payment">Pending Payment</data> + </entity> +</entities> diff --git a/app/code/Magento/Sales/Test/Mftf/Data/OrderStatusConfigData.xml b/app/code/Magento/Sales/Test/Mftf/Data/OrderStatusConfigData.xml new file mode 100644 index 0000000000000..4bb8256b68be1 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Data/OrderStatusConfigData.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="EnableCheckmoOrderStatusPending"> + <data key="path">payment/checkmo/order_status</data> + <data key="scope">payment</data> + <data key="scope_id">1</data> + <data key="label">Pending</data> + <data key="value">pending</data> + </entity> +</entities> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminAssignOrderStatusToStateSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminAssignOrderStatusToStateSection.xml new file mode 100644 index 0000000000000..6412c5063cb04 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminAssignOrderStatusToStateSection.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminAssignOrderStatusToStateSection"> + <element name="orderStatus" type="select" selector="#status"/> + <element name="orderState" type="select" selector="#state"/> + <element name="orderStatusAsDefault" type="checkbox" selector="#is_default"/> + <element name="visibleOnStorefront" type="checkbox" selector="#visible_on_front"/> + <element name="saveStatusAssignment" type="button" selector="#save"/> + </section> +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderStatusGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderStatusGridSection.xml index b624639281187..06b55cee11f5a 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderStatusGridSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderStatusGridSection.xml @@ -12,5 +12,12 @@ <element name="statusCodeFilterField" type="input" selector="[data-role=filter-form] [name=status]"/> <element name="statusCodeDataColumn" type="input" selector="[data-role=row] [data-column=status]"/> <element name="statusLabelDataColumn" type="input" selector="[data-role=row] [data-column=label]"/> + <element name="assignStatusToStateBtn" type="button" selector="#assign"/> + <element name="statusLabel" type="input" selector="#sales_order_status_grid_filter_label"/> + <element name="statusCode" type="input" selector="#sales_order_status_grid_filter_status"/> + <element name="resetFilter" type="button" selector="//div[contains(concat(' ',normalize-space(@class),' '),' action-reset ')]" timeout="30"/> + <element name="search" type="button" selector="[data-action='grid-filter-apply']" timeout="30"/> + <element name="gridCell" type="text" selector="//tr['{{row}}']//td[count(//div[contains(concat(' ',normalize-space(@class),' '),' admin__data-grid-wrap ')]//tr//th[contains(., '{{cellName}}')]/preceding-sibling::th) +1 ]" parameterized="true" timeout="30"/> + <element name="unassign" type="button" selector="//td[contains(concat(' ',normalize-space(@class),' '),' col-actions col-unassign ')]"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml index 53a6cbffcdac6..6e6110bc6cc96 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrdersGridSection.xml @@ -31,5 +31,8 @@ <element name="viewColumnCheckbox" type="checkbox" selector="//div[contains(@class,'admin__data-grid-action-columns')]//div[contains(@class, 'admin__field-option')]//label[text() = '{{column}}']/preceding-sibling::input" parameterized="true"/> <element name="customerInOrdersSection" type="button" selector="(//td[contains(text(),'{{customer}}')])[1]" parameterized="true"/> <element name="productForOrder" type="button" selector="//td[contains(text(),'{{var}}')]" parameterized="true"/> + <element name="checkOrder" type="input" selector="//td[count(//div[@data-role='grid-wrapper'])]//input"/> + <element name="orderActions" type="button" selector="//div[contains(concat(' ',normalize-space(@class),' '),' row-gutter ')]//button[@title='Select Items']"/> + <element name="changeOrderStatus" type="button" selector="//div[contains(concat(' ',normalize-space(@class),' '),' row-gutter ')]//span[text()='{{status}}']" parameterized="true" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderInformationMainSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderInformationMainSection.xml index e42c301206152..eddcfd4bdd235 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderInformationMainSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontOrderInformationMainSection.xml @@ -11,5 +11,6 @@ <section name="StorefrontOrderInformationMainSection"> <element name="orderTitle" type="span" selector="#page-title-wrapper"/> <element name="return" type="span" selector="//span[contains(text(), 'Return')]"/> + <element name="emptyMessage" type="text" selector="//div[contains(concat(' ',normalize-space(@class),' '),' message info empty ')]/span"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml new file mode 100644 index 0000000000000..c292afe65cdf3 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusNotVisibleOnStorefrontTest.xml @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AssignCustomOrderStatusNotVisibleOnStorefrontTest"> + <annotations> + <features value="Sales"/> + <stories value="Assign Custom Order Status"/> + <title value="Assign custom order status not visible on storefront test"/> + <description value="Assign custom order status not visible on storefront"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-16053"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create customer --> + <createData entity="Simple_US_Customer" stepKey="createCustomer"/> + + <!-- Create product --> + <createData entity="SimpleProduct2" stepKey="createSimpleProduct"/> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + </before> + <after> + <!-- Disable created order status --> + <magentoCLI command="config:set {{EnableCheckmoOrderStatusPending.path}} {{EnableCheckmoOrderStatusPending.value}}" stepKey="rollbackNewOrderStatus"/> + + <!-- Logout customer --> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/> + + <!-- Delete product --> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> + + <!-- Delete customer --> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + + <!-- Log out --> + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <!-- Create order status --> + <amOnPage url="{{AdminOrderStatusPage.url}}" stepKey="goToOrderStatusPage"/> + <waitForPageLoad stepKey="waitForOrderStatusPageLoad"/> + <click selector="{{AdminMainActionsSection.add}}" stepKey="clickCreateNewStatus"/> + + <!-- Fill form and validate message --> + <actionGroup ref="AdminOrderStatusFormFillAndSave" stepKey="fillFormAndClickSave"> + <argument name="status" value="{{defaultOrderStatus.status}}"/> + <argument name="label" value="{{defaultOrderStatus.label}}"/> + </actionGroup> + <actionGroup ref="AssertOrderStatusFormSaveSuccess" stepKey="seeFormSaveSuccess"/> + + <!-- Assign status to state --> + <click selector="{{AdminOrderStatusGridSection.assignStatusToStateBtn}}" stepKey="clickAssignStatusBtn"/> + <selectOption selector="{{AdminAssignOrderStatusToStateSection.orderStatus}}" userInput="{{defaultOrderStatus.status}}" stepKey="selectOrderStatus"/> + <selectOption selector="{{AdminAssignOrderStatusToStateSection.orderState}}" userInput="{{OrderState.new}}" stepKey="selectOrderState"/> + <checkOption selector="{{AdminAssignOrderStatusToStateSection.orderStatusAsDefault}}" stepKey="orderStatusAsDefault"/> + <uncheckOption selector="{{AdminAssignOrderStatusToStateSection.visibleOnStorefront}}" stepKey="visibleOnStorefront"/> + <click selector="{{AdminAssignOrderStatusToStateSection.saveStatusAssignment}}" stepKey="clickSaveStatus"/> + <see selector="{{AdminMessagesSection.success}}" userInput="You assigned the order status." stepKey="seeSuccess"/> + + <!-- Prepare data for constraints --> + <magentoCLI command="config:set {{EnableCheckmoOrderStatusPending.path}} {{defaultOrderStatus.label}}" stepKey="enableNewOrderStatus"/> + + <!-- Assert order status in grid --> + <actionGroup ref="FilterOrderStatusByLabelAndCodeActionGroup" stepKey="filterOrderStatusGrid"> + <argument name="statusLabel" value="{{defaultOrderStatus.label}}"/> + <argument name="statusCode" value="{{defaultOrderStatus.status}}"/> + </actionGroup> + <see selector="{{AdminOrderStatusGridSection.gridCell('1', 'State Code and Title')}}" userInput="new[{{defaultOrderStatus.label}}]" stepKey="seeOrderStatusInOrderGrid"/> + + <!-- Create order and grab order id --> + <actionGroup ref="CreateOrderActionGroup" stepKey="createNewOrder"> + <argument name="product" value="$$createSimpleProduct$$"/> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + <grabTextFrom selector="|Order # (\d+)|" stepKey="getOrderId"/> + + <!-- Assert order status is correct --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrdersPage"/> + <waitForPageLoad stepKey="waitForOrdersPageLoad"/> + <actionGroup ref="filterOrderGridById" stepKey="filterOrdersGridById"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <click selector="{{AdminDataGridTableSection.firstRow}}" stepKey="clickCreatedOrderInGrid"/> + <see selector="{{AdminOrderDetailsInformationSection.orderStatus}}" userInput="{{defaultOrderStatus.label}}" stepKey="seeOrderStatus"/> + + <!-- Login as customer --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginToStorefrontAccount"> + <argument name="Customer" value="$$createCustomer$$"/> + </actionGroup> + <waitForPageLoad stepKey="waitForCustomerLogin"/> + + <!-- Open My Orders --> + <amOnPage url="{{StorefrontCustomerDashboardPage.url}}" stepKey="goToCustomerDashboardPage"/> + <waitForPageLoad stepKey="waitForCustomerDashboardPageLoad"/> + <actionGroup ref="StorefrontCustomerGoToSidebarMenu" stepKey="goToMyOrdersPage"> + <argument name="menu" value="My Orders"/> + </actionGroup> + + <!-- Assert order not visible on My Orders --> + <see selector="{{StorefrontOrderInformationMainSection.emptyMessage}}" userInput="You have placed no orders." stepKey="seeEmptyMessage"/> + + <!-- Cancel order --> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToAdminOrdersPage"/> + <waitForPageLoad stepKey="waitForAdminOrdersPageLoad"/> + <actionGroup ref="filterOrderGridById" stepKey="filterOrdersGridByOrderId"> + <argument name="orderId" value="$getOrderId"/> + </actionGroup> + <checkOption selector="{{AdminOrdersGridSection.checkOrder}}" stepKey="selectOrder"/> + <actionGroup ref="SelectActionForOrdersActionGroup" stepKey="selectCancelOrderAction"> + <argument name="action" value="{{OrderActions.cancel}}"/> + </actionGroup> + <see selector="{{AdminMessagesSection.success}}" userInput="We canceled 1 order(s)." stepKey="seeSuccessMessage"/> + + <!-- Unassign order status --> + <amOnPage url="{{AdminOrderStatusPage.url}}" stepKey="goToOrderStatus"/> + <waitForPageLoad stepKey="waitForStatusPageLoad"/> + <actionGroup ref="FilterOrderStatusByLabelAndCodeActionGroup" stepKey="filterStatusGrid"> + <argument name="statusLabel" value="{{defaultOrderStatus.label}}"/> + <argument name="statusCode" value="{{defaultOrderStatus.status}}"/> + </actionGroup> + <click selector="{{AdminOrderStatusGridSection.unassign}}" stepKey="unassignOrderStatus"/> + <see selector="{{AdminMessagesSection.success}}" userInput="You have unassigned the order status." stepKey="seeMessage"/> + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusVisibleOnStorefrontTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusVisibleOnStorefrontTest.xml new file mode 100644 index 0000000000000..d81baf7755eab --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/AssignCustomOrderStatusVisibleOnStorefrontTest.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AssignCustomOrderStatusVisibleOnStorefrontTest" extends="AssignCustomOrderStatusNotVisibleOnStorefrontTest"> + <annotations> + <features value="Sales"/> + <stories value="Assign Custom Order Status"/> + <title value="Assign custom order status visible on storefront test"/> + <description value="Assign custom order status visible on storefront"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-16054"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <remove keyForRemoval="seeEmptyMessage"/> + + <!-- Assign status to state part --> + <checkOption selector="{{AdminAssignOrderStatusToStateSection.visibleOnStorefront}}" stepKey="visibleOnStorefront"/> + + <!-- Assert order in orders grid on frontend --> + <see selector="{{StorefrontCustomerOrderSection.status}}" userInput="{{defaultOrderStatus.label}}" stepKey="seeOrderStatusOnStorefront" after="goToMyOrdersPage"/> + </test> +</tests> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/AssignCustomOrderStatusTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/AssignCustomOrderStatusTest.xml index 6ac008dc4e98a..808201b8e6acc 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/AssignCustomOrderStatusTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/AssignCustomOrderStatusTest.xml @@ -8,6 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Sales\Test\TestCase\AssignCustomOrderStatusTest" summary="Assign Custom Order Status" ticketId="MAGETWO-29382"> <variation name="AssignCustomOrderStatusTestVariation1"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="orderStatusState/state" xsi:type="string">Pending</data> <data name="orderStatusState/is_default" xsi:type="string">Yes</data> <data name="orderStatusState/visible_on_front" xsi:type="string">No</data> @@ -16,6 +17,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrderNotVisibleOnMyAccount" /> </variation> <variation name="AssignCustomOrderStatusTestVariation2"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="orderStatusState/state" xsi:type="string">Pending</data> <data name="orderStatusState/is_default" xsi:type="string">Yes</data> <data name="orderStatusState/visible_on_front" xsi:type="string">Yes</data> From f393ffdc0f207a92f2df4274137b84ab50799362 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 12:34:21 -0500 Subject: [PATCH 094/224] GraphQL-641: Schema Inconsistency of "cartItems" declaration --- .../Magento/ConfigurableProductGraphQl/etc/schema.graphqls | 2 +- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 4 ++-- .../Magento/GraphQl/CatalogInventory/AddProductToCartTest.php | 2 +- .../ConfigurableProduct/AddConfigurableProductToCartTest.php | 2 +- .../Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php | 2 +- .../Quote/AddSimpleProductWithCustomOptionsToCartTest.php | 4 ++-- .../Quote/AddVirtualProductWithCustomOptionsToCartTest.php | 4 ++-- .../GraphQl/Quote/Customer/AddSimpleProductToCartTest.php | 2 +- .../GraphQl/Quote/Customer/AddVirtualProductToCartTest.php | 2 +- .../Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php | 2 +- .../GraphQl/Quote/Guest/AddSimpleProductToCartTest.php | 2 +- .../GraphQl/Quote/Guest/AddVirtualProductToCartTest.php | 2 +- .../Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php | 2 +- 13 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls index d4780c5c0867a..45a4323e7f4bc 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls @@ -41,7 +41,7 @@ type ConfigurableProductOptionsValues @doc(description: "ConfigurableProductOpti input AddConfigurableProductsToCartInput { cart_id: String! - cartItems: [ConfigurableProductCartItemInput!]! + cart_items: [ConfigurableProductCartItemInput!]! } type AddConfigurableProductsToCartOutput { diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index e2d29e93db574..5828fd4975d78 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -27,7 +27,7 @@ input createEmptyCartInput { input AddSimpleProductsToCartInput { cart_id: String! - cartItems: [SimpleProductCartItemInput!]! + cart_items: [SimpleProductCartItemInput!]! } input SimpleProductCartItemInput { @@ -37,7 +37,7 @@ input SimpleProductCartItemInput { input AddVirtualProductsToCartInput { cart_id: String! - cartItems: [VirtualProductCartItemInput!]! + cart_items: [VirtualProductCartItemInput!]! } input VirtualProductCartItemInput { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php index 6f27693eeb4a7..6ed0f6ef7a132 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogInventory/AddProductToCartTest.php @@ -112,7 +112,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity) : addSimpleProductsToCart( input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: $quantity diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php index 6810f9d44ce91..a6f02e4239f25 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php @@ -93,7 +93,7 @@ private function getQuery(string $maskedQuoteId, string $variantSku, int $quanti addConfigurableProductsToCart( input: { cart_id: "{$maskedQuoteId}" - cartItems: [ + cart_items: [ { variant_sku: "{$variantSku}" data: { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php index e09ee8bc969af..808fd95d331e1 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/PageCache/Quote/Guest/CartCacheTest.php @@ -79,7 +79,7 @@ private function addSimpleProductToCart(string $maskedCartId, int $qty, string $ addSimpleProductsToCart( input: { cart_id: "{$maskedCartId}" - cartItems: [ + cart_items: [ { data: { qty: $qty diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php index 63546298304b0..d254e146f5b12 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductWithCustomOptionsToCartTest.php @@ -59,7 +59,7 @@ public function testAddSimpleProductWithOptions() addSimpleProductsToCart( input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: $quantity @@ -118,7 +118,7 @@ public function testAddSimpleProductWithNoRequiredOptionsSet() addSimpleProductsToCart( input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: $quantity diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php index 94ac11ad8e0b1..19bf591e81084 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddVirtualProductWithCustomOptionsToCartTest.php @@ -59,7 +59,7 @@ public function testAddVirtualProductWithOptions() addVirtualProductsToCart( input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: $quantity @@ -118,7 +118,7 @@ public function testAddVirtualProductWithNoRequiredOptionsSet() addVirtualProductsToCart( input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: $quantity diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php index be22d860df122..aca13e53875dd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddSimpleProductToCartTest.php @@ -139,7 +139,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity): mutation { addSimpleProductsToCart(input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: {$quantity} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php index 1269b9d8e7b3d..86573dcde2e35 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/AddVirtualProductToCartTest.php @@ -139,7 +139,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity): mutation { addVirtualProductsToCart(input: { cart_id: "{$maskedQuoteId}", - cartItems: [ + cart_items: [ { data: { quantity: {$quantity} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index 92974f2491f75..8ea8fce3a4327 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -212,7 +212,7 @@ private function addProductToCart(string $cartId, float $qty, string $sku): void addSimpleProductsToCart( input: { cart_id: "{$cartId}" - cartItems: [ + cart_items: [ { data: { quantity: {$qty} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php index 8b20320fc2f02..9a943cf4b204e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddSimpleProductToCartTest.php @@ -112,7 +112,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity): addSimpleProductsToCart( input: { cart_id: "{$maskedQuoteId}" - cartItems: [ + cart_items: [ { data: { quantity: $quantity diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php index cb429e7b9cb9e..cadbec857c2d6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/AddVirtualProductToCartTest.php @@ -113,7 +113,7 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity): addVirtualProductsToCart( input: { cart_id: "{$maskedQuoteId}" - cartItems: [ + cart_items: [ { data: { quantity: {$quantity} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index bddee2151f5cd..da6ac5f31448a 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -172,7 +172,7 @@ private function addProductToCart(string $cartId, float $quantity, string $sku): addSimpleProductsToCart( input: { cart_id: "{$cartId}" - cartItems: [ + cart_items: [ { data: { quantity: {$quantity} From 83ed2ed7195ca025a8da21141647209ff2ac3d52 Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy <dpoperechnyy@magento.com> Date: Tue, 30 Apr 2019 13:37:19 -0500 Subject: [PATCH 095/224] MC-16046: Leverage the font-display CSS feature to ensure text is user-visible while webfonts are loading - Make font-display auto by default; --- lib/web/css/source/lib/_typography.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/css/source/lib/_typography.less b/lib/web/css/source/lib/_typography.less index 2b8065b634d41..3ca09d3782619 100644 --- a/lib/web/css/source/lib/_typography.less +++ b/lib/web/css/source/lib/_typography.less @@ -12,7 +12,7 @@ @font-path, @font-weight: normal, @font-style: normal, - @font-display: swap + @font-display: auto ) { @font-face { font-family: @family-name; From c28268ebb89fdfbdd7d7b5ede2698d809e123cc7 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 13:41:52 -0500 Subject: [PATCH 096/224] GraphQL-630: Schema inconsistency of "AvailableShippingMethod" declaration --- .../AvailableShippingMethods.php | 46 ++++++++++++++++++- .../SelectedShippingMethod.php | 20 +++++++- .../Magento/QuoteGraphQl/etc/schema.graphqls | 8 ++-- .../GetAvailableShippingMethodsTest.php | 40 ++++++++++++---- .../Guest/GetAvailableShippingMethodsTest.php | 40 ++++++++++++---- 5 files changed, 131 insertions(+), 23 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php index a9e0ba59d15d9..958934ed18032 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php @@ -7,13 +7,16 @@ namespace Magento\QuoteGraphQl\Model\Resolver\ShippingAddress; +use Magento\Directory\Model\Currency; use Magento\Framework\Api\ExtensibleDataObjectConverter; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Api\Data\ShippingMethodInterface; use Magento\Quote\Model\Cart\ShippingMethodConverter; +use Magento\Store\Model\StoreManagerInterface; /** * @inheritdoc @@ -30,16 +33,24 @@ class AvailableShippingMethods implements ResolverInterface */ private $shippingMethodConverter; + /** + * @var StoreManagerInterface + */ + private $storeManager; + /** * @param ExtensibleDataObjectConverter $dataObjectConverter * @param ShippingMethodConverter $shippingMethodConverter + * @param StoreManagerInterface $storeManager */ public function __construct( ExtensibleDataObjectConverter $dataObjectConverter, - ShippingMethodConverter $shippingMethodConverter + ShippingMethodConverter $shippingMethodConverter, + StoreManagerInterface $storeManager ) { $this->dataObjectConverter = $dataObjectConverter; $this->shippingMethodConverter = $shippingMethodConverter; + $this->storeManager = $storeManager; } /** @@ -65,13 +76,44 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $shippingRates = $address->getGroupedAllShippingRates(); foreach ($shippingRates as $carrierRates) { foreach ($carrierRates as $rate) { - $methods[] = $this->dataObjectConverter->toFlatArray( + $methodData = $this->dataObjectConverter->toFlatArray( $this->shippingMethodConverter->modelToDataObject($rate, $cart->getQuoteCurrencyCode()), [], ShippingMethodInterface::class ); + $methods[] = $this->processMoneyTypeData($methodData, $cart->getQuoteCurrencyCode()); } } return $methods; } + + /** + * Process money type data + * + * @param array $data + * @param string $quoteCurrencyCode + * @return array + * @throws NoSuchEntityException + */ + private function processMoneyTypeData(array $data, string $quoteCurrencyCode): array + { + if (isset($data['amount'])) { + $data['amount'] = ['value' => $data['amount'], 'currency' => $quoteCurrencyCode]; + } + + if (isset($data['base_amount'])) { + /** @var Currency $currency */ + $currency = $this->storeManager->getStore()->getBaseCurrency(); + $data['base_amount'] = ['value' => $data['base_amount'], 'currency' => $currency->getCode()]; + } + + if (isset($data['price_excl_tax'])) { + $data['price_excl_tax'] = ['value' => $data['price_excl_tax'], 'currency' => $quoteCurrencyCode]; + } + + if (isset($data['price_incl_tax'])) { + $data['price_incl_tax'] = ['value' => $data['price_incl_tax'], 'currency' => $quoteCurrencyCode]; + } + return $data; + } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index cd8f20c3f164f..e396d2b46494a 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -7,18 +7,34 @@ namespace Magento\QuoteGraphQl\Model\Resolver\ShippingAddress; +use Magento\Directory\Model\Currency; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Model\Quote\Address; use Magento\Quote\Model\Quote\Address\Rate; +use Magento\Store\Model\StoreManagerInterface; /** * @inheritdoc */ class SelectedShippingMethod implements ResolverInterface { + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @param StoreManagerInterface $storeManager + */ + public function __construct( + StoreManagerInterface $storeManager + ) { + $this->storeManager = $storeManager; + } + /** * @inheritdoc */ @@ -35,6 +51,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value list($carrierCode, $methodCode) = explode('_', $address->getShippingMethod(), 2); /** @var Rate $rate */ $rate = current($rates); + /** @var Currency $currency */ + $currency = $this->storeManager->getStore()->getBaseCurrency(); $data = [ 'carrier_code' => $carrierCode, @@ -47,7 +65,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value ], 'base_amount' => [ 'value' => $address->getBaseShippingAmount(), - 'currency' => $address->getQuote()->getBaseCurrencyCode(), + 'currency' => $currency, ], ]; } else { diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index e2d29e93db574..3324ff644192a 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -243,10 +243,10 @@ type AvailableShippingMethod { method_code: String @doc(description: "Could be null if method is not available") method_title: String @doc(description: "Could be null if method is not available") error_message: String - amount: Float! - base_amount: Float @doc(description: "Could be null if method is not available") - price_excl_tax: Float! - price_incl_tax: Float! + amount: Money! + base_amount: Money @doc(description: "Could be null if method is not available") + price_excl_tax: Money! + price_incl_tax: Money! available: Boolean! } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php index 2b647f61c4c63..b01921ae67ed7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetAvailableShippingMethodsTest.php @@ -58,15 +58,27 @@ public function testGetAvailableShippingMethods() self::assertCount(1, $response['cart']['shipping_addresses'][0]['available_shipping_methods']); $expectedAddressData = [ - 'amount' => 10, - 'base_amount' => 10, + 'amount' => [ + 'value' => 10, + 'currency' => 'USD', + ], + 'base_amount' => [ + 'value' => 10, + 'currency' => 'USD', + ], 'carrier_code' => 'flatrate', 'carrier_title' => 'Flat Rate', 'error_message' => '', 'method_code' => 'flatrate', 'method_title' => 'Fixed', - 'price_incl_tax' => 10, - 'price_excl_tax' => 10, + 'price_incl_tax' => [ + 'value' => 10, + 'currency' => 'USD', + ], + 'price_excl_tax' => [ + 'value' => 10, + 'currency' => 'USD', + ], ]; self::assertEquals( $expectedAddressData, @@ -158,15 +170,27 @@ private function getQuery(string $maskedQuoteId): string cart (cart_id: "{$maskedQuoteId}") { shipping_addresses { available_shipping_methods { - amount - base_amount + amount { + value + currency + } + base_amount { + value + currency + } carrier_code carrier_title error_message method_code method_title - price_excl_tax - price_incl_tax + price_excl_tax { + value + currency + } + price_incl_tax { + value + currency + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php index a8113657eff6e..8703a690c62e3 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetAvailableShippingMethodsTest.php @@ -50,15 +50,27 @@ public function testGetAvailableShippingMethods() self::assertCount(1, $response['cart']['shipping_addresses'][0]['available_shipping_methods']); $expectedAddressData = [ - 'amount' => 10, - 'base_amount' => 10, + 'amount' => [ + 'value' => 10, + 'currency' => 'USD', + ], + 'base_amount' => [ + 'value' => 10, + 'currency' => 'USD', + ], 'carrier_code' => 'flatrate', 'carrier_title' => 'Flat Rate', 'error_message' => '', 'method_code' => 'flatrate', 'method_title' => 'Fixed', - 'price_incl_tax' => 10, - 'price_excl_tax' => 10, + 'price_incl_tax' => [ + 'value' => 10, + 'currency' => 'USD', + ], + 'price_excl_tax' => [ + 'value' => 10, + 'currency' => 'USD', + ], ]; self::assertEquals( $expectedAddressData, @@ -126,15 +138,27 @@ private function getQuery(string $maskedQuoteId): string cart (cart_id: "{$maskedQuoteId}") { shipping_addresses { available_shipping_methods { - amount - base_amount + amount { + value + currency + } + base_amount { + value + currency + } carrier_code carrier_title error_message method_code method_title - price_excl_tax - price_incl_tax + price_excl_tax { + value + currency + } + price_incl_tax { + value + currency + } } } } From 05ea6ef10a470a76735219e705825d896bf3c848 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 13:49:39 -0500 Subject: [PATCH 097/224] GraphQL-474: Cannot return null for non-nullable field SelectedCustomizableOptionValue.sort_order and Call to a member function getPriceType() on null --- .../QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index 251f17619c2a8..b491b10730c10 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -132,7 +132,7 @@ private function extractCustomizableOptions(array $cartItemData): array $customizableOptionsData = []; foreach ($cartItemData['customizable_options'] as $customizableOption) { if (isset($customizableOption['value_string'])) { - $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptions( + $customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptionValue( $customizableOption['value_string'] ); } @@ -158,10 +158,12 @@ private function createBuyRequest(float $quantity, array $customOptions): DataOb } /** + * Convert custom options vakue + * * @param string $value * @return string|array */ - private function convertCustomOptions(string $value) + private function convertCustomOptionValue(string $value) { $value = trim($value); if (substr($value, 0, 1) === "[" && From 9a01c2f2699bbd0a18dec9460cf41ce2da1dc55f Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 13:57:41 -0500 Subject: [PATCH 098/224] GraphQL-641: Schema Inconsistency of "cartItems" declaration --- .../Model/Resolver/AddSimpleProductsToCart.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php index 82ffd0970d672..cfae0e1267802 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php @@ -52,12 +52,12 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value } $maskedCartId = $args['input']['cart_id']; - if (!isset($args['input']['cartItems']) || empty($args['input']['cartItems']) - || !is_array($args['input']['cartItems']) + if (!isset($args['input']['cart_items']) || empty($args['input']['cart_items']) + || !is_array($args['input']['cart_items']) ) { - throw new GraphQlInputException(__('Required parameter "cartItems" is missing')); + throw new GraphQlInputException(__('Required parameter "cart_items" is missing')); } - $cartItems = $args['input']['cartItems']; + $cartItems = $args['input']['cart_items']; $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); $this->addProductsToCart->execute($cart, $cartItems); From 2d3760edbbf40d26f47ce66c69e89fd2bd4eb3ad Mon Sep 17 00:00:00 2001 From: Denis Kopylov <dkopylov@magenius.team> Date: Tue, 30 Apr 2019 18:35:55 +0300 Subject: [PATCH 099/224] [Catalog|Eav] Revert change of PR magento/magento2#13302 not included into revert commit https://github.com/magento/magento2/commit/06019a6215ea31982494708d55745ae0b9622696 --- .../Catalog/Model/ResourceModel/Product/Collection.php | 1 - .../Model/Entity/Collection/AbstractCollectionTest.php | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php index 0cdf8b39f7d52..76e65400721d9 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php @@ -19,7 +19,6 @@ use Magento\Framework\DB\Select; use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Indexer\DimensionFactory; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; use Magento\Store\Model\Indexer\WebsiteDimensionProvider; use Magento\Store\Model\Store; diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php index ab5b40c56685c..bc4ed7d4bd9e4 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Collection/AbstractCollectionTest.php @@ -5,9 +5,6 @@ */ namespace Magento\Eav\Test\Unit\Model\Entity\Collection; -use Magento\Framework\Data\Collection\Db\FetchStrategyInterface; -use Magento\Framework\Model\ResourceModel\ResourceModelPoolInterface; - /** * AbstractCollection test * @@ -31,7 +28,7 @@ class AbstractCollectionTest extends \PHPUnit\Framework\TestCase protected $loggerMock; /** - * @var FetchStrategyInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Data\Collection\Db\FetchStrategyInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $fetchStrategyMock; @@ -61,7 +58,7 @@ class AbstractCollectionTest extends \PHPUnit\Framework\TestCase protected $resourceHelperMock; /** - * @var ResourceModelPoolInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Validator\UniversalFactory|\PHPUnit_Framework_MockObject_MockObject */ protected $validatorFactoryMock; From a253222106d67ad7950c14d029a9de9dd59fc338 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 15:39:47 -0500 Subject: [PATCH 100/224] GraphQL-630: Schema inconsistency of "AvailableShippingMethod" declaration --- .../Resolver/ShippingAddress/SelectedShippingMethod.php | 2 +- .../GraphQl/Quote/Customer/CheckoutEndToEndTest.php | 7 +++++-- .../Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index e396d2b46494a..bf6315086ae8b 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -65,7 +65,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value ], 'base_amount' => [ 'value' => $address->getBaseShippingAmount(), - 'currency' => $currency, + 'currency' => $currency->getCode(), ], ]; } else { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php index 92974f2491f75..eddc1f98d7a96 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -309,7 +309,9 @@ private function setShippingAddress(string $cartId): array available_shipping_methods { carrier_code method_code - amount + amount { + value + } } } } @@ -334,7 +336,8 @@ private function setShippingAddress(string $cartId): array self::assertNotEmpty($availableShippingMethod['method_code']); self::assertArrayHasKey('amount', $availableShippingMethod); - self::assertNotEmpty($availableShippingMethod['amount']); + self::assertArrayHasKey('value', $availableShippingMethod['amount']); + self::assertNotEmpty($availableShippingMethod['amount']['value']); return $availableShippingMethod; } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php index bddee2151f5cd..a95e4404a08ac 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php @@ -269,7 +269,9 @@ private function setShippingAddress(string $cartId): array available_shipping_methods { carrier_code method_code - amount + amount { + value + } } } } @@ -294,7 +296,8 @@ private function setShippingAddress(string $cartId): array self::assertNotEmpty($availableShippingMethod['method_code']); self::assertArrayHasKey('amount', $availableShippingMethod); - self::assertNotEmpty($availableShippingMethod['amount']); + self::assertArrayHasKey('value', $availableShippingMethod['amount']); + self::assertNotEmpty($availableShippingMethod['amount']['value']); return $availableShippingMethod; } From ea718482b61e2dff472491bda1a64d2faf75a713 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Tue, 30 Apr 2019 15:41:30 -0500 Subject: [PATCH 101/224] GraphQL-630: Schema inconsistency of "AvailableShippingMethod" declaration --- app/code/Magento/QuoteGraphQl/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/composer.json b/app/code/Magento/QuoteGraphQl/composer.json index a3c07f7df2cee..6f4d3969d1018 100644 --- a/app/code/Magento/QuoteGraphQl/composer.json +++ b/app/code/Magento/QuoteGraphQl/composer.json @@ -11,7 +11,8 @@ "magento/module-store": "*", "magento/module-customer": "*", "magento/module-customer-graph-ql": "*", - "magento/module-sales": "*" + "magento/module-sales": "*", + "magento/module-directory": "*" }, "suggest": { "magento/module-graph-ql": "*", From 7b523ee3cace09b3d558333b9d4d649574addd5f Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@adobe.com> Date: Tue, 30 Apr 2019 17:04:35 -0500 Subject: [PATCH 102/224] MQE-1536: Magento\Install\Test\TestCase\InstallTest is failing - reverting MAGETWO-99210 --- .../lib/Magento/Mtf/Util/Command/Cli.php | 41 ++++++++--- .../Mtf/Util/Command/File/Export/Reader.php | 39 ++++++++--- .../Command/File/Export/ReaderInterface.php | 2 +- .../lib/Magento/Mtf/Util/Command/File/Log.php | 37 +++++++--- .../Mtf/Util/Command/GeneratedCode.php | 39 +++++++++-- .../lib/Magento/Mtf/Util/Command/Locales.php | 42 ++++++++--- .../Magento/Mtf/Util/Command/PathChecker.php | 43 +++++++++--- .../lib/Magento/Mtf/Util/Command/Website.php | 40 +++++++---- .../CurlTransport/BackendDecorator.php | 69 ++++++++++++++----- .../CurlTransport/WebapiDecorator.php | 32 ++++++++- .../Config/Test/Handler/ConfigData/Curl.php | 2 +- dev/tests/functional/utils/authenticate.php | 29 ++++++++ dev/tests/functional/utils/command.php | 32 +++++---- .../utils/deleteMagentoGeneratedCode.php | 14 +++- dev/tests/functional/utils/export.php | 51 +++++++------- dev/tests/functional/utils/locales.php | 34 +++++---- dev/tests/functional/utils/log.php | 32 +++++---- dev/tests/functional/utils/pathChecker.php | 27 ++++---- dev/tests/functional/utils/website.php | 52 +++++++------- 19 files changed, 467 insertions(+), 190 deletions(-) create mode 100644 dev/tests/functional/utils/authenticate.php diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php index 8fa22122cce89..f0abd280f3ebc 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Cli.php @@ -8,6 +8,7 @@ use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; +use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * Perform bin/magento commands from command line for functional tests executions. @@ -17,7 +18,7 @@ class Cli /** * Url to command.php. */ - const URL = 'dev/tests/functional/utils/command.php'; + const URL = '/dev/tests/functional/utils/command.php'; /** * Curl transport protocol. @@ -26,12 +27,21 @@ class Cli */ private $transport; + /** + * Webapi handler. + * + * @var WebapiDecorator + */ + private $webapiHandler; + /** * @param CurlTransport $transport + * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport) + public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) { $this->transport = $transport; + $this->webapiHandler = $webapiHandler; } /** @@ -43,22 +53,31 @@ public function __construct(CurlTransport $transport) */ public function execute($command, $options = []) { - $curl = $this->transport; - $curl->write($this->prepareUrl($command, $options), [], CurlInterface::GET); - $curl->read(); - $curl->close(); + $this->transport->write( + rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, + $this->prepareParamArray($command, $options), + CurlInterface::POST, + [] + ); + $this->transport->read(); + $this->transport->close(); } /** - * Prepare url. + * Prepare parameter array. * * @param string $command * @param array $options [optional] - * @return string + * @return array */ - private function prepareUrl($command, $options = []) + private function prepareParamArray($command, $options = []) { - $command .= ' ' . implode(' ', $options); - return $_ENV['app_frontend_url'] . self::URL . '?command=' . urlencode($command); + if (!empty($options)) { + $command .= ' ' . implode(' ', $options); + } + return [ + 'token' => urlencode($this->webapiHandler->getWebapiToken()), + 'command' => urlencode($command) + ]; } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php index d7336b51a18e2..f5b6d681e4f6c 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/Reader.php @@ -3,12 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Mtf\Util\Command\File\Export; use Magento\Mtf\ObjectManagerInterface; use Magento\Mtf\Util\Protocol\CurlTransport; use Magento\Mtf\Util\Protocol\CurlInterface; +use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * File reader for Magento export files. @@ -36,16 +36,29 @@ class Reader implements ReaderInterface */ private $transport; + /** + * Webapi handler. + * + * @var WebapiDecorator + */ + private $webapiHandler; + /** * @param ObjectManagerInterface $objectManager * @param CurlTransport $transport + * @param WebapiDecorator $webapiHandler * @param string $template */ - public function __construct(ObjectManagerInterface $objectManager, CurlTransport $transport, $template) - { + public function __construct( + ObjectManagerInterface $objectManager, + CurlTransport $transport, + WebapiDecorator $webapiHandler, + $template + ) { $this->objectManager = $objectManager; $this->template = $template; $this->transport = $transport; + $this->webapiHandler = $webapiHandler; } /** @@ -70,20 +83,28 @@ public function getData() */ private function getFiles() { - $this->transport->write($this->prepareUrl(), [], CurlInterface::GET); + $this->transport->write( + rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, + $this->prepareParamArray(), + CurlInterface::POST, + [] + ); $serializedFiles = $this->transport->read(); $this->transport->close(); // phpcs:ignore Magento2.Security.InsecureFunction - return unserialize($serializedFiles, ['allowed_classes' => false]); + return unserialize($serializedFiles); } /** - * Prepare url. + * Prepare parameter array. * - * @return string + * @return array */ - private function prepareUrl() + private function prepareParamArray() { - return $_ENV['app_frontend_url'] . self::URL . '?template=' . urlencode($this->template); + return [ + 'token' => urlencode($this->webapiHandler->getWebapiToken()), + 'template' => urlencode($this->template) + ]; } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php index 93f7cf1ce9764..3666e8643efa3 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Export/ReaderInterface.php @@ -14,7 +14,7 @@ interface ReaderInterface /** * Url to export.php. */ - const URL = 'dev/tests/functional/utils/export.php'; + const URL = '/dev/tests/functional/utils/export.php'; /** * Exporting files as Data object from Magento. diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Log.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Log.php index f4e55682857a2..2539be593a713 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Log.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/File/Log.php @@ -7,6 +7,7 @@ namespace Magento\Mtf\Util\Command\File; use Magento\Mtf\Util\Protocol\CurlTransport; +use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * Get content of log file in var/log folder. @@ -16,7 +17,7 @@ class Log /** * Url to log.php. */ - const URL = 'dev/tests/functional/utils/log.php'; + const URL = '/dev/tests/functional/utils/log.php'; /** * Curl transport protocol. @@ -25,12 +26,21 @@ class Log */ private $transport; + /** + * Webapi handler. + * + * @var WebapiDecorator + */ + private $webapiHandler; + /** * @param CurlTransport $transport + * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport) + public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) { $this->transport = $transport; + $this->webapiHandler = $webapiHandler; } /** @@ -41,22 +51,29 @@ public function __construct(CurlTransport $transport) */ public function getFileContent($name) { - $curl = $this->transport; - $curl->write($this->prepareUrl($name), [], CurlTransport::GET); - $data = $curl->read(); - $curl->close(); + $this->transport->write( + rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, + $this->prepareParamArray($name), + CurlInterface::POST, + [] + ); + $data = $this->transport->read(); + $this->transport->close(); // phpcs:ignore Magento2.Security.InsecureFunction return unserialize($data); } /** - * Prepare url. + * Prepare parameter array. * * @param string $name - * @return string + * @return array */ - private function prepareUrl($name) + private function prepareParamArray($name) { - return $_ENV['app_frontend_url'] . self::URL . '?name=' . urlencode($name); + return [ + 'token' => urlencode($this->webapiHandler->getWebapiToken()), + 'name' => urlencode($name) + ]; } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/GeneratedCode.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/GeneratedCode.php index dde3409ed1562..a9fefa25ffa24 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/GeneratedCode.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/GeneratedCode.php @@ -7,6 +7,7 @@ use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; +use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * GeneratedCode removes generated code of Magento (like generated/code and generated/metadata). @@ -16,7 +17,7 @@ class GeneratedCode /** * Url to deleteMagentoGeneratedCode.php. */ - const URL = 'dev/tests/functional/utils/deleteMagentoGeneratedCode.php'; + const URL = '/dev/tests/functional/utils/deleteMagentoGeneratedCode.php'; /** * Curl transport protocol. @@ -25,12 +26,21 @@ class GeneratedCode */ private $transport; + /** + * Webapi handler. + * + * @var WebapiDecorator + */ + private $webapiHandler; + /** * @param CurlTransport $transport + * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport) + public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) { $this->transport = $transport; + $this->webapiHandler = $webapiHandler; } /** @@ -40,10 +50,25 @@ public function __construct(CurlTransport $transport) */ public function delete() { - $url = $_ENV['app_frontend_url'] . self::URL; - $curl = $this->transport; - $curl->write($url, [], CurlInterface::GET); - $curl->read(); - $curl->close(); + $this->transport->write( + rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, + $this->prepareParamArray(), + CurlInterface::POST, + [] + ); + $this->transport->read(); + $this->transport->close(); + } + + /** + * Prepare parameter array. + * + * @return array + */ + private function prepareParamArray() + { + return [ + 'token' => urlencode($this->webapiHandler->getWebapiToken()) + ]; } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Locales.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Locales.php index f669d91f2f2e5..a55d803f43087 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Locales.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Locales.php @@ -7,6 +7,7 @@ use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; +use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * Returns array of locales depends on fetching type. @@ -26,7 +27,7 @@ class Locales /** * Url to locales.php. */ - const URL = 'dev/tests/functional/utils/locales.php'; + const URL = '/dev/tests/functional/utils/locales.php'; /** * Curl transport protocol. @@ -35,12 +36,21 @@ class Locales */ private $transport; + /** + * Webapi handler. + * + * @var WebapiDecorator + */ + private $webapiHandler; + /** * @param CurlTransport $transport Curl transport protocol + * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport) + public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) { $this->transport = $transport; + $this->webapiHandler = $webapiHandler; } /** @@ -51,12 +61,28 @@ public function __construct(CurlTransport $transport) */ public function getList($type = self::TYPE_ALL) { - $url = $_ENV['app_frontend_url'] . self::URL . '?type=' . $type; - $curl = $this->transport; - $curl->write($url, [], CurlInterface::GET); - $result = $curl->read(); - $curl->close(); - + $this->transport->write( + rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, + $this->prepareParamArray($type), + CurlInterface::POST, + [] + ); + $result = $this->transport->read(); + $this->transport->close(); return explode('|', $result); } + + /** + * Prepare parameter array. + * + * @param string $type + * @return array + */ + private function prepareParamArray($type) + { + return [ + 'token' => urlencode($this->webapiHandler->getWebapiToken()), + 'type' => urlencode($type) + ]; + } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/PathChecker.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/PathChecker.php index fd1f746a6f09c..4b12f6eec87aa 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/PathChecker.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/PathChecker.php @@ -7,6 +7,7 @@ use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; +use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * PathChecker checks that path to file or directory exists. @@ -16,7 +17,7 @@ class PathChecker /** * Url to checkPath.php. */ - const URL = 'dev/tests/functional/utils/pathChecker.php'; + const URL = '/dev/tests/functional/utils/pathChecker.php'; /** * Curl transport protocol. @@ -26,11 +27,21 @@ class PathChecker private $transport; /** + * Webapi handler. + * + * @var WebapiDecorator + */ + private $webapiHandler; + + /** + * @constructor * @param CurlTransport $transport + * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport) + public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) { $this->transport = $transport; + $this->webapiHandler = $webapiHandler; } /** @@ -41,12 +52,28 @@ public function __construct(CurlTransport $transport) */ public function pathExists($path) { - $url = $_ENV['app_frontend_url'] . self::URL . '?path=' . urlencode($path); - $curl = $this->transport; - $curl->write($url, [], CurlInterface::GET); - $result = $curl->read(); - $curl->close(); - + $this->transport->write( + rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, + $this->prepareParamArray($path), + CurlInterface::POST, + [] + ); + $result = $this->transport->read(); + $this->transport->close(); return strpos($result, 'path exists: true') !== false; } + + /** + * Prepare parameter array. + * + * @param string $path + * @return array + */ + private function prepareParamArray($path) + { + return [ + 'token' => urlencode($this->webapiHandler->getWebapiToken()), + 'path' => urlencode($path) + ]; + } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php index 7d73634c0360d..fec20bb2a8715 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Command/Website.php @@ -3,11 +3,11 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Mtf\Util\Command; use Magento\Mtf\Util\Protocol\CurlInterface; use Magento\Mtf\Util\Protocol\CurlTransport; +use Magento\Mtf\Util\Protocol\CurlTransport\WebapiDecorator; /** * Perform Website folder creation for functional tests executions. @@ -17,7 +17,7 @@ class Website /** * Url to website.php. */ - const URL = 'dev/tests/functional/utils/website.php'; + const URL = '/dev/tests/functional/utils/website.php'; /** * Curl transport protocol. @@ -26,13 +26,22 @@ class Website */ private $transport; + /** + * Webapi handler. + * + * @var WebapiDecorator + */ + private $webapiHandler; + /** * @constructor * @param CurlTransport $transport + * @param WebapiDecorator $webapiHandler */ - public function __construct(CurlTransport $transport) + public function __construct(CurlTransport $transport, WebapiDecorator $webapiHandler) { $this->transport = $transport; + $this->webapiHandler = $webapiHandler; } /** @@ -43,21 +52,28 @@ public function __construct(CurlTransport $transport) */ public function create($websiteCode) { - $curl = $this->transport; - $curl->addOption(CURLOPT_HEADER, 1); - $curl->write($this->prepareUrl($websiteCode), [], CurlInterface::GET); - $curl->read(); - $curl->close(); + $this->transport->addOption(CURLOPT_HEADER, 1); + $this->transport->write( + rtrim(str_replace('index.php', '', $_ENV['app_frontend_url']), '/') . self::URL, + $this->prepareParamArray($websiteCode), + CurlInterface::POST, + [] + ); + $this->transport->read(); + $this->transport->close(); } /** - * Prepare url. + * Prepare parameter array. * * @param string $websiteCode - * @return string + * @return array */ - private function prepareUrl($websiteCode) + private function prepareParamArray($websiteCode) { - return $_ENV['app_frontend_url'] . self::URL . '?website_code=' . urlencode($websiteCode); + return [ + 'token' => urlencode($this->webapiHandler->getWebapiToken()), + 'website_code' => urlencode($websiteCode) + ]; } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php index b1c552370835c..5999b52141f05 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php @@ -63,24 +63,59 @@ public function __construct(CurlTransport $transport, DataInterface $configurati */ protected function authorize() { - // Perform GET to backend url so form_key is set - $url = $_ENV['app_backend_url']; - $this->transport->write($url, [], CurlInterface::GET); - $this->read(); - - $url = $_ENV['app_backend_url'] . $this->configuration->get('application/0/backendLoginUrl/0/value'); - $data = [ - 'login[username]' => $this->configuration->get('application/0/backendLogin/0/value'), - 'login[password]' => $this->configuration->get('application/0/backendPassword/0/value'), - 'form_key' => $this->formKey, - ]; - $this->transport->write($url, $data, CurlInterface::POST); - $response = $this->read(); - if (strpos($response, 'login-form') !== false) { + // There are situations where magento application backend url could be slightly different from the environment + // variable we know. It could be intentionally (e.g. InstallTest) or unintentionally. We would still want tests + // to run in this case. + // When the original app_backend_url does not work, we will try 4 variants of the it. i.e. with and without + // url rewrite, http and https. + $urls = []; + $originalUrl = rtrim($_ENV['app_backend_url'], '/') . '/'; + $urls[] = $originalUrl; + // It could be the case that the page needs a refresh, so we will try the original one twice. + $urls[] = $originalUrl; + if (strpos($originalUrl, '/index.php') !== false) { + $url2 = str_replace('/index.php', '', $originalUrl); + } else { + $url2 = $originalUrl . 'index.php/'; + } + $urls[] = $url2; + if (strpos($originalUrl, 'https') !== false) { + $urls[] = str_replace('https', 'http', $originalUrl); + $urls[] = str_replace('https', 'http', $url2); + } else { + $urls[] = str_replace('http', 'https', $originalUrl); + $urls[] = str_replace('http', 'https', $url2); + } + + $isAuthorized = false; + foreach ($urls as $url) { + try { + // Perform GET to backend url so form_key is set + $this->transport->write($url, [], CurlInterface::GET); + $this->read(); + + $authUrl = $url . $this->configuration->get('application/0/backendLoginUrl/0/value'); + $data = [ + 'login[username]' => $this->configuration->get('application/0/backendLogin/0/value'), + 'login[password]' => $this->configuration->get('application/0/backendPassword/0/value'), + 'form_key' => $this->formKey, + ]; + + $this->transport->write($authUrl, $data, CurlInterface::POST); + $response = $this->read(); + if (strpos($response, 'login-form') !== false) { + continue; + } + $isAuthorized = true; + $_ENV['app_backend_url'] = $url; + break; + } catch (\Exception $e) { + continue; + } + } + if ($isAuthorized == false) { // phpcs:ignore Magento2.Exceptions.DirectThrow - throw new \Exception( - 'Admin user cannot be logged in by curl handler!' - ); + throw new \Exception('Admin user cannot be logged in by curl handler!'); } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/WebapiDecorator.php b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/WebapiDecorator.php index 3aa756904ab00..df5ab45a3f96d 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/WebapiDecorator.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/WebapiDecorator.php @@ -70,6 +70,13 @@ class WebapiDecorator implements CurlInterface */ protected $response; + /** + * Webapi token. + * + * @var string + */ + protected $webapiToken; + /** * @construct * @param ObjectManager $objectManager @@ -110,6 +117,9 @@ protected function init() $integration->persist(); $this->setConfiguration($integration); + $this->webapiToken = $integration->getToken(); + } else { + $this->webapiToken = $integrationToken; } } @@ -161,7 +171,13 @@ protected function setConfiguration(Integration $integration) */ protected function isValidIntegration() { - $this->write($_ENV['app_frontend_url'] . 'rest/V1/modules', [], CurlInterface::GET); + $url = rtrim($_ENV['app_frontend_url'], '/'); + if (strpos($url, 'index.php') === false) { + $url .= '/index.php/rest/V1/modules'; + } else { + $url .= '/rest/V1/modules'; + } + $this->write($url, [], CurlInterface::GET); $response = json_decode($this->read(), true); return (null !== $response) && !isset($response['message']); @@ -219,4 +235,18 @@ public function close() { $this->transport->close(); } + + /** + * Return webapiToken. + * + * @return string + */ + public function getWebapiToken() + { + // Request token if integration is no longer valid + if (!$this->isValidIntegration()) { + $this->init(); + } + return $this->webapiToken; + } } diff --git a/dev/tests/functional/tests/app/Magento/Config/Test/Handler/ConfigData/Curl.php b/dev/tests/functional/tests/app/Magento/Config/Test/Handler/ConfigData/Curl.php index 66587879848a3..0d89a1d4eba6e 100644 --- a/dev/tests/functional/tests/app/Magento/Config/Test/Handler/ConfigData/Curl.php +++ b/dev/tests/functional/tests/app/Magento/Config/Test/Handler/ConfigData/Curl.php @@ -123,9 +123,9 @@ protected function prepareConfigPath(array $input) */ protected function applyConfigSettings(array $data, $section) { - $url = $this->getUrl($section); $curl = new BackendDecorator(new CurlTransport(), $this->_configuration); $curl->addOption(CURLOPT_HEADER, 1); + $url = $this->getUrl($section); $curl->write($url, $data); $response = $curl->read(); $curl->close(); diff --git a/dev/tests/functional/utils/authenticate.php b/dev/tests/functional/utils/authenticate.php new file mode 100644 index 0000000000000..15851f6e8000a --- /dev/null +++ b/dev/tests/functional/utils/authenticate.php @@ -0,0 +1,29 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Check if token passed in is a valid auth token. + * + * @param string $token + * @return bool + */ +function authenticate($token) +{ + require_once __DIR__ . '/../../../../app/bootstrap.php'; + + $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); + $magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER); + $tokenModel = $magentoObjectManager->get(\Magento\Integration\Model\Oauth\Token::class); + + $tokenPassedIn = $token; + // Token returned will be null if the token we passed in is invalid + $tokenFromMagento = $tokenModel->loadByToken($tokenPassedIn)->getToken(); + if (!empty($tokenFromMagento) && ($tokenFromMagento == $tokenPassedIn)) { + return true; + } else { + return false; + } +} diff --git a/dev/tests/functional/utils/command.php b/dev/tests/functional/utils/command.php index 99025dd1cffcc..a3f6d1e19b4e9 100644 --- a/dev/tests/functional/utils/command.php +++ b/dev/tests/functional/utils/command.php @@ -3,7 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - +// phpcs:ignore Magento2.Security.IncludeFile +include __DIR__ . '/authenticate.php'; // phpcs:ignore Magento2.Security.IncludeFile require_once __DIR__ . '/../../../../app/bootstrap.php'; @@ -11,18 +12,21 @@ use Symfony\Component\Console\Output\NullOutput; // phpcs:ignore Magento2.Security.Superglobal -if (isset($_GET['command'])) { - // phpcs:ignore Magento2.Security.Superglobal - $command = urldecode($_GET['command']); - // phpcs:ignore Magento2.Security.Superglobal - $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); - // phpcs:ignore Magento2.Security.Superglobal - $magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER); - $cli = $magentoObjectManager->create(\Magento\Framework\Console\Cli::class); - $input = new StringInput($command); - $input->setInteractive(false); - $output = new NullOutput(); - $cli->doRun($input, $output); +if (!empty($_POST['token']) && !empty($_POST['command'])) { + if (authenticate(urldecode($_POST['token']))) { + $command = urldecode($_POST['command']); + // phpcs:ignore Magento2.Security.Superglobal + $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); + // phpcs:ignore Magento2.Security.Superglobal + $magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER); + $cli = $magentoObjectManager->create(\Magento\Framework\Console\Cli::class); + $input = new StringInput(escapeshellcmd($command)); + $input->setInteractive(false); + $output = new NullOutput(); + $cli->doRun($input, $output); + } else { + echo "Command not unauthorized."; + } } else { - throw new \InvalidArgumentException("Command GET parameter is not set."); + echo "'token' or 'command' parameter is not set."; } diff --git a/dev/tests/functional/utils/deleteMagentoGeneratedCode.php b/dev/tests/functional/utils/deleteMagentoGeneratedCode.php index 17260bd1da635..dcdedcbeeb04a 100644 --- a/dev/tests/functional/utils/deleteMagentoGeneratedCode.php +++ b/dev/tests/functional/utils/deleteMagentoGeneratedCode.php @@ -3,6 +3,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +// phpcs:ignore Magento2.Security.IncludeFile +include __DIR__ . '/authenticate.php'; -// phpcs:ignore Magento2.Security.InsecureFunction -exec('rm -rf ../../../../generated/*'); +if (!empty($_POST['token']) && !empty($_POST['path'])) { + if (authenticate(urldecode($_POST['token']))) { + // phpcs:ignore Magento2.Security.InsecureFunction + exec('rm -rf ../../../../generated/*'); + } else { + echo "Command not unauthorized."; + } +} else { + echo "'token' parameter is not set."; +} diff --git a/dev/tests/functional/utils/export.php b/dev/tests/functional/utils/export.php index fa50bc729d0f6..5cdc74c880a76 100644 --- a/dev/tests/functional/utils/export.php +++ b/dev/tests/functional/utils/export.php @@ -3,32 +3,35 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +// phpcs:ignore Magento2.Security.IncludeFile +include __DIR__ . '/authenticate.php'; -// phpcs:ignore Magento2.Security.Superglobal -if (!isset($_GET['template'])) { - // phpcs:ignore Magento2.Exceptions.DirectThrow - throw new \InvalidArgumentException('Argument "template" must be set.'); -} +if (!empty($_POST['token']) && !empty($_POST['template'])) { + if (authenticate(urldecode($_POST['token']))) { + $varDir = '../../../../var/'; + $template = urldecode($_POST['template']); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + $fileList = scandir($varDir, SCANDIR_SORT_NONE); + $files = []; -$varDir = '../../../../var/export/'; -// phpcs:ignore Magento2.Security.Superglobal -$template = urldecode($_GET['template']); -// phpcs:ignore Magento2.Functions.DiscouragedFunction -$fileList = scandir($varDir, SCANDIR_SORT_NONE); -$files = []; + foreach ($fileList as $fileName) { + if (preg_match("`$template`", $fileName) === 1) { + $filePath = $varDir . $fileName; + $files[] = [ + // phpcs:ignore Magento2.Functions.DiscouragedFunction + 'content' => file_get_contents($filePath), + 'name' => $fileName, + // phpcs:ignore Magento2.Functions.DiscouragedFunction + 'date' => filectime($filePath), + ]; + } + } -foreach ($fileList as $fileName) { - if (preg_match("`$template`", $fileName) === 1) { - $filePath = $varDir . $fileName; - $files[] = [ - // phpcs:ignore Magento2.Functions.DiscouragedFunction - 'content' => file_get_contents($filePath), - 'name' => $fileName, - // phpcs:ignore Magento2.Functions.DiscouragedFunction - 'date' => filectime($filePath), - ]; + // phpcs:ignore Magento2.Security.LanguageConstruct, Magento2.Security.InsecureFunction + echo serialize($files); + } else { + echo "Command not unauthorized."; } +} else { + echo "'token' or 'template' parameter is not set."; } - -// phpcs:ignore Magento2.Security.LanguageConstruct, Magento2.Security.InsecureFunction -echo serialize($files); diff --git a/dev/tests/functional/utils/locales.php b/dev/tests/functional/utils/locales.php index 11e1e2b70fa50..97c8932a9e6c0 100644 --- a/dev/tests/functional/utils/locales.php +++ b/dev/tests/functional/utils/locales.php @@ -3,20 +3,26 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +// phpcs:ignore Magento2.Security.IncludeFile +include __DIR__ . '/authenticate.php'; -// phpcs:ignore Magento2.Security.Superglobal -if (isset($_GET['type']) && $_GET['type'] == 'deployed') { - // phpcs:ignore Magento2.Security.Superglobal - $themePath = isset($_GET['theme_path']) ? $_GET['theme_path'] : 'adminhtml/Magento/backend'; - $directory = __DIR__ . '/../../../../pub/static/' . $themePath; - // phpcs:ignore Magento2.Functions.DiscouragedFunction - $locales = array_diff(scandir($directory), ['..', '.']); +if (!empty($_POST['token'])) { + if (authenticate(urldecode($_POST['token']))) { + if ($_POST['type'] == 'deployed') { + $themePath = isset($_POST['theme_path']) ? $_POST['theme_path'] : 'adminhtml/Magento/backend'; + $directory = __DIR__ . '/../../../../pub/static/' . $themePath; + $locales = array_diff(scandir($directory), ['..', '.']); + } else { + // phpcs:ignore Magento2.Security.IncludeFile + require_once __DIR__ . DIRECTORY_SEPARATOR . 'bootstrap.php'; + $localeConfig = $magentoObjectManager->create(\Magento\Framework\Locale\Config::class); + $locales = $localeConfig->getAllowedLocales(); + } + // phpcs:ignore Magento2.Security.LanguageConstruct + echo implode('|', $locales); + } else { + echo "Command not unauthorized."; + } } else { - // phpcs:ignore Magento2.Security.IncludeFile - require_once __DIR__ . DIRECTORY_SEPARATOR . 'bootstrap.php'; - $localeConfig = $magentoObjectManager->create(\Magento\Framework\Locale\Config::class); - $locales = $localeConfig->getAllowedLocales(); + echo "'token' parameter is not set."; } - -// phpcs:ignore Magento2.Security.LanguageConstruct -echo implode('|', $locales); diff --git a/dev/tests/functional/utils/log.php b/dev/tests/functional/utils/log.php index 30783ae8e1d28..cec2e1c0ad211 100644 --- a/dev/tests/functional/utils/log.php +++ b/dev/tests/functional/utils/log.php @@ -3,21 +3,23 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - declare(strict_types=1); -// phpcs:ignore Magento2.Security.Superglobal -if (!isset($_GET['name'])) { - // phpcs:ignore Magento2.Exceptions.DirectThrow - throw new \InvalidArgumentException( - 'The name of log file is required for getting logs.' - ); -} +// phpcs:ignore Magento2.Security.IncludeFile +include __DIR__ . '/authenticate.php'; -// phpcs:ignore Magento2.Security.Superglobal -$name = urldecode($_GET['name']); -if (preg_match('/\.\.(\\\|\/)/', $name)) { - throw new \InvalidArgumentException('Invalid log file name'); -} +if (!empty($_POST['token']) && !empty($_POST['name'])) { + if (authenticate(urldecode($_POST['token']))) { + $name = urldecode($_POST['name']); + if (preg_match('/\.\.(\\\|\/)/', $name)) { + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \InvalidArgumentException('Invalid log file name'); + } -// phpcs:ignore Magento2.Security.InsecureFunction, Magento2.Functions.DiscouragedFunction, Magento2.Security.LanguageConstruct -echo serialize(file_get_contents('../../../../var/log' .'/' .$name)); + // phpcs:ignore Magento2.Security.InsecureFunction, Magento2.Functions.DiscouragedFunction, Magento2.Security.LanguageConstruct + echo serialize(file_get_contents('../../../../var/log' . '/' . $name)); + } else { + echo "Command not unauthorized."; + } +} else { + echo "'token' or 'name' parameter is not set."; +} diff --git a/dev/tests/functional/utils/pathChecker.php b/dev/tests/functional/utils/pathChecker.php index 217cf90af0a56..ed1949d71768d 100644 --- a/dev/tests/functional/utils/pathChecker.php +++ b/dev/tests/functional/utils/pathChecker.php @@ -3,20 +3,23 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +// phpcs:ignore Magento2.Security.IncludeFile +include __DIR__ . '/authenticate.php'; -// phpcs:ignore Magento2.Security.Superglobal -if (isset($_GET['path'])) { - // phpcs:ignore Magento2.Security.Superglobal - $path = urldecode($_GET['path']); - // phpcs:ignore Magento2.Functions.DiscouragedFunction - if (file_exists('../../../../' . $path)) { - // phpcs:ignore Magento2.Security.LanguageConstruct - echo 'path exists: true'; +if (!empty($_POST['token']) && !empty($_POST['path'])) { + if (authenticate(urldecode($_POST['token']))) { + $path = urldecode($_POST['path']); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + if (file_exists('../../../../' . $path)) { + // phpcs:ignore Magento2.Security.LanguageConstruct + echo 'path exists: true'; + } else { + // phpcs:ignore Magento2.Security.LanguageConstruct + echo 'path exists: false'; + } } else { - // phpcs:ignore Magento2.Security.LanguageConstruct - echo 'path exists: false'; + echo "Command not unauthorized."; } } else { - // phpcs:ignore Magento2.Exceptions.DirectThrow - throw new \InvalidArgumentException("GET parameter 'path' is not set."); + echo "'token' or 'path' parameter is not set."; } diff --git a/dev/tests/functional/utils/website.php b/dev/tests/functional/utils/website.php index 720b4962aedd4..980dd557db6f7 100644 --- a/dev/tests/functional/utils/website.php +++ b/dev/tests/functional/utils/website.php @@ -3,36 +3,40 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +// phpcs:ignore Magento2.Security.IncludeFile +include __DIR__ . '/authenticate.php'; -// phpcs:ignore Magento2.Security.Superglobal -if (!isset($_GET['website_code'])) { - // phpcs:ignore Magento2.Exceptions.DirectThrow - throw new \Exception("website_code GET parameter is not set."); -} - -// phpcs:ignore Magento2.Security.Superglobal -$websiteCode = urldecode($_GET['website_code']); -$rootDir = '../../../../'; -$websiteDir = $rootDir . 'websites/' . $websiteCode . '/'; -// phpcs:ignore Magento2.Functions.DiscouragedFunction -$contents = file_get_contents($rootDir . 'index.php'); +if (!empty($_POST['token']) && !empty($_POST['website_code'])) { + if (authenticate(urldecode($_POST['token']))) { + $websiteCode = urldecode($_POST['website_code']); + $rootDir = '../../../../'; + $websiteDir = $rootDir . 'websites/' . $websiteCode . '/'; + // phpcs:ignore Magento2.Functions.DiscouragedFunction + $contents = file_get_contents($rootDir . 'index.php'); -$websiteParam = <<<EOD + $websiteParam = <<<EOD \$params = \$_SERVER; \$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE] = '$websiteCode'; \$params[\Magento\Store\Model\StoreManager::PARAM_RUN_TYPE] = 'website'; EOD; -$pattern = '`(try {.*?)(\/app\/bootstrap.*?}\n)(.*?)\$_SERVER`mis'; -$replacement = "$1/../..$2\n$websiteParam$3\$params"; + $pattern = '`(try {.*?)(\/app\/bootstrap.*?}\n)(.*?)\$_SERVER`mis'; + $replacement = "$1/../..$2\n$websiteParam$3\$params"; -$contents = preg_replace($pattern, $replacement, $contents); + $contents = preg_replace($pattern, $replacement, $contents); -$old = umask(0); -// phpcs:ignore Magento2.Functions.DiscouragedFunction -mkdir($websiteDir, 0760, true); -umask($old); -// phpcs:ignore Magento2.Functions.DiscouragedFunction -copy($rootDir . '.htaccess', $websiteDir . '.htaccess'); -// phpcs:ignore Magento2.Functions.DiscouragedFunction -file_put_contents($websiteDir . 'index.php', $contents); + $old = umask(0); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + mkdir($websiteDir, 0760, true); + umask($old); + + // phpcs:ignore Magento2.Functions.DiscouragedFunction + copy($rootDir . '.htaccess', $websiteDir . '.htaccess'); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + file_put_contents($websiteDir . 'index.php', $contents); + } else { + echo "Command not unauthorized."; + } +} else { + echo "'token' or 'website_code' parameter is not set."; +} From 91d8a9279adab6e067422840af32eec8b7507a50 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 1 May 2019 02:12:06 +0300 Subject: [PATCH 103/224] magento/graphql-ce#646: Incorrect name of Selected Shipping Method --- .../SelectedShippingMethod.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index cd8f20c3f164f..61c535d350092 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -30,17 +30,26 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value /** @var Address $address */ $address = $value['model']; $rates = $address->getAllShippingRates(); + $carrierTitle = null; + $methodTitle = null; if (count($rates) > 0) { list($carrierCode, $methodCode) = explode('_', $address->getShippingMethod(), 2); + /** @var Rate $rate */ - $rate = current($rates); + foreach ($rates as $rate) { + if ($rate->getCode() == $address->getShippingMethod()) { + $carrierTitle = $rate->getCarrierTitle(); + $methodTitle = $rate->getMethodTitle(); + break; + } + } $data = [ 'carrier_code' => $carrierCode, 'method_code' => $methodCode, - 'carrier_title' => $rate->getCarrierTitle(), - 'method_title' => $rate->getMethodTitle(), + 'carrier_title' => $carrierTitle, + 'method_title' => $methodTitle, 'amount' => [ 'value' => $address->getShippingAmount(), 'currency' => $address->getQuote()->getQuoteCurrencyCode(), @@ -54,8 +63,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $data = [ 'carrier_code' => null, 'method_code' => null, - 'carrier_title' => null, - 'method_title' => null, + 'carrier_title' => $carrierTitle, + 'method_title' => $methodTitle, 'amount' => null, 'base_amount' => null, ]; From 8a65e48c2414f7516b0c6444525dc078c8a9b392 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 1 May 2019 10:29:41 +0300 Subject: [PATCH 104/224] graphQl-640: fixed input type declaration for PaymentMethodAdditionalDataInput and SelectedPaymentMethodAdditionalData --- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index e2d29e93db574..800d0582ff6d4 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -134,8 +134,7 @@ input PaymentMethodInput { purchase_order_number: String @doc(description:"Purchase order number") } -input PaymentMethodAdditionalDataInput { -} +input PaymentMethodAdditionalDataInput input SetGuestEmailOnCartInput { cart_id: String! @@ -262,8 +261,7 @@ type SelectedPaymentMethod { purchase_order_number: String @doc(description: "The purchase order number.") } -type SelectedPaymentMethodAdditionalData { -} +type SelectedPaymentMethodAdditionalData type AppliedCoupon { code: String! From 9d240e3a52af09f32799ec52dc08e3dc89e707f0 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 1 May 2019 11:49:53 +0300 Subject: [PATCH 105/224] graphQl-535: provided catalog configs --- .../Magento/CatalogGraphQl/etc/graphql/di.xml | 22 ++++++++ .../CatalogGraphQl/etc/schema.graphqls | 19 +++++++ .../GraphQl/Catalog/StoreConfigTest.php | 55 +++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/StoreConfigTest.php diff --git a/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml b/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml index a5bd42860ded0..5d5c92edd3d57 100644 --- a/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml @@ -80,4 +80,26 @@ </virtualType> <preference for="Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match" type="Magento\CatalogGraphQl\Model\Search\Adapter\Mysql\Query\Builder\Match" /> + <type name="Magento\StoreGraphQl\Model\Resolver\Store\StoreConfigDataProvider"> + <arguments> + <argument name="extendedConfigData" xsi:type="array"> + <item name="product_url_suffix" xsi:type="string">catalog/seo/product_url_suffix</item> + <item name="category_url_suffix" xsi:type="string">catalog/seo/category_url_suffix</item> + <item name="product_use_categories" xsi:type="string">catalog/seo/product_use_categories</item> + <item name="save_rewrites_history" xsi:type="string">catalog/seo/save_rewrites_history</item> + <item name="title_separator" xsi:type="string">catalog/seo/title_separator</item> + <item name="category_canonical_tag" xsi:type="string">catalog/seo/category_canonical_tag</item> + <item name="product_canonical_tag" xsi:type="string">catalog/seo/product_canonical_tag</item> + <item name="list_mode" xsi:type="string">catalog/frontend/list_mode</item> + <item name="grid_per_page_values" xsi:type="string">catalog/frontend/grid_per_page_values</item> + <item name="list_per_page_values" xsi:type="string">catalog/frontend/list_per_page_values</item> + <item name="grid_per_page" xsi:type="string">catalog/frontend/grid_per_page</item> + <item name="list_per_page" xsi:type="string">catalog/frontend/list_per_page</item> + <item name="flat_catalog_category" xsi:type="string">catalog/frontend/flat_catalog_category</item> + <item name="catalog_default_sort_by" xsi:type="string">catalog/frontend/default_sort_by</item> + <item name="parse_url_directives" xsi:type="string">catalog/frontend/parse_url_directives</item> + <item name="remember_pagination" xsi:type="string">catalog/frontend/remember_pagination</item> + </argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 9f102a1c6a150..1b04e2b0ff6aa 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -401,3 +401,22 @@ type SortFields @doc(description: "SortFields contains a default value for sort default: String @doc(description: "Default value of sort fields") options: [SortField] @doc(description: "Available sort fields") } + +type StoreConfig @doc(description: "The type contains information about a store config") { + product_url_suffix : String @doc(description: "Product URL Suffix") + category_url_suffix : String @doc(description: "Category URL Suffix") + product_use_categories : Int @doc(description: "Use Categories Path for Product URLs") + save_rewrites_history : Int @doc(description: "Create Permanent Redirect for URLs if URL Key Changed") + title_separator : String @doc(description: "Page Title Separator") + category_canonical_tag : Int @doc(description: "Use Canonical Link Meta Tag For Categories") + product_canonical_tag : Int @doc(description: "Use Canonical Link Meta Tag For Products") + list_mode : String @doc(description: "List Mode") + grid_per_page_values : String @doc(description: "Products per Page on Grid Allowed Values") + list_per_page_values : String @doc(description: "Products per Page on List Allowed Values") + grid_per_page : Int @doc(description: "Products per Page on Grid Default Value") + list_per_page : Int @doc(description: "Products per Page on List Default Value") + flat_catalog_category : Int @doc(description: "Use Flat Catalog Category") + catalog_default_sort_by : String @doc(description: "Default Sort By") + parse_url_directives : Int @doc(description: "Parse URL directives") + remember_pagination : Int @doc(description: "Remember Pagination") +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/StoreConfigTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/StoreConfigTest.php new file mode 100644 index 0000000000000..813ed9faefa94 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/StoreConfigTest.php @@ -0,0 +1,55 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Store; + +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test the GraphQL endpoint's StoreConfigs query for Catalog Configs + */ +class StoreConfigTest extends GraphQlAbstract +{ + protected function setUp() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/167'); + } + + /** + * @magentoApiDataFixture Magento/Store/_files/store.php + */ + public function testGetStoreConfig() + { + $query + = <<<QUERY +{ + storeConfig{ + product_url_suffix, + category_url_suffix, + product_use_categories, + save_rewrites_history, + title_separator, + category_canonical_tag, + product_canonical_tag, + list_mode, + grid_per_page_values, + list_per_page_values, + grid_per_page, + list_per_page, + flat_catalog_category, + catalog_default_sort_by, + parse_url_directives, + remember_pagination + } +} +QUERY; + $response = $this->graphQlQuery($query); + $this->assertArrayHasKey('storeConfig', $response); + + //TODO: provide assertions after unmarking test as incomplete + } +} From 98b1d3ca49f07f85359848e7459189c423069591 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 1 May 2019 11:53:22 +0300 Subject: [PATCH 106/224] magento/graphql-ce#649: GetSpecifiedBillingAddressTest fix misspelling --- .../Quote/Customer/GetSpecifiedBillingAddressTest.php | 10 +++++----- .../Quote/Guest/GetSpecifiedBillingAddressTest.php | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php index 1ff5ddbde54ec..b6dde46871cbb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedBillingAddressTest.php @@ -44,7 +44,7 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ - public function testGeSpecifiedBillingAddress() + public function testGetSpecifiedBillingAddress() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); @@ -83,7 +83,7 @@ public function testGeSpecifiedBillingAddress() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ - public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() + public function testGetSpecifiedBillingAddressIfBillingAddressIsNotSet() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); @@ -121,7 +121,7 @@ public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() * @expectedException \Exception * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" */ - public function testGeSpecifiedBillingAddressOfNonExistentCart() + public function testGetSpecifiedBillingAddressOfNonExistentCart() { $maskedQuoteId = 'non_existent_masked_id'; $query = $this->getQuery($maskedQuoteId); @@ -137,7 +137,7 @@ public function testGeSpecifiedBillingAddressOfNonExistentCart() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ - public function testGeSpecifiedBillingAddressFromAnotherGuestCart() + public function testGetSpecifiedBillingAddressFromAnotherGuestCart() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); @@ -155,7 +155,7 @@ public function testGeSpecifiedBillingAddressFromAnotherGuestCart() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ - public function testGeSpecifiedBillingAddressFromAnotherCustomerCart() + public function testGetSpecifiedBillingAddressFromAnotherCustomerCart() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php index 48bff73226894..8ddf1641ede8a 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedBillingAddressTest.php @@ -36,7 +36,7 @@ protected function setUp() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_billing_address.php */ - public function testGeSpecifiedBillingAddress() + public function testGetSpecifiedBillingAddress() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); @@ -73,7 +73,7 @@ public function testGeSpecifiedBillingAddress() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php */ - public function testGeSpecifiedBillingAddressIfBillingAddressIsNotSet() + public function testGetSpecifiedBillingAddressIfBillingAddressIsNotSet() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); From ac76e2ef674fcb4bb9b1b1054cb9c7841762efee Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Wed, 1 May 2019 13:10:45 +0300 Subject: [PATCH 107/224] magento/graphql-ce#602: [Test Coverage] Get Specified shipping address --- .../GetSpecifiedShippingAddressTest.php | 219 ++++++++++++++++++ .../Guest/GetSpecifiedShippingAddressTest.php | 170 ++++++++++++++ 2 files changed, 389 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php new file mode 100644 index 0000000000000..766dd102b749c --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php @@ -0,0 +1,219 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for get specified shipping address + */ +class GetSpecifiedShippingAddressTest extends GraphQlAbstract +{ + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSpecifiedShippingAddress() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + + $expectedShippingAddressData = [ + 'firstname' => 'John', + 'lastname' => 'Smith', + 'company' => 'CompanyName', + 'street' => [ + 'Green str, 67' + ], + 'city' => 'CityM', + 'region' => [ + 'code' => 'AL', + 'label' => 'Alabama', + ], + 'postcode' => '75477', + 'country' => [ + 'code' => 'US', + 'label' => 'US', + ], + 'telephone' => '3468676', + '__typename' => 'ShippingCartAddress', + 'customer_notes' => null, + ]; + self::assertEquals($expectedShippingAddressData, current($response['cart']['shipping_addresses'])); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testGetSpecifiedShippingAddressIfShippingAddressIsNotSet() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + + $expectedShippingAddressData = [ + 'firstname' => null, + 'lastname' => null, + 'company' => null, + 'street' => [ + '' + ], + 'city' => null, + 'region' => [ + 'code' => null, + 'label' => null, + ], + 'postcode' => null, + 'country' => [ + 'code' => null, + 'label' => null, + ], + 'telephone' => null, + '__typename' => 'ShippingCartAddress', + 'customer_notes' => null, + ]; + self::assertEquals($expectedShippingAddressData, current($response['cart']['shipping_addresses'])); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" + */ + public function testGetSpecifiedShippingAddressOfNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSpecifiedShippingAddressFromAnotherGuestCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + $this->graphQlQuery($this->getQuery($maskedQuoteId), [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSpecifiedShippingAddressFromAnotherCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + $this->graphQlQuery( + $this->getQuery($maskedQuoteId), + [], + '', + $this->getHeaderMap('customer2@search.example.com') + ); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id: "$maskedQuoteId") { + shipping_addresses { + firstname + lastname + company + street + city + region + { + code + label + } + postcode + country + { + code + label + } + telephone + __typename + customer_notes + } + } +} +QUERY; + } + + /** + * @param string $username + * @param string $password + * @return array + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php new file mode 100644 index 0000000000000..3b96a873bdb81 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php @@ -0,0 +1,170 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for get specified shipping address + */ +class GetSpecifiedShippingAddressTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @inheritdoc + */ + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSpecifiedShippingAddress() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + + $expectedShippingAddressData = [ + 'firstname' => 'John', + 'lastname' => 'Smith', + 'company' => 'CompanyName', + 'street' => [ + 'Green str, 67' + ], + 'city' => 'CityM', + 'region' => [ + 'code' => 'AL', + 'label' => 'Alabama', + ], + 'postcode' => '75477', + 'country' => [ + 'code' => 'US', + 'label' => 'US', + ], + 'telephone' => '3468676', + '__typename' => 'ShippingCartAddress', + ]; + self::assertEquals($expectedShippingAddressData, current($response['cart']['shipping_addresses'])); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testGetSpecifiedShippingAddressIfShippingAddressIsNotSet() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $response = $this->graphQlQuery($query); + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + + $expectedShippingAddressData = [ + 'firstname' => null, + 'lastname' => null, + 'company' => null, + 'street' => [ + '' + ], + 'city' => null, + 'region' => [ + 'code' => null, + 'label' => null, + ], + 'postcode' => null, + 'country' => [ + 'code' => null, + 'label' => null, + ], + 'telephone' => null, + '__typename' => 'ShippingCartAddress', + ]; + self::assertEquals($expectedShippingAddressData, current($response['cart']['shipping_addresses'])); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id" + */ + public function testGetShippingAddressOfNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetShippingAddressFromAnotherCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + $this->graphQlQuery($query); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id: "$maskedQuoteId") { + shipping_addresses { + firstname + lastname + company + street + city + region + { + code + label + } + postcode + country + { + code + label + } + telephone + __typename + } + } +} +QUERY; + } +} From 8f36cf21b9fda33f031c9c42457c520b84548afe Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 1 May 2019 14:04:32 +0300 Subject: [PATCH 108/224] graphQl-535: fixed namespace --- .../testsuite/Magento/GraphQl/Catalog/StoreConfigTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/StoreConfigTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/StoreConfigTest.php index 813ed9faefa94..5932fd8b034e6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/StoreConfigTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/StoreConfigTest.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\GraphQl\Store; +namespace Magento\GraphQl\Catalog; use Magento\TestFramework\TestCase\GraphQlAbstract; From 020578721d825e1ed2b6c8ba804f857e98a13346 Mon Sep 17 00:00:00 2001 From: Abhinay Pratap Singh <32534204+abhinay111222@users.noreply.github.com> Date: Wed, 1 May 2019 16:39:20 +0530 Subject: [PATCH 109/224] Resolved typo error Resolved typo error --- lib/web/css/docs/source/_pages.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/css/docs/source/_pages.less b/lib/web/css/docs/source/_pages.less index 6b01fa7549e92..59eb121112d28 100644 --- a/lib/web/css/docs/source/_pages.less +++ b/lib/web/css/docs/source/_pages.less @@ -4,7 +4,7 @@ // */ // # Pagination HTML markup -// Pagination is used to display numbers of pages in case content exceeds page limits. The markup corresponds to accesibility demands. +// Pagination is used to display numbers of pages in case content exceeds page limits. The markup corresponds to accessibility demands. // // Required HTML markup: // ```html From 54063286858824c4f8b492d22672008864d87b81 Mon Sep 17 00:00:00 2001 From: Abhinay Pratap Singh <32534204+abhinay111222@users.noreply.github.com> Date: Wed, 1 May 2019 16:44:56 +0530 Subject: [PATCH 110/224] fixed typo error fixed typo error --- lib/web/css/docs/source/_popups.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/css/docs/source/_popups.less b/lib/web/css/docs/source/_popups.less index b192219b6438f..7251cde45bc3c 100644 --- a/lib/web/css/docs/source/_popups.less +++ b/lib/web/css/docs/source/_popups.less @@ -245,7 +245,7 @@ // <td>@popup-title-headings__level</td> // <td class="vars_value">h3</td> // <td class="vars_value">h1 | h2 | h3 | h4 | h5 | h6</td> -// <td>What heading style is applyed to the popup title</td> +// <td>What heading style is applied to the popup title</td> // </tr> // <tr> // <th colspan="5" class="vars_section">Popup close button</th> From 6bd7e484775716d475f9a86913af64112745bb34 Mon Sep 17 00:00:00 2001 From: Volodymyr Vygovskyi <v.vygovskyi@atwix.com> Date: Wed, 1 May 2019 16:01:53 +0300 Subject: [PATCH 111/224] Added Test coverage for "Get Selected payment method" --- .../Customer/GetSelectedPaymentMethodTest.php | 143 ++++++++++++++++++ .../Guest/GetSelectedPaymentMethodTest.php | 105 +++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php new file mode 100644 index 0000000000000..d876d74de661b --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php @@ -0,0 +1,143 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Customer; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for getting selected payment method from cart + */ +class GetSelectedPaymentMethodTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testGetSelectedPaymentMethod() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + + $this->assertArrayHasKey('cart', $response); + $this->assertArrayHasKey('selected_payment_method', $response['cart']); + $this->assertArrayHasKey('code', $response['cart']['selected_payment_method']); + $this->assertEquals('checkmo', $response['cart']['selected_payment_method']['code']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + */ + public function testGetSelectedPaymentMethodFromNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + 'Could not find a cart with ID "non_existent_masked_id"' + ); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testGetSelectedPaymentMethodFromGuestCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$maskedQuoteId\"" + ); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + */ + public function testGetSelectedPaymentMethodFromAnotherCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"{$maskedQuoteId}\"" + ); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer3@search.example.com')); + } + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id:"$maskedQuoteId") { + selected_payment_method { + code + } + } +} +QUERY; + } + + /** + * @param string $username + * @param string $password + * @return array + * @throws \Magento\Framework\Exception\AuthenticationException + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php new file mode 100644 index 0000000000000..ef04da88ea67a --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php @@ -0,0 +1,105 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\Quote\Guest; + +use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Test for getting selected payment method from cart + */ +class GetSelectedPaymentMethodTest extends GraphQlAbstract +{ + /** + * @var GetMaskedQuoteIdByReservedOrderId + */ + private $getMaskedQuoteIdByReservedOrderId; + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + * + */ + public function testGetSelectedPaymentMethod() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + + $this->assertArrayHasKey('cart', $response); + $this->assertArrayHasKey('selected_payment_method', $response['cart']); + $this->assertArrayHasKey('code', $response['cart']['selected_payment_method']); + $this->assertEquals('checkmo', $response['cart']['selected_payment_method']['code']); + } + + /** + * @expectedException \Exception + */ + public function testGetSelectedPaymentMethodFromNonExistentCart() + { + $maskedQuoteId = 'non_existent_masked_id'; + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + 'Could not find a cart with ID "non_existent_masked_id"' + ); + + $this->graphQlQuery($query); + } + + /** + * _security + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_checkmo_payment_method.php + */ + public function testGetSelectedPaymentMethodFromCustomerCart() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"{$maskedQuoteId}\"" + ); + + $this->graphQlQuery($query); + } + + /** + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<<QUERY +{ + cart(cart_id:"$maskedQuoteId") { + selected_payment_method { + code + } + } +} +QUERY; + } +} From a69e9e9cc7daddca58c4b0575a116fec3f0fed93 Mon Sep 17 00:00:00 2001 From: Justin Liotta <6843459+justin-at-bounteous@users.noreply.github.com> Date: Wed, 1 May 2019 09:49:07 -0400 Subject: [PATCH 112/224] Update credit-card-number-validator.js - Remove: erroneous leading alternation, preventing space characters from being replaced - Add: replace each contiguous string of space characters, for good measure --- .../credit-card-validation/credit-card-number-validator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator.js b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator.js index 785b636d5832f..b459b3598a857 100644 --- a/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator.js +++ b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator.js @@ -36,7 +36,7 @@ define([ return resultWrapper(null, false, false); } - value = value.replace(/|\s/g, ''); + value = value.replace(/\s+/g, ''); if (!/^\d*$/.test(value)) { return resultWrapper(null, false, false); From 48f416c2f7c11fb406dac0b0ef93b12a5efbf527 Mon Sep 17 00:00:00 2001 From: Volodymyr Vygovskyi <v.vygovskyi@atwix.com> Date: Wed, 1 May 2019 16:53:18 +0300 Subject: [PATCH 113/224] Refactoring, fixing code review notes --- ...minCMSPageMassActionDisableActionGroup.xml | 2 +- ...l => AdminOpenCMSPagesGridActionGroup.xml} | 3 ++- .../AdminSelectCMSPageFromGridActionGroup.xml | 16 +++++++++++++ ...> AdminSelectCMSPageInGridActionGroup.xml} | 2 +- ...CMSPageNotFoundOnStorefrontActionGroup.xml | 13 ++++++++++ ...l => StorefrontGoToCMSPageActionGroup.xml} | 7 +++--- .../Section/CmsPagesPageActionsSection.xml | 2 +- .../Mftf/Test/AdminCmsPageMassActionTest.xml | 24 ++++++++++++------- 8 files changed, 52 insertions(+), 17 deletions(-) rename app/code/Magento/Cms/Test/Mftf/ActionGroup/{AdminCMSPageNavigateToGridActionGroup.xml => AdminOpenCMSPagesGridActionGroup.xml} (79%) create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageFromGridActionGroup.xml rename app/code/Magento/Cms/Test/Mftf/ActionGroup/{AdminCMSPageSelectInGridActionGroup.xml => AdminSelectCMSPageInGridActionGroup.xml} (90%) create mode 100644 app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnStorefrontActionGroup.xml rename app/code/Magento/Cms/Test/Mftf/ActionGroup/{AssertCMSPageNotFoundOnFrontActionGroup.xml => StorefrontGoToCMSPageActionGroup.xml} (75%) diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionDisableActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionDisableActionGroup.xml index 031dab84d6c37..9678a919f9198 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionDisableActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionDisableActionGroup.xml @@ -7,7 +7,7 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminCMSPageMassActionDisable"> + <actionGroup name="AdminCMSPageMassActionDisableActionGroup"> <click selector="{{CmsPagesPageActionsSection.massActionsButton}}" stepKey="clickMassActionDropdown"/> <click selector="{{CmsPagesPageActionsSection.massActionsOption('Disable')}}" stepKey="clickDisableAction"/> <waitForPageLoad stepKey="waitForPageToReload"/> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageNavigateToGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpenCMSPagesGridActionGroup.xml similarity index 79% rename from app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageNavigateToGridActionGroup.xml rename to app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpenCMSPagesGridActionGroup.xml index ad7af07201dd5..fe5c6202c977d 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageNavigateToGridActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpenCMSPagesGridActionGroup.xml @@ -7,7 +7,8 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminCMSPageNavigateToGrid"> + <actionGroup name="AdminOpenCMSPagesGridActionGroup"> <amOnPage url="{{CmsPagesPage.url}}" stepKey="navigateToCMSPagesGrid"/> + <waitForPageLoad stepKey="waitForPageLoad"/> </actionGroup> </actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageFromGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageFromGridActionGroup.xml new file mode 100644 index 0000000000000..6a08b8fa89eef --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageFromGridActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminSelectCMSPageFromGridActionGroup"> + <arguments> + <argument name="identifier" defaultValue=""/> + </arguments> + <click selector="{{CmsPagesPageActionsSection.select(identifier)}}" stepKey="clickSelectCMSPage" /> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageSelectInGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml similarity index 90% rename from app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageSelectInGridActionGroup.xml rename to app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml index cfe24fdd5b7c7..a808e7707bfe1 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageSelectInGridActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml @@ -7,7 +7,7 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminCMSPageSelectInGrid"> + <actionGroup name="AdminSelectCMSPageInGridActionGroup"> <arguments> <argument name="identifier" type="string"/> </arguments> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnStorefrontActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnStorefrontActionGroup.xml new file mode 100644 index 0000000000000..c0e0a1b599482 --- /dev/null +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnStorefrontActionGroup.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AssertCMSPageNotFoundOnStorefrontActionGroup"> + <see userInput="Whoops, our bad..." stepKey="seePageErrorNotFound"/> + </actionGroup> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnFrontActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/StorefrontGoToCMSPageActionGroup.xml similarity index 75% rename from app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnFrontActionGroup.xml rename to app/code/Magento/Cms/Test/Mftf/ActionGroup/StorefrontGoToCMSPageActionGroup.xml index 77a8a8884cabf..ac27ac89bba14 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnFrontActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/StorefrontGoToCMSPageActionGroup.xml @@ -7,12 +7,11 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertCMSPageNotFoundOnFront"> + <actionGroup name="StorefrontGoToCMSPageActionGroup"> <arguments> <argument name="identifier" type="string"/> </arguments> - <amOnPage url="{{StorefrontHomePage.url}}/{{identifier}}" stepKey="amOnPageOnStorefront"/> + <amOnPage url="{{StorefrontHomePage.url}}/{{identifier}}" stepKey="amOnCmsPageOnStorefront"/> <waitForPageLoad stepKey="waitForPageLoadOnStorefront"/> - <see userInput="Whoops, our bad..." stepKey="seePageErrorNotFound"/> </actionGroup> -</actionGroups> +</actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml b/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml index 4d0ae671ca05e..d359ae7160afa 100644 --- a/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml +++ b/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml @@ -27,7 +27,7 @@ <element name="savePageSuccessMessage" type="text" selector=".message-success"/> <element name="delete" type="button" selector="//div[text()='{{var1}}']/parent::td//following-sibling::td[@class='data-grid-actions-cell']//a[text()='Delete']" parameterized="true"/> <element name="deleteConfirm" type="button" selector=".action-primary.action-accept" timeout="60"/> - <element name="pageRowCheckboxByIdentifier" type="block" selector="//td[count(../../..//th[./*[.='URL Key']]/preceding-sibling::th) + 1][./*[.='{{identifier}}']]/../td//input[@data-action='select-row']" parameterized="true" /> + <element name="pageRowCheckboxByIdentifier" type="block" selector="//div[@data-bind="scope: 'cms_page_listing.cms_page_listing'"]//td[count(../../..//th[./*[.='URL Key']]/preceding-sibling::th) + 1][./*[.='{{identifier}}']]/../td//input[@data-action='select-row']" parameterized="true" /> <element name="massActionsButton" type="button" selector="div.admin__data-grid-header-row.row div.action-select-wrap button.action-select"/> <element name="massActionsOption" type="button" selector="//div[contains(@class,'admin__data-grid-header-row') and contains(@class, 'row')]//div[contains(@class, 'action-select-wrap')]//ul/li/span[text() = '{{label}}']" parameterized="true"/> </section> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml index 04fb9d97a9175..1ef2ad551b4de 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml @@ -27,29 +27,35 @@ <actionGroup ref="logout" stepKey="logout"/> </after> <!--Go to Grid page--> - <actionGroup ref="AdminCMSPageNavigateToGrid" stepKey="navigateToCMSPageGrid"/> + <actionGroup ref="AdminOpenCMSPagesGridActionGroup" stepKey="navigateToCMSPageGrid"/> <!--Select pages in Grid--> - <actionGroup ref="AdminCMSPageSelectInGrid" stepKey="selectFirstCMSPage"> + <actionGroup ref="AdminSelectCMSPageInGridActionGroup" stepKey="selectFirstCMSPage"> <argument name="identifier" value="$$firstCMSPage.identifier$$"/> </actionGroup> - <actionGroup ref="AdminCMSPageSelectInGrid" stepKey="selectSecondCMSPage"> + <actionGroup ref="AdminSelectCMSPageInGridActionGroup" stepKey="selectSecondCMSPage"> <argument name="identifier" value="$$secondCMSPage.identifier$$"/> </actionGroup> <!-- Disable Pages--> - <actionGroup ref="AdminCMSPageMassActionDisable" stepKey="disablePages"/> + <actionGroup ref="AdminCMSPageMassActionDisableActionGroup" stepKey="disablePages"/> <!--Verify pages in Grid--> - <actionGroup ref="AssertCMSPageInGrid" stepKey="verifyFirstPageInGrid"> + <actionGroup ref="AdminOpenCMSPagesGridActionGroup" stepKey="openCMSPagesGridActionGroup"/> + <actionGroup ref="clearFiltersAdminDataGrid" stepKey="clearGridFilters"/> + <actionGroup ref="SortByIdDescendingActionGroup" stepKey="sortGridByIdDescending"/> + <actionGroup ref="AdminSelectCMSPageFromGridActionGroup" stepKey="verifyFirstPageInGrid"> <argument name="identifier" value="$$firstCMSPage.identifier$$"/> </actionGroup> - <actionGroup ref="AssertCMSPageInGrid" stepKey="verifySecondPageInGrid"> + <actionGroup ref="AdminSelectCMSPageFromGridActionGroup" stepKey="verifySecondPageInGrid"> <argument name="identifier" value="$$secondCMSPage.identifier$$"/> </actionGroup> - <!--Verify Pages are disabled on Frontend--> - <actionGroup ref="AssertCMSPageNotFoundOnFront" stepKey="checkFirstPageNotFoundOnFront"> + <!--Verify first page is disabled on Frontend--> + <actionGroup ref="StorefrontGoToCMSPageActionGroup" stepKey="goToFirstCMSPageOnStorefront"> <argument name="identifier" value="$$firstCMSPage.identifier$$"/> </actionGroup> - <actionGroup ref="AssertCMSPageNotFoundOnFront" stepKey="checkSecondPageNotFoundOnFront"> + <actionGroup ref="AssertCMSPageNotFoundOnStorefrontActionGroup" stepKey="seeNotFoundErrorForFirstPage"/> + <!--Verify second page is disabled on Frontend--> + <actionGroup ref="StorefrontGoToCMSPageActionGroup" stepKey="goToSecondCMSPageOnStorefront"> <argument name="identifier" value="$$secondCMSPage.identifier$$"/> </actionGroup> + <actionGroup ref="AssertCMSPageNotFoundOnStorefrontActionGroup" stepKey="seeNotFoundErrorForSecondPage"/> </test> </tests> \ No newline at end of file From f3f79fb74df556d39384e51c4193ccb0875b0a83 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Wed, 1 May 2019 19:36:22 +0530 Subject: [PATCH 114/224] Correct spelling --- .../Magento/Catalog/Model/ResourceModel/Product/Collection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php index 0cdf8b39f7d52..9a800f5796147 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php @@ -808,7 +808,7 @@ public function load($printQuery = false, $logQuery = false) } /** - * Processs adding product website names to result collection + * Process adding product website names to result collection * * @return $this */ From d9edfe27a638e115a4c66eb721c77b8aa0e86f78 Mon Sep 17 00:00:00 2001 From: Kevin Kozan <kkozan@magento.com> Date: Wed, 1 May 2019 12:57:31 -0500 Subject: [PATCH 115/224] MQE-1532: Bump MFTF version in Magento - Version bump and lock file update --- composer.json | 2 +- composer.lock | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index cff2d676038d7..2ba4d20c6533e 100644 --- a/composer.json +++ b/composer.json @@ -86,7 +86,7 @@ "friendsofphp/php-cs-fixer": "~2.13.0", "lusitanian/oauth": "~0.8.10", "magento/magento-coding-standard": "~1.0.0", - "magento/magento2-functional-testing-framework": "~2.3.14", + "magento/magento2-functional-testing-framework": "~2.4.0", "pdepend/pdepend": "2.5.2", "phpmd/phpmd": "@stable", "phpunit/phpunit": "~6.5.0", diff --git a/composer.lock b/composer.lock index 5d9f7fbdf695c..09ca8cd9f3f02 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "597fe6a47b695221292482fead498d83", + "content-hash": "6b0350be54f49186c1c9f55ac29bf1cb", "packages": [ { "name": "braintree/braintree_php", @@ -6699,16 +6699,16 @@ }, { "name": "magento/magento2-functional-testing-framework", - "version": "2.3.14", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/magento/magento2-functional-testing-framework.git", - "reference": "b4002b3fe53884895921b44cf519d42918e3c7c6" + "reference": "ef534dbcb3aeea68f9254dfd018165c546ad2edb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/b4002b3fe53884895921b44cf519d42918e3c7c6", - "reference": "b4002b3fe53884895921b44cf519d42918e3c7c6", + "url": "https://api.github.com/repos/magento/magento2-functional-testing-framework/zipball/ef534dbcb3aeea68f9254dfd018165c546ad2edb", + "reference": "ef534dbcb3aeea68f9254dfd018165c546ad2edb", "shasum": "" }, "require": { @@ -6721,12 +6721,12 @@ "fzaninotto/faker": "^1.6", "monolog/monolog": "^1.0", "mustache/mustache": "~2.5", - "php": "7.0.2|7.0.4|~7.0.6|~7.1.0|~7.2.0", + "php": "7.0.2||7.0.4||~7.0.6||~7.1.0||~7.2.0||~7.3.0", "symfony/process": "^2.8 || ^3.1 || ^4.0", "vlucas/phpdotenv": "^2.4" }, "require-dev": { - "brainmaestro/composer-git-hooks": "^2.3", + "brainmaestro/composer-git-hooks": "^2.3.1", "codacy/coverage": "^1.4", "codeception/aspect-mock": "^3.0", "doctrine/cache": "<1.7.0", @@ -6768,19 +6768,19 @@ "magento", "testing" ], - "time": "2019-02-19T16:03:22+00:00" + "time": "2019-04-29T20:56:26+00:00" }, { "name": "mikey179/vfsStream", "version": "v1.6.5", "source": { "type": "git", - "url": "https://github.com/mikey179/vfsStream.git", + "url": "https://github.com/bovigo/vfsStream.git", "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", + "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", "shasum": "" }, From 30b049d6be5475d651b0400c9f07b2a1a2961485 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 1 May 2019 13:15:09 -0500 Subject: [PATCH 116/224] GraphQL-602: [Test Coverage] Get Specified shipping address --- .../GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php | 2 +- .../GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php index 766dd102b749c..de3c384e65783 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSpecifiedShippingAddressTest.php @@ -137,7 +137,7 @@ public function testGetSpecifiedShippingAddressOfNonExistentCart() * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php */ - public function testGetSpecifiedShippingAddressFromAnotherGuestCart() + public function testGetSpecifiedShippingAddressFromGuestCart() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php index 3b96a873bdb81..f71915bab650f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSpecifiedShippingAddressTest.php @@ -117,13 +117,14 @@ public function testGetShippingAddressOfNonExistentCart() } /** + * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php */ - public function testGetShippingAddressFromAnotherCustomerCart() + public function testGetShippingAddressFromCustomerCart() { $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); $query = $this->getQuery($maskedQuoteId); From 64e76c4888f8baae719791ed2787b9f0948562b4 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 1 May 2019 13:29:31 -0500 Subject: [PATCH 117/224] GraphQL-646: Incorrect name of Selected Shipping Method --- .../Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php index c50ae0a70380e..7de689a6ad0f5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Ups/SetUpsShippingMethodsOnCartTest.php @@ -116,6 +116,7 @@ public function testSetUpsShippingMethod(string $methodCode, string $methodTitle self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** @@ -171,6 +172,7 @@ public function testSetUpsShippingMethodBasedOnCanadaAddress(string $methodCode, self::assertEquals(self::CARRIER_TITLE, $shippingAddress['selected_shipping_method']['carrier_title']); self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertEquals($methodTitle, $shippingAddress['selected_shipping_method']['method_title']); } /** From 0ccea38d9e8e923d1644e3df953e8b2c62f3946d Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Wed, 1 May 2019 14:24:34 -0500 Subject: [PATCH 118/224] MAGETWO-99451: Custom customer address attribute values are empty when address is changed in admin checkout --- .../templates/order/create/form/address.phtml | 12 +------ .../Api/ExtensibleDataObjectConverter.php | 33 ++++++++++++++----- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/address.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/address.phtml index d1a90783c68c7..46d0961353c65 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/address.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/address.phtml @@ -6,16 +6,6 @@ // @codingStandardsIgnoreFile -/** - * @var \Magento\Customer\Model\ResourceModel\Address\Collection $addressCollection - */ -$addressCollection = $block->getData('customerAddressCollection'); - -$addressArray = []; -if ($block->getCustomerId()) { - $addressArray = $addressCollection->setCustomerFilter([$block->getCustomerId()])->toArray(); -} - /** * @var \Magento\Sales\ViewModel\Customer\AddressFormatter $customerAddressFormatter */ @@ -32,7 +22,7 @@ if ($block->getIsShipping()): require(["Magento_Sales/order/create/form"], function(){ order.shippingAddressContainer = '<?= /* @escapeNotVerified */ $_fieldsContainerId ?>'; - order.setAddresses(<?= /* @escapeNotVerified */ $customerAddressFormatter->getAddressesJson($addressArray) ?>); + order.setAddresses(<?= /* @escapeVerfied */ $block->getAddressCollectionJson() ?>); }); </script> diff --git a/lib/internal/Magento/Framework/Api/ExtensibleDataObjectConverter.php b/lib/internal/Magento/Framework/Api/ExtensibleDataObjectConverter.php index 538f4e646d060..c3efcf6a0dc54 100644 --- a/lib/internal/Magento/Framework/Api/ExtensibleDataObjectConverter.php +++ b/lib/internal/Magento/Framework/Api/ExtensibleDataObjectConverter.php @@ -45,6 +45,28 @@ public function toNestedArray( } $dataObjectArray = $this->dataObjectProcessor->buildOutputDataArray($dataObject, $dataObjectType); //process custom attributes if present + $dataObjectArray = $this->processCustomAttributes($dataObjectArray, $skipAttributes); + + if (!empty($dataObjectArray[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY])) { + /** @var array $extensionAttributes */ + $extensionAttributes = $dataObjectArray[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]; + unset($dataObjectArray[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]); + foreach ($extensionAttributes as $attributeKey => $attributeValue) { + if (!in_array($attributeKey, $skipAttributes)) { + $dataObjectArray[$attributeKey] = $attributeValue; + } + } + } + return $dataObjectArray; + } + + /** + * @param array $dataObjectArray + * @param array $skipAttributes + * @return array + */ + private function processCustomAttributes(array $dataObjectArray, array $skipAttributes): array + { if (!empty($dataObjectArray[AbstractExtensibleObject::CUSTOM_ATTRIBUTES_KEY])) { /** @var AttributeValue[] $customAttributes */ $customAttributes = $dataObjectArray[AbstractExtensibleObject::CUSTOM_ATTRIBUTES_KEY]; @@ -56,14 +78,9 @@ public function toNestedArray( } } } - if (!empty($dataObjectArray[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY])) { - /** @var array $extensionAttributes */ - $extensionAttributes = $dataObjectArray[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]; - unset($dataObjectArray[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]); - foreach ($extensionAttributes as $attributeKey => $attributeValue) { - if (!in_array($attributeKey, $skipAttributes)) { - $dataObjectArray[$attributeKey] = $attributeValue; - } + foreach ($dataObjectArray as $key => $value) { + if (is_array($value)) { + $dataObjectArray[$key] = $this->processCustomAttributes($value, $skipAttributes); } } return $dataObjectArray; From 0959569c5b159b670bc9d46d48da8e52f6741a8b Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 1 May 2019 15:14:05 -0500 Subject: [PATCH 119/224] GraphQL-640: Input type declaration in GraphQL SDL cannot be empty --- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 800d0582ff6d4..e87a5f4fc1d49 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -130,12 +130,9 @@ input SetPaymentMethodOnCartInput { input PaymentMethodInput { code: String! @doc(description:"Payment method code") - additional_data: PaymentMethodAdditionalDataInput @doc(description:"Additional payment data") purchase_order_number: String @doc(description:"Purchase order number") } -input PaymentMethodAdditionalDataInput - input SetGuestEmailOnCartInput { cart_id: String! email: String! @@ -257,12 +254,9 @@ type AvailablePaymentMethod { type SelectedPaymentMethod { code: String! @doc(description: "The payment method code") title: String! @doc(description: "The payment method title.") - additional_data: SelectedPaymentMethodAdditionalData @doc(description: "Additional payment data") purchase_order_number: String @doc(description: "The purchase order number.") } -type SelectedPaymentMethodAdditionalData - type AppliedCoupon { code: String! } From a4452308ae99dfde1e9d415179116745e0639f77 Mon Sep 17 00:00:00 2001 From: Kevin Kozan <kkozan@magento.com> Date: Wed, 1 May 2019 15:22:06 -0500 Subject: [PATCH 120/224] MQE-1532: Bump MFTF version in Magento - Flaky test fix --- ...rtStorefrontShoppingCartSummaryWithShippingActionGroup.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml index 5eb3de3a1af82..dcb683a50125d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml @@ -13,8 +13,6 @@ </arguments> <waitForLoadingMaskToDisappear stepKey="waitForMaskToDisappear" after="assertSubtotal"/> <waitForElementVisible selector="{{CheckoutCartSummarySection.shipping}}" time="60" stepKey="waitForElementToBeVisible" after="waitForMaskToDisappear"/> - <!-- Shipping can take a long time to change in builds, can't rely on an explicit wait--> - <wait time="30" stepKey="waitForShippingDetailsToLoad" after="waitForElementToBeVisible"/> - <see userInput="{{shipping}}" selector="{{CheckoutCartSummarySection.shipping}}" stepKey="assertShipping" after="waitForShippingDetailsToLoad" /> + <waitForText userInput="{{shipping}}" selector="{{CheckoutCartSummarySection.shipping}}" time="60" stepKey="assertShipping" after="waitForElementToBeVisible"/> </actionGroup> </actionGroups> From 98bf900c748e922a632f824033e5b7e221c4eec7 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Wed, 1 May 2019 16:10:00 -0500 Subject: [PATCH 121/224] MAGETWO-99451: Custom customer address attribute values are empty when address is changed in admin checkout --- .../templates/order/create/form/address.phtml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/address.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/address.phtml index 46d0961353c65..ad2641577c4a7 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/address.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/address.phtml @@ -6,6 +6,16 @@ // @codingStandardsIgnoreFile +/** + * @var \Magento\Customer\Model\ResourceModel\Address\Collection $addressCollection + */ +$addressCollection = $block->getData('customerAddressCollection'); + +$addressArray = []; +if ($block->getCustomerId()) { + $addressArray = $addressCollection->setCustomerFilter([$block->getCustomerId()])->toArray(); +} + /** * @var \Magento\Sales\ViewModel\Customer\AddressFormatter $customerAddressFormatter */ From 3bba6f3cbd8e5b53bc5b0a032deaba1da88352a1 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Wed, 1 May 2019 16:12:52 -0500 Subject: [PATCH 122/224] MAGETWO-99451: Custom customer address attribute values are empty when address is changed in admin checkout --- .../Magento/Framework/Api/ExtensibleDataObjectConverter.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/internal/Magento/Framework/Api/ExtensibleDataObjectConverter.php b/lib/internal/Magento/Framework/Api/ExtensibleDataObjectConverter.php index c3efcf6a0dc54..e51788ad9ecf5 100644 --- a/lib/internal/Magento/Framework/Api/ExtensibleDataObjectConverter.php +++ b/lib/internal/Magento/Framework/Api/ExtensibleDataObjectConverter.php @@ -61,6 +61,8 @@ public function toNestedArray( } /** + * Recursive process array to process customer attributes + * * @param array $dataObjectArray * @param array $skipAttributes * @return array From 0e6779d61c80fe17037ea70d2f5a8a6bc0fa677d Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Wed, 1 May 2019 16:16:05 -0500 Subject: [PATCH 123/224] MC-4764: Convert MoveProductsInComparedOnOrderPageTest to MFTF --- ...ustomerActivitiesComparisonListSection.xml | 17 ++ .../AdminCustomerCreateNewOrderSection.xml | 15 ++ .../AdminCustomerMainActionsSection.xml | 1 + .../AddConfigureToProductActionGroup.xml | 21 +++ ...rableProductsInComparedOnOrderPageTest.xml | 163 ++++++++++++++++++ ...impleProductsInComparedOnOrderPageTest.xml | 96 +++++++++++ .../MoveProductsInComparedOnOrderPageTest.xml | 4 +- 7 files changed, 315 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesComparisonListSection.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AddConfigureToProductActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/MoveCongigurableProductsInComparedOnOrderPageTest.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/MoveSimpleProductsInComparedOnOrderPageTest.xml diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesComparisonListSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesComparisonListSection.xml new file mode 100644 index 0000000000000..f54dfdc2b236f --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesComparisonListSection.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminCustomerActivitiesComparisonListSection"> + <element name="addProductToOrder" type="text" selector="//div[@id='order-sidebar_compared']//tr[td[.='{{productName}}']]//input[contains(@name,'add')]" parameterized="true" timeout="30"/> + <element name="addToOrderConfigure" type="button" selector="//div[@id='order-sidebar_compared']//tr[td[contains(.,'{{productName}}')]]//a[contains(@class, 'icon-configure')]" parameterized="true" timeout="30"/> + <element name="addAttribute" type="select" selector="[id*='attribute']" timeout="30"/> + <element name="okButton" type="button" selector="//button[contains(concat(' ',normalize-space(@class),' '),' action-primary ')]" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml new file mode 100644 index 0000000000000..5e6e42188d8e5 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminCustomerCreateNewOrderSection"> + <element name="updateChangesBtn" type="button" selector=".order-sidebar .actions .action-default.scalable" timeout="30"/> + <element name="gridCell" type="text" selector="//div[@class='admin__table-wrapper']//tbody['{{row}}']//td[count(//tr[@class='headings']//th[contains(., '{{column}}')]/preceding-sibling::th) +1 ]" parameterized="true" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerMainActionsSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerMainActionsSection.xml index 304068d89b729..18bc26bfd4987 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerMainActionsSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerMainActionsSection.xml @@ -13,5 +13,6 @@ <element name="saveAndContinue" type="button" selector="#save_and_continue" timeout="30"/> <element name="resetPassword" type="button" selector="#resetPassword" timeout="30"/> <element name="manageShoppingCart" type="button" selector="#manage_quote" timeout="30"/> + <element name="createOrderBtn" type="button" selector="#order" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AddConfigureToProductActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AddConfigureToProductActionGroup.xml new file mode 100644 index 0000000000000..79aaa46b7bb9d --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AddConfigureToProductActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AddConfigureToProductActionGroup"> + <arguments> + <argument name="productName" type="string"/> + <argument name="option" type="string"/> + </arguments> + <click selector="{{AdminCustomerActivitiesComparisonListSection.addToOrderConfigure(productName)}}" stepKey="configureFirstProduct"/> + <selectOption selector="{{AdminCustomerActivitiesComparisonListSection.addAttribute}}" userInput="{{option}}" stepKey="selectOption"/> + <click selector="{{AdminCustomerActivitiesComparisonListSection.okButton}}" stepKey="clickOkBtn"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveCongigurableProductsInComparedOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveCongigurableProductsInComparedOnOrderPageTest.xml new file mode 100644 index 0000000000000..11e40d4364de2 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveCongigurableProductsInComparedOnOrderPageTest.xml @@ -0,0 +1,163 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="MoveConfigurableProductsInComparedOnOrderPageTest"> + <annotations> + <features value="Sales"/> + <stories value="Add Products to Order from Products in Comparison List Section"/> + <title value="Move configurable products in compared on order page test"/> + <description value="Move configurable products in compared on order page test"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-16104"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create customer --> + <createData entity="Simple_US_Customer_CA" stepKey="createCustomer"/> + + <!-- Create category --> + <createData entity="_defaultCategory" stepKey="createCategory"/> + + <!-- Create first configurable product --> + <createData entity="ApiConfigurableProduct" stepKey="createFirstConfigProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="productAttributeWithTwoOptions" stepKey="createFirstConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createFirstConfigProductAttributeOption"> + <requiredEntity createDataKey="createFirstConfigProductAttribute"/> + </createData> + <createData entity="AddToDefaultSet" stepKey="createFirstConfigAddToAttributeSet"> + <requiredEntity createDataKey="createFirstConfigProductAttribute"/> + </createData> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getFirstConfigAttributeOption"> + <requiredEntity createDataKey="createFirstConfigProductAttribute"/> + </getData> + <createData entity="ApiSimpleOne" stepKey="createFirstConfigChildProduct"> + <requiredEntity createDataKey="createFirstConfigProductAttribute"/> + <requiredEntity createDataKey="getFirstConfigAttributeOption"/> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ConfigurableProductTwoOptions" stepKey="createFirstConfigProductOption"> + <requiredEntity createDataKey="createFirstConfigProduct"/> + <requiredEntity createDataKey="createFirstConfigProductAttribute"/> + <requiredEntity createDataKey="getFirstConfigAttributeOption"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createFirstConfigProductAddChild"> + <requiredEntity createDataKey="createFirstConfigProduct"/> + <requiredEntity createDataKey="createFirstConfigChildProduct"/> + </createData> + + <!-- Create second configurable product --> + <createData entity="ApiConfigurableProduct" stepKey="createSecondConfigProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="productAttributeWithTwoOptions" stepKey="createSecondConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createSecondConfigProductAttributeOption"> + <requiredEntity createDataKey="createSecondConfigProductAttribute"/> + </createData> + <createData entity="AddToDefaultSet" stepKey="createSecondConfigAddToAttributeSet"> + <requiredEntity createDataKey="createSecondConfigProductAttribute"/> + </createData> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getSecondConfigAttributeOption"> + <requiredEntity createDataKey="createSecondConfigProductAttribute"/> + </getData> + <createData entity="ApiSimpleOne" stepKey="createSecondConfigChildProduct"> + <requiredEntity createDataKey="createSecondConfigProductAttribute"/> + <requiredEntity createDataKey="getSecondConfigAttributeOption"/> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ConfigurableProductTwoOptions" stepKey="createSecondConfigProductOption"> + <requiredEntity createDataKey="createSecondConfigProduct"/> + <requiredEntity createDataKey="createSecondConfigProductAttribute"/> + <requiredEntity createDataKey="getSecondConfigAttributeOption"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createSecondConfigProductAddChild"> + <requiredEntity createDataKey="createSecondConfigProduct"/> + <requiredEntity createDataKey="createSecondConfigChildProduct"/> + </createData> + </before> + <after> + <!-- Admin logout --> + <actionGroup ref="logout" stepKey="logout"/> + + <!-- Logout customer --> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> + + <!-- Delete configurable products data --> + <deleteData createDataKey="createFirstConfigChildProduct" stepKey="deleteFirstConfigChildProduct"/> + <deleteData createDataKey="createFirstConfigProduct" stepKey="deleteFirstConfigProduct"/> + <deleteData createDataKey="createFirstConfigProductAttribute" stepKey="deleteFirstConfigProductAttribute"/> + <deleteData createDataKey="createSecondConfigChildProduct" stepKey="deleteSecondConfigChildProduct"/> + <deleteData createDataKey="createSecondConfigProduct" stepKey="deleteSecondConfigProduct"/> + <deleteData createDataKey="createSecondConfigProductAttribute" stepKey="deleteSecondConfigProductAttribute"/> + + <!-- Delete category --> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + </after> + + <!-- Login as customer --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCustomer"> + <argument name="Customer" value="$$createCustomer$$" /> + </actionGroup> + + <!-- Add first product to compare list --> + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openFirstProductPage"> + <argument name="productUrl" value="$$createFirstConfigProduct.custom_attributes[url_key]$$"/> + </actionGroup> + <scrollTo selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="scrollToCompareProductButton"/> + <actionGroup ref="StorefrontAddProductToCompareActionGroup" stepKey="addFirstProductToCompare"> + <argument name="productVar" value="$$createFirstConfigProduct$$"/> + </actionGroup> + + <!-- Add second product to compare list --> + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openSecondProductPage"> + <argument name="productUrl" value="$$createSecondConfigProduct.custom_attributes[url_key]$$"/> + </actionGroup> + <scrollTo selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="scrollToCompareProductBtn"/> + <actionGroup ref="StorefrontAddProductToCompareActionGroup" stepKey="addSecondProductToCompare"> + <argument name="productVar" value="$$createSecondConfigProduct$$"/> + </actionGroup> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Open Customers -> All Customers --> + <amOnPage url="{{AdminCustomerPage.url}}" stepKey="openCustomersGridPage"/> + <waitForPageLoad stepKey="waitForCustomerPageLoad"/> + <actionGroup ref="OpenEditCustomerFromAdminActionGroup" stepKey="openEditCustomerPage"> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Click 'Create Order' --> + <click selector="{{AdminCustomerMainActionsSection.createOrderBtn}}" stepKey="clickCreateOrder"/> + + <!-- Add configure to first product --> + <actionGroup ref="AddConfigureToProductActionGroup" stepKey="addConfigureToFirstProduct"> + <argument name="productName" value="$$createFirstConfigProduct.name$$"/> + <argument name="option" value="$$getFirstConfigAttributeOption.value$$"/> + </actionGroup> + + <!-- Add configure to second product --> + <actionGroup ref="AddConfigureToProductActionGroup" stepKey="addConfigureToSecondProduct"> + <argument name="productName" value="$$createSecondConfigProduct.name$$"/> + <argument name="option" value="$$getSecondConfigAttributeOption.value$$"/> + </actionGroup> + + <!-- Click 'Update Changes' --> + <click selector="{{AdminCustomerCreateNewOrderSection.updateChangesBtn}}" stepKey="clickUpdateChangesBtn"/> + + <!-- Assert products in items ordered grid --> + <see selector="{{AdminCustomerCreateNewOrderSection.gridCell('1', 'Product')}}" userInput="$$createFirstConfigProduct.name$$" stepKey="seeFirstProductName"/> + <see selector="{{AdminCustomerCreateNewOrderSection.gridCell('1', 'Price')}}" userInput="$123.00" stepKey="seeFirstProductPrice"/> + <see selector="{{AdminCustomerCreateNewOrderSection.gridCell('2', 'Product')}}" userInput="$$createSecondConfigProduct.name$$" stepKey="seeSecondProductName"/> + <see selector="{{AdminCustomerCreateNewOrderSection.gridCell('2', 'Price')}}" userInput="$123.00" stepKey="seeSecondProductPrice"/> + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveSimpleProductsInComparedOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveSimpleProductsInComparedOnOrderPageTest.xml new file mode 100644 index 0000000000000..3c01878b59e59 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveSimpleProductsInComparedOnOrderPageTest.xml @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="MoveSimpleProductsInComparedOnOrderPageTest"> + <annotations> + <features value="Sales"/> + <stories value="Add Products to Order from Products in Comparison List Section"/> + <title value="Move simple products in compared on order page test"/> + <description value="Move simple products in compared on order page test"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-16103"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Create customer --> + <createData entity="Simple_US_Customer_CA" stepKey="createCustomer"/> + + <!-- Create simple products --> + <createData entity="SimpleProduct2" stepKey="createFirstSimpleProduct"> + <field key="price">560</field> + </createData> + <createData entity="SimpleProduct2" stepKey="createSecondSimpleProduct"> + <field key="price">560</field> + </createData> + </before> + <after> + <!-- Admin logout --> + <actionGroup ref="logout" stepKey="logout"/> + + <!-- Logout customer --> + <actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="logoutCustomer"/> + + <!-- Delete created entities --> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="createFirstSimpleProduct" stepKey="deleteFirstSimpleProduct"/> + <deleteData createDataKey="createSecondSimpleProduct" stepKey="deleteSecondSimpleProduct"/> + </after> + + <!-- Login as customer --> + <actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCustomer"> + <argument name="Customer" value="$$createCustomer$$" /> + </actionGroup> + + <!-- Add first product to compare list --> + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openFirstProductPage"> + <argument name="productUrl" value="$$createFirstSimpleProduct.custom_attributes[url_key]$$"/> + </actionGroup> + <scrollTo selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="scrollToCompareProductButton"/> + <actionGroup ref="StorefrontAddProductToCompareActionGroup" stepKey="addFirstProductToCompare"> + <argument name="productVar" value="$$createFirstSimpleProduct$$"/> + </actionGroup> + + <!-- Add second product to compare list --> + <actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openSecondProductPage"> + <argument name="productUrl" value="$$createSecondSimpleProduct.custom_attributes[url_key]$$"/> + </actionGroup> + <scrollTo selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="scrollToCompareButton"/> + <actionGroup ref="StorefrontAddProductToCompareActionGroup" stepKey="addSecondProductToCompare"> + <argument name="productVar" value="$$createSecondSimpleProduct$$"/> + </actionGroup> + + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Open Customers -> All Customers --> + <amOnPage url="{{AdminCustomerPage.url}}" stepKey="openCustomersGridPage"/> + <waitForPageLoad stepKey="waitForCustomerPageLoad"/> + <actionGroup ref="OpenEditCustomerFromAdminActionGroup" stepKey="openEditCustomerPage"> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Click 'Create Order' --> + <click selector="{{AdminCustomerMainActionsSection.createOrderBtn}}" stepKey="clickCreateOrder"/> + + <!-- Select products in comparison list section --> + <click selector="{{AdminCustomerActivitiesComparisonListSection.addProductToOrder($$createFirstSimpleProduct.name$$)}}" stepKey="addFirstProductToOrder"/> + <click selector="{{AdminCustomerActivitiesComparisonListSection.addProductToOrder($$createSecondSimpleProduct.name$$)}}" stepKey="addSecondProductToOrder"/> + + <!-- Click 'Update Changes' --> + <click selector="{{AdminCustomerCreateNewOrderSection.updateChangesBtn}}" stepKey="clickUpdateChangesBtn"/> + + <!-- Assert products in items ordered grid --> + <see selector="{{AdminCustomerCreateNewOrderSection.gridCell('1', 'Product')}}" userInput="$$createFirstSimpleProduct.name$$" stepKey="seeFirstProductName"/> + <see selector="{{AdminCustomerCreateNewOrderSection.gridCell('1', 'Price')}}" userInput="$$createFirstSimpleProduct.price$$" stepKey="seeFirstProductPrice"/> + <see selector="{{AdminCustomerCreateNewOrderSection.gridCell('2', 'Product')}}" userInput="$$createSecondSimpleProduct.name$$" stepKey="seeSecondProductName"/> + <see selector="{{AdminCustomerCreateNewOrderSection.gridCell('2', 'Price')}}" userInput="$$createSecondSimpleProduct.price$$" stepKey="seeSecondProductPrice"/> + </test> +</tests> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveProductsInComparedOnOrderPageTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveProductsInComparedOnOrderPageTest.xml index 3badce50c6f63..cfeb5719ac667 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveProductsInComparedOnOrderPageTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveProductsInComparedOnOrderPageTest.xml @@ -8,13 +8,13 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Sales\Test\TestCase\MoveProductsInComparedOnOrderPageTest" summary="Add Products to Order from Products in Comparison List Section" ticketId="MAGETWO-28050"> <variation name="MoveProductsInComparedOnOrderPageTestVariation1"> - <data name="tag" xsi:type="string">to_maintain:yes</data> + <data name="tag" xsi:type="string">to_maintain:yes, mftf_migrated:yes</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="products/1" xsi:type="string">catalogProductSimple::default</data> <constraint name="Magento\Sales\Test\Constraint\AssertProductInItemsOrderedGrid" /> </variation> <variation name="MoveProductsInComparedOnOrderPageTestVariation2"> - <data name="tag" xsi:type="string">to_maintain:yes</data> + <data name="tag" xsi:type="string">to_maintain:yes, mftf_migrated:yes</data> <data name="products/0" xsi:type="string">configurableProduct::configurable_with_qty_1</data> <data name="products/1" xsi:type="string">configurableProduct::configurable_with_qty_1</data> <constraint name="Magento\Sales\Test\Constraint\AssertProductInItemsOrderedGrid" /> From a2b7a08face5ba8f1940d3ad945e13bd0d000f0c Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy <dpoperechnyy@magento.com> Date: Wed, 1 May 2019 16:46:16 -0500 Subject: [PATCH 124/224] MC-16046: Leverage the font-display CSS feature to ensure text is user-visible while webfonts are loading - Remove font display swap from icons; --- app/design/frontend/Magento/blank/web/css/source/_icons.less | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/design/frontend/Magento/blank/web/css/source/_icons.less b/app/design/frontend/Magento/blank/web/css/source/_icons.less index 52ae8a0e8c707..7d1ceaca73c72 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_icons.less +++ b/app/design/frontend/Magento/blank/web/css/source/_icons.less @@ -8,7 +8,6 @@ @family-name: @icons__font-name, @font-path: @icons__font-path, @font-weight: normal, - @font-style: normal, - @font-display: swap + @font-style: normal ); } From 9dd61cfd8b25cafbe012eedf8c8abec7208ee755 Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy <dpoperechnyy@magento.com> Date: Wed, 1 May 2019 17:49:10 -0500 Subject: [PATCH 125/224] MC-16046: Leverage the font-display CSS feature to ensure text is user-visible while webfonts are loading - Add font display swap from icons; --- app/design/frontend/Magento/blank/web/css/source/_icons.less | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/design/frontend/Magento/blank/web/css/source/_icons.less b/app/design/frontend/Magento/blank/web/css/source/_icons.less index 7d1ceaca73c72..52ae8a0e8c707 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_icons.less +++ b/app/design/frontend/Magento/blank/web/css/source/_icons.less @@ -8,6 +8,7 @@ @family-name: @icons__font-name, @font-path: @icons__font-path, @font-weight: normal, - @font-style: normal + @font-style: normal, + @font-display: swap ); } From 9359cca6c7ced8511117e4e88bcafb6c942c5644 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 1 May 2019 19:56:25 -0500 Subject: [PATCH 126/224] GraphQL-641: Schema Inconsistency of "cartItems" declaration --- setup/performance-toolkit/benchmark.jmx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/setup/performance-toolkit/benchmark.jmx b/setup/performance-toolkit/benchmark.jmx index 0609be4d7d193..a8a7e419373b8 100644 --- a/setup/performance-toolkit/benchmark.jmx +++ b/setup/performance-toolkit/benchmark.jmx @@ -41347,7 +41347,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41567,7 +41567,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -41739,7 +41739,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42045,7 +42045,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42303,7 +42303,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42609,7 +42609,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -42867,7 +42867,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -43094,7 +43094,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -43959,7 +43959,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation {\n addConfigurableProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n variant_sku: \"${product_option}\"\n data: {\n quantity: 2\n sku: \"${product_option}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n id\n quantity\n product {\n name\n sku\n }\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n }\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -44019,7 +44019,7 @@ vars.put("product_sku", product.get("sku")); <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cartItems: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> + <stringProp name="Argument.value">{"query":"mutation { \n addSimpleProductsToCart(\n input: {\n cart_id: \"${quote_id}\"\n cart_items: [\n {\n data: {\n quantity: 2\n sku: \"${product_sku}\"\n }\n }\n ]\n }\n ) {\n cart {\n items {\n quantity\n product {\n sku\n }\n }\n }\n }\n}","variables":null,"operationName":null}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> From b96c2d8a44a54fce04c2b20c52f8477965a828a2 Mon Sep 17 00:00:00 2001 From: Ravi Chandra <ravi.chandra@krishtechnolabs.com> Date: Thu, 2 May 2019 09:51:08 +0530 Subject: [PATCH 127/224] Correct spelling --- .../Ui/DataProvider/Product/ProductRenderCollectorComposite.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductRenderCollectorComposite.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductRenderCollectorComposite.php index 359b1a1a948f8..a4b3f231cfb9c 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductRenderCollectorComposite.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductRenderCollectorComposite.php @@ -9,7 +9,7 @@ use Magento\Catalog\Api\Data\ProductRenderInterface; /** - * Composite, which holds collectors, that collect enought information for + * Composite, which holds collectors, that collect enough information for * product render */ class ProductRenderCollectorComposite implements ProductRenderCollectorInterface From 1abadb5ddf82505c2048dac9312a5d58f21e5992 Mon Sep 17 00:00:00 2001 From: Mark van der Sanden <mark@ecomni.nl> Date: Thu, 2 May 2019 11:43:17 +0200 Subject: [PATCH 128/224] Fix undefined methods 'addClass' and 'removeClass' on a PrototypeJS Element The code was originally copied from the Swatches module, which already uses jQuery. In this file however, the 'panel' variable is not a jQuery object but a DOM Element. --- .../adminhtml/templates/catalog/product/attribute/js.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml index 195ac92422715..ddcec99f2108c 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml @@ -45,11 +45,11 @@ function checkOptionsPanelVisibility(){ if($('frontend_input') && ($('frontend_input').value=='select' || $('frontend_input').value=='multiselect')){ panel.show(); - panel.addClass(activePanelClass); + jQuery(panel).addClass(activePanelClass); } else { panel.hide(); - panel.removeClass(activePanelClass); + jQuery(panel).removeClass(activePanelClass); } } } From 183e0620a53083aca08d2fbdb373f0041847278e Mon Sep 17 00:00:00 2001 From: Afreen Sheikh <titania.afreen@gmail.com> Date: Thu, 2 May 2019 18:07:14 +0530 Subject: [PATCH 129/224] fixed typo issue fixed typo issue --- lib/web/css/docs/source/_responsive.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/css/docs/source/_responsive.less b/lib/web/css/docs/source/_responsive.less index 46c19bc23a66c..8e7397d6ad6f3 100644 --- a/lib/web/css/docs/source/_responsive.less +++ b/lib/web/css/docs/source/_responsive.less @@ -81,7 +81,7 @@ // // ## Gathering // -// Everything that you include in collector mixins above will go in place where they declarated. +// Everything that you include in collector mixins above will go in place where they declared. // As example all // ```css // .media-width(@extremum, @break) { From 4ebb66f29b30727027b7c99d1216709f4ed92021 Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Thu, 2 May 2019 08:31:12 -0500 Subject: [PATCH 130/224] MQE-4431: Convert DeleteCatalogPriceRuleEntityTest to MFTF - Adding the correct argument type to the Action Group. --- .../Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml index 9f1467ccc3a91..d744065fabc10 100644 --- a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/CatalogPriceRuleActionGroup.xml @@ -56,8 +56,8 @@ <actionGroup name="CreateCatalogPriceRuleViaTheUi"> <arguments> <argument name="catalogRule" defaultValue="_defaultCatalogRule"/> - <argument name="customerGroup" defaultValue="General"/> - <argument name="disregardRules" defaultValue="Yes"/> + <argument name="customerGroup" defaultValue="General" type="string"/> + <argument name="disregardRules" defaultValue="Yes" type="string"/> </arguments> <fillField selector="{{AdminNewCatalogPriceRule.ruleName}}" userInput="{{catalogRule.name}}" stepKey="fillName1"/> From 9d8eaa487d1f30bea5be94ed9311184d2c2a1686 Mon Sep 17 00:00:00 2001 From: Dmytro Poperechnyy <dpoperechnyy@magento.com> Date: Thu, 2 May 2019 09:12:25 -0500 Subject: [PATCH 131/224] MC-16046: Leverage the font-display CSS feature to ensure text is user-visible while webfonts are loading - Remove font display swap from icons; --- app/design/frontend/Magento/blank/web/css/source/_icons.less | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/design/frontend/Magento/blank/web/css/source/_icons.less b/app/design/frontend/Magento/blank/web/css/source/_icons.less index 52ae8a0e8c707..7d1ceaca73c72 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_icons.less +++ b/app/design/frontend/Magento/blank/web/css/source/_icons.less @@ -8,7 +8,6 @@ @family-name: @icons__font-name, @font-path: @icons__font-path, @font-weight: normal, - @font-style: normal, - @font-display: swap + @font-style: normal ); } From a83eade22bc3a376be6b5a4b586e3a8318abe053 Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@adobe.com> Date: Thu, 2 May 2019 09:51:35 -0500 Subject: [PATCH 132/224] MQE-1536: Magento\Install\Test\TestCase\InstallTest is failing - reverting MAGETWO-99210 --- .../Mtf/Util/Protocol/CurlTransport/BackendDecorator.php | 1 + dev/tests/functional/utils/authenticate.php | 5 +++++ dev/tests/functional/utils/command.php | 5 +++++ dev/tests/functional/utils/deleteMagentoGeneratedCode.php | 4 ++++ dev/tests/functional/utils/export.php | 7 ++++++- dev/tests/functional/utils/locales.php | 7 +++++++ dev/tests/functional/utils/log.php | 5 +++++ dev/tests/functional/utils/pathChecker.php | 5 +++++ dev/tests/functional/utils/website.php | 5 +++++ 9 files changed, 43 insertions(+), 1 deletion(-) diff --git a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php index 5999b52141f05..a9a082e2c0027 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php +++ b/dev/tests/functional/lib/Magento/Mtf/Util/Protocol/CurlTransport/BackendDecorator.php @@ -109,6 +109,7 @@ protected function authorize() $isAuthorized = true; $_ENV['app_backend_url'] = $url; break; + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (\Exception $e) { continue; } diff --git a/dev/tests/functional/utils/authenticate.php b/dev/tests/functional/utils/authenticate.php index 15851f6e8000a..958b692cbd385 100644 --- a/dev/tests/functional/utils/authenticate.php +++ b/dev/tests/functional/utils/authenticate.php @@ -9,12 +9,17 @@ * * @param string $token * @return bool + * + * phpcs:disable Squiz.Functions.GlobalFunction */ function authenticate($token) { + // phpcs:ignore Magento2.Security.IncludeFile require_once __DIR__ . '/../../../../app/bootstrap.php'; + // phpcs:ignore Magento2.Security.Superglobal $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); + // phpcs:ignore Magento2.Security.Superglobal $magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER); $tokenModel = $magentoObjectManager->get(\Magento\Integration\Model\Oauth\Token::class); diff --git a/dev/tests/functional/utils/command.php b/dev/tests/functional/utils/command.php index a3f6d1e19b4e9..9405f4ff7c4ca 100644 --- a/dev/tests/functional/utils/command.php +++ b/dev/tests/functional/utils/command.php @@ -13,20 +13,25 @@ // phpcs:ignore Magento2.Security.Superglobal if (!empty($_POST['token']) && !empty($_POST['command'])) { + // phpcs:ignore Magento2.Security.Superglobal if (authenticate(urldecode($_POST['token']))) { + // phpcs:ignore Magento2.Security.Superglobal $command = urldecode($_POST['command']); // phpcs:ignore Magento2.Security.Superglobal $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); // phpcs:ignore Magento2.Security.Superglobal $magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER); $cli = $magentoObjectManager->create(\Magento\Framework\Console\Cli::class); + // phpcs:ignore Magento2.Functions.DiscouragedFunction $input = new StringInput(escapeshellcmd($command)); $input->setInteractive(false); $output = new NullOutput(); $cli->doRun($input, $output); } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "Command not unauthorized."; } } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "'token' or 'command' parameter is not set."; } diff --git a/dev/tests/functional/utils/deleteMagentoGeneratedCode.php b/dev/tests/functional/utils/deleteMagentoGeneratedCode.php index dcdedcbeeb04a..bd4ed828202e1 100644 --- a/dev/tests/functional/utils/deleteMagentoGeneratedCode.php +++ b/dev/tests/functional/utils/deleteMagentoGeneratedCode.php @@ -6,13 +6,17 @@ // phpcs:ignore Magento2.Security.IncludeFile include __DIR__ . '/authenticate.php'; +// phpcs:ignore Magento2.Security.Superglobal if (!empty($_POST['token']) && !empty($_POST['path'])) { + // phpcs:ignore Magento2.Security.Superglobal if (authenticate(urldecode($_POST['token']))) { // phpcs:ignore Magento2.Security.InsecureFunction exec('rm -rf ../../../../generated/*'); } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "Command not unauthorized."; } } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "'token' parameter is not set."; } diff --git a/dev/tests/functional/utils/export.php b/dev/tests/functional/utils/export.php index 5cdc74c880a76..df97c8db48406 100644 --- a/dev/tests/functional/utils/export.php +++ b/dev/tests/functional/utils/export.php @@ -6,9 +6,12 @@ // phpcs:ignore Magento2.Security.IncludeFile include __DIR__ . '/authenticate.php'; +// phpcs:ignore Magento2.Security.Superglobal if (!empty($_POST['token']) && !empty($_POST['template'])) { + // phpcs:ignore Magento2.Security.Superglobal if (authenticate(urldecode($_POST['token']))) { - $varDir = '../../../../var/'; + $varDir = '../../../../var/export/'; + // phpcs:ignore Magento2.Security.Superglobal $template = urldecode($_POST['template']); // phpcs:ignore Magento2.Functions.DiscouragedFunction $fileList = scandir($varDir, SCANDIR_SORT_NONE); @@ -30,8 +33,10 @@ // phpcs:ignore Magento2.Security.LanguageConstruct, Magento2.Security.InsecureFunction echo serialize($files); } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "Command not unauthorized."; } } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "'token' or 'template' parameter is not set."; } diff --git a/dev/tests/functional/utils/locales.php b/dev/tests/functional/utils/locales.php index 97c8932a9e6c0..40781ba8b68ec 100644 --- a/dev/tests/functional/utils/locales.php +++ b/dev/tests/functional/utils/locales.php @@ -6,11 +6,16 @@ // phpcs:ignore Magento2.Security.IncludeFile include __DIR__ . '/authenticate.php'; +// phpcs:ignore Magento2.Security.Superglobal if (!empty($_POST['token'])) { + // phpcs:ignore Magento2.Security.Superglobal if (authenticate(urldecode($_POST['token']))) { + // phpcs:ignore Magento2.Security.Superglobal if ($_POST['type'] == 'deployed') { + // phpcs:ignore Magento2.Security.Superglobal $themePath = isset($_POST['theme_path']) ? $_POST['theme_path'] : 'adminhtml/Magento/backend'; $directory = __DIR__ . '/../../../../pub/static/' . $themePath; + // phpcs:ignore Magento2.Functions.DiscouragedFunction $locales = array_diff(scandir($directory), ['..', '.']); } else { // phpcs:ignore Magento2.Security.IncludeFile @@ -21,8 +26,10 @@ // phpcs:ignore Magento2.Security.LanguageConstruct echo implode('|', $locales); } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "Command not unauthorized."; } } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "'token' parameter is not set."; } diff --git a/dev/tests/functional/utils/log.php b/dev/tests/functional/utils/log.php index cec2e1c0ad211..c07f52575504f 100644 --- a/dev/tests/functional/utils/log.php +++ b/dev/tests/functional/utils/log.php @@ -7,8 +7,11 @@ // phpcs:ignore Magento2.Security.IncludeFile include __DIR__ . '/authenticate.php'; +// phpcs:ignore Magento2.Security.Superglobal if (!empty($_POST['token']) && !empty($_POST['name'])) { + // phpcs:ignore Magento2.Security.Superglobal if (authenticate(urldecode($_POST['token']))) { + // phpcs:ignore Magento2.Security.Superglobal $name = urldecode($_POST['name']); if (preg_match('/\.\.(\\\|\/)/', $name)) { // phpcs:ignore Magento2.Exceptions.DirectThrow @@ -18,8 +21,10 @@ // phpcs:ignore Magento2.Security.InsecureFunction, Magento2.Functions.DiscouragedFunction, Magento2.Security.LanguageConstruct echo serialize(file_get_contents('../../../../var/log' . '/' . $name)); } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "Command not unauthorized."; } } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "'token' or 'name' parameter is not set."; } diff --git a/dev/tests/functional/utils/pathChecker.php b/dev/tests/functional/utils/pathChecker.php index ed1949d71768d..d4a59529fac44 100644 --- a/dev/tests/functional/utils/pathChecker.php +++ b/dev/tests/functional/utils/pathChecker.php @@ -6,8 +6,11 @@ // phpcs:ignore Magento2.Security.IncludeFile include __DIR__ . '/authenticate.php'; +// phpcs:ignore Magento2.Security.Superglobal if (!empty($_POST['token']) && !empty($_POST['path'])) { + // phpcs:ignore Magento2.Security.Superglobal if (authenticate(urldecode($_POST['token']))) { + // phpcs:ignore Magento2.Security.Superglobal $path = urldecode($_POST['path']); // phpcs:ignore Magento2.Functions.DiscouragedFunction if (file_exists('../../../../' . $path)) { @@ -18,8 +21,10 @@ echo 'path exists: false'; } } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "Command not unauthorized."; } } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "'token' or 'path' parameter is not set."; } diff --git a/dev/tests/functional/utils/website.php b/dev/tests/functional/utils/website.php index 980dd557db6f7..859b60785e49d 100644 --- a/dev/tests/functional/utils/website.php +++ b/dev/tests/functional/utils/website.php @@ -6,8 +6,11 @@ // phpcs:ignore Magento2.Security.IncludeFile include __DIR__ . '/authenticate.php'; +// phpcs:ignore Magento2.Security.Superglobal if (!empty($_POST['token']) && !empty($_POST['website_code'])) { + // phpcs:ignore Magento2.Security.Superglobal if (authenticate(urldecode($_POST['token']))) { + // phpcs:ignore Magento2.Security.Superglobal $websiteCode = urldecode($_POST['website_code']); $rootDir = '../../../../'; $websiteDir = $rootDir . 'websites/' . $websiteCode . '/'; @@ -35,8 +38,10 @@ // phpcs:ignore Magento2.Functions.DiscouragedFunction file_put_contents($websiteDir . 'index.php', $contents); } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "Command not unauthorized."; } } else { + // phpcs:ignore Magento2.Security.LanguageConstruct echo "'token' or 'website_code' parameter is not set."; } From 94ac59087bb602d1a08d1fcbb1311a194e5d5902 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Thu, 2 May 2019 11:47:19 -0500 Subject: [PATCH 133/224] MC-4760: Convert CreateInvoiceEntityTest to MFTF --- .../Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml index 4aa4d879c4caa..093dc8365bad9 100644 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminOrderActionGroup.xml @@ -380,13 +380,13 @@ <!--Select Bank Transfer payment method--> <actionGroup name="SelectBankTransferPaymentMethodActionGroup" extends="SelectCheckMoneyPaymentMethod"> <remove keyForRemoval="checkCheckMoneyOption"/> - <conditionalClick selector="{{AdminOrderFormPaymentSection.bankTransferOption}}" dependentSelector="{{AdminOrderFormPaymentSection.bankTransferOption}}" visible="true" stepKey="checkBankTransferOption" after="waitForPaymentOptions"/> + <conditionalClick selector="{{AdminOrderFormPaymentSection.checkBankTransfer}}" dependentSelector="{{AdminOrderFormPaymentSection.checkBankTransfer}}" visible="true" stepKey="checkBankTransferOption" after="waitForPaymentOptions"/> </actionGroup> <!--Select Cash on Delivery payment method--> <actionGroup name="SelectCashOnDeliveryPaymentMethodActionGroup" extends="SelectCheckMoneyPaymentMethod"> <remove keyForRemoval="checkCheckMoneyOption"/> - <conditionalClick selector="{{AdminOrderFormPaymentSection.cashOnDelivery}}" dependentSelector="{{AdminOrderFormPaymentSection.cashOnDelivery}}" visible="true" stepKey="checkCashOnDeliveryOption" after="waitForPaymentOptions"/> + <conditionalClick selector="{{AdminOrderFormPaymentSection.checkCashOnDelivery}}" dependentSelector="{{AdminOrderFormPaymentSection.checkCashOnDelivery}}" visible="true" stepKey="checkCashOnDeliveryOption" after="waitForPaymentOptions"/> </actionGroup> <!--Select Purchase Order payment method--> @@ -395,8 +395,8 @@ <argument name="purchaseOrderNumber" type="string"/> </arguments> <remove keyForRemoval="checkCheckMoneyOption"/> - <conditionalClick selector="{{AdminOrderFormPaymentSection.purchaseOrder}}" dependentSelector="{{AdminOrderFormPaymentSection.purchaseOrder}}" visible="true" stepKey="checkPurchaseOrderOption" after="waitForPaymentOptions"/> - <fillField selector="{{AdminOrderFormPaymentSection.purchaseOrderNumber}}" userInput="{{purchaseOrderNumber}}" stepKey="fillPurchaseOrderNumber"/> + <conditionalClick selector="{{AdminOrderFormPaymentSection.checkPurchaseOrder}}" dependentSelector="{{AdminOrderFormPaymentSection.checkPurchaseOrder}}" visible="true" stepKey="checkPurchaseOrderOption" after="waitForPaymentOptions"/> + <fillField selector="{{AdminOrderFormPaymentSection.fieldPurchaseOrderNumber}}" userInput="{{purchaseOrderNumber}}" stepKey="fillPurchaseOrderNumber"/> </actionGroup> <!-- Create Order --> From 2f8fad776e0ab1f66aacbfe4714c399598e165c8 Mon Sep 17 00:00:00 2001 From: Grzegorz Bogusz <grz.bogusz@gmail.com> Date: Thu, 2 May 2019 19:11:33 +0200 Subject: [PATCH 134/224] Test for additional condition in getRegion() method --- .../Magento/Quote/Model/Quote/AddressTest.php | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/Quote/AddressTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/Quote/AddressTest.php index 62e417d27c51b..d040f85545b40 100644 --- a/dev/tests/integration/testsuite/Magento/Quote/Model/Quote/AddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/Quote/AddressTest.php @@ -25,6 +25,12 @@ class AddressTest extends \Magento\TestFramework\Indexer\TestCase /**@var \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository */ protected $customerRepository; + /** @var \Magento\Customer\Api\AddressRepositoryInterface $addressRepository */ + protected $addressRepository; + + /** @var \Magento\Framework\Reflection\DataObjectProcessor */ + protected $dataProcessor; + public static function setUpBeforeClass() { $db = \Magento\TestFramework\Helper\Bootstrap::getInstance()->getBootstrap() @@ -61,6 +67,14 @@ public function setUp() $this->_address->setId(1); $this->_address->load($this->_address->getId()); $this->_address->setQuote($this->_quote); + + $this->addressRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Customer\Api\AddressRepositoryInterface::class + ); + + $this->dataProcessor = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Framework\Reflection\DataObjectProcessor::class + ); } protected function tearDown() @@ -322,4 +336,22 @@ public function dataProvider() [[123, true], [123, true]] ]; } + + public function testSaveShippingAddressWithEmptyRegionId() + { + $customerAddress = $this->addressRepository->getById(1); + $customerAddress->setRegionId(0); + + $address = $this->dataProcessor->buildOutputDataArray( + $customerAddress, \Magento\Customer\Api\Data\AddressInterface::class + ); + + $shippingAddress = $this->_quote->getShippingAddress(); + $shippingAddress->addData($address); + + $shippingAddress->save(); + + $this->assertEquals(0, $shippingAddress->getRegionId()); + $this->assertEquals(0, $shippingAddress->getRegion()); + } } From 6fbc79dd622db53bfa484eaf48ccbaa082cc9b76 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Thu, 2 May 2019 12:13:35 -0500 Subject: [PATCH 135/224] MC-4765: Convert MoveLastOrderedProductsOnOrderPageTest to MFTF --- ...inCustomerActivitiesLastOrderedSection.xml | 14 +++ .../AdminCustomerCreateNewOrderSection.xml | 15 +++ .../AdminCustomerMainActionsSection.xml | 1 + .../AdminSubmitOrderActionGroup.xml | 15 +++ ...eredConfigurableProductOnOrderPageTest.xml | 112 ++++++++++++++++++ ...astOrderedSimpleProductOnOrderPageTest.xml | 65 ++++++++++ 6 files changed, 222 insertions(+) create mode 100644 app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesLastOrderedSection.xml create mode 100644 app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminSubmitOrderActionGroup.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml create mode 100644 app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedSimpleProductOnOrderPageTest.xml diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesLastOrderedSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesLastOrderedSection.xml new file mode 100644 index 0000000000000..22fa1b5bd21cb --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesLastOrderedSection.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminCustomerActivitiesLastOrderedSection"> + <element name="addProductToOrder" type="text" selector="//div[@id='sidebar_data_reorder']//tr[td[.='{{productName}}']]//input[contains(@name,'add')]" parameterized="true" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml new file mode 100644 index 0000000000000..5e6e42188d8e5 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminCustomerCreateNewOrderSection"> + <element name="updateChangesBtn" type="button" selector=".order-sidebar .actions .action-default.scalable" timeout="30"/> + <element name="gridCell" type="text" selector="//div[@class='admin__table-wrapper']//tbody['{{row}}']//td[count(//tr[@class='headings']//th[contains(., '{{column}}')]/preceding-sibling::th) +1 ]" parameterized="true" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerMainActionsSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerMainActionsSection.xml index 304068d89b729..18bc26bfd4987 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerMainActionsSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerMainActionsSection.xml @@ -13,5 +13,6 @@ <element name="saveAndContinue" type="button" selector="#save_and_continue" timeout="30"/> <element name="resetPassword" type="button" selector="#resetPassword" timeout="30"/> <element name="manageShoppingCart" type="button" selector="#manage_quote" timeout="30"/> + <element name="createOrderBtn" type="button" selector="#order" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminSubmitOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminSubmitOrderActionGroup.xml new file mode 100644 index 0000000000000..56e81da1e55a0 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminSubmitOrderActionGroup.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminSubmitOrderActionGroup"> + <click selector="{{OrdersGridSection.submitOrder}}" stepKey="submitOrder"/> + <see stepKey="seeSuccessMessageForOrder" userInput="You created the order."/> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml new file mode 100644 index 0000000000000..3cc14392c6183 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedConfigurableProductOnOrderPageTest.xml @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="MoveLastOrderedConfigurableProductOnOrderPageTest"> + <annotations> + <features value="Sales"/> + <stories value="Add Products to Order from Last Ordered Products Section"/> + <title value="Move last ordered configurable product on order page test"/> + <description value="Move last ordered configurable product on order page"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-16155"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Create customer --> + <createData entity="Simple_US_CA_Customer" stepKey="createCustomer"/> + + <!-- Create category --> + <createData entity="_defaultCategory" stepKey="createCategory"/> + + <!-- Create configurable product --> + <createData entity="ApiConfigurableProduct" stepKey="createConfigProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="productAttributeWithTwoOptions" stepKey="createConfigProductAttribute"/> + <createData entity="productAttributeOption1" stepKey="createConfigProductAttributeOption"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <createData entity="AddToDefaultSet" stepKey="createConfigAddToAttributeSet"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </createData> + <getData entity="ProductAttributeOptionGetter" index="1" stepKey="getConfigAttributeOption"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + </getData> + <createData entity="ApiSimpleOne" stepKey="createConfigChildProduct"> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption"/> + <requiredEntity createDataKey="createCategory"/> + </createData> + <createData entity="ConfigurableProductTwoOptions" stepKey="createConfigProductOption"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigProductAttribute"/> + <requiredEntity createDataKey="getConfigAttributeOption"/> + </createData> + <createData entity="ConfigurableProductAddChild" stepKey="createConfigProductAddChild"> + <requiredEntity createDataKey="createConfigProduct"/> + <requiredEntity createDataKey="createConfigChildProduct"/> + </createData> + </before> + <after> + <!-- Delete created data --> + <actionGroup ref="logout" stepKey="logout"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <deleteData createDataKey="createConfigChildProduct" stepKey="deleteConfigChildProduct"/> + <deleteData createDataKey="createConfigProduct" stepKey="deleteConfigProduct"/> + <deleteData createDataKey="createConfigProductAttribute" stepKey="deleteConfigProductAttribute"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + </after> + + <!-- Create order --> + <actionGroup ref="navigateToNewOrderPageExistingCustomer" stepKey="goToCreateOrderPage"> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Add configurable product to order --> + <actionGroup ref="addConfigurableProductToOrderFromAdmin" stepKey="addConfigurableProductToOrder"> + <argument name="product" value="$$createConfigProduct$$"/> + <argument name="attribute" value="$$createConfigProductAttribute$$"/> + <argument name="option" value="$$getConfigAttributeOption$$"/> + </actionGroup> + + <!-- Select shipping method --> + <click selector="{{AdminInvoicePaymentShippingSection.getShippingMethodAndRates}}" stepKey="openShippingMethod"/> + <waitForPageLoad stepKey="waitForShippingMethods"/> + <click selector="{{AdminInvoicePaymentShippingSection.shippingMethod}}" stepKey="chooseShippingMethod"/> + <waitForPageLoad stepKey="waitForShippingMethodLoad"/> + + <!-- Submit order --> + <actionGroup ref="AdminSubmitOrderActionGroup" stepKey="submitOrder"/> + + <!-- Search and open customer --> + <actionGroup ref="AdminFilterCustomerByEmail" stepKey="filterCreatedCustomer"> + <argument name="email" value="$$createCustomer.email$$"/> + </actionGroup> + <click selector="{{AdminCustomerGridSection.firstRowEditLink}}" stepKey="clickEditButton"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + + <!-- Click create order --> + <click selector="{{AdminCustomerMainActionsSection.createOrderBtn}}" stepKey="clickCreateOrder"/> + + <!-- Select product in Last Ordered Items section --> + <click selector="{{AdminCustomerActivitiesLastOrderedSection.addProductToOrder($$createConfigProduct.name$$)}}" stepKey="addProductToOrder"/> + + <!-- Click Update Changes --> + <click selector="{{AdminCustomerCreateNewOrderSection.updateChangesBtn}}" stepKey="clickUpdateChangesBtn"/> + + <!-- Assert product in items ordered grid --> + <see selector="{{AdminCustomerCreateNewOrderSection.gridCell('1', 'Product')}}" userInput="$$createConfigProduct.name$$" stepKey="seeProductName"/> + <see selector="{{AdminCustomerCreateNewOrderSection.gridCell('1', 'Price')}}" userInput="$123.00" stepKey="seeProductPrice"/> + </test> +</tests> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedSimpleProductOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedSimpleProductOnOrderPageTest.xml new file mode 100644 index 0000000000000..f13a934276e35 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveLastOrderedSimpleProductOnOrderPageTest.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="MoveLastOrderedSimpleProductOnOrderPageTest"> + <annotations> + <features value="Sales"/> + <stories value="Add Products to Order from Last Ordered Products Section"/> + <title value="Move last ordered simple product on order page test"/> + <description value="Move last ordered simple product on order page"/> + <severity value="CRITICAL"/> + <testCaseId value="MC-16154"/> + <group value="sales"/> + <group value="mtf_migrated"/> + </annotations> + <before> + <!-- Login as admin --> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + + <!-- Create customer --> + <createData entity="Simple_US_CA_Customer" stepKey="createCustomer"/> + + <!-- Create product --> + <createData entity="SimpleProduct2" stepKey="createProduct"/> + </before> + <after> + <!-- Delete created data --> + <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/> + <actionGroup ref="logout" stepKey="logOut"/> + </after> + + <!-- Create order --> + <actionGroup ref="CreateOrderActionGroup" stepKey="createOrder"> + <argument name="product" value="$$createProduct$$"/> + <argument name="customer" value="$$createCustomer$$"/> + </actionGroup> + + <!-- Search and open customer --> + <actionGroup ref="AdminFilterCustomerByEmail" stepKey="filterCreatedCustomer"> + <argument name="email" value="$$createCustomer.email$$"/> + </actionGroup> + <click selector="{{AdminCustomerGridSection.firstRowEditLink}}" stepKey="clickEditButton"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + + <!-- Click create order --> + <click selector="{{AdminCustomerMainActionsSection.createOrderBtn}}" stepKey="clickCreateOrder"/> + + <!-- Select product in Last Ordered Items section --> + <click selector="{{AdminCustomerActivitiesLastOrderedSection.addProductToOrder($$createProduct.name$$)}}" stepKey="addProductToOrder"/> + + <!-- Click Update Changes --> + <click selector="{{AdminCustomerCreateNewOrderSection.updateChangesBtn}}" stepKey="clickUpdateChangesBtn"/> + + <!-- Assert product in items ordered grid --> + <see selector="{{AdminCustomerCreateNewOrderSection.gridCell('1', 'Product')}}" userInput="$$createProduct.name$$" stepKey="seeProductName"/> + <see selector="{{AdminCustomerCreateNewOrderSection.gridCell('1', 'Price')}}" userInput="$$createProduct.price$$" stepKey="seeProductPrice"/> + </test> +</tests> From 149d8eb677e4214d95ade1d7987e6935c64ae511 Mon Sep 17 00:00:00 2001 From: Oleksandr Iegorov <oiegorov@magento.com> Date: Thu, 2 May 2019 12:13:57 -0500 Subject: [PATCH 136/224] MAGETWO-99451: Custom customer address attribute values are empty when address is changed in admin checkout --- .../Unit/ExtensibleDataObjectConverterTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/ExtensibleDataObjectConverterTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensibleDataObjectConverterTest.php index f0e333aa5e1d5..e362d652b7a13 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/ExtensibleDataObjectConverterTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensibleDataObjectConverterTest.php @@ -83,6 +83,17 @@ public function testToNestedArrayCustom() AttributeValue::VALUE => 'custom_attribute_value_skip', ], ], + 'test' => [ + 0 => [ + '3rd_attribute_key' => '3rd_attribute_value', + AbstractExtensibleObject::CUSTOM_ATTRIBUTES_KEY => [ + [ + AttributeValue::ATTRIBUTE_CODE => 'another_custom_attribute_code', + AttributeValue::VALUE => 'another_custom_attribute_value', + ] + ] + ] + ] ]; $resultArray = [ @@ -92,6 +103,12 @@ public function testToNestedArrayCustom() 'custom_attribute_value_multi_1', 'custom_attribute_value_multi_2', ], + 'test' => [ + 0 => [ + '3rd_attribute_key' => '3rd_attribute_value', + 'another_custom_attribute_code' => 'another_custom_attribute_value', + ] + ] ]; $this->processor->expects($this->any()) From bf46e741dacd2d7af84885c6d5c9b484d9bfbdd2 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Thu, 2 May 2019 12:18:31 -0500 Subject: [PATCH 137/224] MC-4765: Convert MoveLastOrderedProductsOnOrderPageTest to MFTF --- .../Test/TestCase/MoveLastOrderedProductsOnOrderPageTest.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveLastOrderedProductsOnOrderPageTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveLastOrderedProductsOnOrderPageTest.xml index 8bb4ef56361fb..ddb66fe921e8f 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveLastOrderedProductsOnOrderPageTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MoveLastOrderedProductsOnOrderPageTest.xml @@ -8,11 +8,13 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Sales\Test\TestCase\MoveLastOrderedProductsOnOrderPageTest" summary="Add Products to Order from Last Ordered Products Section" ticketId="MAGETWO-27640"> <variation name="MoveLastOrderedProductsOnOrderPageTestVariation1"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="order/dataset" xsi:type="string">default</data> <data name="order/data/entity_id/products" xsi:type="string">catalogProductSimple::default</data> <constraint name="Magento\Sales\Test\Constraint\AssertProductInItemsOrderedGrid" /> </variation> <variation name="MoveLastOrderedProductsOnOrderPageTestVariation2"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="order/dataset" xsi:type="string">default</data> <data name="order/data/entity_id/products" xsi:type="string">configurableProduct::configurable_with_qty_1</data> <constraint name="Magento\Sales\Test\Constraint\AssertProductInItemsOrderedGrid" /> From 237ae33440fc1cdd9ae2e18bddad7e02b755f8de Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Thu, 2 May 2019 13:40:37 -0500 Subject: [PATCH 138/224] MC-4466: Convert DeleteProductFromMiniShoppingCartTest to MFTF added mftf migrated tags --- .../Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml | 1 + .../Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml | 4 ++-- .../Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml | 1 + .../Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml index cc93c82a6312a..3f16c27b6ec79 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml @@ -10,6 +10,7 @@ <variation name="DeleteBundleProductFromMiniShoppingCartTestVariation"> <data name="products/0" xsi:type="string">bundleProduct::default</data> <data name="deletedProductIndex" xsi:type="string">0</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty" /> </variation> </testCase> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml index d29d1674e2b15..43ad90fd45be3 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Checkout\Test\TestCase\DeleteProductFromMiniShoppingCartTest" summary="Delete Product from Mini Shopping Cart" ticketId="MAGETWO-29104"> <variation name="DeleteProductFromMiniShoppingCartTestVariation1"> - <data name="tag" xsi:type="string">severity:S0</data> + <data name="tag" xsi:type="string">severity:S0, mftf_migrated:yes</data> <data name="description" xsi:type="string">delete Simple</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="products/1" xsi:type="string">catalogProductVirtual::default</data> @@ -17,7 +17,7 @@ <constraint name="Magento\Checkout\Test\Constraint\AssertProductPresentInMiniShoppingCart" /> </variation> <variation name="DeleteProductFromMiniShoppingCartTestVariation2"> - <data name="tag" xsi:type="string">severity:S1</data> + <data name="tag" xsi:type="string">severity:S1, mftf_migrated:yes</data> <data name="description" xsi:type="string">delete Simple</data> <data name="products/0" xsi:type="string">catalogProductSimple::default</data> <data name="deletedProductIndex" xsi:type="string">0</data> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml index 2d00317b61bad..042c4d45cac19 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml @@ -10,6 +10,7 @@ <variation name="DeleteConfigurableProductFromMiniShoppingCartTestVariation"> <data name="products/0" xsi:type="string">configurableProduct::default</data> <data name="deletedProductIndex" xsi:type="string">0</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty" /> </variation> </testCase> diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml index bb6a917152503..dd585ae218f5e 100644 --- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml +++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml @@ -10,6 +10,7 @@ <variation name="DeleteDownloadableProductFromMiniShoppingCartTestVariation"> <data name="products/0" xsi:type="string">downloadableProduct::default</data> <data name="deletedProductIndex" xsi:type="string">0</data> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty" /> </variation> </testCase> From 44a35086206676f8f7d01b2f79cdc03e63c4b47a Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Thu, 2 May 2019 14:28:07 -0500 Subject: [PATCH 139/224] MC-4466: Convert DeleteProductFromMiniShoppingCartTest to MFTF added mftf migrated tags --- .../Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml index dd585ae218f5e..980fdb2998c08 100644 --- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml +++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/TestCase/DeleteProductFromMiniShoppingCartTest.xml @@ -8,9 +8,9 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Checkout\Test\TestCase\DeleteProductFromMiniShoppingCartTest" summary="Delete Downloadable Product from Mini Shopping Cart" ticketId="MAGETWO-29104"> <variation name="DeleteDownloadableProductFromMiniShoppingCartTestVariation"> + <data name="tag" xsi:type="string">mftf_migrated:yes</data> <data name="products/0" xsi:type="string">downloadableProduct::default</data> <data name="deletedProductIndex" xsi:type="string">0</data> - <data name="tag" xsi:type="string">mftf_migrated:yes</data> <constraint name="Magento\Checkout\Test\Constraint\AssertCartIsEmpty" /> </variation> </testCase> From 21fdc04608e2eef8ff037004e91cf881c72fd719 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Thu, 2 May 2019 14:58:19 -0500 Subject: [PATCH 140/224] MQE-1540: Deliver weekly MTF conversion PR Deleting duplicate action group --- ...WithSegmentForCartPriceRuleActionGroup.xml | 46 ------------------- 1 file changed, 46 deletions(-) delete mode 100644 app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup.xml diff --git a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup.xml b/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup.xml deleted file mode 100644 index ac88e2d2d8118..0000000000000 --- a/app/code/Magento/SalesRule/Test/Mftf/ActionGroup/SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup.xml +++ /dev/null @@ -1,46 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <!--Set condition for Customer Segment--> - <actionGroup name="SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup"> - <arguments> - <argument name="attributeName" type="string"/> - <argument name="value" type="entity"/> - </arguments> - - <scrollTo selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" stepKey="scrollToActionTab"/> - <conditionalClick selector="{{AdminCartPriceRulesFormSection.conditionsHeader}}" dependentSelector="{{AdminCartPriceRulesFormSection.conditionsHeaderOpen}}" visible="false" stepKey="openActionTab"/> - <click selector="{{AdminCartPriceRulesFormSection.conditions}}" stepKey="applyRuleForConditions"/> - - <waitForPageLoad stepKey="waitForDropDownOpened"/> - <selectOption selector="{{AdminCartPriceRulesFormSection.childAttribute}}" userInput="{{attributeName}}" stepKey="selectAttribute"/> - - <waitForPageLoad time="20" stepKey="waitForOperator"/> - <click selector="{{AdminCartPriceRulesFormSection.condition('...')}}" stepKey="clickToChooseOption1"/> - <click selector="{{AdminCartPriceRulesFormSection.openList}}" stepKey="openList" /> - <waitForPageLoad time="20" stepKey="waitForGrid"/> - <fillField selector="{{AdminCartPriceRulesFormSection.searchSegmentName}}" userInput="{{value.name}}" stepKey="fillSegmentName"/> - <click selector="{{AdminCartPriceRulesFormSection.searchButton}}" stepKey="clickButtonSearch"/> - - <waitForPageLoad stepKey="waitForResults"/> - <checkOption selector="{{AdminCartPriceRulesFormSection.selectAll}}" stepKey="checkAll"/> - <waitForPageLoad stepKey="waitForChecking"/> - <moveMouseOver selector="{{AdminCartPriceRulesFormSection.setSegment}}" stepKey="moveOnButton"/> - <click selector="{{AdminCartPriceRulesFormSection.setSegment}}" stepKey="setCustomerSegment"/> - <click selector="{{AdminMainActionsSection.saveAndContinue}}" stepKey="clickSaveButton"/> - <see selector="{{AdminCartPriceRulesSection.messages}}" userInput="You saved the rule." stepKey="seeSuccessMessage"/> - </actionGroup> - <actionGroup name="SetCartAttributeConditionWhenMatchForCartPriceRuleActionGroup" extends="SetCartAttributeConditionWithSegmentForCartPriceRuleActionGroup"> - <arguments> - <argument name="operatorType" type="string" defaultValue="matches"/> - </arguments> - <click selector="{{AdminCartPriceRulesFormSection.condition('matches')}}" stepKey="clickToChooseOption" after="waitForOperator"/> - <selectOption userInput="{{operatorType}}" selector="{{AdminCartPriceRulesFormSection.conditionsOperator}}" stepKey="setOperatorType" after="clickToChooseOption"/> - </actionGroup> -</actionGroups> From c94a655fe9a5829a2721b293869cda3ae1be430a Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Thu, 2 May 2019 17:42:33 -0500 Subject: [PATCH 141/224] GraphQl-309: [Checkout] Checkout Agreements --- .../Model/Resolver/CheckoutAgreements.php | 54 +++++++++++-- .../DataProvider/CheckoutAgreements.php | 81 ------------------- .../CheckoutAgreementsGraphQl/composer.json | 3 +- ...Test.php => GetCheckoutAgreementsTest.php} | 50 +++++++----- 4 files changed, 75 insertions(+), 113 deletions(-) delete mode 100644 app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php rename dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/{Api/CheckoutAgreementsListTest.php => GetCheckoutAgreementsTest.php} (79%) diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php index 7009e1e2d85e6..c312d8622a0a9 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php +++ b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php @@ -7,10 +7,14 @@ namespace Magento\CheckoutAgreementsGraphQl\Model\Resolver; -use Magento\CheckoutAgreementsGraphQl\Model\Resolver\DataProvider\CheckoutAgreements as CheckoutAgreementsDataProvider; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; +use Magento\CheckoutAgreements\Api\Data\AgreementInterface; +use Magento\CheckoutAgreements\Model\ResourceModel\Agreement\CollectionFactory; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\StoreManagerInterface; /** * Checkout Agreements resolver, used for GraphQL request processing @@ -18,17 +22,33 @@ class CheckoutAgreements implements ResolverInterface { /** - * @var CheckoutAgreementsDataProvider + * @var CollectionFactory */ - private $checkoutAgreementsDataProvider; + private $agreementCollectionFactory; /** - * @param CheckoutAgreementsDataProvider $checkoutAgreementsDataProvider + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * @param CollectionFactory $agreementCollectionFactory + * @param StoreManagerInterface $storeManager + * @param ScopeConfigInterface $scopeConfig */ public function __construct( - CheckoutAgreementsDataProvider $checkoutAgreementsDataProvider + CollectionFactory $agreementCollectionFactory, + StoreManagerInterface $storeManager, + ScopeConfigInterface $scopeConfig ) { - $this->checkoutAgreementsDataProvider = $checkoutAgreementsDataProvider; + $this->agreementCollectionFactory = $agreementCollectionFactory; + $this->storeManager = $storeManager; + $this->scopeConfig = $scopeConfig; } /** @@ -41,8 +61,26 @@ public function resolve( array $value = null, array $args = null ) { - $checkoutAgreementsData = $this->checkoutAgreementsDataProvider->getData(); + if (!$this->scopeConfig->isSetFlag('checkout/options/enable_agreements', ScopeInterface::SCOPE_STORE)) { + return []; + } + + $agreementsCollection = $this->agreementCollectionFactory->create(); + $agreementsCollection->addStoreFilter($this->storeManager->getStore()->getId()); + $agreementsCollection->addFieldToFilter('is_active', 1); - return $checkoutAgreementsData; + $checkoutAgreementData = []; + /** @var AgreementInterface $checkoutAgreement */ + foreach ($agreementsCollection->getItems() as $checkoutAgreement) { + $checkoutAgreementData[] = [ + AgreementInterface::AGREEMENT_ID => $checkoutAgreement->getAgreementId(), + AgreementInterface::CONTENT => $checkoutAgreement->getContent(), + AgreementInterface::NAME => $checkoutAgreement->getName(), + AgreementInterface::CONTENT_HEIGHT => $checkoutAgreement->getContentHeight(), + AgreementInterface::CHECKBOX_TEXT => $checkoutAgreement->getCheckboxText(), + AgreementInterface::IS_HTML => $checkoutAgreement->getIsHtml(), + ]; + } + return $checkoutAgreementData; } } diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php deleted file mode 100644 index 3dab845627261..0000000000000 --- a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\CheckoutAgreementsGraphQl\Model\Resolver\DataProvider; - -use Magento\CheckoutAgreements\Api\Data\AgreementInterface; -use Magento\CheckoutAgreements\Model\Agreement; -use Magento\CheckoutAgreements\Model\ResourceModel\Agreement\CollectionFactory; -use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Store\Model\ScopeInterface; -use Magento\Store\Model\StoreManagerInterface; - -/** - * Checkout Agreements data provider - */ -class CheckoutAgreements -{ - /** - * @var CollectionFactory - */ - private $agreementCollectionFactory; - - /** - * @var StoreManagerInterface - */ - private $storeManager; - - /** - * @var ScopeConfigInterface - */ - private $scopeConfig; - - /** - * @param CollectionFactory $agreementCollectionFactory - * @param StoreManagerInterface $storeManager - * @param ScopeConfigInterface $scopeConfig - */ - public function __construct( - CollectionFactory $agreementCollectionFactory, - StoreManagerInterface $storeManager, - ScopeConfigInterface $scopeConfig - ) { - $this->agreementCollectionFactory = $agreementCollectionFactory; - $this->storeManager = $storeManager; - $this->scopeConfig = $scopeConfig; - } - - /** - * Get All Active Checkout Agreements Data - * - * @return array - */ - public function getData(): array - { - if (!$this->scopeConfig->isSetFlag('checkout/options/enable_agreements', ScopeInterface::SCOPE_STORE)) { - return []; - } - $agreementsCollection = $this->agreementCollectionFactory->create(); - $agreementsCollection->addStoreFilter($this->storeManager->getStore()->getId()); // TODO: store should be get from query context - $agreementsCollection->addFieldToFilter('is_active', 1); - - $checkoutAgreementData = []; - /** @var Agreement $checkoutAgreement */ - foreach ($agreementsCollection->getItems() as $checkoutAgreement) { - $checkoutAgreementData[] = [ - AgreementInterface::AGREEMENT_ID => $checkoutAgreement->getAgreementId(), - AgreementInterface::CONTENT => $checkoutAgreement->getContent(), - AgreementInterface::NAME => $checkoutAgreement->getName(), - AgreementInterface::CONTENT_HEIGHT => $checkoutAgreement->getContentHeight(), - AgreementInterface::CHECKBOX_TEXT => $checkoutAgreement->getCheckboxText(), - AgreementInterface::IS_HTML => $checkoutAgreement->getIsHtml(), - ]; - } - - return $checkoutAgreementData; - } -} diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/composer.json b/app/code/Magento/CheckoutAgreementsGraphQl/composer.json index 064e8f7c2ec94..5972d48b35ea9 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/composer.json +++ b/app/code/Magento/CheckoutAgreementsGraphQl/composer.json @@ -9,8 +9,7 @@ "magento/module-checkout-agreements": "*" }, "suggest": { - "magento/module-graph-ql": "*", - "magento/module-store-graph-ql": "*" + "magento/module-graph-ql": "*" }, "license": [ "OSL-3.0", diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/GetCheckoutAgreementsTest.php similarity index 79% rename from dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php rename to dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/GetCheckoutAgreementsTest.php index 62491e5e8376b..663b314ffdb57 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/GetCheckoutAgreementsTest.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\GraphQl\CheckoutAgreements\Api; +namespace Magento\GraphQl\CheckoutAgreements; use Magento\CheckoutAgreements\Api\Data\AgreementInterface; use Magento\CheckoutAgreements\Model\Agreement as AgreementModel; @@ -20,8 +20,14 @@ use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; -class CheckoutAgreementsListTest extends GraphQlAbstract +/** + * Get checkout agreements test + */ +class GetCheckoutAgreementsTest extends GraphQlAbstract { + /** + * @var string + */ private $agreementsXmlConfigPath = 'checkout/options/enable_agreements'; /** @@ -55,14 +61,14 @@ public function testGetActiveAgreement() $response = $this->graphQlQuery($query); - $this->assertArrayHasKey('checkoutAgreements', $response); + self::assertArrayHasKey('checkoutAgreements', $response); $agreements = $response['checkoutAgreements']; - $this->assertCount(1, $agreements); - $this->assertEquals('Checkout Agreement (active)', $agreements[0]['name']); - $this->assertEquals('Checkout agreement content: <b>HTML</b>', $agreements[0]['content']); - $this->assertEquals('200px', $agreements[0]['content_height']); - $this->assertEquals('Checkout agreement checkbox text.', $agreements[0]['checkbox_text']); - $this->assertEquals(true, $agreements[0]['is_html']); + self::assertCount(1, $agreements); + self::assertEquals('Checkout Agreement (active)', $agreements[0]['name']); + self::assertEquals('Checkout agreement content: <b>HTML</b>', $agreements[0]['content']); + self::assertEquals('200px', $agreements[0]['content_height']); + self::assertEquals('Checkout agreement checkbox text.', $agreements[0]['checkbox_text']); + self::assertEquals(true, $agreements[0]['is_html']); } /** @@ -81,14 +87,14 @@ public function testGetActiveAgreementOnSecondStore() $headerMap['Store'] = $secondStoreCode; $response = $this->graphQlQuery($query, [], '', $headerMap); - $this->assertArrayHasKey('checkoutAgreements', $response); + self::assertArrayHasKey('checkoutAgreements', $response); $agreements = $response['checkoutAgreements']; - $this->assertCount(1, $agreements); - $this->assertEquals($agreementsName, $agreements[0]['name']); - $this->assertEquals('Checkout agreement content: <b>HTML</b>', $agreements[0]['content']); - $this->assertEquals('200px', $agreements[0]['content_height']); - $this->assertEquals('Checkout agreement checkbox text.', $agreements[0]['checkbox_text']); - $this->assertEquals(true, $agreements[0]['is_html']); + self::assertCount(1, $agreements); + self::assertEquals($agreementsName, $agreements[0]['name']); + self::assertEquals('Checkout agreement content: <b>HTML</b>', $agreements[0]['content']); + self::assertEquals('200px', $agreements[0]['content_height']); + self::assertEquals('Checkout agreement checkbox text.', $agreements[0]['checkbox_text']); + self::assertEquals(true, $agreements[0]['is_html']); } /** @@ -106,9 +112,9 @@ public function testGetActiveAgreementFromSecondStoreOnDefaultStore() $response = $this->graphQlQuery($query); - $this->assertArrayHasKey('checkoutAgreements', $response); + self::assertArrayHasKey('checkoutAgreements', $response); $agreements = $response['checkoutAgreements']; - $this->assertCount(0, $agreements); + self::assertCount(0, $agreements); } public function testGetAgreementNotSet() @@ -117,9 +123,9 @@ public function testGetAgreementNotSet() $response = $this->graphQlQuery($query); - $this->assertArrayHasKey('checkoutAgreements', $response); + self::assertArrayHasKey('checkoutAgreements', $response); $agreements = $response['checkoutAgreements']; - $this->assertCount(0, $agreements); + self::assertCount(0, $agreements); } /** @@ -133,9 +139,9 @@ public function testDisabledAgreements() $response = $this->graphQlQuery($query); - $this->assertArrayHasKey('checkoutAgreements', $response); + self::assertArrayHasKey('checkoutAgreements', $response); $agreements = $response['checkoutAgreements']; - $this->assertCount(0, $agreements); + self::assertCount(0, $agreements); } /** From cc65d3e6fbb53de01cdd3cd36ba1b78ef0ca3bc1 Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Thu, 2 May 2019 22:34:42 -0400 Subject: [PATCH 142/224] Prevent Error When Getting Payment Method Before Setting Calling [`Magento\Quote\Model\Quote\Payment::getMethodInstance`](https://github.com/magento/graphql-ce/blob/b2ce2a37d921b5ad88fc38663fc0ff3dd6c582d1/app/code/Magento/Payment/Model/Info.php#L105) throws an exception when the method is not set. This would trigger and error when requsting the `selected_payment_method` cart property. This commit returns an empty string instead. --- .../Model/Resolver/SelectedPaymentMethod.php | 10 +++++++-- .../Customer/GetSelectedPaymentMethodTest.php | 21 +++++++++++++++++++ .../Guest/GetSelectedPaymentMethodTest.php | 20 ++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SelectedPaymentMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SelectedPaymentMethod.php index 8cda06eba3c91..44912d249cc24 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SelectedPaymentMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SelectedPaymentMethod.php @@ -34,9 +34,15 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value return []; } + try { + $methodTitle = $payment->getMethodInstance()->getTitle(); + } catch (LocalizedException $e) { + $methodTitle = ''; + } + return [ - 'code' => $payment->getMethod(), - 'title' => $payment->getMethodInstance()->getTitle(), + 'code' => $payment->getMethod() ?? '', + 'title' => $methodTitle, 'purchase_order_number' => $payment->getPoNumber(), ]; } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php index d876d74de661b..4432a233e96e7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedPaymentMethodTest.php @@ -49,6 +49,27 @@ public function testGetSelectedPaymentMethod() $this->assertEquals('checkmo', $response['cart']['selected_payment_method']['code']); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSelectedPaymentMethodBeforeSet() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + + $this->assertArrayHasKey('cart', $response); + $this->assertArrayHasKey('selected_payment_method', $response['cart']); + $this->assertArrayHasKey('code', $response['cart']['selected_payment_method']); + $this->assertEquals('', $response['cart']['selected_payment_method']['code']); + } + /** * @magentoApiDataFixture Magento/Customer/_files/customer.php * @expectedException \Exception diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php index ef04da88ea67a..a918279bada65 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedPaymentMethodTest.php @@ -49,6 +49,26 @@ public function testGetSelectedPaymentMethod() $this->assertEquals('checkmo', $response['cart']['selected_payment_method']['code']); } + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/enable_offline_payment_methods.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSelectedPaymentMethodBeforeSet() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + + $this->assertArrayHasKey('cart', $response); + $this->assertArrayHasKey('selected_payment_method', $response['cart']); + $this->assertArrayHasKey('code', $response['cart']['selected_payment_method']); + $this->assertEquals('', $response['cart']['selected_payment_method']['code']); + } + /** * @expectedException \Exception */ From 8b37ef75fd63eb797e71b65c64d650c1a896293c Mon Sep 17 00:00:00 2001 From: Patrick McLain <pat@pmclain.com> Date: Thu, 2 May 2019 23:24:27 -0400 Subject: [PATCH 143/224] Prevent undefined index warning before setting shipping method `list` would cause and undefined index error when address rates had been collected and the shipping method was not set. This commit checks that the shipping method is set prior to resolving. Fixes magento/graphql-ce#657 --- .../SelectedShippingMethod.php | 2 +- .../GetSelectedShippingMethodTest.php | 38 +++++++++++++++++++ .../Guest/GetSelectedShippingMethodTest.php | 37 ++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php index 05bc196acfc22..b359971880036 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -49,7 +49,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $carrierTitle = null; $methodTitle = null; - if (count($rates) > 0) { + if (count($rates) > 0 && !empty($address->getShippingMethod())) { list($carrierCode, $methodCode) = explode('_', $address->getShippingMethod(), 2); /** @var Rate $rate */ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php index 5575830ea51cd..9bb36bf8f0929 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetSelectedShippingMethodTest.php @@ -88,6 +88,40 @@ public function testGetSelectedShippingMethod() self::assertEquals('USD', $baseAmount['currency']); } + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSelectedShippingMethodBeforeSet() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + self::assertCount(1, $response['cart']['shipping_addresses']); + + $shippingAddress = current($response['cart']['shipping_addresses']); + self::assertArrayHasKey('selected_shipping_method', $shippingAddress); + + self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); + self::assertNull($shippingAddress['selected_shipping_method']['carrier_code']); + + self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); + self::assertNull($shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertNull($shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertNull($shippingAddress['selected_shipping_method']['method_title']); + } + /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php @@ -193,6 +227,10 @@ private function getQuery(string $maskedQuoteId): string { cart(cart_id: "$maskedQuoteId") { shipping_addresses { + available_shipping_methods { + carrier_code + method_code + } selected_shipping_method { carrier_code method_code diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php index bd684a950b590..5d1033b39819e 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetSelectedShippingMethodTest.php @@ -80,6 +80,39 @@ public function testGetSelectedShippingMethod() self::assertEquals('USD', $baseAmount['currency']); } + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/set_new_shipping_address.php + */ + public function testGetSelectedShippingMethodBeforeSet() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey('cart', $response); + self::assertArrayHasKey('shipping_addresses', $response['cart']); + self::assertCount(1, $response['cart']['shipping_addresses']); + + $shippingAddress = current($response['cart']['shipping_addresses']); + self::assertArrayHasKey('selected_shipping_method', $shippingAddress); + + self::assertArrayHasKey('carrier_code', $shippingAddress['selected_shipping_method']); + self::assertNull($shippingAddress['selected_shipping_method']['carrier_code']); + + self::assertArrayHasKey('method_code', $shippingAddress['selected_shipping_method']); + self::assertNull($shippingAddress['selected_shipping_method']['method_code']); + + self::assertArrayHasKey('carrier_title', $shippingAddress['selected_shipping_method']); + self::assertNull($shippingAddress['selected_shipping_method']['carrier_title']); + + self::assertArrayHasKey('method_title', $shippingAddress['selected_shipping_method']); + self::assertNull($shippingAddress['selected_shipping_method']['method_title']); + } + /** * _security * @magentoApiDataFixture Magento/Customer/_files/customer.php @@ -149,6 +182,10 @@ private function getQuery(string $maskedQuoteId): string { cart(cart_id: "$maskedQuoteId") { shipping_addresses { + available_shipping_methods { + carrier_code + method_code + } selected_shipping_method { carrier_code method_code From fd369e7bed816ae9b803e31a1d3ed615bdc09f4c Mon Sep 17 00:00:00 2001 From: Nikita Shcherbatykh <nikita.shcherbatykh@transoftgroup.com> Date: Fri, 3 May 2019 11:10:19 +0300 Subject: [PATCH 144/224] MAGETWO-98656: Purchasing a downloadable product as guest then creating an account on the onepagesuccess step doesn't link product with account --- ...orefrontCustomerDownloadableProductsSection.xml | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml deleted file mode 100644 index d45a774077ba0..0000000000000 --- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerDownloadableProductsSection.xml +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> - <section name="StorefrontCustomerDownloadableProductsSection"> - <element name="productName" type="text" selector="//table[@id='my-downloadable-products-table']//strong[contains(@class, 'product-name') and normalize-space(.)='{{productName}}']" parameterized="true"/> - </section> -</sections> From 093af61ea5db9f2c052d85f26d097aea19ec492a Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Fri, 3 May 2019 12:44:04 +0300 Subject: [PATCH 145/224] Fix static tests. --- .../Magento/Vault/Observer/AfterPaymentSaveObserver.php | 2 +- .../Test/Unit/Observer/AfterPaymentSaveObserverTest.php | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Vault/Observer/AfterPaymentSaveObserver.php b/app/code/Magento/Vault/Observer/AfterPaymentSaveObserver.php index 00aee961d8d3f..14b7cc6c726bb 100644 --- a/app/code/Magento/Vault/Observer/AfterPaymentSaveObserver.php +++ b/app/code/Magento/Vault/Observer/AfterPaymentSaveObserver.php @@ -113,7 +113,7 @@ protected function generatePublicHash(PaymentTokenInterface $paymentToken) /** * Reads Payment token from Order Payment * - * @param OrderPaymentExtensionInterface | null $extensionAttributes + * @param OrderPaymentExtensionInterface|null $extensionAttributes * @return PaymentTokenInterface | null */ protected function getPaymentToken(OrderPaymentExtensionInterface $extensionAttributes = null) diff --git a/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php b/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php index 539a4b5c38b34..2ae16e186030d 100644 --- a/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php +++ b/app/code/Magento/Vault/Test/Unit/Observer/AfterPaymentSaveObserverTest.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Vault\Test\Unit\Observer; use Magento\Framework\App\DeploymentConfig; @@ -19,6 +20,9 @@ use Magento\Vault\Observer\AfterPaymentSaveObserver; use PHPUnit_Framework_MockObject_MockObject as MockObject; +/** + * Tests for AfterPaymentSaveObserver. + */ class AfterPaymentSaveObserverTest extends \PHPUnit\Framework\TestCase { /** @@ -162,7 +166,10 @@ public function testPositiveCase($customerId, $createdAt, $token, $isActive, $me static::assertEquals($token, $paymentToken->getGatewayToken()); static::assertEquals($isActive, $paymentToken->getIsActive()); static::assertEquals($createdAt, $paymentToken->getCreatedAt()); - static::assertEquals($additionalInfo[VaultConfigProvider::IS_ACTIVE_CODE] ?? false, $paymentToken->getIsVisible()); + static::assertEquals( + $additionalInfo[VaultConfigProvider::IS_ACTIVE_CODE] ?? false, + $paymentToken->getIsVisible() + ); } /** From 509cded0ce0cf3bd23dc1cf0b7c442483c9d1dd9 Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Fri, 3 May 2019 14:34:10 +0300 Subject: [PATCH 146/224] magento/magento2#22599 static-test-fix --- .../DataProvider/Product/ProductRenderCollectorComposite.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductRenderCollectorComposite.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductRenderCollectorComposite.php index a4b3f231cfb9c..7edf25ff20cc1 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductRenderCollectorComposite.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/ProductRenderCollectorComposite.php @@ -9,8 +9,7 @@ use Magento\Catalog\Api\Data\ProductRenderInterface; /** - * Composite, which holds collectors, that collect enough information for - * product render + * Composite, which holds collectors, that collect enough information for product render */ class ProductRenderCollectorComposite implements ProductRenderCollectorInterface { From 5f5a2618d218a31705c472167654e4db25dcdc51 Mon Sep 17 00:00:00 2001 From: UdgamN <udgamnigam@cedcoss.com> Date: Fri, 3 May 2019 18:18:36 +0530 Subject: [PATCH 147/224] Resolved Typo Updated and corrected the spelling of 'accesibility' to accessiblity --- lib/web/css/docs/source/_breadcrumbs.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/css/docs/source/_breadcrumbs.less b/lib/web/css/docs/source/_breadcrumbs.less index 848af20c0728e..5b5df991e3cdc 100644 --- a/lib/web/css/docs/source/_breadcrumbs.less +++ b/lib/web/css/docs/source/_breadcrumbs.less @@ -8,7 +8,7 @@ // // Breadcrumbs layout with links can be separated by any symbol, for example <code>></code> symbol. // -// The following markup corresponds to the accesibility demands: +// The following markup corresponds to the accessibility demands: // ```html // <div class="example-breadcrumbs-1"> // <span class="label" id="breadcrumb-label">You are here:</span> From ffdbf8584600e80cb5d8eaeb50c558f6fd52f241 Mon Sep 17 00:00:00 2001 From: Justin Liotta <6843459+justin-at-bounteous@users.noreply.github.com> Date: Fri, 3 May 2019 10:27:09 -0400 Subject: [PATCH 148/224] Fix Exception While Creating an Order in the Admin Changes: - $total->getDiscountDescription() returns a Phrase, but strlen expects a string --- .../SalesRule/Model/Quote/Address/Total/ShippingDiscount.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Model/Quote/Address/Total/ShippingDiscount.php b/app/code/Magento/SalesRule/Model/Quote/Address/Total/ShippingDiscount.php index c37ca276e0ee2..53adcd268f81d 100644 --- a/app/code/Magento/SalesRule/Model/Quote/Address/Total/ShippingDiscount.php +++ b/app/code/Magento/SalesRule/Model/Quote/Address/Total/ShippingDiscount.php @@ -89,7 +89,7 @@ public function fetch(Quote $quote, Total $total): array $amount = $total->getDiscountAmount(); if ($amount != 0) { - $description = $total->getDiscountDescription() ?: ''; + $description = (string)$total->getDiscountDescription() ?: ''; $result = [ 'code' => DiscountCollector::COLLECTOR_TYPE_CODE, 'title' => strlen($description) ? __('Discount (%1)', $description) : __('Discount'), From f06ccb18fcd05942984b73694d7f190f6c280046 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Fri, 3 May 2019 10:02:22 -0500 Subject: [PATCH 149/224] MC-4764: Convert MoveProductsInComparedOnOrderPageTest to MFTF --- ...ustomerActivitiesComparisonListSection.xml | 2 -- ...dminCustomerActivitiesConfigureSection.xml | 15 +++++++++++++ .../AddConfigureToProductActionGroup.xml | 21 ------------------- ...rableProductsInComparedOnOrderPageTest.xml | 16 +++++++------- 4 files changed, 23 insertions(+), 31 deletions(-) create mode 100644 app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesConfigureSection.xml delete mode 100644 app/code/Magento/Sales/Test/Mftf/ActionGroup/AddConfigureToProductActionGroup.xml diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesComparisonListSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesComparisonListSection.xml index f54dfdc2b236f..46eed69f22467 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesComparisonListSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesComparisonListSection.xml @@ -11,7 +11,5 @@ <section name="AdminCustomerActivitiesComparisonListSection"> <element name="addProductToOrder" type="text" selector="//div[@id='order-sidebar_compared']//tr[td[.='{{productName}}']]//input[contains(@name,'add')]" parameterized="true" timeout="30"/> <element name="addToOrderConfigure" type="button" selector="//div[@id='order-sidebar_compared']//tr[td[contains(.,'{{productName}}')]]//a[contains(@class, 'icon-configure')]" parameterized="true" timeout="30"/> - <element name="addAttribute" type="select" selector="[id*='attribute']" timeout="30"/> - <element name="okButton" type="button" selector="//button[contains(concat(' ',normalize-space(@class),' '),' action-primary ')]" timeout="30"/> </section> </sections> diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesConfigureSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesConfigureSection.xml new file mode 100644 index 0000000000000..5d7c4b1171558 --- /dev/null +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerActivitiesConfigureSection.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminCustomerActivitiesConfigureSection"> + <element name="addAttribute" type="select" selector="[id*='attribute']" timeout="30"/> + <element name="okButton" type="button" selector="//button[contains(concat(' ',normalize-space(@class),' '),' action-primary ')]" timeout="30"/> + </section> +</sections> diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AddConfigureToProductActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AddConfigureToProductActionGroup.xml deleted file mode 100644 index 79aaa46b7bb9d..0000000000000 --- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AddConfigureToProductActionGroup.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AddConfigureToProductActionGroup"> - <arguments> - <argument name="productName" type="string"/> - <argument name="option" type="string"/> - </arguments> - <click selector="{{AdminCustomerActivitiesComparisonListSection.addToOrderConfigure(productName)}}" stepKey="configureFirstProduct"/> - <selectOption selector="{{AdminCustomerActivitiesComparisonListSection.addAttribute}}" userInput="{{option}}" stepKey="selectOption"/> - <click selector="{{AdminCustomerActivitiesComparisonListSection.okButton}}" stepKey="clickOkBtn"/> - <waitForPageLoad stepKey="waitForPageLoad"/> - </actionGroup> -</actionGroups> diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveCongigurableProductsInComparedOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveCongigurableProductsInComparedOnOrderPageTest.xml index 11e40d4364de2..980d5cc82b93d 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/MoveCongigurableProductsInComparedOnOrderPageTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/MoveCongigurableProductsInComparedOnOrderPageTest.xml @@ -140,16 +140,16 @@ <click selector="{{AdminCustomerMainActionsSection.createOrderBtn}}" stepKey="clickCreateOrder"/> <!-- Add configure to first product --> - <actionGroup ref="AddConfigureToProductActionGroup" stepKey="addConfigureToFirstProduct"> - <argument name="productName" value="$$createFirstConfigProduct.name$$"/> - <argument name="option" value="$$getFirstConfigAttributeOption.value$$"/> - </actionGroup> + <click selector="{{AdminCustomerActivitiesComparisonListSection.addToOrderConfigure($$createFirstConfigProduct.name$$)}}" stepKey="configureFirstProduct"/> + <selectOption selector="{{AdminCustomerActivitiesConfigureSection.addAttribute}}" userInput="$$getFirstConfigAttributeOption.value$$" stepKey="selectOptionForFirstProduct"/> + <click selector="{{AdminCustomerActivitiesConfigureSection.okButton}}" stepKey="clickOkBtnForFirstProduct"/> + <waitForPageLoad stepKey="waitForConfigureForFirstProductLoad"/> <!-- Add configure to second product --> - <actionGroup ref="AddConfigureToProductActionGroup" stepKey="addConfigureToSecondProduct"> - <argument name="productName" value="$$createSecondConfigProduct.name$$"/> - <argument name="option" value="$$getSecondConfigAttributeOption.value$$"/> - </actionGroup> + <click selector="{{AdminCustomerActivitiesComparisonListSection.addToOrderConfigure($$createSecondConfigProduct.name$$)}}" stepKey="configureSecondProduct"/> + <selectOption selector="{{AdminCustomerActivitiesConfigureSection.addAttribute}}" userInput="$$getSecondConfigAttributeOption.value$$" stepKey="selectOptionForSecond"/> + <click selector="{{AdminCustomerActivitiesConfigureSection.okButton}}" stepKey="clickOkBtnForSecondProduct"/> + <waitForPageLoad stepKey="waitForConfigureForSecondProductLoad"/> <!-- Click 'Update Changes' --> <click selector="{{AdminCustomerCreateNewOrderSection.updateChangesBtn}}" stepKey="clickUpdateChangesBtn"/> From 984fce36985986fbb7c36aa30598b71d342c858a Mon Sep 17 00:00:00 2001 From: Hailong Zhao <hailongzh@hotmail.com> Date: Fri, 3 May 2019 11:26:34 -0400 Subject: [PATCH 150/224] Add a missting colon in the pdf page. --- app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php b/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php index 85e34f560bb7b..cc7c2768ead36 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php @@ -511,7 +511,7 @@ protected function insertOrder(&$page, $obj, $putOrderId = true) $this->y -= 15; $this->_setFontBold($page, 12); $page->setFillColor(new \Zend_Pdf_Color_GrayScale(0)); - $page->drawText(__('Payment Method'), 35, $this->y, 'UTF-8'); + $page->drawText(__('Payment Method:'), 35, $this->y, 'UTF-8'); $page->drawText(__('Shipping Method:'), 285, $this->y, 'UTF-8'); $this->y -= 10; From b6fce58e9d2148f97e16742947940f8a1fc9e7e4 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Fri, 3 May 2019 10:32:20 -0500 Subject: [PATCH 151/224] MC-11063: Add Product to Cart, Backorder Allowed - Fixed missing argument - Added waitForPageLoad --- .../Test/Mftf/ActionGroup/AddProductToCartActionGroup.xml | 1 + .../Test/Mftf/Test/AdminBackorderAllowedAddProductToCartTest.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddProductToCartActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddProductToCartActionGroup.xml index a544be434f9c5..97d4ac5389311 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddProductToCartActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AddProductToCartActionGroup.xml @@ -12,6 +12,7 @@ <argument name="product" defaultValue="product"/> </arguments> <amOnPage url="{{StorefrontProductPage.url(product.custom_attributes[url_key])}}" stepKey="goToProductPage"/> + <waitForPageLoad stepKey="waitForProductPage"/> <click selector="{{StorefrontProductPageSection.addToCartBtn}}" stepKey="addToCart"/> <waitForElementNotVisible selector="{{StorefrontProductActionSection.addToCartButtonTitleIsAdding}}" stepKey="waitForElementNotVisibleAddToCartButtonTitleIsAdding"/> <waitForElementNotVisible selector="{{StorefrontProductActionSection.addToCartButtonTitleIsAdded}}" stepKey="waitForElementNotVisibleAddToCartButtonTitleIsAdded"/> diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminBackorderAllowedAddProductToCartTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminBackorderAllowedAddProductToCartTest.xml index 9d8839621a0e3..88c524eff387c 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminBackorderAllowedAddProductToCartTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminBackorderAllowedAddProductToCartTest.xml @@ -44,6 +44,7 @@ <waitForPageLoad stepKey="waitForCartLoad"/> <actionGroup ref="AssertStorefrontCheckoutCartItemsActionGroup" stepKey="assertProductItemInCheckOutCart"> <argument name="productName" value="$$createProduct.name$$"/> + <argument name="productSku" value="$$createProduct.sku$$"/> <argument name="productPrice" value="$$createProduct.price$$"/> <argument name="subtotal" value="$$createProduct.price$$" /> <argument name="qty" value="1"/> From 28c254efaffbec7e351456e54b26ee079ef3ded0 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Fri, 3 May 2019 10:54:09 -0500 Subject: [PATCH 152/224] MC-4761: Convert UnassignCustomOrderStatusTest to MFTF - Made changes from code review --- .../AdminUnassignCustomOrderStatusTest.xml | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml index ed8a487159ec3..982f0b9251cfc 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminUnassignCustomOrderStatusTest.xml @@ -19,20 +19,22 @@ </annotations> <before> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> - <!--Go to new order status page--> - <amOnPage url="{{AdminOrderStatusPage.url}}" stepKey="goToOrderStatusPage"/> - <click selector="{{AdminMainActionsSection.add}}" stepKey="clickCreateNewStatus"/> - <!--Fill the form and validate save success message--> - <actionGroup ref="AdminOrderStatusFormFillAndSave" stepKey="fillFormAndClickSave"> - <argument name="status" value="{{defaultOrderStatus.status}}"/> - <argument name="label" value="{{defaultOrderStatus.label}}"/> - </actionGroup> - <actionGroup ref="AssertOrderStatusFormSaveSuccess" stepKey="seeFormSaveSuccess"/> </before> <after> <actionGroup ref="logout" stepKey="logout"/> </after> + <!--Go to new order status page--> + <amOnPage url="{{AdminOrderStatusPage.url}}" stepKey="goToOrderStatusPage"/> + <click selector="{{AdminMainActionsSection.add}}" stepKey="clickCreateNewStatus"/> + + <!--Fill the form and validate save success message--> + <actionGroup ref="AdminOrderStatusFormFillAndSave" stepKey="fillFormAndClickSave"> + <argument name="status" value="{{defaultOrderStatus.status}}"/> + <argument name="label" value="{{defaultOrderStatus.label}}"/> + </actionGroup> + <actionGroup ref="AssertOrderStatusFormSaveSuccess" stepKey="seeFormSaveSuccess"/> + <!--Open the created order status in grid page and change the order state to Pending and verify save message--> <actionGroup ref="AssertOrderStatusExistsInGrid" stepKey="searchCreatedOrderStatus"> <argument name="status" value="{{defaultOrderStatus.status}}"/> @@ -50,6 +52,7 @@ <argument name="status" value="{{defaultOrderStatus.status}}"/> <argument name="label" value="{{defaultOrderStatus.label}}"/> </actionGroup> + <!--Click unassign and verify AssertOrderStatusSuccessUnassignMessage--> <click selector="{{AdminOrderStatusGridSection.unassign}}" stepKey="clickUnassign"/> <see selector="{{AdminMessagesSection.success}}" userInput="You have unassigned the order status." stepKey="seeAssertOrderStatusSuccessUnassignMessage"/> @@ -59,8 +62,9 @@ <argument name="status" value="{{defaultOrderStatus.status}}"/> <argument name="label" value="{{defaultOrderStatus.label}}"/> </actionGroup> + <!--Verify the order status grid page shows the updated order status and verify AssertOrderStatusNotAssigned--> <dontSee selector="{{AdminOrderStatusGridSection.stateCodeAndTitleDataColumn}}" stepKey="seeEmptyStateCodeAndTitleValue"/> <dontSee selector="{{AdminOrderStatusGridSection.unassign}}" stepKey="seeAssertOrderStatusNotAssigned"/> </test> -</tests> \ No newline at end of file +</tests> From c6b1e108a16a41db59ac2ead340c7089a1c7ca2e Mon Sep 17 00:00:00 2001 From: Kevin Kozan <kkozan@magento.com> Date: Wed, 1 May 2019 15:22:06 -0500 Subject: [PATCH 153/224] MQE-1532: Bump MFTF version in Magento - Flaky test fix (cherry picked from commit a445230) --- ...rtStorefrontShoppingCartSummaryWithShippingActionGroup.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml index 5eb3de3a1af82..dcb683a50125d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml @@ -13,8 +13,6 @@ </arguments> <waitForLoadingMaskToDisappear stepKey="waitForMaskToDisappear" after="assertSubtotal"/> <waitForElementVisible selector="{{CheckoutCartSummarySection.shipping}}" time="60" stepKey="waitForElementToBeVisible" after="waitForMaskToDisappear"/> - <!-- Shipping can take a long time to change in builds, can't rely on an explicit wait--> - <wait time="30" stepKey="waitForShippingDetailsToLoad" after="waitForElementToBeVisible"/> - <see userInput="{{shipping}}" selector="{{CheckoutCartSummarySection.shipping}}" stepKey="assertShipping" after="waitForShippingDetailsToLoad" /> + <waitForText userInput="{{shipping}}" selector="{{CheckoutCartSummarySection.shipping}}" time="60" stepKey="assertShipping" after="waitForElementToBeVisible"/> </actionGroup> </actionGroups> From cf119bec073ba75239d72a3f737097d4f6a0aa28 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Sat, 4 May 2019 01:11:04 +0300 Subject: [PATCH 154/224] 387-Test coverage of getting IDs of CMS page/blocks by GraphQL API --- .../Model/Resolver/DataProvider/Page.php | 84 +++++++++++-- .../DataProvider/PageDataProvider.php | 110 ------------------ .../CmsGraphQl/Model/Resolver/Page.php | 30 +++-- 3 files changed, 90 insertions(+), 134 deletions(-) delete mode 100644 app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php index 2cee9e8e9e44c..a9513b1a24932 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php @@ -8,22 +8,21 @@ namespace Magento\CmsGraphQl\Model\Resolver\DataProvider; use Magento\Cms\Api\Data\PageInterface; +use Magento\Cms\Api\GetPageByIdentifierInterface; use Magento\Cms\Api\PageRepositoryInterface; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Store\Model\StoreManagerInterface; use Magento\Widget\Model\Template\FilterEmulate; /** - * @deprecated - * @see Magento\CmsGraphQl\Model\Resolver\DataProvider\PageDataProvider - * * Cms page data provider */ class Page { /** - * @var FilterEmulate + * @var GetPageByIdentifierInterface */ - private $widgetFilter; + private $pageByIdentifier; /** * @var PageRepositoryInterface @@ -31,18 +30,37 @@ class Page private $pageRepository; /** - * @param PageRepositoryInterface $pageRepository + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var FilterEmulate + */ + private $widgetFilter; + + /** + * @param GetPageByIdentifierInterface $getPageByIdentifier * @param FilterEmulate $widgetFilter + * @param PageRepositoryInterface $pageRepository + * @param StoreManagerInterface $storeManager */ public function __construct( + GetPageByIdentifierInterface $getPageByIdentifier, + FilterEmulate $widgetFilter, PageRepositoryInterface $pageRepository, - FilterEmulate $widgetFilter + StoreManagerInterface $storeManager ) { + $this->pageByIdentifier = $getPageByIdentifier; $this->pageRepository = $pageRepository; + $this->storeManager = $storeManager; $this->widgetFilter = $widgetFilter; } /** + * @deprecated + * @see getDataByPageId(int $pageId) + * * Get the page data * * @param int $pageId @@ -72,4 +90,56 @@ public function getData(int $pageId): array ]; return $pageData; } + + /** + * @param int $pageId + * @return array + * @throws NoSuchEntityException + */ + public function getDataByPageId(int $pageId): array + { + $page = $this->pageRepository->getById($pageId); + + return $this->convertPageData($page); + } + + /** + * @param string $pageIdentifier + * @return array + * @throws NoSuchEntityException + */ + public function getDataByPageIdentifier(string $pageIdentifier): array + { + $storeId = (int)$this->storeManager->getStore()->getId(); + $page = $this->pageByIdentifier->execute($pageIdentifier, $storeId); + + return $this->convertPageData($page); + } + + /** + * @param PageInterface $page + * @return array + * @throws NoSuchEntityException + */ + private function convertPageData(PageInterface $page) + { + if (false === $page->isActive()) { + throw new NoSuchEntityException(); + } + + $renderedContent = $this->widgetFilter->filter($page->getContent()); + + $pageData = [ + 'url_key' => $page->getIdentifier(), + PageInterface::IDENTIFIER => $page->getIdentifier(), + PageInterface::TITLE => $page->getTitle(), + PageInterface::CONTENT => $renderedContent, + PageInterface::CONTENT_HEADING => $page->getContentHeading(), + PageInterface::PAGE_LAYOUT => $page->getPageLayout(), + PageInterface::META_TITLE => $page->getMetaTitle(), + PageInterface::META_DESCRIPTION => $page->getMetaDescription(), + PageInterface::META_KEYWORDS => $page->getMetaKeywords(), + ]; + return $pageData; + } } diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php deleted file mode 100644 index 47fa4c08a9c31..0000000000000 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/PageDataProvider.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\CmsGraphQl\Model\Resolver\DataProvider; - -use Magento\Cms\Api\Data\PageInterface; -use Magento\Cms\Api\GetPageByIdentifierInterface; -use Magento\Cms\Api\PageRepositoryInterface; -use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Store\Model\StoreManagerInterface; -use Magento\Widget\Model\Template\FilterEmulate; - -/** - * Cms page data provider - */ -class PageDataProvider -{ - /** - * @var GetPageByIdentifierInterface - */ - private $pageByIdentifier; - - /** - * @var PageRepositoryInterface - */ - private $pageRepository; - - /** - * @var StoreManagerInterface - */ - private $storeManager; - - /** - * @var FilterEmulate - */ - private $widgetFilter; - - /** - * @param GetPageByIdentifierInterface $getPageByIdentifier - * @param FilterEmulate $widgetFilter - * @param PageRepositoryInterface $pageRepository - * @param StoreManagerInterface $storeManager - */ - public function __construct( - GetPageByIdentifierInterface $getPageByIdentifier, - FilterEmulate $widgetFilter, - PageRepositoryInterface $pageRepository, - StoreManagerInterface $storeManager - ) { - $this->pageByIdentifier = $getPageByIdentifier; - $this->pageRepository = $pageRepository; - $this->storeManager = $storeManager; - $this->widgetFilter = $widgetFilter; - } - - /** - * @param int $pageId - * @return array - * @throws NoSuchEntityException - */ - public function getDataByPageId(int $pageId): array - { - $page = $this->pageRepository->getById($pageId); - - return $this->convertPageData($page); - } - - /** - * @param string $pageIdentifier - * @return array - */ - public function getDataByPageIdentifier(string $pageIdentifier): array - { - $storeId = (int)$this->storeManager->getStore()->getId(); - $page = $this->pageByIdentifier->execute($pageIdentifier, $storeId); - - return $this->convertPageData($page); - } - - /** - * @param PageInterface $page - * @return array - * @throws NoSuchEntityException - */ - private function convertPageData(PageInterface $page) - { - if (false === $page->isActive()) { - throw new NoSuchEntityException(); - } - - $renderedContent = $this->widgetFilter->filter($page->getContent()); - - $pageData = [ - 'url_key' => $page->getIdentifier(), - PageInterface::IDENTIFIER => $page->getIdentifier(), - PageInterface::TITLE => $page->getTitle(), - PageInterface::CONTENT => $renderedContent, - PageInterface::CONTENT_HEADING => $page->getContentHeading(), - PageInterface::PAGE_LAYOUT => $page->getPageLayout(), - PageInterface::META_TITLE => $page->getMetaTitle(), - PageInterface::META_DESCRIPTION => $page->getMetaDescription(), - PageInterface::META_KEYWORDS => $page->getMetaKeywords(), - ]; - return $pageData; - } -} diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php index 544a09c780070..489a3e0a75c80 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php @@ -7,7 +7,7 @@ namespace Magento\CmsGraphQl\Model\Resolver; -use Magento\CmsGraphQl\Model\Resolver\DataProvider\PageDataProvider as PageDataProvider; +use Magento\CmsGraphQl\Model\Resolver\DataProvider\Page as PageDataProvider; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Exception\GraphQlInputException; @@ -49,10 +49,16 @@ public function resolve( throw new GraphQlInputException(__('"Page id/identifier should be specified')); } - if (isset($args['id'])) { - $pageData = $this->getPageDataById($this->getPageId($args)); - } elseif (isset($args['identifier'])) { - $pageData = $this->getPageDataByIdentifier($this->getPageIdentifier($args)); + $pageData = []; + + try { + if (isset($args['id'])) { + $pageData = $this->getPageDataById($this->getPageId($args)); + } elseif (isset($args['identifier'])) { + $pageData = $this->getPageDataByIdentifier($this->getPageIdentifier($args)); + } + } catch (NoSuchEntityException $e) { + throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); } return $pageData; @@ -83,12 +89,7 @@ private function getPageIdentifier(array $args): string */ private function getPageDataById(int $pageId): array { - try { - $pageData = $this->pageDataProvider->getDataByPageId($pageId); - } catch (NoSuchEntityException $e) { - throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); - } - return $pageData; + return $this->pageDataProvider->getDataByPageId($pageId); } /** @@ -98,11 +99,6 @@ private function getPageDataById(int $pageId): array */ private function getPageDataByIdentifier(string $pageIdentifier): array { - try { - $pageData = $this->pageDataProvider->getDataByPageIdentifier($pageIdentifier); - } catch (NoSuchEntityException $e) { - throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); - } - return $pageData; + return $this->pageDataProvider->getDataByPageIdentifier($pageIdentifier); } } From ff658b515ba18f6579e692935e195ad5d3cba99b Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Sat, 4 May 2019 01:18:19 +0300 Subject: [PATCH 155/224] 387-Test coverage of getting IDs of CMS page/blocks by GraphQL API --- app/code/Magento/CmsGraphQl/etc/schema.graphqls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CmsGraphQl/etc/schema.graphqls b/app/code/Magento/CmsGraphQl/etc/schema.graphqls index 26689c5d4c91d..3558d853aa4df 100644 --- a/app/code/Magento/CmsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CmsGraphQl/etc/schema.graphqls @@ -12,7 +12,7 @@ type StoreConfig @doc(description: "The type contains information about a store type Query { cmsPage ( - id: Int @doc(description: "Id of the CMS page") @deprecated(reason: "Use `identifier`") @doc(description: "The CMS page query returns information about a CMS page") + id: Int @doc(description: "Id of the CMS page") @deprecated(reason: "The `id` is deprecated. Use `identifier` instead.") @doc(description: "The CMS page query returns information about a CMS page") identifier: String @doc(description: "Identifier of the CMS page") ): CmsPage @resolver(class: "Magento\\CmsGraphQl\\Model\\Resolver\\Page") @doc(description: "The CMS page query returns information about a CMS page") @cache(cacheTag: "cms_p", cacheIdentity: "Magento\\CmsGraphQl\\Model\\Resolver\\Page\\Identity") cmsBlocks ( From df3047bfc17f96ce37f0f9106dcf1b4eed2b5790 Mon Sep 17 00:00:00 2001 From: Vishal Sutariya <vishalsutariya7037@gmail.com> Date: Sat, 4 May 2019 11:04:41 +0530 Subject: [PATCH 156/224] Fixed typo issue and added missing header in customer sales order grid --- app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Orders.php | 4 ++-- app/code/Magento/Customer/i18n/en_US.csv | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Orders.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Orders.php index 2fb59ec767e8a..3d4ccb789dc72 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Orders.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/Orders.php @@ -107,7 +107,7 @@ protected function _prepareCollection() */ protected function _prepareColumns() { - $this->addColumn('increment_id', ['header' => __('Order'), 'width' => '100', 'index' => 'increment_id']); + $this->addColumn('increment_id', ['header' => __('Order #'), 'width' => '100', 'index' => 'increment_id']); $this->addColumn( 'created_at', @@ -140,7 +140,7 @@ protected function _prepareColumns() $this->addColumn( 'action', [ - 'header' => ' ', + 'header' => 'Action', 'filter' => false, 'sortable' => false, 'width' => '100px', diff --git a/app/code/Magento/Customer/i18n/en_US.csv b/app/code/Magento/Customer/i18n/en_US.csv index 578267984f985..e1c68f3d81e9d 100644 --- a/app/code/Magento/Customer/i18n/en_US.csv +++ b/app/code/Magento/Customer/i18n/en_US.csv @@ -47,7 +47,7 @@ Sending,Sending Paused,Paused View,View Unknown,Unknown -Order,Order +"Order #","Order #" Purchased,Purchased "Bill-to Name","Bill-to Name" "Ship-to Name","Ship-to Name" From 4927b5dc037ab34260c081ea97d2cb8b1557e96a Mon Sep 17 00:00:00 2001 From: Arvinda kumar <arvindakumar@cedcommerce.com> Date: Sat, 4 May 2019 11:23:36 +0530 Subject: [PATCH 157/224] Issue fixed #22636 Issue fixed #22636 --- .../web/css/source/module/main/_collapsible-blocks.less | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less index dec35d1364836..13b0b9bd525e2 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less @@ -105,11 +105,17 @@ // .admin__collapsible-block-wrapper { + .admin__collapsible-title[aria-expanded="true"]{ + &:before { + content: @icon-expand-close__content; + } + } + .__collapsible-block-wrapper-pattern(); .admin__collapsible-title { .__collapsible-title-pattern(); } - + &.opened, &._show { > .fieldset-wrapper-title { From 1ae8bf536dc6174e5d810ef7c82864b6134cf376 Mon Sep 17 00:00:00 2001 From: Arvinda kumar <arvindakumar@cedcommerce.com> Date: Sat, 4 May 2019 12:32:40 +0530 Subject: [PATCH 158/224] issue #22647 fixed issue #22647 fixed --- .../Magento/luma/Magento_Theme/web/css/source/_module.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less index dfcc51e0a0a26..b841f2206e1d9 100644 --- a/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Theme/web/css/source/_module.less @@ -80,7 +80,7 @@ .page-main { > .page-title-wrapper { .page-title { - word-break: break-all; + hyphens: auto; } } } From 3555b2614b8db3124751007b473a4d46f7ea123a Mon Sep 17 00:00:00 2001 From: Arvinda kumar <arvindakumar@cedcommerce.com> Date: Sat, 4 May 2019 12:48:32 +0530 Subject: [PATCH 159/224] _collapsible-blocks.less updated _collapsible-blocks.less updated --- .../web/css/source/module/main/_collapsible-blocks.less | 1 - 1 file changed, 1 deletion(-) diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less index 13b0b9bd525e2..6ca7614dfa883 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less @@ -115,7 +115,6 @@ .admin__collapsible-title { .__collapsible-title-pattern(); } - &.opened, &._show { > .fieldset-wrapper-title { From 86402dc9733a4a311efe42a407ca91da6a179d17 Mon Sep 17 00:00:00 2001 From: Uttam Mishra <uttamprakashmishra@cedcommerce.com> Date: Sat, 4 May 2019 13:14:37 +0530 Subject: [PATCH 160/224] Fixed Typo Error Fixed Typo Error in css --- lib/web/css/docs/source/_rating.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/css/docs/source/_rating.less b/lib/web/css/docs/source/_rating.less index 88de27b24cb87..6f7ec12b77bff 100644 --- a/lib/web/css/docs/source/_rating.less +++ b/lib/web/css/docs/source/_rating.less @@ -236,7 +236,7 @@ // # Accessible rating with vote // -// The following markup corresponds to **accesibility** demands +// The following markup corresponds to **accessibility** demands // ``` html // <fieldset class="exapmle-ratings-5 fieldset ratings vote"> // <legend>How do you rate this product?</legend> From 7644b971089569516264830e83a5e1f1de1760f9 Mon Sep 17 00:00:00 2001 From: Jitendra Kumar Singh <jitendrakumarsingh@cedcommerce.com> Date: Sat, 4 May 2019 14:04:13 +0530 Subject: [PATCH 161/224] Fixed Typo Issue Fixed Typo Issue --- .../view/adminhtml/templates/order/create/form/account.phtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/account.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/account.phtml index 0d2ee1f24d5b3..21f517bcee78e 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/account.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/account.phtml @@ -9,12 +9,12 @@ <span class="title"><?= /* @escapeNotVerified */ $block->getHeaderText() ?></span> <div class="actions"></div> </div> -<div id="customer_account_fieds" class="admin__page-section-content"> +<div id="customer_account_fields" class="admin__page-section-content"> <?= $block->getForm()->getHtml() ?> </div> <script> require(["prototype", "Magento_Sales/order/create/form"], function(){ - order.accountFieldsBind($('customer_account_fieds')); + order.accountFieldsBind($('customer_account_fields')); }); </script> From 5e7123e5101d43008f92fc62c70996a9a3a0ec95 Mon Sep 17 00:00:00 2001 From: Jitendra Kumar Singh <jitendrakumarsingh@cedcommerce.com> Date: Sat, 4 May 2019 14:10:35 +0530 Subject: [PATCH 162/224] Fixed Typo Issue Fixed Typo Issue --- .../Catalog/Block/Product/View/Options/AbstractOptions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php b/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php index 059580b9b5eae..c0a271a0e229c 100644 --- a/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php +++ b/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php @@ -15,7 +15,7 @@ use Magento\Catalog\Pricing\Price\CustomOptionPriceInterface; /** - * Product aoptions section abstract block. + * Product options section abstract block. * * @api * @since 100.0.2 From 6d2e1bb305d781567cfdcf38e34a2ea90a234adc Mon Sep 17 00:00:00 2001 From: Jitendra Kumar Singh <jitendrakumarsingh@cedcommerce.com> Date: Sat, 4 May 2019 14:14:54 +0530 Subject: [PATCH 163/224] Fixed Typo Issue Fixed Typo Issue --- .../Magento/Reports/Model/Product/Index/AbstractIndex.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php b/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php index 7337286149cc3..ceb25997a05fc 100644 --- a/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php +++ b/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php @@ -156,7 +156,7 @@ public function getStoreId() } /** - * On customer loggin merge visitor/customer index + * On customer login merge visitor/customer index * * @return $this */ @@ -230,7 +230,7 @@ public function getCount() $this->calculate(); } - return $this->_getSession()->getData($this->_countCacheKey); + return $this->_getSession()->getData($this->_countCacheKey);app } /** From a1b3aefcbfa386e7caef77e4aabce46693cd5c8d Mon Sep 17 00:00:00 2001 From: Jitendra Kumar Singh <jitendrakumarsingh@cedcommerce.com> Date: Sat, 4 May 2019 14:23:34 +0530 Subject: [PATCH 164/224] Fixed Typo Issue Fixed Typo Issue --- .../Magento/Paypal/Test/Unit/Model/AbstractConfigTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Paypal/Test/Unit/Model/AbstractConfigTest.php b/app/code/Magento/Paypal/Test/Unit/Model/AbstractConfigTest.php index 6bb2173e06f8d..7c528e5718c3b 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/AbstractConfigTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/AbstractConfigTest.php @@ -109,8 +109,8 @@ public function testGetValue($key, $method, $returnMap, $expectedValue) /** * - * @case #1 This conf parameters must return AbstractConfig::PAYMENT_ACTION_SALE (isWppApiAvailabe == false) - * @case #2 This conf parameters must return configValue (isWppApiAvailabe == true) + * @case #1 This conf parameters must return AbstractConfig::PAYMENT_ACTION_SALE (isWppApiAvailable == false) + * @case #2 This conf parameters must return configValue (isWppApiAvailable == true) * @case #3 This conf parameters must return configValue ($key != 'payment_action') * @case #4 This conf parameters must return configValue (configValue == 'Sale') * @case #5 This conf parameters must return configValue (shouldUseUnilateralPayments == false) From e73f0dd2f5ebb116813a637a47fa369c2bd16f5a Mon Sep 17 00:00:00 2001 From: Jitendra Kumar Singh <jitendrakumarsingh@cedcommerce.com> Date: Sat, 4 May 2019 15:47:23 +0530 Subject: [PATCH 165/224] Fixed Typo Issue Fixed Typo Issue --- .../Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php index 9e13e9424d1fd..50d29c195968c 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php @@ -8,7 +8,7 @@ use Magento\Framework\Pricing\PriceCurrencyInterface; /** - * Credit memo adjustmets block + * Credit memo adjustments block * * @api * @since 100.0.2 From 1b8e2a4d404d3a92fa9f665c2c07c1219dbc7e32 Mon Sep 17 00:00:00 2001 From: Jitendra Kumar Singh <jitendrakumarsingh@cedcommerce.com> Date: Sat, 4 May 2019 16:02:25 +0530 Subject: [PATCH 166/224] Fixed Typo Issue Fixed Typo Issue --- .../Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml index 8fea72764f280..fa5e8a616787b 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml @@ -49,7 +49,7 @@ <waitForLoadingMaskToDisappear stepKey="waitForPageLoad3"/> <!--see Insert Variable button disabled--> <see selector="{{VariableSection.InsertVariableBtnDisabled}}" userInput="Insert Variable" stepKey="seeInsertWidgetDisabled" /> - <!--see Cancel button enabed--> + <!--see Cancel button enabled--> <see selector="{{VariableSection.CancelBtnEnabled}}" userInput="Cancel" stepKey="seeCancelBtnEnabled" /> <!--see 4 colums--> <see selector="{{VariableSection.ColName('Select')}}" userInput="Select" stepKey="selectCol" /> From 049c36d99ae8691237bda96fe39fc3efead8f104 Mon Sep 17 00:00:00 2001 From: Jitendra Kumar Singh <jitendrakumarsingh@cedcommerce.com> Date: Sat, 4 May 2019 16:14:42 +0530 Subject: [PATCH 167/224] Fixed Typo Issue Fixed Typo Issue --- .../Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGCMSTest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGCMSTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGCMSTest.xml index 9e5eb2558d6f2..3b501859e606e 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGCMSTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGCMSTest.xml @@ -43,9 +43,9 @@ <waitForText userInput="Insert Variable" stepKey="waitForSlideOutOpen"/> <!--see Insert Variable button disabled--> <see selector="{{VariableSection.InsertVariableBtnDisabled}}" userInput="Insert Variable" stepKey="seeInsertWidgetDisabled" /> - <!--see Cancel button enabed--> + <!--see Cancel button enabled--> <see selector="{{VariableSection.CancelBtnEnabled}}" userInput="Cancel" stepKey="seeCancelBtnEnabled" /> - <!--see 4 colums--> + <!--see 4 columns--> <see selector="{{VariableSection.ColName('Select')}}" userInput="Select" stepKey="selectCol" /> <see selector="{{VariableSection.ColName('Variable Name')}}" userInput="Variable Name" stepKey="variableCol" /> <see selector="{{VariableSection.ColName('Type')}}" userInput="Type" stepKey="typeCol" /> From fd8d452d4a4cd48d039184cc485f3bf68316347c Mon Sep 17 00:00:00 2001 From: Jitendra Kumar Singh <jitendrakumarsingh@cedcommerce.com> Date: Sat, 4 May 2019 16:19:55 +0530 Subject: [PATCH 168/224] Fixed Typo Issue Fixed Typo Issue --- .../Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml index e3d73fb57333e..841d202d518ab 100644 --- a/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml +++ b/app/code/Magento/Newsletter/Test/Mftf/Test/AdminAddVariableToWYSIWYGNewsletterTest.xml @@ -49,9 +49,9 @@ <waitForLoadingMaskToDisappear stepKey="waitForPageLoad3"/> <!--see Insert Variable button disabled--> <see selector="{{VariableSection.InsertVariableBtnDisabled}}" userInput="Insert Variable" stepKey="seeInsertWidgetDisabled" /> - <!--see Cancel button enabed--> + <!--see Cancel button enabled--> <see selector="{{VariableSection.CancelBtnEnabled}}" userInput="Cancel" stepKey="seeCancelBtnEnabled" /> - <!--see 4 colums--> + <!--see 4 columns--> <see selector="{{VariableSection.ColName('Select')}}" userInput="Select" stepKey="selectCol" /> <see selector="{{VariableSection.ColName('Variable Name')}}" userInput="Variable Name" stepKey="variableCol" /> <see selector="{{VariableSection.ColName('Type')}}" userInput="Type" stepKey="typeCol" /> From ffeaa5bc229af2ae6ce6e2cdb6b517ec03e535b0 Mon Sep 17 00:00:00 2001 From: Jitendra Kumar Singh <jitendrakumarsingh@cedcommerce.com> Date: Sat, 4 May 2019 16:27:02 +0530 Subject: [PATCH 169/224] Fixed Typo Issue Fixed Typo Issue --- .../AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml index 393e25e474f12..8b18c4eaef5db 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogCategoryLinkTypeTest.xml @@ -37,7 +37,7 @@ <see userInput="Inserting a widget does not create a widget instance." stepKey="seeMessage" /> <!--see Insert Widget button disabled--> <see selector="{{WidgetSection.InsertWidgetBtnDisabled}}" userInput="Insert Widget" stepKey="seeInsertWidgetDisabled" /> - <!--see Cancel button enabed--> + <!--see Cancel button enabled--> <see selector="{{WidgetSection.CancelBtnEnabled}}" userInput="Cancel" stepKey="seeCancelBtnEnabled" /> <!--Select "Widget Type"--> <selectOption selector="{{WidgetSection.WidgetType}}" userInput="Catalog Category Link" stepKey="selectCatalogCategoryLink" /> From 5a18e50dedd5c273f05c835b882be4a11ebfc77d Mon Sep 17 00:00:00 2001 From: Jitendra Kumar Singh <jitendrakumarsingh@cedcommerce.com> Date: Sat, 4 May 2019 16:31:22 +0530 Subject: [PATCH 170/224] Fixed Typo Issue Fixed Typo Issue --- .../AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml index 9ee9d27de477a..fc4accf211577 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddWidgetToWYSIWYGWithCatalogProductLinkTypeTest.xml @@ -41,7 +41,7 @@ <waitForPageLoad stepKey="wait3"/> <!--see Insert Widget button disabled--> <see selector="{{WidgetSection.InsertWidgetBtnDisabled}}" userInput="Insert Widget" stepKey="seeInsertWidgetDisabled" /> - <!--see Cancel button enabed--> + <!--see Cancel button enabled--> <see selector="{{WidgetSection.CancelBtnEnabled}}" userInput="Cancel" stepKey="seeCancelBtnEnabled" /> <!--Select "Widget Type"--> <selectOption selector="{{WidgetSection.WidgetType}}" userInput="Catalog Product Link" stepKey="selectCatalogProductLink" /> From fbcfd11559def0891e829746a75ff5df2db438ee Mon Sep 17 00:00:00 2001 From: Satya Prakash <p.satyaprakash.viet.2009@gmail.com> Date: Sat, 4 May 2019 16:41:52 +0530 Subject: [PATCH 171/224] Fixed:#22395 Fixed #22395: config:set -le and -lc short form options don't work --- app/code/Magento/Config/Console/Command/ConfigSetCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Config/Console/Command/ConfigSetCommand.php b/app/code/Magento/Config/Console/Command/ConfigSetCommand.php index cb79daddbf5f9..2e76e717ba36b 100644 --- a/app/code/Magento/Config/Console/Command/ConfigSetCommand.php +++ b/app/code/Magento/Config/Console/Command/ConfigSetCommand.php @@ -114,13 +114,13 @@ protected function configure() ), new InputOption( static::OPTION_LOCK_ENV, - 'le', + 'e', InputOption::VALUE_NONE, 'Lock value which prevents modification in the Admin (will be saved in app/etc/env.php)' ), new InputOption( static::OPTION_LOCK_CONFIG, - 'lc', + 'c', InputOption::VALUE_NONE, 'Lock and share value with other installations, prevents modification in the Admin ' . '(will be saved in app/etc/config.php)' From 848d21b61ca7fb4685fd908ff5a6e90320033ed5 Mon Sep 17 00:00:00 2001 From: Jitendra Kumar Singh <jitendrakumarsingh@cedcommerce.com> Date: Sat, 4 May 2019 16:44:16 +0530 Subject: [PATCH 172/224] Fixed Typo Issue Fixed Typo Issue --- .../Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryTest.xml index 8806612c0f5de..15171fe3713c3 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCreateCategoryTest.xml @@ -96,7 +96,7 @@ <click selector="{{AdminCategoryMainActionsSection.SaveButton}}" stepKey="saveCategory"/> <see selector="{{AdminCategoryBasicFieldSection.FieldError('uid')}}" userInput="This is a required field." stepKey="seeErrorMessage"/> <!-- Verify that the Layered navigation price step field has the required indicator --> - <comment userInput="Check if Layered navigation price field has required indictor icon" stepKey="comment" /> + <comment userInput="Check if Layered navigation price field has required indicator icon" stepKey="comment" /> <executeJS function="{{CategoryDisplaySettingsSection.RequiredFieldIndicator('filter_price_range')}}" stepKey="getRequiredFieldIndicator"/> <assertEquals expected='"*"' expectedType="string" actualType="variable" actual="getRequiredFieldIndicator" message="pass" stepKey="assertRequiredFieldIndicator1"/> </test> From ba1e125f2fe09a777e2cb7810e4b88b42d3ed266 Mon Sep 17 00:00:00 2001 From: Jitendra Kumar Singh <jitendrakumarsingh@cedcommerce.com> Date: Sat, 4 May 2019 17:15:49 +0530 Subject: [PATCH 173/224] Fixed Typo Issue Fixed Typo Issue --- .../Model/ResourceModel/Product/Type/Configurable/Attribute.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute.php index e93c44893bf58..cdbee21573e10 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute.php +++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute.php @@ -52,7 +52,7 @@ public function __construct( } /** - * Inititalize connection and define tables + * Initialize connection and define tables * * @return void */ From 1f4e759290e0d8e689d709f2b874bf35b01ac4cf Mon Sep 17 00:00:00 2001 From: Jitendra Kumar Singh <jitendrakumarsingh@cedcommerce.com> Date: Sat, 4 May 2019 17:20:52 +0530 Subject: [PATCH 174/224] Fixed Typo Issue Fixed Typo Issue --- .../Adminhtml/Product/Initialization/Helper/AttributeFilter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php index 188b0b22f33bf..6d201c7999968 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php @@ -73,7 +73,7 @@ private function prepareDefaultData(array $attributeList, string $attributeCode, /** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute */ $attribute = $attributeList[$attributeCode]; $attributeType = $attribute->getBackendType(); - // For non-numberic types set the attributeValue to 'false' to trigger their removal from the db + // For non-numeric types set the attributeValue to 'false' to trigger their removal from the db if ($attributeType === 'varchar' || $attributeType === 'text' || $attributeType === 'datetime') { $attribute->setIsRequired(false); $productData[$attributeCode] = false; From bed47263a81cd266c8ddc179e545b429ddd0d09b Mon Sep 17 00:00:00 2001 From: Pieter Hoste <hoste.pieter@gmail.com> Date: Sat, 4 May 2019 21:43:01 +0200 Subject: [PATCH 175/224] Ignores allure-results in git. --- dev/tests/integration/.gitignore | 1 + dev/tests/static/.gitignore | 8 +++++--- dev/tests/unit/.gitignore | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/dev/tests/integration/.gitignore b/dev/tests/integration/.gitignore index 7f8540b3c7710..c4d6c1a77a9cc 100644 --- a/dev/tests/integration/.gitignore +++ b/dev/tests/integration/.gitignore @@ -2,3 +2,4 @@ !/etc/integration-tests-config.xml /var/ /etc/*.php +/framework/tests/unit/var/allure-results/ diff --git a/dev/tests/static/.gitignore b/dev/tests/static/.gitignore index 651969a59ce46..175be896e8def 100644 --- a/dev/tests/static/.gitignore +++ b/dev/tests/static/.gitignore @@ -1,4 +1,6 @@ /*.xml -framework/tests/unit/*.xml -report/ -tmp/ +/framework/tests/unit/*.xml +/framework/tests/unit/var/allure-results/ +/report/ +/tmp/ +/var/allure-results/ diff --git a/dev/tests/unit/.gitignore b/dev/tests/unit/.gitignore index 319b3826f9338..944850d16608e 100644 --- a/dev/tests/unit/.gitignore +++ b/dev/tests/unit/.gitignore @@ -1 +1,2 @@ /phpunit.xml +/var/allure-results/ From 6d46c58234c34528cec2004943f241e8b47118ab Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Sun, 5 May 2019 16:34:16 +0300 Subject: [PATCH 176/224] magento/magento2#22670 Fix typo --- app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php b/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php index ceb25997a05fc..5f69d8008db0a 100644 --- a/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php +++ b/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php @@ -230,7 +230,7 @@ public function getCount() $this->calculate(); } - return $this->_getSession()->getData($this->_countCacheKey);app + return $this->_getSession()->getData($this->_countCacheKey); } /** From c1d01288891574a3d44ca36691fd59375cde9003 Mon Sep 17 00:00:00 2001 From: Ihor Sviziev <ihor-sviziev@users.noreply.github.com> Date: Sun, 5 May 2019 16:44:35 +0300 Subject: [PATCH 177/224] magento/mmagento2#22729 Fox typo issues --- .../Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml index fa5e8a616787b..ce34a8d09c302 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminAddVariableToWYSIWYGBlockTest.xml @@ -51,7 +51,7 @@ <see selector="{{VariableSection.InsertVariableBtnDisabled}}" userInput="Insert Variable" stepKey="seeInsertWidgetDisabled" /> <!--see Cancel button enabled--> <see selector="{{VariableSection.CancelBtnEnabled}}" userInput="Cancel" stepKey="seeCancelBtnEnabled" /> - <!--see 4 colums--> + <!--see 4 columns--> <see selector="{{VariableSection.ColName('Select')}}" userInput="Select" stepKey="selectCol" /> <see selector="{{VariableSection.ColName('Variable Name')}}" userInput="Variable Name" stepKey="variableCol" /> <see selector="{{VariableSection.ColName('Type')}}" userInput="Type" stepKey="typeCol" /> From bd56e2f6943eb650e2734eebe230e874180aa6d5 Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Mon, 6 May 2019 09:57:37 +0300 Subject: [PATCH 178/224] magento/magento2#22558 static-test-fix --- .../testsuite/Magento/Quote/Model/Quote/AddressTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/Quote/AddressTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/Quote/AddressTest.php index d040f85545b40..545638bcb0c57 100644 --- a/dev/tests/integration/testsuite/Magento/Quote/Model/Quote/AddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/Quote/AddressTest.php @@ -31,6 +31,9 @@ class AddressTest extends \Magento\TestFramework\Indexer\TestCase /** @var \Magento\Framework\Reflection\DataObjectProcessor */ protected $dataProcessor; + /** + * phpcs:ignoreFile + */ public static function setUpBeforeClass() { $db = \Magento\TestFramework\Helper\Bootstrap::getInstance()->getBootstrap() @@ -343,7 +346,8 @@ public function testSaveShippingAddressWithEmptyRegionId() $customerAddress->setRegionId(0); $address = $this->dataProcessor->buildOutputDataArray( - $customerAddress, \Magento\Customer\Api\Data\AddressInterface::class + $customerAddress, + \Magento\Customer\Api\Data\AddressInterface::class ); $shippingAddress = $this->_quote->getShippingAddress(); From df69419c979109f6c99b3345d532b3ee95223653 Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Mon, 6 May 2019 11:47:48 +0300 Subject: [PATCH 179/224] Fix static tests. --- .../web/css/source/module/main/_collapsible-blocks.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less index 6ca7614dfa883..a43f9acbaa099 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less @@ -105,7 +105,7 @@ // .admin__collapsible-block-wrapper { - .admin__collapsible-title[aria-expanded="true"]{ + .admin__collapsible-title[aria-expanded='true'] { &:before { content: @icon-expand-close__content; } From aafe5d567c7113cb0275dd639e531576fb85d3ac Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Mon, 6 May 2019 12:53:15 +0300 Subject: [PATCH 180/224] magento/magento2#22628 static-test-fix refactoring on static-test result --- .../Sales/Model/Order/Pdf/AbstractPdf.php | 168 +++++++++++------- 1 file changed, 105 insertions(+), 63 deletions(-) diff --git a/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php b/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php index cc7c2768ead36..ab1d94ef7fabf 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php @@ -116,6 +116,11 @@ abstract public function getPdf(); */ protected $addressRenderer; + /** + * @var array $pageSettings + */ + private $pageSettings; + /** * @param \Magento\Payment\Helper\Data $paymentData * @param \Magento\Framework\Stdlib\StringUtils $string @@ -172,10 +177,12 @@ public function __construct( */ public function widthForStringUsingFontSize($string, $font, $fontSize) { + // phpcs:ignore Generic.PHP.NoSilencedErrors $drawingString = '"libiconv"' == ICONV_IMPL ? iconv( 'UTF-8', 'UTF-16BE//IGNORE', $string + // phpcs:ignore Generic.PHP.NoSilencedErrors ) : @iconv( 'UTF-8', 'UTF-16BE', @@ -183,7 +190,10 @@ public function widthForStringUsingFontSize($string, $font, $fontSize) ); $characters = []; - for ($i = 0; $i < strlen($drawingString); $i++) { + + $drawingStringLength = strlen($drawingString); + + for ($i = 0; $i < $drawingStringLength; $i++) { $characters[] = ord($drawingString[$i++]) << 8 | ord($drawingString[$i]); } $glyphs = $font->glyphNumbersForCharacters($characters); @@ -224,14 +234,14 @@ public function getAlignCenter($string, $x, $columnWidth, \Zend_Pdf_Resource_Fon $width = $this->widthForStringUsingFontSize($string, $font, $fontSize); return $x + round(($columnWidth - $width) / 2); } - /** * Insert logo to pdf page * - * @param \Zend_Pdf_Page &$page + * @param \Zend_Pdf_Page $page * @param string|null $store * @return void * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @throws \Zend_Pdf_Exception */ protected function insertLogo(&$page, $store = null) { @@ -283,7 +293,7 @@ protected function insertLogo(&$page, $store = null) /** * Insert address to pdf page * - * @param \Zend_Pdf_Page &$page + * @param \Zend_Pdf_Page $page * @param string|null $store * @return void */ @@ -364,9 +374,9 @@ protected function _calcAddressHeight($address) } /** - * Insert order to pdf page + * Insert order to pdf page. * - * @param \Zend_Pdf_Page &$page + * @param \Zend_Pdf_Page $page * @param \Magento\Sales\Model\Order $obj * @param bool $putOrderId * @return void @@ -964,9 +974,11 @@ public function newPage(array $settings = []) * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ public function drawLineBlocks(\Zend_Pdf_Page $page, array $draw, array $pageSettings = []) { + $this->pageSettings = $pageSettings; foreach ($draw as $itemsProp) { if (!isset($itemsProp['lines']) || !is_array($itemsProp['lines'])) { throw new \Magento\Framework\Exception\LocalizedException( @@ -975,7 +987,6 @@ public function drawLineBlocks(\Zend_Pdf_Page $page, array $draw, array $pageSet } $lines = $itemsProp['lines']; $height = isset($itemsProp['height']) ? $itemsProp['height'] : 10; - if (empty($itemsProp['shift'])) { $shift = 0; foreach ($lines as $line) { @@ -986,6 +997,7 @@ public function drawLineBlocks(\Zend_Pdf_Page $page, array $draw, array $pageSet $column['text'] = [$column['text']]; } $top = 0; + // foreach ($column['text'] as $part) { $top += $lineSpacing; } @@ -1000,69 +1012,99 @@ public function drawLineBlocks(\Zend_Pdf_Page $page, array $draw, array $pageSet if ($this->y - $itemsProp['shift'] < 15) { $page = $this->newPage($pageSettings); } + $this->correctLines($lines, $page, $height); + } - foreach ($lines as $line) { - $maxHeight = 0; - foreach ($line as $column) { - $fontSize = empty($column['font_size']) ? 10 : $column['font_size']; - if (!empty($column['font_file'])) { - $font = \Zend_Pdf_Font::fontWithPath($column['font_file']); - $page->setFont($font, $fontSize); - } else { - $fontStyle = empty($column['font']) ? 'regular' : $column['font']; - switch ($fontStyle) { - case 'bold': - $font = $this->_setFontBold($page, $fontSize); - break; - case 'italic': - $font = $this->_setFontItalic($page, $fontSize); - break; - default: - $font = $this->_setFontRegular($page, $fontSize); - break; - } - } - - if (!is_array($column['text'])) { - $column['text'] = [$column['text']]; - } - - $lineSpacing = !empty($column['height']) ? $column['height'] : $height; - $top = 0; - foreach ($column['text'] as $part) { - if ($this->y - $lineSpacing < 15) { - $page = $this->newPage($pageSettings); - } + return $page; + } - $feed = $column['feed']; - $textAlign = empty($column['align']) ? 'left' : $column['align']; - $width = empty($column['width']) ? 0 : $column['width']; - switch ($textAlign) { - case 'right': - if ($width) { - $feed = $this->getAlignRight($part, $feed, $width, $font, $fontSize); - } else { - $feed = $feed - $this->widthForStringUsingFontSize($part, $font, $fontSize); - } - break; - case 'center': - if ($width) { - $feed = $this->getAlignCenter($part, $feed, $width, $font, $fontSize); - } - break; - default: - break; - } - $page->drawText($part, $feed, $this->y - $top, 'UTF-8'); - $top += $lineSpacing; + /** + * Correct lines. + * + * @param array $lines + * @param \Zend_Pdf_Page $page + * @param int $height + * @throws \Zend_Pdf_Exception + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + private function correctLines($lines, $page, $height) :void + { + foreach ($lines as $line) { + $maxHeight = 0; + foreach ($line as $column) { + $fontSize = empty($column['font_size']) ? 10 : $column['font_size']; + if (!empty($column['font_file'])) { + $font = \Zend_Pdf_Font::fontWithPath($column['font_file']); + $page->setFont($font, $fontSize); + } else { + $fontStyle = empty($column['font']) ? 'regular' : $column['font']; + switch ($fontStyle) { + case 'bold': + $font = $this->_setFontBold($page, $fontSize); + break; + case 'italic': + $font = $this->_setFontItalic($page, $fontSize); + break; + default: + $font = $this->_setFontRegular($page, $fontSize); + break; } + } - $maxHeight = $top > $maxHeight ? $top : $maxHeight; + if (!is_array($column['text'])) { + $column['text'] = [$column['text']]; } - $this->y -= $maxHeight; + $top = $this->correctText($column, $height, $font, $page); + + $maxHeight = $top > $maxHeight ? $top : $maxHeight; } + $this->y -= $maxHeight; } + } - return $page; + /** + * Correct text. + * + * @param array $column + * @param int $height + * @param \Zend_Pdf_Resource_Font $font + * @param \Zend_Pdf_Page $page + * @throws \Zend_Pdf_Exception + * @return int + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + private function correctText($column, $height, $font, $page) :int + { + $top = 0; + $lineSpacing = !empty($column['height']) ? $column['height'] : $height; + $fontSize = empty($column['font_size']) ? 10 : $column['font_size']; + foreach ($column['text'] as $part) { + if ($this->y - $lineSpacing < 15) { + $page = $this->newPage($this->pageSettings); + } + + $feed = $column['feed']; + $textAlign = empty($column['align']) ? 'left' : $column['align']; + $width = empty($column['width']) ? 0 : $column['width']; + switch ($textAlign) { + case 'right': + if ($width) { + $feed = $this->getAlignRight($part, $feed, $width, $font, $fontSize); + } else { + $feed = $feed - $this->widthForStringUsingFontSize($part, $font, $fontSize); + } + break; + case 'center': + if ($width) { + $feed = $this->getAlignCenter($part, $feed, $width, $font, $fontSize); + } + break; + default: + break; + } + $page->drawText($part, $feed, $this->y - $top, 'UTF-8'); + $top += $lineSpacing; + } + return $top; } } From fed22e0af98c5571e65a30e05ef5c8c44dcb6b4a Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Mon, 6 May 2019 15:51:47 +0300 Subject: [PATCH 181/224] 387-Test coverage of getting IDs of CMS page/blocks by GraphQL API --- .../Model/Resolver/DataProvider/Page.php | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php index a9513b1a24932..a67cc877e7db8 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php @@ -10,6 +10,7 @@ use Magento\Cms\Api\Data\PageInterface; use Magento\Cms\Api\GetPageByIdentifierInterface; use Magento\Cms\Api\PageRepositoryInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Store\Model\StoreManagerInterface; use Magento\Widget\Model\Template\FilterEmulate; @@ -40,21 +41,22 @@ class Page private $widgetFilter; /** - * @param GetPageByIdentifierInterface $getPageByIdentifier - * @param FilterEmulate $widgetFilter * @param PageRepositoryInterface $pageRepository + * @param FilterEmulate $widgetFilter + * @param GetPageByIdentifierInterface $getPageByIdentifier * @param StoreManagerInterface $storeManager */ public function __construct( - GetPageByIdentifierInterface $getPageByIdentifier, - FilterEmulate $widgetFilter, PageRepositoryInterface $pageRepository, - StoreManagerInterface $storeManager + FilterEmulate $widgetFilter, + GetPageByIdentifierInterface $getPageByIdentifier = null, + StoreManagerInterface $storeManager = null ) { - $this->pageByIdentifier = $getPageByIdentifier; + $this->pageRepository = $pageRepository; - $this->storeManager = $storeManager; $this->widgetFilter = $widgetFilter; + $this->pageByIdentifier = $getPageByIdentifier ?: ObjectManager::getInstance()->get(GetPageByIdentifierInterface::class); + $this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(StoreManagerInterface::class); } /** @@ -75,23 +77,12 @@ public function getData(int $pageId): array throw new NoSuchEntityException(); } - $renderedContent = $this->widgetFilter->filter($page->getContent()); - - $pageData = [ - PageInterface::PAGE_ID => $page->getId(), - 'url_key' => $page->getIdentifier(), - PageInterface::TITLE => $page->getTitle(), - PageInterface::CONTENT => $renderedContent, - PageInterface::CONTENT_HEADING => $page->getContentHeading(), - PageInterface::PAGE_LAYOUT => $page->getPageLayout(), - PageInterface::META_TITLE => $page->getMetaTitle(), - PageInterface::META_DESCRIPTION => $page->getMetaDescription(), - PageInterface::META_KEYWORDS => $page->getMetaKeywords(), - ]; - return $pageData; + return $this->convertPageData($page); } /** + * Returns page data by page_id + * * @param int $pageId * @return array * @throws NoSuchEntityException @@ -100,10 +91,12 @@ public function getDataByPageId(int $pageId): array { $page = $this->pageRepository->getById($pageId); - return $this->convertPageData($page); + return $this->convertPageData($page, false, true); } /** + * Returns page data by page identifier + * * @param string $pageIdentifier * @return array * @throws NoSuchEntityException @@ -113,15 +106,17 @@ public function getDataByPageIdentifier(string $pageIdentifier): array $storeId = (int)$this->storeManager->getStore()->getId(); $page = $this->pageByIdentifier->execute($pageIdentifier, $storeId); - return $this->convertPageData($page); + return $this->convertPageData($page, false, true); } /** * @param PageInterface $page + * @param bool $includePageId + * @param bool $includePageIdentifier * @return array * @throws NoSuchEntityException */ - private function convertPageData(PageInterface $page) + private function convertPageData(PageInterface $page, $includePageId = true, $includePageIdentifier = false) { if (false === $page->isActive()) { throw new NoSuchEntityException(); @@ -131,7 +126,6 @@ private function convertPageData(PageInterface $page) $pageData = [ 'url_key' => $page->getIdentifier(), - PageInterface::IDENTIFIER => $page->getIdentifier(), PageInterface::TITLE => $page->getTitle(), PageInterface::CONTENT => $renderedContent, PageInterface::CONTENT_HEADING => $page->getContentHeading(), @@ -140,6 +134,15 @@ private function convertPageData(PageInterface $page) PageInterface::META_DESCRIPTION => $page->getMetaDescription(), PageInterface::META_KEYWORDS => $page->getMetaKeywords(), ]; + + if ($includePageId) { + $pageData[PageInterface::PAGE_ID] = $page->getId(); + } + + if ($includePageIdentifier) { + $pageData[PageInterface::IDENTIFIER] = $page->getIdentifier(); + } + return $pageData; } } From b4ea6b93496342a51430694f3f3ca7d82d50f746 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Mon, 6 May 2019 16:49:15 +0300 Subject: [PATCH 182/224] 387-Test coverage of getting IDs of CMS page/blocks by GraphQL API --- .../Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php index a67cc877e7db8..cfeecd402828e 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php @@ -72,11 +72,7 @@ public function __construct( public function getData(int $pageId): array { $page = $this->pageRepository->getById($pageId); - - if (false === $page->isActive()) { - throw new NoSuchEntityException(); - } - + return $this->convertPageData($page); } From 4ee64a57bbaaf8c4564c589b1c2f794869da8d74 Mon Sep 17 00:00:00 2001 From: Alex Taranovsky <firster@atwix.com> Date: Mon, 6 May 2019 16:56:42 +0300 Subject: [PATCH 183/224] 387-Test coverage of getting IDs of CMS page/blocks by GraphQL API --- .../CmsGraphQl/Model/Resolver/DataProvider/Page.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php index cfeecd402828e..2001bc006bbb8 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php @@ -10,7 +10,6 @@ use Magento\Cms\Api\Data\PageInterface; use Magento\Cms\Api\GetPageByIdentifierInterface; use Magento\Cms\Api\PageRepositoryInterface; -use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Store\Model\StoreManagerInterface; use Magento\Widget\Model\Template\FilterEmulate; @@ -49,14 +48,14 @@ class Page public function __construct( PageRepositoryInterface $pageRepository, FilterEmulate $widgetFilter, - GetPageByIdentifierInterface $getPageByIdentifier = null, - StoreManagerInterface $storeManager = null + GetPageByIdentifierInterface $getPageByIdentifier, + StoreManagerInterface $storeManager ) { $this->pageRepository = $pageRepository; $this->widgetFilter = $widgetFilter; - $this->pageByIdentifier = $getPageByIdentifier ?: ObjectManager::getInstance()->get(GetPageByIdentifierInterface::class); - $this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(StoreManagerInterface::class); + $this->pageByIdentifier = $getPageByIdentifier; + $this->storeManager = $storeManager; } /** @@ -72,7 +71,7 @@ public function __construct( public function getData(int $pageId): array { $page = $this->pageRepository->getById($pageId); - + return $this->convertPageData($page); } From 33e7ea7c3baca5c62cde8f8f8dbc33145d1d4d22 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Mon, 6 May 2019 09:29:46 -0500 Subject: [PATCH 184/224] MC-4764: Convert MoveProductsInComparedOnOrderPageTest to MFTF --- .../Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml index 3128db8272904..a01687990999e 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml @@ -13,6 +13,6 @@ <element name="productName" type="text" selector="#order-items_grid span[id*=order_item]"/> <element name="productPrice" type="text" selector=".even td[class=col-price] span[class=price]"/> <element name="productQty" type="input" selector="td[class=col-qty] input"/> - <element name="gridCell" type="text" selector="//div[@class='admin__table-wrapper']//tbody['{{row}}']//td[count(//tr[@class='headings']//th[contains(., '{{column}}')]/preceding-sibling::th) +1 ]" parameterized="true" timeout="30"/> + <element name="gridCell" type="text" selector="//div[contains(@id, 'order-items_grid')]//tbody[{{row}}]//td[count(//table[contains(@class, 'order-tables')]//th[contains(., '{{column}}')]/preceding-sibling::th) +1 ]" parameterized="true" timeout="30"/> </section> </sections> From aba963eef4bd0aad1094ca099265b52606994568 Mon Sep 17 00:00:00 2001 From: Serhii Balko <serhii.balko@transoftgroup.com> Date: Mon, 6 May 2019 17:41:15 +0300 Subject: [PATCH 185/224] MAGETWO-98832: Multistore Allowed Countries List Problem --- app/code/Magento/Customer/Model/AccountManagement.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 9a197a37fb483..8439a3f2308c2 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -565,6 +565,7 @@ public function authenticate($username, $password) } try { $this->getAuthentication()->authenticate($customerId, $password); + // phpcs:disable Magento2.Exceptions.ThrowCatch } catch (InvalidEmailOrPasswordException $e) { throw new InvalidEmailOrPasswordException(__('Invalid login or password.')); } @@ -905,6 +906,7 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash throw new InputMismatchException( __('A customer with the same email address already exists in an associated website.') ); + // phpcs:disable Magento2.Exceptions.ThrowCatch } catch (LocalizedException $e) { throw $e; } @@ -924,6 +926,7 @@ public function createAccountWithPasswordHash(CustomerInterface $customer, $hash } } $this->customerRegistry->remove($customer->getId()); + // phpcs:disable Magento2.Exceptions.ThrowCatch } catch (InputException $e) { $this->customerRepository->delete($customer); throw $e; @@ -1026,6 +1029,7 @@ private function changePasswordForCustomer($customer, $currentPassword, $newPass { try { $this->getAuthentication()->authenticate($customer->getId(), $currentPassword); + // phpcs:disable Magento2.Exceptions.ThrowCatch } catch (InvalidEmailOrPasswordException $e) { throw new InvalidEmailOrPasswordException( __("The password doesn't match this account. Verify the password and try again.") From f9828d098155fee264d44ce8bbbf0b8a2f456d0a Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Mon, 6 May 2019 09:48:20 -0500 Subject: [PATCH 186/224] MC-4765: Convert MoveLastOrderedProductsOnOrderPageTest to MFTF --- .../Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml index 3128db8272904..a01687990999e 100644 --- a/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml +++ b/app/code/Magento/Customer/Test/Mftf/Section/AdminCustomerCreateNewOrderSection.xml @@ -13,6 +13,6 @@ <element name="productName" type="text" selector="#order-items_grid span[id*=order_item]"/> <element name="productPrice" type="text" selector=".even td[class=col-price] span[class=price]"/> <element name="productQty" type="input" selector="td[class=col-qty] input"/> - <element name="gridCell" type="text" selector="//div[@class='admin__table-wrapper']//tbody['{{row}}']//td[count(//tr[@class='headings']//th[contains(., '{{column}}')]/preceding-sibling::th) +1 ]" parameterized="true" timeout="30"/> + <element name="gridCell" type="text" selector="//div[contains(@id, 'order-items_grid')]//tbody[{{row}}]//td[count(//table[contains(@class, 'order-tables')]//th[contains(., '{{column}}')]/preceding-sibling::th) +1 ]" parameterized="true" timeout="30"/> </section> </sections> From ff6ec5a2dd385182bbd9c4c2e02d9d287df50f63 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Mon, 6 May 2019 10:18:48 -0500 Subject: [PATCH 187/224] MC-4764: Convert MoveProductsInComparedOnOrderPageTest to MFTF fixed file name --- ....xml => MoveConfigurableProductsInComparedOnOrderPageTest.xml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/code/Magento/Sales/Test/Mftf/Test/{MoveCongigurableProductsInComparedOnOrderPageTest.xml => MoveConfigurableProductsInComparedOnOrderPageTest.xml} (100%) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/MoveCongigurableProductsInComparedOnOrderPageTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/MoveConfigurableProductsInComparedOnOrderPageTest.xml similarity index 100% rename from app/code/Magento/Sales/Test/Mftf/Test/MoveCongigurableProductsInComparedOnOrderPageTest.xml rename to app/code/Magento/Sales/Test/Mftf/Test/MoveConfigurableProductsInComparedOnOrderPageTest.xml From a12ecfd2885e84dfd9e4dc109fca0cdeb6b8e032 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi <horytsky@adobe.com> Date: Mon, 6 May 2019 12:21:35 -0500 Subject: [PATCH 188/224] MAGETWO-99451: Custom customer address attribute values are empty when address is changed in admin checkout --- .../Api/Test/Unit/ExtensibleDataObjectConverterTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/ExtensibleDataObjectConverterTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensibleDataObjectConverterTest.php index e362d652b7a13..08fad90fe2f29 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/ExtensibleDataObjectConverterTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensibleDataObjectConverterTest.php @@ -10,6 +10,9 @@ use Magento\Framework\Api\AbstractExtensibleObject; use Magento\Framework\Api\AttributeValue; +/** + * Class ExtensibleDataObjectConverterTest + */ class ExtensibleDataObjectConverterTest extends \PHPUnit\Framework\TestCase { /** @var \Magento\Framework\Api\ExtensibleDataObjectConverter */ From 62cbf5b9d9443cd4b2dbdbef18d188b58888124c Mon Sep 17 00:00:00 2001 From: Nazarn96 <nazarn96@gmail.com> Date: Tue, 7 May 2019 10:27:21 +0300 Subject: [PATCH 189/224] magento/magento2#22720 static-test-fix --- app/code/Magento/Config/Console/Command/ConfigSetCommand.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Config/Console/Command/ConfigSetCommand.php b/app/code/Magento/Config/Console/Command/ConfigSetCommand.php index 2e76e717ba36b..999d8e41af5bc 100644 --- a/app/code/Magento/Config/Console/Command/ConfigSetCommand.php +++ b/app/code/Magento/Config/Console/Command/ConfigSetCommand.php @@ -139,8 +139,10 @@ protected function configure() /** * Creates and run appropriate processor, depending on input options. * - * {@inheritdoc} + * @param InputInterface $input + * @param OutputInterface $output * @since 100.2.0 + * @return int|null */ protected function execute(InputInterface $input, OutputInterface $output) { From a7f3f979079cd2fb3b4478b50845e5011c378f07 Mon Sep 17 00:00:00 2001 From: Sergii Ivashchenko <serg.ivashchenko@gmail.com> Date: Tue, 7 May 2019 10:55:25 +0100 Subject: [PATCH 190/224] magento-engcom/magento2ce#2824: Fixed static tests --- app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php b/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php index ab1d94ef7fabf..1e4b8500f026d 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php @@ -14,6 +14,7 @@ * @api * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * phpcs:disable Magento2.Classes.AbstractApi * @since 100.0.2 */ abstract class AbstractPdf extends \Magento\Framework\DataObject From 152d8216e87c1f91fff266de78862d34fb57f771 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@adobe.com> Date: Tue, 7 May 2019 09:52:46 -0500 Subject: [PATCH 191/224] magento-engcom/magento2ce#2824: Suppressed phpcs warning --- app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php b/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php index 1e4b8500f026d..723940a5f67c0 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php @@ -11,10 +11,10 @@ /** * Sales Order PDF abstract model * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - * phpcs:disable Magento2.Classes.AbstractApi * @since 100.0.2 */ abstract class AbstractPdf extends \Magento\Framework\DataObject From 9f2f5b605564465876b391883be3f19035b5f80a Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 8 May 2019 10:30:32 +0300 Subject: [PATCH 192/224] graphQl-535: removed unnecessary configs --- app/code/Magento/CatalogGraphQl/etc/graphql/di.xml | 7 ------- app/code/Magento/CatalogGraphQl/etc/schema.graphqls | 7 ------- .../Magento/GraphQl/Catalog/StoreConfigTest.php | 9 +-------- 3 files changed, 1 insertion(+), 22 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml b/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml index 5d5c92edd3d57..2292004f3cf01 100644 --- a/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml @@ -85,20 +85,13 @@ <argument name="extendedConfigData" xsi:type="array"> <item name="product_url_suffix" xsi:type="string">catalog/seo/product_url_suffix</item> <item name="category_url_suffix" xsi:type="string">catalog/seo/category_url_suffix</item> - <item name="product_use_categories" xsi:type="string">catalog/seo/product_use_categories</item> - <item name="save_rewrites_history" xsi:type="string">catalog/seo/save_rewrites_history</item> <item name="title_separator" xsi:type="string">catalog/seo/title_separator</item> - <item name="category_canonical_tag" xsi:type="string">catalog/seo/category_canonical_tag</item> - <item name="product_canonical_tag" xsi:type="string">catalog/seo/product_canonical_tag</item> <item name="list_mode" xsi:type="string">catalog/frontend/list_mode</item> <item name="grid_per_page_values" xsi:type="string">catalog/frontend/grid_per_page_values</item> <item name="list_per_page_values" xsi:type="string">catalog/frontend/list_per_page_values</item> <item name="grid_per_page" xsi:type="string">catalog/frontend/grid_per_page</item> <item name="list_per_page" xsi:type="string">catalog/frontend/list_per_page</item> - <item name="flat_catalog_category" xsi:type="string">catalog/frontend/flat_catalog_category</item> <item name="catalog_default_sort_by" xsi:type="string">catalog/frontend/default_sort_by</item> - <item name="parse_url_directives" xsi:type="string">catalog/frontend/parse_url_directives</item> - <item name="remember_pagination" xsi:type="string">catalog/frontend/remember_pagination</item> </argument> </arguments> </type> diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 1b04e2b0ff6aa..261d204cd19fc 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -405,18 +405,11 @@ type SortFields @doc(description: "SortFields contains a default value for sort type StoreConfig @doc(description: "The type contains information about a store config") { product_url_suffix : String @doc(description: "Product URL Suffix") category_url_suffix : String @doc(description: "Category URL Suffix") - product_use_categories : Int @doc(description: "Use Categories Path for Product URLs") - save_rewrites_history : Int @doc(description: "Create Permanent Redirect for URLs if URL Key Changed") title_separator : String @doc(description: "Page Title Separator") - category_canonical_tag : Int @doc(description: "Use Canonical Link Meta Tag For Categories") - product_canonical_tag : Int @doc(description: "Use Canonical Link Meta Tag For Products") list_mode : String @doc(description: "List Mode") grid_per_page_values : String @doc(description: "Products per Page on Grid Allowed Values") list_per_page_values : String @doc(description: "Products per Page on List Allowed Values") grid_per_page : Int @doc(description: "Products per Page on Grid Default Value") list_per_page : Int @doc(description: "Products per Page on List Default Value") - flat_catalog_category : Int @doc(description: "Use Flat Catalog Category") catalog_default_sort_by : String @doc(description: "Default Sort By") - parse_url_directives : Int @doc(description: "Parse URL directives") - remember_pagination : Int @doc(description: "Remember Pagination") } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/StoreConfigTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/StoreConfigTest.php index 5932fd8b034e6..2672431dbb56c 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/StoreConfigTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/StoreConfigTest.php @@ -30,20 +30,13 @@ public function testGetStoreConfig() storeConfig{ product_url_suffix, category_url_suffix, - product_use_categories, - save_rewrites_history, title_separator, - category_canonical_tag, - product_canonical_tag, list_mode, grid_per_page_values, list_per_page_values, grid_per_page, list_per_page, - flat_catalog_category, - catalog_default_sort_by, - parse_url_directives, - remember_pagination + catalog_default_sort_by } } QUERY; From 7305a43ce2b0b96dbf17621ca3a238463773f6e7 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 8 May 2019 11:03:25 +0300 Subject: [PATCH 193/224] graphQl-309: added agreement mode --- .../Model/Resolver/DataProvider/CheckoutAgreements.php | 1 + app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls | 1 + .../CheckoutAgreements/Api/CheckoutAgreementsListTest.php | 3 +++ 3 files changed, 5 insertions(+) diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php index 3dab845627261..2fa3fe9d1284d 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php +++ b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/DataProvider/CheckoutAgreements.php @@ -73,6 +73,7 @@ public function getData(): array AgreementInterface::CONTENT_HEIGHT => $checkoutAgreement->getContentHeight(), AgreementInterface::CHECKBOX_TEXT => $checkoutAgreement->getCheckboxText(), AgreementInterface::IS_HTML => $checkoutAgreement->getIsHtml(), + AgreementInterface::MODE => $checkoutAgreement->getMode(), ]; } diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls b/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls index e63368bb3c884..3debdb2513c63 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls @@ -12,4 +12,5 @@ type CheckoutAgreement @doc(description: "Defines all Checkout Agreement informa content_height: String @doc(description: "Checkout Agreement content height") checkbox_text: String @doc(description: "Checkout Agreement checkbox tex") is_html: Boolean @doc(description: "Is Checkout Agreement content in HTML format") + mode: Int @doc(description: "Is Checkout Agreement content in HTML format") } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php index 62491e5e8376b..05f2afe0ed2cf 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/Api/CheckoutAgreementsListTest.php @@ -63,6 +63,7 @@ public function testGetActiveAgreement() $this->assertEquals('200px', $agreements[0]['content_height']); $this->assertEquals('Checkout agreement checkbox text.', $agreements[0]['checkbox_text']); $this->assertEquals(true, $agreements[0]['is_html']); + $this->assertEquals(0, $agreements[0]['mode']); } /** @@ -89,6 +90,7 @@ public function testGetActiveAgreementOnSecondStore() $this->assertEquals('200px', $agreements[0]['content_height']); $this->assertEquals('Checkout agreement checkbox text.', $agreements[0]['checkbox_text']); $this->assertEquals(true, $agreements[0]['is_html']); + $this->assertEquals(0, $agreements[0]['mode']); } /** @@ -153,6 +155,7 @@ private function getQuery(): string content_height checkbox_text is_html + mode } } QUERY; From ac7af37678704e4ac8d5e96d70bb5c7036ff610e Mon Sep 17 00:00:00 2001 From: nmalevanec <mikola.malevanec@transoftgroup.com> Date: Wed, 8 May 2019 11:57:40 +0300 Subject: [PATCH 194/224] Fix static tests. --- .../Product/Initialization/Helper/AttributeFilter.php | 6 ++++++ .../ResourceModel/Product/Type/Configurable/Attribute.php | 8 ++++---- .../Magento/Reports/Model/Product/Index/AbstractIndex.php | 2 ++ .../adminhtml/templates/order/create/form/account.phtml | 4 ++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php index 6d201c7999968..49165c85f85d7 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper/AttributeFilter.php @@ -46,6 +46,8 @@ public function prepareProductAttributes(Product $product, array $productData, a } /** + * Reset "Use Config Settings" to false in product data. + * * @param Product $product * @param string $attributeCode * @param array $productData @@ -62,6 +64,8 @@ private function prepareConfigData(Product $product, string $attributeCode, arra } /** + * Prepare default attribute data for product. + * * @param array $attributeList * @param string $attributeCode * @param array $productData @@ -86,6 +90,8 @@ private function prepareDefaultData(array $attributeList, string $attributeCode, } /** + * Check, whether attribute should not be updated. + * * @param Product $product * @param array $useDefaults * @param string $attribute diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute.php index cdbee21573e10..1b5ea4d020f8e 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute.php +++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Type/Configurable/Attribute.php @@ -1,7 +1,5 @@ <?php /** - * Catalog super product attribute resource model - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -11,6 +9,9 @@ use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Store\Model\Store; +/** + * Catalog super product attribute resource model. + */ class Attribute extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb { /** @@ -189,8 +190,7 @@ public function deleteAttributesByProductId($productId) } /** - * @param \Magento\Framework\Model\AbstractModel $object - * @return $this + * @inheritDoc */ protected function _afterLoad(\Magento\Framework\Model\AbstractModel $object) { diff --git a/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php b/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php index 5f69d8008db0a..48bbbf0898219 100644 --- a/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php +++ b/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php @@ -7,8 +7,10 @@ /** * Reports Product Index Abstract Model + * * @api * @since 100.0.2 + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) */ abstract class AbstractIndex extends \Magento\Framework\Model\AbstractModel { diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/account.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/account.phtml index 21f517bcee78e..f7d5f4aa8aa33 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/account.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form/account.phtml @@ -5,8 +5,8 @@ */ ?> -<div class="admin__page-section-title <?= /* @escapeNotVerified */ $block->getHeaderCssClass() ?>"> - <span class="title"><?= /* @escapeNotVerified */ $block->getHeaderText() ?></span> +<div class="admin__page-section-title <?= /* @noEscape */ $block->getHeaderCssClass() ?>"> + <span class="title"><?= /* @noEscape */ $block->getHeaderText() ?></span> <div class="actions"></div> </div> <div id="customer_account_fields" class="admin__page-section-content"> From 3a88a354ad8d982f514dbbe3e88cb4259f9e4766 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 8 May 2019 13:39:27 +0300 Subject: [PATCH 195/224] graphQl-198: refactor related products graph ql business logic to separate module --- .../Magento/CatalogGraphQl/etc/graphql/di.xml | 22 ------------- .../CatalogGraphQl/etc/schema.graphqls | 3 -- .../Products/LinkedProductsDataProvider.php | 2 +- .../DataProvider}/RelatedDataProvider.php | 4 +-- .../Model/Resolver}/CrossSellProducts.php | 4 +-- .../Model/Resolver}/RelatedProducts.php | 4 +-- .../Model/Resolver}/UpSellProducts.php | 4 +-- .../RelatedProductGraphQl/composer.json | 26 ++++++++++++++++ .../RelatedProductGraphQl/etc/graphql/di.xml | 31 +++++++++++++++++++ .../RelatedProductGraphQl/etc/module.xml | 10 ++++++ .../RelatedProductGraphQl/etc/schema.graphqls | 8 +++++ .../RelatedProductGraphQl/registration.php | 9 ++++++ composer.json | 1 + composer.lock | 2 +- .../ProductRelatedProductsTest.php | 2 +- 15 files changed, 96 insertions(+), 36 deletions(-) rename app/code/Magento/{CatalogGraphQl/Model/Resolver/Products/DataProvider/Related => RelatedProductGraphQl/Model/DataProvider}/Products/LinkedProductsDataProvider.php (93%) rename app/code/Magento/{CatalogGraphQl/Model/Resolver/Products/DataProvider/Related => RelatedProductGraphQl/Model/DataProvider}/RelatedDataProvider.php (91%) rename app/code/Magento/{CatalogGraphQl/Model/Resolver/Product/Related => RelatedProductGraphQl/Model/Resolver}/CrossSellProducts.php (85%) rename app/code/Magento/{CatalogGraphQl/Model/Resolver/Product/Related => RelatedProductGraphQl/Model/Resolver}/RelatedProducts.php (85%) rename app/code/Magento/{CatalogGraphQl/Model/Resolver/Product/Related => RelatedProductGraphQl/Model/Resolver}/UpSellProducts.php (85%) create mode 100644 app/code/Magento/RelatedProductGraphQl/composer.json create mode 100644 app/code/Magento/RelatedProductGraphQl/etc/graphql/di.xml create mode 100644 app/code/Magento/RelatedProductGraphQl/etc/module.xml create mode 100644 app/code/Magento/RelatedProductGraphQl/etc/schema.graphqls create mode 100644 app/code/Magento/RelatedProductGraphQl/registration.php rename dev/tests/api-functional/testsuite/Magento/GraphQl/{Catalog => RelatedProduct}/ProductRelatedProductsTest.php (99%) diff --git a/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml b/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml index af8ce3e5442ac..a5bd42860ded0 100644 --- a/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml @@ -78,28 +78,6 @@ </argument> </arguments> </virtualType> - <virtualType name="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\CrossSellDataProvider" type="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\RelatedDataProvider"> - <arguments> - <argument name="linkType" xsi:type="const">Magento\Catalog\Model\Product\Link::LINK_TYPE_CROSSSELL</argument> - <argument name="schemaNodeName" xsi:type="string">crosssell_products</argument> - </arguments> - </virtualType> - <type name="Magento\CatalogGraphQl\Model\Resolver\Product\Related\CrossSellProducts"> - <arguments> - <argument name="dataProvider" xsi:type="object">Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\CrossSellDataProvider</argument> - </arguments> - </type> - <virtualType name="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\UpSellDataProvider" type="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\RelatedDataProvider"> - <arguments> - <argument name="linkType" xsi:type="const">Magento\Catalog\Model\Product\Link::LINK_TYPE_UPSELL</argument> - <argument name="schemaNodeName" xsi:type="string">upsell_products</argument> - </arguments> - </virtualType> - <type name="Magento\CatalogGraphQl\Model\Resolver\Product\Related\UpSellProducts"> - <arguments> - <argument name="dataProvider" xsi:type="object">Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\UpSellDataProvider</argument> - </arguments> - </type> <preference for="Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match" type="Magento\CatalogGraphQl\Model\Search\Adapter\Mysql\Query\Builder\Match" /> </config> diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 3e95e9672ab82..b436bdadebea0 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -93,9 +93,6 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ websites: [Website] @doc(description: "An array of websites in which the product is available") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Websites") product_links: [ProductLinksInterface] @doc(description: "An array of ProductLinks objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\ProductLinks") media_gallery_entries: [MediaGalleryEntry] @doc(description: "An array of MediaGalleryEntry objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\MediaGalleryEntries") - related_products: [ProductInterface] @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related\\RelatedProducts") - upsell_products: [ProductInterface] @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related\\UpSellProducts") - crosssell_products: [ProductInterface] @doc(description: "RelatedProduct") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Related\\CrossSellProducts") tier_prices: [ProductTierPrices] @doc(description: "An array of ProductTierPrices objects") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\TierPrices") price: ProductPrices @doc(description: "A ProductPrices object, indicating the price of an item") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\Price") gift_message_available: String @doc(description: "Indicates whether a gift message is available") diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/Products/LinkedProductsDataProvider.php b/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/Products/LinkedProductsDataProvider.php similarity index 93% rename from app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/Products/LinkedProductsDataProvider.php rename to app/code/Magento/RelatedProductGraphQl/Model/DataProvider/Products/LinkedProductsDataProvider.php index d2daefd128129..9a62a6685a532 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/Products/LinkedProductsDataProvider.php +++ b/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/Products/LinkedProductsDataProvider.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\Products; +namespace Magento\RelatedProductGraphQl\Model\DataProvider\Products; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Link; diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/RelatedDataProvider.php b/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedDataProvider.php similarity index 91% rename from app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/RelatedDataProvider.php rename to app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedDataProvider.php index 8f42cc8411a72..eb437ea31fce1 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Related/RelatedDataProvider.php +++ b/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedDataProvider.php @@ -5,12 +5,12 @@ */ declare(strict_types=1); -namespace Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related; +namespace Magento\RelatedProductGraphQl\Model\DataProvider; use Magento\Catalog\Model\Product\Link; use Magento\Catalog\Model\Product\LinkFactory; use Magento\CatalogGraphQl\Model\Resolver\Product\ProductFieldsSelector; -use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\Products\LinkedProductsDataProvider; +use Magento\RelatedProductGraphQl\Model\DataProvider\Products\LinkedProductsDataProvider; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; /** diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/CrossSellProducts.php b/app/code/Magento/RelatedProductGraphQl/Model/Resolver/CrossSellProducts.php similarity index 85% rename from app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/CrossSellProducts.php rename to app/code/Magento/RelatedProductGraphQl/Model/Resolver/CrossSellProducts.php index 2ae3d30a2b01f..3a6fdb855b856 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/CrossSellProducts.php +++ b/app/code/Magento/RelatedProductGraphQl/Model/Resolver/CrossSellProducts.php @@ -5,9 +5,9 @@ */ declare(strict_types=1); -namespace Magento\CatalogGraphQl\Model\Resolver\Product\Related; +namespace Magento\RelatedProductGraphQl\Model\Resolver; -use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\RelatedDataProvider; +use Magento\RelatedProductGraphQl\Model\DataProvider\RelatedDataProvider; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/RelatedProducts.php b/app/code/Magento/RelatedProductGraphQl/Model/Resolver/RelatedProducts.php similarity index 85% rename from app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/RelatedProducts.php rename to app/code/Magento/RelatedProductGraphQl/Model/Resolver/RelatedProducts.php index cb437a2202c88..280e3d9d0ede6 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/RelatedProducts.php +++ b/app/code/Magento/RelatedProductGraphQl/Model/Resolver/RelatedProducts.php @@ -5,9 +5,9 @@ */ declare(strict_types=1); -namespace Magento\CatalogGraphQl\Model\Resolver\Product\Related; +namespace Magento\RelatedProductGraphQl\Model\Resolver; -use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\RelatedDataProvider; +use Magento\RelatedProductGraphQl\Model\DataProvider\RelatedDataProvider; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/UpSellProducts.php b/app/code/Magento/RelatedProductGraphQl/Model/Resolver/UpSellProducts.php similarity index 85% rename from app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/UpSellProducts.php rename to app/code/Magento/RelatedProductGraphQl/Model/Resolver/UpSellProducts.php index e43e0fe57de4b..5299b43f5f54f 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Related/UpSellProducts.php +++ b/app/code/Magento/RelatedProductGraphQl/Model/Resolver/UpSellProducts.php @@ -5,9 +5,9 @@ */ declare(strict_types=1); -namespace Magento\CatalogGraphQl\Model\Resolver\Product\Related; +namespace Magento\RelatedProductGraphQl\Model\Resolver; -use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Related\RelatedDataProvider; +use Magento\RelatedProductGraphQl\Model\DataProvider\RelatedDataProvider; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; diff --git a/app/code/Magento/RelatedProductGraphQl/composer.json b/app/code/Magento/RelatedProductGraphQl/composer.json new file mode 100644 index 0000000000000..0d314d433f177 --- /dev/null +++ b/app/code/Magento/RelatedProductGraphQl/composer.json @@ -0,0 +1,26 @@ +{ + "name": "magento/module-related-product-graph-ql", + "description": "N/A", + "type": "magento2-module", + "require": { + "php": "~7.1.3||~7.2.0", + "magento/module-catalog": "*", + "magento/module-catalog-graph-ql": "*", + "magento/framework": "*" + }, + "suggest": { + "magento/module-graph-ql": "*" + }, + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "autoload": { + "files": [ + "registration.php" + ], + "psr-4": { + "Magento\\RelatedProductGraphQl\\": "" + } + } +} diff --git a/app/code/Magento/RelatedProductGraphQl/etc/graphql/di.xml b/app/code/Magento/RelatedProductGraphQl/etc/graphql/di.xml new file mode 100644 index 0000000000000..f64cf197b250f --- /dev/null +++ b/app/code/Magento/RelatedProductGraphQl/etc/graphql/di.xml @@ -0,0 +1,31 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> + <virtualType name="Magento\RelatedProductGraphQl\Model\DataProvider\CrossSellDataProvider" type="Magento\RelatedProductGraphQl\Model\DataProvider\RelatedDataProvider"> + <arguments> + <argument name="linkType" xsi:type="const">Magento\Catalog\Model\Product\Link::LINK_TYPE_CROSSSELL</argument> + <argument name="schemaNodeName" xsi:type="string">crosssell_products</argument> + </arguments> + </virtualType> + <type name="Magento\RelatedProductGraphQl\Model\Resolver\CrossSellProducts"> + <arguments> + <argument name="dataProvider" xsi:type="object">Magento\RelatedProductGraphQl\Model\DataProvider\CrossSellDataProvider</argument> + </arguments> + </type> + <virtualType name="Magento\RelatedProductGraphQl\Model\DataProvider\UpSellDataProvider" type="Magento\RelatedProductGraphQl\Model\DataProvider\RelatedDataProvider"> + <arguments> + <argument name="linkType" xsi:type="const">Magento\Catalog\Model\Product\Link::LINK_TYPE_UPSELL</argument> + <argument name="schemaNodeName" xsi:type="string">upsell_products</argument> + </arguments> + </virtualType> + <type name="Magento\RelatedProductGraphQl\Model\Resolver\UpSellProducts"> + <arguments> + <argument name="dataProvider" xsi:type="object">Magento\RelatedProductGraphQl\Model\DataProvider\UpSellDataProvider</argument> + </arguments> + </type> +</config> diff --git a/app/code/Magento/RelatedProductGraphQl/etc/module.xml b/app/code/Magento/RelatedProductGraphQl/etc/module.xml new file mode 100644 index 0000000000000..e30775c253a45 --- /dev/null +++ b/app/code/Magento/RelatedProductGraphQl/etc/module.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> + <module name="Magento_RelatedProductGraphQl"/> +</config> diff --git a/app/code/Magento/RelatedProductGraphQl/etc/schema.graphqls b/app/code/Magento/RelatedProductGraphQl/etc/schema.graphqls new file mode 100644 index 0000000000000..240fc6c4496f0 --- /dev/null +++ b/app/code/Magento/RelatedProductGraphQl/etc/schema.graphqls @@ -0,0 +1,8 @@ +# Copyright © Magento, Inc. All rights reserved. +# See COPYING.txt for license details. + +interface ProductInterface { + related_products: [ProductInterface] @doc(description: "RelatedProduct") @resolver(class: "Magento\\RelatedProductGraphQl\\Model\\Resolver\\RelatedProducts") + upsell_products: [ProductInterface] @doc(description: "RelatedProduct") @resolver(class: "Magento\\RelatedProductGraphQl\\Model\\Resolver\\UpSellProducts") + crosssell_products: [ProductInterface] @doc(description: "RelatedProduct") @resolver(class: "Magento\\RelatedProductGraphQl\\Model\\Resolver\\CrossSellProducts") +} \ No newline at end of file diff --git a/app/code/Magento/RelatedProductGraphQl/registration.php b/app/code/Magento/RelatedProductGraphQl/registration.php new file mode 100644 index 0000000000000..d18dfc27cc7c6 --- /dev/null +++ b/app/code/Magento/RelatedProductGraphQl/registration.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Framework\Component\ComponentRegistrar; + +ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_RelatedProductGraphQl', __DIR__); diff --git a/composer.json b/composer.json index 2ba4d20c6533e..049e6e5c6af7e 100644 --- a/composer.json +++ b/composer.json @@ -201,6 +201,7 @@ "magento/module-quote": "*", "magento/module-quote-analytics": "*", "magento/module-quote-graph-ql": "*", + "magento/module-related-product-graph-ql": "*", "magento/module-release-notification": "*", "magento/module-reports": "*", "magento/module-require-js": "*", diff --git a/composer.lock b/composer.lock index 09ca8cd9f3f02..184c73401e384 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6b0350be54f49186c1c9f55ac29bf1cb", + "content-hash": "fc118f9749005c046c08f815dbde0665", "packages": [ { "name": "braintree/braintree_php", diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductRelatedProductsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/ProductRelatedProductsTest.php similarity index 99% rename from dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductRelatedProductsTest.php rename to dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/ProductRelatedProductsTest.php index 2cc3f0c8530a8..5317e88d7e118 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/ProductRelatedProductsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/ProductRelatedProductsTest.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\GraphQl\Catalog; +namespace Magento\GraphQl\RelatedProduct; use Magento\TestFramework\TestCase\GraphQlAbstract; From 4a5b33022ddc36bf9c67426f33b43c6c58f88276 Mon Sep 17 00:00:00 2001 From: Vitaliy Boyko <v.boyko@atwix.com> Date: Wed, 8 May 2019 13:52:27 +0300 Subject: [PATCH 196/224] graphQl-198: fixed description --- app/code/Magento/CatalogGraphQl/etc/schema.graphqls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index b436bdadebea0..9f102a1c6a150 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -50,7 +50,7 @@ type ProductPrices @doc(description: "The ProductPrices object contains the regu type ProductLinks implements ProductLinksInterface @doc(description: "ProductLinks is an implementation of ProductLinksInterface.") { } -interface ProductLinksInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\ProductLinkTypeResolverComposite") @doc(description:"Related contains information about linked products, including the link type and product type of each item.") { +interface ProductLinksInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\ProductLinkTypeResolverComposite") @doc(description:"ProductLinks contains information about linked products, including the link type and product type of each item.") { sku: String @doc(description: "The identifier of the linked product") link_type: String @doc(description: "One of related, associated, upsell, or crosssell") linked_product_sku: String @doc(description: "The SKU of the linked product") From 29d5b8843093acc63c902db3ad7ec896920adad5 Mon Sep 17 00:00:00 2001 From: Kajal Solanki <kajal.solanki@krishtechnolabs.com> Date: Wed, 8 May 2019 18:25:04 +0530 Subject: [PATCH 197/224] testBundleProductWithNotVisibleChildren fix misspelling --- .../testsuite/Magento/GraphQl/Bundle/BundleProductViewTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Bundle/BundleProductViewTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Bundle/BundleProductViewTest.php index 0621370972763..20d097906d7e7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Bundle/BundleProductViewTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Bundle/BundleProductViewTest.php @@ -108,7 +108,7 @@ public function testAllFieldsBundleProducts() /** * @magentoApiDataFixture Magento/Bundle/_files/bundle_product_with_not_visible_children.php */ - public function testBundleProdutWithNotVisibleChildren() + public function testBundleProductWithNotVisibleChildren() { $productSku = 'bundle-product-1'; $query From ad5d78d2521ec786dcad64c0ffe1b39ffbb12434 Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Wed, 8 May 2019 10:08:05 -0500 Subject: [PATCH 198/224] MC-1540: Deliver weekly MTF conversion PR fixed error on PR build --- ...ertStorefrontShoppingCartSummaryWithShippingActionGroup.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml index dcb683a50125d..73dfad9cff4bb 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/AssertStorefrontShoppingCartSummaryWithShippingActionGroup.xml @@ -13,6 +13,7 @@ </arguments> <waitForLoadingMaskToDisappear stepKey="waitForMaskToDisappear" after="assertSubtotal"/> <waitForElementVisible selector="{{CheckoutCartSummarySection.shipping}}" time="60" stepKey="waitForElementToBeVisible" after="waitForMaskToDisappear"/> - <waitForText userInput="{{shipping}}" selector="{{CheckoutCartSummarySection.shipping}}" time="60" stepKey="assertShipping" after="waitForElementToBeVisible"/> + <wait time="5" stepKey="waitForShippingDetailsToLoad" after="waitForElementToBeVisible"/> + <waitForText userInput="{{shipping}}" selector="{{CheckoutCartSummarySection.shipping}}" time="120" stepKey="assertShipping" after="waitForShippingDetailsToLoad"/> </actionGroup> </actionGroups> From 279bad294769c23936e4859dbf1259aa5bd60b17 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Wed, 8 May 2019 10:13:45 -0500 Subject: [PATCH 199/224] MC-4562: Convert ValidateRequireAddressAttributeEntityTest to MFTF --- .../Checkout/Test/Mftf/Section/CheckoutShippingSection.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml index 97ae206a67005..6c5eef9ce7a9d 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml @@ -39,5 +39,6 @@ <element name="editActiveAddress" type="button" selector="//div[@class='shipping-address-item selected-item']//span[text()='Edit']" timeout="30"/> <element name="loginButton" type="button" selector=".action.login" timeout="30"/> <element name="shipHereButton" type="button" selector="//div[text()='{{street}}']/button[@class='action action-select-shipping-item']" parameterized="true" timeout="30"/> + <element name="textFieldAttrRequireMessage" selector="//input[@name='custom_attributes[{{attribute}}]']/ancestor::div[contains(@class, 'control')]/div/span" parameterized="true" timeout="30"/> </section> </sections> From 1e7ea98a4eb47f8d1d9482e572ef779711448f68 Mon Sep 17 00:00:00 2001 From: Maria Kovdrysh <kovdrysh@adobe.com> Date: Wed, 8 May 2019 10:21:06 -0500 Subject: [PATCH 200/224] MC-4562: Convert ValidateRequireAddressAttributeEntityTest to MFTF --- .../Checkout/Test/Mftf/Section/CheckoutShippingSection.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml index 6c5eef9ce7a9d..97ae206a67005 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingSection.xml @@ -39,6 +39,5 @@ <element name="editActiveAddress" type="button" selector="//div[@class='shipping-address-item selected-item']//span[text()='Edit']" timeout="30"/> <element name="loginButton" type="button" selector=".action.login" timeout="30"/> <element name="shipHereButton" type="button" selector="//div[text()='{{street}}']/button[@class='action action-select-shipping-item']" parameterized="true" timeout="30"/> - <element name="textFieldAttrRequireMessage" selector="//input[@name='custom_attributes[{{attribute}}]']/ancestor::div[contains(@class, 'control')]/div/span" parameterized="true" timeout="30"/> </section> </sections> From c3040e682d56964b78c6e7a29388bea6c1a34c85 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 8 May 2019 10:26:16 -0500 Subject: [PATCH 201/224] GraphQl-309: [Checkout] Checkout Agreements --- .../Model/Resolver/CheckoutAgreements.php | 8 ++++++-- .../etc/schema.graphqls | 17 +++++++++++------ .../GetCheckoutAgreementsTest.php | 14 +++++++------- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php index 02345f71681f8..670107aef73f2 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php +++ b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php @@ -7,6 +7,8 @@ namespace Magento\CheckoutAgreementsGraphQl\Model\Resolver; +use Magento\CheckoutAgreements\Model\AgreementModeOptions; +use Magento\CheckoutAgreements\Model\ResourceModel\Agreement\Collection; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; @@ -65,9 +67,10 @@ public function resolve( return []; } + /** @var Collection $agreementsCollection */ $agreementsCollection = $this->agreementCollectionFactory->create(); $agreementsCollection->addStoreFilter($this->storeManager->getStore()->getId()); - $agreementsCollection->addFieldToFilter('is_active', 1); + $agreementsCollection->addFieldToFilter(AgreementInterface::IS_ACTIVE, 1); $checkoutAgreementData = []; /** @var AgreementInterface $checkoutAgreement */ @@ -79,7 +82,8 @@ public function resolve( AgreementInterface::CONTENT_HEIGHT => $checkoutAgreement->getContentHeight(), AgreementInterface::CHECKBOX_TEXT => $checkoutAgreement->getCheckboxText(), AgreementInterface::IS_HTML => $checkoutAgreement->getIsHtml(), - AgreementInterface::MODE => $checkoutAgreement->getMode(), + AgreementInterface::MODE => + AgreementModeOptions::MODE_AUTO === $checkoutAgreement->getMode() ? 'AUTO' : 'MANUAL', ]; } return $checkoutAgreementData; diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls b/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls index 3debdb2513c63..64ef9411dfca6 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CheckoutAgreementsGraphQl/etc/schema.graphqls @@ -6,11 +6,16 @@ type Query { } type CheckoutAgreement @doc(description: "Defines all Checkout Agreement information") { - agreement_id: Int @doc(description: "Checkout Agreement identifier") - name: String @doc(description: "Checkout Agreement name") - content: String @doc(description: "Checkout Agreement content") + agreement_id: Int! @doc(description: "Checkout Agreement identifier") + name: String! @doc(description: "Checkout Agreement name") + content: String! @doc(description: "Checkout Agreement content") content_height: String @doc(description: "Checkout Agreement content height") - checkbox_text: String @doc(description: "Checkout Agreement checkbox tex") - is_html: Boolean @doc(description: "Is Checkout Agreement content in HTML format") - mode: Int @doc(description: "Is Checkout Agreement content in HTML format") + checkbox_text: String! @doc(description: "Checkout Agreement checkbox text") + is_html: Boolean! @doc(description: "Is Checkout Agreement content in HTML format") + mode: CheckoutAgreementMode! +} + +enum CheckoutAgreementMode { + AUTO + MANUAL } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/GetCheckoutAgreementsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/GetCheckoutAgreementsTest.php index 8fdfd5cf0108d..3aa01d7994222 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/GetCheckoutAgreementsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/CheckoutAgreements/GetCheckoutAgreementsTest.php @@ -68,8 +68,8 @@ public function testGetActiveAgreement() self::assertEquals('Checkout agreement content: <b>HTML</b>', $agreements[0]['content']); self::assertEquals('200px', $agreements[0]['content_height']); self::assertEquals('Checkout agreement checkbox text.', $agreements[0]['checkbox_text']); - self::assertEquals(true, $agreements[0]['is_html']); - self::assertEquals(0, $agreements[0]['mode']); + self::assertTrue($agreements[0]['is_html']); + self::assertEquals('AUTO', $agreements[0]['mode']); } /** @@ -95,8 +95,8 @@ public function testGetActiveAgreementOnSecondStore() self::assertEquals('Checkout agreement content: <b>HTML</b>', $agreements[0]['content']); self::assertEquals('200px', $agreements[0]['content_height']); self::assertEquals('Checkout agreement checkbox text.', $agreements[0]['checkbox_text']); - self::assertEquals(true, $agreements[0]['is_html']); - self::assertEquals(0, $agreements[0]['mode']); + self::assertTrue($agreements[0]['is_html']); + self::assertEquals('AUTO', $agreements[0]['mode']); } /** @@ -116,7 +116,7 @@ public function testGetActiveAgreementFromSecondStoreOnDefaultStore() self::assertArrayHasKey('checkoutAgreements', $response); $agreements = $response['checkoutAgreements']; - self::assertCount(0, $agreements); + self::assertEmpty($agreements); } public function testGetAgreementNotSet() @@ -127,7 +127,7 @@ public function testGetAgreementNotSet() self::assertArrayHasKey('checkoutAgreements', $response); $agreements = $response['checkoutAgreements']; - self::assertCount(0, $agreements); + self::assertEmpty($agreements); } /** @@ -143,7 +143,7 @@ public function testDisabledAgreements() self::assertArrayHasKey('checkoutAgreements', $response); $agreements = $response['checkoutAgreements']; - self::assertCount(0, $agreements); + self::assertEmpty($agreements); } /** From 4d7be93e831db12cc1c10c41651f6c36c3bb122e Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 8 May 2019 10:54:54 -0500 Subject: [PATCH 202/224] GraphQl-309: [Checkout] Checkout Agreements --- .../Model/Resolver/CheckoutAgreements.php | 2 +- composer.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php index 670107aef73f2..3daf88226d8e5 100644 --- a/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php +++ b/app/code/Magento/CheckoutAgreementsGraphQl/Model/Resolver/CheckoutAgreements.php @@ -83,7 +83,7 @@ public function resolve( AgreementInterface::CHECKBOX_TEXT => $checkoutAgreement->getCheckboxText(), AgreementInterface::IS_HTML => $checkoutAgreement->getIsHtml(), AgreementInterface::MODE => - AgreementModeOptions::MODE_AUTO === $checkoutAgreement->getMode() ? 'AUTO' : 'MANUAL', + AgreementModeOptions::MODE_AUTO === (int)$checkoutAgreement->getMode() ? 'AUTO' : 'MANUAL', ]; } return $checkoutAgreementData; diff --git a/composer.lock b/composer.lock index 09ca8cd9f3f02..77783c00dd641 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6b0350be54f49186c1c9f55ac29bf1cb", + "content-hash": "24c95683a202b83c7f182921c0c88328", "packages": [ { "name": "braintree/braintree_php", @@ -6775,12 +6775,12 @@ "version": "v1.6.5", "source": { "type": "git", - "url": "https://github.com/bovigo/vfsStream.git", + "url": "https://github.com/mikey179/vfsStream.git", "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", + "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", "shasum": "" }, From 36c61859b16acb63f2c3ab4e001bb034b53a5028 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Wed, 8 May 2019 11:33:03 -0500 Subject: [PATCH 203/224] MC-16312: Revert fix ENGCOM-1351 --- .../Model/ResourceModel/Catalog/Product.php | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/app/code/Magento/Sitemap/Model/ResourceModel/Catalog/Product.php b/app/code/Magento/Sitemap/Model/ResourceModel/Catalog/Product.php index 1419fa375a117..7ad1fe7405dee 100644 --- a/app/code/Magento/Sitemap/Model/ResourceModel/Catalog/Product.php +++ b/app/code/Magento/Sitemap/Model/ResourceModel/Catalog/Product.php @@ -310,10 +310,6 @@ public function getCollection($storeId) } $connection = $this->getConnection(); - $urlsConfigCondition = ''; - if ($this->isCategoryProductURLsConfig($storeId)) { - $urlsConfigCondition = 'NOT '; - } $this->_select = $connection->select()->from( ['e' => $this->getMainTable()], @@ -324,9 +320,7 @@ public function getCollection($storeId) [] )->joinLeft( ['url_rewrite' => $this->getTable('url_rewrite')], - 'e.entity_id = url_rewrite.entity_id AND url_rewrite.is_autogenerated = 1 ' - . 'AND NULLIF(url_rewrite.metadata,"") IS ' - . $urlsConfigCondition . 'NULL' + 'e.entity_id = url_rewrite.entity_id AND url_rewrite.is_autogenerated = 1 AND url_rewrite.metadata IS NULL' . $connection->quoteInto(' AND url_rewrite.store_id = ?', $store->getId()) . $connection->quoteInto(' AND url_rewrite.entity_type = ?', ProductUrlRewriteGenerator::ENTITY_TYPE), ['url' => 'request_path'] @@ -490,20 +484,4 @@ private function getProductImageUrl($image) { return $this->imageUrlBuilder->getUrl($image, 'product_page_image_large'); } - - /** - * Return Use Categories Path for Product URLs config value - * - * @param null|string $storeId - * - * @return bool - */ - private function isCategoryProductURLsConfig($storeId) - { - return $this->scopeConfig->isSetFlag( - HelperProduct::XML_PATH_PRODUCT_URL_USE_CATEGORY, - ScopeInterface::SCOPE_STORE, - $storeId - ); - } } From d7b7a2e19fe376b30ac45df91c75b80c416e38bb Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 8 May 2019 11:49:58 -0500 Subject: [PATCH 204/224] GraphQl-387: Test coverage of getting IDs of CMS page/blocks by GraphQL API --- .../Model/Resolver/DataProvider/Page.php | 36 +++------------ .../CmsGraphQl/Model/Resolver/Page.php | 45 ++----------------- 2 files changed, 8 insertions(+), 73 deletions(-) diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php index 2001bc006bbb8..8b9766ca311c7 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php @@ -58,23 +58,6 @@ public function __construct( $this->storeManager = $storeManager; } - /** - * @deprecated - * @see getDataByPageId(int $pageId) - * - * Get the page data - * - * @param int $pageId - * @return array - * @throws NoSuchEntityException - */ - public function getData(int $pageId): array - { - $page = $this->pageRepository->getById($pageId); - - return $this->convertPageData($page); - } - /** * Returns page data by page_id * @@ -86,7 +69,7 @@ public function getDataByPageId(int $pageId): array { $page = $this->pageRepository->getById($pageId); - return $this->convertPageData($page, false, true); + return $this->convertPageData($page); } /** @@ -101,17 +84,15 @@ public function getDataByPageIdentifier(string $pageIdentifier): array $storeId = (int)$this->storeManager->getStore()->getId(); $page = $this->pageByIdentifier->execute($pageIdentifier, $storeId); - return $this->convertPageData($page, false, true); + return $this->convertPageData($page); } /** * @param PageInterface $page - * @param bool $includePageId - * @param bool $includePageIdentifier * @return array * @throws NoSuchEntityException */ - private function convertPageData(PageInterface $page, $includePageId = true, $includePageIdentifier = false) + private function convertPageData(PageInterface $page) { if (false === $page->isActive()) { throw new NoSuchEntityException(); @@ -128,16 +109,9 @@ private function convertPageData(PageInterface $page, $includePageId = true, $in PageInterface::META_TITLE => $page->getMetaTitle(), PageInterface::META_DESCRIPTION => $page->getMetaDescription(), PageInterface::META_KEYWORDS => $page->getMetaKeywords(), + PageInterface::PAGE_ID => $page->getId(), + PageInterface::IDENTIFIER => $page->getIdentifier(), ]; - - if ($includePageId) { - $pageData[PageInterface::PAGE_ID] = $page->getId(); - } - - if ($includePageIdentifier) { - $pageData[PageInterface::IDENTIFIER] = $page->getIdentifier(); - } - return $pageData; } } diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php index 489a3e0a75c80..fbd8e26030952 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php @@ -45,7 +45,7 @@ public function resolve( array $value = null, array $args = null ) { - if (!isset($args['id']) && !isset($args['identifier'])) { + if (!isset($args['id'], $args['identifier'])) { throw new GraphQlInputException(__('"Page id/identifier should be specified')); } @@ -53,52 +53,13 @@ public function resolve( try { if (isset($args['id'])) { - $pageData = $this->getPageDataById($this->getPageId($args)); + $pageData = $this->pageDataProvider->getDataByPageId((int)$args['id']); } elseif (isset($args['identifier'])) { - $pageData = $this->getPageDataByIdentifier($this->getPageIdentifier($args)); + $pageData = $this->pageDataProvider->getDataByPageIdentifier((string)$args['identifier']); } } catch (NoSuchEntityException $e) { throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); } - return $pageData; } - - /** - * @param array $args - * @return int - */ - private function getPageId(array $args): int - { - return isset($args['id']) ? (int)$args['id'] : 0; - } - - /** - * @param array $args - * @return string - */ - private function getPageIdentifier(array $args): string - { - return isset($args['identifier']) ? (string)$args['identifier'] : ''; - } - - /** - * @param int $pageId - * @return array - * @throws GraphQlNoSuchEntityException - */ - private function getPageDataById(int $pageId): array - { - return $this->pageDataProvider->getDataByPageId($pageId); - } - - /** - * @param string $pageIdentifier - * @return array - * @throws GraphQlNoSuchEntityException - */ - private function getPageDataByIdentifier(string $pageIdentifier): array - { - return $this->pageDataProvider->getDataByPageIdentifier($pageIdentifier); - } } From 863c7adf44df1da8aaee2d3e81f1d4e2c70f152e Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Wed, 8 May 2019 12:12:33 -0500 Subject: [PATCH 205/224] Add testCaseId to test annotation - issue magento/magento-functional-tests-migration/386 - pull request magento/magento-functional-tests-migration/683 --- .../Test/Mftf/Test/StorefrontLockCustomerOnLoginPageTest.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLockCustomerOnLoginPageTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLockCustomerOnLoginPageTest.xml index 092800af43025..84ebaf4f9f5c4 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLockCustomerOnLoginPageTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontLockCustomerOnLoginPageTest.xml @@ -13,7 +13,8 @@ <features value="Customer"/> <title value="Lock customer on Storefront with after many attempts to log in with incorrect credentials"/> <description value="Lock customer on Storefront with after many attempts to log in with incorrect credentials"/> - <group value="Customer"/> + <testCaseId value="MC-14388" /> + <group value="customer"/> <group value="security"/> <group value="mtf_migrated"/> </annotations> From 4835285066637047ef47af81759efb2f2fde29dd Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 8 May 2019 12:27:02 -0500 Subject: [PATCH 206/224] GraphQl-198: Products: access to related/up-sell/cross-sell product fields --- .../DataProvider/RelatedDataProvider.php | 80 -------- ...der.php => RelatedProductDataProvider.php} | 35 +++- .../Model/Resolver/CrossSellProducts.php | 31 ++- .../Model/Resolver/RelatedProducts.php | 30 ++- .../Model/Resolver/UpSellProducts.php | 31 ++- .../RelatedProductGraphQl/etc/graphql/di.xml | 31 --- .../RelatedProduct/GetRelatedProductsTest.php | 178 ++++++++++++++++++ .../ProductRelatedProductsTest.php | 175 ----------------- 8 files changed, 275 insertions(+), 316 deletions(-) delete mode 100644 app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedDataProvider.php rename app/code/Magento/RelatedProductGraphQl/Model/DataProvider/{Products/LinkedProductsDataProvider.php => RelatedProductDataProvider.php} (52%) delete mode 100644 app/code/Magento/RelatedProductGraphQl/etc/graphql/di.xml create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/GetRelatedProductsTest.php delete mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/ProductRelatedProductsTest.php diff --git a/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedDataProvider.php b/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedDataProvider.php deleted file mode 100644 index eb437ea31fce1..0000000000000 --- a/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedDataProvider.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\RelatedProductGraphQl\Model\DataProvider; - -use Magento\Catalog\Model\Product\Link; -use Magento\Catalog\Model\Product\LinkFactory; -use Magento\CatalogGraphQl\Model\Resolver\Product\ProductFieldsSelector; -use Magento\RelatedProductGraphQl\Model\DataProvider\Products\LinkedProductsDataProvider; -use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; - -/** - * Related Products Data Provider - */ -class RelatedDataProvider -{ - /** - * @var LinkFactory - */ - private $dataProvider; - - /** - * @var ProductFieldsSelector - */ - private $productFieldsSelector; - - /** - * @var int - */ - private $linkType; - - /** - * @var string - */ - private $schemaNodeName; - - /** - * @param LinkedProductsDataProvider $dataProvider - * @param ProductFieldsSelector $productFieldsSelector - * @param int $linkType - * @param string $schemaNodeName - */ - public function __construct( - LinkedProductsDataProvider $dataProvider, - ProductFieldsSelector $productFieldsSelector, - int $linkType = Link::LINK_TYPE_RELATED, - string $schemaNodeName = 'related_products' - ) { - $this->dataProvider = $dataProvider; - $this->productFieldsSelector = $productFieldsSelector; - $this->linkType = $linkType; - $this->schemaNodeName = $schemaNodeName; - } - - /** - * Related Products Data - * - * @param ResolveInfo $info - * @param array $value - * @return array - */ - public function getProducts(ResolveInfo $info, array $value): array - { - $product = $value['model']; - $fields = $this->productFieldsSelector->getProductFieldsFromInfo($info, $this->schemaNodeName); - $products = $this->dataProvider->getRelatedProducts($product, $fields, $this->linkType); - - $data = []; - foreach ($products as $key => $product) { - $data[$key] = $product->getData(); - $data[$key]['model'] = $product; - } - - return $data; - } -} diff --git a/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/Products/LinkedProductsDataProvider.php b/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedProductDataProvider.php similarity index 52% rename from app/code/Magento/RelatedProductGraphQl/Model/DataProvider/Products/LinkedProductsDataProvider.php rename to app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedProductDataProvider.php index 9a62a6685a532..04a71da0337de 100644 --- a/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/Products/LinkedProductsDataProvider.php +++ b/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedProductDataProvider.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\RelatedProductGraphQl\Model\DataProvider\Products; +namespace Magento\RelatedProductGraphQl\Model\DataProvider; use Magento\Catalog\Model\Product; use Magento\Catalog\Model\Product\Link; @@ -14,7 +14,7 @@ /** * Related Products Data Provider */ -class LinkedProductsDataProvider +class RelatedProductDataProvider { /** * @var LinkFactory @@ -24,24 +24,45 @@ class LinkedProductsDataProvider /** * @param LinkFactory $linkFactory */ - public function __construct(LinkFactory $linkFactory) - { + public function __construct( + LinkFactory $linkFactory + ) { $this->linkFactory = $linkFactory; } /** - * Get Related Products by Product and Link Type + * Related Products Data + * + * @param Product $product + * @param array $fields + * @param int $linkType + * @return array + */ + public function getData(Product $product, array $fields, int $linkType): array + { + $relatedProducts = $this->getRelatedProducts($product, $fields, $linkType); + + $data = []; + foreach ($relatedProducts as $relatedProduct) { + $relatedProductData = $relatedProduct->getData(); + $relatedProductData['model'] = $relatedProduct; + } + return $data; + } + + /** + * Get Related Products * * @param Product $product * @param array $fields * @param int $linkType * @return Product[] */ - public function getRelatedProducts(Product $product, array $fields, int $linkType): array + private function getRelatedProducts(Product $product, array $fields, int $linkType): array { /** @var Link $link */ $link = $this->linkFactory->create([ 'data' => [ - 'link_type_id' => $linkType + 'link_type_id' => $linkType, ]]); $collection = $link->getProductCollection(); diff --git a/app/code/Magento/RelatedProductGraphQl/Model/Resolver/CrossSellProducts.php b/app/code/Magento/RelatedProductGraphQl/Model/Resolver/CrossSellProducts.php index 3a6fdb855b856..dcaa75b85f599 100644 --- a/app/code/Magento/RelatedProductGraphQl/Model/Resolver/CrossSellProducts.php +++ b/app/code/Magento/RelatedProductGraphQl/Model/Resolver/CrossSellProducts.php @@ -7,7 +7,10 @@ namespace Magento\RelatedProductGraphQl\Model\Resolver; -use Magento\RelatedProductGraphQl\Model\DataProvider\RelatedDataProvider; +use Magento\Catalog\Model\Product\Link; +use Magento\CatalogGraphQl\Model\Resolver\Product\ProductFieldsSelector; +use Magento\Framework\Exception\LocalizedException; +use Magento\RelatedProductGraphQl\Model\DataProvider\RelatedProductDataProvider; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; @@ -18,18 +21,25 @@ class CrossSellProducts implements ResolverInterface { /** - * @see module di.xml - * @var RelatedDataProvider + * @var ProductFieldsSelector */ - private $dataProvider; + private $productFieldsSelector; /** - * @param RelatedDataProvider $dataProvider + * @var RelatedProductDataProvider + */ + private $relatedProductDataProvider; + + /** + * @param ProductFieldsSelector $productFieldsSelector + * @param RelatedProductDataProvider $relatedProductDataProvider */ public function __construct( - RelatedDataProvider $dataProvider + ProductFieldsSelector $productFieldsSelector, + RelatedProductDataProvider $relatedProductDataProvider ) { - $this->dataProvider = $dataProvider; + $this->productFieldsSelector = $productFieldsSelector; + $this->relatedProductDataProvider = $relatedProductDataProvider; } /** @@ -37,8 +47,13 @@ public function __construct( */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { - $data = $this->dataProvider->getProducts($info, $value); + if (!isset($value['model'])) { + throw new LocalizedException(__('"model" value should be specified')); + } + $product = $value['model']; + $fields = $this->productFieldsSelector->getProductFieldsFromInfo($info, 'crosssell_products'); + $data = $this->relatedProductDataProvider->getData($product, $fields, Link::LINK_TYPE_CROSSSELL); return $data; } } diff --git a/app/code/Magento/RelatedProductGraphQl/Model/Resolver/RelatedProducts.php b/app/code/Magento/RelatedProductGraphQl/Model/Resolver/RelatedProducts.php index 280e3d9d0ede6..568c3282a6ee8 100644 --- a/app/code/Magento/RelatedProductGraphQl/Model/Resolver/RelatedProducts.php +++ b/app/code/Magento/RelatedProductGraphQl/Model/Resolver/RelatedProducts.php @@ -7,7 +7,10 @@ namespace Magento\RelatedProductGraphQl\Model\Resolver; -use Magento\RelatedProductGraphQl\Model\DataProvider\RelatedDataProvider; +use Magento\Catalog\Model\Product\Link; +use Magento\CatalogGraphQl\Model\Resolver\Product\ProductFieldsSelector; +use Magento\Framework\Exception\LocalizedException; +use Magento\RelatedProductGraphQl\Model\DataProvider\RelatedProductDataProvider; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; @@ -18,17 +21,25 @@ class RelatedProducts implements ResolverInterface { /** - * @var RelatedDataProvider + * @var ProductFieldsSelector */ - private $dataProvider; + private $productFieldsSelector; /** - * @param RelatedDataProvider $dataProvider + * @var RelatedProductDataProvider + */ + private $relatedProductDataProvider; + + /** + * @param ProductFieldsSelector $productFieldsSelector + * @param RelatedProductDataProvider $relatedProductDataProvider */ public function __construct( - RelatedDataProvider $dataProvider + ProductFieldsSelector $productFieldsSelector, + RelatedProductDataProvider $relatedProductDataProvider ) { - $this->dataProvider = $dataProvider; + $this->productFieldsSelector = $productFieldsSelector; + $this->relatedProductDataProvider = $relatedProductDataProvider; } /** @@ -36,8 +47,13 @@ public function __construct( */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { - $data = $this->dataProvider->getProducts($info, $value); + if (!isset($value['model'])) { + throw new LocalizedException(__('"model" value should be specified')); + } + $product = $value['model']; + $fields = $this->productFieldsSelector->getProductFieldsFromInfo($info, 'related_products'); + $data = $this->relatedProductDataProvider->getData($product, $fields, Link::LINK_TYPE_RELATED); return $data; } } diff --git a/app/code/Magento/RelatedProductGraphQl/Model/Resolver/UpSellProducts.php b/app/code/Magento/RelatedProductGraphQl/Model/Resolver/UpSellProducts.php index 5299b43f5f54f..df3a62408c53f 100644 --- a/app/code/Magento/RelatedProductGraphQl/Model/Resolver/UpSellProducts.php +++ b/app/code/Magento/RelatedProductGraphQl/Model/Resolver/UpSellProducts.php @@ -7,7 +7,10 @@ namespace Magento\RelatedProductGraphQl\Model\Resolver; -use Magento\RelatedProductGraphQl\Model\DataProvider\RelatedDataProvider; +use Magento\Catalog\Model\Product\Link; +use Magento\CatalogGraphQl\Model\Resolver\Product\ProductFieldsSelector; +use Magento\Framework\Exception\LocalizedException; +use Magento\RelatedProductGraphQl\Model\DataProvider\RelatedProductDataProvider; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; @@ -18,18 +21,25 @@ class UpSellProducts implements ResolverInterface { /** - * @see module di.xml - * @var RelatedDataProvider + * @var ProductFieldsSelector */ - private $dataProvider; + private $productFieldsSelector; /** - * @param RelatedDataProvider $dataProvider + * @var RelatedProductDataProvider + */ + private $relatedProductDataProvider; + + /** + * @param ProductFieldsSelector $productFieldsSelector + * @param RelatedProductDataProvider $relatedProductDataProvider */ public function __construct( - RelatedDataProvider $dataProvider + ProductFieldsSelector $productFieldsSelector, + RelatedProductDataProvider $relatedProductDataProvider ) { - $this->dataProvider = $dataProvider; + $this->productFieldsSelector = $productFieldsSelector; + $this->relatedProductDataProvider = $relatedProductDataProvider; } /** @@ -37,8 +47,13 @@ public function __construct( */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { - $data = $this->dataProvider->getProducts($info, $value); + if (!isset($value['model'])) { + throw new LocalizedException(__('"model" value should be specified')); + } + $product = $value['model']; + $fields = $this->productFieldsSelector->getProductFieldsFromInfo($info, 'upsell_products'); + $data = $this->relatedProductDataProvider->getData($product, $fields, Link::LINK_TYPE_UPSELL); return $data; } } diff --git a/app/code/Magento/RelatedProductGraphQl/etc/graphql/di.xml b/app/code/Magento/RelatedProductGraphQl/etc/graphql/di.xml deleted file mode 100644 index f64cf197b250f..0000000000000 --- a/app/code/Magento/RelatedProductGraphQl/etc/graphql/di.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> - <virtualType name="Magento\RelatedProductGraphQl\Model\DataProvider\CrossSellDataProvider" type="Magento\RelatedProductGraphQl\Model\DataProvider\RelatedDataProvider"> - <arguments> - <argument name="linkType" xsi:type="const">Magento\Catalog\Model\Product\Link::LINK_TYPE_CROSSSELL</argument> - <argument name="schemaNodeName" xsi:type="string">crosssell_products</argument> - </arguments> - </virtualType> - <type name="Magento\RelatedProductGraphQl\Model\Resolver\CrossSellProducts"> - <arguments> - <argument name="dataProvider" xsi:type="object">Magento\RelatedProductGraphQl\Model\DataProvider\CrossSellDataProvider</argument> - </arguments> - </type> - <virtualType name="Magento\RelatedProductGraphQl\Model\DataProvider\UpSellDataProvider" type="Magento\RelatedProductGraphQl\Model\DataProvider\RelatedDataProvider"> - <arguments> - <argument name="linkType" xsi:type="const">Magento\Catalog\Model\Product\Link::LINK_TYPE_UPSELL</argument> - <argument name="schemaNodeName" xsi:type="string">upsell_products</argument> - </arguments> - </virtualType> - <type name="Magento\RelatedProductGraphQl\Model\Resolver\UpSellProducts"> - <arguments> - <argument name="dataProvider" xsi:type="object">Magento\RelatedProductGraphQl\Model\DataProvider\UpSellDataProvider</argument> - </arguments> - </type> -</config> diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/GetRelatedProductsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/GetRelatedProductsTest.php new file mode 100644 index 0000000000000..3c0b578d850b9 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/GetRelatedProductsTest.php @@ -0,0 +1,178 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types=1); + +namespace Magento\GraphQl\RelatedProduct; + +use Magento\TestFramework\TestCase\GraphQlAbstract; + +/** + * Get related products test + */ +class GetRelatedProductsTest extends GraphQlAbstract +{ + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_related_multiple.php + */ + public function testQueryRelatedProducts() + { + $productSku = 'simple_with_cross'; + + $query = <<<QUERY +{ + products(filter: {sku: {eq: "{$productSku}"}}) + { + items { + related_products + { + sku + name + url_key + id + created_at + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey('products', $response); + self::assertArrayHasKey('items', $response['products']); + self::assertEquals(1, count($response['products']['items'])); + self::assertArrayHasKey(0, $response['products']['items']); + self::assertArrayHasKey('related_products', $response['products']['items'][0]); + $relatedProducts = $response['products']['items'][0]['related_products']; + self::assertCount(2, $relatedProducts); + self::assertRelatedProducts($relatedProducts); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_crosssell.php + */ + public function testQueryCrossSellProducts() + { + $productSku = 'simple_with_cross'; + + $query = <<<QUERY +{ + products(filter: {sku: {eq: "{$productSku}"}}) + { + items { + crosssell_products + { + sku + name + url_key + id + created_at + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey('products', $response); + self::assertArrayHasKey('items', $response['products']); + self::assertEquals(1, count($response['products']['items'])); + self::assertArrayHasKey(0, $response['products']['items']); + self::assertArrayHasKey('crosssell_products', $response['products']['items'][0]); + $crossSellProducts = $response['products']['items'][0]['crosssell_products']; + self::assertCount(1, $crossSellProducts); + $crossSellProduct = $crossSellProducts[0]; + self::assertArrayHasKey('sku', $crossSellProduct); + self::assertArrayHasKey('name', $crossSellProduct); + self::assertArrayHasKey('url_key', $crossSellProduct); + self::assertArrayHasKey('id', $crossSellProduct); + self::assertArrayHasKey('created_at', $crossSellProduct); + self::assertEquals($crossSellProduct['sku'], 'simple'); + self::assertEquals($crossSellProduct['name'], 'Simple Cross Sell'); + self::assertEquals($crossSellProduct['url_key'], 'simple-cross-sell'); + self::assertNotEmpty($crossSellProduct['created_at']); + self::assertNotEmpty($crossSellProduct['id']); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_upsell.php + */ + public function testQueryUpSellProducts() + { + $productSku = 'simple_with_upsell'; + + $query = <<<QUERY +{ + products(filter: {sku: {eq: "{$productSku}"}}) + { + items { + upsell_products + { + sku + name + url_key + id + created_at + } + } + } +} +QUERY; + $response = $this->graphQlQuery($query); + + self::assertArrayHasKey('products', $response); + self::assertArrayHasKey('items', $response['products']); + self::assertEquals(1, count($response['products']['items'])); + self::assertArrayHasKey(0, $response['products']['items']); + self::assertArrayHasKey('upsell_products', $response['products']['items'][0]); + $upSellProducts = $response['products']['items'][0]['upsell_products']; + self::assertCount(1, $upSellProducts); + $upSellProduct = $upSellProducts[0]; + self::assertArrayHasKey('sku', $upSellProduct); + self::assertArrayHasKey('name', $upSellProduct); + self::assertArrayHasKey('url_key', $upSellProduct); + self::assertArrayHasKey('id', $upSellProduct); + self::assertArrayHasKey('created_at', $upSellProduct); + self::assertEquals($upSellProduct['sku'], 'simple'); + self::assertEquals($upSellProduct['name'], 'Simple Up Sell'); + self::assertEquals($upSellProduct['url_key'], 'simple-up-sell'); + self::assertNotEmpty($upSellProduct['created_at']); + self::assertNotEmpty($upSellProduct['id']); + } + + /** + * @param array $relatedProducts + */ + private function assertRelatedProducts(array $relatedProducts): void + { + $expectedData = [ + 'simple' => [ + 'name' => 'Simple Related Product', + 'url_key' => 'simple-related-product', + + ], + 'simple_with_cross_two' => [ + 'name' => 'Simple Product With Related Product Two', + 'url_key' => 'simple-product-with-related-product-two', + ] + ]; + + foreach ($relatedProducts as $product) { + self::assertArrayHasKey('sku', $product); + self::assertArrayHasKey('name', $product); + self::assertArrayHasKey('url_key', $product); + self::assertArrayHasKey('id', $product); + self::assertArrayHasKey('created_at', $product); + + self::assertArrayHasKey($product['sku'], $expectedData); + $productExpectedData = $expectedData[$product['sku']]; + + self::assertEquals($product['name'], $productExpectedData['name']); + self::assertEquals($product['url_key'], $productExpectedData['url_key']); + self::assertNotEmpty($product['created_at']); + self::assertNotEmpty($product['id']); + } + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/ProductRelatedProductsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/ProductRelatedProductsTest.php deleted file mode 100644 index 5317e88d7e118..0000000000000 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/ProductRelatedProductsTest.php +++ /dev/null @@ -1,175 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types=1); - -namespace Magento\GraphQl\RelatedProduct; - -use Magento\TestFramework\TestCase\GraphQlAbstract; - -class ProductRelatedProductsTest extends GraphQlAbstract -{ - /** - * @magentoApiDataFixture Magento/Catalog/_files/products_related_multiple.php - */ - public function testQueryRelatedProducts() - { - $productSku = 'simple_with_cross'; - - $query = <<<QUERY -{ - products(filter: {sku: {eq: "{$productSku}"}}) - { - items { - related_products - { - sku - name - url_key - id - created_at - } - } - } -} -QUERY; - $response = $this->graphQlQuery($query); - - $this->assertArrayHasKey('products', $response); - $this->assertArrayHasKey('items', $response['products']); - $this->assertEquals(1, count($response['products']['items'])); - $this->assertArrayHasKey(0, $response['products']['items']); - $this->assertArrayHasKey('related_products', $response['products']['items'][0]); - $relatedProducts = $response['products']['items'][0]['related_products']; - $this->assertCount(2, $relatedProducts); - $this->assertRelatedProducts($relatedProducts); - } - - /** - * @magentoApiDataFixture Magento/Catalog/_files/products_crosssell.php - */ - public function testQueryCrossSellProducts() - { - $productSku = 'simple_with_cross'; - - $query = <<<QUERY -{ - products(filter: {sku: {eq: "{$productSku}"}}) - { - items { - crosssell_products - { - sku - name - url_key - id - created_at - } - } - } -} -QUERY; - $response = $this->graphQlQuery($query); - - $this->assertArrayHasKey('products', $response); - $this->assertArrayHasKey('items', $response['products']); - $this->assertEquals(1, count($response['products']['items'])); - $this->assertArrayHasKey(0, $response['products']['items']); - $this->assertArrayHasKey('crosssell_products', $response['products']['items'][0]); - $crossSellProducts = $response['products']['items'][0]['crosssell_products']; - $this->assertCount(1, $crossSellProducts); - $crossSellProduct = $crossSellProducts[0]; - $this->assertArrayHasKey('sku', $crossSellProduct); - $this->assertArrayHasKey('name', $crossSellProduct); - $this->assertArrayHasKey('url_key', $crossSellProduct); - $this->assertArrayHasKey('id', $crossSellProduct); - $this->assertArrayHasKey('created_at', $crossSellProduct); - $this->assertEquals($crossSellProduct['sku'], 'simple'); - $this->assertEquals($crossSellProduct['name'], 'Simple Cross Sell'); - $this->assertEquals($crossSellProduct['url_key'], 'simple-cross-sell'); - $this->assertNotEmpty($crossSellProduct['created_at']); - $this->assertNotEmpty($crossSellProduct['id']); - } - - /** - * @magentoApiDataFixture Magento/Catalog/_files/products_upsell.php - */ - public function testQueryUpSellProducts() - { - $productSku = 'simple_with_upsell'; - - $query = <<<QUERY -{ - products(filter: {sku: {eq: "{$productSku}"}}) - { - items { - upsell_products - { - sku - name - url_key - id - created_at - } - } - } -} -QUERY; - $response = $this->graphQlQuery($query); - - $this->assertArrayHasKey('products', $response); - $this->assertArrayHasKey('items', $response['products']); - $this->assertEquals(1, count($response['products']['items'])); - $this->assertArrayHasKey(0, $response['products']['items']); - $this->assertArrayHasKey('upsell_products', $response['products']['items'][0]); - $upSellProducts = $response['products']['items'][0]['upsell_products']; - $this->assertCount(1, $upSellProducts); - $upSellProduct = $upSellProducts[0]; - $this->assertArrayHasKey('sku', $upSellProduct); - $this->assertArrayHasKey('name', $upSellProduct); - $this->assertArrayHasKey('url_key', $upSellProduct); - $this->assertArrayHasKey('id', $upSellProduct); - $this->assertArrayHasKey('created_at', $upSellProduct); - $this->assertEquals($upSellProduct['sku'], 'simple'); - $this->assertEquals($upSellProduct['name'], 'Simple Up Sell'); - $this->assertEquals($upSellProduct['url_key'], 'simple-up-sell'); - $this->assertNotEmpty($upSellProduct['created_at']); - $this->assertNotEmpty($upSellProduct['id']); - } - - /** - * @param array $relatedProducts - */ - private function assertRelatedProducts(array $relatedProducts): void - { - $expectedData = [ - 'simple' => [ - 'name' => 'Simple Related Product', - 'url_key' => 'simple-related-product', - - ], - 'simple_with_cross_two' => [ - 'name' => 'Simple Product With Related Product Two', - 'url_key' => 'simple-product-with-related-product-two', - ] - ]; - - foreach ($relatedProducts as $product) { - $this->assertArrayHasKey('sku', $product); - $this->assertArrayHasKey('name', $product); - $this->assertArrayHasKey('url_key', $product); - $this->assertArrayHasKey('id', $product); - $this->assertArrayHasKey('created_at', $product); - - $this->assertArrayHasKey($product['sku'], $expectedData); - $productExpectedData = $expectedData[$product['sku']]; - - $this->assertEquals($product['name'], $productExpectedData['name']); - $this->assertEquals($product['url_key'], $productExpectedData['url_key']); - $this->assertNotEmpty($product['created_at']); - $this->assertNotEmpty($product['id']); - } - } -} From 92d6feb32078960f3dce422482c351629bb87cf2 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 8 May 2019 12:29:40 -0500 Subject: [PATCH 207/224] GraphQl-198: Products: access to related/up-sell/cross-sell product fields --- .../CatalogGraphQl/Model/Resolver/Product.php | 14 +------------- .../DataProvider/RelatedProductDataProvider.php | 9 +++++---- app/code/Magento/RelatedProductGraphQl/README.md | 3 +++ .../RelatedProduct/GetRelatedProductsTest.php | 9 --------- 4 files changed, 9 insertions(+), 26 deletions(-) create mode 100644 app/code/Magento/RelatedProductGraphQl/README.md diff --git a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product.php b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product.php index b3283883f5561..86137990cc57d 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Resolver/Product.php +++ b/app/code/Magento/CatalogGraphQl/Model/Resolver/Product.php @@ -9,10 +9,8 @@ use Magento\CatalogGraphQl\Model\Resolver\Product\ProductFieldsSelector; use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Deferred\Product as ProductDataProvider; -use Magento\Framework\App\ObjectManager; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Exception\GraphQlInputException; -use Magento\Framework\GraphQl\Query\FieldTranslator; use Magento\Framework\GraphQl\Query\Resolver\ValueFactory; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; @@ -32,12 +30,6 @@ class Product implements ResolverInterface */ private $valueFactory; - /** - * @deprecated - * @var FieldTranslator - */ - private $fieldTranslator; - /** * @var ProductFieldsSelector */ @@ -46,20 +38,16 @@ class Product implements ResolverInterface /** * @param ProductDataProvider $productDataProvider * @param ValueFactory $valueFactory - * @param FieldTranslator $fieldTranslator * @param ProductFieldsSelector $productFieldsSelector */ public function __construct( ProductDataProvider $productDataProvider, ValueFactory $valueFactory, - FieldTranslator $fieldTranslator, ProductFieldsSelector $productFieldsSelector ) { $this->productDataProvider = $productDataProvider; $this->valueFactory = $valueFactory; - $this->fieldTranslator = $fieldTranslator; - $this->productFieldsSelector = $productFieldsSelector - ?? ObjectManager::getInstance()->get(ProductFieldsSelector::class); + $this->productFieldsSelector = $productFieldsSelector; } /** diff --git a/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedProductDataProvider.php b/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedProductDataProvider.php index 04a71da0337de..173c0a94312ee 100644 --- a/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedProductDataProvider.php +++ b/app/code/Magento/RelatedProductGraphQl/Model/DataProvider/RelatedProductDataProvider.php @@ -42,12 +42,13 @@ public function getData(Product $product, array $fields, int $linkType): array { $relatedProducts = $this->getRelatedProducts($product, $fields, $linkType); - $data = []; + $productsData = []; foreach ($relatedProducts as $relatedProduct) { - $relatedProductData = $relatedProduct->getData(); - $relatedProductData['model'] = $relatedProduct; + $productData = $relatedProduct->getData(); + $productData['model'] = $relatedProduct; + $productsData[] = $productData; } - return $data; + return $productsData; } /** diff --git a/app/code/Magento/RelatedProductGraphQl/README.md b/app/code/Magento/RelatedProductGraphQl/README.md new file mode 100644 index 0000000000000..5b57af5af9884 --- /dev/null +++ b/app/code/Magento/RelatedProductGraphQl/README.md @@ -0,0 +1,3 @@ +# RelatedProductGraphQl + +**RelatedProductGraphQl** provides endpoints for getting Cross Sell / Related/ Up Sell products data. \ No newline at end of file diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/GetRelatedProductsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/GetRelatedProductsTest.php index 3c0b578d850b9..dff1301e12f11 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/GetRelatedProductsTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/RelatedProduct/GetRelatedProductsTest.php @@ -31,7 +31,6 @@ public function testQueryRelatedProducts() sku name url_key - id created_at } } @@ -67,7 +66,6 @@ public function testQueryCrossSellProducts() sku name url_key - id created_at } } @@ -87,13 +85,11 @@ public function testQueryCrossSellProducts() self::assertArrayHasKey('sku', $crossSellProduct); self::assertArrayHasKey('name', $crossSellProduct); self::assertArrayHasKey('url_key', $crossSellProduct); - self::assertArrayHasKey('id', $crossSellProduct); self::assertArrayHasKey('created_at', $crossSellProduct); self::assertEquals($crossSellProduct['sku'], 'simple'); self::assertEquals($crossSellProduct['name'], 'Simple Cross Sell'); self::assertEquals($crossSellProduct['url_key'], 'simple-cross-sell'); self::assertNotEmpty($crossSellProduct['created_at']); - self::assertNotEmpty($crossSellProduct['id']); } /** @@ -113,7 +109,6 @@ public function testQueryUpSellProducts() sku name url_key - id created_at } } @@ -133,13 +128,11 @@ public function testQueryUpSellProducts() self::assertArrayHasKey('sku', $upSellProduct); self::assertArrayHasKey('name', $upSellProduct); self::assertArrayHasKey('url_key', $upSellProduct); - self::assertArrayHasKey('id', $upSellProduct); self::assertArrayHasKey('created_at', $upSellProduct); self::assertEquals($upSellProduct['sku'], 'simple'); self::assertEquals($upSellProduct['name'], 'Simple Up Sell'); self::assertEquals($upSellProduct['url_key'], 'simple-up-sell'); self::assertNotEmpty($upSellProduct['created_at']); - self::assertNotEmpty($upSellProduct['id']); } /** @@ -163,7 +156,6 @@ private function assertRelatedProducts(array $relatedProducts): void self::assertArrayHasKey('sku', $product); self::assertArrayHasKey('name', $product); self::assertArrayHasKey('url_key', $product); - self::assertArrayHasKey('id', $product); self::assertArrayHasKey('created_at', $product); self::assertArrayHasKey($product['sku'], $expectedData); @@ -172,7 +164,6 @@ private function assertRelatedProducts(array $relatedProducts): void self::assertEquals($product['name'], $productExpectedData['name']); self::assertEquals($product['url_key'], $productExpectedData['url_key']); self::assertNotEmpty($product['created_at']); - self::assertNotEmpty($product['id']); } } } From 30b7000c83fa92cbb0738141528be915f0412a76 Mon Sep 17 00:00:00 2001 From: "Lopukhov, Stanislav" <lopukhov@adobe.com> Date: Wed, 8 May 2019 13:04:18 -0500 Subject: [PATCH 208/224] MC-16312: Revert fix ENGCOM-1351 --- app/code/Magento/Sitemap/Model/ResourceModel/Catalog/Product.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Sitemap/Model/ResourceModel/Catalog/Product.php b/app/code/Magento/Sitemap/Model/ResourceModel/Catalog/Product.php index 7ad1fe7405dee..9f4f698458cf8 100644 --- a/app/code/Magento/Sitemap/Model/ResourceModel/Catalog/Product.php +++ b/app/code/Magento/Sitemap/Model/ResourceModel/Catalog/Product.php @@ -194,7 +194,6 @@ protected function _addFilter($storeId, $attributeCode, $value, $type = '=') break; default: return false; - break; } $attribute = $this->_getAttribute($attributeCode); From 787d31b2f9d7eba3de123c5bcb799f8ff016b9d0 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 8 May 2019 13:16:42 -0500 Subject: [PATCH 209/224] GraphQl-387: Test coverage of getting IDs of CMS page/blocks by GraphQL API --- .../Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php | 2 ++ app/code/Magento/CmsGraphQl/Model/Resolver/Page.php | 2 +- .../testsuite/Magento/GraphQl/Cms/CmsBlockTest.php | 3 +++ .../testsuite/Magento/GraphQl/Cms/CmsPageTest.php | 3 +++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php index 8b9766ca311c7..40825e70a994e 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Page.php @@ -88,6 +88,8 @@ public function getDataByPageIdentifier(string $pageIdentifier): array } /** + * Convert page data + * * @param PageInterface $page * @return array * @throws NoSuchEntityException diff --git a/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php b/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php index fbd8e26030952..64891cfeaa87a 100644 --- a/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php +++ b/app/code/Magento/CmsGraphQl/Model/Resolver/Page.php @@ -45,7 +45,7 @@ public function resolve( array $value = null, array $args = null ) { - if (!isset($args['id'], $args['identifier'])) { + if (!isset($args['id']) && !isset($args['identifier'])) { throw new GraphQlInputException(__('"Page id/identifier should be specified')); } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsBlockTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsBlockTest.php index 542b00d434db0..d598a463a48a7 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsBlockTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsBlockTest.php @@ -13,6 +13,9 @@ use Magento\TestFramework\TestCase\GraphQlAbstract; use Magento\Widget\Model\Template\FilterEmulate; +/** + * Get CMS Block test + */ class CmsBlockTest extends GraphQlAbstract { /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsPageTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsPageTest.php index 53e47185c9866..afbb3d40bc921 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsPageTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsPageTest.php @@ -11,6 +11,9 @@ use Magento\TestFramework\ObjectManager; use Magento\TestFramework\TestCase\GraphQlAbstract; +/** + * Get CMS Page test + */ class CmsPageTest extends GraphQlAbstract { /** From d14baa048530905d083b4a0cc1fbf8cc18a5022f Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Wed, 8 May 2019 13:29:47 -0500 Subject: [PATCH 210/224] Add testCaseId to test annotation - issue magento/magento-functional-tests-migration/578 - pull request magento/magento-functional-tests-migration/685 --- .../Test/Mftf/Test/StorefrontCreateExistingCustomerTest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateExistingCustomerTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateExistingCustomerTest.xml index 323174777c265..7442f8f2ffacb 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateExistingCustomerTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontCreateExistingCustomerTest.xml @@ -13,6 +13,7 @@ <features value="Customer"/> <title value="Attempt to register customer on storefront with existing email"/> <description value="Attempt to register customer on storefront with existing email"/> + <testCaseId value="MC-10907" /> <group value="customers"/> <group value="mtf_migrated"/> </annotations> From f6f0f8463a49e215112ed4d48ffd79a923580f4a Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Wed, 8 May 2019 15:13:18 -0500 Subject: [PATCH 211/224] MC-1540: Deliver weekly MTF conversion PR fixed error on PR build --- .../ActionGroup/LoginAsCustomerOnCheckoutPageActionGroup.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/LoginAsCustomerOnCheckoutPageActionGroup.xml b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/LoginAsCustomerOnCheckoutPageActionGroup.xml index 26d926d18a380..88dd1d01c5f8f 100644 --- a/app/code/Magento/Checkout/Test/Mftf/ActionGroup/LoginAsCustomerOnCheckoutPageActionGroup.xml +++ b/app/code/Magento/Checkout/Test/Mftf/ActionGroup/LoginAsCustomerOnCheckoutPageActionGroup.xml @@ -18,8 +18,10 @@ <waitForElementVisible selector="{{CheckoutShippingSection.password}}" stepKey="waitForElementVisible"/> <fillField selector="{{CheckoutShippingSection.password}}" userInput="{{customer.password}}" stepKey="fillPasswordField"/> <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear2"/> + <waitForElementVisible selector="{{CheckoutShippingSection.loginButton}}" stepKey="waitForLoginButtonVisible"/> <doubleClick selector="{{CheckoutShippingSection.loginButton}}" stepKey="clickLoginBtn"/> <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear3"/> - <waitForPageLoad stepKey="waitForLogin"/> + <waitForPageLoad stepKey="waitToBeLoggedIn"/> + <waitForElementNotVisible selector="{{CheckoutShippingSection.email}}" userInput="{{customer.email}}" stepKey="waitForEmailInvisible" time ="60"/> </actionGroup> </actionGroups> From dcbf99bcc8c53879049ccdd4e03d957838ac68ac Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 8 May 2019 15:28:26 -0500 Subject: [PATCH 212/224] GraphQl-198: Products: access to related/up-sell/cross-sell product fields -- Update composer.lock --- composer.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.lock b/composer.lock index 77783c00dd641..4e052c61fd460 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "24c95683a202b83c7f182921c0c88328", + "content-hash": "33e7703ac47e1c27235b830825e14800", "packages": [ { "name": "braintree/braintree_php", @@ -6775,12 +6775,12 @@ "version": "v1.6.5", "source": { "type": "git", - "url": "https://github.com/mikey179/vfsStream.git", + "url": "https://github.com/bovigo/vfsStream.git", "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", + "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", "shasum": "" }, From 06f04270b8c82c77e31faced16026ae52fe94dd6 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 8 May 2019 15:39:55 -0500 Subject: [PATCH 213/224] GraphQl-689: testBundleProductWithNotVisibleChildren fix misspelling --- .../testsuite/Magento/GraphQl/Bundle/BundleProductViewTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Bundle/BundleProductViewTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Bundle/BundleProductViewTest.php index 20d097906d7e7..d5d34e48d77c3 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Bundle/BundleProductViewTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Bundle/BundleProductViewTest.php @@ -15,6 +15,9 @@ use Magento\TestFramework\ObjectManager; use Magento\TestFramework\TestCase\GraphQlAbstract; +/** + * Bundle product view test + */ class BundleProductViewTest extends GraphQlAbstract { const KEY_PRICE_TYPE_FIXED = 'FIXED'; From 89b5c7d9f685677dbab9e0fc99231be1a6d70fb7 Mon Sep 17 00:00:00 2001 From: Oleksii Korshenko <korshenk@adobe.com> Date: Wed, 8 May 2019 16:05:39 -0500 Subject: [PATCH 214/224] Renamed travis.yml file to travis.yml.sample - travis build is not required on magento2 repository - all required builds are implemented as GitHub checks --- .travis.yml => .travis.yml.sample | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .travis.yml => .travis.yml.sample (100%) diff --git a/.travis.yml b/.travis.yml.sample similarity index 100% rename from .travis.yml rename to .travis.yml.sample From ad254063a59011579eecd429e1fbae7e7f1da376 Mon Sep 17 00:00:00 2001 From: Oleksii Korshenko <korshenk@adobe.com> Date: Wed, 8 May 2019 16:12:17 -0500 Subject: [PATCH 215/224] Renamed travis.yml file to travis.yml.sample - updated Pull Request teample. Travis is not required --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f191bd9aaba67..9d66ee40d6f59 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -35,4 +35,4 @@ - [ ] Pull request has a meaningful description of its purpose - [ ] All commits are accompanied by meaningful commit messages - [ ] All new or changed code is covered with unit/integration tests (if applicable) - - [ ] All automated tests passed successfully (all builds on Travis CI are green) + - [ ] All automated tests passed successfully (all builds are green) From bb5df5108196692245d74a7c75fef3f34f437982 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Wed, 8 May 2019 16:17:41 -0500 Subject: [PATCH 216/224] Add testCaseId to test annotation - issue magento/magento-functional-tests-migration/276 - pull request magento/magento-functional-tests-migration/690 - moved config data to module which declares it --- .../Test/AdminLoginAfterJSMinificationTest.xml | 1 + .../Config/Test/Mftf/Data/SystemConfigData.xml | 15 --------------- .../Store/Test/Mftf/Data/StoreConfigData.xml | 15 +++++++++++++++ 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml index 4be6d18d92020..baa229ed2e146 100644 --- a/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml +++ b/app/code/Magento/Backend/Test/Mftf/Test/AdminLoginAfterJSMinificationTest.xml @@ -13,6 +13,7 @@ <features value="Backend"/> <title value="Admin panel should be accessible with JS minification enabled"/> <description value="Admin panel should be accessible with JS minification enabled"/> + <testCaseId value="MC-14104" /> <group value="backend"/> <group value="mtf_migrated"/> </annotations> diff --git a/app/code/Magento/Config/Test/Mftf/Data/SystemConfigData.xml b/app/code/Magento/Config/Test/Mftf/Data/SystemConfigData.xml index 7b838dffd7661..85188eb6e04cb 100644 --- a/app/code/Magento/Config/Test/Mftf/Data/SystemConfigData.xml +++ b/app/code/Magento/Config/Test/Mftf/Data/SystemConfigData.xml @@ -20,19 +20,4 @@ <entity name="DisableAdminAccountSharing" type="admin_account_sharing_config"> <requiredEntity type="admin_account_sharing_value">AdminAccountSharingNo</requiredEntity> </entity> - <entity name="MinifyJavaScriptFilesDisableConfigData"> - <!-- Default value --> - <data key="path">dev/js/minify_files</data> - <data key="scope">admin</data> - <data key="scope_id">0</data> - <data key="label">No</data> - <data key="value">0</data> - </entity> - <entity name="MinifyJavaScriptFilesEnableConfigData"> - <data key="path">dev/js/minify_files</data> - <data key="scope">admin</data> - <data key="scope_id">0</data> - <data key="label">Yes</data> - <data key="value">1</data> - </entity> </entities> diff --git a/app/code/Magento/Store/Test/Mftf/Data/StoreConfigData.xml b/app/code/Magento/Store/Test/Mftf/Data/StoreConfigData.xml index 4333446925474..9f4de2ffb5723 100644 --- a/app/code/Magento/Store/Test/Mftf/Data/StoreConfigData.xml +++ b/app/code/Magento/Store/Test/Mftf/Data/StoreConfigData.xml @@ -21,4 +21,19 @@ <data key="label">Yes</data> <data key="value">1</data> </entity> + <entity name="MinifyJavaScriptFilesDisableConfigData"> + <!-- Default value --> + <data key="path">dev/js/minify_files</data> + <data key="scope">admin</data> + <data key="scope_id">0</data> + <data key="label">No</data> + <data key="value">0</data> + </entity> + <entity name="MinifyJavaScriptFilesEnableConfigData"> + <data key="path">dev/js/minify_files</data> + <data key="scope">admin</data> + <data key="scope_id">0</data> + <data key="label">Yes</data> + <data key="value">1</data> + </entity> </entities> From b0919e8422680d8893c66c8cd6025bc00083cb76 Mon Sep 17 00:00:00 2001 From: Valerii Naida <vnayda@adobe.com> Date: Wed, 8 May 2019 17:47:17 -0500 Subject: [PATCH 217/224] GraphQl-198: Products: access to related/up-sell/cross-sell product fields -- Update composer.lock --- .../CatalogUrlRewrite/_files/product_with_category_rollback.php | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/CatalogUrlRewrite/_files/product_with_category_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogUrlRewrite/_files/product_with_category_rollback.php index 3a1e379213342..61e2d84513f15 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogUrlRewrite/_files/product_with_category_rollback.php +++ b/dev/tests/integration/testsuite/Magento/CatalogUrlRewrite/_files/product_with_category_rollback.php @@ -21,7 +21,6 @@ /** @var ProductRepositoryInterface $productRepository */ $productRepository = $objectManager->get(ProductRepositoryInterface::class); -//$productRepository->deleteById('p002'); $product = $productRepository->get('p002', false, null, true); $productRepository->delete($product); From 41e0337c6cb82eb223d1cbb5b656f4a5136e2a8f Mon Sep 17 00:00:00 2001 From: Oleksii Korshenko <korshenk@adobe.com> Date: Thu, 9 May 2019 10:17:10 -0500 Subject: [PATCH 218/224] Renamed travis.yml file to travis.yml.sample - updated readme file --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ecd457a4f1aef..73154c18d891d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -[![Build Status](https://travis-ci.org/magento/magento2.svg?branch=2.3-develop)](https://travis-ci.org/magento/magento2) [![Open Source Helpers](https://www.codetriage.com/magento/magento2/badges/users.svg)](https://www.codetriage.com/magento/magento2) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/magento/magento2?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/magento-2/localized.svg)](https://crowdin.com/project/magento-2) From 68299cfc3edc8179cc965076dc6d6f05d9ccdd2d Mon Sep 17 00:00:00 2001 From: Hwashiang Yu <hwyu@adobe.com> Date: Thu, 9 May 2019 10:29:55 -0500 Subject: [PATCH 219/224] MAGETWO-94807: Storefront Shop By collapsible button works in a mobile theme - Updated test annotation --- .../Test/Mftf/Test/ShopByButtonInMobile.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/LayeredNavigation/Test/Mftf/Test/ShopByButtonInMobile.xml b/app/code/Magento/LayeredNavigation/Test/Mftf/Test/ShopByButtonInMobile.xml index 28b937f61ee95..721942f58f7cc 100644 --- a/app/code/Magento/LayeredNavigation/Test/Mftf/Test/ShopByButtonInMobile.xml +++ b/app/code/Magento/LayeredNavigation/Test/Mftf/Test/ShopByButtonInMobile.xml @@ -11,11 +11,11 @@ <test name="ShopByButtonInMobile"> <annotations> <features value="Layered Navigation"/> - <stories value="Shop By button is not working in a mobile theme"/> - <title value="Layered Navigation"/> - <description value="Storefront Shop By collapsible button works in a mobile theme"/> + <stories value="Storefront Shop By collapsible button in mobile themes"/> + <title value="Storefront Shop By collapsible button works in a mobile theme"/> + <description value="Storefront Shop By collapsible button should work in a mobile theme"/> <severity value="CRITICAL"/> - <testCaseId value="MAGETWO-94873"/> + <testCaseId value="MC-6092"/> <group value="LayeredNavigation"/> </annotations> <before> From 744852f58ccd20078215a07056563ddf919cdcda Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@adobe.com> Date: Fri, 10 May 2019 08:56:32 -0500 Subject: [PATCH 220/224] magento-engcom/magento2ce#2824: Suppress phpcs warning --- .../Catalog/Block/Product/View/Options/AbstractOptions.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php b/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php index c0a271a0e229c..030b6e1d2204c 100644 --- a/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php +++ b/app/code/Magento/Catalog/Block/Product/View/Options/AbstractOptions.php @@ -17,6 +17,7 @@ /** * Product options section abstract block. * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @since 100.0.2 */ From e70ab3ba9997e617fb3ebfc244e0540f611b4e19 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov <sidolov@adobe.com> Date: Fri, 10 May 2019 08:56:39 -0500 Subject: [PATCH 221/224] magento-engcom/magento2ce#2824: Suppress phpcs warning --- app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php b/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php index 48bbbf0898219..78b6b7d6c9ab7 100644 --- a/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php +++ b/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php @@ -8,6 +8,7 @@ /** * Reports Product Index Abstract Model * + * phpcs:disable Magento2.Classes.AbstractApi * @api * @since 100.0.2 * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) From ba07e75882ff9ed25d67ff02514be61c3db552a1 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 10 May 2019 12:05:24 -0500 Subject: [PATCH 222/224] Add testCaseId to test annotation - issue magento/magento-functional-tests-migration/623 - pull request magento/magento-functional-tests-migration/703 - test fixes --- ...minCMSPageMassActionSelectActionGroup.xml} | 9 ++-- .../AdminOpenCMSPagesGridActionGroup.xml | 2 +- .../AdminSelectCMSPageInGridActionGroup.xml | 2 +- .../AssertCMSPageInGridActionGroup.xml | 17 ++----- ...CMSPageNotFoundOnStorefrontActionGroup.xml | 2 +- .../StorefrontGoToCMSPageActionGroup.xml | 2 +- .../Section/CmsPagesPageActionsSection.xml | 6 +-- .../Mftf/Test/AdminCmsPageMassActionTest.xml | 50 ++++++++++++++----- .../AdminGridFilterApplyActionGroup.xml} | 11 ++-- ...minGridFilterFillInputFieldActionGroup.xml | 21 ++++++++ .../AdminGridFilterResetActionGroup.xml | 16 ++++++ .../Section/AdminDataGridFilterSection.xml | 18 +++++++ .../Section/AdminDataGridTableSection.xml | 2 + 13 files changed, 117 insertions(+), 41 deletions(-) rename app/code/Magento/Cms/Test/Mftf/ActionGroup/{AdminCMSPageMassActionDisableActionGroup.xml => AdminCMSPageMassActionSelectActionGroup.xml} (72%) rename app/code/Magento/{Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageFromGridActionGroup.xml => Ui/Test/Mftf/ActionGroup/AdminGridFilterApplyActionGroup.xml} (53%) create mode 100644 app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterFillInputFieldActionGroup.xml create mode 100644 app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterResetActionGroup.xml create mode 100644 app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridFilterSection.xml diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionDisableActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionSelectActionGroup.xml similarity index 72% rename from app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionDisableActionGroup.xml rename to app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionSelectActionGroup.xml index 9678a919f9198..2945538ed5f9f 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionDisableActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminCMSPageMassActionSelectActionGroup.xml @@ -7,9 +7,12 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminCMSPageMassActionDisableActionGroup"> + <actionGroup name="AdminCMSPageMassActionSelectActionGroup"> + <arguments> + <argument name="action" type="string" /> + </arguments> <click selector="{{CmsPagesPageActionsSection.massActionsButton}}" stepKey="clickMassActionDropdown"/> - <click selector="{{CmsPagesPageActionsSection.massActionsOption('Disable')}}" stepKey="clickDisableAction"/> + <click selector="{{CmsPagesPageActionsSection.massActionsOption(action)}}" stepKey="clickAction"/> <waitForPageLoad stepKey="waitForPageToReload"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpenCMSPagesGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpenCMSPagesGridActionGroup.xml index fe5c6202c977d..2439953cde0ec 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpenCMSPagesGridActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminOpenCMSPagesGridActionGroup.xml @@ -11,4 +11,4 @@ <amOnPage url="{{CmsPagesPage.url}}" stepKey="navigateToCMSPagesGrid"/> <waitForPageLoad stepKey="waitForPageLoad"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml index a808e7707bfe1..4de1157e3180b 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageInGridActionGroup.xml @@ -13,4 +13,4 @@ </arguments> <checkOption selector="{{CmsPagesPageActionsSection.pageRowCheckboxByIdentifier(identifier)}}" stepKey="selectCmsPageInGrid"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageInGridActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageInGridActionGroup.xml index 607e0676a0412..84feb0a16c4ef 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageInGridActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageInGridActionGroup.xml @@ -7,19 +7,12 @@ --> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AssertCMSPageInGrid"> + <actionGroup name="AssertCMSPageInGridActionGroup"> <arguments> - <argument name="identifier" defaultValue=""/> + <argument name="cmsPage" type="entity" /> </arguments> - <amOnPage url="{{CmsPagesPage.url}}" stepKey="navigateToCMSPagesGrid"/> - <waitForPageLoad stepKey="waitForPageLoad1"/> - <conditionalClick selector="{{CmsPagesPageActionsSection.clearAllButton}}" dependentSelector="{{CmsPagesPageActionsSection.activeFilters}}" stepKey="clickToResetFilter" visible="true"/> - <waitForPageLoad stepKey="waitForPageLoad2"/> - <conditionalClick selector="//div[contains(@data-role, 'grid-wrapper')]/table/thead/tr/th/span[contains(text(), 'ID')]" dependentSelector="//span[contains(text(), 'ID')]/parent::th[not(contains(@class, '_descend'))]/parent::tr/parent::thead/parent::table/parent::div[contains(@data-role, 'grid-wrapper')]" stepKey="clickToAttemptSortByIdDescending" visible="true"/> - <waitForLoadingMaskToDisappear stepKey="waitForFirstIdSortDescendingToFinish" /> - <!-- Conditional Click again in case it goes from default state to ascending on first click --> - <conditionalClick selector="//div[contains(@data-role, 'grid-wrapper')]/table/thead/tr/th/span[contains(text(), 'ID')]" dependentSelector="//span[contains(text(), 'ID')]/parent::th[not(contains(@class, '_descend'))]/parent::tr/parent::thead/parent::table/parent::div[contains(@data-role, 'grid-wrapper')]" stepKey="secondClickToAttemptSortByIdDescending" visible="true"/> - <waitForLoadingMaskToDisappear stepKey="waitForSecondIdSortDescendingToFinish" /> - <click selector="{{CmsPagesPageActionsSection.select(identifier)}}" stepKey="clickSelectCMSPage" /> + + <seeElement stepKey="seeElementByCmsPageIdentifier" selector="{{AdminDataGridTableSection.rowTemplateStrict(cmsPage.identifier)}}" /> + <see userInput="{{cmsPage.title}}" stepKey="seeCmsPageTitle" selector="{{AdminDataGridTableSection.rowTemplateStrict(cmsPage.identifier)}}" /> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnStorefrontActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnStorefrontActionGroup.xml index c0e0a1b599482..b92413a379454 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnStorefrontActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/AssertCMSPageNotFoundOnStorefrontActionGroup.xml @@ -10,4 +10,4 @@ <actionGroup name="AssertCMSPageNotFoundOnStorefrontActionGroup"> <see userInput="Whoops, our bad..." stepKey="seePageErrorNotFound"/> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/StorefrontGoToCMSPageActionGroup.xml b/app/code/Magento/Cms/Test/Mftf/ActionGroup/StorefrontGoToCMSPageActionGroup.xml index ac27ac89bba14..0ec8db3f27c9c 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/StorefrontGoToCMSPageActionGroup.xml +++ b/app/code/Magento/Cms/Test/Mftf/ActionGroup/StorefrontGoToCMSPageActionGroup.xml @@ -11,7 +11,7 @@ <arguments> <argument name="identifier" type="string"/> </arguments> - <amOnPage url="{{StorefrontHomePage.url}}/{{identifier}}" stepKey="amOnCmsPageOnStorefront"/> + <amOnPage url="{{StorefrontHomePage.url}}{{identifier}}" stepKey="amOnCmsPageOnStorefront"/> <waitForPageLoad stepKey="waitForPageLoadOnStorefront"/> </actionGroup> </actionGroups> \ No newline at end of file diff --git a/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml b/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml index d359ae7160afa..382723631628f 100644 --- a/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml +++ b/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml @@ -27,8 +27,8 @@ <element name="savePageSuccessMessage" type="text" selector=".message-success"/> <element name="delete" type="button" selector="//div[text()='{{var1}}']/parent::td//following-sibling::td[@class='data-grid-actions-cell']//a[text()='Delete']" parameterized="true"/> <element name="deleteConfirm" type="button" selector=".action-primary.action-accept" timeout="60"/> - <element name="pageRowCheckboxByIdentifier" type="block" selector="//div[@data-bind="scope: 'cms_page_listing.cms_page_listing'"]//td[count(../../..//th[./*[.='URL Key']]/preceding-sibling::th) + 1][./*[.='{{identifier}}']]/../td//input[@data-action='select-row']" parameterized="true" /> - <element name="massActionsButton" type="button" selector="div.admin__data-grid-header-row.row div.action-select-wrap button.action-select"/> - <element name="massActionsOption" type="button" selector="//div[contains(@class,'admin__data-grid-header-row') and contains(@class, 'row')]//div[contains(@class, 'action-select-wrap')]//ul/li/span[text() = '{{label}}']" parameterized="true"/> + <element name="pageRowCheckboxByIdentifier" type="checkbox" selector="//table[@data-role='grid']//td[count(../../..//th[./*[.='URL Key']]/preceding-sibling::th) + 1][./*[.='{{identifier}}']]/../td//input[@data-action='select-row']" parameterized="true" /> + <element name="massActionsButton" type="button" selector="//div[@class='admin__data-grid-header'][(not(ancestor::*[@class='sticky-header']) and not(contains(@style,'visibility: hidden'))) or (ancestor::*[@class='sticky-header' and not(contains(@style,'display: none'))])]//*[contains(@class, 'row-gutter')]//button[contains(@class, 'action-select')]" /> + <element name="massActionsOption" type="button" selector="//div[@class='admin__data-grid-header'][(not(ancestor::*[@class='sticky-header']) and not(contains(@style,'visibility: hidden'))) or (ancestor::*[@class='sticky-header' and not(contains(@style,'display: none'))])]//span[contains(@class, 'action-menu-item') and .= '{{action}}']" parameterized="true"/> </section> </sections> diff --git a/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml b/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml index 1ef2ad551b4de..7cc0719dcbeb2 100644 --- a/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml +++ b/app/code/Magento/Cms/Test/Mftf/Test/AdminCmsPageMassActionTest.xml @@ -9,11 +9,14 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminCmsPageMassActionTest"> <annotations> - <features value="Cms"/> + <features value="CmsPage"/> <title value="Create two CMS Pages and perform mass disable action"/> <description value="Admin should be able to perform mass actions to CMS pages"/> + <stories value="Admin Grid Mass Action" /> + <testCaseId value="MC-14659" /> + <severity value="CRITICAL"/> <group value="backend"/> - <group value="cMSContent"/> + <group value="CMSContent"/> <group value="mtf_migrated"/> </annotations> <before> @@ -26,8 +29,11 @@ <deleteData createDataKey="secondCMSPage" stepKey="deleteSecondCMSPage" /> <actionGroup ref="logout" stepKey="logout"/> </after> + <!--Go to Grid page--> <actionGroup ref="AdminOpenCMSPagesGridActionGroup" stepKey="navigateToCMSPageGrid"/> + <actionGroup ref="AdminGridFilterResetActionGroup" stepKey="clearPossibleGridFilters"/> + <!--Select pages in Grid--> <actionGroup ref="AdminSelectCMSPageInGridActionGroup" stepKey="selectFirstCMSPage"> <argument name="identifier" value="$$firstCMSPage.identifier$$"/> @@ -35,27 +41,45 @@ <actionGroup ref="AdminSelectCMSPageInGridActionGroup" stepKey="selectSecondCMSPage"> <argument name="identifier" value="$$secondCMSPage.identifier$$"/> </actionGroup> + <!-- Disable Pages--> - <actionGroup ref="AdminCMSPageMassActionDisableActionGroup" stepKey="disablePages"/> + <actionGroup ref="AdminCMSPageMassActionSelectActionGroup" stepKey="disablePages"> + <argument name="action" value="Disable" /> + </actionGroup> + + <actionGroup ref="AssertMessageInAdminPanelActionGroup" stepKey="assertSuccessMessage"> + <argument name="message" value="A total of 2 record(s) have been disabled." /> + </actionGroup> + <!--Verify pages in Grid--> - <actionGroup ref="AdminOpenCMSPagesGridActionGroup" stepKey="openCMSPagesGridActionGroup"/> - <actionGroup ref="clearFiltersAdminDataGrid" stepKey="clearGridFilters"/> - <actionGroup ref="SortByIdDescendingActionGroup" stepKey="sortGridByIdDescending"/> - <actionGroup ref="AdminSelectCMSPageFromGridActionGroup" stepKey="verifyFirstPageInGrid"> - <argument name="identifier" value="$$firstCMSPage.identifier$$"/> + <actionGroup ref="AdminGridFilterResetActionGroup" stepKey="clearGridFilters"/> + <actionGroup ref="AdminGridFilterFillInputFieldActionGroup" stepKey="filterGridByFirstCmsPageIdentifier"> + <argument name="filterInputName" value="identifier" /> + <argument name="filterValue" value="$$firstCMSPage.identifier$$" /> </actionGroup> - <actionGroup ref="AdminSelectCMSPageFromGridActionGroup" stepKey="verifySecondPageInGrid"> - <argument name="identifier" value="$$secondCMSPage.identifier$$"/> + <actionGroup ref="AdminGridFilterApplyActionGroup" stepKey="applyFirstGridFilters"/> + <actionGroup ref="AssertCMSPageInGridActionGroup" stepKey="assertFirstCmsPageInGrid"> + <argument name="cmsPage" value="$$firstCMSPage$$" /> + </actionGroup> + + <actionGroup ref="AdminGridFilterFillInputFieldActionGroup" stepKey="filterGridBySecondCmsPageIdentifier"> + <argument name="filterInputName" value="identifier" /> + <argument name="filterValue" value="$$secondCMSPage.identifier$$" /> + </actionGroup> + <actionGroup ref="AdminGridFilterApplyActionGroup" stepKey="applySecondGridFilters"/> + <actionGroup ref="AssertCMSPageInGridActionGroup" stepKey="assertSecondCmsPageInGrid"> + <argument name="cmsPage" value="$$secondCMSPage$$" /> </actionGroup> - <!--Verify first page is disabled on Frontend--> + <actionGroup ref="AdminGridFilterResetActionGroup" stepKey="clearGridFiltersToIsolateTest"/> + + <!--Verify pages are disabled on Storefront--> <actionGroup ref="StorefrontGoToCMSPageActionGroup" stepKey="goToFirstCMSPageOnStorefront"> <argument name="identifier" value="$$firstCMSPage.identifier$$"/> </actionGroup> <actionGroup ref="AssertCMSPageNotFoundOnStorefrontActionGroup" stepKey="seeNotFoundErrorForFirstPage"/> - <!--Verify second page is disabled on Frontend--> <actionGroup ref="StorefrontGoToCMSPageActionGroup" stepKey="goToSecondCMSPageOnStorefront"> <argument name="identifier" value="$$secondCMSPage.identifier$$"/> </actionGroup> <actionGroup ref="AssertCMSPageNotFoundOnStorefrontActionGroup" stepKey="seeNotFoundErrorForSecondPage"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageFromGridActionGroup.xml b/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterApplyActionGroup.xml similarity index 53% rename from app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageFromGridActionGroup.xml rename to app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterApplyActionGroup.xml index 6a08b8fa89eef..9f0b7da28fffc 100644 --- a/app/code/Magento/Cms/Test/Mftf/ActionGroup/AdminSelectCMSPageFromGridActionGroup.xml +++ b/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterApplyActionGroup.xml @@ -5,12 +5,11 @@ * See COPYING.txt for license details. */ --> + <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="AdminSelectCMSPageFromGridActionGroup"> - <arguments> - <argument name="identifier" defaultValue=""/> - </arguments> - <click selector="{{CmsPagesPageActionsSection.select(identifier)}}" stepKey="clickSelectCMSPage" /> + <actionGroup name="AdminGridFilterApplyActionGroup"> + <click selector="{{AdminDataGridFilterSection.apply}}" stepKey="applyFilters" /> + <waitForPageLoad stepKey="waitForFiltersReset" /> </actionGroup> -</actionGroups> \ No newline at end of file +</actionGroups> diff --git a/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterFillInputFieldActionGroup.xml b/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterFillInputFieldActionGroup.xml new file mode 100644 index 0000000000000..7cf05ab8c186b --- /dev/null +++ b/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterFillInputFieldActionGroup.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminGridFilterFillInputFieldActionGroup"> + <arguments> + <argument name="filterInputName" type="string"/> + <argument name="filterValue" type="string"/> + </arguments> + + <conditionalClick selector="{{AdminDataGridFilterSection.filterExpand}}" dependentSelector="{{AdminDataGridFilterSection.filterForm}}" visible="false" stepKey="openFiltersFormIfNecessary" /> + <waitForElementVisible selector="{{AdminDataGridFilterSection.filterForm}}" stepKey="waitForFormVisible" /> + <fillField userInput="{{filterValue}}" selector="{{AdminDataGridFilterSection.inputFieldByNameAttr(filterInputName)}}" stepKey="fillFilterInputField" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterResetActionGroup.xml b/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterResetActionGroup.xml new file mode 100644 index 0000000000000..8430975a119a8 --- /dev/null +++ b/app/code/Magento/Ui/Test/Mftf/ActionGroup/AdminGridFilterResetActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> + <actionGroup name="AdminGridFilterResetActionGroup"> + <scrollToTopOfPage stepKey="scrollToTop" /> + <conditionalClick selector="{{AdminDataGridFilterSection.clear}}" dependentSelector="{{AdminDataGridFilterSection.clear}}" visible="true" stepKey="clearExistingFilters" /> + <waitForPageLoad stepKey="waitForFiltersReset" /> + </actionGroup> +</actionGroups> diff --git a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridFilterSection.xml b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridFilterSection.xml new file mode 100644 index 0000000000000..6ae4ebafa0df1 --- /dev/null +++ b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridFilterSection.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> + <section name="AdminDataGridFilterSection"> + <element name="filterForm" type="block" selector="[data-part='filter-form']" /> + <element name="filterExpand" type="button" selector="//div[@class='admin__data-grid-header'][(not(ancestor::*[@class='sticky-header']) and not(contains(@style,'visibility: hidden'))) or (ancestor::*[@class='sticky-header' and not(contains(@style,'display: none'))])]//button[@data-action='grid-filter-expand']" /> + <element name="inputFieldByNameAttr" type="input" selector="//*[@data-part='filter-form']//input[@name='{{inputNameAttr}}']" parameterized="true" /> + <element name="apply" type="button" selector="//*[@data-part='filter-form']//button[@data-action='grid-filter-apply']" /> + <element name="clear" type="button" selector=".admin__data-grid-header [data-action='grid-filter-reset']" /> + </section> +</sections> diff --git a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml index a2b7ba8c1ffd5..8a61bf76cc5ea 100644 --- a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml +++ b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml @@ -19,5 +19,7 @@ <element name="gridCell" type="text" selector="//tr[{{row}}]//td[count(//div[@data-role='grid-wrapper']//tr//th[contains(., '{{column}}')]/preceding-sibling::th) +1 ]" parameterized="true"/> <element name="rowViewAction" type="button" selector=".data-grid tbody > tr:nth-of-type({{row}}) .action-menu-item" parameterized="true" timeout="30"/> <element name="dataGridEmpty" type="block" selector=".data-grid-tr-no-data td"/> + <element name="rowTemplateStrict" type="block" selector="//tbody/tr[td[*[text()[normalize-space()='{{text}}']]]]" parameterized="true" /> + <element name="rowTemplate" type="block" selector="//tbody/tr[td[*[contains(.,normalize-space('{{text}}'))]]]" parameterized="true" /> </section> </sections> From f7b84806b25cc5163c60257801a50a0840e5bbda Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 10 May 2019 15:16:49 -0500 Subject: [PATCH 223/224] Minor fix to mass action selector --- .../Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml b/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml index 382723631628f..494c98ca44e7f 100644 --- a/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml +++ b/app/code/Magento/Cms/Test/Mftf/Section/CmsPagesPageActionsSection.xml @@ -28,7 +28,7 @@ <element name="delete" type="button" selector="//div[text()='{{var1}}']/parent::td//following-sibling::td[@class='data-grid-actions-cell']//a[text()='Delete']" parameterized="true"/> <element name="deleteConfirm" type="button" selector=".action-primary.action-accept" timeout="60"/> <element name="pageRowCheckboxByIdentifier" type="checkbox" selector="//table[@data-role='grid']//td[count(../../..//th[./*[.='URL Key']]/preceding-sibling::th) + 1][./*[.='{{identifier}}']]/../td//input[@data-action='select-row']" parameterized="true" /> - <element name="massActionsButton" type="button" selector="//div[@class='admin__data-grid-header'][(not(ancestor::*[@class='sticky-header']) and not(contains(@style,'visibility: hidden'))) or (ancestor::*[@class='sticky-header' and not(contains(@style,'display: none'))])]//*[contains(@class, 'row-gutter')]//button[contains(@class, 'action-select')]" /> + <element name="massActionsButton" type="button" selector="//div[@class='admin__data-grid-header'][(not(ancestor::*[@class='sticky-header']) and not(contains(@style,'visibility: hidden'))) or (ancestor::*[@class='sticky-header' and not(contains(@style,'display: none'))])]//button[contains(@class, 'action-select')]" /> <element name="massActionsOption" type="button" selector="//div[@class='admin__data-grid-header'][(not(ancestor::*[@class='sticky-header']) and not(contains(@style,'visibility: hidden'))) or (ancestor::*[@class='sticky-header' and not(contains(@style,'display: none'))])]//span[contains(@class, 'action-menu-item') and .= '{{action}}']" parameterized="true"/> </section> </sections> From 8eed6a591acf759ff8bb1327fa65557506250ceb Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Thu, 16 May 2019 10:19:25 -0500 Subject: [PATCH 224/224] MC-4776: Convert AssignCustomOrderStatusTest to MFTF - Add timeout back to element that got lost during resolving merge conflicts --- .../Test/Mftf/Section/AdminAssignOrderStatusToStateSection.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminAssignOrderStatusToStateSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminAssignOrderStatusToStateSection.xml index 485a017c6e569..53e5e14497c63 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminAssignOrderStatusToStateSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminAssignOrderStatusToStateSection.xml @@ -13,6 +13,6 @@ <element name="orderState" type="select" selector="#state"/> <element name="orderStatusAsDefault" type="checkbox" selector="#is_default"/> <element name="visibleOnStorefront" type="checkbox" selector="#visible_on_front"/> - <element name="saveStatusAssignment" type="button" selector="#save"/> + <element name="saveStatusAssignment" type="button" selector="#save" timeout="30"/> </section> </sections> \ No newline at end of file