diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php index 8e93868dc7e51916a1c44997ad98045edbe1bd4f..8fdb867c9dbd84a2903a9a3372144d05c54922f4 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Eav/Attribute.php @@ -417,6 +417,9 @@ class Attribute extends \Magento\Eav\Model\Entity\Attribute implements if ($this->getAttributeCode() == 'price') { return false; } + if ($this->getAttributeCode() == 'visibility') { + return true; + } if (!$this->getIsFilterableInSearch() && !$this->getIsVisibleInAdvancedSearch() && !$this->getIsFilterable()) { return false; diff --git a/app/code/Magento/CatalogInventory/Setup/InstallSchema.php b/app/code/Magento/CatalogInventory/Setup/InstallSchema.php index a19eb9d1cc57344e6f2fcce5f94b81be113cc84f..cbe1aa3d066651a7d90f75b655da1ef79c95cf49 100644 --- a/app/code/Magento/CatalogInventory/Setup/InstallSchema.php +++ b/app/code/Magento/CatalogInventory/Setup/InstallSchema.php @@ -254,10 +254,10 @@ class InstallSchema implements InstallSchemaInterface ->addIndex( $installer->getIdxName( 'cataloginventory_stock_item', - ['product_id', 'website_id'], + ['product_id', 'stock_id'], \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE ), - ['product_id', 'website_id'], + ['product_id', 'stock_id'], ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE] ) ->addIndex( diff --git a/app/code/Magento/CatalogInventory/Setup/UpgradeSchema.php b/app/code/Magento/CatalogInventory/Setup/UpgradeSchema.php new file mode 100644 index 0000000000000000000000000000000000000000..8fd3d264ee67d6a5bef74cebb829f82b9a324e92 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Setup/UpgradeSchema.php @@ -0,0 +1,123 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogInventory\Setup; + +use Magento\Framework\Setup\UpgradeSchemaInterface; +use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\Setup\SchemaSetupInterface; +use Magento\CatalogInventory\Model\Stock\Item as StockItem; + +class UpgradeSchema implements UpgradeSchemaInterface +{ + /** + * @var string + */ + private $productCompositeKeyVersion = '2.2.0'; + + /** + * {@inheritdoc} + */ + public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) + { + $setup->startSetup(); + + if (version_compare($context->getVersion(), $this->productCompositeKeyVersion, '<')) { + $this->upgradeProductCompositeKey($setup); + } + + $setup->endSetup(); + } + + /** + * @param SchemaSetupInterface $setup + * @return void + */ + private function upgradeProductCompositeKey(SchemaSetupInterface $setup) + { + $oldCompositeKeyColumns = ['product_id', 'website_id']; + $newCompositeKeyColumns = ['product_id', 'stock_id']; + + $foreignKeys = $this->getForeignKeys($setup, $oldCompositeKeyColumns); + // drop foreign keys + $this->dropForeignKeys($setup, $foreignKeys); + + $oldIndexName = $setup->getIdxName( + $setup->getTable(StockItem::ENTITY), + $oldCompositeKeyColumns, + \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE + ); + + $newIndexName = $setup->getIdxName( + $setup->getTable(StockItem::ENTITY), + $newCompositeKeyColumns, + \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE + ); + + // Drop a key based on the following columns: "product_id","website_id" + $setup->getConnection()->dropIndex($setup->getTable(StockItem::ENTITY), $oldIndexName); + + // Create a key based on the following columns: "product_id","stock_id" + $setup->getConnection() + ->addIndex( + $setup->getTable(StockItem::ENTITY), + $newIndexName, + $newCompositeKeyColumns, + \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE + ); + // restore deleted foreign keys + $this->createForeignKeys($setup, $foreignKeys); + } + + /** + * @param SchemaSetupInterface $setup + * @param array $keys + * @return void + */ + private function dropForeignKeys(SchemaSetupInterface $setup, array $keys) + { + foreach ($keys as $key) { + $setup->getConnection()->dropForeignKey($key['TABLE_NAME'], $key['FK_NAME']); + } + } + + /** + * @param SchemaSetupInterface $setup + * @param array $keys + * @return void + */ + private function createForeignKeys(SchemaSetupInterface $setup, array $keys) + { + foreach ($keys as $key) { + $setup->getConnection()->addForeignKey( + $key['FK_NAME'], + $key['TABLE_NAME'], + $key['COLUMN_NAME'], + $key['REF_TABLE_NAME'], + $key['REF_COLUMN_NAME'], + $key['ON_DELETE'] + ); + } + } + + /** + * @param SchemaSetupInterface $setup + * @param array $compositeKeys + * @return array + */ + private function getForeignKeys(SchemaSetupInterface $setup, array $compositeKeys) + { + $foreignKeys = []; + $allForeignKeys = $setup->getConnection()->getForeignKeys($setup->getTable(StockItem::ENTITY)); + foreach ($allForeignKeys as $key) { + if (in_array($key['COLUMN_NAME'], $compositeKeys)) { + $foreignKeys[] = $key; + } + } + + return $foreignKeys; + } +} diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html index da625c51d4b7734ccc4808fd9161502e15acf1a9..798be1f978f54e3cd7e4c51bfb0e3e20e8ae82e2 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html @@ -15,7 +15,12 @@ <!-- /ko --><br/> <!-- ko foreach: { data: currentBillingAddress().customAttributes, as: 'element' } --> <!-- ko foreach: { data: Object.keys(element), as: 'attribute' } --> - <!-- ko text: element[attribute].value --><!-- /ko --> + <!-- ko if: (typeof element[attribute] === "object") --> + <!-- ko text: element[attribute].value --><!-- /ko --> + <!-- /ko --> + <!-- ko if: (typeof element[attribute] === "string") --> + <!-- ko text: element[attribute] --><!-- /ko --> + <!-- /ko --><br/> <!-- /ko --> <!-- /ko --> <button type="button" diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html index a2b83ead6b354451b99a4a1003a0f04df905dbbc..92469fdec3d7fcc8660d7d5a385cfa9c28c18252 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html @@ -15,7 +15,12 @@ <!-- /ko --><br/> <!-- ko foreach: { data: address().customAttributes, as: 'element' } --> <!-- ko foreach: { data: Object.keys(element), as: 'attribute' } --> - <!-- ko text: element[attribute].value --><!-- /ko --> + <!-- ko if: (typeof element[attribute] === "object") --> + <!-- ko text: element[attribute].value --><!-- /ko --> + <!-- /ko --> + <!-- ko if: (typeof element[attribute] === "string") --> + <!-- ko text: element[attribute] --><!-- /ko --> + <!-- /ko --><br/> <!-- /ko --> <!-- /ko --> <!-- ko if: (address().isEditable()) --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html index 440a2c7fc468fc493d10eb0cb57320c5593e1bf8..36ea556ae9ec95f09496094771a1340305ffdd43 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html @@ -15,7 +15,12 @@ <!-- /ko --><br/> <!-- ko foreach: { data: address().customAttributes, as: 'element' } --> <!-- ko foreach: { data: Object.keys(element), as: 'attribute' } --> - <!-- ko text: element[attribute].value --><!-- /ko --> + <!-- ko if: (typeof element[attribute] === "object") --> + <!-- ko text: element[attribute].value --><!-- /ko --> + <!-- /ko --> + <!-- ko if: (typeof element[attribute] === "string") --> + <!-- ko text: element[attribute] --><!-- /ko --> + <!-- /ko --><br/> <!-- /ko --> <!-- /ko --> <!-- /ko --> diff --git a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php index 02ff894df7c1fb1ed6ec7b6af07f019cece1b8cb..74a7e8112aa0ddb528b46168a16df15310fd227c 100644 --- a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php +++ b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php @@ -202,7 +202,7 @@ class Grouped extends \Magento\Catalog\Model\Product\Type\AbstractType $collection = $this->getAssociatedProductCollection( $product )->addAttributeToSelect( - ['name', 'price', 'special_price', 'special_from_date', 'special_to_date'] + ['name', 'price', 'special_price', 'special_from_date', 'special_to_date', 'tax_class_id'] )->addFilterByRequiredOptions()->setPositionOrder()->addStoreFilter( $this->getStoreFilter($product) )->addAttributeToFilter( diff --git a/app/code/Magento/Store/Model/StoreManager.php b/app/code/Magento/Store/Model/StoreManager.php index 13840b120636773dd108adcdf4a9f590e629383d..f64f2fe84a8cd9a496c0c85f8135e3274cd75f2f 100644 --- a/app/code/Magento/Store/Model/StoreManager.php +++ b/app/code/Magento/Store/Model/StoreManager.php @@ -152,7 +152,7 @@ class StoreManager implements public function getStore($storeId = null) { if (!isset($storeId) || '' === $storeId || $storeId === true) { - if (!$this->currentStoreId) { + if (null === $this->currentStoreId) { \Magento\Framework\Profiler::start('store.resolve'); $this->currentStoreId = $this->storeResolver->getCurrentStoreId(); \Magento\Framework\Profiler::stop('store.resolve'); diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.php index 8a949c474bc847942f1bd5922d00514cd6133d08..43bd771f609cd86fddcfb99c21ac05687bfe06a9 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.php @@ -65,4 +65,20 @@ class AddressModal extends Form return $result; } + + /** + * Fixture mapping. + * + * @param array|null $fields + * @param string|null $parent + * @return array + */ + protected function dataMapping(array $fields = null, $parent = null) + { + if (isset($fields['custom_attribute'])) { + $this->placeholders = ['attribute_code' => $fields['custom_attribute']['code']]; + $this->applyPlaceholders(); + } + return parent::dataMapping($fields, $parent); + } } diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.xml index 13403b792684512c9741bca74a78f7c84036eb48..4a6160698839382c83809824913ebcf3770a0f7f 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.xml +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.xml @@ -22,5 +22,8 @@ </country_id> <telephone /> <postcode /> + <custom_attribute> + <selector>[name="custom_attributes[%attribute_code%]"]</selector> + </custom_attribute> </fields> </mapping> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.php index b9d5f3c3af01e10559e2c942e546f4eeda6576c3..78eaf403826bc054996c570c2167600ac4fac0ff 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Block/Address/Edit.php @@ -61,4 +61,20 @@ class Edit extends Form { $this->_rootElement->find($this->saveAddress)->click(); } + + /** + * Fixture mapping. + * + * @param array|null $fields + * @param string|null $parent + * @return array + */ + protected function dataMapping(array $fields = null, $parent = null) + { + if (isset($fields['custom_attribute'])) { + $this->placeholders = ['attribute_code' => $fields['custom_attribute']['code']]; + $this->applyPlaceholders(); + } + return parent::dataMapping($fields, $parent); + } } diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAddressEdit.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAddressEdit.php deleted file mode 100644 index 4946f0825870974337a3724fae591e58b8d861be..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAddressEdit.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Customer\Test\Page; - -use Magento\Mtf\Client\Locator; -use Magento\Mtf\Factory\Factory; -use Magento\Mtf\Page\Page; - -/** - * Customer Address Edit page. - */ -class CustomerAddressEdit extends Page -{ - /** - * URL for Customer Address Edit page. - */ - const MCA = 'customer/address/edit'; - - /** - * Customer Address Edit form. - * - * @var string - */ - protected $editForm = '#form-validate'; - - /** - * Init page. Set page url. - * - * @return void - */ - protected function initUrl() - { - $this->url = $_ENV['app_frontend_url'] . self::MCA; - } - - /** - * Get Customer Address Edit form. - * - * @return \Magento\Customer\Test\Block\Address\Edit - */ - public function getEditForm() - { - return Factory::getBlockFactory()->getMagentoCustomerAddressEdit( - $this->browser->find($this->editForm, Locator::SELECTOR_CSS) - ); - } -} diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAddressEdit.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAddressEdit.xml new file mode 100644 index 0000000000000000000000000000000000000000..2f3738d05e5e3d0439496b2df70532613b9144d8 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Page/CustomerAddressEdit.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/pages.xsd"> + <page name="CustomerAddressEdit" mca="customer/address/edit" module="Magento_Customer"> + <block name="editForm" class="Magento\Customer\Test\Block\Address\Edit" locator="#form-validate" strategy="css selector" /> + </page> +</config> diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php index bd774f806053eb90b28ff70003cd703f315e1b2d..31ce18926b51ba89d70d8e5a73508562d405c9cf 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View.php @@ -94,4 +94,19 @@ class View extends ParentView { $this->getGroupedProductBlock()->fill($product); } + + /** + * Set quantity and click add to cart. + * @param FixtureInterface $product + * @param string|int $qty + */ + public function setQtyAndClickAddToCartGrouped(FixtureInterface $product, $qty) + { + $associatedProducts = $product->getAssociated()['products']; + $groupedProductBlock = $this->getGroupedProductBlock(); + foreach ($associatedProducts as $product) { + $groupedProductBlock->setQty($product->getId(), $qty); + } + $this->clickAddToCart(); + } } diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View/Type/Grouped.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View/Type/Grouped.php index 42b3b0dfcf76047bcd3c23ed1fcf117e497dcbf2..7498c3c56587dd1bace2b00727c90428af19435d 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View/Type/Grouped.php +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Catalog/Product/View/Type/Grouped.php @@ -65,6 +65,18 @@ class Grouped extends Block return $this->_rootElement->find(sprintf($this->qtySubProductById, $subProductId))->getValue(); } + /** + * Set qty to subproduct block + * + * @param int $subProductId + * @param string|int $qty + * @return void + */ + public function setQty($subProductId, $qty) + { + $this->_rootElement->find(sprintf($this->qtySubProductById, $subProductId))->setValue($qty); + } + /** * Fill product options on view page. * diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Checkout/Cart/CartItem.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Checkout/Cart/CartItem.php index f843482eca1ca860869bb3a4413f71c632f05719..9db1477946df13464d6fabbb2a95cfed7a4046c6 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Checkout/Cart/CartItem.php +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Block/Checkout/Cart/CartItem.php @@ -8,6 +8,7 @@ namespace Magento\GroupedProduct\Test\Block\Checkout\Cart; use Magento\Checkout\Test\Block\Cart\AbstractCartItem; use Magento\Checkout\Test\Block\Cart\CartItem as CheckoutCartItem; +use Magento\Mtf\Client\Locator; /** * Class CartItem @@ -119,4 +120,57 @@ class CartItem extends AbstractCartItem $cartItem->removeItem(); } } + + /** + * Get product price including tax + * + * @return string|null + */ + public function getPriceInclTax() + { + return $this->getPriceByType($this->priceInclTax, Locator::SELECTOR_XPATH); + } + + /** + * Get product price excluding tax + * + * @return string|null + */ + public function getPriceExclTax() + { + return $this->getPriceByType($this->priceExclTax, Locator::SELECTOR_XPATH); + } + + /** + * Get sub-total excluding tax for the specified item in the cart + * + * @return string|null + */ + public function getSubtotalPriceExclTax() + { + return $this->getPriceByType($this->subTotalPriceExclTax); + } + + /** + * Get price for the specified item in the cart by the price type + * + * @return string|null + */ + public function getSubtotalPriceInclTax() + { + return $this->getPriceByType($this->subTotalPriceInclTax); + } + + /** + * @param string $priceType + * @param string $strategy + * @return mixed|null + */ + private function getPriceByType($priceType, $strategy = Locator::SELECTOR_CSS) + { + $cartProductPrice = $this->_rootElement->find($priceType, $strategy); + return $cartProductPrice->isVisible() + ? str_replace(',', '', $this->escapeCurrency($cartProductPrice->getText())) + : null; + } } diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AbstractAssertTaxRuleIsAppliedToAllPricesOnGroupedProductPage.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AbstractAssertTaxRuleIsAppliedToAllPricesOnGroupedProductPage.php new file mode 100644 index 0000000000000000000000000000000000000000..9fd3ebe177b3a2f5b0cfb10141f4a3e64f41a8b9 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AbstractAssertTaxRuleIsAppliedToAllPricesOnGroupedProductPage.php @@ -0,0 +1,82 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\GroupedProduct\Test\Constraint; + +use Magento\Cms\Test\Page\CmsIndex; +use Magento\Catalog\Test\Page\Category\CatalogCategoryView; +use Magento\Catalog\Test\Page\Product\CatalogProductView; +use Magento\Checkout\Test\Page\CheckoutCart; +use Magento\Tax\Test\Constraint\AbstractAssertTaxRuleIsAppliedToAllPrices; +use Magento\Mtf\Fixture\FixtureFactory; +use Magento\Mtf\Fixture\FixtureInterface; +use Magento\Mtf\Fixture\InjectableFixture; + +/** + * Checks that prices excl tax on category, product and cart pages are equal to specified in dataset. + */ +abstract class AbstractAssertTaxRuleIsAppliedToAllPricesOnGroupedProductPage extends + AbstractAssertTaxRuleIsAppliedToAllPrices +{ + + /** + * Get grouped product view prices. + * + * @param FixtureInterface $product + * @param array $actualPrices + * @return array + */ + abstract protected function getGroupedProductPagePrices(FixtureInterface $product, array $actualPrices); + + /** + * Assert that specified prices are actual on category, product and cart pages. + * + * @param InjectableFixture $product + * @param array $prices + * @param int $qty + * @param CmsIndex $cmsIndex + * @param CatalogCategoryView $catalogCategoryView + * @param CatalogProductView $catalogProductView + * @param CheckoutCart $checkoutCart + * @param FixtureFactory $fixtureFactory + * @return void + */ + public function processAssert( + InjectableFixture $product, + array $prices, + $qty, + CmsIndex $cmsIndex, + CatalogCategoryView $catalogCategoryView, + CatalogProductView $catalogProductView, + CheckoutCart $checkoutCart, + FixtureFactory $fixtureFactory + ) { + $this->cmsIndex = $cmsIndex; + $this->catalogCategoryView = $catalogCategoryView; + $this->catalogProductView = $catalogProductView; + $this->checkoutCart = $checkoutCart; + //Preconditions + $address = $fixtureFactory->createByCode('address', ['dataset' => 'US_address_NY']); + $shipping = ['shipping_service' => 'Flat Rate', 'shipping_method' => 'Fixed']; + $actualPrices = []; + //Assertion steps + $productCategory = $product->getCategoryIds()[0]; + $this->openCategory($productCategory); + $actualPrices = $this->getCategoryPrices($product, $actualPrices); + $catalogCategoryView->getListProductBlock()->getProductItem($product)->open(); + $catalogProductView->getGroupedProductViewBlock()->fillOptions($product); + $actualPrices = $this->getGroupedProductPagePrices($product, $actualPrices); + $catalogProductView->getGroupedProductViewBlock()->setQtyAndClickAddToCartGrouped($product, $qty); + $catalogProductView->getMessagesBlock()->waitSuccessMessage(); + $this->checkoutCart->open(); + $this->fillEstimateBlock($address, $shipping); + $actualPrices = $this->getCartPrices($product, $actualPrices); + $actualPrices = $this->getTotals($actualPrices); + //Prices verification + $message = 'Prices from dataset should be equal to prices on frontend.'; + \PHPUnit_Framework_Assert::assertEquals($prices, $actualPrices, $message); + } +} diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertTaxRuleIsAppliedToAllPricesGroupedExcludingIncludingTax.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertTaxRuleIsAppliedToAllPricesGroupedExcludingIncludingTax.php new file mode 100644 index 0000000000000000000000000000000000000000..57853d344672b0e09a2f6aa9a821146108295cb4 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertTaxRuleIsAppliedToAllPricesGroupedExcludingIncludingTax.php @@ -0,0 +1,74 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\GroupedProduct\Test\Constraint; + +use Magento\Mtf\Fixture\FixtureInterface; + +/** + * Checks that prices excl tax on category, product and cart pages are equal to specified in dataset. + */ +class AssertTaxRuleIsAppliedToAllPricesGroupedExcludingIncludingTax extends + AbstractAssertTaxRuleIsAppliedToAllPricesOnGroupedProductPage +{ + /** + * @inheritdoc + */ + public function getCategoryPrices(FixtureInterface $product, $actualPrices) + { + $priceBlock = $this->catalogCategoryView->getListProductBlock()->getProductItem($product)->getPriceBlock(); + $actualPrices['category_price_excl_tax'] = $priceBlock->getPriceExcludingTax(); + $actualPrices['category_price_incl_tax'] = $priceBlock->getPriceIncludingTax(); + + return $actualPrices; + } + + /** + * @inheritdoc + */ + public function getGroupedProductPagePrices(FixtureInterface $product, array $actualPrices) + { + $associatedProducts = $product->getAssociated(); + /** @var \Magento\GroupedProduct\Test\Block\Catalog\Product\View $groupedProductBlock */ + $this->catalogProductView = $this->catalogProductView->getGroupedProductViewBlock(); + foreach (array_keys($associatedProducts['products']) as $productIndex) { + //Process assertions + $this->catalogProductView ->itemPriceProductBlock(++$productIndex); + $actualPrices['sub_product_view_prices_' . $productIndex] = $this->getProductPagePrices($actualPrices); + } + return $actualPrices; + } + + /** + * @inheritdoc + */ + public function getProductPagePrices($actualPrices) + { + $priceBlock = $this->catalogProductView ->getPriceBlock(); + $productPrices['product_view_price_excl_tax'] = $priceBlock->getPriceExcludingTax(); + $productPrices['product_view_price_incl_tax'] = $priceBlock->getPriceIncludingTax(); + + return $productPrices; + } + + /** + * @inheritdoc + */ + public function getTotals($actualPrices) + { + $totalsBlock = $this->checkoutCart->getTotalsBlock(); + $actualPrices['subtotal_excl_tax'] = $totalsBlock->getSubtotalExcludingTax(); + $actualPrices['subtotal_incl_tax'] = $totalsBlock->getSubtotalIncludingTax(); + $actualPrices['discount'] = $totalsBlock->getDiscount(); + $actualPrices['shipping_excl_tax'] = $totalsBlock->getShippingPrice(); + $actualPrices['shipping_incl_tax'] = $totalsBlock->getShippingPriceInclTax(); + $actualPrices['tax'] = $totalsBlock->getTax(); + $actualPrices['grand_total_excl_tax'] = $totalsBlock->getGrandTotalExcludingTax(); + $actualPrices['grand_total_incl_tax'] = $totalsBlock->getGrandTotalIncludingTax(); + + return $actualPrices; + } +} diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml index bbdbc011ae8c9c8859d16dcfbd6b2e7428d46246..7648899060f8f3314d1a33b26082724ae1495fa8 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Repository/GroupedProduct.xml @@ -125,5 +125,33 @@ <item name="dataset" xsi:type="string">grouped_three_simple_products</item> </field> </dataset> + + <dataset name="grouped_product_with_special_price"> + <field name="name" xsi:type="string">Test grouped product with special price %isolation%</field> + <field name="sku" xsi:type="string">sku_test_grouped_product_with_special_price_%isolation%</field> + <field name="category_ids" xsi:type="array"> + <item name="dataset" xsi:type="string">default</item> + </field> + <field name="associated" xsi:type="array"> + <item name="dataset" xsi:type="string">defaultSimpleProduct_with_specialPrice</item> + </field> + <field name="status" xsi:type="string">Yes</field> + <field name="visibility" xsi:type="string">Catalog, Search</field> + <field name="tax_class_id" xsi:type="array"> + <item name="dataset" xsi:type="string">taxable_goods</item> + </field> + <field name="url_key" xsi:type="string">test-grouped-product-with-special-price-%isolation%</field> + <field name="quantity_and_stock_status" xsi:type="array"> + <item name="is_in_stock" xsi:type="string">In Stock</item> + </field> + <field name="website_ids" xsi:type="array"> + <item name="0" xsi:type="array"> + <item name="dataset" xsi:type="string">default</item> + </item> + </field> + <field name="attribute_set_id" xsi:type="array"> + <item name="dataset" xsi:type="string">default</item> + </field> + </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/TaxCalculationTest.xml b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/TaxCalculationTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..c57afc28b88683e3b08917ae2c1d8942a7c3b614 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/TestCase/TaxCalculationTest.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Tax\Test\TestCase\TaxCalculationTest" summary="Apply Taxes for grouped products" ticketId="MAGETWO-60576"> + <variation name="TaxCalculationTestGroupedProduct"> + <data name="product" xsi:type="string">groupedProduct::grouped_product_with_special_price</data> + <data name="taxRule" xsi:type="string">us_full_tax_rule</data> + <data name="shippingAddress/dataset" xsi:type="string">US_address_1</data> + <data name="customer/dataset" xsi:type="string">johndoe_unique</data> + <data name="salesRule" xsi:type="string">active_sales_rule_for_all_groups_no_coupon</data> + <data name="catalogRule" xsi:type="string">-</data> + <data name="configData" xsi:type="string">total_cat_excl_ship_incl_after_disc_on_excl, display_excluding_including_tax</data> + <data name="flushCache" xsi:type="boolean">true</data> + <data name="qty" xsi:type="string">3</data> + <data name="prices/category_price_excl_tax" xsi:type="string">9.00</data> + <data name="prices/category_price_incl_tax" xsi:type="string">9.90</data> + <data name="prices/sub_product_view_prices_1/product_view_price_excl_tax" xsi:type="string">9.00</data> + <data name="prices/sub_product_view_prices_1/product_view_price_incl_tax" xsi:type="string">9.90</data> + <data name="prices/sub_product_view_prices_2/product_view_price_excl_tax" xsi:type="string">9.00</data> + <data name="prices/sub_product_view_prices_2/product_view_price_incl_tax" xsi:type="string">9.90</data> + <data name="prices/cart_item_price_excl_tax" xsi:type="string">9.00</data> + <data name="prices/cart_item_price_incl_tax" xsi:type="string">9.90</data> + <data name="prices/cart_item_subtotal_excl_tax" xsi:type="string">27.00</data> + <data name="prices/cart_item_subtotal_incl_tax" xsi:type="string">29.70</data> + <data name="prices/subtotal_excl_tax" xsi:type="string">54.00</data> + <data name="prices/subtotal_incl_tax" xsi:type="string">59.40</data> + <data name="prices/shipping_excl_tax" xsi:type="string">30.00</data> + <data name="prices/shipping_incl_tax" xsi:type="string">30.00</data> + <data name="prices/discount" xsi:type="string">27.00</data> + <data name="prices/tax" xsi:type="string">2.70</data> + <data name="prices/grand_total_excl_tax" xsi:type="string">57.00</data> + <data name="prices/grand_total_incl_tax" xsi:type="string">59.70</data> + <constraint name="Magento\GroupedProduct\Test\Constraint\AssertTaxRuleIsAppliedToAllPricesGroupedExcludingIncludingTax" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php index fc2763aea017dee37b05216a1b881665a29dc551..c17553629ae59a3b0c8ef7c1643112743cd82bf8 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Action/AttributeTest.php @@ -45,6 +45,47 @@ class AttributeTest extends \Magento\TestFramework\TestCase\AbstractBackendContr $this->assertTrue($isRedirectPresent); } + /** + * @covers \Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute\Save::execute + * + * @dataProvider saveActionVisibilityAttrDataProvider + * @param array $attributes + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + */ + public function testSaveActionChangeVisibility($attributes) + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $repository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Model\ProductRepository::class + ); + $product = $repository->get('simple'); + $product->setOrigData(); + $product->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE); + $product->save(); + + /** @var $session \Magento\Backend\Model\Session */ + $session = $objectManager->get(\Magento\Backend\Model\Session::class); + $session->setProductIds([$product->getId()]); + $this->getRequest()->setParam('attributes', $attributes); + + $this->dispatch('backend/catalog/product_action_attribute/save/store/0'); + /** @var \Magento\Catalog\Model\Category $category */ + $categoryFactory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + \Magento\Catalog\Model\CategoryFactory::class + ); + /** @var \Magento\Catalog\Block\Product\ListProduct $listProduct */ + $listProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( + \Magento\Catalog\Block\Product\ListProduct::class + ); + + $category = $categoryFactory->create()->load(2); + $layer = $listProduct->getLayer(); + $layer->setCurrentCategory($category); + $productCollection = $layer->getProductCollection(); + $productItem = $productCollection->getFirstItem(); + $this->assertEquals($session->getProductIds(), [$productItem->getId()]); + } + /** * @covers \Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute\Validate::execute * @@ -97,4 +138,17 @@ class AttributeTest extends \Magento\TestFramework\TestCase\AbstractBackendContr ] ]; } + + /** + * Data Provider for save with visibility attribute + * + * @return array + */ + public function saveActionVisibilityAttrDataProvider() + { + return [ + ['arguments' => ['visibility' => \Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH]], + ['arguments' => ['visibility' => \Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_CATALOG]] + ]; + } } diff --git a/dev/tests/integration/testsuite/Magento/Store/Model/StoreManagerTest.php b/dev/tests/integration/testsuite/Magento/Store/Model/StoreManagerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c42856d865649d5206df2c76de323fff521c5482 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Store/Model/StoreManagerTest.php @@ -0,0 +1,48 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Store\Model; + +use Magento\Framework\ObjectManagerInterface as ObjectManager; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; +use Magento\TestFramework\Helper\Bootstrap; + +class StoreManagerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var StoreManagerInterface + */ + private $storeManager; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * Class dependencies initialization + * + * @return void + */ + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + $this->storeManager = $this->objectManager->get(StoreManagerInterface::class); + } + + /** + * Check that behavior of setting and getting store into StoreManager is correct + * Setting: Magento\Store\Model\StoreManagerInterface::setCurrentStore + * Getting: Magento\Store\Model\StoreManagerInterface::getStore + * + * @return void + */ + public function testDefaultStoreIdIsSetCorrectly() + { + $this->storeManager->setCurrentStore(Store::DEFAULT_STORE_ID); + $this->assertEquals(Store::DEFAULT_STORE_ID, $this->storeManager->getStore()->getId()); + } +}