diff --git a/.travis.yml b/.travis.yml index 900ffd8e62069a940fe271aeab4ce8d00b643b88..5aa3b310f5faf85ef65dec2f9647e6aa0c1d189f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ before_script: # Create DB for Integration tests - sh -c "if [ '$TEST_SUITE' = 'integration' ] || [ '$TEST_SUITE' = 'integration_integrity' ]; then mysql -e 'create database magento_integration_tests;'; mv dev/tests/integration/etc/local-mysql.travis.xml.dist dev/tests/integration/etc/local-mysql.xml; fi" # Install tools for static tests - - sh -c "if [ '$TEST_SUITE' = 'static_phpcs' ] || [ '$TEST_SUITE' = 'static_annotation' ]; then pear install pear/PHP_CodeSniffer-1.4.7; fi" + - sh -c "if [ '$TEST_SUITE' = 'static_phpcs' ] || [ '$TEST_SUITE' = 'static_annotation' ]; then pear install pear/PHP_CodeSniffer-1.5.2; fi" - phpenv rehash; script: # Unit tests diff --git a/CHANGELOG.md b/CHANGELOG.md index 23ebdb30c7178609670777c48768322c328d892f..74d8042f568dc77ce7862a5c682ffa6a541e7f99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,42 @@ +2.0.0.0-dev83 +============= +* Created the Service API for the Magento_Catalog Module: + * Product Attribute Media API + * Product Group Price API +* Tax calculation updates: + * Fixed tax calculation rounding issues which appeared when a discount was applied + * Fixed extra penny issue which appeared when exact tax amount ended with 0.5 cent + * Fixed tax calculation issues which appeared when a customer tax rate was different from the store tax rate + * Fixed price inconsistencies between catalog and shopping cart + * Added support for maintaining consistent prices including tax for customers with different tax rates + * Added support for applying tax rules with different priorities to be applied to subtotal only + * Added support for tax rounding at individual tax rate +* Porting Tax Features from Magento 1.x: + * Price consistency UX and algorithm + * Canadian provincial sales taxes + * Fixed issues with bundle product price inconsistency across the system + * Added warnings if invalid tax configuration is created in the Admin panel + * Fixed issues with regards to hidden tax +* Fixed bugs: + * Fixed an issue where grouped price was not applied for grouped products + * Fixed an issue where a fatal error occurred when opening a grouped product page without assigned products on the frontend + * Fixed an issue where it was possible to apply an inactive discount coupon + * Fixed an issue where the linked products information was lost when exporting products + * Fixed non-informative error messages for "Attribute Group Service" + * Fixed the invalid default value of the "apply_after_discount" tax setting + * Fixed an issue where the integration tests coverage whitelist was broken + * Fixed Admin panel UI issues: grids, headers and footers +* Added the following functional tests: + * Create Product Url Rewrite + * Delete Catalog Price Rule + * Delete Category Url Rewrite + * Delete CMS Page Rewrite + * Delete Product Rating + * Delete Sales Rule + * Delete Tax Rate + * Update Catalog Price Rule + * Update Shopping Cart + 2.0.0.0-dev82 ============= * Added support for MTF Reporting Tool diff --git a/app/code/Magento/AdminNotification/view/adminhtml/layout/default.xml b/app/code/Magento/AdminNotification/view/adminhtml/layout/default.xml index 7c7dbf54fa7b43b3070ad20af536818a91e53a74..f54c5cc9f724c0aae45f4c9d62ac8a010b741e1e 100644 --- a/app/code/Magento/AdminNotification/view/adminhtml/layout/default.xml +++ b/app/code/Magento/AdminNotification/view/adminhtml/layout/default.xml @@ -30,7 +30,7 @@ <block class="Magento\AdminNotification\Block\Window" name="notification_window" as="notification_window" acl="Magento_AdminNotification::show_toolbar" template="notification/window.phtml"/> </referenceContainer> <referenceContainer name="header"> - <block class="Magento\AdminNotification\Block\ToolbarEntry" template="toolbar_entry.phtml" /> + <block class="Magento\AdminNotification\Block\ToolbarEntry" before="user" template="toolbar_entry.phtml" /> </referenceContainer> <referenceBlock name="head"> <block class="Magento\Theme\Block\Html\Head\Script" name="magento-adminnotification-toolbar-entry-js" after="jquery-jquery-js"> diff --git a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php index 511001916c643ede7e24bb613cf7ee2a31b1100a..02ecf79e0bc6e1e97c938b8f77e4aa4b00b278be 100644 --- a/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php +++ b/app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php @@ -24,12 +24,31 @@ namespace Magento\Bundle\Block\Catalog\Product\View\Type; use Magento\Framework\Pricing\PriceCurrencyInterface; +use Magento\Tax\Model\Calculation; /** * Catalog bundle product info block */ class Bundle extends \Magento\Catalog\Block\Product\View\AbstractView { + /** + * constants for different rounding methods + */ + const UNIT_ROUNDING = 0; + const ROW_ROUNDING = 1; + const TOTAL_ROUNDING = 2; + + /** + * Mapping between constants in \Magento\Tax\Model\Calculation and this class + * + * @var array + */ + protected $mapping = [ + Calculation::CALC_UNIT_BASE => self::UNIT_ROUNDING, + Calculation::CALC_ROW_BASE => self::ROW_ROUNDING, + Calculation::CALC_TOTAL_BASE => self::TOTAL_ROUNDING, + ]; + /** * @var array */ @@ -305,4 +324,16 @@ class Bundle extends \Magento\Catalog\Block\Product\View\AbstractView } return $optionBlock->setOption($option)->toHtml(); } + + /** + * Return the rounding method based on tax calculation + * This is a workaround as the proper way is to always call tax service to get taxed price + * + * @return int + */ + public function getRoundingMethod() + { + $algorithm = $this->_taxData->getCalculationAgorithm(); + return isset($this->mapping[$algorithm]) ? $this->mapping[$algorithm] : self::TOTAL_ROUNDING; + } } diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index 0c32a23043f7aabb6ff8d2e971ade43e57ccf0c3..ac700c144f5744c488a603e4ea38d0da939a7eac 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -31,6 +31,9 @@ use Magento\Bundle\Pricing\Price\BundleSelectionFactory; use Magento\Framework\Pricing\Adjustment\Calculator as CalculatorBase; use Magento\Bundle\Model\Product\Price; use Magento\Bundle\Pricing\Price\BundleOptionPrice; +use Magento\Tax\Model\Calculation as TaxCalculation; +use Magento\Store\Model\Store; +use Magento\Tax\Helper\Data as TaxHelper; /** * Bundle price calculator @@ -52,20 +55,29 @@ class Calculator implements BundleCalculatorInterface */ protected $selectionFactory; + /** + * Tax helper, needed to get rounding setting + * + * @var TaxHelper + */ + protected $taxHelper; /** * @param CalculatorBase $calculator * @param AmountFactory $amountFactory * @param BundleSelectionFactory $bundleSelectionFactory + * @param TaxHelper $taxHelper * @return Calculator */ public function __construct( CalculatorBase $calculator, AmountFactory $amountFactory, - BundleSelectionFactory $bundleSelectionFactory + BundleSelectionFactory $bundleSelectionFactory, + TaxHelper $taxHelper ) { $this->calculator = $calculator; $this->amountFactory = $amountFactory; $this->selectionFactory = $bundleSelectionFactory; + $this->taxHelper = $taxHelper; } /** @@ -254,11 +266,24 @@ class Calculator implements BundleCalculatorInterface foreach ($selectionPriceList as $selectionPrice) { $amountList[] = $selectionPrice->getAmount(); } + /** @var Store $store */ + $store = $bundleProduct->getStore(); + $roundingMethod = $this->taxHelper->getCalculationAgorithm($store); /** @var \Magento\Framework\Pricing\Amount\AmountInterface $itemAmount */ foreach ($amountList as $itemAmount) { - $fullAmount += $itemAmount->getValue(); - foreach ($itemAmount->getAdjustmentAmounts() as $code => $adjustment) { - $adjustments[$code] = isset($adjustments[$code]) ? $adjustments[$code] + $adjustment : $adjustment; + if ($roundingMethod != TaxCalculation::CALC_TOTAL_BASE) { + //We need to round the individual selection first + $fullAmount += $store->roundPrice($itemAmount->getValue()); + foreach ($itemAmount->getAdjustmentAmounts() as $code => $adjustment) { + $adjustment = $store->roundPrice($adjustment); + $adjustments[$code] = isset($adjustments[$code]) ? $adjustments[$code] + $adjustment : $adjustment; + } + } else { + $fullAmount += $itemAmount->getValue(); + foreach ($itemAmount->getAdjustmentAmounts() as $code => $adjustment) { + $adjustments[$code] = isset($adjustments[$code]) ? $adjustments[$code] + $adjustment : $adjustment; + } + } } if ($exclude && isset($adjustments[$exclude])) { diff --git a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle.phtml b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle.phtml index c6fcace245b5db528c00c5d53c455ad3e6b1074a..29926a7a454c2502a7b9c8796fca41cb9601ba6d 100644 --- a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle.phtml +++ b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle.phtml @@ -32,6 +32,7 @@ $(document).ready(function() { $('#product_addtocart_form').mage('bundleOption', { "bundleConfig": <?php echo $this->getJsonConfig() ?>, + "roundingMethod" : "<?php echo $this->getRoundingMethod() ?>", "bundleOptionQtyPrefix": "#bundle-option-", "bundleOptionQtySuffix": "-qty-input", "priceSelectors": { diff --git a/app/code/Magento/Bundle/view/frontend/web/bundle.js b/app/code/Magento/Bundle/view/frontend/web/bundle.js index 4ac75e5ae6083585dff48cf70122164ed15bb78e..0310fe5aa0687b5822757ac0a4d5f3430f4e4787 100644 --- a/app/code/Magento/Bundle/view/frontend/web/bundle.js +++ b/app/code/Magento/Bundle/view/frontend/web/bundle.js @@ -251,6 +251,10 @@ }, selectionPrice: function(optionId, selectionId) { + //Those constants need to be in sync with Magento\Bundle\Block\Catalog\Product\View\Type\Bundle + var TOTAL_ROUNDING = 2; + var ROW_ROUNDING = 1; + var UNIT_ROUNDING = 0; var qty = null, config = this.options.bundleConfig, configOption = config.options[optionId]; @@ -281,7 +285,19 @@ }); } - return [price * qty, exclTaxPrice * qty, inclTaxPrice * qty]; + if (this.options.bundleConfig.isFixedPrice || this.options.roundingMethod == TOTAL_ROUNDING) { + return [price * qty, exclTaxPrice * qty, inclTaxPrice * qty]; + } else if (this.options.roundingMethod == UNIT_ROUNDING) { + price = Math.round(price * 100) / 100; + exclTaxPrice = Math.round(exclTaxPrice * 100) / 100; + inclTaxPrice = Math.round(inclTaxPrice * 100) / 100; + return [price * qty, exclTaxPrice * qty, inclTaxPrice * qty]; + } else { + var rowTotal = Math.round(price * qty * 100) /100; + var rowTotalExclTax = Math.round(exclTaxPrice * qty * 100) /100; + var rowTotalInclTax = Math.round(inclTaxPrice * qty * 100) /100; + return [rowTotal, rowTotalExclTax, rowTotalInclTax]; + } }, populateQty: function(optionId, selectionId) { diff --git a/app/code/Magento/Catalog/Block/Product/View.php b/app/code/Magento/Catalog/Block/Product/View.php index 546eaa128f4c1742bec617e0d6171d25347ce3a9..031273808fa6bf81a497a3e3829ca3fc637798ad 100644 --- a/app/code/Magento/Catalog/Block/Product/View.php +++ b/app/code/Magento/Catalog/Block/Product/View.php @@ -236,7 +236,7 @@ class View extends AbstractProduct implements \Magento\Framework\View\Block\Iden return $this->_jsonEncoder->encode($config); } - $request = $this->_taxCalculation->getRateRequest(false, false, false); + $request = $this->_taxCalculation->getDefaultRateRequest(); /* @var $product \Magento\Catalog\Model\Product */ $product = $this->getProduct(); $request->setProductClassId($product->getTaxClassId()); diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Groupprice/AbstractGroupprice.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Groupprice/AbstractGroupprice.php index 93e54cbbd9e723ea27a957f29f2b7479c8d9380b..8f726dfda1b6db7c6d0f8cf6f8910d20fbab7fb3 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Groupprice/AbstractGroupprice.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Groupprice/AbstractGroupprice.php @@ -169,6 +169,11 @@ abstract class AbstractGroupprice extends Price if (isset($duplicates[$compare])) { throw new \Magento\Framework\Model\Exception($this->_getDuplicateErrorMessage()); } + + if (!preg_match('/^\d*(\.|,)?\d{0,4}$/i', $priceRow['price']) || $priceRow['price'] < 0) { + return __('Group price must be a number greater than 0.'); + } + $duplicates[$compare] = true; } diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php index a6b2cd70383d98c4f2a7ee9df06cf4227eac4967..3f007f47d416f3d5d642621a7759d24b6b1193d9 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php @@ -346,6 +346,7 @@ class Media extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend $this->_getResource()->deleteGallery($recordsToDelete); $this->removeDeletedImages($filesToDelete); + $object->setData($attrCode, $value); } /** diff --git a/app/code/Magento/Catalog/Model/Product/PriceModifier.php b/app/code/Magento/Catalog/Model/Product/PriceModifier.php new file mode 100644 index 0000000000000000000000000000000000000000..01373135fa1038be0c3783fcd69104279650e211 --- /dev/null +++ b/app/code/Magento/Catalog/Model/Product/PriceModifier.php @@ -0,0 +1,109 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Catalog\Model\Product; + +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Exception\CouldNotSaveException; + +class PriceModifier +{ + /** + * @param \Magento\Catalog\Model\Product $product + * @param int $customerGroupId + * @param int $websiteId + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\CouldNotSaveException + * @return void + */ + public function removeGroupPrice(\Magento\Catalog\Model\Product $product, $customerGroupId, $websiteId) + { + $prices = $product->getData('group_price'); + if (is_null($prices)) { + throw new NoSuchEntityException("This product doesn't have group price"); + } + $groupPriceQty = count($prices); + + foreach ($prices as $key => $groupPrice) { + if ($groupPrice['cust_group'] == $customerGroupId + && intval($groupPrice['website_id']) === intval($websiteId)) { + unset ($prices[$key]); + } + } + if ($groupPriceQty == count($prices)) { + throw new NoSuchEntityException( + "Product hasn't group price with such data: customerGroupId = '$customerGroupId'," + . "website = $websiteId." + ); + } + $product->setData('group_price', $prices); + try { + $product->save(); + } catch (\Exception $exception) { + throw new CouldNotSaveException("Invalid data provided for group price"); + } + } + + /** + * @param \Magento\Catalog\Model\Product $product + * @param int|string $customerGroupId + * @param int $qty + * @param int $websiteId + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\CouldNotSaveException + * @return void + */ + public function removeTierPrice(\Magento\Catalog\Model\Product $product, $customerGroupId, $qty, $websiteId) + { + $prices = $product->getData('tier_price'); + // verify if price exist + if (is_null($prices)) { + throw new NoSuchEntityException("This product doesn't have tier price"); + } + $tierPricesQty = count($prices); + + foreach ($prices as $key => $tierPrice) { + if ($customerGroupId == 'all' && $tierPrice['price_qty'] == $qty + && $tierPrice['all_groups'] == 1 && intval($tierPrice['website_id']) === intval($websiteId)) { + unset ($prices[$key]); + } elseif ($tierPrice['price_qty'] == $qty && $tierPrice['cust_group'] == $customerGroupId + && intval($tierPrice['website_id']) === intval($websiteId)) { + unset ($prices[$key]); + } + } + + if ($tierPricesQty == count($prices)) { + throw new NoSuchEntityException( + "Product hasn't group price with such data: customerGroupId = '$customerGroupId'," + . "website = $websiteId, qty = $qty" + ); + } + $product->setData('tier_price', $prices); + try { + $product->save(); + } catch (\Exception $exception) { + throw new CouldNotSaveException("Invalid data provided for tier_price"); + } + } +} diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php new file mode 100644 index 0000000000000000000000000000000000000000..8dc31bb44c1bf020747e3879ca223e22dca0d223 --- /dev/null +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -0,0 +1,73 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Model; + +use Magento\Framework\Exception\NoSuchEntityException; + +class ProductRepository +{ + /** + * @var ProductFactory + */ + protected $productFactory; + + /** + * @var Product[] + */ + protected $instances = array(); + + /** + * @param ProductFactory $productFactory + */ + public function __construct(ProductFactory $productFactory) + { + $this->productFactory = $productFactory; + } + + /** + * Retrieve product instance by sku + * + * @param string $sku + * @param boolean $editMode + * @return Product + * @throws NoSuchEntityException + */ + public function get($sku, $editMode = false) + { + if (!isset($this->instances[$sku])) { + $product = $this->productFactory->create(); + $productId = $product->getIdBySku($sku); + if (!$productId) { + throw new NoSuchEntityException('Requested product doesn\'t exist'); + } + if ($editMode) { + $product->setData('_edit_mode', true); + } + $product->load($productId); + $this->instances[$sku] = $product; + } + return $this->instances[$sku]; + } +} diff --git a/app/code/Magento/Catalog/Pricing/Price/GroupPrice.php b/app/code/Magento/Catalog/Pricing/Price/GroupPrice.php index 9fcec9c00de511f86bceabfb232a4a91d3e59ce7..626f76151d28ec16bbbb1229be13a3f7e785f36a 100644 --- a/app/code/Magento/Catalog/Pricing/Price/GroupPrice.php +++ b/app/code/Magento/Catalog/Pricing/Price/GroupPrice.php @@ -100,21 +100,16 @@ class GroupPrice extends AbstractPrice implements GroupPriceInterface, BasePrice */ public function getStoredGroupPrice() { - if (null !== $this->storedGroupPrice) { - return $this->storedGroupPrice; - } - - $this->storedGroupPrice = $this->product->getData('group_price'); - if (null === $this->storedGroupPrice) { - $attribute = $this->product->getResource()->getAttribute('group_price'); + $resource = $this->product->getResource(); + $attribute = $resource->getAttribute('group_price'); if ($attribute) { $attribute->getBackend()->afterLoad($this->product); $this->storedGroupPrice = $this->product->getData('group_price'); } - } - if (null === $this->storedGroupPrice || !is_array($this->storedGroupPrice)) { - $this->storedGroupPrice = []; + if (null === $this->storedGroupPrice || !is_array($this->storedGroupPrice)) { + $this->storedGroupPrice = []; + } } return $this->storedGroupPrice; } diff --git a/app/code/Magento/Catalog/Service/V1/Data/Product/GroupPrice.php b/app/code/Magento/Catalog/Service/V1/Data/Product/GroupPrice.php new file mode 100644 index 0000000000000000000000000000000000000000..83e8212c9e919061dd54b1cad2d5474790b336ec --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Data/Product/GroupPrice.php @@ -0,0 +1,53 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Data\Product; + +use Magento\Framework\Service\Data\AbstractObject; + +class GroupPrice extends AbstractObject +{ + const CUSTOMER_GROUP_ID = 'customer_group_id'; + const VALUE = 'value'; + + /** + * Retrieve customer group id + * + * @return int + */ + public function getCustomerGroupId() + { + return $this->_get(self::CUSTOMER_GROUP_ID); + } + + /** + * Retrieve price value + * + * @return float + */ + public function getValue() + { + return $this->_get(self::VALUE); + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Data/Product/GroupPriceBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Product/GroupPriceBuilder.php new file mode 100644 index 0000000000000000000000000000000000000000..3210e1dc84f71da1488fdccd3c7ccf7874f98a09 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Data/Product/GroupPriceBuilder.php @@ -0,0 +1,54 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Data\Product; + +use Magento\Framework\Service\Data\AbstractObjectBuilder; + +class GroupPriceBuilder extends AbstractObjectBuilder +{ + /** + * Set customer group id + * + * @param int $customerGroupId + * @return $this + */ + public function setCustomerGroupId($customerGroupId) + { + $this->_set(GroupPrice::CUSTOMER_GROUP_ID, $customerGroupId); + return $this; + } + + /** + * Set price value + * + * @param float $value + * @return $this + */ + public function setValue($value) + { + $this->_set(GroupPrice::VALUE, $value); + return $this; + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Data/Product/TierPrice.php b/app/code/Magento/Catalog/Service/V1/Data/Product/TierPrice.php new file mode 100644 index 0000000000000000000000000000000000000000..75e554ed306e3a39797d449a7f684cfe759b0d63 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Data/Product/TierPrice.php @@ -0,0 +1,54 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Data\Product; + +use Magento\Framework\Service\Data\AbstractObject; + +class TierPrice extends AbstractObject +{ + const QTY = 'qty'; + + const VALUE = 'value'; + + /** + * Retrieve tier qty + * + * @return float + */ + public function getQty() + { + return $this->_get(self::QTY); + } + + /** + * Retrieve price value + * + * @return float + */ + public function getValue() + { + return $this->_get(self::VALUE); + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Data/Product/TierPriceBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Product/TierPriceBuilder.php new file mode 100644 index 0000000000000000000000000000000000000000..4903056618bd1f070c711a392589b8c0d400f6e8 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Data/Product/TierPriceBuilder.php @@ -0,0 +1,54 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Data\Product; + +use Magento\Framework\Service\Data\AbstractObjectBuilder; + +class TierPriceBuilder extends AbstractObjectBuilder +{ + /** + * Set Quantity + * + * @param float $qty + * @return $this + */ + public function setQty($qty) + { + $this->_set(TierPrice::QTY, $qty); + return $this; + } + + /** + * Set Value + * + * @param float $value + * @return $this + */ + public function setValue($value) + { + $this->_set(TierPrice::VALUE, $value); + return $this; + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntry.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntry.php new file mode 100644 index 0000000000000000000000000000000000000000..489990c592608f6c226c5f7dfdbc2ccfc28d9e22 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntry.php @@ -0,0 +1,98 @@ +<?php +/** + * Product Media Attribute + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media\Data; + +use \Magento\Framework\Service\Data\AbstractObject; + +class GalleryEntry extends AbstractObject +{ + const ID = 'id'; + const LABEL = 'label'; + const POSITION = 'position'; + const DISABLED = 'disabled'; + const TYPES = 'types'; + const FILE = 'file'; + + /** + * Retrieve gallery entry ID + * + * @return int|null + */ + public function getId() + { + return $this->_get(self::ID); + } + + /** + * Retrieve gallery entry alternative text + * + * @return string|null + */ + public function getLabel() + { + return $this->_get(self::LABEL); + } + + /** + * Retrieve gallery entry position (sort order) + * + * @return int + */ + public function getPosition() + { + return $this->_get(self::POSITION); + } + + /** + * Check if gallery entry is hidden from product page + * + * @return bool + */ + public function isDisabled() + { + return $this->_get(self::DISABLED); + } + + /** + * Retrieve gallery entry image types (thumbnail, image, small_image etc) + * + * @return string[]|null + */ + public function getTypes() + { + return $this->_get(self::TYPES); + } + + /** + * Get file path + * + * @return string|null + */ + public function getFile() + { + return $this->_get(self::FILE); + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryBuilder.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryBuilder.php new file mode 100644 index 0000000000000000000000000000000000000000..b613592fe078053de3d7bf5d81ac1d0d9699705e --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryBuilder.php @@ -0,0 +1,97 @@ +<?php +/** + * Builder for media attribute + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media\Data; + +use Magento\Framework\Service\Data\AbstractObjectBuilder; + +class GalleryEntryBuilder extends AbstractObjectBuilder +{ + /** + * Set gallery entity ID + * + * @param int $entityId + * @return $this + */ + public function setId($entityId) + { + return $this->_set(GalleryEntry::ID, $entityId); + } + + /** + * Set media alternative text + * + * @param string $label + * @return $this + */ + public function setLabel($label) + { + return $this->_set(GalleryEntry::LABEL, $label); + } + + /** + * Set gallery entity position (sort order) + * + * @param int $position + * @return $this + */ + public function setPosition($position) + { + return $this->_set(GalleryEntry::POSITION, $position); + } + + /** + * Set disabled flag that shows if gallery entity is hidden from product page + * + * @param bool $isDisabled + * @return $this + */ + public function setDisabled($isDisabled) + { + return $this->_set(GalleryEntry::DISABLED, $isDisabled); + } + + /** + * Set gallery entry types (thumbnail, image, small_image etc) + * + * @param array $roles + * @return $this + */ + public function setTypes(array $roles) + { + return $this->_set(GalleryEntry::TYPES, $roles); + } + + /** + * Set file path + * + * @param string $file + * @return $this + */ + public function setFile($file) + { + return $this->_set(GalleryEntry::FILE, $file); + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryContent.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryContent.php new file mode 100644 index 0000000000000000000000000000000000000000..87777694aa15db1ada8636cc787f8c958a6c89ab --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryContent.php @@ -0,0 +1,65 @@ +<?php +/** + * Product Media Content + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media\Data; + +use \Magento\Framework\Service\Data\AbstractObject; + +class GalleryEntryContent extends AbstractObject +{ + const DATA = 'data'; + const MIME_TYPE = 'mime_type'; + const NAME = 'name'; + + /** + * Retrieve media data (base64 encoded content) + * + * @return string + */ + public function getData() + { + return $this->_get(self::DATA); + } + + /** + * Retrieve MIME type + * + * @return string + */ + public function getMimeType() + { + return $this->_get(self::MIME_TYPE); + } + + /** + * Retrieve image name + * + * @return string + */ + public function getName() + { + return $this->_get(self::NAME); + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryContentBuilder.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryContentBuilder.php new file mode 100644 index 0000000000000000000000000000000000000000..16ee223a7ac95fad837a9b0c9167d4399c9a1307 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryContentBuilder.php @@ -0,0 +1,64 @@ +<?php +/** + * Product Media Content Builder + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media\Data; + +use Magento\Framework\Service\Data\AbstractObjectBuilder; + +class GalleryEntryContentBuilder extends AbstractObjectBuilder +{ + /** + * Set media data (base64 encoded content) + * + * @param string $data + * @return $this + */ + public function setData($data) + { + return $this->_set(GalleryEntryContent::DATA, $data); + } + + /** + * Set MIME type + * + * @param string $mimeType + * @return $this + */ + public function setMimeType($mimeType) + { + return $this->_set(GalleryEntryContent::MIME_TYPE, $mimeType); + } + + /** + * Set image name (without extension) + * + * @param string $name + * @return $this + */ + public function setName($name) + { + return $this->_set(GalleryEntryContent::NAME, $name); + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryContentValidator.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryContentValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..170b53b0aee02ccd6b7831d964827e755862b7ba --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryContentValidator.php @@ -0,0 +1,108 @@ +<?php +/** + * Product Media Content Validator + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media\Data; + +use \Magento\Framework\Exception\InputException; + +class GalleryEntryContentValidator +{ + /** + * @var array + */ + private $defaultMimeTypes = array( + 'image/jpg', + 'image/jpeg', + 'image/gif', + 'image/png', + ); + + /** + * @var array + */ + private $allowedMimeTypes; + + /** + * @param array $allowedMimeTypes + */ + public function __construct( + array $allowedMimeTypes = array() + ) { + $this->allowedMimeTypes = array_merge($this->defaultMimeTypes, $allowedMimeTypes); + } + + /** + * Check if gallery entry content is valid + * + * @param GalleryEntryContent $entryContent + * @return bool + * @throws InputException + */ + public function isValid(GalleryEntryContent $entryContent) + { + $fileContent = @base64_decode($entryContent->getData(), true); + if (empty($fileContent)) { + throw new InputException('The image content must be valid base64 encoded data.'); + } + $imageProperties = @getimagesizefromstring($fileContent); + if (empty($imageProperties)) { + throw new InputException('The image content must be valid base64 encoded data.'); + } + $sourceMimeType = $imageProperties['mime']; + if ($sourceMimeType != $entryContent->getMimeType() || !$this->isMimeTypeValid($sourceMimeType)) { + throw new InputException('The image MIME type is not valid or not supported.'); + } + if (!$this->isNameValid($entryContent->getName())) { + throw new InputException('Provided image name contains forbidden characters.'); + } + return true; + } + + /** + * Check if given mime type is valid + * + * @param string $mimeType + * @return bool + */ + protected function isMimeTypeValid($mimeType) + { + return in_array($mimeType, $this->allowedMimeTypes); + } + + /** + * Check if given filename is valid + * + * @param string $name + * @return bool + */ + protected function isNameValid($name) + { + // Cannot contain \ / : * ? " < > | + if (!preg_match('/^[^\\/?*:";<>()|{}\\\\]+$/', $name)) { + return false; + } + return true; + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/MediaImage.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/MediaImage.php new file mode 100644 index 0000000000000000000000000000000000000000..6b4769a693e64290186b16c9628e08371f8fb3db --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/MediaImage.php @@ -0,0 +1,78 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media\Data; + +/** + * Contains media_image attribute info + */ +class MediaImage extends \Magento\Framework\Service\Data\AbstractObject +{ + const CODE = 'code'; + + const SCOPE = 'scope'; + + const LABEL = 'frontend_label'; + + const IS_USER_DEFINED = 'is_user_defined'; + + /** + * attribute code + * + * @return string + */ + public function getCode() + { + return $this->_get(self::CODE); + } + + /** + * Return values are 'Global', 'Website' or 'Store View' + * + * @return string + */ + public function getScope() + { + return $this->_get(self::SCOPE); + } + + /** + * Frontend label for attribute + * + * @return string + */ + public function getFrontendLabel() + { + return $this->_get(self::LABEL); + } + + /** + * User defined or system attribute + * + * @return int 0 or 1 + */ + public function getIsUserDefined() + { + return (int)(bool)$this->_get(self::IS_USER_DEFINED); + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/MediaImageBuilder.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/MediaImageBuilder.php new file mode 100644 index 0000000000000000000000000000000000000000..3689228c4731a281708db43d85c21a2aeabe2a13 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/MediaImageBuilder.php @@ -0,0 +1,74 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media\Data; + +/** + * Builder for media_image + */ +class MediaImageBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder +{ + /** + * Set attribute code + * + * @param string $code + * @return $this + */ + public function setCode($code) + { + return $this->_set(MediaImage::CODE, $code); + } + + /** + * Set attribute frontend label + * + * @param string $label + * @return $this + */ + public function setFrontendLabel($label) + { + return $this->_set(MediaImage::LABEL, $label); + } + + /** + * Set attribute scope. Valid values are 'Global', 'Website' and 'Store View' + * + * @param string $scope + * @return $this + */ + public function setScope($scope) + { + return $this->_set(MediaImage::SCOPE, $scope); + } + + /** + * Set true for user attributes or false for system attributes + * + * @param bool $isUserDefined + * @return $this + */ + public function setIsUserDefined($isUserDefined) + { + return $this->_set(MediaImage::IS_USER_DEFINED, $isUserDefined); + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/GalleryEntryResolver.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/GalleryEntryResolver.php new file mode 100644 index 0000000000000000000000000000000000000000..95cea9d34bce06f66cb14b37cc6259468376c45a --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/GalleryEntryResolver.php @@ -0,0 +1,75 @@ +<?php +/** + * Product Media Gallery Entry Resolver + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media; + +use \Magento\Catalog\Model\Product; + +class GalleryEntryResolver +{ + /** + * Retrieve file path that corresponds to the given gallery entry ID + * + * @param Product $product + * @param int $entryId + * @return string|null + */ + public function getEntryFilePathById(Product $product, $entryId) + { + $mediaGalleryData = $product->getData('media_gallery'); + if (!isset($mediaGalleryData['images']) || !is_array($mediaGalleryData['images'])) { + return null; + } + + foreach ($mediaGalleryData['images'] as $image) { + if (isset($image['value_id']) && $image['value_id'] == $entryId) { + return isset($image['file']) ? $image['file'] : null; + } + } + return null; + } + + /** + * Retrieve gallery entry ID that corresponds to the given file path + * + * @param Product $product + * @param string $filePath + * @return int|null + */ + public function getEntryIdByFilePath(Product $product, $filePath) + { + $mediaGalleryData = $product->getData('media_gallery'); + if (!isset($mediaGalleryData['images']) || !is_array($mediaGalleryData['images'])) { + return null; + } + + foreach ($mediaGalleryData['images'] as $image) { + if (isset($image['file']) && $image['file'] == $filePath) { + return isset($image['value_id']) ? $image['value_id'] : null; + } + } + return null; + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/ReadService.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/ReadService.php new file mode 100644 index 0000000000000000000000000000000000000000..22794baae06cc76865a54cb6fd83001c50bc3567 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/ReadService.php @@ -0,0 +1,242 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Catalog\Service\V1\Product\Attribute\Media; + +use Magento\Catalog\Service\V1\Product\Attribute\Media\Data\MediaImageBuilder; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Exception\InputException; +use Magento\Framework\Exception\StateException; +use \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntryBuilder; +use \Magento\Catalog\Model\Product; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ReadService implements ReadServiceInterface +{ + /** + * @var \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory + */ + protected $collectionFactory; + + /** + * @var \Magento\Eav\Model\Entity\Attribute\SetFactory + */ + protected $setFactory; + + /** @var \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\MediaImageBuilder */ + protected $builder; + + /** + * @var \Magento\Eav\Model\Config + */ + protected $eavConfig; + + /** + * @var \Magento\Catalog\Model\ProductRepository + */ + protected $productRepository; + + /** + * @var GalleryEntryBuilder + */ + protected $galleryEntryBuilder; + + /** + * @var \Magento\Catalog\Model\Resource\Product\Attribute\Backend\Media + */ + protected $mediaGallery; + + /** + * @var \Magento\Catalog\Model\Resource\Eav\AttributeFactory + */ + protected $attributeFactory; + + /** + * @var \Magento\Store\Model\StoreManagerInterface + */ + protected $storeManager; + + /** + * @param \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $collectionFactory + * @param \Magento\Eav\Model\Entity\Attribute\SetFactory $setFactory + * @param \Magento\Eav\Model\Config $eavConfig + * @param \Magento\Catalog\Model\Resource\Product\Attribute\Backend\Media $mediaGallery + * @param \Magento\Catalog\Model\Resource\Eav\AttributeFactory $attributeFactory + * @param \Magento\Store\Model\StoreManagerInterface $storeManager + * @param MediaImageBuilder $mediaImageBuilder + * @param \Magento\Catalog\Model\ProductRepository $productRepository + * @param GalleryEntryBuilder $galleryEntryBuilder + */ + public function __construct( + \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $collectionFactory, + \Magento\Eav\Model\Entity\Attribute\SetFactory $setFactory, + \Magento\Eav\Model\Config $eavConfig, + \Magento\Catalog\Model\Resource\Product\Attribute\Backend\Media $mediaGallery, + \Magento\Catalog\Model\Resource\Eav\AttributeFactory $attributeFactory, + \Magento\Store\Model\StoreManagerInterface $storeManager, + MediaImageBuilder $mediaImageBuilder, + \Magento\Catalog\Model\ProductRepository $productRepository, + GalleryEntryBuilder $galleryEntryBuilder + ) { + $this->collectionFactory = $collectionFactory; + $this->setFactory = $setFactory; + $this->eavConfig = $eavConfig; + $this->mediaGallery = $mediaGallery; + $this->attributeFactory = $attributeFactory; + $this->storeManager = $storeManager; + $this->builder = $mediaImageBuilder; + $this->productRepository = $productRepository; + $this->galleryEntryBuilder = $galleryEntryBuilder; + } + + /** + * Convert data from array to data object + * + * @param \Magento\Catalog\Model\Resource\Eav\Attribute[] $items + * @return array|\Magento\Catalog\Model\Resource\Eav\Attribute[] + * @throws \Magento\Framework\Exception\StateException + */ + protected function prepareData($items) + { + $data = []; + /** @var \Magento\Catalog\Model\Resource\Eav\Attribute $attribute */ + foreach ($items as $attribute) { + $this->builder->setFrontendLabel($attribute->getStoreLabel()); + $this->builder->setCode($attribute->getData('attribute_code')); + $this->builder->setIsUserDefined($attribute->getData('is_user_defined')); + if ($attribute->getIsGlobal()) { + $scope = 'Global'; + } elseif ($attribute->isScopeWebsite()) { + $scope = 'Website'; + } elseif ($attribute->isScopeStore()) { + $scope = 'Store View'; + } else { + throw new StateException('Attribute has invalid scope. Id = ' . $attribute->getId()); + } + $this->builder->setScope($scope); + $data[] = $this->builder->create(); + } + return $data; + } + + /** + * {@inheritdoc} + */ + public function types($attributeSetId) + { + $attributeSet = $this->setFactory->create()->load($attributeSetId); + if (!$attributeSet->getId()) { + throw NoSuchEntityException::singleField('attribute_set_id', $attributeSetId); + } + + $productEntityId = $this->eavConfig->getEntityType(\Magento\Catalog\Model\Product::ENTITY)->getId(); + if ($attributeSet->getEntityTypeId() != $productEntityId) { + throw InputException::invalidFieldValue('entity_type_id', $attributeSetId); + } + + $collection = $this->collectionFactory->create(); + $collection->setAttributeSetFilter($attributeSetId); + $collection->setFrontendInputTypeFilter('media_image'); + $collection->addStoreLabel($this->storeManager->getStore()->getId()); + + return $this->prepareData($collection->getItems()); + } + + /** + * {@inheritdoc} + */ + public function getList($productSku) + { + $result = array(); + /** @var \Magento\Catalog\Model\Product $product */ + $product = $this->productRepository->get($productSku); + + $galleryAttribute = $this->attributeFactory->create()->loadByCode( + $this->eavConfig->getEntityType(\Magento\Catalog\Model\Product::ENTITY), + 'media_gallery' + ); + + $container = new \Magento\Framework\Object(array('attribute' => $galleryAttribute)); + $gallery = $this->mediaGallery->loadGallery($product, $container); + + $productImages = $this->getMediaAttributeValues($product); + + foreach ($gallery as $image) { + $this->galleryEntryBuilder->setId($image['value_id']); + $this->galleryEntryBuilder->setLabel($image['label_default']); + $this->galleryEntryBuilder->setTypes(array_keys($productImages, $image['file'])); + $this->galleryEntryBuilder->setDisabled($image['disabled_default']); + $this->galleryEntryBuilder->setPosition($image['position_default']); + $this->galleryEntryBuilder->setFile($image['file']); + $result[] = $this->galleryEntryBuilder->create(); + } + return $result; + } + + /** + * {@inheritdoc} + */ + public function info($productSku, $imageId) + { + try { + $product = $this->productRepository->get($productSku); + } catch (\Exception $exception) { + throw new NoSuchEntityException("Such product doesn't exist"); + } + + $output = null; + $productImages = $this->getMediaAttributeValues($product); + foreach ((array)$product->getMediaGallery('images') as $image) { + if (intval($image['value_id']) == intval($imageId)) { + $image['types'] = array_keys($productImages, $image['file']); + $output = $this->galleryEntryBuilder->populateWithArray($image)->create(); + break; + } + } + + if (is_null($output)) { + throw new NoSuchEntityException("Such image doesn't exist"); + } + return $output; + } + + /** + * Retrieve assoc array that contains media attribute values of the given product + * + * @param Product $product + * @return array + */ + protected function getMediaAttributeValues(Product $product) + { + $mediaAttributeCodes = array_keys($product->getMediaAttributes()); + $mediaAttributeValues = array(); + foreach ($mediaAttributeCodes as $attributeCode) { + $mediaAttributeValues[$attributeCode] = $product->getData($attributeCode); + } + return $mediaAttributeValues; + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/ReadServiceInterface.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/ReadServiceInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..020e95b2e2a4896dc722e4f4d0d4af63b4eb4cc6 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/ReadServiceInterface.php @@ -0,0 +1,54 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media; + +interface ReadServiceInterface +{ + /** + * Return all media attributes for pointed attribute set + * + * @param int $attributeSetId + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\InputException + * @return \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\MediaImage[] + */ + public function types($attributeSetId); + + /** + * @param string $productSku + * @return \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntry[] + */ + public function getList($productSku); + + /** + * Return information about gallery entity + * + * @param string $productSku + * @param int $imageId + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @return \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntry + */ + public function info($productSku, $imageId); +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/WriteService.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/WriteService.php new file mode 100644 index 0000000000000000000000000000000000000000..0c80699b6dd34e83229f698a99fe6b4d00dccdcb --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/WriteService.php @@ -0,0 +1,225 @@ +<?php +/** + * Product Media Attribute + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media; + +use \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntry; +use \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntryContent; +use \Magento\Framework\App\Filesystem; +use \Magento\Catalog\Service\V1\Product\ProductLoader; +use \Magento\Catalog\Model\Product\Media\Config as MediaConfig; +use \Magento\Catalog\Model\Product; +use \Magento\Eav\Model\Entity\Attribute\AbstractAttribute; +use \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntryContentValidator; +use \Magento\Store\Model\StoreFactory; +use \Magento\Framework\Exception\InputException; +use \Magento\Framework\Exception\StateException; +use \Magento\Framework\Exception\NoSuchEntityException; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class WriteService implements WriteServiceInterface +{ + /** + * MIME type/extension map + * + * @var array + */ + private $mimeTypeExtensionMap = array( + 'image/jpg' => 'jpg', + 'image/jpeg' => 'jpg', + 'image/gif' => 'gif', + 'image/png' => 'png', + ); + + /** + * @var GalleryEntryContentValidator + */ + private $contentValidator; + + /** + * @var Filesystem + */ + private $filesystem; + + /** + * @var MediaConfig + */ + private $mediaConfig; + + /** + * @var ProductLoader + */ + private $productLoader; + + /** + * @var StoreFactory + */ + private $storeFactory; + + /** + * @var GalleryEntryResolver + */ + private $entryResolver; + + /** + * @param GalleryEntryContentValidator $contentValidator + * @param Filesystem $filesystem + * @param ProductLoader $productLoader + * @param MediaConfig $mediaConfig + * @param StoreFactory $storeFactory + * @param GalleryEntryResolver $entryResolver + */ + public function __construct( + GalleryEntryContentValidator $contentValidator, + Filesystem $filesystem, + ProductLoader $productLoader, + MediaConfig $mediaConfig, + StoreFactory $storeFactory, + GalleryEntryResolver $entryResolver + ) { + $this->contentValidator = $contentValidator; + $this->filesystem = $filesystem; + $this->productLoader = $productLoader; + $this->mediaConfig = $mediaConfig; + $this->storeFactory = $storeFactory; + $this->entryResolver = $entryResolver; + } + + /** + * {@inheritdoc} + */ + public function create($productSku, GalleryEntry $entry, GalleryEntryContent $entryContent, $storeId = 0) + { + $store = $this->storeFactory->create()->load($storeId); + if ($store->getId() != $storeId) { + throw new NoSuchEntityException('There is no store with provided ID.'); + } + if (!$this->contentValidator->isValid($entryContent)) { + throw new InputException('The image content is not valid.'); + } + $product = $this->productLoader->load($productSku); + + $fileContent = @base64_decode($entryContent->getData(), true); + $mediaTmpPath = $this->mediaConfig->getBaseTmpMediaPath(); + $mediaDirectory = $this->filesystem->getDirectoryWrite(Filesystem::MEDIA_DIR); + $mediaDirectory->create($mediaTmpPath); + $fileName = $entryContent->getName() . '.' . $this->mimeTypeExtensionMap[$entryContent->getMimeType()]; + $relativeFilePath = $mediaTmpPath . DIRECTORY_SEPARATOR . $fileName; + $absoluteFilePath = $mediaDirectory->getAbsolutePath($relativeFilePath); + $mediaDirectory->writeFile($relativeFilePath, $fileContent); + + /** @var $productMediaGallery \Magento\Catalog\Model\Product\Attribute\Backend\Media */ + $productMediaGallery = $this->getGalleryAttributeBackend($product); + $imageFileUri = $productMediaGallery->addImage( + $product, + $absoluteFilePath, + $entry->getTypes(), + true, + $entry->isDisabled() + ); + // Update additional fields that are still empty after addImage call + $productMediaGallery->updateImage($product, $imageFileUri, array( + 'label' => $entry->getLabel(), + 'position' => $entry->getPosition(), + 'disabled' => $entry->isDisabled(), + )); + $product->setStoreId($storeId); + $product->save(); + // Remove all temporary files + $mediaDirectory->delete($relativeFilePath); + // File could change its name during the move from tmp dir + return $this->entryResolver->getEntryIdByFilePath( + $product, + $productMediaGallery->getRenamedImage($imageFileUri) + ); + } + + /** + * {@inheritdoc} + */ + public function update($productSku, GalleryEntry $entry, $storeId = 0) + { + $store = $this->storeFactory->create()->load($storeId); + if ($store->getId() != $storeId) { + throw new NoSuchEntityException('There is no store with provided ID.'); + } + $product = $this->productLoader->load($productSku); + /** @var $productMediaGallery \Magento\Catalog\Model\Product\Attribute\Backend\Media */ + $productMediaGallery = $this->getGalleryAttributeBackend($product); + $filePath = $this->entryResolver->getEntryFilePathById($product, $entry->getId()); + if (is_null($filePath)) { + throw new NoSuchEntityException('There is no image with provided ID.'); + } + + $productMediaGallery->updateImage($product, $filePath, array( + 'label' => $entry->getLabel(), + 'position' => $entry->getPosition(), + 'disabled' => $entry->isDisabled(), + )); + $productMediaGallery->clearMediaAttribute($product, array_keys($product->getMediaAttributes())); + $productMediaGallery->setMediaAttribute($product, $entry->getTypes(), $filePath); + $product->setStoreId($storeId); + $product->save(); + return true; + } + + /** + * {@inheritdoc} + */ + public function delete($productSku, $entryId) + { + $product = $this->productLoader->load($productSku); + /** @var $productMediaGallery \Magento\Catalog\Model\Product\Attribute\Backend\Media */ + $productMediaGallery = $this->getGalleryAttributeBackend($product); + $filePath = $this->entryResolver->getEntryFilePathById($product, $entryId); + if (is_null($filePath)) { + throw new NoSuchEntityException('There is no image with provided ID.'); + } + + $productMediaGallery->removeImage($product, $filePath); + $product->save(); + return true; + } + + /** + * Retrieve backend model of product media gallery attribute + * + * @param Product $product + * @return \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend + * @throws StateException + */ + protected function getGalleryAttributeBackend(Product $product) + { + $attributes = $product->getTypeInstance()->getSetAttributes($product); + if (!isset($attributes['media_gallery']) || !($attributes['media_gallery'] instanceof AbstractAttribute)) { + throw new StateException('Requested product does not support images.'); + } + /** @var $galleryAttribute AbstractAttribute */ + $galleryAttribute = $attributes['media_gallery']; + return $galleryAttribute->getBackend(); + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/WriteServiceInterface.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/WriteServiceInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c5672db0f63843291a87661690c016ac8c020fe9 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/Media/WriteServiceInterface.php @@ -0,0 +1,69 @@ +<?php +/** + * Product Media Attribute Write Service + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media; + +use \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntry; +use \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntryContent; + +interface WriteServiceInterface +{ + /** + * Create new gallery entry + * + * @param string $productSku + * @param \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntry $entry + * @param \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntryContent $entryContent + * @param int $storeId + * @return int gallery entry ID + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\StateException + */ + public function create($productSku, GalleryEntry $entry, GalleryEntryContent $entryContent, $storeId = 0); + + /** + * Update gallery entry + * + * @param string $productSku + * @param \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntry $entry + * @param int $storeId + * @return bool + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\StateException + */ + public function update($productSku, GalleryEntry $entry, $storeId = 0); + + /** + * Remove gallery entry + * + * @param string $productSku + * @param int $entryId + * @return bool + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\StateException + */ + public function delete($productSku, $entryId); +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/ReadService.php b/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/ReadService.php index 3307a26979be8018d9c019a38e41d343f1c84f2c..03ebc1a45e876ab18ba09d4c3b73725303c39dc3 100644 --- a/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/ReadService.php +++ b/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/ReadService.php @@ -27,6 +27,8 @@ namespace Magento\Catalog\Service\V1\Product\AttributeGroup; use \Magento\Catalog\Service\V1\Data; use \Magento\Eav\Model\Resource\Entity\Attribute\Group\CollectionFactory as AttributeGroupCollectionFactory; +use \Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory; +use \Magento\Framework\Exception\NoSuchEntityException; class ReadService implements ReadServiceInterface { @@ -35,6 +37,11 @@ class ReadService implements ReadServiceInterface */ protected $groupListFactory; + /** + * @var \Magento\Eav\Model\Entity\Attribute\SetFactory + */ + protected $attributeSetFactory; + /** * @var \Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder */ @@ -42,13 +49,16 @@ class ReadService implements ReadServiceInterface /** * @param AttributeGroupCollectionFactory $groupListFactory - * @param \Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder $groupBuilder + * @param AttributeSetFactory $attributeSetFactory + * @param Data\Eav\AttributeGroupBuilder $groupBuilder */ public function __construct( AttributeGroupCollectionFactory $groupListFactory, + AttributeSetFactory $attributeSetFactory, Data\Eav\AttributeGroupBuilder $groupBuilder ) { $this->groupListFactory = $groupListFactory; + $this->attributeSetFactory = $attributeSetFactory; $this->groupBuilder = $groupBuilder; } @@ -57,6 +67,10 @@ class ReadService implements ReadServiceInterface */ public function getList($attributeSetId) { + if (!$this->attributeSetFactory->create()->load($attributeSetId)->getId()) { + throw NoSuchEntityException::singleField('attributeSetId', $attributeSetId); + } + $collection = $this->groupListFactory->create(); $collection->setAttributeSetFilter($attributeSetId); $collection->setSortOrder(); diff --git a/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/ReadServiceInterface.php b/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/ReadServiceInterface.php index ae4eaba782b5766f4cf6f420f229772742e4a6ee..74dc98351c95ee0a0ee21e4363250b0fc368cd5b 100644 --- a/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/ReadServiceInterface.php +++ b/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/ReadServiceInterface.php @@ -31,6 +31,7 @@ interface ReadServiceInterface * * @param string $attributeSetId * @return \Magento\Catalog\Service\V1\Data\Eav\AttributeGroup[] + * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function getList($attributeSetId); } diff --git a/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/WriteService.php b/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/WriteService.php index b6074d36a26e9031a464d611874b7b2693fd11cd..df387169387b373549f7e0c41390a93394f72ceb 100644 --- a/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/WriteService.php +++ b/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/WriteService.php @@ -26,10 +26,11 @@ namespace Magento\Catalog\Service\V1\Product\AttributeGroup; use \Magento\Catalog\Model\Product\Attribute\GroupFactory; use \Magento\Catalog\Model\Product\Attribute\Group; -use Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder; -use Magento\Framework\Exception\CouldNotSaveException; -use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Framework\Exception\StateException; +use \Magento\Eav\Model\Entity\Attribute\SetFactory; +use \Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder; +use \Magento\Framework\Exception\CouldNotSaveException; +use \Magento\Framework\Exception\NoSuchEntityException; +use \Magento\Framework\Exception\StateException; class WriteService implements WriteServiceInterface { @@ -43,13 +44,23 @@ class WriteService implements WriteServiceInterface */ protected $groupBuilder; + /** + * @var \Magento\Eav\Model\Entity\Attribute\SetFactory + */ + protected $setFactory; + /** * @param GroupFactory $groupFactory + * @param SetFactory $attributeSetFactory * @param AttributeGroupBuilder $groupBuilder */ - public function __construct(GroupFactory $groupFactory, AttributeGroupBuilder $groupBuilder) - { + public function __construct( + GroupFactory $groupFactory, + SetFactory $attributeSetFactory, + AttributeGroupBuilder $groupBuilder + ) { $this->groupFactory = $groupFactory; + $this->setFactory = $attributeSetFactory; $this->groupBuilder = $groupBuilder; } @@ -58,6 +69,10 @@ class WriteService implements WriteServiceInterface */ public function create($attributeSetId, \Magento\Catalog\Service\V1\Data\Eav\AttributeGroup $groupData) { + if (!$this->setFactory->create()->load($attributeSetId)->getId()) { + throw NoSuchEntityException::singleField('attributeSetId', $attributeSetId); + } + try { /** @var Group $attributeGroup */ $attributeGroup = $this->groupFactory->create(); @@ -70,23 +85,28 @@ class WriteService implements WriteServiceInterface $attributeGroup->getAttributeGroupName() )->create(); } catch (\Exception $e) { - throw new CouldNotSaveException('Could not create attribute group'); + throw new CouldNotSaveException( + 'Could not create attribute group. Maybe group with such name already exists' + ); } } /** * {@inheritdoc} */ - public function update($groupId, \Magento\Catalog\Service\V1\Data\Eav\AttributeGroup $groupData) + public function update($attributeSetId, $groupId, \Magento\Catalog\Service\V1\Data\Eav\AttributeGroup $groupData) { /** @var Group $attributeGroup */ $attributeGroup = $this->groupFactory->create(); $attributeGroup->load($groupId); if (!$attributeGroup->getId()) { - throw new NoSuchEntityException(); + throw NoSuchEntityException::singleField('attributeGroupId', $attributeGroup->getId()); + } + if ($attributeGroup->getAttributeSetId() != $attributeSetId) { + throw new StateException('Attribute group does not belong to provided attribute set'); } try { - $attributeGroup->setId($groupData->getId()); + $attributeGroup->setId($groupId); $attributeGroup->setAttributeGroupName($groupData->getName()); $attributeGroup->save(); } catch (\Exception $e) { @@ -97,17 +117,22 @@ class WriteService implements WriteServiceInterface /** * {@inheritdoc} */ - public function delete($groupId) + public function delete($attributeSetId, $groupId) { /** @var Group $attributeGroup */ $attributeGroup = $this->groupFactory->create(); $attributeGroup->load($groupId); + + if (!$attributeGroup->getId()) { + throw NoSuchEntityException::singleField('attributeGroupId', $groupId); + } if ($attributeGroup->hasSystemAttributes()) { throw new StateException('Attribute group that contains system attributes can not be deleted'); } - if (!$attributeGroup->getId()) { - throw new NoSuchEntityException(); + if ($attributeGroup->getAttributeSetId() != $attributeSetId) { + throw new StateException('Attribute group does not belong to provided attribute set'); } $attributeGroup->delete(); + return true; } } diff --git a/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/WriteServiceInterface.php b/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/WriteServiceInterface.php index 3d3c396539eed9b409fb70fb23af30355f5982fa..9a2515a06e3672d21bb89024fb7e72056da98f25 100644 --- a/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/WriteServiceInterface.php +++ b/app/code/Magento/Catalog/Service/V1/Product/AttributeGroup/WriteServiceInterface.php @@ -33,27 +33,31 @@ interface WriteServiceInterface * @param \Magento\Catalog\Service\V1\Data\Eav\AttributeGroup $groupData * @return \Magento\Catalog\Service\V1\Data\Eav\AttributeGroup * @throws \Magento\Framework\Exception\CouldNotSaveException + * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function create($attributeSetId, \Magento\Catalog\Service\V1\Data\Eav\AttributeGroup $groupData); /** * Update attribute group * + * @param string $attributeSetId * @param string $groupId * @param \Magento\Catalog\Service\V1\Data\Eav\AttributeGroup $groupData * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\StateException * @throws \Magento\Framework\Exception\CouldNotSaveException * @return bool */ - public function update($groupId, \Magento\Catalog\Service\V1\Data\Eav\AttributeGroup $groupData); + public function update($attributeSetId, $groupId, \Magento\Catalog\Service\V1\Data\Eav\AttributeGroup $groupData); /** * Remove attribute group * + * @param string $attributeSetId * @param string $groupId * @throws \Magento\Framework\Exception\NoSuchEntityException * @throws \Magento\Framework\Exception\StateException * @return bool */ - public function delete($groupId); + public function delete($attributeSetId, $groupId); } diff --git a/app/code/Magento/Catalog/Service/V1/Product/GroupPriceService.php b/app/code/Magento/Catalog/Service/V1/Product/GroupPriceService.php new file mode 100644 index 0000000000000000000000000000000000000000..41729855bc5f65cf981a153967c4de250f4ba421 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/GroupPriceService.php @@ -0,0 +1,175 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product; + +use Magento\Catalog\Model\ProductFactory; +use Magento\Catalog\Model\ProductRepository; +use Magento\Framework\Exception\CouldNotSaveException; +use Magento\Framework\Exception\InputException; +use Magento\Catalog\Service\V1\Data\Product; + +class GroupPriceService implements GroupPriceServiceInterface +{ + /** + * @var \Magento\Catalog\Model\ProductRepository + */ + protected $productRepository; + + /** + * @var \Magento\Catalog\Service\V1\Data\Product\GroupPriceBuilder + */ + protected $groupPriceBuilder; + + /** + * @var \Magento\Store\Model\StoreManagerInterface + */ + protected $storeManager; + + /** + * @var \Magento\Customer\Service\V1\CustomerGroupServiceInterface + */ + protected $customerGroupService; + + /** + * @var \Magento\Catalog\Model\Product\PriceModifier + */ + protected $priceModifier; + + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface + */ + protected $config; + + /** + * @param ProductRepository $productRepository + * @param Product\GroupPriceBuilder $groupPriceBuilder + * @param \Magento\Store\Model\StoreManagerInterface $storeManager + * @param \Magento\Customer\Service\V1\CustomerGroupServiceInterface $customerGroupService + * @param \Magento\Catalog\Model\Product\PriceModifier $priceModifier + * @param \Magento\Framework\App\Config\ScopeConfigInterface $config + */ + public function __construct( + ProductRepository $productRepository, + Product\GroupPriceBuilder $groupPriceBuilder, + \Magento\Store\Model\StoreManagerInterface $storeManager, + \Magento\Customer\Service\V1\CustomerGroupServiceInterface $customerGroupService, + \Magento\Catalog\Model\Product\PriceModifier $priceModifier, + \Magento\Framework\App\Config\ScopeConfigInterface $config + ) { + $this->productRepository = $productRepository; + $this->groupPriceBuilder = $groupPriceBuilder; + $this->storeManager = $storeManager; + $this->customerGroupService = $customerGroupService; + $this->priceModifier = $priceModifier; + $this->config = $config; + } + + /** + * {@inheritdoc} + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function set($productSku, \Magento\Catalog\Service\V1\Data\Product\GroupPrice $price) + { + $customerGroup = $this->customerGroupService->getGroup($price->getCustomerGroupId()); + $product = $this->productRepository->get($productSku, true); + + $groupPrices = $product->getData('group_price'); + $websiteId = 0; + if ($this->config->getValue('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) != 0) { + $websiteId = $this->storeManager->getWebsite()->getId(); + } + $found = false; + foreach ($groupPrices as &$currentPrice) { + if (intval($currentPrice['cust_group']) === $price->getCustomerGroupId() + && intval($currentPrice['website_id']) === intval($websiteId) + ) { + $currentPrice['price'] = $price->getValue(); + $found = true; + break; + } + } + if (!$found) { + $groupPrices[] = array( + 'cust_group' => $customerGroup->getId(), + 'website_id' => $websiteId, + 'price' => $price->getValue(), + ); + } + + $product->setData('group_price', $groupPrices); + $errors = $product->validate(); + if (is_array($errors) && count($errors)) { + $errorAttributeCodes = implode(', ', array_keys($errors)); + throw new InputException( + sprintf('Values of following attributes are invalid: %s', $errorAttributeCodes) + ); + } + try { + $product->save(); + } catch (\Exception $e) { + throw new CouldNotSaveException('Could not save group price'); + } + return true; + } + + /** + * {@inheritdoc} + */ + public function delete($productSku, $customerGroupId) + { + $product = $this->productRepository->get($productSku, true); + if ($this->config->getValue('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) == 0) { + $websiteId = 0; + } else { + $websiteId = $this->storeManager->getWebsite()->getId(); + } + $this->priceModifier->removeGroupPrice($product, $customerGroupId, $websiteId); + return true; + } + + /** + * {@inheritdoc} + */ + public function getList($productSku) + { + $product = $this->productRepository->get($productSku, true); + $priceKey = 'website_price'; + if ($this->config->getValue('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) == 0) { + $priceKey = 'price'; + } + + $prices = array(); + foreach ($product->getData('group_price') as $price) { + $this->groupPriceBuilder->populateWithArray(array( + Product\GroupPrice::CUSTOMER_GROUP_ID => $price['all_groups'] ? 'all' : $price['cust_group'], + Product\GroupPrice::VALUE => $price[$priceKey], + )); + $prices[] = $this->groupPriceBuilder->create(); + } + return $prices; + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/GroupPriceServiceInterface.php b/app/code/Magento/Catalog/Service/V1/Product/GroupPriceServiceInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..fa8a40f81122c91deecb20b9a062a8b55b7b545f --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/GroupPriceServiceInterface.php @@ -0,0 +1,59 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product; + +interface GroupPriceServiceInterface +{ + /** + * Set group price for product + * + * @param string $productSku + * @param \Magento\Catalog\Service\V1\Data\Product\GroupPrice $price + * @return boolean + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\CouldNotSaveException + */ + public function set($productSku, \Magento\Catalog\Service\V1\Data\Product\GroupPrice $price); + + /** + * Remove group price from product + * + * @param string $productSku + * @param int $customerGroupId + * @return boolean + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\CouldNotSaveException + */ + public function delete($productSku, $customerGroupId); + + /** + * Retrieve list of product prices + * + * @param string $productSku + * @return \Magento\Catalog\Service\V1\Data\Product\GroupPrice[] + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function getList($productSku); +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/TierPriceService.php b/app/code/Magento/Catalog/Service/V1/Product/TierPriceService.php new file mode 100644 index 0000000000000000000000000000000000000000..c45a24f22a6294654c1b7f797c6080c082f82e50 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/TierPriceService.php @@ -0,0 +1,192 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product; + +use Magento\Catalog\Model\ProductFactory; +use Magento\Catalog\Model\ProductRepository; +use Magento\Framework\Exception\InputException; +use Magento\Framework\Exception\CouldNotSaveException; +use Magento\Catalog\Service\V1\Data\Product; + +class TierPriceService implements TierPriceServiceInterface +{ + /** + * @var \Magento\Catalog\Model\ProductRepository + */ + protected $productRepository; + + /** + * @var \Magento\Catalog\Service\V1\Data\Product\TierPriceBuilder + */ + protected $priceBuilder; + + /** + * @var \Magento\Store\Model\StoreManagerInterface + */ + protected $storeManager; + + /** + * @var \Magento\Catalog\Model\Product\PriceModifier + */ + protected $priceModifier; + + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface + */ + protected $config; + + /** + * @var \Magento\Customer\Service\V1\CustomerGroupServiceInterface + */ + protected $customerGroupService; + + /** + * @param ProductRepository $productRepository + * @param Product\TierPriceBuilder $priceBuilder + * @param \Magento\Store\Model\StoreManagerInterface $storeManager + * @param \Magento\Catalog\Model\Product\PriceModifier $priceModifier + * @param \Magento\Framework\App\Config\ScopeConfigInterface $config + * @param \Magento\Customer\Service\V1\CustomerGroupServiceInterface $customerGroupService + */ + public function __construct( + ProductRepository $productRepository, + Product\TierPriceBuilder $priceBuilder, + \Magento\Store\Model\StoreManagerInterface $storeManager, + \Magento\Catalog\Model\Product\PriceModifier $priceModifier, + \Magento\Framework\App\Config\ScopeConfigInterface $config, + \Magento\Customer\Service\V1\CustomerGroupServiceInterface $customerGroupService + ) { + $this->productRepository = $productRepository; + $this->priceBuilder = $priceBuilder; + $this->storeManager = $storeManager; + $this->priceModifier = $priceModifier; + $this->config = $config; + $this->customerGroupService = $customerGroupService; + } + + /** + * {@inheritdoc} + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function set($productSku, $customerGroupId, \Magento\Catalog\Service\V1\Data\Product\TierPrice $price) + { + $product = $this->productRepository->get($productSku, true); + $customerGroup = $this->customerGroupService->getGroup($customerGroupId); + + $tierPrices = $product->getData('tier_price'); + $websiteId = 0; + if ($this->config->getValue('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) != 0) { + $websiteId = $this->storeManager->getWebsite()->getId(); + } + + $found = false; + + foreach ($tierPrices as &$item) { + if ('all' == $customerGroupId) { + $isGroupValid = ($item['all_groups'] == 1); + } else { + $isGroupValid = ($item['cust_group'] == $customerGroupId); + } + + if ($isGroupValid && $item['website_id'] == $websiteId && $item['price_qty'] == $price->getQty()) { + $item['price'] = $price->getValue(); + $found = true; + break; + } + } + if (!$found) { + $mappedCustomerGroupId = 'all' == $customerGroupId + ? \Magento\Customer\Service\V1\CustomerGroupServiceInterface::CUST_GROUP_ALL + : $customerGroup->getId(); + + $tierPrices[] = array( + 'cust_group' => $mappedCustomerGroupId, + 'price' => $price->getValue(), + 'website_price' => $price->getValue(), + 'website_id' => $websiteId, + 'price_qty' => $price->getQty() + ); + } + + $product->setData('tier_price', $tierPrices); + $errors = $product->validate(); + if (is_array($errors) && count($errors)) { + $errorAttributeCodes = implode(', ', array_keys($errors)); + throw new InputException( + sprintf('Values of following attributes are invalid: %s', $errorAttributeCodes) + ); + } + try { + $product->save(); + } catch (\Exception $e) { + throw new CouldNotSaveException('Could not save group price'); + } + return true; + } + + /** + * {@inheritdoc} + */ + public function delete($productSku, $customerGroupId, $qty) + { + $product = $this->productRepository->get($productSku, true); + if ($this->config->getValue('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) == 0) { + $websiteId = 0; + } else { + $websiteId = $this->storeManager->getWebsite()->getId(); + } + $this->priceModifier->removeTierPrice($product, $customerGroupId, $qty, $websiteId); + return true; + } + + /** + * {@inheritdoc} + */ + public function getList($productSku, $customerGroupId) + { + $product = $this->productRepository->get($productSku, true); + + $priceKey = 'website_price'; + if ($this->config->getValue('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) == 0) { + $priceKey = 'price'; + } + + $prices = array(); + foreach ($product->getData('tier_price') as $price) { + if ((is_numeric($customerGroupId) && intval($price['cust_group']) === intval($customerGroupId)) + || ($customerGroupId === 'all' && $price['all_groups']) + ) { + $this->priceBuilder->populateWithArray(array( + Product\TierPrice::VALUE => $price[$priceKey], + Product\TierPrice::QTY => $price['price_qty'] + )); + $prices[] = $this->priceBuilder->create(); + } + } + return $prices; + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/TierPriceServiceInterface.php b/app/code/Magento/Catalog/Service/V1/Product/TierPriceServiceInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..83a941fdd5cdc5c3e72d61c6d1dae355cfc7ec49 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/TierPriceServiceInterface.php @@ -0,0 +1,62 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product; + +interface TierPriceServiceInterface +{ + /** + * Create tire price for product + * + * @param string $productSku + * @param string $customerGroupId + * @param \Magento\Catalog\Service\V1\Data\Product\TierPrice $price + * @return boolean + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\CouldNotSaveException + */ + public function set($productSku, $customerGroupId, \Magento\Catalog\Service\V1\Data\Product\TierPrice $price); + + /** + * Remove tire price from product + * + * @param string $productSku + * @param string $customerGroupId + * @param float $qty + * @return boolean + * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\CouldNotSaveException + */ + public function delete($productSku, $customerGroupId, $qty); + + /** + * Get tire price of product + * + * @param string $productSku + * @param string $customerGroupId + * @return \Magento\Catalog\Service\V1\Data\Product\TierPrice[] + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function getList($productSku, $customerGroupId); +} diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index 37365f8cb6596c5e96276ae8853c9376a51c1751..e38c660f426e7632c4f8ad0f91101301148df774 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -42,9 +42,13 @@ <preference for="Magento\Catalog\Service\V1\Product\AttributeSet\ReadServiceInterface" type="Magento\Catalog\Service\V1\Product\AttributeSet\ReadService" /> <preference for="Magento\Catalog\Service\V1\Product\AttributeSet\WriteServiceInterface" type="Magento\Catalog\Service\V1\Product\AttributeSet\WriteService" /> <preference for="Magento\Catalog\Service\V1\Product\AttributeSet\AttributeServiceInterface" type="Magento\Catalog\Service\V1\Product\AttributeSet\AttributeService" /> + <preference for="Magento\Catalog\Service\V1\Product\Attribute\Media\ReadServiceInterface" type="\Magento\Catalog\Service\V1\Product\Attribute\Media\ReadService" /> + <preference for="\Magento\Catalog\Service\V1\Product\Attribute\Media\WriteServiceInterface" type="\Magento\Catalog\Service\V1\Product\Attribute\Media\WriteService" /> <preference for="Magento\Catalog\Service\V1\Product\Link\ReadServiceInterface" type="Magento\Catalog\Service\V1\Product\Link\ReadService" /> <preference for="Magento\Catalog\Service\V1\Product\Link\WriteServiceInterface" type="Magento\Catalog\Service\V1\Product\Link\WriteService" /> <preference for="Magento\Catalog\Service\V1\Product\Link\Data\ProductLink\DataMapperInterface" type="Magento\Catalog\Service\V1\Product\Link\Data\ProductLink\DataMapper\Composite" /> + <preference for="Magento\Catalog\Service\V1\Product\GroupPriceServiceInterface" type="Magento\Catalog\Service\V1\Product\GroupPriceService" /> + <preference for="Magento\Catalog\Service\V1\Product\TierPriceServiceInterface" type="Magento\Catalog\Service\V1\Product\TierPriceService" /> <type name="Magento\Log\Model\Resource\Log"> <plugin name="catalogLog" type="Magento\Catalog\Model\Plugin\Log" /> </type> diff --git a/app/code/Magento/Catalog/etc/webapi.xml b/app/code/Magento/Catalog/etc/webapi.xml index cd647e5e9e761151cd6b6c9d5f60195ae4824721..aa3c9ec05ca239ee2395fd1b4e2c7cb1295d04ed 100644 --- a/app/code/Magento/Catalog/etc/webapi.xml +++ b/app/code/Magento/Catalog/etc/webapi.xml @@ -181,4 +181,76 @@ <resource ref="Magento_Catalog::catalog"/> </resources> </route> + <route url="/V1/products/media/types/:attributeSetId" method="GET"> + <service class="Magento\Catalog\Service\V1\Product\Attribute\Media\ReadServiceInterface" method="types"/> + <resources> + <resource ref="Magento_Catalog::catalog"/> + </resources> + </route> + <route url="/V1/products/:productSku/media/:imageId" method="GET"> + <service class="Magento\Catalog\Service\V1\Product\Attribute\Media\ReadServiceInterface" method="info"/> + <resources> + <resource ref="Magento_Catalog::catalog"/> + </resources> + </route> + <route url="/V1/products/:productSku/media" method="POST"> + <service class="Magento\Catalog\Service\V1\Product\Attribute\Media\WriteServiceInterface" method="create"/> + <resources> + <resource ref="Magento_Catalog::catalog"/> + </resources> + </route> + <route url="/V1/products/:productSku/media" method="PUT"> + <service class="Magento\Catalog\Service\V1\Product\Attribute\Media\WriteServiceInterface" method="update"/> + <resources> + <resource ref="Magento_Catalog::catalog"/> + </resources> + </route> + <route url="/V1/products/:productSku/media/:entryId" method="DELETE"> + <service class="Magento\Catalog\Service\V1\Product\Attribute\Media\WriteServiceInterface" method="delete"/> + <resources> + <resource ref="Magento_Catalog::catalog"/> + </resources> + </route> + <route url="/V1/products/:productSku/media" method="GET"> + <service class="Magento\Catalog\Service\V1\Product\Attribute\Media\ReadServiceInterface" method="getList"/> + <resources> + <resource ref="Magento_Catalog::catalog"/> + </resources> + </route> + <route url="/V1/products/:productSku/group-prices" method="GET"> + <service class="Magento\Catalog\Service\V1\Product\GroupPriceServiceInterface" method="getList"/> + <resources> + <resource ref="Magento_Catalog::catalog"/> + </resources> + </route> + <route url="/V1/products/:productSku/group-prices" method="POST"> + <service class="Magento\Catalog\Service\V1\Product\GroupPriceServiceInterface" method="set"/> + <resources> + <resource ref="Magento_Catalog::catalog"/> + </resources> + </route> + <route url="/V1/products/:productSku/group-prices/:customerGroupId" method="DELETE"> + <service class="Magento\Catalog\Service\V1\Product\GroupPriceServiceInterface" method="delete"/> + <resources> + <resource ref="Magento_Catalog::catalog"/> + </resources> + </route> + <route url="/V1/products/:productSku/group-prices/:customerGroupId/tiers" method="GET"> + <service class="Magento\Catalog\Service\V1\Product\TierPriceServiceInterface" method="getList"/> + <resources> + <resource ref="Magento_Catalog::catalog"/> + </resources> + </route> + <route url="/V1/products/:productSku/group-prices/:customerGroupId/tiers" method="POST"> + <service class="Magento\Catalog\Service\V1\Product\TierPriceServiceInterface" method="set"/> + <resources> + <resource ref="Magento_Catalog::catalog"/> + </resources> + </route> + <route url="/V1/products/:productSku/group-prices/:customerGroupId/tiers/:qty" method="DELETE"> + <service class="Magento\Catalog\Service\V1\Product\TierPriceServiceInterface" method="delete"/> + <resources> + <resource ref="Magento_Catalog::catalog"/> + </resources> + </route> </routes> diff --git a/app/code/Magento/Eav/Model/Resource/Attribute/Collection.php b/app/code/Magento/Eav/Model/Resource/Attribute/Collection.php index 1cc178682cbe5d79113e5e7940fd54f74d9ca093..c924148a9e1df9ea0dd477d38b48b1de4b23701c 100644 --- a/app/code/Magento/Eav/Model/Resource/Attribute/Collection.php +++ b/app/code/Magento/Eav/Model/Resource/Attribute/Collection.php @@ -201,19 +201,19 @@ abstract class Collection extends \Magento\Eav\Model\Resource\Entity\Attribute\C $scopeColumns['scope_website_id'] = $columnName; } else { if (isset($mainColumns[$columnName])) { - $alias = sprintf('scope_%s', $columnName); - $expression = $connection->getCheckSql('main_table.%s IS NULL', 'scope_table.%s', 'main_table.%s'); - $expression = sprintf($expression, $columnName, $columnName, $columnName); + $alias = 'scope_' . $columnName; + $condition = 'main_table.' . $columnName . ' IS NULL'; + $true = 'scope_table.' . $columnName; + $false = 'main_table.' . $columnName; + $expression = $connection->getCheckSql($condition, $true, $false); $this->addFilterToMap($columnName, $expression); $scopeColumns[$alias] = $columnName; } elseif (isset($extraColumns[$columnName])) { - $alias = sprintf('scope_%s', $columnName); - $expression = $connection->getCheckSql( - 'additional_table.%s IS NULL', - 'scope_table.%s', - 'additional_table.%s' - ); - $expression = sprintf($expression, $columnName, $columnName, $columnName); + $alias = 'scope_' . $columnName; + $condition = 'additional_table.' . $columnName . ' IS NULL'; + $true = 'scope_table.' . $columnName; + $false = 'additional_table.' . $columnName; + $expression = $connection->getCheckSql($condition, $true, $false); $this->addFilterToMap($columnName, $expression); $scopeColumns[$alias] = $columnName; } diff --git a/app/code/Magento/GroupedProduct/view/base/templates/product/price/final_price.phtml b/app/code/Magento/GroupedProduct/view/base/templates/product/price/final_price.phtml index a1f0c46360243e6602f70ffd8ab6cfb8ae47cc9e..aad1419c8822e059ef620d75ee56fbcae9ada3ee 100644 --- a/app/code/Magento/GroupedProduct/view/base/templates/product/price/final_price.phtml +++ b/app/code/Magento/GroupedProduct/view/base/templates/product/price/final_price.phtml @@ -31,16 +31,19 @@ $minProduct = $this->getSaleableItem() ->getPriceInfo() ->getPrice(\Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE) ->getMinProduct(); -$amountRender = $this->getRendererPool() - ->createAmountRender( - $minProduct->getPriceInfo()->getPrice('final_price')->getAmount(), - $minProduct, - $minProduct->getPriceInfo()->getPrice('final_price'), - [] - ); + +if ($minProduct) { + $amountRender = $this->getRendererPool() + ->createAmountRender( + $minProduct->getPriceInfo()->getPrice('final_price')->getAmount(), + $minProduct, + $minProduct->getPriceInfo()->getPrice('final_price'), + [] + ); +} ?> <div class="price-box" itemprop="offers" itemscope itemtype="http://schema.org/Offer"> - <?php if (\Magento\Framework\Pricing\Render::ZONE_ITEM_VIEW != $this->getZone()): ?> + <?php if ($minProduct && \Magento\Framework\Pricing\Render::ZONE_ITEM_VIEW != $this->getZone()): ?> <p class="minimal-price"> <span class="price-label"><?php echo __('Starting at:') . $amountRender->toHtml();?></span> </p> diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml index 25c562f31744ca156a095090a945abc27560fa91..c68215b765f5727517b1065e6885007296a4c218 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml +++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml @@ -68,10 +68,6 @@ <td class="col price"> <?php if ($this->getCanShowProductPrice($_item)): ?> <?php echo $this->getProductPrice($_item) ?> - <?php echo $this->getProductPriceHtml( - $_item, - \Magento\Catalog\Pricing\Price\TierPrice::PRICE_CODE - ) ?> <?php endif; ?> </td> <?php endif; ?> diff --git a/app/code/Magento/Sales/Model/Quote/Item/AbstractItem.php b/app/code/Magento/Sales/Model/Quote/Item/AbstractItem.php index c3511a5c79729dff1821ecf053f495a61c765ce8..b37c9dd59c850edc5160e304249e3c500e90e3f1 100644 --- a/app/code/Magento/Sales/Model/Quote/Item/AbstractItem.php +++ b/app/code/Magento/Sales/Model/Quote/Item/AbstractItem.php @@ -403,7 +403,7 @@ abstract class AbstractItem extends \Magento\Framework\Model\AbstractModel imple $qty = $this->getTotalQty(); // Round unit price before multiplying to prevent losing 1 cent on subtotal $total = $this->getStore()->roundPrice($this->getCalculationPriceOriginal()) * $qty; - $baseTotal = $this->getBaseCalculationPriceOriginal() * $qty; + $baseTotal = $this->getStore()->roundPrice($this->getBaseCalculationPriceOriginal()) * $qty; $this->setRowTotal($this->getStore()->roundPrice($total)); $this->setBaseRowTotal($this->getStore()->roundPrice($baseTotal)); diff --git a/app/code/Magento/SalesRule/Model/Validator.php b/app/code/Magento/SalesRule/Model/Validator.php index 25f7269da75a6fe6a2460fc43785a8fc50a77d17..12367e76dc23821de6355fcc8529f5b84a91d0b2 100644 --- a/app/code/Magento/SalesRule/Model/Validator.php +++ b/app/code/Magento/SalesRule/Model/Validator.php @@ -173,7 +173,8 @@ class Validator extends \Magento\Framework\Model\AbstractModel $websiteId, $customerGroupId, $couponCode - )->load(); + )->addFieldToFilter('is_active', 1) + ->load(); } return $this; } diff --git a/app/code/Magento/Tax/Block/Adminhtml/Rule/Edit/Form.php b/app/code/Magento/Tax/Block/Adminhtml/Rule/Edit/Form.php index dc44e5abfd065e05b66af6f2ae6bd081de4db604..b5c6352852ab5a325f3508c447184d82f0854d81 100644 --- a/app/code/Magento/Tax/Block/Adminhtml/Rule/Edit/Form.php +++ b/app/code/Magento/Tax/Block/Adminhtml/Rule/Edit/Form.php @@ -164,6 +164,20 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic false, true ); + + $fieldset->addField( + 'calculate_subtotal', + 'checkbox', + array( + 'name' => 'calculate_subtotal', + 'label' => __('Calculate Off Subtotal Only'), + 'onclick' => 'this.value = this.checked ? 1 : 0;', + 'checked' => (int)$model->getCalculateSubtotal() + ), + false, + true + ); + $fieldset->addField( 'position', 'text', diff --git a/app/code/Magento/Tax/Block/Sales/Order/Tax.php b/app/code/Magento/Tax/Block/Sales/Order/Tax.php index 911ab864539e908ea9df56be200bad8e094d71b7..49c4d799852b3d884a4ce287af6bc0905e0f6e69 100644 --- a/app/code/Magento/Tax/Block/Sales/Order/Tax.php +++ b/app/code/Magento/Tax/Block/Sales/Order/Tax.php @@ -148,14 +148,24 @@ class Tax extends \Magento\Framework\View\Element\Template $subtotalIncl = (double)$this->_source->getSubtotalInclTax(); $baseSubtotalIncl = (double)$this->_source->getBaseSubtotalInclTax(); - if (!$subtotalIncl) { - $subtotalIncl = $subtotal + $this->_source->getTaxAmount() - $this->_source->getShippingTaxAmount(); - } - if (!$baseSubtotalIncl) { - $baseSubtotalIncl = $baseSubtotal + - $this->_source->getBaseTaxAmount() - - $this->_source->getBaseShippingTaxAmount(); + if (!$subtotalIncl || !$baseSubtotalIncl) { + // Calculate the subtotal if it is not set + $subtotalIncl = $subtotal + + $this->_source->getTaxAmount() + - $this->_source->getShippingTaxAmount(); + $baseSubtotalIncl = $baseSubtotal + + $this->_source->getBaseTaxAmount() + - $this->_source->getBaseShippingTaxAmount(); + + if ($this->_source instanceof Order) { + // Adjust for the discount tax compensation + foreach ($this->_source->getAllItems() as $item) { + $subtotalIncl += $item->getHiddenTaxAmount(); + $baseSubtotalIncl += $item->getBaseHiddenTaxAmount(); + } + } } + $subtotalIncl = max(0, $subtotalIncl); $baseSubtotalIncl = max(0, $baseSubtotalIncl); $totalExcl = new \Magento\Framework\Object( diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rule.php b/app/code/Magento/Tax/Controller/Adminhtml/Rule.php index 05f5d442f0c1dd17f4a8c475f64d02abce96f19c..9de72cd297dea671dc07c8b121d33542990c1b74 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rule.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rule.php @@ -51,6 +51,8 @@ class Rule extends \Magento\Backend\App\Action } /** + * Index action + * * @return $this */ public function indexAction() @@ -63,6 +65,8 @@ class Rule extends \Magento\Backend\App\Action } /** + * Redirects to edit action + * * @return void */ public function newAction() @@ -71,6 +75,8 @@ class Rule extends \Magento\Backend\App\Action } /** + * Edit action + * * @return void */ public function editAction() @@ -106,6 +112,8 @@ class Rule extends \Magento\Backend\App\Action } /** + * Save action + * * @return void */ public function saveAction() @@ -115,6 +123,7 @@ class Rule extends \Magento\Backend\App\Action $ruleModel = $this->_objectManager->get('Magento\Tax\Model\Calculation\Rule'); $ruleModel->setData($postData); + $ruleModel->setCalculateSubtotal($this->getRequest()->getParam('calculate_subtotal', 0)); try { $ruleModel->save(); @@ -142,6 +151,8 @@ class Rule extends \Magento\Backend\App\Action } /** + * Delete action + * * @return void */ public function deleteAction() @@ -191,6 +202,8 @@ class Rule extends \Magento\Backend\App\Action } /** + * Check if sales rule is allowed + * * @return bool */ protected function _isAllowed() diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Tax.php b/app/code/Magento/Tax/Controller/Adminhtml/Tax.php index 9d89ee15c1a27ac09992ef8d199fcb711026d5ed..4286cf94cec92b7c5501f912cf4cb2d3e89a436a 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Tax.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Tax.php @@ -155,4 +155,24 @@ class Tax extends \Magento\Backend\App\Action { return $this->_authorization->isAllowed('Magento_Tax::manage_tax'); } + + /** + * Set tax ignore notification flag and redirect back + * + * @return \Magento\Framework\App\ResponseInterface + */ + public function ignoreTaxNotificationAction() + { + $section = $this->getRequest()->getParam('section'); + if ($section) { + try { + $path = 'tax/notification/ignore_' . $section; + $this->_objectManager->get('\Magento\Core\Model\Resource\Config')->saveConfig($path, 1, \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, 0); + } catch (Exception $e) { + $this->messageManager->addError($e->getMessage()); + } + } + + $this->getResponse()->setRedirect($this->_redirect->getRefererUrl()); + } } diff --git a/app/code/Magento/Tax/Helper/Data.php b/app/code/Magento/Tax/Helper/Data.php index c3c4371f52800af9bb27e62fb89a8e06b220660e..60a3902074688bb99fca90c29a37f416b11347a6 100644 --- a/app/code/Magento/Tax/Helper/Data.php +++ b/app/code/Magento/Tax/Helper/Data.php @@ -25,6 +25,7 @@ namespace Magento\Tax\Helper; use Magento\Store\Model\Store; use Magento\Customer\Model\Address; +use Magento\Tax\Model\Calculation; use Magento\Tax\Model\Config; /** @@ -481,6 +482,42 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper return $this->_coreData->jsonEncode($result); } + /** + * Get unrounded product price + * + * @param \Magento\Catalog\Model\Product $product + * @param float $price inputed product price + * @param bool $includingTax return price include tax flag + * @param null|Address $shippingAddress + * @param null|Address $billingAddress + * @param null|int $ctc customer tax class + * @param null|string|bool|int|Store $store + * @param bool $priceIncludesTax flag what price parameter contain tax + * @return float + */ + public function getPriceUnrounded( + $product, + $price, + $includingTax = null, + $shippingAddress = null, + $billingAddress = null, + $ctc = null, + $store = null, + $priceIncludesTax = null + ) { + return $this->getPrice( + $product, + $price, + $includingTax, + $shippingAddress, + $billingAddress, + $ctc, + $store, + $priceIncludesTax, + false + ); + } + /** * Get product price with all tax settings processing * diff --git a/app/code/Magento/Tax/Model/Config.php b/app/code/Magento/Tax/Model/Config.php index 83aae6075cfec2ec15499e13b9b70d97460dad6a..cf0b53ae8f76d582696b3ab7997515fb02383523 100644 --- a/app/code/Magento/Tax/Model/Config.php +++ b/app/code/Magento/Tax/Model/Config.php @@ -33,6 +33,15 @@ use Magento\Store\Model\Store; class Config { + // tax notifications + const XML_PATH_TAX_NOTIFICATION_IGNORE_DISCOUNT = 'tax/notification/ignore_discount'; + + const XML_PATH_TAX_NOTIFICATION_IGNORE_PRICE_DISPLAY = 'tax/notification/ignore_price_display'; + + const XML_PATH_TAX_NOTIFICATION_IGNORE_FPT_CONFIGURATION = 'tax/notification/ignore_fpt_configuration'; + + const XML_PATH_TAX_NOTIFICATION_INFO_URL = 'tax/notification/info_url'; + // tax classes const CONFIG_XML_PATH_SHIPPING_TAX_CLASS = 'tax/classes/shipping_tax_class'; @@ -683,7 +692,7 @@ class Config * @param null|string|bool|int|Store $store * @return bool */ - public function displaySalestDiscountExclTax($store = null) + public function displaySalesDiscountExclTax($store = null) { return $this->_scopeConfig->getValue( self::XML_PATH_DISPLAY_SALES_DISCOUNT, @@ -758,4 +767,64 @@ class Config $store ); } + + /** + * Check if do not show notification about wrong display settings + * + * @param null|string|bool|int|Store $store + * @return bool + */ + public function isWrongDisplaySettingsIgnored($store = null) + { + return (bool)$this->_scopeConfig->getValue( + self::XML_PATH_TAX_NOTIFICATION_IGNORE_PRICE_DISPLAY, + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $store + ); + } + + /** + * Check if do not show notification about wrong discount settings + * + * @param null|string|bool|int|Store $store + * @return bool + */ + public function isWrongDiscountSettingsIgnored($store = null) + { + return (bool)$this->_scopeConfig->getValue( + self::XML_PATH_TAX_NOTIFICATION_IGNORE_DISCOUNT, + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $store + ); + } + + /** + * Check if warning about conflicting FPT configuration should be shown + * + * @param null|string|bool|int|Store $store + * @return bool + */ + public function isConflictingFptTaxConfigurationSettingsIgnored($store = null) + { + return (bool)$this->_scopeConfig->getValue( + self::XML_PATH_TAX_NOTIFICATION_IGNORE_FPT_CONFIGURATION, + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $store + ); + } + + /** + * Return the notification info url + * + * @param null|string|bool|int|Store $store + * @return bool + */ + public function getInfoUrl($store = null) + { + return (bool)$this->_scopeConfig->getValue( + self::XML_PATH_TAX_NOTIFICATION_INFO_URL, + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $store + ); + } } diff --git a/app/code/Magento/Tax/Model/Config/Notification.php b/app/code/Magento/Tax/Model/Config/Notification.php new file mode 100644 index 0000000000000000000000000000000000000000..0c4805c6ab32a7737b4c74f09200589d4dc2f617 --- /dev/null +++ b/app/code/Magento/Tax/Model/Config/Notification.php @@ -0,0 +1,83 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Tax\Model\Config; + +/** + * Tax Config Notification + */ +class Notification extends \Magento\Framework\App\Config\Value +{ + /** + * @var \Magento\Core\Model\Resource\Config + */ + protected $resourceConfig; + + /** + * @param \Magento\Framework\Model\Context $context + * @param \Magento\Framework\Registry $registry + * @param \Magento\Framework\App\Config\ScopeConfigInterface $config + * @param \Magento\Core\Model\Resource\Config $resourceConfig + * @param \Magento\Framework\Model\Resource\AbstractResource $resource + * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param array $data + */ + public function __construct( + \Magento\Framework\Model\Context $context, + \Magento\Framework\Registry $registry, + \Magento\Framework\App\Config\ScopeConfigInterface $config, + \Magento\Core\Model\Resource\Config $resourceConfig, + \Magento\Framework\Model\Resource\AbstractResource $resource = null, + \Magento\Framework\Data\Collection\Db $resourceCollection = null, + array $data = array() + ) { + $this->resourceConfig = $resourceConfig; + parent::__construct($context, $registry, $config, $resource, $resourceCollection, $data); + } + + /** + * Prepare and store cron settings after save + * + * @return \Magento\Tax\Model\Config\Notification + */ + protected function _afterSave() + { + if ($this->isValueChanged()) { + $this->_resetNotificationFlag(\Magento\Tax\Model\Config::XML_PATH_TAX_NOTIFICATION_IGNORE_DISCOUNT); + $this->_resetNotificationFlag(\Magento\Tax\Model\Config::XML_PATH_TAX_NOTIFICATION_IGNORE_PRICE_DISPLAY); + } + return parent::_afterSave($this); + } + + /** + * Reset flag for showing tax notifications + * + * @param string $path + * @return \Magento\Tax\Model\Config\Notification + */ + protected function _resetNotificationFlag($path) + { + $this->resourceConfig->saveConfig($path, 0, \Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT, 0); + return $this; + } +} diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php index fc1080efb468a322d559a0476636788f292ca1a4..87a6942814093a8e62fba64a7032ca21179269f8 100644 --- a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php +++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php @@ -933,7 +933,6 @@ class Tax extends AbstractTotal $rateKey = ($taxId == null) ? (string)$rate : $taxId; $taxSubtotal = $subtotal = $item->getTaxableAmount() + $item->getExtraRowTaxableAmount(); $baseTaxSubtotal = $baseSubtotal = $item->getBaseTaxableAmount() + $item->getBaseExtraRowTaxableAmount(); - $item->setTaxPercent($rate); if (!isset($taxGroups[$rateKey]['totals'])) { $taxGroups[$rateKey]['totals'] = array(); diff --git a/app/code/Magento/Tax/Model/System/Message/Notifications.php b/app/code/Magento/Tax/Model/System/Message/Notifications.php new file mode 100644 index 0000000000000000000000000000000000000000..4e0d52ef0630cdeff548a424b70eb66012c3f778 --- /dev/null +++ b/app/code/Magento/Tax/Model/System/Message/Notifications.php @@ -0,0 +1,337 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Tax\Model\System\Message; + +/** + * Notifications class + */ +class Notifications implements \Magento\AdminNotification\Model\System\MessageInterface +{ + /** + * Store manager object + * + * @var \Magento\Store\Model\StoreManagerInterface + */ + protected $storeManager; + + /** + * @var \Magento\Framework\UrlInterface + */ + protected $urlBuilder; + + /** + * Tax configuration object + * + * @var \Magento\Tax\Model\Config + */ + protected $taxConfig; + + /* + * Stores with invalid display settings + * + * @var array + */ + protected $storesWithInvalidDisplaySettings; + + /* + * Websites with invalid discount settings + * + * @var array + */ + protected $storesWithInvalidDiscountSettings; + + /* + * Stores with conflicting FPT settings + * + * @var array + */ + protected $storesWithConflictingFPTSettings; + + /** + * @param \Magento\Store\Model\StoreManagerInterface $storeManager + * @param \Magento\Framework\UrlInterface $urlBuilder + * @param \Magento\Tax\Model\Config $taxConfig + */ + public function __construct( + \Magento\Store\Model\StoreManagerInterface $storeManager, + \Magento\Framework\UrlInterface $urlBuilder, + \Magento\Tax\Model\Config $taxConfig + ) { + $this->storeManager = $storeManager; + $this->urlBuilder = $urlBuilder; + $this->taxConfig = $taxConfig; + } + + /** + * Retrieve unique message identity + * + * @return string + */ + public function getIdentity() + { + return md5('TAX_NOTIFICATION'); + } + + /** + * Check if tax calculation type and price display settings are compatible + * + * Invalid settings if + * Tax Calculation Method Based On 'Total' or 'Row' + * and at least one Price Display Settings has 'Including and Excluding Tax' value + * + * @param null|int|bool|string|Store $store $store + * @return bool + */ + public function checkDisplaySettings($store = null) + { + if ($this->taxConfig->getAlgorithm($store) == \Magento\Tax\Model\Calculation::CALC_UNIT_BASE) { + return true; + } + return $this->taxConfig->getPriceDisplayType($store) != \Magento\Tax\Model\Config::DISPLAY_TYPE_BOTH + && $this->taxConfig->getShippingPriceDisplayType($store) != \Magento\Tax\Model\Config::DISPLAY_TYPE_BOTH + && !$this->taxConfig->displayCartPricesBoth($store) + && !$this->taxConfig->displayCartSubtotalBoth($store) + && !$this->taxConfig->displayCartShippingBoth($store) + && !$this->taxConfig->displaySalesPricesBoth($store) + && !$this->taxConfig->displaySalesSubtotalBoth($store) + && !$this->taxConfig->displaySalesShippingBoth($store); + } + + /** + * Check if tax discount settings are compatible + * + * Matrix for invalid discount settings is as follows: + * Before Discount / Excluding Tax + * Before Discount / Including Tax + * + * @param null|int|bool|string|Store $store $store + * @return bool + */ + public function checkDiscountSettings($store = null) + { + return $this->taxConfig->applyTaxAfterDiscount($store); + } + + /** + * Get URL for the tax notification documentation + * + * @return string + */ + public function getInfoUrl() + { + return $this->taxConfig->getInfoUrl(); + } + + /** + * Get URL to the admin tax configuration page + * + * @return string + */ + public function getManageUrl() + { + return $this->urlBuilder->getUrl('adminhtml/system_config/edit/section/tax'); + } + + /** + * Get URL to ignore tax notifications + * + * @param string $section + * @return string + */ + public function getIgnoreTaxNotificationUrl($section) + { + return $this->urlBuilder->getUrl('tax/tax/ignoreTaxNotification', array('section' => $section)); + } + + /** + * Return list of store names which have not compatible tax calculation type and price display settings. + * Return true if settings are wrong for default store. + * + * @return array + */ + public function getStoresWithWrongDisplaySettings() + { + $storeNames = array(); + $storeCollection = $this->storeManager->getStores(true); + foreach ($storeCollection as $store) { + if (!$this->checkDisplaySettings($store)) { + $website = $store->getWebsite(); + $storeNames[] = $website->getName() . '(' . $store->getName() . ')'; + } + } + return $storeNames; + } + + /** + * Return list of store names where tax discount settings are compatible. + * Return true if settings are wrong for default store. + * + * @return array + */ + public function getStoresWithWrongDiscountSettings() + { + $storeNames = array(); + $storeCollection = $this->storeManager->getStores(true); + foreach ($storeCollection as $store) { + if (!$this->checkDiscountSettings($store)) { + $website = $store->getWebsite(); + $storeNames[] = $website->getName() . '(' . $store->getName() . ')'; + } + } + return $storeNames; + } + + /** + * Return list of store names which have not compatible tax calculation type and price display settings. + * Return true if settings are wrong for default store. + * + * @return array + */ + public function getStoresWithConflictingFptTaxConfigurationSettings() + { + $storeNames = array(); + + // Will enable in future work + //$storeCollection = $this->storeManager->getStores(true); + //foreach ($storeCollection as $store) { + // if ($this->weeeData->validateCatalogPricesAndFptConfiguration($store)) { + // $website = $store->getWebsite(); + // $storeNames[] = $website->getName() . '(' . $store->getName() . ')'; + // } + //} + + return $storeNames; + } + + /** + * Check whether notification is displayed + * Checks if any of these settings are being ignored or valid: + * 1. Wrong discount settings + * 2. Wrong display settings + * 3. Conflicting FPT settings + * + * @return bool + */ + public function isDisplayed() + { + // Check if we are ignoring all notifications + if ($this->taxConfig->isWrongDisplaySettingsIgnored() && $this->taxConfig->isWrongDiscountSettingsIgnored() + && $this->taxConfig->isConflictingFptTaxConfigurationSettingsIgnored()) { + return false; + } + + $this->storesWithInvalidDisplaySettings = $this->getStoresWithWrongDisplaySettings(); + $this->storesWithInvalidDiscountSettings = $this->getStoresWithWrongDiscountSettings(); + $this->storesWithConflictingFPTSettings = $this->getStoresWithConflictingFptTaxConfigurationSettings(); + + // Check if we have valid tax notifications + if ((!empty($this->storesWithInvalidDisplaySettings) && !$this->taxConfig->isWrongDisplaySettingsIgnored()) + || (!empty($this->storesWithInvalidDiscountSettings) && !$this->taxConfig->isWrongDiscountSettingsIgnored()) + || (!empty($this->storesWithConflictingFPTSettings) + && !$this->taxConfig->isConflictingFptTaxConfigurationSettingsIgnored())) { + return true; + } + + return false; + } + + /** + * Build message text + * Determine which notification and data to display + * + * @return string + */ + public function getText() + { + $messageDetails = ''; + + if (!empty($this->storesWithInvalidDisplaySettings) && !$this->taxConfig->isWrongDisplaySettingsIgnored()) { + $messageDetails .= '<strong>'; + $messageDetails .= __('Warning tax configuration can result in rounding errors. '); + $messageDetails .= '</strong><br>'; + $messageDetails .= __('Store(s) affected: '); + $messageDetails .= implode(', ', $this->storesWithInvalidDisplaySettings); + $messageDetails .= '<br><div style="text-align:right">'; + $messageDetails .= __( + 'Click on the link to <a href="%1">ignore this notification</a>', + $this->getIgnoreTaxNotificationUrl('price_display') + ); + $messageDetails .= "</div><br>"; + } + + if (!empty($this->storesWithInvalidDiscountSettings) && !$this->taxConfig->isWrongDiscountSettingsIgnored()) { + $messageDetails .= '<strong>'; + $messageDetails .= __( + 'Warning tax discount configuration might result in different discounts + than a customer might expect. ' + ); + $messageDetails .= '</strong><br>'; + $messageDetails .= __('Store(s) affected: '); + $messageDetails .= implode(', ', $this->storesWithInvalidDiscountSettings); + $messageDetails .= '<br><div style="text-align:right">'; + $messageDetails .= __( + 'Click on the link to <a href="%1">ignore this notification</a>', + $this->getIgnoreTaxNotificationUrl('discount') + ); + $messageDetails .= "</div><br>"; + } + + if (!empty($this->storesWithConflictingFPTSettings) + && !$this->taxConfig->isConflictingFptTaxConfigurationSettingsIgnored() + ) { + $messageDetails .= '<strong>'; + $messageDetails .= __( + 'Warning tax configuration can result in unexpected FPT prices on applicable devices. ' + ); + $messageDetails .= '</strong><br>'; + $messageDetails .= __('Store(s) affected: '); + $messageDetails .= implode(', ', $this->storesWithConflictingFPTSettings); + $messageDetails .= '<br><div style="text-align:right">'; + $messageDetails .= __( + 'Click on the link to <a href="%1">ignore this notification</a>', + $this->getIgnoreTaxNotificationUrl('fpt_configuration') + ); + $messageDetails .= "</div><br>"; + } + + $messageDetails .= '<br>'; + $messageDetails .= __('Please see <a href="%1">documentation</a> for more details. ', $this->getInfoUrl()); + $messageDetails .= __( + 'Click here to go to <a href="%1">Tax Configuration</a> and change your settings.', + $this->getManageUrl() + ); + + return $messageDetails; + } + + /** + * Retrieve message severity + * + * @return int + */ + public function getSeverity() + { + return self::SEVERITY_CRITICAL; + } +} diff --git a/app/code/Magento/Tax/Pricing/Adjustment.php b/app/code/Magento/Tax/Pricing/Adjustment.php index daa43ca113ed050a5a52b70f73df953880240482..edd8467edf5e0a91267b1721929be69735d04c17 100644 --- a/app/code/Magento/Tax/Pricing/Adjustment.php +++ b/app/code/Magento/Tax/Pricing/Adjustment.php @@ -98,7 +98,7 @@ class Adjustment implements AdjustmentInterface public function extractAdjustment($amount, SaleableInterface $saleableItem) { if ($this->taxHelper->priceIncludesTax()) { - $adjustedAmount = $this->taxHelper->getPrice($saleableItem, $amount); + $adjustedAmount = $this->taxHelper->getPriceUnrounded($saleableItem, $amount); $result = $amount - $adjustedAmount; } else { $result = 0.; @@ -116,7 +116,7 @@ class Adjustment implements AdjustmentInterface public function applyAdjustment($amount, SaleableInterface $saleableItem) { $includingTax = !$this->taxHelper->priceIncludesTax(); - return $this->taxHelper->getPrice($saleableItem, $amount, $includingTax); + return $this->taxHelper->getPriceUnrounded($saleableItem, $amount, $includingTax); } /** diff --git a/app/code/Magento/Tax/etc/adminhtml/di.xml b/app/code/Magento/Tax/etc/adminhtml/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..16e2bb8fa3cff244161ad90987a93dd1711aa5aa --- /dev/null +++ b/app/code/Magento/Tax/etc/adminhtml/di.xml @@ -0,0 +1,34 @@ +<?xml version="1.0"?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"> + <type name="Magento\AdminNotification\Model\System\MessageList"> + <arguments> + <argument name="messages" xsi:type="array"> + <item name="tax" xsi:type="string">Magento\Tax\Model\System\Message\Notifications</item> + </argument> + </arguments> + </type> +</config> \ No newline at end of file diff --git a/app/code/Magento/Tax/etc/adminhtml/system.xml b/app/code/Magento/Tax/etc/adminhtml/system.xml index 9c1ec0e5e212de8204e4926ab043ab9d6507c318..0e240d0de7bc7b5f838012e6a4196b8f87223d0e 100644 --- a/app/code/Magento/Tax/etc/adminhtml/system.xml +++ b/app/code/Magento/Tax/etc/adminhtml/system.xml @@ -54,6 +54,7 @@ <field id="based_on" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Tax Calculation Based On</label> <source_model>Magento\Tax\Model\Config\Source\Basedon</source_model> + <backend_model>Magento\Tax\Model\Config\Notification</backend_model> </field> <field id="price_includes_tax" translate="label comment" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Catalog Prices</label> @@ -70,16 +71,23 @@ <field id="apply_after_discount" translate="label comment" type="select" sortOrder="40" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Apply Customer Tax</label> <source_model>Magento\Tax\Model\System\Config\Source\Apply</source_model> + <backend_model>Magento\Tax\Model\Config\Notification</backend_model> </field> <field id="discount_tax" translate="label comment" type="select" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Apply Discount On Prices</label> <source_model>Magento\Tax\Model\System\Config\Source\PriceType</source_model> + <backend_model>Magento\Tax\Model\Config\Notification</backend_model> <comment>Apply discount on price including tax is calculated based on store tax, if "Apply Tax after Discount" is selected.</comment> </field> <field id="apply_tax_on" translate="label comment" type="select" sortOrder="60" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Apply Tax On</label> <source_model>Magento\Tax\Model\Config\Source\Apply\On</source_model> </field> + <field id="cross_border_trade_enabled" translate="label comment" type="select" sortOrder="70" showInDefault="1" showInWebsite="1" showInStore="0"> + <label>Enable Cross Border Trade</label> + <source_model>Magento\Backend\Model\Config\Source\Yesno</source_model> + <comment>When catalog price includes tax, enable this setting will fix the price no matter what the customer's tax rate is.</comment> + </field> </group> <group id="defaults" translate="label" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Default Tax Destination Calculation</label> @@ -101,10 +109,12 @@ <field id="type" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Display Product Prices In Catalog</label> <source_model>Magento\Tax\Model\System\Config\Source\Tax\Display\Type</source_model> + <backend_model>Magento\Tax\Model\Config\Notification</backend_model> </field> <field id="shipping" translate="label" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Display Shipping Prices</label> <source_model>Magento\Tax\Model\System\Config\Source\Tax\Display\Type</source_model> + <backend_model>Magento\Tax\Model\Config\Notification</backend_model> </field> </group> <group id="cart_display" translate="label" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1"> @@ -112,14 +122,17 @@ <field id="price" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Display Prices</label> <source_model>Magento\Tax\Model\System\Config\Source\Tax\Display\Type</source_model> + <backend_model>Magento\Tax\Model\Config\Notification</backend_model> </field> <field id="subtotal" translate="label" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Display Subtotal</label> <source_model>Magento\Tax\Model\System\Config\Source\Tax\Display\Type</source_model> + <backend_model>Magento\Tax\Model\Config\Notification</backend_model> </field> <field id="shipping" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Display Shipping Amount</label> <source_model>Magento\Tax\Model\System\Config\Source\Tax\Display\Type</source_model> + <backend_model>Magento\Tax\Model\Config\Notification</backend_model> </field> <field id="grandtotal" translate="label" type="select" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Include Tax In Grand Total</label> @@ -139,14 +152,17 @@ <field id="price" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Display Prices</label> <source_model>Magento\Tax\Model\System\Config\Source\Tax\Display\Type</source_model> + <backend_model>Magento\Tax\Model\Config\Notification</backend_model> </field> <field id="subtotal" translate="label" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Display Subtotal</label> <source_model>Magento\Tax\Model\System\Config\Source\Tax\Display\Type</source_model> + <backend_model>Magento\Tax\Model\Config\Notification</backend_model> </field> <field id="shipping" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Display Shipping Amount</label> <source_model>Magento\Tax\Model\System\Config\Source\Tax\Display\Type</source_model> + <backend_model>Magento\Tax\Model\Config\Notification</backend_model> </field> <field id="grandtotal" translate="label" type="select" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Include Tax In Grand Total</label> diff --git a/app/code/Magento/Tax/etc/config.xml b/app/code/Magento/Tax/etc/config.xml index 9df3ec19f8dd80310d351616fea39299aa53f97a..9d4ef0238027de34643fe8e691e2eaeea79e263e 100644 --- a/app/code/Magento/Tax/etc/config.xml +++ b/app/code/Magento/Tax/etc/config.xml @@ -31,7 +31,7 @@ </classes> <calculation> <algorithm>TOTAL_BASE_CALCULATION</algorithm> - <apply_after_discount>0</apply_after_discount> + <apply_after_discount>1</apply_after_discount> <discount_tax>0</discount_tax> <based_on>shipping</based_on> <price_includes_tax>0</price_includes_tax> @@ -66,6 +66,9 @@ <full_summary>0</full_summary> <zero_tax>0</zero_tax> </sales_display> + <notification> + <url>http://www.magentocommerce.com/knowledge-base/entry/magento-ce-18-ee-113-tax-calc</url> + </notification> </tax> </default> </config> diff --git a/app/code/Magento/Tax/etc/module.xml b/app/code/Magento/Tax/etc/module.xml index 39c8385237c06b43917c1f0d6099460299f72b52..4a737678df7c304d7eb91b968c1d8107d5eced72 100644 --- a/app/code/Magento/Tax/etc/module.xml +++ b/app/code/Magento/Tax/etc/module.xml @@ -44,6 +44,7 @@ <module name="Magento_Reports"/> <module name="Magento_Theme"/> <module name="Magento_ConfigurableProduct"/> + <module name="Magento_AdminNotification"/> </depends> </module> </config> diff --git a/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_block.xml b/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_block.xml index c64f797803d1ae57802e66f8de09d98001f24dc0..56f0be480113ae2bf17172ab91fc6b79f8db2078 100644 --- a/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_block.xml +++ b/app/code/Magento/Tax/view/adminhtml/layout/tax_rule_block.xml @@ -94,6 +94,13 @@ <argument name="type" xsi:type="string">text</argument> </arguments> </block> + <block class="Magento\Backend\Block\Widget\Grid\Column" as="calculate_subtotal"> + <arguments> + <argument name="header" xsi:type="string" translate="true">Subtotal Only</argument> + <argument name="index" xsi:type="string">calculate_subtotal</argument> + <argument name="type" xsi:type="string">text</argument> + </arguments> + </block> <block class="Magento\Backend\Block\Widget\Grid\Column" as="position"> <arguments> <argument name="header" xsi:type="string" translate="true">Sort Order</argument> diff --git a/app/code/Magento/Weee/Model/Tax.php b/app/code/Magento/Weee/Model/Tax.php index f9c8fa904b5fc603e8af21e5f653b4824b4ae4ba..c826dbe93b0a02640c5233915603763347e15750 100644 --- a/app/code/Magento/Weee/Model/Tax.php +++ b/app/code/Magento/Weee/Model/Tax.php @@ -242,7 +242,7 @@ class Tax extends \Magento\Framework\Model\AbstractModel } $rateRequest = $calculator->getRateRequest($shipping, $billing, $customerTaxClass, $store); - $defaultRateRequest = $calculator->getRateRequest(false, false, false, $store); + $defaultRateRequest = $calculator->getDefaultRateRequest($store); $discountPercent = 0; if (!$ignoreDiscount && $this->_weeeData->isDiscounted($store)) { diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module.less index 09c58867ae82873e61385606b3853b85c149ff20..1c58ab846ef30d7806f35a6b2f57c7e96301339a 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module.less @@ -90,6 +90,7 @@ text-align: left; position: relative; z-index: 1; + margin: 0 10px; &.active { z-index: 999; } @@ -122,6 +123,7 @@ .qty.counter { display: inline-block; background: #ed4f2e; + color: @primary7; font-size: 12px; line-height: 12px; font-weight: bold; diff --git a/app/design/adminhtml/Magento/backend/web/css/admin.less b/app/design/adminhtml/Magento/backend/web/css/admin.less index bd89088c42bd7e063b576938aca9fbc45930c22a..6333aaf2fa21753d8fd81d49fe27a973ae86c56e 100644 --- a/app/design/adminhtml/Magento/backend/web/css/admin.less +++ b/app/design/adminhtml/Magento/backend/web/css/admin.less @@ -3677,10 +3677,11 @@ tr.dynamic-grid input.input-text { float: none; } -.fpt-item-container select { - width: 100%; - - &:first-child { +.data-table .fpt-item-container { + td { + vertical-align: top; + } + select:first-child { margin-bottom: 8px; } } @@ -3688,6 +3689,7 @@ tr.dynamic-grid input.input-text { .eq-ie9 { .col-1-layout, .catalog-product-edit, + .catalog-product-new, .sales-order-view, .catalog-category-edit { table.data { diff --git a/app/design/adminhtml/Magento/backend/web/css/source/table.less b/app/design/adminhtml/Magento/backend/web/css/source/table.less index 2b95c3b3630b756dc103a392e6c4d692111412c6..447c0997800770b1d2a8963e815b45f111a5a70e 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/table.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/table.less @@ -337,7 +337,8 @@ table { &.col-time, &.col-billing_name, &.col-shipping_name, - &.col-phone { + &.col-phone, + &.col-type { &:extend(.ellipsis all); } } @@ -416,6 +417,11 @@ table { &:extend(.col-40 all); } + .col-select, + .col-massaction { + text-align: center; + } + .editable .input-text { width: 65px; } @@ -460,7 +466,8 @@ td.col-updated_at, td.col-customer_since, td.col-session_start_time, td.col-time, -td.col-sku { +td.col-sku, +td.col-type { &:extend(.nowrap all); } @@ -1105,6 +1112,9 @@ td.col-sku { .rma-request-details { &:extend(.data-table-td-max all); } + #rma_items_grid_table .headings th { + &:extend(.nowrap all); + } } .adminhtml-rma-edit { @@ -1138,6 +1148,10 @@ td.col-sku { } } +.catalog-product-index .grid .hor-scroll { + &:extend(.h-scroll); +} + .catalog-product-review-index { .grid { .col-name, @@ -1561,7 +1575,7 @@ td.col-sku { .adminhtml-cache-index, .adminhtml-process-list, .indexer-indexer-list { - .col-select { + .grid .col-select { width: 10px; } } diff --git a/app/design/adminhtml/Magento/backend/web/js/theme.js b/app/design/adminhtml/Magento/backend/web/js/theme.js index e2992b036202500d3a6562a90cc0f70a62e96b23..01d7ba7252d805787734bc34789e55c41172d13d 100644 --- a/app/design/adminhtml/Magento/backend/web/js/theme.js +++ b/app/design/adminhtml/Magento/backend/web/js/theme.js @@ -142,16 +142,22 @@ }, _leaveEffects: function (e) { - var targetSubmenu = $(e.target).closest('.submenu'); + var targetSubmenu = $(e.target).closest('.submenu'), + self = $(this), + submenu = $('> .submenu', this); + if(targetSubmenu.length && targetSubmenu.is(':hidden')) { return; } - var self = $(this); - $('> .submenu', this) - .slideUp('fast', function() { + if(submenu.length) { + submenu.slideUp('fast', function() { self.removeClass('hover'); }); + } else { + self.removeClass('hover'); + } + } }); diff --git a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/MultiselectlistElement.php b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/MultiselectlistElement.php index 0b2526fa6f667bfb0e3e6aa327faeb08e268fd1e..8f58e9e552973a0f248686406bebdab0bdea1f8d 100644 --- a/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/MultiselectlistElement.php +++ b/dev/tests/functional/lib/Mtf/Client/Driver/Selenium/Element/MultiselectlistElement.php @@ -123,4 +123,22 @@ class MultiselectlistElement extends MultiselectElement return $options; } + + /** + * Method that returns array with all options in multiple select list + * + * @return array + */ + public function getAllValues() + { + $optionsValue = []; + $options = $this->getOptions(); + + foreach ($options as $option) { + /** @var Element $option */ + $optionsValue[] = $option->getText(); + } + + return $optionsValue; + } } diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/FormPageActions.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/FormPageActions.php index 636a537ea7476c03bfcc15298f4bd5f77e1fa3ca..a17327a5c59d18e0c4de538248f64b40aac512b5 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/FormPageActions.php +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/FormPageActions.php @@ -29,7 +29,6 @@ use Mtf\Client\Element\Locator; /** * Class FormPageActions * Form page actions block - * */ class FormPageActions extends PageActions { diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Price.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Price.php index 9360e0d761f52514720b8415d656aa3133f0cdb2..721a1ddb748ff368df831147123767fe03cc024d 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Price.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Price.php @@ -24,7 +24,6 @@ namespace Magento\Catalog\Test\Block\Product; use Mtf\Block\Block; -use Mtf\Factory\Factory; use Mtf\Client\Element\Locator; /** @@ -171,7 +170,9 @@ class Price extends Block $priceElement = $this->_rootElement->find($this->regularPriceClass, Locator::SELECTOR_CSS); } // return the actual value of the price - return $priceElement->find($this->priceClass, Locator::SELECTOR_CSS)->getText(); + $element = $priceElement->find($this->priceClass, Locator::SELECTOR_CSS); + $price = preg_replace('#[^\d\.\s]+#umis', '', $element->getText()); + return number_format(trim($price), 2); } /** @@ -181,13 +182,10 @@ class Price extends Block */ public function getSpecialPrice() { - return $this->_rootElement->find( - $this->specialPriceClass, - Locator::SELECTOR_CSS - )->find( - $this->priceClass, - Locator::SELECTOR_CSS - )->getText(); + $element = $this->_rootElement->find($this->specialPriceClass, Locator::SELECTOR_CSS) + ->find($this->priceClass, Locator::SELECTOR_CSS); + $price = preg_replace('#[^\d\.\s]+#umis', '', $element->getText()); + return number_format(trim($price), 2); } /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCart.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCart.php index e72639796d61a7cff6513069a27b51d67c355689..83987d7abd5524e702d421c7268a945bab99f450 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCart.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCart.php @@ -114,7 +114,7 @@ class AssertProductInCart extends AbstractConstraint $price = $checkoutCart->getCartBlock()->getProductPriceByName($productName); \PHPUnit_Framework_Assert::assertEquals( - '$' . number_format($priceComparing, 2), + number_format($priceComparing, 2), $price, 'Product price in shopping cart is not correct.' ); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCategory.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCategory.php index 58c7fd8faed3742a2ade30d6f42ceb5209acc86d..164eafe6024a2d1312495248c763cdf63427d8e2 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCategory.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductInCategory.php @@ -87,9 +87,8 @@ class AssertProductInCategory extends AbstractConstraint $price = $catalogCategoryView->getListProductBlock()->getProductPriceBlock($product->getName()) ->getRegularPrice(); - $priceComparing = '$' . number_format($product->getPrice(), 2); \PHPUnit_Framework_Assert::assertEquals( - $priceComparing, + number_format($product->getPrice(), 2), $price, 'Product regular price on category page is not correct.' ); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/Price.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/Price.php index a8726289546e6d7b7c0086674baeb2f699d26c7b..19d881b7ad2be459c7561707865cf077a8f39b48 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/Price.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple/Price.php @@ -107,35 +107,35 @@ class Price implements FixtureInterface { $presets = [ 'MAGETWO-23062' => [ - 'category_price' => '$100.00', - 'product_price' => '$100.00', - 'cart_price' => '$130.00' + 'category_price' => '100.00', + 'product_price' => '100.00', + 'cart_price' => '130.00' ], 'MAGETWO-23063' => [ - 'category_price' => '$100.00', - 'product_price' => '$100.00', - 'cart_price' => '$140.00' + 'category_price' => '100.00', + 'product_price' => '100.00', + 'cart_price' => '140.00' ], 'MAGETWO-23029' => [ - 'category_price' => '$100.00', - 'category_special_price' => '$90.00', - 'product_price' => '$100.00', - 'product_special_price' => '$90.00', - 'cart_price' => '$120.00' + 'category_price' => '100.00', + 'category_special_price' => '90.00', + 'product_price' => '100.00', + 'product_special_price' => '90.00', + 'cart_price' => '120.00' ], 'MAGETWO-23030' => [ - 'category_price' => '$100.00', - 'category_special_price' => '$90.00', - 'product_price' => '$100.00', - 'product_special_price' => '$90.00', - 'cart_price' => '$126.00' + 'category_price' => '100.00', + 'category_special_price' => '90.00', + 'product_price' => '100.00', + 'product_special_price' => '90.00', + 'cart_price' => '126.00' ], 'MAGETWO-23036' => [ - 'category_price' => '$100.00', - 'category_special_price' => '$90.00', - 'product_price' => '$100.00', - 'product_special_price' => '$90.00', - 'cart_price' => '$90.00' + 'category_price' => '100.00', + 'category_special_price' => '90.00', + 'product_price' => '100.00', + 'product_special_price' => '90.00', + 'cart_price' => '90.00' ] ]; if (!isset($presets[$this->currentPreset])) { diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php index 8b5a513031685e80f942eee96881e1783a52f073..79e02713099f50fbab0b77d011f4b7f9b9ac581c 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart.php @@ -73,6 +73,27 @@ class Cart extends Block */ protected $cartProductPrice = '//tr[string(td/div/strong/a)="%s"]/td[@class="col price excl tax"]/span/span'; + /** + * 'Update Shopping Cart' button + * + * @var string + */ + protected $updateShoppingCart = '[name="update_cart_action"]'; + + /** + * Quantity input selector + * + * @var string + */ + protected $productQty = '//input[@type="number" and @title="Qty"]'; + + /** + * Cart item selector + * + * @var string + */ + protected $cartItem = '//tr[normalize-space(td)="%s"]'; + /** * Get sub-total for the specified item in the cart * @@ -81,9 +102,7 @@ class Cart extends Block */ public function getCartItemSubTotal($product) { - $selector = '//tr[normalize-space(td)="' . $this->getProductName( - $product - ) . '"]' . $this->itemSubTotalSelector; + $selector = sprintf($this->cartItem, $this->getProductName($product)) . $this->itemSubTotalSelector; return $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)->getText(); } @@ -95,8 +114,9 @@ class Cart extends Block */ public function getCartItemSubTotalByProductName($productName) { - $selector = '//tr[normalize-space(td)="' . $productName . '"]' . $this->itemSubTotalSelector; - return $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)->getText(); + $selector = sprintf($this->cartItem, $productName) . $this->itemSubTotalSelector; + $itemSubtotal = $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)->getText(); + return $this->escapeCurrency($itemSubtotal); } /** @@ -108,15 +128,9 @@ class Cart extends Block */ public function getCartItemUnitPrice($product, $currency = '$') { - $selector = '//tr[normalize-space(td)="' . $this->getProductName( - $product - ) . '"]' . $this->itemUnitPriceSelector; - + $selector = sprintf($this->cartItem, $this->getProductName($product)) . $this->itemUnitPriceSelector; $prices = explode("\n", trim($this->_rootElement->find($selector, Locator::SELECTOR_XPATH)->getText())); - if (count($prices) == 1) { - return floatval(trim($prices[0], $currency)); - } - return $this->formatPricesData($prices, $currency); + return floatval(trim($prices[0], $currency)); } /** @@ -236,7 +250,7 @@ class Cart extends Block public function isProductInShoppingCart($product) { return $this->_rootElement->find( - '//tr[normalize-space(td)="' . $this->getProductName($product) . '"]', + sprintf($this->cartItem, $this->getProductName($product)), Locator::SELECTOR_XPATH )->isVisible(); } @@ -268,6 +282,54 @@ class Cart extends Block public function getProductPriceByName($productName) { $priceSelector = sprintf($this->cartProductPrice, $productName); - return $this->_rootElement->find($priceSelector, Locator::SELECTOR_XPATH)->getText(); + $cartProductPrice = $this->_rootElement->find($priceSelector, Locator::SELECTOR_XPATH)->getText(); + return $this->escapeCurrency($cartProductPrice); + } + + /** + * Update shopping cart + * + * @return void + */ + public function updateShoppingCart() + { + $this->_rootElement->find($this->updateShoppingCart, Locator::SELECTOR_CSS)->click(); + } + + /** + * Set product quantity + * + * @param string $productName + * @param int $qty + * @return void + */ + public function setProductQty($productName, $qty) + { + $productQtySelector = sprintf($this->cartItem, $productName) . $this->productQty; + $this->_rootElement->find($productQtySelector, Locator::SELECTOR_XPATH)->setValue($qty); + } + + /** + * Get product quantity + * + * @param string $productName + * @return string + */ + public function getProductQty($productName) + { + $productQtySelector = sprintf($this->cartItem, $productName) . $this->productQty; + return $this->_rootElement->find($productQtySelector, Locator::SELECTOR_XPATH)->getValue(); + } + + /** + * Method that escapes currency symbols + * + * @param string $price + * @return string + */ + protected function escapeCurrency($price) + { + preg_match("/^\\D*\\s*([\\d,\\.]+)\\s*\\D*$/", $price, $matches); + return (isset($matches[1])) ? $matches[1] : null; } } diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar.php new file mode 100644 index 0000000000000000000000000000000000000000..c557d720fd3fda0ed93fb01f8ed96bb7955ad3c3 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Cart/Sidebar.php @@ -0,0 +1,80 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Checkout\Test\Block\Cart; + +use Mtf\Block\Block; +use Mtf\Client\Element\Locator; + +/** + * Class Sidebar + * Mini shopping cart block + */ +class Sidebar extends Block +{ + /** + * Quantity input selector + * + * @var string + */ + protected $qty = '//*[@class="product"]/*[@title="%s"]/following-sibling::*//*[@class="value qty"]'; + + /** + * Mini cart link selector + * + * @var string + */ + protected $cartLink = 'a.showcart'; + + /** + * Mini cart content selector + * + * @var string + */ + protected $cartContent = 'div.minicart'; + + /** + * Open mini cart + * + * @return void + */ + public function openMiniCart() + { + if (!$this->_rootElement->find($this->cartContent)->isVisible()) { + $this->_rootElement->find($this->cartLink)->click(); + } + } + + /** + * Get product quantity + * + * @param string $productName + * @return string + */ + public function getProductQty($productName) + { + $this->openMiniCart(); + $productQty = sprintf($this->qty, $productName); + return $this->_rootElement->find($productQty, Locator::SELECTOR_XPATH)->getText(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertPriceInShoppingCart.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertPriceInShoppingCart.php new file mode 100644 index 0000000000000000000000000000000000000000..96949593e8a2f6e800368ee43601409b3e55859d --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertPriceInShoppingCart.php @@ -0,0 +1,75 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Checkout\Test\Constraint; + +use Mtf\Constraint\AbstractConstraint; +use Magento\Checkout\Test\Page\CheckoutCart; +use Magento\Checkout\Test\Fixture\Cart; +use Magento\Catalog\Test\Fixture\CatalogProductSimple; + +/** + * Class AssertPriceInShoppingCart + */ +class AssertPriceInShoppingCart extends AbstractConstraint +{ + /** + * Constraint severeness + * + * @var string + */ + protected $severeness = 'low'; + + /** + * Assert that price in the shopping cart equals to expected price from data set + * + * @param CheckoutCart $checkoutCart + * @param Cart $cart + * @param CatalogProductSimple $product + * @return void + */ + public function processAssert( + CheckoutCart $checkoutCart, + Cart $cart, + CatalogProductSimple $product + ) { + $cartProductPrice = $checkoutCart->open()->getCartBlock()->getProductPriceByName($product->getName()); + \PHPUnit_Framework_Assert::assertEquals( + $cartProductPrice, + $cart->getPrice(), + 'Shopping cart product price: \'' . $cartProductPrice + . '\' not equals with price from data set: \'' . $cart->getPrice() . '\'' + ); + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return 'Price in the shopping cart equals to expected price from data set.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertProductQtyInMiniShoppingCart.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertProductQtyInMiniShoppingCart.php new file mode 100644 index 0000000000000000000000000000000000000000..d13ad0604139484784229f11dd5ef67dbc71912d --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertProductQtyInMiniShoppingCart.php @@ -0,0 +1,75 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Checkout\Test\Constraint; + +use Mtf\Constraint\AbstractConstraint; +use Magento\Cms\Test\Page\CmsIndex; +use Magento\Checkout\Test\Fixture\Cart; +use Magento\Catalog\Test\Fixture\CatalogProductSimple; + +/** + * Class AssertProductQtyInMiniShoppingCart + */ +class AssertProductQtyInMiniShoppingCart extends AbstractConstraint +{ + /** + * Constraint severeness + * + * @var string + */ + protected $severeness = 'low'; + + /** + * Assert that product quantity in the mini shopping cart is equals to expected quantity from data set + * + * @param CmsIndex $cmsIndex + * @param Cart $cart + * @param CatalogProductSimple $product + * @return void + */ + public function processAssert( + CmsIndex $cmsIndex, + Cart $cart, + CatalogProductSimple $product + ) { + $productQtyInMiniCart = $cmsIndex->open()->getCartSidebarBlock()->getProductQty($product->getName()); + \PHPUnit_Framework_Assert::assertEquals( + $productQtyInMiniCart, + $cart->getQty(), + 'Mini shopping cart product qty: \'' . $productQtyInMiniCart + . '\' not equals with qty from data set: \'' . $cart->getQty() . '\'' + ); + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return 'Quantity in the mini shopping cart equals to expected quantity from data set.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertProductQtyInShoppingCart.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertProductQtyInShoppingCart.php new file mode 100644 index 0000000000000000000000000000000000000000..fa27cfce7b78115ef2a39c2a2be782eb5d2230d0 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertProductQtyInShoppingCart.php @@ -0,0 +1,75 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Checkout\Test\Constraint; + +use Mtf\Constraint\AbstractConstraint; +use Magento\Checkout\Test\Page\CheckoutCart; +use Magento\Checkout\Test\Fixture\Cart; +use Magento\Catalog\Test\Fixture\CatalogProductSimple; + +/** + * Class AssertProductQtyInShoppingCart + */ +class AssertProductQtyInShoppingCart extends AbstractConstraint +{ + /** + * Constraint severeness + * + * @var string + */ + protected $severeness = 'low'; + + /** + * Assert that quantity in the shopping cart is equals to expected quantity from data set + * + * @param CheckoutCart $checkoutCart + * @param Cart $cart + * @param CatalogProductSimple $product + * @return void + */ + public function processAssert( + CheckoutCart $checkoutCart, + Cart $cart, + CatalogProductSimple $product + ) { + $cartProductQty = $checkoutCart->open()->getCartBlock()->getProductQty($product->getName()); + \PHPUnit_Framework_Assert::assertEquals( + $cartProductQty, + $cart->getQty(), + 'Shopping cart product qty: \'' . $cartProductQty + . '\' not equals with qty from data set: \'' . $cart->getQty() . '\'' + ); + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return 'Quantity in the shopping cart equals to expected quantity from data set.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertSubtotalInShoppingCart.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertSubtotalInShoppingCart.php new file mode 100644 index 0000000000000000000000000000000000000000..c788bc26dcb83d757f0033698828771be13a2918 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Constraint/AssertSubtotalInShoppingCart.php @@ -0,0 +1,76 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Checkout\Test\Constraint; + +use Mtf\Constraint\AbstractConstraint; +use Magento\Checkout\Test\Page\CheckoutCart; +use Magento\Checkout\Test\Fixture\Cart; +use Magento\Catalog\Test\Fixture\CatalogProductSimple; + +/** + * Class AssertSubtotalInShoppingCart + */ +class AssertSubtotalInShoppingCart extends AbstractConstraint +{ + /** + * Constraint severeness + * + * @var string + */ + protected $severeness = 'low'; + + /** + * Assert that subtotal total in the shopping cart is equals to expected total from data set + * + * @param CheckoutCart $checkoutCart + * @param Cart $cart + * @param CatalogProductSimple $product + * @return void + */ + public function processAssert( + CheckoutCart $checkoutCart, + Cart $cart, + CatalogProductSimple $product + ) { + $cartProductSubtotal = $checkoutCart->open()->getCartBlock() + ->getCartItemSubTotalByProductName($product->getName()); + \PHPUnit_Framework_Assert::assertEquals( + $cartProductSubtotal, + $cart->getRowTotal(), + 'Shopping cart subtotal: \'' . $cartProductSubtotal + . '\' not equals with total from data set: \'' . $cart->getRowTotal() . '\'' + ); + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return 'Subtotal in the shopping cart equals to expected total from data set.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/global/constraint.xml new file mode 100644 index 0000000000000000000000000000000000000000..041a6ac5bf0447f6e039cffe4d00fdf0aeeb11c2 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/global/constraint.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" ?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<constraint> + <assertPriceInShoppingCart module="Magento_Checkout"> + <severeness>low</severeness> + </assertPriceInShoppingCart> + <assertProductQtyInShoppingCart module="Magento_Checkout"> + <severeness>low</severeness> + </assertProductQtyInShoppingCart> + <assertProductQtyInMiniShoppingCart module="Magento_Checkout"> + <severeness>low</severeness> + </assertProductQtyInMiniShoppingCart> + <assertSubtotalInShoppingCart module="Magento_Checkout"> + <severeness>low</severeness> + </assertSubtotalInShoppingCart> +</constraint> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/global/fixture.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/global/fixture.xml new file mode 100644 index 0000000000000000000000000000000000000000..e9d8be3cb2647492c57ee1800402a6fbbcbc2a2e --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/etc/global/fixture.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" ?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<fixture> + <cart module="Magento_Checkout"> + <type>flat</type> + <entity_type>sales_flat_quote_item</entity_type> + <collection>Magento\Checkout\Model\Resource\Cart</collection> + </cart> +</fixture> diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Actions.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/CmsPageInterface.php similarity index 70% rename from dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Actions.php rename to dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/CmsPageInterface.php index 01ae4c2757b053b0b04ceede2f200266cc18e047..f111082b687369da435a30a649d48520249f1f8a 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Actions.php +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/CmsPageInterface.php @@ -1,7 +1,5 @@ <?php /** - * URL rewrite grid actions - * * Magento * * NOTICE OF LICENSE @@ -23,24 +21,15 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\UrlRewrite\Test\Block; -use Mtf\Block\Block; +namespace Magento\Cms\Test\Handler\CmsPage; -class Actions extends Block -{ - /** - * Add button - * - * @var string - */ - protected $addNewButton = '#add'; +use Mtf\Handler\HandlerInterface; - /** - * Add new URL rewrite - */ - public function addNewUrlRewrite() - { - $this->_rootElement->find($this->addNewButton)->click(); - } +/** + * Interface CmsPageInterface + */ +interface CmsPageInterface extends HandlerInterface +{ + // } diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/Curl.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/Curl.php new file mode 100644 index 0000000000000000000000000000000000000000..a9cd22332ce78db1a7138da773ad2d7d5d427214 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Handler/CmsPage/Curl.php @@ -0,0 +1,80 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Cms\Test\Handler\CmsPage; + +use Mtf\Fixture\FixtureInterface; +use Mtf\Handler\Curl as AbstractCurl; +use Mtf\Util\Protocol\CurlInterface; +use Mtf\Util\Protocol\CurlTransport; +use Mtf\Util\Protocol\CurlTransport\BackendDecorator; +use Mtf\System\Config; + +/** + * Class Curl + * Curl handler for creating cms page + */ +class Curl extends AbstractCurl implements CmsPageInterface +{ + /** + * Data mapping + * + * @var array + */ + protected $mappingData = [ + 'status' => ['Published' => 1, 'Disabled' => 0], + 'store_id' => ['All Store Views' => 0], + ]; + + /** + * Url for save rewrite + * + * @var string + */ + protected $url = 'admin/cms_page/save/back/edit/active_tab/content_section/'; + + /** + * Post request for creating cms page + * + * @param FixtureInterface $fixture + * @return array + * @throws \Exception + */ + public function persist(FixtureInterface $fixture = null) + { + $url = $_ENV['app_backend_url'] . $this->url; + $data = $this->replaceMappingData($fixture->getData()); + $curl = new BackendDecorator(new CurlTransport(), new Config()); + $curl->write(CurlInterface::POST, $url, '1.0', [], $data); + $response = $curl->read(); + + if (!strpos($response, 'data-ui-id="messages-message-success"')) { + throw new \Exception("Page creation by curl handler was not successful! Response: $response"); + } + + preg_match("~page_id\/(\d*?)\/~", $response, $matches); + $id = isset($matches[1]) ? $matches[1] : null; + return ['page_id' => $id]; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.php index 6c5e2cf5df734df72fe0d34d8657e41692f07951..2e110104a54f9ec3c7d229b76cab0df5dcd3514e 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.php +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.php @@ -70,6 +70,12 @@ class CmsIndex extends FrontendPage 'locator' => '[data-ui-id="language-switcher"]', 'strategy' => 'css selector', ], + 'cartSidebarBlock' => [ + 'name' => 'cartSidebarBlock', + 'class' => 'Magento\Checkout\Test\Block\Cart\Sidebar', + 'locator' => '[data-block="minicart"]', + 'strategy' => 'css selector', + ], ]; /** @@ -119,4 +125,12 @@ class CmsIndex extends FrontendPage { return $this->getBlockInstance('storeSwitcherBlock'); } + + /** + * @return \Magento\Checkout\Test\Block\Cart\Sidebar + */ + public function getCartSidebarBlock() + { + return $this->getBlockInstance('cartSidebarBlock'); + } } diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.xml index a28d9698d8828060d9895992d55a369c8a6b0943..0f03a95f956a10066fbaa2e4879f2dfbaf6bb66d 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.xml +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Page/CmsIndex.xml @@ -60,4 +60,10 @@ <locator>//*[@data-ui-id="language-switcher"]</locator> <strategy>css selector</strategy> </block> + <block> + <name>cartSidebarBlock</name> + <class>Magento\Checkout\Test\Block\Cart\Sidebar</class> + <locator>[data-block="minicart"]</locator> + <strategy>css selector</strategy> + </block> </page> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableInCategory.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableInCategory.php index 03c60d74f23558c1fffad7614b8543ada98434a1..19b546ec68af83481e6e517ffd0acd2be5b3e22c 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableInCategory.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableInCategory.php @@ -105,7 +105,7 @@ class AssertConfigurableInCategory extends AbstractConstraint ->getProductPriceBlock($configurable->getName()) ->getPrice(); \PHPUnit_Framework_Assert::assertEquals( - '$' . $price['price_regular_price'], + $price['price_regular_price'], $pricePresetData['category_price'], 'Product price on category page is not correct.' ); diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableView.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableView.php index 6a047a0f2ea089678c83b32f9986187b9252a13b..2bb1333dd39276175c222d382b0561f235d6927b 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableView.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertConfigurableView.php @@ -94,7 +94,7 @@ class AssertConfigurableView extends AbstractConstraint ->getProductPriceBlock($configurable->getName()) ->getPrice(); \PHPUnit_Framework_Assert::assertEquals( - '$' . $price['price_regular_price'], + $price['price_regular_price'], $pricePresetData['product_price'], 'Product price on category page is not correct.' ); diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingInGrid.php b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingInGrid.php index c21132f3c50762a83ac8843469abccbbcc1086ba..d6307d1e643154780f3aa50856fea08d58e47b68 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingInGrid.php +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingInGrid.php @@ -24,6 +24,8 @@ namespace Magento\Review\Test\Constraint; +use Magento\Review\Test\Fixture\Rating; +use Magento\Review\Test\Page\Adminhtml\RatingIndex; use Mtf\Constraint\AbstractConstraint; /** @@ -39,18 +41,30 @@ class AssertProductRatingInGrid extends AbstractConstraint protected $severeness = 'middle'; /** + * Assert product Rating availability in product Rating grid + * + * @param RatingIndex $ratingIndex + * @param Rating $productRating * @return void */ - public function processAssert() + public function processAssert(RatingIndex $ratingIndex, Rating $productRating) { - // + $filter = ['rating_code' => $productRating->getRatingCode()]; + + $ratingIndex->open(); + \PHPUnit_Framework_Assert::assertTrue( + $ratingIndex->getRatingGrid()->isRowVisible($filter), + "Product Rating " . $productRating->getRatingCode() . " is absent on product Rating grid." + ); } /** + * Text success exist product Rating in grid + * * @return string */ public function toString() { - // + return 'Product Rating is present in grid.'; } } diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingNotInGrid.php b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingNotInGrid.php new file mode 100644 index 0000000000000000000000000000000000000000..41c760abbdf473c3c0d96e2be3afc99621f3a2a1 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingNotInGrid.php @@ -0,0 +1,70 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Review\Test\Constraint; + +use Magento\Review\Test\Fixture\Rating; +use Magento\Review\Test\Page\Adminhtml\RatingIndex; +use Mtf\Constraint\AbstractConstraint; + +/** + * Class AssertProductRatingNotInGrid + */ +class AssertProductRatingNotInGrid extends AbstractConstraint +{ + /** + * Constraint severeness + * + * @var string + */ + protected $severeness = 'middle'; + + /** + * Assert product Rating is absent on product Rating grid + * + * @param RatingIndex $ratingIndex + * @param Rating $productRating + * @return void + */ + public function processAssert(RatingIndex $ratingIndex, Rating $productRating) + { + $filter = ['rating_code' => $productRating->getRatingCode()]; + + $ratingIndex->open(); + \PHPUnit_Framework_Assert::assertFalse( + $ratingIndex->getRatingGrid()->isRowVisible($filter), + "Product Rating " . $productRating->getRatingCode() . " is exist on product Rating grid." + ); + } + + /** + * Text success absent product Rating in grid + * + * @return string + */ + public function toString() + { + return 'Product Rating is absent in grid.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingSuccessDeleteMessage.php new file mode 100644 index 0000000000000000000000000000000000000000..33e9dbcaf4c6b5fa168ddfa412e72d8b927d319a --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Constraint/AssertProductRatingSuccessDeleteMessage.php @@ -0,0 +1,71 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Review\Test\Constraint; + +use Magento\Review\Test\Page\Adminhtml\RatingIndex; +use Mtf\Constraint\AbstractConstraint; + +/** + * Class AssertProductRatingSuccessDeleteMessage + */ +class AssertProductRatingSuccessDeleteMessage extends AbstractConstraint +{ + const SUCCESS_DELETE_MESSAGE = 'You deleted the rating.'; + + /** + * Constraint severeness + * + * @var string + */ + protected $severeness = 'high'; + + /** + * Assert that success message is displayed after rating delete + * + * @param RatingIndex $ratingIndex + * @return void + */ + public function processAssert(RatingIndex $ratingIndex) + { + $actualMessage = $ratingIndex->getMessagesBlock()->getSuccessMessages(); + \PHPUnit_Framework_Assert::assertEquals( + self::SUCCESS_DELETE_MESSAGE, + $actualMessage, + 'Wrong success message is displayed.' + . "\nExpected: " . self::SUCCESS_DELETE_MESSAGE + . "\nActual: " . $actualMessage + ); + } + + /** + * Text success delete message is displayed + * + * @return string + */ + public function toString() + { + return 'Rating success delete message is present.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Fixture/Rating.php b/dev/tests/functional/tests/app/Magento/Review/Test/Fixture/Rating.php index 517aa62be438fb2b0d83a7491b5d93ae65aa8fd7..447987b294d0918079d680608ef0bc276336360b 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/Fixture/Rating.php +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Fixture/Rating.php @@ -34,12 +34,12 @@ class Rating extends InjectableFixture /** * @var string */ - protected $repositoryClass = 'Magento\Rating\Test\Repository\Rating'; + protected $repositoryClass = 'Magento\Review\Test\Repository\Rating'; /** * @var string */ - protected $handlerInterface = 'Magento\Rating\Test\Handler\Rating\RatingInterface'; + protected $handlerInterface = 'Magento\Review\Test\Handler\Rating\RatingInterface'; protected $defaultDataSet = [ 'rating_code' => 'Rating %isolation%', diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Rating/Curl.php b/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Rating/Curl.php new file mode 100644 index 0000000000000000000000000000000000000000..2672dc9b45a8517813fd79e1d33d7348cc4a1e22 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Rating/Curl.php @@ -0,0 +1,96 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Review\Test\Handler\Rating; + +use Magento\Backend\Test\Handler\Extractor; +use Mtf\Fixture\FixtureInterface; +use Mtf\Handler\Curl as AbstractCurl; +use Mtf\System\Config; +use Mtf\Util\Protocol\CurlInterface; +use Mtf\Util\Protocol\CurlTransport\BackendDecorator; +use Mtf\Util\Protocol\CurlTransport; + +/** + * Class Curl + * Curl handler for creating product Rating through backend. + */ +class Curl extends AbstractCurl implements RatingInterface +{ + /** + * Mapping values for data. + * + * @var array + */ + protected $mappingData = [ + 'is_active' => [ + 'Yes' => 1, + 'No' => 0, + ], + 'stores' => [ + 'Main Website/Main Website Store/Default Store View' => 1 + ] + ]; + + /** + * Post request for creating product Rating in backend + * + * @param FixtureInterface|null $rating + * @return array + * @throws \Exception + */ + public function persist(FixtureInterface $rating = null) + { + $url = $_ENV['app_backend_url'] . 'review/rating/save/'; + $curl = new BackendDecorator(new CurlTransport(), new Config()); + $data = $this->replaceMappingData($rating->getData()); + + $data['stores'] = is_array($data['stores']) ? $data['stores'] : [$data['stores']]; + $curl->write(CurlInterface::POST, $url, '1.0', [], $data); + $response = $curl->read(); + $curl->close(); + if (!strpos($response, 'data-ui-id="messages-message-success"')) { + throw new \Exception( + 'Product Rating entity creating by curl handler was not successful! Response:' . $response + ); + } + + return ['id' => $this->getProductRatingId()]; + } + + /** + * Get product Rating id + * + * @return int|null + */ + protected function getProductRatingId() + { + $url = 'review/rating/index/sort/rating_id/dir/desc/'; + $regex = '/data-column="rating_id"[^>]*>\s*([0-9]+)\s*</'; + $extractor = new Extractor($url, $regex); + $match = $extractor->getData(); + + return empty($match[1]) ? null : $match[1]; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Rating/RatingInterface.php b/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Rating/RatingInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..f3bea35c9ae23d692ddd5845ba54183205cd893f --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Handler/Rating/RatingInterface.php @@ -0,0 +1,35 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Review\Test\Handler\Rating; + +use Mtf\Handler\HandlerInterface; + +/** + * Interface RatingInterface + */ +interface RatingInterface extends HandlerInterface +{ + // +} diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/Repository/Rating.php b/dev/tests/functional/tests/app/Magento/Review/Test/Repository/Rating.php new file mode 100644 index 0000000000000000000000000000000000000000..4141b11447d8f6f30374802b865dcc11fcfcb134 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Review/Test/Repository/Rating.php @@ -0,0 +1,48 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Review\Test\Repository; + +use Mtf\Repository\AbstractRepository; + +/** + * Class Rating + * Data for creation product Rating + */ +class Rating extends AbstractRepository +{ + /** + * @constructor + * @param array $defaultConfig + * @param array $defaultData + */ + public function __construct(array $defaultConfig = [], array $defaultData = []) + { + $this->_data['default'] = [ + 'rating_code' => 'Rating %isolation%', + 'stores' => ['Main Website/Main Website Store/Default Store View'], + 'is_active' => 'Yes', + ]; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/TestCase/CreateBackendProductRatingTest.php b/dev/tests/functional/tests/app/Magento/Review/Test/TestCase/CreateProductRatingEntityTest.php similarity index 96% rename from dev/tests/functional/tests/app/Magento/Review/Test/TestCase/CreateBackendProductRatingTest.php rename to dev/tests/functional/tests/app/Magento/Review/Test/TestCase/CreateProductRatingEntityTest.php index e940b1497696dcb3a589694847f1012e8286b874..5d6f3dda381ec87c8609f384f32bcc3208086173 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/TestCase/CreateBackendProductRatingTest.php +++ b/dev/tests/functional/tests/app/Magento/Review/Test/TestCase/CreateProductRatingEntityTest.php @@ -50,7 +50,7 @@ use Mtf\TestCase\Injectable; * @group Reviews_and_Ratings_(MX) * @ZephyrId MAGETWO-23331 */ -class CreateBackendProductRatingTest extends Injectable +class CreateProductRatingEntityTest extends Injectable { /** * @var Rating @@ -97,7 +97,7 @@ class CreateBackendProductRatingTest extends Injectable * @param Rating $productRating * @return void */ - public function testCreateBackendProductRating( + public function testCreateProductRatingEntityTest( CatalogProductSimple $product, Rating $productRating ) { diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/TestCase/CreateBackendProductRatingTest/testCreateBackendProductRating.csv b/dev/tests/functional/tests/app/Magento/Review/Test/TestCase/CreateProductRatingEntityTest/testCreateProductRatingEntityTest.csv similarity index 100% rename from dev/tests/functional/tests/app/Magento/Review/Test/TestCase/CreateBackendProductRatingTest/testCreateBackendProductRating.csv rename to dev/tests/functional/tests/app/Magento/Review/Test/TestCase/CreateProductRatingEntityTest/testCreateProductRatingEntityTest.csv diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/TestCase/DeleteProductRatingEntityTest.php b/dev/tests/functional/tests/app/Magento/Review/Test/TestCase/DeleteProductRatingEntityTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a9d58fc44b1775c61641bab82f0befc098d3cb91 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Review/Test/TestCase/DeleteProductRatingEntityTest.php @@ -0,0 +1,105 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Review\Test\TestCase; + +use Magento\Catalog\Test\Fixture\CatalogProductSimple; +use Magento\Review\Test\Fixture\Rating; +use Magento\Review\Test\Page\Adminhtml\RatingEdit; +use Magento\Review\Test\Page\Adminhtml\RatingIndex; +use Mtf\TestCase\Injectable; + +/** + * Test Creation for DeleteProductRatingEntity + * + * Test Flow: + * + * Preconditions: + * 1. Simple product is created. + * 2. Product rating is created. + * + * Steps: + * 1. Login to backend. + * 2. Navigate to Stores->Attributes->Rating. + * 3. Search product rating in grid by given data. + * 4. Open this product rating by clicking. + * 5. Click 'Delete Rating' button. + * 6. Perform all asserts. + * + * @group Reviews_and_Ratings_(MX) + * @ZephyrId MAGETWO-23276 + */ +class DeleteProductRatingEntityTest extends Injectable +{ + /** + * @var RatingIndex + */ + protected $ratingIndex; + + /** + * @var RatingEdit + */ + protected $ratingEdit; + + /** + * Prepare data + * + * @param CatalogProductSimple $product + * @return array + */ + public function __prepare(CatalogProductSimple $product) + { + $product->persist(); + return ['product' => $product]; + } + + /** + * Inject data + * + * @param RatingIndex $ratingIndex + * @param RatingEdit $ratingEdit + * @return void + */ + public function __inject(RatingIndex $ratingIndex, RatingEdit $ratingEdit) + { + $this->ratingIndex = $ratingIndex; + $this->ratingEdit = $ratingEdit; + } + + /** + * Runs delete product Rating entity test + * + * @param Rating $productRating + * @return void + */ + public function testDeleteProductRatingEntity(Rating $productRating) + { + // Preconditions + $productRating->persist(); + + // Steps + $this->ratingIndex->open(); + $this->ratingIndex->getRatingGrid()->searchAndOpen(['rating_code' => $productRating->getRatingCode()]); + $this->ratingEdit->getPageActions()->delete(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/TestCase/DeleteProductRatingEntityTest/testDeleteProductRatingEntity.csv b/dev/tests/functional/tests/app/Magento/Review/Test/TestCase/DeleteProductRatingEntityTest/testDeleteProductRatingEntity.csv new file mode 100644 index 0000000000000000000000000000000000000000..ef9e67e693c33b84579dacbff32ea8c5c0b949a0 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Review/Test/TestCase/DeleteProductRatingEntityTest/testDeleteProductRatingEntity.csv @@ -0,0 +1,2 @@ +"productRating/dataSet";"constraint" +"default";"assertProductRatingSuccessDeleteMessage, assertProductRatingNotInGrid, assertProductRatingNotInProductPage" diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/etc/curl/di.xml b/dev/tests/functional/tests/app/Magento/Review/Test/etc/curl/di.xml new file mode 100644 index 0000000000000000000000000000000000000000..fa49f6b3789386ee515c6fd3a921cb216d39ad5d --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Review/Test/etc/curl/di.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" ?> +<!-- +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Academic Free License (AFL 3.0) + * that is bundled with this package in the file LICENSE_AFL.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/afl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"> + <preference for="Magento\Review\Test\Handler\Rating\RatingInterface" type="\Magento\Review\Test\Handler\Rating\Curl"/> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Review/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/Review/Test/etc/global/constraint.xml index d69c444ee7cc43a2aba31af8ae861cdef0b6d4ba..d6f63c99b49b5fea30490965bea1ef2e1c3cd201 100644 --- a/dev/tests/functional/tests/app/Magento/Review/Test/etc/global/constraint.xml +++ b/dev/tests/functional/tests/app/Magento/Review/Test/etc/global/constraint.xml @@ -27,9 +27,15 @@ <assertProductRatingSuccessSaveMessage module="Magento_Review"> <severeness>high</severeness> </assertProductRatingSuccessSaveMessage> + <assertProductRatingSuccessDeleteMessage module="Magento_Review"> + <severeness>high</severeness> + </assertProductRatingSuccessDeleteMessage> <assertProductRatingInGrid module="Magento_Review"> <severeness>middle</severeness> </assertProductRatingInGrid> + <assertProductRatingNotInGrid module="Magento_Review"> + <severeness>middle</severeness> + </assertProductRatingNotInGrid> <assertProductRatingInProductPage module="Magento_Review"> <severeness>middle</severeness> </assertProductRatingInProductPage> diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rate/Edit/FormPageActions.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rate/Edit/FormPageActions.php index 659a93a506a85a1b0541e3a8c24cc42bc045a678..5407bf6cf5f81a1e1d5626989c916d3f5edeac68 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rate/Edit/FormPageActions.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rate/Edit/FormPageActions.php @@ -38,4 +38,11 @@ class FormPageActions extends ParentFormPageActions * @var string */ protected $saveButton = '.save-rate'; + + /** + * "Delete" button + * + * @var string + */ + protected $deleteButton = '.delete'; } diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rule/Edit/Form.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rule/Edit/Form.php index fcf5167241896b40097889093b885cf121f673b3..ed71e7fa8507be0c0322d6ba6f7ddf0e7618c675 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rule/Edit/Form.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rule/Edit/Form.php @@ -238,4 +238,16 @@ class Form extends FormInterface { $this->_rootElement->find($this->additionalSettings)->click(); } + + /** + * Getting all options in Tax Rate multi select list + * + * @return array + */ + public function getAllTaxRates() + { + /** @var \Mtf\Client\Driver\Selenium\Element\MultiselectlistElement $taxRates */ + $taxRates = $this->_rootElement->find($this->taxRateBlock, Locator::SELECTOR_CSS, 'multiselectlist'); + return $taxRates->getAllValues(); + } } diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateNotInGrid.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateNotInGrid.php new file mode 100644 index 0000000000000000000000000000000000000000..b327d77bc034a75dbc3df1a3c1acc37a91e6fa77 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateNotInGrid.php @@ -0,0 +1,74 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Tax\Test\Constraint; + +use Mtf\Constraint\AbstractConstraint; +use Magento\Tax\Test\Page\Adminhtml\TaxRateIndex; +use Magento\Tax\Test\Fixture\TaxRate; + +/** + * Class AssertTaxRateNotInGrid + */ +class AssertTaxRateNotInGrid extends AbstractConstraint +{ + /** + * Constraint severeness + * + * @var string + */ + protected $severeness = 'high'; + + /** + * Assert that tax rate not available in Tax Rate grid + * + * @param TaxRateIndex $taxRateIndex + * @param TaxRate $taxRate + * @return void + */ + public function processAssert( + TaxRateIndex $taxRateIndex, + TaxRate $taxRate + ) { + $filter = [ + 'code' => $taxRate->getCode(), + ]; + + $taxRateIndex->open(); + \PHPUnit_Framework_Assert::assertFalse( + $taxRateIndex->getTaxRateGrid()->isRowVisible($filter), + 'Tax Rate \'' . $filter['code'] . '\' is present in Tax Rate grid.' + ); + } + + /** + * Text of Tax Rate not in grid assert + * + * @return string + */ + public function toString() + { + return 'Tax rate is absent in grid.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateNotInTaxRule.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateNotInTaxRule.php new file mode 100644 index 0000000000000000000000000000000000000000..8a8c615c8f5cdecfc97b758721d945596cd3b3a3 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateNotInTaxRule.php @@ -0,0 +1,71 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Tax\Test\Constraint; + +use Magento\Tax\Test\Fixture\TaxRate; +use Magento\Tax\Test\Page\Adminhtml\TaxRuleNew; +use Mtf\Constraint\AbstractConstraint; + +/** + * Class AssertTaxRateNotInTaxRule + */ +class AssertTaxRateNotInTaxRule extends AbstractConstraint +{ + /** + * Constraint severeness + * + * @var string + */ + protected $severeness = 'high'; + + /** + * Assert that tax rate is absent in tax rule form + * + * @param TaxRate $taxRate + * @param TaxRuleNew $taxRuleNew + * @return void + */ + public function processAssert( + TaxRate $taxRate, + TaxRuleNew $taxRuleNew + ) { + $taxRuleNew->open(); + $taxRatesList = $taxRuleNew->getTaxRuleForm()->getAllTaxRates(); + \PHPUnit_Framework_Assert::assertFalse( + in_array($taxRate->getCode(), $taxRatesList), + 'Tax Rate \'' . $taxRate->getCode() . '\' is present in Tax Rule form.' + ); + } + + /** + * Text of Tax Rate not in Tax Rule form + * + * @return string + */ + public function toString() + { + return 'Tax rate is absent in tax rule from.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessDeleteMessage.php new file mode 100644 index 0000000000000000000000000000000000000000..914ea56e28366da7cd3b459199f65048810a7b02 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessDeleteMessage.php @@ -0,0 +1,71 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Tax\Test\Constraint; + +use Mtf\Constraint\AbstractConstraint; +use Magento\Tax\Test\Page\Adminhtml\TaxRateIndex; + +/** + * Class AssertTaxRateSuccessDeleteMessage + */ +class AssertTaxRateSuccessDeleteMessage extends AbstractConstraint +{ + const SUCCESS_DELETE_MESSAGE = 'The tax rate has been deleted.'; + + /** + * Constraint severeness + * + * @var string + */ + protected $severeness = 'high'; + + /** + * Assert that success delete message is displayed after tax rate deleted + * + * @param TaxRateIndex $taxRateIndex + * @return void + */ + public function processAssert(TaxRateIndex $taxRateIndex) + { + $actualMessage = $taxRateIndex->getMessagesBlock()->getSuccessMessages(); + \PHPUnit_Framework_Assert::assertEquals( + self::SUCCESS_DELETE_MESSAGE, + $actualMessage, + 'Wrong success delete message is displayed.' + . "\nExpected: " . self::SUCCESS_DELETE_MESSAGE + . "\nActual: " . $actualMessage + ); + } + + /** + * Text of Deleted Tax Rate Success Message assert + * + * @return string + */ + public function toString() + { + return 'Tax rate success delete message is present.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/DeleteTaxRateEntityTest.php b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/DeleteTaxRateEntityTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0dc974965c2dd08afb1ae8c22bda8f1403ef0e50 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/DeleteTaxRateEntityTest.php @@ -0,0 +1,99 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Tax\Test\TestCase; + +use Magento\Tax\Test\Fixture\TaxRate; +use Magento\Tax\Test\Page\Adminhtml\TaxRateIndex; +use Magento\Tax\Test\Page\Adminhtml\TaxRateNew; +use Mtf\TestCase\Injectable; + +/** + * Test creation for delete TaxRateEntity + * + * Test Flow: + * Preconditions: + * 1. Create Tax Rate + * + * Steps: + * 1. Log in as default admin user + * 2. Go to Stores -> Taxes -> Tax Zones and Rates + * 3. Open created tax rate + * 4. Click Delete Rate + * 5. Perform all assertions + * + * @group Tax_(CS) + * @ZephyrId MAGETWO-23295 + */ +class DeleteTaxRateEntityTest extends Injectable +{ + /** + * Tax Rate grid page + * + * @var TaxRateIndex + */ + protected $taxRateIndex; + + /** + * Tax Rate new/edit page + * + * @var TaxRateNew + */ + protected $taxRateNew; + + /** + * Injection data + * + * @param TaxRateIndex $taxRateIndex + * @param TaxRateNew $taxRateNew + * @return void + */ + public function __inject( + TaxRateIndex $taxRateIndex, + TaxRateNew $taxRateNew + ) { + $this->taxRateIndex = $taxRateIndex; + $this->taxRateNew = $taxRateNew; + } + + /** + * Delete Tax Rate Entity test + * + * @param TaxRate $taxRate + * @return void + */ + public function testDeleteTaxRate(TaxRate $taxRate) + { + // Precondition + $taxRate->persist(); + + // Steps + $filter = [ + 'code' => $taxRate->getCode(), + ]; + $this->taxRateIndex->open(); + $this->taxRateIndex->getTaxRateGrid()->searchAndOpen($filter); + $this->taxRateNew->getFormPageActions()->delete(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/DeleteTaxRateEntityTest/testDeleteTaxRate.csv b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/DeleteTaxRateEntityTest/testDeleteTaxRate.csv new file mode 100644 index 0000000000000000000000000000000000000000..ada912bbcb170791b78bffa4052fb635287ad744 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/DeleteTaxRateEntityTest/testDeleteTaxRate.csv @@ -0,0 +1,2 @@ +"taxRate/dataSet";"constraint" +"default";"assertTaxRateSuccessDeleteMessage, assertTaxRateNotInGrid, assertTaxRateNotInTaxRule" \ No newline at end of file diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/etc/global/constraint.xml index 3e353cf8a61ea01eecae2f6a113b1686e2554592..38f3260709d305403df7f447c54b0f32d8a3d954 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/etc/global/constraint.xml +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/etc/global/constraint.xml @@ -95,4 +95,26 @@ <taxRule class="Magento\Tax\Test\Fixture\TaxRule" /> </require> </assertTaxRuleNotInGrid> + <assertTaxRateSuccessDeleteMessage module="Magento_Tax"> + <severeness>high</severeness> + <require> + <taxRateIndex class="Magento\Tax\Test\Page\Adminhtml\TaxRateIndex" /> + </require> + </assertTaxRateSuccessDeleteMessage> + <assertTaxRateNotInGrid module="Magento_Tax"> + <severeness>high</severeness> + <require> + <taxRateIndex class="Magento\Tax\Test\Page\Adminhtml\TaxRateIndex" /> + <taxRate class="Magento\Tax\Test\Fixture\TaxRate" /> + </require> + </assertTaxRateNotInGrid> + <assertTaxRateNotInTaxRule module="Magento_Tax"> + <severeness>high</severeness> + <require> + <taxRate class="Magento\Tax\Test\Fixture\TaxRate" /> + <taxRule class="Magento\Tax\Test\Fixture\TaxRule" /> + <taxRuleIndex class="Magento\Tax\Test\Page\Adminhtml\TaxRuleIndex" /> + <taxRuleNew class="Magento\Tax\Test\Page\Adminhtml\TaxRuleNew" /> + </require> + </assertTaxRateNotInTaxRule> </constraint> diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Category/Grid.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Category/Grid.php similarity index 81% rename from dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Category/Grid.php rename to dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Category/Grid.php index 499d5a6cc423856b2be7f3052b75debbd74a0d0f..35b318a1b3f5c0cc9765fa003fc9127595b53ff8 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Category/Grid.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Category/Grid.php @@ -22,24 +22,27 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\UrlRewrite\Test\Block\Catalog\Category; +namespace Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Category; -use Magento\Backend\Test\Block\Widget\Grid as GridInterface; +use Magento\Backend\Test\Block\Widget\Grid as ParentGrid; /** * Class Grid * URL Redirect grid */ -class Grid extends GridInterface +class Grid extends ParentGrid { /** * Filters array mapping * - * @var array $filters + * @var array */ protected $filters = [ 'request_path' => [ 'selector' => '#urlrewriteGrid_filter_request_path' + ], + 'id_path' => [ + 'selector' => '#urlrewriteGrid_filter_id_path' ] ]; } diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Category/Tree.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Category/Tree.php similarity index 72% rename from dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Category/Tree.php rename to dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Category/Tree.php index d8f6a9338448f1bbabe46f32df3daeba2e0074b2..6bfad738887dc462e4dde48daa356e950d7de285 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Category/Tree.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Category/Tree.php @@ -22,7 +22,7 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\UrlRewrite\Test\Block\Catalog\Category; +namespace Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Category; use Mtf\Block\Block; use Mtf\Client\Element\Locator; @@ -30,17 +30,34 @@ use Mtf\Client\Element\Locator; /** * Class Tree * Categories tree block - * */ class Tree extends Block { + /** + * Locator value for skip category button + * + * @var string + */ + protected $skipCategoryButton = '[data-ui-id="urlrewrite-catalog-product-edit-skip-categories"]'; + /** * Select category by its name * * @param string $categoryName + * @return void */ public function selectCategory($categoryName) { $this->_rootElement->find("//a[contains(text(),'{$categoryName}')]", Locator::SELECTOR_XPATH)->click(); } + + /** + * Skip category selection + * + * @return void + */ + public function skipCategorySelection() + { + $this->_rootElement->find($this->skipCategoryButton, Locator::SELECTOR_CSS)->click(); + } } diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Edit/Form.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/Form.php similarity index 94% rename from dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Edit/Form.php rename to dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/Form.php index bb35b4366b92f29f0970dc2ed2da76e744ac601e..f4489b10a08421dd755f929ccbf26c3aada01145 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Edit/Form.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/Form.php @@ -22,7 +22,7 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\UrlRewrite\Test\Block\Catalog\Edit; +namespace Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Edit; use Magento\Backend\Test\Block\Widget\Form as FormWidget; diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Edit/Form.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/Form.xml similarity index 100% rename from dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Edit/Form.xml rename to dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Edit/Form.xml diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Product/Grid.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Product/Grid.php similarity index 69% rename from dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Product/Grid.php rename to dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Product/Grid.php index 6ababae7f9a6ae7f008d271fa7989254765eb64d..5f9f7baeece3f88c0243ea7000547704e18e069d 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Catalog/Product/Grid.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Catalog/Product/Grid.php @@ -22,37 +22,41 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\UrlRewrite\Test\Block\Catalog\Product; +namespace Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Product; -use Magento\Backend\Test\Block\Widget\Grid as GridInterface; +use Magento\Backend\Test\Block\Widget\Grid as ParentGrid; /** * Class Grid * Product grid - * */ -class Grid extends GridInterface +class Grid extends ParentGrid { + /** + * An element locator which allows to select entities in grid + * + * @var string + */ + protected $selectItem = 'tbody tr .col-entity_id'; + + /** + * Locator value for link in action column + * + * @var string + */ + protected $editLink = 'td.col-name'; + /** * Filters array mapping * * @var array */ - protected $filters = array( - 'id' => array( + protected $filters = [ + 'id' => [ 'selector' => '[id=productGrid_product_filter_entity_id]', - ), - 'sku' => array( + ], + 'sku' => [ 'selector' => '[id=productGrid_product_filter_sku]', - ), - ); - - /** - * Initialize block elements - */ - protected function _init() - { - parent::_init(); - $this->selectItem = 'tbody tr .col-entity_id'; - } + ], + ]; } diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Cms/Page/Grid.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Cms/Page/Grid.php new file mode 100644 index 0000000000000000000000000000000000000000..efe4eafe95e10e621baa0b1826b1dc45ea9dd35f --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Cms/Page/Grid.php @@ -0,0 +1,52 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\UrlRewrite\Test\Block\Adminhtml\Cms\Page; + +use Magento\Backend\Test\Block\Widget\Grid as ParentGrid; + +/** + * Class Grid + * URL Redirect grid + */ +class Grid extends ParentGrid +{ + /** + * Locator value for link in action column + * + * @var string + */ + protected $editLink = 'td.col-title'; + + /** + * Filters array mapping + * + * @var array + */ + protected $filters = [ + 'title' => [ + 'selector' => '#cmsPageGrid_filter_title' + ] + ]; +} diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Selector.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Selector.php similarity index 96% rename from dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Selector.php rename to dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Selector.php index 4d19b92fdefac88f05f20e6bd92f4ec479ffbe43..d55a83a9a4442ed025005cc3ba8c118f94e13417 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Selector.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Block/Adminhtml/Selector.php @@ -23,7 +23,7 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\UrlRewrite\Test\Block; +namespace Magento\UrlRewrite\Test\Block\Adminhtml; use Mtf\Block\Block; use Mtf\Client\Element\Locator; diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteCmsPageRedirect.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteCmsPageRedirect.php new file mode 100644 index 0000000000000000000000000000000000000000..8a8988192c5009664d7ec988b3b9bd1281fd6bf1 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteCmsPageRedirect.php @@ -0,0 +1,88 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\UrlRewrite\Test\Constraint; + +use Mtf\Client\Browser; +use Mtf\Constraint\AbstractConstraint; +use Magento\UrlRewrite\Test\Fixture\UrlRewrite; +use Magento\Cms\Test\Fixture\CmsPage; + +/** + * Class AssertUrlRewriteCmsPageRedirect + * Assert that created CMS Page URL Redirect lead to appropriate page in frontend + */ +class AssertUrlRewriteCmsPageRedirect extends AbstractConstraint +{ + /** + * Constraint severeness + * + * @var string + */ + protected $severeness = 'low'; + + /** + * URL for CMS Page + * + * @var string + */ + protected $url = 'cms/page/view/page_id/'; + + /** + * Assert that created CMS Page URL Redirect lead to appropriate page in frontend + * + * @param UrlRewrite $urlRewrite + * @param CmsPage $cmsPage + * @param Browser $browser + * @return void + */ + public function processAssert( + UrlRewrite $urlRewrite, + CmsPage $cmsPage, + Browser $browser + ) { + $browser->open($_ENV['app_frontend_url'] . $urlRewrite->getRequestPath()); + $url = $urlRewrite->getOptions() == 'No' + ? $urlRewrite->getRequestPath() + : $this->url . $cmsPage->getPageId(); + + \PHPUnit_Framework_Assert::assertEquals( + $browser->getUrl(), + $_ENV['app_frontend_url'] . $url, + 'URL rewrite CMS Page redirect false.' + . "\nExpected: " . $_ENV['app_frontend_url'] . $url + . "\nActual: " . $browser->getUrl() + ); + } + + /** + * URL Redirect lead to appropriate page in frontend + * + * @return string + */ + public function toString() + { + return 'URL Redirect lead to appropriate page in frontend.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertProductUrlAvailableOnTheFront.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteProductRedirect.php similarity index 82% rename from dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertProductUrlAvailableOnTheFront.php rename to dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteProductRedirect.php index 298b499c2196664515d0062e7faf88efb34e41ab..12a84e1d84023c013eae6723d732f8449bc5f5f7 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertProductUrlAvailableOnTheFront.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Constraint/AssertUrlRewriteProductRedirect.php @@ -28,12 +28,13 @@ use Magento\Catalog\Test\Page\Product\CatalogProductView; use Mtf\Client\Browser; use Mtf\Constraint\AbstractConstraint; use Magento\UrlRewrite\Test\Fixture\UrlRewrite; +use Mtf\Fixture\InjectableFixture; /** - * Class AssertProductUrlAvailableOnTheFront + * Class AssertUrlRewriteProductRedirect * Assert that product available by new URL on the front */ -class AssertProductUrlAvailableOnTheFront extends AbstractConstraint +class AssertUrlRewriteProductRedirect extends AbstractConstraint { /** * Constraint severeness @@ -47,20 +48,25 @@ class AssertProductUrlAvailableOnTheFront extends AbstractConstraint * * @param UrlRewrite $urlRewrite * @param CatalogProductView $catalogProductView + * @param InjectableFixture $product * @param Browser $browser * @return void */ public function processAssert( UrlRewrite $urlRewrite, CatalogProductView $catalogProductView, - Browser $browser + Browser $browser, + InjectableFixture $product = null ) { $browser->open($_ENV['app_frontend_url'] . $urlRewrite->getRequestPath()); + if ($product === null) { + $product = $urlRewrite->getDataFieldConfig('id_path')['source']->getEntity(); + } \PHPUnit_Framework_Assert::assertEquals( $catalogProductView->getTitleBlock()->getTitle(), - $urlRewrite->getDataFieldConfig('product_id')['source']->getProduct()->getName(), + $product->getName(), 'URL rewrite product redirect false.' - . "\nExpected: " . $urlRewrite->getDataFieldConfig('product_id')['source']->getProduct()->getName() + . "\nExpected: " . $product->getName() . "\nActual: " . $catalogProductView->getTitleBlock()->getTitle() ); } diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.php index 8ed995d48c50f27881b35411394ef9f9113531b2..8b115150414939e4d6313eda1964fa6186b092a3 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.php @@ -54,12 +54,7 @@ class UrlRewrite extends InjectableFixture protected $id_path = [ 'attribute_code' => 'id_path', 'backend_type' => 'virtual', - ]; - - protected $product_id = [ - 'attribute_code' => 'product_id', - 'backend_type' => 'virtual', - 'source' => 'Magento\UrlRewrite\Test\Fixture\UrlRewrite\ProductId', + 'source' => 'Magento\UrlRewrite\Test\Fixture\UrlRewrite\IdPath', ]; protected $store_id = [ @@ -102,11 +97,6 @@ class UrlRewrite extends InjectableFixture return $this->getData('id_path'); } - public function getProductId() - { - return $this->getData('product_id'); - } - public function getStoreId() { return $this->getData('store_id'); diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.xml index 88247b3c1a82dda2523c70fbfc5602702711981b..20e71d8cb3dc84901948caea7e0895f141d1b76d 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.xml +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite.xml @@ -37,11 +37,8 @@ <id_path> <attribute_code>id_path</attribute_code> <backend_type>virtual</backend_type> + <source>Magento\UrlRewrite\Test\Fixture\UrlRewrite\IdPath</source> </id_path> - <product_id> - <attribute_code>product_id</attribute_code> - <backend_type>virtual</backend_type> - </product_id> <store_id> <attribute_code>store_id</attribute_code> <backend_type>virtual</backend_type> diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/ProductId.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/IdPath.php similarity index 74% rename from dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/ProductId.php rename to dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/IdPath.php index 17c31ee4ab9f91bf7fcda048cf93bfff98971be9..d67d9cc7dc0cd233b238bfaad4e4918d0ef7fc60 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/ProductId.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Fixture/UrlRewrite/IdPath.php @@ -28,10 +28,10 @@ use Mtf\Fixture\FixtureFactory; use Mtf\Fixture\FixtureInterface; /** - * Class ProductId - * Prepare product + * Class IdPath + * Prepare ID Path */ -class ProductId implements FixtureInterface +class IdPath implements FixtureInterface { /** * Resource data @@ -41,11 +41,11 @@ class ProductId implements FixtureInterface protected $data; /** - * Return product + * Return category * * @var FixtureInterface */ - protected $product; + protected $entity; /** * @param FixtureFactory $fixtureFactory @@ -55,14 +55,19 @@ class ProductId implements FixtureInterface public function __construct(FixtureFactory $fixtureFactory, array $params, array $data = []) { $this->params = $params; - $explodeValue = explode('::', $data['dataSet']); + if (!isset($data['entity'])) { + $this->data = array_shift($data); + return; + } + preg_match('`%(.*?)%`', $data['entity'], $dataSet); + $explodeValue = explode('::', $dataSet[1]); if (!empty($explodeValue) && count($explodeValue) > 1) { /** @var FixtureInterface $fixture */ - $this->product = $fixtureFactory->createByCode($explodeValue[0], ['dataSet' => $explodeValue[1]]); - $this->product->persist(); - $this->data = $this->product->getId(); + $this->entity = $fixtureFactory->createByCode($explodeValue[0], ['entity' => $explodeValue[1]]); + $this->entity->persist(); + $this->data = preg_replace('`(%.*?%)`', $this->entity->getId(), $data['entity']); } else { - $this->data = strval($data['dataSet']); + $this->data = strval($data['entity']); } } @@ -98,12 +103,12 @@ class ProductId implements FixtureInterface } /** - * Return product + * Return entity * * @return FixtureInterface */ - public function getProduct() + public function getEntity() { - return $this->product; + return $this->entity; } } diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/Curl.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/Curl.php index b34e502aac8206f6ff8fe0929981b55500e858fd..fdd1c3eab70782438e581ce3a618d238de8ec820 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/Curl.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/Curl.php @@ -42,7 +42,7 @@ class Curl extends AbstractCurl implements UrlRewriteInterface * * @var array */ - protected $dataMapping = [ + protected $mappingData = [ 'store_id' => ['Default Store View' => 1], 'options' => [ 'Temporary (302)' => 'R', @@ -68,7 +68,7 @@ class Curl extends AbstractCurl implements UrlRewriteInterface public function persist(FixtureInterface $fixture = null) { $url = $_ENV['app_backend_url'] . $this->url . $fixture->getIdPath(); - $data = $this->prepareData($fixture->getData()); + $data = $this->replaceMappingData($fixture->getData()); $curl = new BackendDecorator(new CurlTransport(), new Config()); $curl->write(CurlInterface::POST, $url, '1.0', array(), $data); $response = $curl->read(); @@ -78,20 +78,4 @@ class Curl extends AbstractCurl implements UrlRewriteInterface } $curl->close(); } - - /** - * Prepare data - * - * @param array $data - * @return array - */ - protected function prepareData(array $data) - { - foreach ($data as $key => $value) { - if (isset($this->dataMapping[$key])) { - $data[$key] = $this->dataMapping[$key][$value]; - } - } - return $data; - } } diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/UrlRewriteInterface.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/UrlRewriteInterface.php index 80dccd6f26f1940cc71994f85070f8bc20885565..8e86e6795ff82f21135abdc9070088eaa19e8191 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/UrlRewriteInterface.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Handler/UrlRewrite/UrlRewriteInterface.php @@ -31,5 +31,5 @@ use Mtf\Handler\HandlerInterface; */ interface UrlRewriteInterface extends HandlerInterface { - // + // } diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.php index 3ace1a1a09fe16ea16327791ded01a5c905f694c..0ab76c1f45b56f4dc3f4e0b0b39f217d865077ce 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.php @@ -36,13 +36,13 @@ class UrlrewriteEdit extends BackendPage protected $_blocks = [ 'treeBlock' => [ 'name' => 'treeBlock', - 'class' => 'Magento\UrlRewrite\Test\Block\Catalog\Category\Tree', - 'locator' => '[data-ui-id="category-selector"]', + 'class' => 'Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Category\Tree', + 'locator' => '[id="page:main-container"]', 'strategy' => 'css selector', ], 'formBlock' => [ 'name' => 'formBlock', - 'class' => 'Magento\UrlRewrite\Test\Block\Catalog\Edit\Form', + 'class' => 'Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Edit\Form', 'locator' => '#edit_form', 'strategy' => 'css selector', ], @@ -52,12 +52,6 @@ class UrlrewriteEdit extends BackendPage 'locator' => '#messages .messages', 'strategy' => 'css selector', ], - 'buttonBlock' => [ - 'name' => 'buttonBlock', - 'class' => 'Magento\Backend\Test\Block\Widget\Form', - 'locator' => '#messages .messages', - 'strategy' => 'css selector', - ], 'pageMainActions' => [ 'name' => 'pageMainActions', 'class' => 'Magento\Backend\Test\Block\FormPageActions', @@ -66,20 +60,26 @@ class UrlrewriteEdit extends BackendPage ], 'productGridBlock' => [ 'name' => 'productGridBlock', - 'class' => 'Magento\UrlRewrite\Test\Block\Catalog\Product\Grid', + 'class' => 'Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Product\Grid', 'locator' => '[id="productGrid"]', 'strategy' => 'css selector', ], 'urlRewriteTypeSelectorBlock' => [ 'name' => 'urlRewriteTypeSelectorBlock', - 'class' => 'Magento\UrlRewrite\Test\Block\Selector', + 'class' => 'Magento\UrlRewrite\Test\Block\Adminhtml\Selector', 'locator' => '[data-ui-id="urlrewrite-type-selector"]', 'strategy' => 'css selector', ], + 'cmsGridBlock' => [ + 'name' => 'gridBlock', + 'class' => 'Magento\UrlRewrite\Test\Block\Adminhtml\Cms\Page\Grid', + 'locator' => '#cmsPageGrid', + 'strategy' => 'css selector', + ], ]; /** - * @return \Magento\UrlRewrite\Test\Block\Catalog\Category\Tree + * @return \Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Category\Tree */ public function getTreeBlock() { @@ -87,7 +87,7 @@ class UrlrewriteEdit extends BackendPage } /** - * @return \Magento\UrlRewrite\Test\Block\Catalog\Edit\Form + * @return \Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Edit\Form */ public function getFormBlock() { @@ -102,14 +102,6 @@ class UrlrewriteEdit extends BackendPage return $this->getBlockInstance('messagesBlock'); } - /** - * @return \Magento\Backend\Test\Block\Widget\Form - */ - public function getButtonBlock() - { - return $this->getBlockInstance('buttonBlock'); - } - /** * @return \Magento\Backend\Test\Block\FormPageActions */ @@ -119,7 +111,7 @@ class UrlrewriteEdit extends BackendPage } /** - * @return \Magento\UrlRewrite\Test\Block\Catalog\Product\Grid + * @return \Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Product\Grid */ public function getProductGridBlock() { @@ -127,10 +119,18 @@ class UrlrewriteEdit extends BackendPage } /** - * @return \Magento\UrlRewrite\Test\Block\Selector + * @return \Magento\UrlRewrite\Test\Block\Adminhtml\Selector */ public function getUrlRewriteTypeSelectorBlock() { return $this->getBlockInstance('urlRewriteTypeSelectorBlock'); } + + /** + * @return \Magento\UrlRewrite\Test\Block\Adminhtml\Cms\Page\Grid + */ + public function getCmsGridBlock() + { + return $this->getBlockInstance('cmsGridBlock'); + } } diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.xml index 0eea42abf335b411125876ff5cd1d8dabd47fdad..35c41fe1518e9807ae1e38308e351b9b084d5b64 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.xml +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteEdit.xml @@ -26,13 +26,13 @@ <page mca="admin/urlrewrite/edit"> <block> <name>treeBlock</name> - <class>Magento\UrlRewrite\Test\Block\Catalog\Category\Tree</class> - <locator>[data-ui-id="category-selector"]</locator> + <class>Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Category\Tree</class> + <locator>[id="page:main-container"]</locator> <strategy>css selector</strategy> </block> <block> <name>formBlock</name> - <class>Magento\UrlRewrite\Test\Block\Catalog\Edit\Form</class> + <class>Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Edit\Form</class> <locator>#edit_form</locator> <strategy>css selector</strategy> </block> @@ -42,12 +42,6 @@ <locator>#messages .messages</locator> <strategy>css selector</strategy> </block> - <block> - <name>buttonBlock</name> - <class>Magento\Backend\Test\Block\Widget\Form</class> - <locator>#messages .messages</locator> - <strategy>css selector</strategy> - </block> <block> <name>pageMainActions</name> <class>Magento\Backend\Test\Block\FormPageActions</class> @@ -56,20 +50,20 @@ </block> <block> <name>productGridBlock</name> - <class>Magento\UrlRewrite\Test\Block\Catalog\Product\Grid</class> + <class>Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Product\Grid</class> <locator>[id="productGrid"]</locator> <strategy>css selector</strategy> </block> <block> <name>urlRewriteTypeSelectorBlock</name> - <class>Magento\UrlRewrite\Test\Block\Selector</class> + <class>Magento\UrlRewrite\Test\Block\Adminhtml\Selector</class> <locator>[data-ui-id="urlrewrite-type-selector"]</locator> <strategy>css selector</strategy> </block> <block> - <name>urlRewriteTypeSelectorBlock</name> - <class>Magento\UrlRewrite\Test\Block\Selector</class> - <locator>[data-ui-id="urlrewrite-type-selector"]</locator> + <name>cmsGridBlock</name> + <class>Magento\UrlRewrite\Test\Block\Cms\Page\Grid</class> + <locator>#cmsPageGrid</locator> <strategy>css selector</strategy> </block> </page> diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteIndex.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteIndex.php index 452fbb6c4263c711828a24c0f36ddc2b995bb2af..900ecad85e1e20edd86f98a18995ebcfddee786e 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteIndex.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteIndex.php @@ -42,7 +42,7 @@ class UrlrewriteIndex extends BackendPage ], 'urlRedirectGrid' => [ 'name' => 'urlRedirectGrid', - 'class' => 'Magento\UrlRewrite\Test\Block\Catalog\Category\Grid', + 'class' => 'Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Category\Grid', 'locator' => '#urlrewriteGrid', 'strategy' => 'css selector', ], @@ -63,7 +63,7 @@ class UrlrewriteIndex extends BackendPage } /** - * @return \Magento\UrlRewrite\Test\Block\Catalog\Category\Grid + * @return \Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Category\Grid */ public function getUrlRedirectGrid() { diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteIndex.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteIndex.xml index 65cd2bcee95453c4b761d8241c47e6463a26562b..566d5370b3892ab7dab4af81008a0baf110f74ac 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteIndex.xml +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/Page/Adminhtml/UrlrewriteIndex.xml @@ -32,7 +32,7 @@ </block> <block> <name>urlRedirectGrid</name> - <class>Magento\UrlRewrite\Test\Block\Catalog\Category\Grid</class> + <class>Magento\UrlRewrite\Test\Block\Adminhtml\Catalog\Category\Grid</class> <locator>#urlrewriteGrid</locator> <strategy>css selector</strategy> </block> diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCmsPageRewriteEntityTest.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCmsPageRewriteEntityTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3bb8056bd214e3cd394514dfb83c03f51ba0edea --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCmsPageRewriteEntityTest.php @@ -0,0 +1,106 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\UrlRewrite\Test\TestCase; + +use Magento\UrlRewrite\Test\Page\Adminhtml\EditCmsPage; +use Mtf\TestCase\Injectable; +use Magento\Cms\Test\Fixture\CmsPage; +use Magento\UrlRewrite\Test\Fixture\UrlRewrite; +use Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteEdit; +use Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteIndex; + +/** + * Test Creation for CreateCmsPageRewriteEntity + * + * Test Flow: + * + * Preconditions + * 1. Create CMS-Page + * + * Steps + * 1. Login to backend as Admin + * 2. Go to the Marketing-> SEO & Search->URL Redirects + * 3. Click "Add Url Rewrite" button + * 4. Select "For CMS Page" in Create URL Rewrite dropdown + * 5. Select CMS page from preconditions in grid + * 6. Fill data according to data set + * 7. Save Rewrite + * 8. Perform all assertions + * + * @group URL_Rewrites_(PS) + * @ZephyrId MAGETWO-24847 + */ +class CreateCmsPageRewriteEntityTest extends Injectable +{ + /** + * Url rewrite index page + * + * @var UrlrewriteIndex + */ + protected $urlRewriteIndex; + + /** + * Url rewrite edit page + * + * @var UrlrewriteEdit + */ + protected $urlRewriteEdit; + + /** + * Inject pages + * + * @param UrlrewriteIndex $urlRewriteIndex + * @param UrlrewriteEdit $urlRewriteEdit + * @return void + */ + public function __inject( + UrlrewriteIndex $urlRewriteIndex, + UrlrewriteEdit $urlRewriteEdit + ) { + $this->urlRewriteIndex = $urlRewriteIndex; + $this->urlRewriteEdit = $urlRewriteEdit; + } + + /** + * Create CMS page rewrites + * + * @param CmsPage $cmsPage + * @param UrlRewrite $urlRewrite + * @return void + */ + public function testCmsPageRewrite(CmsPage $cmsPage, UrlRewrite $urlRewrite) + { + //Preconditions + $cmsPage->persist(); + //Steps + $this->urlRewriteIndex->open(); + $this->urlRewriteIndex->getPageActionsBlock()->addNew(); + $this->urlRewriteEdit->getUrlRewriteTypeSelectorBlock()->selectType('For CMS page'); + $filter = ['title' => $cmsPage->getTitle()]; + $this->urlRewriteEdit->getCmsGridBlock()->searchAndOpen($filter); + $this->urlRewriteEdit->getFormBlock()->fill($urlRewrite); + $this->urlRewriteEdit->getPageMainActions()->save(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCmsPageRewriteEntityTest/testCmsPageRewrite.csv b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCmsPageRewriteEntityTest/testCmsPageRewrite.csv new file mode 100644 index 0000000000000000000000000000000000000000..7edd14cc928acdc6f7f02af2592b12b233b0a3f8 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateCmsPageRewriteEntityTest/testCmsPageRewrite.csv @@ -0,0 +1,5 @@ +"cmsPage/dataSet";"urlRewrite/data/store_id";"urlRewrite/data/request_path";"urlRewrite/data/options";"urlRewrite/data/description";"isRequired";"constraint" +"default";"-";"request_path%isolation%";"No";"test_description_default";"Yes";"assertUrlRewriteSaveMessage, assertUrlRewriteCmsPageRedirect" +"default";"-";"request_path%isolation%.html";"Temporary (302)";"test description_302";"Yes";"assertUrlRewriteSaveMessage, assertUrlRewriteCmsPageRedirect" +"default";"-";"request_path%isolation%.htm";"Permanent (301)";"test description_301";"Yes";"assertUrlRewriteSaveMessage, assertUrlRewriteCmsPageRedirect" +"default";"-";"request_path%isolation%.aspx";"Permanent (301)";"test description_%isolation%";"Yes";"assertUrlRewriteSaveMessage, assertUrlRewriteCmsPageRedirect" diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest.php new file mode 100644 index 0000000000000000000000000000000000000000..14d5305487823bde357ac979ef76223e558cb366 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest.php @@ -0,0 +1,104 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\UrlRewrite\Test\TestCase; + +use Magento\Catalog\Test\Fixture\CatalogProductSimple; +use Mtf\TestCase\Injectable; +use Magento\UrlRewrite\Test\Fixture\UrlRewrite; +use Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteIndex; +use Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteEdit; + +/** + * Test Creation for Product URL Rewrites Entity + * + * Test Flow: + * Preconditions: + * 1. Create custom storeView + * 2. Create simple product + * + * Steps: + * 1. Open Backend + * 2. Go to Marketing->Url Redirects + * 3. Click "Add URL Rewrite" button + * 4. Select "For Product" from "Create URL Rewrite:" dropdown + * 5. Select created early product + * 6. Click "Skip Category Selection" button + * 7. Fill data according to dataSet + * 8. Perform all assertions + * + * @group URL_Rewrites_(PS) + * @ZephyrId MAGETWO-25150 + */ +class CreateProductUrlRewriteEntityTest extends Injectable +{ + /** + * Url rewrite index page + * + * @var UrlrewriteIndex + */ + protected $urlRewriteIndex; + + /** + * Url rewrite edit page + * + * @var UrlrewriteEdit + */ + protected $urlRewriteEdit; + + /** + * Prepare pages + * + * @param UrlrewriteIndex $urlRewriteIndex + * @param UrlrewriteEdit $urlRewriteEdit + * @return void + */ + public function __inject(UrlrewriteIndex $urlRewriteIndex, UrlrewriteEdit $urlRewriteEdit) + { + $this->urlRewriteIndex = $urlRewriteIndex; + $this->urlRewriteEdit = $urlRewriteEdit; + } + + /** + * Create product URL Rewrite + * + * @param CatalogProductSimple $product + * @param UrlRewrite $urlRewrite + * @return void + */ + public function testProductUrlRewrite(CatalogProductSimple $product, UrlRewrite $urlRewrite) + { + //Precondition + $product->persist(); + $filter = ['id' => $product->getId()]; + //Steps + $this->urlRewriteIndex->open(); + $this->urlRewriteIndex->getPageActionsBlock()->addNew(); + $this->urlRewriteEdit->getUrlRewriteTypeSelectorBlock()->selectType('For product'); + $this->urlRewriteEdit->getProductGridBlock()->searchAndOpen($filter); + $this->urlRewriteEdit->getTreeBlock()->skipCategorySelection(); + $this->urlRewriteEdit->getFormBlock()->fill($urlRewrite); + $this->urlRewriteEdit->getPageMainActions()->save(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest/testProductUrlRewrite.csv b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest/testProductUrlRewrite.csv new file mode 100644 index 0000000000000000000000000000000000000000..5c712f8e5b9083eb18aa38d10627b55d8aa5fe89 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/CreateProductUrlRewriteEntityTest/testProductUrlRewrite.csv @@ -0,0 +1,4 @@ +"product/dataSet";"urlRewrite/data/store_id";"urlRewrite/data/request_path";"urlRewrite/data/options";"urlRewrite/data/description";"constraint" +"default";"Main Website/Main Website Store/Default Store View";"test_%isolation%.html";"No";"description_%isolation%";"assertUrlRewriteSaveMessage" +"default";"Main Website/Main Website Store/Default Store View";"test_%isolation%.html";"Temporary (302)";"description_%isolation%";"assertUrlRewriteSaveMessage, assertUrlRewriteProductRedirect" +"default";"Main Website/Main Website Store/Default Store View";"test_%isolation%.html";"Permanent (301)";"description_%isolation%";"assertUrlRewriteSaveMessage, assertUrlRewriteProductRedirect" \ No newline at end of file diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCategoryUrlRewriteEntityTest.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCategoryUrlRewriteEntityTest.php new file mode 100644 index 0000000000000000000000000000000000000000..02943ff1a55ffa14c607a6f8bcd00d45083ae4e6 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCategoryUrlRewriteEntityTest.php @@ -0,0 +1,99 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\UrlRewrite\Test\TestCase; + +use Magento\UrlRewrite\Test\Fixture\UrlRewrite; +use Mtf\TestCase\Injectable; +use Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteEdit; +use Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteIndex; + +/** + * Test Creation for Delete Category URL Rewrites Entity + * + * Test Flow: + * Preconditions: + * 1. Create category + * 2. Create custom category UrlRewrite + * + * Steps: + * 1. Open Backend + * 2. Go to Marketing->URL Redirects + * 3. Search and open created URL Redirect + * 4. Delete URL Redirect + * 5. Perform all assertions + * + * @group URL_Rewrites_(PS) + * @ZephyrId MAGETWO-25086 + */ +class DeleteCategoryUrlRewriteEntityTest extends Injectable +{ + /** + * Url rewrite index page + * + * @var UrlrewriteIndex + */ + protected $urlRewriteIndex; + + /** + * Url rewrite edit page + * + * @var UrlrewriteEdit + */ + protected $urlRewriteEdit; + + /** + * Inject pages + * + * @param UrlrewriteIndex $urlRewriteIndex + * @param UrlrewriteEdit $urlRewriteEdit + * @return void + */ + public function __inject(UrlrewriteIndex $urlRewriteIndex, UrlrewriteEdit $urlRewriteEdit) + { + $this->urlRewriteIndex = $urlRewriteIndex; + $this->urlRewriteEdit = $urlRewriteEdit; + } + + /** + * Delete category Url Rewrite + * + * @param UrlRewrite $urlRewrite + * @return void + */ + public function testDeleteCategoryUrlRewrite(UrlRewrite $urlRewrite) + { + //Precondition + $urlRewrite->persist(); + //Steps + $this->urlRewriteIndex->open(); + if ($urlRewrite->getRequestPath()) { + $filter = ['request_path' => $urlRewrite->getRequestPath()]; + } else { + $filter = ['id_path' => $urlRewrite->getIdPath()]; + } + $this->urlRewriteIndex->getUrlRedirectGrid()->searchAndOpen($filter); + $this->urlRewriteEdit->getPageMainActions()->delete(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCategoryUrlRewriteEntityTest/testDeleteCategoryUrlRewrite.csv b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCategoryUrlRewriteEntityTest/testDeleteCategoryUrlRewrite.csv new file mode 100644 index 0000000000000000000000000000000000000000..d56bf6e45377b2df1b21a9615a87c02b3517f876 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteCategoryUrlRewriteEntityTest/testDeleteCategoryUrlRewrite.csv @@ -0,0 +1,3 @@ +"urlRewrite/data/id_path/entity";"urlRewrite/data/options";"urlRewrite/data/request_path";"constraint" +"category/%catalogCategory::default%";"No";"-";"assertUrlRewriteDeletedMessage, assertPageByUrlRewriteIsNotFound" +"category/%catalogCategory::default%";"No";"example%isolation%.html";"assertUrlRewriteDeletedMessage, assertPageByUrlRewriteIsNotFound" diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteProductUrlRewriteEntityTest.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteProductUrlRewriteEntityTest.php index 6b7b8baa82b73ca62d700e53f8b3afaf63964f1f..1c0765dcd669a9fcfd8892c18e7e8e9202631ef3 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteProductUrlRewriteEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteProductUrlRewriteEntityTest.php @@ -28,7 +28,6 @@ use Magento\Catalog\Test\Fixture\CatalogProductSimple; use Magento\UrlRewrite\Test\Fixture\UrlRewrite; use Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteEdit; use Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteIndex; -use Mtf\Fixture\FixtureFactory; use Mtf\TestCase\Injectable; /** @@ -66,35 +65,18 @@ class DeleteProductUrlRewriteEntityTest extends Injectable protected $urlRewriteEdit; /** - * Prepare dataSets and pages + * Prepare pages * - * @param FixtureFactory $fixtureFactory * @param UrlrewriteIndex $urlRewriteIndex * @param UrlrewriteEdit $urlRewriteEdit - * @return array + * @return void */ public function __inject( - FixtureFactory $fixtureFactory, UrlrewriteIndex $urlRewriteIndex, UrlrewriteEdit $urlRewriteEdit ) { - /** @var CatalogProductSimple $product */ - $product = $fixtureFactory->createByCode('catalogProductSimple', ['dataSet' => 'product_without_category']); - $product->persist(); - - /** @var UrlRewrite $productRedirect */ - $productRedirect = $fixtureFactory->createByCode( - 'urlRewrite', - [ - 'dataSet' => 'default', - 'data' => ['id_path' => 'product/' . $product->getId()] - ] - ); - $productRedirect->persist(); - $this->urlRewriteIndex = $urlRewriteIndex; $this->urlRewriteEdit = $urlRewriteEdit; - return ['productRedirect' => $productRedirect]; } /** @@ -105,6 +87,9 @@ class DeleteProductUrlRewriteEntityTest extends Injectable */ public function testDeleteProductUrlRewrite(UrlRewrite $productRedirect) { + // Precondition + $productRedirect->persist(); + // Steps $this->urlRewriteIndex->open(); $filter = ['request_path' => $productRedirect->getRequestPath()]; $this->urlRewriteIndex->getUrlRedirectGrid()->searchAndOpen($filter); diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteProductUrlRewriteEntityTest/testDeleteProductUrlRewrite.csv b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteProductUrlRewriteEntityTest/testDeleteProductUrlRewrite.csv index a0af0ee8456176c7a6ad3413c1c9f39546360b48..102c7b7f215b9acef0ecf7afa19d2e719cc50da2 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteProductUrlRewriteEntityTest/testDeleteProductUrlRewrite.csv +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/DeleteProductUrlRewriteEntityTest/testDeleteProductUrlRewrite.csv @@ -1,2 +1,2 @@ -"constraint" -"assertUrlRewriteDeletedMessage, assertUrlRewriteNotInGrid, assertPageByUrlRewriteIsNotFound" +"productRedirect/dataSet";"productRedirect/data/id_path/entity";"constraint" +"default";"product/%catalogProductSimple::100_dollar_product%";"assertUrlRewriteDeletedMessage, assertUrlRewriteNotInGrid, assertPageByUrlRewriteIsNotFound" diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest.php index f27c54428de4115be349fb8145eb91a55b25853c..ae00d41bc8b458067df41f5abc3432dfabcae4aa 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateCategoryUrlRewriteEntityTest.php @@ -89,7 +89,7 @@ class UpdateCategoryUrlRewriteEntityTest extends Injectable 'urlRewrite', [ 'dataSet' => 'default', - 'data' => ['id_path' => 'category/' . $category->getId()] + 'data' => ['id_path' => ['category/' . $category->getId()]] ] ); $categoryRedirect->persist(); diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateProductUrlRewriteEntityTest.php b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateProductUrlRewriteEntityTest.php index 88e91acf55ca673c9c9aec9150403e8971007884..bead2feb702647c17a7fe8dbbe67d25ee6f6928d 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateProductUrlRewriteEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateProductUrlRewriteEntityTest.php @@ -97,7 +97,7 @@ class UpdateProductUrlRewriteEntityTest extends Injectable 'urlRewrite', [ 'dataSet' => 'default', - 'data' => ['id_path' => 'product/' . $urlRewrite->getProductId()] + 'data' => ['id_path' => [$urlRewrite->getIdPath()]] ] ); $productRedirect->persist(); diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateProductUrlRewriteEntityTest/testUpdateProductUrlRewrite.csv b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateProductUrlRewriteEntityTest/testUpdateProductUrlRewrite.csv index a2149c6d1a899adce9138b1ddad118dad0cc5a28..4a76b6aaf184a03e856300be39f16cfe1b90a5fc 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateProductUrlRewriteEntityTest/testUpdateProductUrlRewrite.csv +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/TestCase/UpdateProductUrlRewriteEntityTest/testUpdateProductUrlRewrite.csv @@ -1,3 +1,2 @@ -"urlRewrite/data/product_id/dataSet";"urlRewrite/data/store_id";"urlRewrite/data/request_path";"urlRewrite/data/options";"urlRewrite/data/description";"isRequired";"constraint" -"catalogProductSimple::100_dollar_product";"Main Website/Main Website Store/Default Store View";"test_%isolation%.html";"Temporary (302)";"description_%isolation%";"Yes";"assertUrlRewriteSaveMessage, assertProductUrlAvailableOnTheFront" -"catalogProductSimple::100_dollar_product";"Main Website/Main Website Store/Custom Store View";"test_%isolation%.php";"No";"description_%isolation%";"No";"assertUrlRewriteSaveMessage, assertProductUrlAvailableOnTheFront" \ No newline at end of file +"urlRewrite/data/id_path/entity";"urlRewrite/data/store_id";"urlRewrite/data/request_path";"urlRewrite/data/options";"urlRewrite/data/description";"isRequired";"constraint" +"product/%catalogProductSimple::100_dollar_product%";"Main Website/Main Website Store/Default Store View";"test_%isolation%.html";"Temporary (302)";"description_%isolation%";"Yes";"assertUrlRewriteSaveMessage, assertUrlRewriteProductRedirect" diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/constraint.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/constraint.xml index 60b2f1620990d65db1753d04b003d960fc0b7319..cba450836dead5a8d33fa44a8cda5badd4038892 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/constraint.xml +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/constraint.xml @@ -37,7 +37,7 @@ <assertUrlRewriteCategoryRedirect module="Magento_UrlRewrite"> <severeness>low</severeness> </assertUrlRewriteCategoryRedirect> - <assertProductUrlAvailableOnTheFront module="Magento_UrlRewrite"> + <assertUrlRewriteProductRedirect module="Magento_UrlRewrite"> <severeness>low</severeness> <require> <urlRewrite class="Magento\UrlRewrite\Test\Fixture\UrlRewrite"/> @@ -45,7 +45,7 @@ <product class="Mtf\Fixture\FixtureInterface"/> <browser class="Mtf\Client\Browser"/> </require> - </assertProductUrlAvailableOnTheFront> + </assertUrlRewriteProductRedirect> <assertUrlRewriteDeletedMessage module="Magento_UrlRewrite"> <severeness>low</severeness> <require> @@ -67,4 +67,12 @@ <browser class="Mtf\Client\Browser"/> </require> </assertPageByUrlRewriteIsNotFound> + <assertUrlRewriteCmsPageRedirect module="Magento_UrlRewrite"> + <severeness>low</severeness> + <require> + <cmsPage class="Magento\Cms\Test\Fixture\CmsPage"/> + <urlRewrite class="Magento\UrlRewrite\Test\Fixture\UrlRewrite"/> + <browser class="Mtf\Client\Browser"/> + </require> + </assertUrlRewriteCmsPageRedirect> </constraint> diff --git a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/page.xml b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/page.xml index 0e1e33bb730f44a15a9209cbd00d91b71bf7999b..d8be3b72836dde3715635803f25982e39451ebde 100644 --- a/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/page.xml +++ b/dev/tests/functional/tests/app/Magento/UrlRewrite/Test/etc/global/page.xml @@ -34,4 +34,9 @@ <area>adminhtml</area> <class>Magento\UrlRewrite\Test\Page\Adminhtml\UrlrewriteEdit</class> </urlrewriteEdit> + <editCmsPage> + <mca>admin/urlrewrite/edit/cms_page</mca> + <area>adminhtml</area> + <class>Magento\UrlRewrite\Test\Page\Adminhtml\EditCmsPage</class> + </editCmsPage> </page> diff --git a/dev/tests/integration/phpunit.xml.dist b/dev/tests/integration/phpunit.xml.dist index 51962f3c709996f811a768cd7ef8df18964ff1e2..2f406070a79352973b0856157a0a62ba33d08ea5 100644 --- a/dev/tests/integration/phpunit.xml.dist +++ b/dev/tests/integration/phpunit.xml.dist @@ -40,7 +40,7 @@ <filter> <whitelist addUncoveredFilesFromWhiteList="true"> <directory suffix=".php">../../../app/code/Magento</directory> - <directory suffix=".php">../../../lib/Magento</directory> + <directory suffix=".php">../../../lib/internal/Magento</directory> <exclude> <directory suffix=".php">../../../app/code/Magento/*/sql</directory> <directory suffix=".php">../../../app/code/Magento/*/data</directory> diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/AbstractTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/AbstractTest.php index 15ecca48c353e87ee28bc06b6c71e4c060d76af0..2a13632919c6782165b5236c4003f008459827fd 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/AbstractTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Product/AbstractTest.php @@ -26,8 +26,7 @@ namespace Magento\Catalog\Block\Product; /** * Test class for \Magento\Catalog\Block\Product\Abstract. * - * @magentoDataFixture Magento/Catalog/_files/product_simple.php - * @magentoDataFixture Magento/Catalog/_files/product_image.php + * @magentoDataFixture Magento/Catalog/_files/product_with_image.php */ class AbstractTest extends \PHPUnit_Framework_TestCase { @@ -144,7 +143,7 @@ class AbstractTest extends \PHPUnit_Framework_TestCase public function testGetImageLabel() { - $this->assertEquals($this->_product->getName(), $this->_block->getImageLabel()); + $this->assertEquals('Image Alt Text', $this->_block->getImageLabel()); } public function testGetProductUrl() diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/TierpriceTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/TierpriceTest.php index 7667a487a686df189c01995f87de19b9e57f92ab..00e57c0ff3055bdcb8d57eaf8ed5ede21a339ab5 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/TierpriceTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Attribute/Backend/TierpriceTest.php @@ -119,7 +119,7 @@ class TierpriceTest extends \PHPUnit_Framework_TestCase $this->_model->afterLoad($product); $price = $product->getTierPrice(); $this->assertNotEmpty($price); - $this->assertEquals(2, count($price)); + $this->assertEquals(3, count($price)); } /** diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/PriceTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/PriceTest.php index e50cb153a33c8ae9d807cba39a6ec6de88d85f7c..1b75531f4a9052dca8224eb9e1da7941edc34bd7 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/PriceTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/Type/PriceTest.php @@ -111,7 +111,7 @@ class PriceTest extends \PHPUnit_Framework_TestCase ); $product->load(1); // fixture - $this->assertEquals(2, $this->_model->getTierPriceCount($product)); + $this->assertEquals(3, $this->_model->getTierPriceCount($product)); } public function testGetFormatedTierPrice() diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute.php new file mode 100644 index 0000000000000000000000000000000000000000..8cdc42ac3ff53de82faec3a913cc17e9c5a31c21 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute.php @@ -0,0 +1,61 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** @var $product \Magento\Catalog\Model\Product */ +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + +/** @var \Magento\Eav\Model\Entity\Attribute\Set $attributeSet */ +$attributeSet = $objectManager->create('\Magento\Eav\Model\Entity\Attribute\Set'); + +$entityType = $objectManager->create('Magento\Eav\Model\Entity\Type')->loadByCode('catalog_product'); +$defaultSetId = $objectManager->create('\Magento\Catalog\Model\Product')->getDefaultAttributeSetid(); + +$data = [ + 'attribute_set_name' => 'custom attribute set 531', + 'entity_type_id' => $entityType->getId(), + 'sort_order' => 200, +]; + +$attributeSet->setData($data); +$attributeSet->validate(); +$attributeSet->save(); +$attributeSet->initFromSkeleton($defaultSetId); +$attributeSet->save(); + +$attributeData = array( + 'entity_type_id' => $entityType->getId(), + 'attribute_code' => 'funny_image', + 'frontend_input' => 'media_image', + 'frontend_label' => 'Funny image', + 'backend_type' => 'varchar', + 'is_required' => 0, + 'is_user_defined' => 1, + 'attribute_set_id' => $attributeSet->getId(), + 'attribute_group_id' => $attributeSet->getDefaultGroupId(), +); + +/** @var \Magento\Catalog\Model\Entity\Attribute $attribute */ +$attribute = $objectManager->create('\Magento\Catalog\Model\Entity\Attribute'); +$attribute->setData($attributeData); +$attribute->save(); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..fcf22a8366a62ce3c5c03a6660e7f3afbf5d1ce0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/attribute_set_with_image_attribute_rollback.php @@ -0,0 +1,54 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** @var $product \Magento\Catalog\Model\Product */ +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + +$entityType = $objectManager->create('Magento\Eav\Model\Entity\Type')->loadByCode('catalog_product'); + +// remove attribute + +/** @var \Magento\Catalog\Model\Resource\Product\Attribute\Collection $attributeCollection */ +$attributeCollection = $objectManager->create('\Magento\Catalog\Model\Resource\Product\Attribute\Collection'); +$attributeCollection->setFrontendInputTypeFilter('media_image'); +$attributeCollection->setCodeFilter('funny_image'); +$attributeCollection->setEntityTypeFilter($entityType->getId()); +$attributeCollection->setPageSize(1); +$attributeCollection->load(); +$attribute = $attributeCollection->fetchItem(); +$attribute->delete(); + +// remove attribute set + +/** @var \Magento\Eav\Model\Resource\Entity\Attribute\Set\Collection $attributeSetCollection */ +$attributeSetCollection = $objectManager->create('\Magento\Eav\Model\Resource\Entity\Attribute\Set\Collection'); +$attributeSetCollection->addFilter('attribute_set_name', 'custom attribute set 531'); +$attributeSetCollection->addFilter('entity_type_id', $entityType->getId()); +$attributeSetCollection->setOrder('attribute_set_id'); // descending is default value +$attributeSetCollection->setPageSize(1); +$attributeSetCollection->load(); + +/** @var \Magento\Eav\Model\Entity\Attribute\Set $attributeSet */ +$attributeSet = $attributeSetCollection->fetchItem(); +$attributeSet->delete(); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_group_prices.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_group_prices.php new file mode 100644 index 0000000000000000000000000000000000000000..f87b3b5af2c4e69ff81a97b23793b649de0fdfd6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_group_prices.php @@ -0,0 +1,68 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** @var $product \Magento\Catalog\Model\Product */ +$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create('Magento\Catalog\Model\Product'); +$product->isObjectNew(true); +$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) + ->setId(1) + ->setAttributeSetId(4) + ->setWebsiteIds(array(1)) + ->setName('Simple Product Group Price') + ->setSku('simple_with_group_price') + ->setPrice(10) + ->setWeight(1) + ->setShortDescription("Short description") + ->setTaxClassId(0) + ->setGroupPrice( + array( + array( + 'website_id' => 0, + 'cust_group' => \Magento\Customer\Service\V1\CustomerGroupServiceInterface::NOT_LOGGED_IN_ID, + 'price' => 9, + ), + array( + 'website_id' => 0, + 'cust_group' => \Magento\Customer\Service\V1\CustomerGroupServiceInterface::CUST_GROUP_ALL, + 'price' => 7, + ), + ) + ) + ->setDescription('Description with <b>html tag</b>') + ->setMetaTitle('meta title') + ->setMetaKeyword('meta keyword') + ->setMetaDescription('meta description') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setCategoryIds(array(2)) + ->setStockData( + array( + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1, + ) + ) + ->save(); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_group_prices_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_group_prices_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..6ffb72acf9bb123fe18604ce907ad2648eb8c84e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_group_prices_rollback.php @@ -0,0 +1,39 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** @var \Magento\Framework\Registry $registry */ +$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry'); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var $product \Magento\Catalog\Model\Product */ +$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product'); +$product->load(1); +if ($product->getId()) { + $product->delete(); +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_image.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_image.php index a4ba42c127bf99ab352f19d3e4ed423cdcd791e3..a433616ce8041fd594fa0eae0678066ee6115cd5 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_image.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_image.php @@ -23,11 +23,18 @@ */ $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); -$mediaPath = $objectManager->get('Magento\Framework\App\Filesystem') - ->getPath(\Magento\Framework\App\Filesystem::MEDIA_DIR); -$additionalPath = $objectManager->get('Magento\Catalog\Model\Product\Media\Config')->getBaseMediaPath(); -$dir = $mediaPath . '/' . $additionalPath . '/m/a'; -if (!is_dir($dir)) { - mkdir($dir, 0777, true); -} -copy(__DIR__ . '/magento_image.jpg', $dir . '/magento_image.jpg'); +/** @var $mediaConfig \Magento\Catalog\Model\Product\Media\Config */ +$mediaConfig = $objectManager->get('Magento\Catalog\Model\Product\Media\Config'); + +/** @var $mediaDirectory \Magento\Framework\Filesystem\Directory\WriteInterface */ +$mediaDirectory = $objectManager->get('Magento\Framework\App\Filesystem') + ->getDirectoryWrite(\Magento\Framework\App\Filesystem::MEDIA_DIR); +$targetDirPath = $mediaConfig->getBaseMediaPath() . str_replace('/', DIRECTORY_SEPARATOR, '/m/a/'); +$targetTmpDirPath = $mediaConfig->getBaseTmpMediaPath() . str_replace('/', DIRECTORY_SEPARATOR, '/m/a/'); +$mediaDirectory->create($targetDirPath); +$mediaDirectory->create($targetTmpDirPath); + +$targetTmpFilePath = $mediaDirectory->getAbsolutePath() . DIRECTORY_SEPARATOR . $targetTmpDirPath + . DIRECTORY_SEPARATOR . 'magento_image.jpg'; +copy(__DIR__ . '/magento_image.jpg', $targetTmpFilePath); +// Copying the image to target dir is not necessary because during product save, it will be moved there from tmp dir diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple.php index d9cd3b8ea96ab884b113c179a1f044c632a0fb22..ab660709210bc8d248a0103a7692cce21637af05 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple.php @@ -50,6 +50,12 @@ $product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) 'price_qty' => 5, 'price' => 5, ), + array( + 'website_id' => 0, + 'cust_group' => \Magento\Customer\Service\V1\CustomerGroupServiceInterface::NOT_LOGGED_IN_ID, + 'price_qty' => 3, + 'price' => 5, + ), ) ) ->setDescription('Description with <b>html tag</b>') diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_image.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_image.php index 925440c9dd4c649ff15c0ee91c4a436c4f4bf99d..5e37963002baead68689a0efe878d5c5ea5d83d2 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_image.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_image.php @@ -23,33 +23,20 @@ */ require __DIR__ . '/product_image.php'; +require __DIR__ . '/product_simple.php'; /** @var $product \Magento\Catalog\Model\Product */ $product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product'); -$product->setTypeId( - \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE -)->setId( - 1 -)->setAttributeSetId( - 4 -)->setWebsiteIds( - array(1) -)->setName( - 'Simple Product' -)->setSku( - 'simple' -)->setPrice( - 10 -)->setDescription( - 'Description with <b>html tag</b>' -)->setImage( - '/m/a/magento_image.jpg' -)->setSmallImage( - '/m/a/magento_image.jpg' -)->setThumbnail( - '/m/a/magento_image.jpg' -)->setVisibility( - \Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH -)->setStatus( - \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED -)->save(); +$product->load(1) + ->setStoreId(0) + ->setImage('/m/a/magento_image.jpg') + ->setSmallImage('/m/a/magento_image.jpg') + ->setThumbnail('/m/a/magento_image.jpg') + ->setData('media_gallery', array('images' => array( + array( + 'file' => '/m/a/magento_image.jpg', + 'position' => 1, + 'label' => 'Image Alt Text', + 'disabled' => 0, + ), + )))->save(); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_image_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_image_rollback.php index 5d0c89be0cdacdfa9f3e3f8150b53c37758d2992..6419bc360aa41b4c5535a003cda86b2ab28932a0 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_image_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_image_rollback.php @@ -22,4 +22,5 @@ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +require __DIR__ . '/product_simple_rollback.php'; require __DIR__ . '/product_image_rollback.php'; diff --git a/dev/tests/integration/testsuite/Magento/Store/_files/website.php b/dev/tests/integration/testsuite/Magento/Store/_files/website.php new file mode 100644 index 0000000000000000000000000000000000000000..b021dfbc3ca8ced9e62835be1cd7732ad24502e3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Store/_files/website.php @@ -0,0 +1,28 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** @var $website \Magento\Store\Model\Website */ +$website = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Store\Model\Website'); +$website->setData(array('code' => 'test', 'name' => 'Test Website', 'default_group_id' => '1', 'is_default' => '0')); +$website->save(); diff --git a/dev/tests/integration/testsuite/Magento/Store/_files/website_rollback.php b/dev/tests/integration/testsuite/Magento/Store/_files/website_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..16b7a94f7065f46f05ebfacd7d57c525c1f2b285 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Store/_files/website_rollback.php @@ -0,0 +1,41 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +/** @var \Magento\Framework\Registry $registry */ +$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry'); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var \Magento\Store\Model\Website $website */ +$website = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Store\Model\Website'); +$website->load('test'); + +if ($website->getId()) { + $website->delete(); +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); + diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php index 30dca15ae97320a61aeb78a50d5f719359cd13c0..0b0247dbb6dda07963ad9adc286ebd8fcc53269e 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SetupUtil.php @@ -46,6 +46,7 @@ class SetupUtil ]; const TAX_RATE_TX = 'tax_rate_tx'; + const TAX_RATE_AUSTIN = 'tax_rate_austin'; const TAX_RATE_SHIPPING = 'tax_rate_shipping'; const TAX_STORE_RATE = 'tax_store_rate'; const REGION_TX = '57'; @@ -69,6 +70,16 @@ class SetupUtil ], 'id' => null, ], + self::TAX_RATE_AUSTIN => [ + 'data' => [ + 'tax_country_id' => self::COUNTRY_US, + 'tax_region_id' => self::REGION_TX, + 'tax_postcode' => self::AUSTIN_POST_CODE, + 'code' => self::TAX_RATE_AUSTIN, + 'rate' => '5', + ], + 'id' => null, + ], self::TAX_RATE_SHIPPING => [ 'data' => [ 'tax_country_id' => self::COUNTRY_US, @@ -301,14 +312,12 @@ class SetupUtil * * @return array */ - protected function getTaxRateIds() + protected function getDefaultTaxRateIds() { - $taxRateIds = []; - foreach ($this->taxRates as $taxRateName => $taxRate) { - if ($taxRateName != self::TAX_RATE_SHIPPING) { - $taxRateIds[] = $taxRate['id']; - } - } + $taxRateIds = [ + $this->taxRates[self::TAX_RATE_TX]['id'], + $this->taxRates[self::TAX_STORE_RATE]['id'], + ]; return $taxRateIds; } @@ -353,7 +362,7 @@ class SetupUtil 'position' => '0', 'tax_customer_class' => $customerClassIds, 'tax_product_class' => $this->getProductTaxClassIds(), - 'tax_rate' => $this->getTaxRateIds(), + 'tax_rate' => $this->getDefaultTaxRateIds(), ]; //Create tax rules diff --git a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/TaxTest.php b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/TaxTest.php index 301e0d8d8190a3701e8b48e38985e0f2e6bf4bb9..478f2549796492b75965cca29bba44d9ae6e4ad3 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/TaxTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/TaxTest.php @@ -51,6 +51,7 @@ class TaxTest extends \PHPUnit_Framework_TestCase * @magentoDataFixture Magento/Tax/_files/tax_classes.php * @magentoDataFixture Magento/Customer/_files/customer_group.php * @magentoDbIsolation enabled + * @magentoAppIsolation enabled */ public function testCollect() { @@ -257,12 +258,12 @@ class TaxTest extends \PHPUnit_Framework_TestCase * @param array $quoteData * @param array $expectedResults * @magentoDbIsolation enabled + * @magentoAppIsolation enabled * @dataProvider taxDataProvider * @return void */ public function testTaxCalculation($configData, $quoteData, $expectedResults) { - Bootstrap::getInstance()->reinitialize(); /** @var \Magento\Framework\ObjectManager $objectManager */ $objectManager = Bootstrap::getObjectManager(); diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_before_discount.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_before_discount.php index 9eaffb5eb7526cf2a2c3f9e46a4771153473de62..845791b66daef5fda469df55323cddd31a5c0cdd 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_before_discount.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_before_discount.php @@ -28,6 +28,7 @@ use Magento\Tax\Model\Sales\Total\Quote\SetupUtil; $taxCalculationData['excluding_tax_apply_tax_before_discount'] = [ 'config_data' => [ SetupUtil::CONFIG_OVERRIDES => [ + Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT => 0, Config::CONFIG_XML_PATH_SHIPPING_TAX_CLASS => SetupUtil::PRODUCT_TAX_CLASS_1, ], SetupUtil::TAX_RATE_OVERRIDES => [ diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_disabled.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_disabled.php new file mode 100644 index 0000000000000000000000000000000000000000..f79dafa544da808a520f4f4108b62d448fdcfc25 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_disabled.php @@ -0,0 +1,107 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +use Magento\Tax\Model\Config; +use Magento\Tax\Model\Sales\Total\Quote\SetupUtil; +use Magento\Tax\Model\Calculation; + +$taxCalculationData['including_tax_cross_border_trade_disabled'] = [ + 'config_data' => [ + SetupUtil::CONFIG_OVERRIDES => [ + Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT => 1, + Config::CONFIG_XML_PATH_PRICE_INCLUDES_TAX => 1, + Config::CONFIG_XML_PATH_CROSS_BORDER_TRADE_ENABLED => 0, + Config::XML_PATH_ALGORITHM => Calculation::CALC_UNIT_BASE, + ], + SetupUtil::TAX_RATE_OVERRIDES => [ + SetupUtil::TAX_RATE_TX => 20, + SetupUtil::TAX_STORE_RATE => 10, + ], + SetupUtil::TAX_RULE_OVERRIDES => [ + ], + ], + 'quote_data' => [ + 'billing_address' => [ + 'region_id' => SetupUtil::REGION_TX, + ], + 'shipping_address' => [ + 'region_id' => SetupUtil::REGION_TX, + ], + 'items' => [ + [ + 'sku' => 'simple1', + 'price' => 9.99, + 'qty' => 2, + ], + ], + ], + 'expected_results' => [ + 'address_data' => [ + 'subtotal' => 18.16, + 'base_subtotal' => 18.16, + 'subtotal_incl_tax' => 21.80, + 'base_subtotal_incl_tax' => 21.80, + 'tax_amount' => 3.64, + 'base_tax_amount' => 3.64, + 'shipping_amount' => 0, + 'base_shipping_amount' => 0, + 'shipping_incl_tax' => 0, + 'base_shipping_incl_tax' => 0, + 'shipping_taxable' => 0, + 'base_shipping_taxable' => 0, + 'shipping_tax_amount' => 0, + 'base_shipping_tax_amount' => 0, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'hidden_tax_amount' => 0, + 'base_hidden_tax_amount' => 0, + 'shipping_hidden_tax_amount' => 0, + 'base_shipping_hidden_tax_amount' => 0, + 'grand_total' => 21.80, + 'base_grand_total' => 21.80, + ], + 'items_data' => [ + 'simple1' => [ + 'row_total' => 18.16, + 'base_row_total' => 18.16, + 'taxable_amount' => 10.90, + 'base_taxable_amount' => 10.90, + 'tax_percent' => 20, + 'price' => 9.08, + 'base_price' => 9.08, + 'price_incl_tax' => 10.90, + 'base_price_incl_tax' => 10.90, + 'row_total_incl_tax' => 21.80, + 'base_row_total_incl_tax' => 21.80, + 'tax_amount' => 3.64, + 'base_tax_amount' => 3.64, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'discount_percent' => 0, + 'hidden_tax_amount' => 0, + 'base_hidden_tax_amount' => 0, + ], + ], + ], +]; \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_enabled.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_enabled.php new file mode 100644 index 0000000000000000000000000000000000000000..c1875cec5a1b265439a56fef108f6bd493b87297 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_enabled.php @@ -0,0 +1,107 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +use Magento\Tax\Model\Config; +use Magento\Tax\Model\Sales\Total\Quote\SetupUtil; +use Magento\Tax\Model\Calculation; + +$taxCalculationData['including_tax_cross_border_trade_enabled'] = [ + 'config_data' => [ + SetupUtil::CONFIG_OVERRIDES => [ + Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT => 1, + Config::CONFIG_XML_PATH_PRICE_INCLUDES_TAX => 1, + Config::CONFIG_XML_PATH_CROSS_BORDER_TRADE_ENABLED => 1, + Config::XML_PATH_ALGORITHM => Calculation::CALC_UNIT_BASE, + ], + SetupUtil::TAX_RATE_OVERRIDES => [ + SetupUtil::TAX_RATE_TX => 20, + SetupUtil::TAX_STORE_RATE => 10, + ], + SetupUtil::TAX_RULE_OVERRIDES => [ + ], + ], + 'quote_data' => [ + 'billing_address' => [ + 'region_id' => SetupUtil::REGION_TX, + ], + 'shipping_address' => [ + 'region_id' => SetupUtil::REGION_TX, + ], + 'items' => [ + [ + 'sku' => 'simple1', + 'price' => 9.99, + 'qty' => 2, + ], + ], + ], + 'expected_results' => [ + 'address_data' => [ + 'subtotal' => 16.64, + 'base_subtotal' => 16.64, + 'subtotal_incl_tax' => 19.98, + 'base_subtotal_incl_tax' => 19.98, + 'tax_amount' => 3.34, + 'base_tax_amount' => 3.34, + 'shipping_amount' => 0, + 'base_shipping_amount' => 0, + 'shipping_incl_tax' => 0, + 'base_shipping_incl_tax' => 0, + 'shipping_taxable' => 0, + 'base_shipping_taxable' => 0, + 'shipping_tax_amount' => 0, + 'base_shipping_tax_amount' => 0, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'hidden_tax_amount' => 0, + 'base_hidden_tax_amount' => 0, + 'shipping_hidden_tax_amount' => 0, + 'base_shipping_hidden_tax_amount' => 0, + 'grand_total' => 19.98, + 'base_grand_total' => 19.98, + ], + 'items_data' => [ + 'simple1' => [ + 'row_total' => 16.64, + 'base_row_total' => 16.64, + 'taxable_amount' => 9.99, + 'base_taxable_amount' => 9.99, + 'tax_percent' => 20, + 'price' => 8.32, + 'base_price' => 8.32, + 'price_incl_tax' => 9.99, + 'base_price_incl_tax' => 9.99, + 'row_total_incl_tax' => 19.98, + 'base_row_total_incl_tax' => 19.98, + 'tax_amount' => 3.34, + 'base_tax_amount' => 3.34, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'discount_percent' => 0, + 'hidden_tax_amount' => 0, + 'base_hidden_tax_amount' => 0, + ], + ], + ], +]; \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_no.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_no.php new file mode 100644 index 0000000000000000000000000000000000000000..6578ab2fdb1e7be7ba28bbd4c40e3e6c725465fa --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_no.php @@ -0,0 +1,152 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +use Magento\Tax\Model\Config; +use Magento\Tax\Model\Sales\Total\Quote\SetupUtil; +use Magento\Tax\Model\Calculation; + +/** + * This test case test the scenario where there are two tax rules with different priority + * The calculate_subtotal field is off, the second tax rate will be applied on top of first + * tax rate. This testcases uses total based calculation. + */ +$taxCalculationData['multi_tax_rule_total_calculate_subtotal_no'] = [ + 'config_data' => [ + SetupUtil::CONFIG_OVERRIDES => [ + Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT => 1, + Config::XML_PATH_ALGORITHM => Calculation::CALC_TOTAL_BASE, + ], + SetupUtil::TAX_RATE_OVERRIDES => [ + SetupUtil::TAX_RATE_TX => 7.5, + SetupUtil::TAX_RATE_AUSTIN => 5.5, + ], + SetupUtil::TAX_RULE_OVERRIDES => [ + [ + //tax rule 1 for product + 'code' => 'Product Tax Rule TX', + 'tax_product_class' => [SetupUtil::PRODUCT_TAX_CLASS_1], + 'tax_rate' => [SetupUtil::TAX_RATE_TX], + 'priority' => 1, + ], + [ + //tax rule 2 for product + 'code' => 'Product Tax Rule AUSTIN', + 'tax_product_class' => [SetupUtil::PRODUCT_TAX_CLASS_1], + 'tax_rate' => [SetupUtil::TAX_RATE_AUSTIN], + 'priority' => 2, + 'calculate_subtotal' => 0, + ], + ], + ], + 'quote_data' => [ + 'billing_address' => [ + 'region_id' => SetupUtil::REGION_TX, + ], + 'shipping_address' => [ + 'region_id' => SetupUtil::REGION_TX, + 'tax_postcode' => SetupUtil::AUSTIN_POST_CODE, + ], + 'items' => [ + [ + 'sku' => 'simple1', + 'price' => 1, + 'qty' => 10, + ], + ], + ], + 'expected_results' => [ + 'address_data' => [ + 'subtotal' => 10, + 'base_subtotal' => 10, + 'subtotal_incl_tax' => 11.34, + 'base_subtotal_incl_tax' => 11.34, + 'tax_amount' => 1.34, + 'base_tax_amount' => 1.34, + 'shipping_amount' => 0, + 'base_shipping_amount' => 0, + 'shipping_incl_tax' => 0, + 'base_shipping_incl_tax' => 0, + 'shipping_taxable' => 0, + 'base_shipping_taxable' => 0, + 'shipping_tax_amount' => 0, + 'base_shipping_tax_amount' => 0, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'hidden_tax_amount' => 0, + 'base_hidden_tax_amount' => 0, + 'shipping_hidden_tax_amount' => 0, + 'base_shipping_hidden_tax_amount' => 0, + 'grand_total' => 11.34, + 'base_grand_total' => 11.34, + 'applied_taxes' => [ + SetupUtil::TAX_RATE_TX => [ + 'percent' => 7.5, + 'amount' => 0.75, + 'base_amount' => 0.75, + 'rates' => [ + [ + 'code' => SetupUtil::TAX_RATE_TX, + 'title' => SetupUtil::TAX_RATE_TX, + 'percent' => 7.5, + ], + ], + ], + SetupUtil::TAX_RATE_AUSTIN => [ + 'percent' => 5.9125, + 'amount' => 0.59, + 'base_amount' => 0.59, + 'rates' => [ + [ + 'code' => SetupUtil::TAX_RATE_AUSTIN, + 'title' => SetupUtil::TAX_RATE_AUSTIN, + 'percent' => 5.5, + ], + ], + ], + ], + ], + 'items_data' => [ + 'simple1' => [ + 'row_total' => 10, + 'base_row_total' => 10, + 'taxable_amount' => 10, + 'base_taxable_amount' => 10, + 'tax_percent' => 13.4125, + 'price' => 1, + 'base_price' => 1, + 'price_incl_tax' => 1.13, + 'base_price_incl_tax' => 1.13, + 'row_total_incl_tax' => 11.34, + 'base_row_total_incl_tax' => 11.34, + 'tax_amount' => 1.34, + 'base_tax_amount' => 1.34, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'discount_percent' => 0, + 'hidden_tax_amount' => 0, + 'base_hidden_tax_amount' => 0, + ], + ], + ], +]; \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_yes.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_yes.php new file mode 100644 index 0000000000000000000000000000000000000000..d88e3ddb026ad453330aa320704e99dd0ea9dbe9 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_yes.php @@ -0,0 +1,152 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +use Magento\Tax\Model\Config; +use Magento\Tax\Model\Sales\Total\Quote\SetupUtil; +use Magento\Tax\Model\Calculation; + +/** + * This test case test the scenario where there are two tax rules with different priority + * The calculate_subtotal field is on, the second tax rate will be applied on subtotal only. + * This testcase uses total based calculation. + */ +$taxCalculationData['multi_tax_rule_total_calculate_subtotal_yes'] = [ + 'config_data' => [ + SetupUtil::CONFIG_OVERRIDES => [ + Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT => 1, + Config::XML_PATH_ALGORITHM => Calculation::CALC_TOTAL_BASE, + ], + SetupUtil::TAX_RATE_OVERRIDES => [ + SetupUtil::TAX_RATE_TX => 7.5, + SetupUtil::TAX_RATE_AUSTIN => 5.5, + ], + SetupUtil::TAX_RULE_OVERRIDES => [ + [ + //tax rule 1 for product + 'code' => 'Product Tax Rule TX', + 'tax_product_class' => [SetupUtil::PRODUCT_TAX_CLASS_1], + 'tax_rate' => [SetupUtil::TAX_RATE_TX], + 'priority' => 1, + ], + [ + //tax rule 2 for product + 'code' => 'Product Tax Rule AUSTIN', + 'tax_product_class' => [SetupUtil::PRODUCT_TAX_CLASS_1], + 'tax_rate' => [SetupUtil::TAX_RATE_AUSTIN], + 'priority' => 2, + 'calculate_subtotal' => 1, + ], + ], + ], + 'quote_data' => [ + 'billing_address' => [ + 'region_id' => SetupUtil::REGION_TX, + ], + 'shipping_address' => [ + 'region_id' => SetupUtil::REGION_TX, + 'tax_postcode' => SetupUtil::AUSTIN_POST_CODE, + ], + 'items' => [ + [ + 'sku' => 'simple1', + 'price' => 1, + 'qty' => 10, + ], + ], + ], + 'expected_results' => [ + 'address_data' => [ + 'subtotal' => 10, + 'base_subtotal' => 10, + 'subtotal_incl_tax' => 11.3, + 'base_subtotal_incl_tax' => 11.3, + 'tax_amount' => 1.3, + 'base_tax_amount' => 1.3, + 'shipping_amount' => 0, + 'base_shipping_amount' => 0, + 'shipping_incl_tax' => 0, + 'base_shipping_incl_tax' => 0, + 'shipping_taxable' => 0, + 'base_shipping_taxable' => 0, + 'shipping_tax_amount' => 0, + 'base_shipping_tax_amount' => 0, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'hidden_tax_amount' => 0, + 'base_hidden_tax_amount' => 0, + 'shipping_hidden_tax_amount' => 0, + 'base_shipping_hidden_tax_amount' => 0, + 'grand_total' => 11.3, + 'base_grand_total' => 11.3, + 'applied_taxes' => [ + SetupUtil::TAX_RATE_TX => [ + 'percent' => 7.5, + 'amount' => 0.75, + 'base_amount' => 0.75, + 'rates' => [ + [ + 'code' => SetupUtil::TAX_RATE_TX, + 'title' => SetupUtil::TAX_RATE_TX, + 'percent' => 7.5, + ], + ], + ], + SetupUtil::TAX_RATE_AUSTIN => [ + 'percent' => 5.5, + 'amount' => 0.55, + 'base_amount' => 0.55, + 'rates' => [ + [ + 'code' => SetupUtil::TAX_RATE_AUSTIN, + 'title' => SetupUtil::TAX_RATE_AUSTIN, + 'percent' => 5.5, + ], + ], + ], + ], + ], + 'items_data' => [ + 'simple1' => [ + 'row_total' => 10, + 'base_row_total' => 10, + 'taxable_amount' => 10, + 'base_taxable_amount' => 10, + 'tax_percent' => 13, + 'price' => 1, + 'base_price' => 1, + 'price_incl_tax' => 1.13, + 'base_price_incl_tax' => 1.13, + 'row_total_incl_tax' => 11.3, + 'base_row_total_incl_tax' => 11.3, + 'tax_amount' => 1.3, + 'base_tax_amount' => 1.3, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'discount_percent' => 0, + 'hidden_tax_amount' => 0, + 'base_hidden_tax_amount' => 0, + ], + ], + ], +]; \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_no.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_no.php new file mode 100644 index 0000000000000000000000000000000000000000..5e0701ea3869bf151ffb4994e1a3689c4398032a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_no.php @@ -0,0 +1,152 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +use Magento\Tax\Model\Config; +use Magento\Tax\Model\Sales\Total\Quote\SetupUtil; +use Magento\Tax\Model\Calculation; + +/** + * This test case test the scenario where there are two tax rules with different priority + * The calculate_subtotal field is off, the second tax rate will be applied on top of first + * tax rate. This testcase uses unit based calculation. + */ +$taxCalculationData['multi_tax_rule_unit_calculate_subtotal_no'] = [ + 'config_data' => [ + SetupUtil::CONFIG_OVERRIDES => [ + Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT => 1, + Config::XML_PATH_ALGORITHM => Calculation::CALC_UNIT_BASE, + ], + SetupUtil::TAX_RATE_OVERRIDES => [ + SetupUtil::TAX_RATE_TX => 7.5, + SetupUtil::TAX_RATE_AUSTIN => 5.5, + ], + SetupUtil::TAX_RULE_OVERRIDES => [ + [ + //tax rule 1 for product + 'code' => 'Product Tax Rule TX', + 'tax_product_class' => [SetupUtil::PRODUCT_TAX_CLASS_1], + 'tax_rate' => [SetupUtil::TAX_RATE_TX], + 'priority' => 1, + ], + [ + //tax rule 2 for product + 'code' => 'Product Tax Rule AUSTIN', + 'tax_product_class' => [SetupUtil::PRODUCT_TAX_CLASS_1], + 'tax_rate' => [SetupUtil::TAX_RATE_AUSTIN], + 'priority' => 2, + 'calculate_subtotal' => 0, + ], + ], + ], + 'quote_data' => [ + 'billing_address' => [ + 'region_id' => SetupUtil::REGION_TX, + ], + 'shipping_address' => [ + 'region_id' => SetupUtil::REGION_TX, + 'tax_postcode' => SetupUtil::AUSTIN_POST_CODE, + ], + 'items' => [ + [ + 'sku' => 'simple1', + 'price' => 1, + 'qty' => 10, + ], + ], + ], + 'expected_results' => [ + 'address_data' => [ + 'subtotal' => 10, + 'base_subtotal' => 10, + 'subtotal_incl_tax' => 11.4, + 'base_subtotal_incl_tax' => 11.4, + 'tax_amount' => 1.4, + 'base_tax_amount' => 1.4, + 'shipping_amount' => 0, + 'base_shipping_amount' => 0, + 'shipping_incl_tax' => 0, + 'base_shipping_incl_tax' => 0, + 'shipping_taxable' => 0, + 'base_shipping_taxable' => 0, + 'shipping_tax_amount' => 0, + 'base_shipping_tax_amount' => 0, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'hidden_tax_amount' => 0, + 'base_hidden_tax_amount' => 0, + 'shipping_hidden_tax_amount' => 0, + 'base_shipping_hidden_tax_amount' => 0, + 'grand_total' => 11.4, + 'base_grand_total' => 11.4, + 'applied_taxes' => [ + SetupUtil::TAX_RATE_TX => [ + 'percent' => 7.5, + 'amount' => 0.8, + 'base_amount' => 0.8, + 'rates' => [ + [ + 'code' => SetupUtil::TAX_RATE_TX, + 'title' => SetupUtil::TAX_RATE_TX, + 'percent' => 7.5, + ], + ], + ], + SetupUtil::TAX_RATE_AUSTIN => [ + 'percent' => 5.9125, + 'amount' => 0.6, + 'base_amount' => 0.6, + 'rates' => [ + [ + 'code' => SetupUtil::TAX_RATE_AUSTIN, + 'title' => SetupUtil::TAX_RATE_AUSTIN, + 'percent' => 5.5, + ], + ], + ], + ], + ], + 'items_data' => [ + 'simple1' => [ + 'row_total' => 10, + 'base_row_total' => 10, + 'taxable_amount' => 1, + 'base_taxable_amount' => 1, + 'tax_percent' => 13.4125, + 'price' => 1, + 'base_price' => 1, + 'price_incl_tax' => 1.14, + 'base_price_incl_tax' => 1.14, + 'row_total_incl_tax' => 11.4, + 'base_row_total_incl_tax' => 11.4, + 'tax_amount' => 1.4, + 'base_tax_amount' => 1.4, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'discount_percent' => 0, + 'hidden_tax_amount' => 0, + 'base_hidden_tax_amount' => 0, + ], + ], + ], +]; \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_yes.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_yes.php new file mode 100644 index 0000000000000000000000000000000000000000..025ba3b402f1274151f8f6d797dff97e4b381fa4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_yes.php @@ -0,0 +1,152 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +use Magento\Tax\Model\Config; +use Magento\Tax\Model\Sales\Total\Quote\SetupUtil; +use Magento\Tax\Model\Calculation; + +/** + * This test case test the scenario where there are two tax rules with different priority + * The calculate_subtotal field is on, the second tax rate will be applied on subtotal only. + * This testcase uses unit based calculation. + */ +$taxCalculationData['multi_tax_rule_unit_calculate_subtotal_yes'] = [ + 'config_data' => [ + SetupUtil::CONFIG_OVERRIDES => [ + Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT => 1, + Config::XML_PATH_ALGORITHM => Calculation::CALC_UNIT_BASE, + ], + SetupUtil::TAX_RATE_OVERRIDES => [ + SetupUtil::TAX_RATE_TX => 7.5, + SetupUtil::TAX_RATE_AUSTIN => 5.5, + ], + SetupUtil::TAX_RULE_OVERRIDES => [ + [ + //tax rule 1 for product + 'code' => 'Product Tax Rule TX', + 'tax_product_class' => [SetupUtil::PRODUCT_TAX_CLASS_1], + 'tax_rate' => [SetupUtil::TAX_RATE_TX], + 'priority' => 1, + ], + [ + //tax rule 2 for product + 'code' => 'Product Tax Rule AUSTIN', + 'tax_product_class' => [SetupUtil::PRODUCT_TAX_CLASS_1], + 'tax_rate' => [SetupUtil::TAX_RATE_AUSTIN], + 'priority' => 2, + 'calculate_subtotal' => 1, + ], + ], + ], + 'quote_data' => [ + 'billing_address' => [ + 'region_id' => SetupUtil::REGION_TX, + ], + 'shipping_address' => [ + 'region_id' => SetupUtil::REGION_TX, + 'tax_postcode' => SetupUtil::AUSTIN_POST_CODE, + ], + 'items' => [ + [ + 'sku' => 'simple1', + 'price' => 1, + 'qty' => 10, + ], + ], + ], + 'expected_results' => [ + 'address_data' => [ + 'subtotal' => 10, + 'base_subtotal' => 10, + 'subtotal_incl_tax' => 11.4, + 'base_subtotal_incl_tax' => 11.4, + 'tax_amount' => 1.4, + 'base_tax_amount' => 1.4, + 'shipping_amount' => 0, + 'base_shipping_amount' => 0, + 'shipping_incl_tax' => 0, + 'base_shipping_incl_tax' => 0, + 'shipping_taxable' => 0, + 'base_shipping_taxable' => 0, + 'shipping_tax_amount' => 0, + 'base_shipping_tax_amount' => 0, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'hidden_tax_amount' => 0, + 'base_hidden_tax_amount' => 0, + 'shipping_hidden_tax_amount' => 0, + 'base_shipping_hidden_tax_amount' => 0, + 'grand_total' => 11.4, + 'base_grand_total' => 11.4, + 'applied_taxes' => [ + SetupUtil::TAX_RATE_TX => [ + 'percent' => 7.5, + 'amount' => 0.8, + 'base_amount' => 0.8, + 'rates' => [ + [ + 'code' => SetupUtil::TAX_RATE_TX, + 'title' => SetupUtil::TAX_RATE_TX, + 'percent' => 7.5, + ], + ], + ], + SetupUtil::TAX_RATE_AUSTIN => [ + 'percent' => 5.5, + 'amount' => 0.6, + 'base_amount' => 0.6, + 'rates' => [ + [ + 'code' => SetupUtil::TAX_RATE_AUSTIN, + 'title' => SetupUtil::TAX_RATE_AUSTIN, + 'percent' => 5.5, + ], + ], + ], + ], + ], + 'items_data' => [ + 'simple1' => [ + 'row_total' => 10, + 'base_row_total' => 10, + 'taxable_amount' => 1, + 'base_taxable_amount' => 1, + 'tax_percent' => 13, + 'price' => 1, + 'base_price' => 1, + 'price_incl_tax' => 1.14, + 'base_price_incl_tax' => 1.14, + 'row_total_incl_tax' => 11.4, + 'base_row_total_incl_tax' => 11.4, + 'tax_amount' => 1.4, + 'base_tax_amount' => 1.4, + 'discount_amount' => 0, + 'base_discount_amount' => 0, + 'discount_percent' => 0, + 'hidden_tax_amount' => 0, + 'base_hidden_tax_amount' => 0, + ], + ], + ], +]; \ No newline at end of file diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php index 13097905b486d7e6b0a051628506ec3939b0bde3..b98287caeccba808e802f6a92b1c9fe92d390745 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/tax_calculation_data_aggregated.php @@ -40,4 +40,9 @@ require_once __DIR__ . '/scenarios/including_tax_total.php'; require_once __DIR__ . '/scenarios/excluding_tax_multi_item_unit.php'; require_once __DIR__ . '/scenarios/excluding_tax_multi_item_row.php'; require_once __DIR__ . '/scenarios/excluding_tax_multi_item_total.php'; - +require_once __DIR__ . '/scenarios/including_tax_cross_border_trade_disabled.php'; +require_once __DIR__ . '/scenarios/including_tax_cross_border_trade_enabled.php'; +require_once __DIR__ . '/scenarios/multi_tax_rule_total_calculate_subtotal_no.php'; +require_once __DIR__ . '/scenarios/multi_tax_rule_unit_calculate_subtotal_no.php'; +require_once __DIR__ . '/scenarios/multi_tax_rule_total_calculate_subtotal_yes.php'; +require_once __DIR__ . '/scenarios/multi_tax_rule_unit_calculate_subtotal_yes.php'; diff --git a/dev/tests/integration/testsuite/Magento/Widget/Model/Widget/InstanceTest.php b/dev/tests/integration/testsuite/Magento/Widget/Model/Widget/InstanceTest.php index aa286b773b37750dec11526ddce4b2d6f5cd8289..093a31ffad9883e6e6164243a7c3a30b57106ed3 100644 --- a/dev/tests/integration/testsuite/Magento/Widget/Model/Widget/InstanceTest.php +++ b/dev/tests/integration/testsuite/Magento/Widget/Model/Widget/InstanceTest.php @@ -61,11 +61,6 @@ class InstanceTest extends \PHPUnit_Framework_TestCase */ public function testGetWidgetConfigAsArray() { - $this->markTestIncomplete( - 'Functionality is failed because widget' . - ' "app/design/frontend/Magento/iphone_html5/etc/widget.xml" replaces' . - ' "new_products" widget in Catalog module' - ); $config = $this->_model->setType('Magento\Catalog\Block\Product\Widget\NewWidget')->getWidgetConfigAsArray(); $this->assertTrue(is_array($config)); $element = null; @@ -96,11 +91,6 @@ class InstanceTest extends \PHPUnit_Framework_TestCase */ public function testGetWidgetSupportedContainers() { - $this->markTestIncomplete( - 'Functionality is failed because widget' . - ' "app/design/frontend/Magento/iphone_html5/etc/widget.xml" replaces' . - ' "new_products" widget in Catalog module' - ); $this->_model->setType('Magento\Catalog\Block\Product\Widget\NewWidget'); $containers = $this->_model->getWidgetSupportedContainers(); $this->assertInternalType('array', $containers); diff --git a/dev/tests/integration/testsuite/Magento/Widget/Model/WidgetTest.php b/dev/tests/integration/testsuite/Magento/Widget/Model/WidgetTest.php index c5b4d41fd53d7f4cc4f02ff0fb3da256433af3c5..a6f8cbcc0fb798b1854f84e39855905c8f9505de 100644 --- a/dev/tests/integration/testsuite/Magento/Widget/Model/WidgetTest.php +++ b/dev/tests/integration/testsuite/Magento/Widget/Model/WidgetTest.php @@ -60,30 +60,14 @@ class WidgetTest extends \PHPUnit_Framework_TestCase */ public function testGetPlaceholderImageUrl($type, $expectedFile) { - $this->markTestIncomplete( - 'Functionality is failed because widget' . - ' "app/design/frontend/Magento/iphone_html5/etc/widget.xml" replaces' . - ' "new_products" widget in Catalog module' - ); $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); \Magento\TestFramework\Helper\Bootstrap::getInstance() ->loadArea(\Magento\Backend\App\Area\FrontNameResolver::AREA_CODE); $objectManager->get('Magento\Framework\View\DesignInterface')->setDesignTheme('Magento/backend'); $expectedFilePath = "/adminhtml/Magento/backend/en_US/{$expectedFile}"; - $expectedPubFile = $objectManager->get( - 'Magento\Framework\App\Filesystem' - )->getPath( - \Magento\Framework\App\Filesystem::STATIC_VIEW_DIR - ) . $expectedFilePath; - - if (file_exists($expectedPubFile)) { - unlink($expectedPubFile); - } $url = $this->_model->getPlaceholderImageUrl($type); - $this->assertStringEndsWith($expectedFile, $url); - $this->assertFileExists($expectedPubFile); - return $expectedPubFile; + $this->assertStringEndsWith($expectedFilePath, $url); } /** @@ -99,32 +83,4 @@ class WidgetTest extends \PHPUnit_Framework_TestCase 'default image' => array('non_existing_widget_type', 'Magento_Widget/placeholder.gif') ); } - - /** - * Tests, that theme file is found anywhere in theme folders, not only in module directory. - * - * @magentoDataFixture Magento/Widget/_files/themes.php - * @magentoAppIsolation enabled - */ - public function testGetPlaceholderImageUrlAtTheme() - { - \Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize( - array( - \Magento\Framework\App\Filesystem::PARAM_APP_DIRS => array( - \Magento\Framework\App\Filesystem::THEMES_DIR => array( - 'path' => dirname(__DIR__) . '/_files/design' - ) - ) - ) - ); - $actualFile = $this->testGetPlaceholderImageUrl( - 'Magento\Catalog\Block\Product\Widget\NewWidget', - 'Magento_Catalog/images/product_widget_new.gif' - ); - - $expectedFile = dirname( - __DIR__ - ) . '/_files/design/adminhtml/Magento/backend/Magento_Catalog/web/images/product_widget_new.gif'; - $this->assertFileEquals($expectedFile, $actualFile); - } } diff --git a/dev/tests/integration/testsuite/Magento/Widget/_files/themes.php b/dev/tests/integration/testsuite/Magento/Widget/_files/themes.php deleted file mode 100644 index c89104025486db21e0585ecc1118ae0de2e499cb..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Magento/Widget/_files/themes.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php -/** - * Magento - * - * NOTICE OF LICENSE - * - * This source file is subject to the Open Software License (OSL 3.0) - * that is bundled with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://opensource.org/licenses/osl-3.0.php - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@magentocommerce.com so we can send you a copy immediately. - * - * DISCLAIMER - * - * Do not edit or add to this file if you wish to upgrade Magento to newer - * versions in the future. If you wish to customize Magento for your - * needs please refer to http://www.magentocommerce.com for more information. - * - * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) - * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) - */ - -\Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize(array( - \Magento\Framework\App\Filesystem::PARAM_APP_DIRS => array( - \Magento\Framework\App\Filesystem::THEMES_DIR => array('path' => __DIR__ . '/design') - ) -)); - -\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\App\AreaList') - ->getArea(\Magento\Backend\App\Area\FrontNameResolver::AREA_CODE) - ->load(\Magento\Framework\App\Area::PART_CONFIG); -/** @var $registration \Magento\Core\Model\Theme\Registration */ -$registration = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - 'Magento\Core\Model\Theme\Registration' -); -$registration->register('*/*/theme.xml'); diff --git a/dev/tests/static/framework/Magento/TestFramework/Utility/ChangedFiles.php b/dev/tests/static/framework/Magento/TestFramework/Utility/ChangedFiles.php new file mode 100644 index 0000000000000000000000000000000000000000..e7fb311d7c28fda24670be3da7ca6454cef958c1 --- /dev/null +++ b/dev/tests/static/framework/Magento/TestFramework/Utility/ChangedFiles.php @@ -0,0 +1,57 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\TestFramework\Utility; + +/** + * A helper to gather various changed files + * if INCREMENTAL_BUILD env variable is set by CI build infrastructure, only files changed in the + * branch are gathered, otherwise all files + */ +class ChangedFiles +{ + /** + * Returns array of PHP-files, that use or declare Magento application classes and Magento libs + * + * @param string $changedFilesList + * @return array + */ + public static function getPhpFiles($changedFilesList) + { + $fileHelper = \Magento\TestFramework\Utility\Files::init(); + $allPhpFiles = $fileHelper->getPhpFiles(); + if (isset($_ENV['INCREMENTAL_BUILD'])) { + $phpFiles = file($changedFilesList, FILE_IGNORE_NEW_LINES); + foreach ($phpFiles as $key => $phpFile) { + $phpFiles[$key] = $fileHelper->getPathToSource() . '/' . $phpFile; + } + $phpFiles = \Magento\TestFramework\Utility\Files::composeDataSets($phpFiles); + $phpFiles = array_intersect_key($phpFiles, $allPhpFiles); + } else { + $phpFiles = $allPhpFiles; + } + + return $phpFiles; + } +} diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteCodeTest.php index 7cf7a9155ef42867b0f1fb2f81de6982f69a56e8..18fcb1f839cd23490b63ceff0f7c6ab06b115782 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteCodeTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteCodeTest.php @@ -148,7 +148,7 @@ class ObsoleteCodeTest extends \PHPUnit_Framework_TestCase $this->_testObsoleteConstants($content); $this->_testObsoletePropertySkipCalculate($content); }, - \Magento\TestFramework\Utility\Files::init()->getPhpFiles() + \Magento\TestFramework\Utility\ChangedFiles::getPhpFiles(__DIR__ . '/_files/changed_files.txt') ); } diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Adjustment/CalculatorTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Adjustment/CalculatorTest.php index 5f7cbfb1931f400c1c9d8971bf040da56426252a..8c8e61289a2c733ee3fcb9748e1d00988f50e353 100644 --- a/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Adjustment/CalculatorTest.php +++ b/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Adjustment/CalculatorTest.php @@ -61,6 +61,11 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase */ protected $selectionFactory; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $taxData; + /** * @var Calculator */ @@ -69,7 +74,7 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase protected function setUp() { $this->saleableItem = $this->getMockBuilder('Magento\Catalog\Model\Product') - ->setMethods(['getPriceInfo', 'getPriceType', '__wakeup']) + ->setMethods(['getPriceInfo', 'getPriceType', '__wakeup', 'getStore']) ->disableOriginalConstructor() ->getMock(); $priceInfo = $this->getMock('Magento\Framework\Pricing\PriceInfo\Base', [], [], '', false); @@ -81,6 +86,12 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase })); $this->saleableItem->expects($this->any())->method('getPriceInfo')->will($this->returnValue($priceInfo)); + $store = $this->getMockBuilder('Magento\Store\Model\Store') + ->disableOriginalConstructor() + ->getMock(); + $store->expects($this->any())->method('roundPrice')->will($this->returnArgument(0)); + + $this->saleableItem->expects($this->any())->method('getStore')->will($this->returnValue($store)); $this->baseCalculator = $this->getMock('Magento\Framework\Pricing\Adjustment\Calculator', [], [], '', false); $this->amountFactory = $this->getMock('Magento\Framework\Pricing\Amount\AmountFactory', [], [], '', false); @@ -99,7 +110,17 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase return $bundlePrice; }); $this->selectionFactory->expects($this->any())->method('create')->will($factoryCallback); - $this->model = new Calculator($this->baseCalculator, $this->amountFactory, $this->selectionFactory); + + $this->taxData = $this->getMockBuilder('Magento\Tax\Helper\Data') + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new Calculator( + $this->baseCalculator, + $this->amountFactory, + $this->selectionFactory, + $this->taxData + ); } protected function tearDown() diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Price/BundleOptionPriceTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Price/BundleOptionPriceTest.php index b0c0d288b64b325253a9ab5a744547bf459a910e..629920fd72b0336466ff522d87080f113d981f1b 100644 --- a/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Price/BundleOptionPriceTest.php +++ b/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Price/BundleOptionPriceTest.php @@ -76,10 +76,20 @@ class BundleOptionPriceTest extends \PHPUnit_Framework_TestCase ->method('getPriceInfo') ->will($this->returnValue($this->priceInfoMock)); + $store = $this->getMockBuilder('Magento\Store\Model\Store') + ->setMethods(['roundPrice', '__wakeup']) + ->disableOriginalConstructor() + ->getMock(); + $store->expects($this->any())->method('roundPrice')->will($this->returnArgument(0)); + $this->saleableItemMock->expects($this->once()) ->method('setQty') ->will($this->returnSelf()); + $this->saleableItemMock->expects($this->any()) + ->method('getStore') + ->will($this->returnValue($store)); + $this->selectionFactoryMock = $this->getMockBuilder('Magento\Bundle\Pricing\Price\BundleSelectionFactory') ->disableOriginalConstructor() ->getMock(); @@ -91,8 +101,13 @@ class BundleOptionPriceTest extends \PHPUnit_Framework_TestCase ); $this->amountFactory->expects($this->any())->method('create')->will($factoryCallback); $this->baseCalculator = $this->getMock('Magento\Framework\Pricing\Adjustment\Calculator', [], [], '', false); + + $taxData = $this->getMockBuilder('Magento\Tax\Helper\Data') + ->disableOriginalConstructor() + ->getMock(); + $this->bundleCalculatorMock = $this->getMockBuilder('Magento\Bundle\Pricing\Adjustment\Calculator') - ->setConstructorArgs([$this->baseCalculator, $this->amountFactory, $this->selectionFactoryMock]) + ->setConstructorArgs([$this->baseCalculator, $this->amountFactory, $this->selectionFactoryMock, $taxData]) ->setMethods(['getOptionsAmount']) ->getMock(); $this->objectManagerHelper = new ObjectManagerHelper($this); diff --git a/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Price/GroupPriceTest.php b/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Price/GroupPriceTest.php index 0ec45ccb35d24b878394dae6c24104a300635acb..6039a1bf000b84fa291b4df2398b4da5754ea333 100644 --- a/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Price/GroupPriceTest.php +++ b/dev/tests/unit/testsuite/Magento/Bundle/Pricing/Price/GroupPriceTest.php @@ -26,88 +26,178 @@ namespace Magento\Bundle\Pricing\Price; class GroupPriceTest extends \PHPUnit_Framework_TestCase { /** - * @var GroupPrice + * @var \Magento\Bundle\Pricing\Price\GroupPrice */ - protected $model; + protected $groupPrice; /** - * @var \Magento\Framework\Pricing\Object\SaleableInterface|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */ - protected $saleable; + protected $productMock; /** - * @var \Magento\Framework\Pricing\PriceInfo\Base |\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\Resource\Product|\PHPUnit_Framework_MockObject_MockObject */ - protected $priceInfo; + protected $productResourceMock; - public function setUp() - { - $this->saleable = $this->getMockBuilder('Magento\Catalog\Model\Product') - ->setMethods(['getPriceInfo', 'getCustomerGroupId', 'getData', '__wakeup']) - ->disableOriginalConstructor() - ->getMock(); - - $this->priceInfo = $this->getMock('Magento\Framework\Pricing\PriceInfo\Base', [], [], '', false); - - $this->saleable->expects($this->once()) - ->method('getPriceInfo') - ->will($this->returnValue($this->priceInfo)); + /** + * @var \Magento\Framework\Pricing\Adjustment\Calculator|\PHPUnit_Framework_MockObject_MockObject + */ + protected $calculatorMock; - $objectHelper = new \Magento\TestFramework\Helper\ObjectManager($this); - $this->model = $objectHelper->getObject( - 'Magento\Bundle\Pricing\Price\GroupPrice', - [ - 'saleableItem' => $this->saleable - ] - ); - } + /** + * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject + */ + protected $customerSessionMock; /** - * @param $regularPrice - * @param $storedGroupPrice - * @param $value - * @param $percent - * @dataProvider getValueDataProvider + * @var \Magento\Customer\Model\Customer|\PHPUnit_Framework_MockObject_MockObject */ - public function testGetValue($regularPrice, $storedGroupPrice, $value, $percent) - { - $customerGroupId = 234; + protected $customerMock; - $this->saleable->expects($this->atLeastOnce()) - ->method('getCustomerGroupId') - ->will($this->returnValue($customerGroupId)); + /** + * @var \Magento\Catalog\Model\Entity\Attribute|\PHPUnit_Framework_MockObject_MockObject + */ + protected $attributeMock; - $this->saleable->expects($this->once()) - ->method('getData') - ->with('group_price') - ->will($this->returnValue($storedGroupPrice)); + /** + * @var \Magento\Catalog\Model\Product\Attribute\Backend\Groupprice|\PHPUnit_Framework_MockObject_MockObject + */ + protected $backendMock; - if (!empty($storedGroupPrice)) { - $price = $this->getMock('Magento\Framework\Pricing\Price\PriceInterface'); - $this->priceInfo->expects($this->once()) - ->method('getPrice') - ->with(\Magento\Catalog\Pricing\Price\RegularPrice::PRICE_CODE) - ->will($this->returnValue($price)); - $price->expects($this->once()) - ->method('getValue') - ->will($this->returnValue($regularPrice)); - } - $this->assertEquals($value, $this->model->getValue()); - $this->assertEquals($percent, $this->model->getDiscountPercent()); - } + /** + * @var \Magento\Framework\Pricing\PriceInfo\Base|\PHPUnit_Framework_MockObject_MockObject + */ + protected $priceInfoMock; /** - * @return array + * @var \Magento\Catalog\Pricing\Price\RegularPrice|\PHPUnit_Framework_MockObject_MockObject */ - public function getValueDataProvider() + protected $regularPrice; + /** + * Set up test case + */ + public function setUp() { - return array( - ['regularPrice' => 100, 'storedGroupPrice' - => [['cust_group' => 234, 'website_price' => 40]], 'value' => 60, 'percent' => 60], - ['regularPrice' => 75, 'storedGroupPrice' - => [['cust_group' => 234, 'website_price' => 40]], 'value' => 45, 'percent' => 60], - ['regularPrice' => 75, 'storedGroupPrice' - => [], 'value' => false, 'percent' => null], + $this->productMock = $this->getMock( + 'Magento\Catalog\Model\Product', + ['__wakeup', 'getCustomerGroupId', 'getPriceInfo', 'getResource', 'getData'], + [], + '', + false + ); + $this->productResourceMock = $this->getMock( + 'Magento\Catalog\Model\Resource\Product', + [], + [], + '', + false + ); + $this->calculatorMock = $this->getMock( + 'Magento\Framework\Pricing\Adjustment\Calculator', + [], + [], + '', + false + ); + $this->customerSessionMock = $this->getMock( + 'Magento\Customer\Model\Session', + [], + [], + '', + false + ); + $this->customerMock = $this->getMock( + 'Magento\Customer\Model\Customer', + [], + [], + '', + false + ); + $this->attributeMock = $this->getMock( + 'Magento\Catalog\Model\Entity\Attribute', + [], + [], + '', + false + ); + $this->backendMock = $this->getMock( + 'Magento\Catalog\Model\Product\Attribute\Backend\Groupprice', + [], + [], + '', + false + ); + $this->priceInfoMock = $this->getMock( + 'Magento\Framework\Pricing\PriceInfo\Base', + ['getPrice'], + [], + '', + false + ); + $this->regularPrice = $this->getMock( + 'Magento\Catalog\Pricing\Price\RegularPrice', + [], + [], + '', + false ); + $this->productMock->expects($this->once()) + ->method('getPriceInfo') + ->will($this->returnValue($this->priceInfoMock)); + + $this->groupPrice = new \Magento\Bundle\Pricing\Price\GroupPrice( + $this->productMock, + 1, + $this->calculatorMock, + $this->customerSessionMock + ); + } + + public function testGetValue() + { + $this->priceInfoMock->expects($this->once()) + ->method('getPrice') + ->with($this->equalTo('regular_price')) + ->will($this->returnValue($this->regularPrice)); + $this->regularPrice->expects($this->once()) + ->method('getValue') + ->will($this->returnValue(100)); + $this->productMock->expects($this->once()) + ->method('getCustomerGroupId') + ->will($this->returnValue(null)); + $this->customerSessionMock->expects($this->once()) + ->method('getCustomerGroupId') + ->will($this->returnValue(3)); + $this->productMock->expects($this->once()) + ->method('getResource') + ->will($this->returnValue($this->productResourceMock)); + $this->productResourceMock->expects($this->once()) + ->method('getAttribute') + ->with($this->equalTo('group_price')) + ->will($this->returnValue($this->attributeMock)); + $this->attributeMock->expects($this->once()) + ->method('getBackend') + ->will($this->returnValue($this->backendMock)); + $this->backendMock->expects($this->once()) + ->method('afterLoad') + ->with($this->equalTo($this->productMock)) + ->will($this->returnValue($this->backendMock)); + $this->productMock->expects($this->once()) + ->method('getData') + ->with( + $this->equalTo('group_price'), + $this->equalTo(null) + ) + ->will($this->returnValue( + [ + [ + 'cust_group' => 3, + 'website_price' => 80 + ] + ] + + )); + $this->assertEquals(20, $this->groupPrice->getValue()); } } diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/PriceModifierTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/PriceModifierTest.php new file mode 100644 index 0000000000000000000000000000000000000000..90db7848043e678feef0e4dc7e088710b6ac7a55 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/Product/PriceModifierTest.php @@ -0,0 +1,161 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +namespace Magento\Catalog\Model\Product; + +class PriceModifierTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Catalog\Model\Product\PriceModifier + */ + protected $priceModifier; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productMock; + + /** + * @var array + */ + protected $prices = array(); + + protected function setUp() + { + $this->productMock = + $this->getMock('Magento\Catalog\Model\Product', + array('getData', 'setData', '__wakeup'), array(), '', false); + $this->priceModifier = new \Magento\Catalog\Model\Product\PriceModifier(); + $this->prices = array( + 0 => array( + 'all_groups' => 0, + 'cust_group' => 1, + 'price_qty' => 15, + 'website_id' => 1 + ), + 1 => array( + 'all_groups' => 1, + 'cust_group' => 0, + 'price_qty' => 10, + 'website_id' => 1 + ) + ); + } + + public function testSuccessfullyRemoveGroupPriceSpecifiedForOneGroup() + { + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('group_price') + ->will($this->returnValue($this->prices)); + $expectedPrices = array(1 => $this->prices[1]); + $this->productMock->expects($this->once())->method('setData')->with('group_price', $expectedPrices); + $this->priceModifier->removeGroupPrice($this->productMock, 1, 1); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedMessage This product doesn't have group price + */ + public function testRemoveWhenGroupPricesNotExists() + { + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('group_price') + ->will($this->returnValue(array())); + $this->productMock->expects($this->never())->method('setData'); + $this->priceModifier->removeGroupPrice($this->productMock, 1, 1); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedMessage For current customerGroupId = '10' any group price exist'. + */ + public function testRemoveGroupPriceForNonExistingCustomerGroup() + { + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('group_price') + ->will($this->returnValue($this->prices)); + $this->productMock->expects($this->never())->method('setData'); + $this->priceModifier->removeGroupPrice($this->productMock, 10, 1); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedMessage This product doesn't have tier price + */ + public function testRemoveWhenTierPricesNotExists() + { + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('tier_price') + ->will($this->returnValue(array())); + $this->productMock->expects($this->never())->method('setData'); + $this->priceModifier->removeTierPrice($this->productMock, 1, 3, 1); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedMessage For current customerGroupId = '10' with 'qty' = 15 any tier price exist'. + */ + public function testRemoveTierPriceForNonExistingCustomerGroup() + { + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('tier_price') + ->will($this->returnValue($this->prices)); + $this->productMock->expects($this->never())->method('setData'); + $this->priceModifier->removeTierPrice($this->productMock, 10, 15, 1); + } + + public function testSuccessfullyRemoveTierPriceSpecifiedForAllGroups() + { + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('tier_price') + ->will($this->returnValue($this->prices)); + $expectedPrices = array($this->prices[0]); + $this->productMock->expects($this->once())->method('setData')->with('tier_price', $expectedPrices); + $this->priceModifier->removeTierPrice($this->productMock, 'all', 10, 1); + } + + public function testSuccessfullyRemoveTierPriceSpecifiedForSpecificGroups() + { + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('tier_price') + ->will($this->returnValue($this->prices)); + $expectedPrices = array(1 => $this->prices[1]); + $this->productMock->expects($this->once())->method('setData')->with('tier_price', $expectedPrices); + $this->priceModifier->removeTierPrice($this->productMock, 1, 15, 1); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b73e577eff08f56a71d7faaa13e2887803c3b5d1 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Catalog/Model/ProductRepositoryTest.php @@ -0,0 +1,76 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Model; + +class ProductRepositoryTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productMock; + + /** + * @var \Magento\Catalog\Model\ProductRepository + */ + protected $model; + + protected function setUp() + { + $productFactoryMock = $this->getMock( + 'Magento\Catalog\Model\ProductFactory', array('create'), array(), '', false + ); + $this->productMock = $this->getMock('Magento\Catalog\Model\Product', array(), array(), '', false); + $productFactoryMock->expects($this->once())->method('create')->will($this->returnValue($this->productMock)); + $this->model = new ProductRepository($productFactoryMock); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + */ + public function testCreateThrowsExceptionIfNoSuchProduct() + { + $this->productMock->expects($this->once())->method('getIdBySku')->with('test_sku') + ->will($this->returnValue(null)); + $this->model->get('test_sku'); + } + + public function testCreateCreatesProduct() + { + $this->productMock->expects($this->once())->method('getIdBySku')->with('test_sku') + ->will($this->returnValue('test_id')); + $this->productMock->expects($this->once())->method('load')->with('test_id'); + $this->assertSame($this->productMock, $this->model->get('test_sku')); + $this->assertSame($this->productMock, $this->model->get('test_sku')); + } + + public function testCreateCreatesProductInEditMode() + { + $this->productMock->expects($this->once())->method('getIdBySku')->with('test_sku') + ->will($this->returnValue('test_id')); + $this->productMock->expects($this->once())->method('setData')->with('_edit_mode', true); + $this->productMock->expects($this->once())->method('load')->with('test_id'); + $this->assertSame($this->productMock, $this->model->get('test_sku', true)); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Pricing/Price/GroupPriceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Pricing/Price/GroupPriceTest.php index 36d889fbdeb1fdd4df8243275570538aec43fdce..395a35555c2b41a6201ada54c743a3ef750c5e32 100644 --- a/dev/tests/unit/testsuite/Magento/Catalog/Pricing/Price/GroupPriceTest.php +++ b/dev/tests/unit/testsuite/Magento/Catalog/Pricing/Price/GroupPriceTest.php @@ -30,211 +30,206 @@ namespace Magento\Catalog\Pricing\Price; class GroupPriceTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\TestFramework\Helper\ObjectManager + * @var \Magento\Catalog\Pricing\Price\GroupPrice */ - protected $objectManager; - - public function setUp() - { - $this->objectManager = new \Magento\TestFramework\Helper\ObjectManager($this); - } + protected $groupPrice; /** - * @param array|null $groupPrice - * @param int $customerGroup - * @param float $expected - * - * @dataProvider groupPriceDataProvider + * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */ - public function testGroupPrice($groupPrice, $customerGroup, $expected) - { - $saleableItemMock = $this->prepareSaleableItem($groupPrice); - $sessionMock = $this->prepareSession($saleableItemMock, $customerGroup); - $groupPriceModel = $this->objectManager->getObject( - 'Magento\Catalog\Pricing\Price\GroupPrice', - [ - 'saleableItem' => $saleableItemMock, - 'customerSession' => $sessionMock - ] - ); - $this->assertEquals($expected, $groupPriceModel->getValue()); - } + protected $productMock; /** - * @param \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Product $saleableItemMock - * @param int $customerGroup - * @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Customer\Model\Session + * @var \Magento\Catalog\Model\Resource\Product|\PHPUnit_Framework_MockObject_MockObject */ - protected function prepareSession($saleableItemMock, $customerGroup) - { - $session = $this->getMock('Magento\Customer\Model\Session', ['getCustomerGroupId'], [], '', false); - $session->expects($this->any()) - ->method('getCustomerGroupId') - ->will($this->returnValue($customerGroup)); + protected $productResourceMock; - $saleableItemMock->expects($this->any()) - ->method('getCustomerGroupId') - ->will($this->returnValue(false)); + /** + * @var \Magento\Framework\Pricing\Adjustment\Calculator|\PHPUnit_Framework_MockObject_MockObject + */ + protected $calculatorMock; - return $session; - } + /** + * @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject + */ + protected $customerSessionMock; /** - * @dataProvider groupPriceNonExistDataProvider - * - * @param array|null $groupPrice - * @param float $expected + * @var \Magento\Customer\Model\Customer|\PHPUnit_Framework_MockObject_MockObject */ - public function testGroupPriceNonExist($groupPrice, $expected) - { - $groupPriceModel = $this->objectManager->getObject( - 'Magento\Catalog\Pricing\Price\GroupPrice', - [ - 'saleableItem' => $this->prepareSaleableItem($groupPrice), - 'customerSession' => $this->getMock('Magento\Customer\Model\Session', [], [], '', false) - ] - ); + protected $customerMock; - $this->assertEquals($expected, $groupPriceModel->getValue()); + /** + * @var \Magento\Catalog\Model\Entity\Attribute|\PHPUnit_Framework_MockObject_MockObject + */ + protected $attributeMock; - //Verify that storedGroupPrice is cached - $this->assertEquals($expected, $groupPriceModel->getValue()); - } + /** + * @var \Magento\Catalog\Model\Product\Attribute\Backend\Groupprice|\PHPUnit_Framework_MockObject_MockObject + */ + protected $backendMock; /** - * @param array|null $groupPrice - * @return \PHPUnit_Framework_MockObject_MockObject + * Set up test case */ - protected function prepareSaleableItem($groupPrice) + public function setUp() { - $saleableItemMock = $this->getMock( + $this->productMock = $this->getMock( 'Magento\Catalog\Model\Product', - ['getCustomerGroupId', 'getData', 'getPrice', 'getPriceInfo', 'getResource', '__wakeup'], + ['__wakeup', 'getCustomerGroupId', 'getPriceInfo', 'getResource', 'getData'], + [], + '', + false + ); + $this->productResourceMock = $this->getMock( + 'Magento\Catalog\Model\Resource\Product', + [], + [], + '', + false + ); + $this->calculatorMock = $this->getMock( + 'Magento\Framework\Pricing\Adjustment\Calculator', + [], + [], + '', + false + ); + $this->customerSessionMock = $this->getMock( + 'Magento\Customer\Model\Session', + [], + [], + '', + false + ); + $this->customerMock = $this->getMock( + 'Magento\Customer\Model\Customer', + [], + [], + '', + false + ); + $this->attributeMock = $this->getMock( + 'Magento\Catalog\Model\Entity\Attribute', + [], + [], + '', + false + ); + $this->backendMock = $this->getMock( + 'Magento\Catalog\Model\Product\Attribute\Backend\Groupprice', + [], [], '', false ); - $saleableItemMock->expects($this->at(1)) - ->method('getData') - ->will($this->returnValue(null)); - - $saleableItemMock->expects($this->at(2)) - ->method('getData') - ->will($this->returnValue($groupPrice)); - - $saleableItemMock->expects($this->any()) - ->method('getResource') - ->will($this->returnValue($this->prepareSaleableItemResource())); - - $priceInfo = $this->getMockBuilder( - 'Magento\Framework\Pricing\PriceInfo\Base' - )->disableOriginalConstructor()->getMockForAbstractClass(); - - $priceInfo->expects($this->any()) - ->method('getAdjustments') - ->will($this->returnValue([])); - - $saleableItemMock->expects($this->any()) - ->method('getPriceInfo') - ->will($this->returnValue($priceInfo)); - - return $saleableItemMock; + $this->groupPrice = new \Magento\Catalog\Pricing\Price\GroupPrice( + $this->productMock, + 1, + $this->calculatorMock, + $this->customerSessionMock + ); } /** - * @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Resource\Product + * test get group price, customer group in session */ - protected function prepareSaleableItemResource() + public function testGroupPriceCustomerGroupInSession() { - $resourceMock = $this->getMockBuilder( - 'Magento\Catalog\Model\Resource\Product' - )->disableOriginalConstructor()->setMethods(['getAttribute', '__wakeup'])->getMock(); - - $attributeMock = $this->getMock( - 'Magento\Framework\Object', - ['getBackend', 'afterLoad'], - [], - '', - false - ); - - $attributeMock->expects($this->any()) + $this->productMock->expects($this->once()) + ->method('getCustomerGroupId') + ->will($this->returnValue(null)); + $this->customerSessionMock->expects($this->once()) + ->method('getCustomerGroupId') + ->will($this->returnValue(3)); + $this->productMock->expects($this->once()) + ->method('getResource') + ->will($this->returnValue($this->productResourceMock)); + $this->productResourceMock->expects($this->once()) + ->method('getAttribute') + ->with($this->equalTo('group_price')) + ->will($this->returnValue($this->attributeMock)); + $this->attributeMock->expects($this->once()) ->method('getBackend') - ->will($this->returnValue($attributeMock)); - - $attributeMock->expects($this->any()) + ->will($this->returnValue($this->backendMock)); + $this->backendMock->expects($this->once()) ->method('afterLoad') - ->will($this->returnValue($attributeMock)); - - $resourceMock->expects($this->any()) - ->method('getAttribute') - ->will($this->returnValue($attributeMock)); + ->with($this->equalTo($this->productMock)) + ->will($this->returnValue($this->backendMock)); + $this->productMock->expects($this->once()) + ->method('getData') + ->with( + $this->equalTo('group_price'), + $this->equalTo(null) + ) + ->will($this->returnValue( + [ + [ + 'cust_group' => 3, + 'website_price' => 80 + ] + ] - return $resourceMock; + )); + $this->assertEquals(80, $this->groupPrice->getValue()); } /** - * @return array + * test get group price, customer group in session */ - public function groupPriceDataProvider() + public function testGroupPriceCustomerGroupInProduct() { - return [ - [ - 'groupPrice' => [ - [ - 'cust_group' => 1, - 'website_price' => 90.9 - ], - [ - 'cust_group' => 2, - 'website_price' => 80.8 - ], + $this->productMock->expects($this->exactly(2)) + ->method('getCustomerGroupId') + ->will($this->returnValue(3)); + $this->productMock->expects($this->once()) + ->method('getResource') + ->will($this->returnValue($this->productResourceMock)); + $this->productResourceMock->expects($this->once()) + ->method('getAttribute') + ->with($this->equalTo('group_price')) + ->will($this->returnValue($this->attributeMock)); + $this->attributeMock->expects($this->once()) + ->method('getBackend') + ->will($this->returnValue($this->backendMock)); + $this->backendMock->expects($this->once()) + ->method('afterLoad') + ->with($this->equalTo($this->productMock)) + ->will($this->returnValue($this->backendMock)); + $this->productMock->expects($this->once()) + ->method('getData') + ->with( + $this->equalTo('group_price'), + $this->equalTo(null) + ) + ->will($this->returnValue( + [ [ - 'cust_group' => 1, - 'website_price' => 70.7 + 'cust_group' => 3, + 'website_price' => 80 ] - ], - 'customer_group' => 1, - 'expected' => 90.9 - ], - [ - 'groupPrice' => [ - [ - 'cust_group' => 2, - 'website_price' => 10.1 - ], - [ - 'cust_group' => 1, - 'website_price' => 20.2 - ], - ], - 'customer_group' => 1, - 'expected' => 20.2 - ], - [ - 'groupPrice' => [ - [ - 'cust_group' => 1, - 'website_price' => 90.9 - ], - ], - 'customer_group' => 2, - 'expected' => false - ] - ]; + ] + + )); + $this->assertEquals(80, $this->groupPrice->getValue()); } /** - * @return array + * test get group price, attribut is noy srt */ - public function groupPriceNonExistDataProvider() + public function testGroupPriceAttributeIsNotSet() { - return [ - [ - 'groupPrice' => null, - 'expected' => false - ] - ]; + $this->productMock->expects($this->exactly(2)) + ->method('getCustomerGroupId') + ->will($this->returnValue(3)); + $this->productMock->expects($this->once()) + ->method('getResource') + ->will($this->returnValue($this->productResourceMock)); + $this->productResourceMock->expects($this->once()) + ->method('getAttribute') + ->with($this->equalTo('group_price')) + ->will($this->returnValue(null)); + $this->assertFalse($this->groupPrice->getValue()); } } diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryContentValidatorTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryContentValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4dc8ca67d7c8671a815d275db0803fbcf85d6263 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/GalleryEntryContentValidatorTest.php @@ -0,0 +1,167 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media\Data; + +class GalleryEntryContentValidatorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var GalleryEntryContentValidator + */ + private $validator; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $entryContentMock; + + /** + * @var string + */ + private $testImagePath; + + protected function setUp() + { + $this->validator = new GalleryEntryContentValidator(); + $this->entryContentMock = $this->getMock( + '\Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntryContent', + array(), + array(), + '', + false + ); + $this->testImagePath = __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'magento_image.jpg'; + } + + public function testIsValid() + { + $this->entryContentMock->expects($this->any())->method('getData')->will($this->returnValue( + base64_encode(file_get_contents($this->testImagePath)) + )); + $this->entryContentMock->expects($this->any())->method('getName')->will($this->returnValue( + 'valid_name' + )); + $this->entryContentMock->expects($this->any())->method('getMimeType')->will($this->returnValue( + 'image/jpeg' + )); + $this->assertTrue($this->validator->isValid($this->entryContentMock)); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage The image content must be valid base64 encoded data. + */ + public function testIsValidThrowsExceptionIfProvidedContentIsNotBase64Encoded() + { + $this->entryContentMock->expects($this->any())->method('getData')->will($this->returnValue( + 'not_a_base64_encoded_content' + )); + $this->entryContentMock->expects($this->any())->method('getName')->will($this->returnValue( + 'valid_name' + )); + $this->entryContentMock->expects($this->any())->method('getMimeType')->will($this->returnValue( + 'image/jpeg' + )); + $this->assertTrue($this->validator->isValid($this->entryContentMock)); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage The image content must be valid base64 encoded data. + */ + public function testIsValidThrowsExceptionIfProvidedContentIsNotAnImage() + { + $this->entryContentMock->expects($this->any())->method('getData')->will($this->returnValue( + base64_encode('not_an_image_data') + )); + $this->entryContentMock->expects($this->any())->method('getName')->will($this->returnValue( + 'valid_name' + )); + $this->entryContentMock->expects($this->any())->method('getMimeType')->will($this->returnValue( + 'image/jpeg' + )); + $this->assertTrue($this->validator->isValid($this->entryContentMock)); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage The image MIME type is not valid or not supported. + */ + public function testIsValidThrowsExceptionIfProvidedImageHasWrongMimeType() + { + $this->entryContentMock->expects($this->any())->method('getData')->will($this->returnValue( + base64_encode(file_get_contents($this->testImagePath)) + )); + $this->entryContentMock->expects($this->any())->method('getName')->will($this->returnValue( + 'valid_name' + )); + $this->entryContentMock->expects($this->any())->method('getMimeType')->will($this->returnValue( + 'wrong_mime_type' + )); + $this->assertTrue($this->validator->isValid($this->entryContentMock)); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage Provided image name contains forbidden characters. + * @dataProvider getInvalidImageNames + * @param string $imageName + */ + public function testIsValidThrowsExceptionIfProvidedImageNameContainsForbiddenCharacters($imageName) + { + $this->entryContentMock->expects($this->any())->method('getData')->will($this->returnValue( + base64_encode(file_get_contents($this->testImagePath)) + )); + $this->entryContentMock->expects($this->any())->method('getName')->will($this->returnValue( + $imageName + )); + $this->entryContentMock->expects($this->any())->method('getMimeType')->will($this->returnValue( + 'image/jpeg' + )); + $this->assertTrue($this->validator->isValid($this->entryContentMock)); + } + + /** + * @return array + */ + public function getInvalidImageNames() + { + return array( + array('test/test'), + array('test\test'), + array('test:test'), + array('test"test'), + array('test*test'), + array('test;test'), + array('test(test'), + array('test)test'), + array('test<test'), + array('test>test'), + array('test?test'), + array('test{test'), + array('test}test'), + array('test|test'), + array('test|test'), + ); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/_files/magento_image.jpg b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/_files/magento_image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bdda86b647e7f0cae331f3bdff83b07cf3b3dce6 Binary files /dev/null and b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/Data/_files/magento_image.jpg differ diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/GalleryEntryResolverTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/GalleryEntryResolverTest.php new file mode 100644 index 0000000000000000000000000000000000000000..99e49e46caf46d3427b57b4f310dbb62241fa07e --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/GalleryEntryResolverTest.php @@ -0,0 +1,77 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media; + +use \Magento\Catalog\Model\Product; + +class GalleryEntryResolverTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var GalleryEntryResolver + */ + private $entryResolver; + + protected function setUp() + { + $this->entryResolver = new GalleryEntryResolver(); + } + + public function testGetEntryFilePathById() + { + $productMock = $this->getMock('Magento\Catalog\Model\Product', array(), array(), '', false); + $productMock->expects($this->any())->method('getData')->with('media_gallery')->will($this->returnValue(array( + 'images' => array( + array( + 'file' => '/i/m/image.jpg', + 'value_id' => 1, + ), + array( + 'file' => '/i/m/image2.jpg', + 'value_id' => 2, + ), + ), + ))); + $this->assertEquals('/i/m/image2.jpg', $this->entryResolver->getEntryFilePathById($productMock, 2)); + $this->assertNull($this->entryResolver->getEntryFilePathById($productMock, 9999)); + } + + public function testGetEntryIdByFilePath() + { + $productMock = $this->getMock('Magento\Catalog\Model\Product', array(), array(), '', false); + $productMock->expects($this->any())->method('getData')->with('media_gallery')->will($this->returnValue(array( + 'images' => array( + array( + 'file' => '/i/m/image2.jpg', + 'value_id' => 2, + ), + array( + 'file' => '/i/m/image.jpg', + 'value_id' => 1, + ), + ), + ))); + $this->assertEquals(1, $this->entryResolver->getEntryIdByFilePath($productMock, '/i/m/image.jpg')); + $this->assertNull($this->entryResolver->getEntryIdByFilePath($productMock, '/i/m/non_existent_image.jpg')); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/ReadServiceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/ReadServiceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..48506b08ed76eb069349deeac681b4f2ae04c511 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/ReadServiceTest.php @@ -0,0 +1,473 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media; + +class ReadServiceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Catalog\Service\V1\Product\Attribute\Media\ReadService + */ + protected $service; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $collectionFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $setFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $eavConfigMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $setMock; + + /** + * @var int attribute set id to use in tests + */ + protected $attributeSetId = 100123; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $attributeCollectionMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productRepoMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $attributeFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $mediaGalleryMock; + + /** + * @var \Magento\TestFramework\Helper\ObjectManager + */ + protected $objectHelper; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeManagerMock; + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + protected function setUp() + { + $this->objectHelper = new \Magento\TestFramework\Helper\ObjectManager($this); + + $this->collectionFactoryMock = $this->getMock( + 'Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory', + array('create', '__wakeup'), + array(), + '', + false + ); + + $this->attributeCollectionMock = $this->getMock( + 'Magento\Catalog\Model\Resource\Product\Attribute\Collection', + array(), + array(), + '', + false + ); + + $mediaImageBuilder = $this->objectHelper->getObject( + '\Magento\Catalog\Service\V1\Product\Attribute\Media\Data\MediaImageBuilder' + ); + + $this->storeMock = $this->getMock('\Magento\Store\Model\Store', array(), array(), '', false); + + $this->storeManagerMock = $this->getMock('\Magento\Store\Model\StoreManagerInterface'); + $this->storeManagerMock->expects($this->any())->method('getStore')->will($this->returnValue($this->storeMock)); + + $this->setFactoryMock = $this->getMock( + 'Magento\Eav\Model\Entity\Attribute\SetFactory', + array('create', '__wakeup'), + array(), + '', + false + ); + + $this->eavConfigMock = $this->getMock( + '\Magento\Eav\Model\Config', array('getEntityType', 'getId'), array(), '', false + ); + + $this->productRepoMock = $this->getMock( + 'Magento\Catalog\Model\ProductRepository', + array(), + array(), + '', + false + ); + + $this->attributeFactoryMock = $this->getMock( + '\Magento\Catalog\Model\Resource\Eav\AttributeFactory', + array('create', '__wakeup'), + array(), + '', + false + ); + + $this->mediaGalleryMock = $this->getMock( + '\Magento\Catalog\Model\Resource\Product\Attribute\Backend\Media', + array(), + array(), + '', + false + ); + + $builder = $this->objectHelper->getObject( + '\Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntryBuilder' + ); + + $this->service = $this->objectHelper->getObject( + '\Magento\Catalog\Service\V1\Product\Attribute\Media\ReadService', + array( + 'collectionFactory' => $this->collectionFactoryMock, + 'setFactory' => $this->setFactoryMock, + 'eavConfig' => $this->eavConfigMock, + 'mediaImageBuilder' => $mediaImageBuilder, + 'storeManager' => $this->storeManagerMock, + 'productRepository' => $this->productRepoMock, + 'attributeFactory' => $this->attributeFactoryMock, + 'mediaGallery' => $this->mediaGalleryMock, + 'galleryEntryBuilder' => $builder, + ) + ); + + $this->setMock = $this->getMock( + '\Magento\Eav\Model\Entity\Attribute\Set', + array('getEntityTypeId', 'load', 'getId', '__wakeup'), + array(), + '', + false + ); + + $this->productMock = $this->getMock( + 'Magento\Catalog\Model\Product', + array('getMediaGallery', 'getData', 'getMediaAttributes', 'getStoreId', '__wakeup'), + array(), + '', + false + ); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + */ + public function testTypesForAbsentId() + { + $this->setFactoryMock->expects($this->once())->method('create')->will($this->returnValue($this->setMock)); + + $this->setMock->expects($this->once()) + ->method('load') + ->with($this->attributeSetId) + ->will($this->returnSelf()); + + $this->setMock->expects($this->once())->method('getId')->will($this->returnValue(null)); + $this->service->types($this->attributeSetId); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + */ + public function testTypesForWrongEntityType() + { + $this->setFactoryMock->expects($this->once())->method('create')->will($this->returnValue($this->setMock)); + + $this->setMock->expects($this->once()) + ->method('load') + ->with($this->attributeSetId) + ->will($this->returnSelf()); + + $this->setMock->expects($this->once())->method('getId')->will($this->returnValue(1)); + + $this->eavConfigMock->expects($this->once()) + ->method('getEntityType') + ->with(\Magento\Catalog\Model\Product::ENTITY) + ->will($this->returnSelf()); + $this->eavConfigMock->expects($this->once())->method('getId')->will($this->returnValue(1)); + $this->setMock->expects($this->once())->method('getEntityTypeId')->will($this->returnValue(4)); + + $this->service->types($this->attributeSetId); + } + + public function testTypesPositive() + { + $this->setFactoryMock->expects($this->once())->method('create')->will($this->returnValue($this->setMock)); + + $this->setMock->expects($this->once()) + ->method('load') + ->with($this->attributeSetId) + ->will($this->returnSelf()); + + $this->setMock->expects($this->once())->method('getId')->will($this->returnValue(1)); + + $this->eavConfigMock->expects($this->once()) + ->method('getEntityType') + ->with(\Magento\Catalog\Model\Product::ENTITY) + ->will($this->returnSelf()); + $this->eavConfigMock->expects($this->once())->method('getId')->will($this->returnValue(4)); + $this->setMock->expects($this->once())->method('getEntityTypeId')->will($this->returnValue(4)); + + $this->collectionFactoryMock->expects($this->once()) + ->method('create') + ->will($this->returnValue($this->attributeCollectionMock)); + $this->attributeCollectionMock->expects($this->once())->method('setAttributeSetFilter') + ->with($this->attributeSetId); + $this->attributeCollectionMock->expects($this->once()) + ->method('setFrontendInputTypeFilter') + ->with('media_image'); + $attributeMock = $this->getMock( + '\Magento\Catalog\Model\Resource\Eav\Attribute', + array('getStoreLabel', 'getData', 'getIsGlobal', 'isScopeWebsite', 'isScopeStore', '__wakeup'), + array(), + '', + false + ); + $attributeMock->expects($this->once())->method('getStoreLabel')->will($this->returnValue('coolLabel')); + $attributeMock->expects($this->any())->method('getData')->will($this->returnArgument(0)); + $attributeMock->expects($this->once())->method('getIsGlobal')->will($this->returnValue(false)); + $attributeMock->expects($this->once())->method('isScopeWebsite')->will($this->returnValue(false)); + $attributeMock->expects($this->once())->method('isScopeStore')->will($this->returnValue(true)); + + $items = array($attributeMock); + $this->attributeCollectionMock->expects($this->once()) + ->method('getItems') + ->will($this->returnValue($items)); + + $attributes = $this->service->types($this->attributeSetId); + $this->assertEquals(1, count($attributes)); + /** @var \Magento\Catalog\Service\V1\Product\Attribute\Media\Data\MediaImage $resultAttribute */ + $resultAttribute = reset($attributes); + $this->assertEquals('coolLabel', $resultAttribute->getFrontendLabel()); + $this->assertEquals('attribute_code', $resultAttribute->getCode()); + $this->assertEquals(true, $resultAttribute->getIsUserDefined()); + $this->assertEquals('Store View', $resultAttribute->getScope()); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + */ + public function testGetListForAbsentSku() + { + $sku = 'absentSku'; + + $this->productRepoMock->expects($this->once()) + ->method('get') + ->with($sku) + ->will($this->throwException(new \Magento\Framework\Exception\NoSuchEntityException())); + + $this->service->getList($sku); + } + + /** + * @dataProvider getListProvider + */ + public function testGetList($gallery, $result, $productDataMap) + { + $sku = 'anyValidSku'; + $productEntityCode = 4; + $attributes = [ + 'image' => 1, + 'small_image'=> 2, + 'thumbnail' => 3 + ]; + + $this->productRepoMock->expects($this->once()) + ->method('get') + ->with($sku) + ->will($this->returnValue($this->productMock)); + + $this->productMock->expects($this->any()) + ->method('getData')->will($this->returnValueMap($productDataMap)); + + $attributeMock = $this->getMock( + '\Magento\Catalog\Model\Resource\Eav\Attribute', + array(), + array(), + '', + false + ); + + $this->attributeFactoryMock->expects($this->once())->method('create')->will($this->returnValue($attributeMock)); + $this->eavConfigMock->expects($this->once()) + ->method('getEntityType') + ->with(\Magento\Catalog\Model\Product::ENTITY) + ->will($this->returnValue($productEntityCode)); + $attributeMock->expects($this->once())->method('loadByCode')->with($productEntityCode, 'media_gallery'); + $this->mediaGalleryMock->expects($this->once())->method('loadGallery')->will($this->returnValue($gallery)); + $this->productMock->expects($this->once())->method('getMediaAttributes')->will($this->returnValue($attributes)); + + $serviceOutput = $this->service->getList($sku); + $this->assertEquals($result, $serviceOutput); + } + + public function getListProvider() + { + $objectHelper = new \Magento\TestFramework\Helper\ObjectManager($this); + + $dataObject = $objectHelper->getObject( + '\Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntryBuilder'); + $dataObject->populateWithArray( + array( + 'id' => 26, + 'label' => 'Image Alt Text', + 'types' => array('image', 'small_image'), + 'disabled' => 0, + 'position' => 1, + 'file' => '/m/a/magento_image.jpg', + 'store_id' => null, + ) + ); + + $productDataMap = [ + ['image', null, '/m/a/magento_image.jpg'], + ['small_image', null, '/m/a/magento_image.jpg'], + ['thumbnail', null, null], + ]; + + return array( + 'empty gallery' => [array(), array(), array()], + 'one image' => [ + array( + 0 => + array ( + 'value_id' => '26', + 'file' => '/m/a/magento_image.jpg', + 'label_default' => 'Image Alt Text', + 'position_default' => '1', + 'disabled_default' => '0', + ), + ), + array($dataObject->create()), + $productDataMap, + ], + ); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + */ + public function testInfoAbsentSku() + { + $productSku = 'Sku absent'; + $imageId = 123321; + + $this->productRepoMock->expects($this->once()) + ->method('get') + ->with($productSku) + ->will($this->throwException(new \Magento\Framework\Exception\NoSuchEntityException())); + + $this->service->info($productSku, $imageId); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + */ + public function testInfoEmptyGallery() + { + $productSku = 'Sku absent'; + $imageId = 123321; + + $this->productRepoMock->expects($this->once()) + ->method('get') + ->with($productSku) + ->will($this->returnValue($this->productMock)); + + + $this->productMock->expects($this->once()) + ->method('getMediaAttributes') + ->will($this->returnValue(array())); + + $this->productMock->expects($this->once()) + ->method('getMediaGallery') + ->with('images') + ->will($this->returnValue([])); + $this->service->info($productSku, $imageId); + } + + public function testInfo() + { + $productSku = 'Sku absent'; + $imageId = 123321; + $images = [ + [ + 'value_id' => $imageId, + 'file' => '/m/a/magento_image.jpg', + 'label' => 'Image Alt Text', + 'position' => '1', + 'disabled' => '0', + ] + ]; + + $this->productRepoMock->expects($this->once()) + ->method('get') + ->with($productSku) + ->will($this->returnValue($this->productMock)); + + $this->productMock->expects($this->once()) + ->method('getMediaGallery') + ->with('images') + ->will($this->returnValue($images)); + + $this->productMock->expects($this->once()) + ->method('getMediaAttributes') + ->will($this->returnValue(array())); + + $result = $this->service->info($productSku, $imageId); + + $resultImage = reset($images); + $this->assertEquals($resultImage['file'], $result->getFile()); + $this->assertEquals($resultImage['label'], $result->getLabel()); + $this->assertEquals($resultImage['position'], $result->getPosition()); + $this->assertEquals($resultImage['disabled'], $result->isDisabled()); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/WriteServiceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/WriteServiceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9db763c478002fd557b661158523436e74862c71 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/Attribute/Media/WriteServiceTest.php @@ -0,0 +1,324 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product\Attribute\Media; + +use \Magento\Framework\App\Filesystem; + +class WriteServiceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $contentValidatorMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $filesystemMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $mediaConfigMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $productLoaderMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $storeFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $entryResolverMock; + + /** + * @var WriteService + */ + private $service; + + protected function setUp() + { + $this->contentValidatorMock = $this->getMock( + 'Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntryContentValidator', + array(), + array(), + '', + false + ); + $this->filesystemMock = $this->getMock( + 'Magento\Framework\App\Filesystem', + array(), + array(), + '', + false + ); + $this->mediaConfigMock = $this->getMock( + 'Magento\Catalog\Model\Product\Media\Config', + array(), + array(), + '', + false + ); + $this->productLoaderMock = $this->getMock( + 'Magento\Catalog\Service\V1\Product\ProductLoader', + array(), + array(), + '', + false + ); + $this->storeFactoryMock = $this->getMock( + 'Magento\Store\Model\StoreFactory', + array('create'), + array(), + '', + false + ); + $this->entryResolverMock = $this->getMock( + 'Magento\Catalog\Service\V1\Product\Attribute\Media\GalleryEntryResolver', + array(), + array(), + '', + false + ); + + $this->service = new WriteService( + $this->contentValidatorMock, + $this->filesystemMock, + $this->productLoaderMock, + $this->mediaConfigMock, + $this->storeFactoryMock, + $this->entryResolverMock + ); + } + + public function testCreate() + { + $productSku = 'simple'; + $storeId = 1; + $mediaTmpPath = 'tmp'; + $entry = array( + 'disabled' => true, + 'types' => array('image'), + 'label' => 'Image', + 'position' => 100, + ); + $entryContent = array( + 'name' => 'image', + 'mime_type' => 'image/jpg', + 'data' => base64_encode('image_content'), + ); + + $storeMock = $this->getMock('Magento\Store\Model\Store', array(), array(), '', false); + $storeMock->expects($this->any())->method('getId')->will($this->returnValue($storeId)); + $storeMock->expects($this->any())->method('load')->will($this->returnSelf()); + $this->storeFactoryMock->expects($this->once())->method('create')->will($this->returnValue($storeMock)); + $entryMock = $this->getMock( + 'Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntry', + array(), + array(), + '', + false + ); + $entryContentMock = $this->getMock( + 'Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntryContent', + array(), + array(), + '', + false + ); + $this->contentValidatorMock->expects($this->once())->method('isValid')->with($entryContentMock) + ->will($this->returnValue(true)); + $productMock = $this->getMock('Magento\Catalog\Model\Product', array(), array(), '', false); + $this->productLoaderMock->expects($this->once())->method('load')->with($productSku) + ->will($this->returnValue($productMock)); + $this->mediaConfigMock->expects($this->any())->method('getBaseTmpMediaPath') + ->will($this->returnValue($mediaTmpPath)); + $mediaDirectoryMock = $this->getMock('Magento\Framework\Filesystem\Directory\WriteInterface'); + $this->filesystemMock->expects($this->any())->method('getDirectoryWrite')->with(Filesystem::MEDIA_DIR) + ->will($this->returnValue($mediaDirectoryMock)); + + $mediaDirectoryMock->expects($this->once())->method('create')->with($mediaTmpPath); + $mediaDirectoryMock->expects($this->once())->method('delete')->with('tmp' . DIRECTORY_SEPARATOR . 'image.jpg'); + $mediaDirectoryMock->expects($this->any())->method('getAbsolutePath') + ->with('tmp' . DIRECTORY_SEPARATOR . 'image.jpg') + ->will($this->returnValue('/i/m/image.jpg')); + + $mediaDirectoryMock->expects($this->once())->method('writeFile') + ->with('tmp' . DIRECTORY_SEPARATOR . 'image.jpg', 'image_content'); + + $entryContentMock->expects($this->any())->method('getData')->will($this->returnValue($entryContent['data'])); + $entryContentMock->expects($this->any())->method('getName')->will($this->returnValue($entryContent['name'])); + $entryContentMock->expects($this->any())->method('getMimeType')->will($this->returnValue( + $entryContent['mime_type'] + )); + + $entryMock->expects($this->any())->method('isDisabled')->will($this->returnValue($entry['disabled'])); + $entryMock->expects($this->any())->method('getTypes')->will($this->returnValue($entry['types'])); + $entryMock->expects($this->any())->method('getLabel')->will($this->returnValue($entry['label'])); + $entryMock->expects($this->any())->method('getPosition')->will($this->returnValue($entry['position'])); + + $galleryMock = $this->getGalleryAttributeBackendMock($productMock); + $testImageUri = '/i/m/image2.jpg'; + $galleryMock->expects($this->once())->method('addImage')->with( + $productMock, + '/i/m/image.jpg', + $entry['types'], + true, + $entry['disabled'] + )->will($this->returnValue($testImageUri)); + + $galleryMock->expects($this->once())->method('updateImage')->with( + $productMock, + $testImageUri, + array( + 'label' => $entry['label'], + 'position' => $entry['position'], + 'disabled' => $entry['disabled'], + ) + ); + $productMock->expects($this->once())->method('save'); + $galleryMock->expects($this->once())->method('getRenamedImage')->with($testImageUri)->will( + $this->returnValue($testImageUri) + ); + $entryId = 1; + $this->entryResolverMock->expects($this->once())->method('getEntryIdByFilePath') + ->with($productMock, $testImageUri) + ->will($this->returnValue($entryId)); + $this->assertEquals($entryId, $this->service->create($productSku, $entryMock, $entryContentMock, $storeId)); + } + + public function testUpdate() + { + $productSku = 'simple'; + $storeId = 1; + $entry = array( + 'id' => 1, + 'disabled' => true, + 'types' => array('image'), + 'label' => 'Updated Image', + 'position' => 100, + ); + $storeMock = $this->getMock('Magento\Store\Model\Store', array(), array(), '', false); + $storeMock->expects($this->any())->method('getId')->will($this->returnValue($storeId)); + $storeMock->expects($this->any())->method('load')->will($this->returnSelf()); + $this->storeFactoryMock->expects($this->once())->method('create')->will($this->returnValue($storeMock)); + $entryMock = $this->getMock( + 'Magento\Catalog\Service\V1\Product\Attribute\Media\Data\GalleryEntry', + array(), + array(), + '', + false + ); + + $productMock = $this->getMock('Magento\Catalog\Model\Product', array(), array(), '', false); + $this->productLoaderMock->expects($this->once())->method('load')->with($productSku) + ->will($this->returnValue($productMock)); + + $entryMock->expects($this->any())->method('getId')->will($this->returnValue($entry['id'])); + $entryMock->expects($this->any())->method('isDisabled')->will($this->returnValue($entry['disabled'])); + $entryMock->expects($this->any())->method('getTypes')->will($this->returnValue($entry['types'])); + $entryMock->expects($this->any())->method('getLabel')->will($this->returnValue($entry['label'])); + $entryMock->expects($this->any())->method('getPosition')->will($this->returnValue($entry['position'])); + $galleryMock = $this->getGalleryAttributeBackendMock($productMock); + + $testImageUri = '/i/m/image2.jpg'; + $mediaAttributes = array('image' => 'image', 'small_image' => 'small_image', 'thumbnail' => 'thumbnail'); + $productMock->expects($this->any())->method('getMediaAttributes')->will($this->returnValue($mediaAttributes)); + $this->entryResolverMock->expects($this->once())->method('getEntryFilePathById') + ->with($productMock, $entry['id']) + ->will($this->returnValue($testImageUri)); + $galleryMock->expects($this->once())->method('updateImage')->with( + $productMock, + $testImageUri, + array( + 'label' => $entry['label'], + 'position' => $entry['position'], + 'disabled' => $entry['disabled'], + ) + ); + $galleryMock->expects($this->once())->method('clearMediaAttribute') + ->with($productMock, array('image', 'small_image', 'thumbnail')); + $galleryMock->expects($this->once())->method('setMediaAttribute') + ->with($productMock, $entry['types'], $testImageUri); + $productMock->expects($this->once())->method('save'); + + $this->assertTrue($this->service->update($productSku, $entryMock, $storeId)); + } + + public function testDelete() + { + $productSku = 'simple'; + $storeId = 1; + $entryId = 1; + $productMock = $this->getMock('Magento\Catalog\Model\Product', array(), array(), '', false); + $this->productLoaderMock->expects($this->once())->method('load')->with($productSku) + ->will($this->returnValue($productMock)); + + $galleryMock = $this->getGalleryAttributeBackendMock($productMock); + + $testImageUri = '/i/m/image2.jpg'; + + $this->entryResolverMock->expects($this->once())->method('getEntryFilePathById') + ->with($productMock, $entryId) + ->will($this->returnValue($testImageUri)); + $galleryMock->expects($this->once())->method('removeImage')->with($productMock, $testImageUri); + $productMock->expects($this->once())->method('save'); + + $this->assertTrue($this->service->delete($productSku, $entryId, $storeId)); + } + + /** + * Create mock for media gallery attribute backend model + * + * @param \PHPUnit_Framework_MockObject_MockObject $productMock + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getGalleryAttributeBackendMock($productMock) + { + $typeInstanceMock = $this->getMock( + 'Magento\Catalog\Model\Product\Type\Simple', + array(), + array(), + '', + false + ); + $attributeModelMock = $this->getMockForAbstractClass('Magento\Eav\Model\Entity\Attribute\AbstractAttribute', + array(), '', false, false, true, array('getBackend', '__wakeup')); + $productMock->expects($this->any())->method('getTypeInstance')->will($this->returnValue($typeInstanceMock)); + $typeInstanceMock->expects($this->any())->method('getSetAttributes')->with($productMock)->will( + $this->returnValue(array( + 'media_gallery' => $attributeModelMock, + )) + ); + $backendModelMock = $this->getMock('Magento\Catalog\Model\Product\Attribute\Backend\Media', array(), array(), + '', false); + $attributeModelMock->expects($this->any())->method('getBackend')->will($this->returnValue($backendModelMock)); + return $backendModelMock; + } +} diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/AttributeGroup/ReadServiceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/AttributeGroup/ReadServiceTest.php index d961bb8f274465024d73bd975b6f0271430e2230..a4128e4d975dd7cf7f371bc8b79fd8a486ed47a2 100644 --- a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/AttributeGroup/ReadServiceTest.php +++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/AttributeGroup/ReadServiceTest.php @@ -36,6 +36,11 @@ class ReadServiceTest extends \PHPUnit_Framework_TestCase */ protected $groupListFactory; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $setFactoryMock; + protected function setUp() { $helper = new \Magento\TestFramework\Helper\ObjectManager($this); @@ -46,8 +51,15 @@ class ReadServiceTest extends \PHPUnit_Framework_TestCase '', false ); + $this->setFactoryMock = $this->getMock( + '\Magento\Eav\Model\Entity\Attribute\SetFactory', + array('create'), + array(), + '', + false + ); $groupBuilder = $helper->getObject('\Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder'); - $this->service = new ReadService($this->groupListFactory, $groupBuilder); + $this->service = new ReadService($this->groupListFactory, $this->setFactoryMock, $groupBuilder); } public function testListGroups() @@ -60,6 +72,17 @@ class ReadServiceTest extends \PHPUnit_Framework_TestCase false ); $this->groupListFactory->expects($this->once())->method('create')->will($this->returnValue($groupList)); + $attributeSetMock = $this->getMock( + '\Magento\Eav\Model\Entity\Attribute\Set', + array(), + array(), + '', + false + ); + $this->setFactoryMock->expects($this->once())->method('create')->will($this->returnValue($attributeSetMock)); + $attributeSetMock->expects($this->once())->method('load')->with(1)->will($this->returnSelf()); + $attributeSetMock->expects($this->once())->method('getId')->will($this->returnValue(1)); + $item1 = new \Magento\Framework\Object(array('id' => 1, 'attribute_group_name' => 'First')); $item2 = new \Magento\Framework\Object(array('id' => 2, 'attribute_group_name' => 'Second')); $groupList->expects($this->once())->method('getItems')->will($this->returnValue(array($item1, $item2))); @@ -70,4 +93,17 @@ class ReadServiceTest extends \PHPUnit_Framework_TestCase $this->assertEquals('First', $result[0]->getName()); $this->assertEquals('Second', $result[1]->getName()); } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + */ + public function testListGroupsWrongAttributeSet() + { + $attributeSetMock = $this->getMock('\Magento\Eav\Model\Entity\Attribute\Set', [], [], '', false); + $this->setFactoryMock->expects($this->once())->method('create')->will($this->returnValue($attributeSetMock)); + $attributeSetMock->expects($this->once())->method('load')->with(1)->will($this->returnSelf()); + $attributeSetMock->expects($this->once())->method('getId')->will($this->returnValue(null)); + + $this->service->getList(1); + } } diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/AttributeGroup/WriteServiceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/AttributeGroup/WriteServiceTest.php index 9d8c7e507472e60b4f45fa6830acd2a54e12c2fd..95e658feb10f251db30db0cc2ed12ee985a10491 100644 --- a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/AttributeGroup/WriteServiceTest.php +++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/AttributeGroup/WriteServiceTest.php @@ -43,6 +43,11 @@ class WriteServiceTest extends \PHPUnit_Framework_TestCase */ protected $group; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $attributeSetMock; + /** * @var \Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder */ @@ -67,7 +72,8 @@ class WriteServiceTest extends \PHPUnit_Framework_TestCase $this->group = $this->getMock( '\Magento\Catalog\Model\Product\Attribute\Group', array( - 'getId', 'setId', 'setAttributeGroupName', '__wakeUp', 'save', 'load', 'delete', 'hasSystemAttributes' + 'getId', 'setId', 'setAttributeGroupName', '__wakeUp', 'save', 'load', 'delete', 'hasSystemAttributes', + 'getAttributeSetId' ), array(), '', @@ -77,7 +83,17 @@ class WriteServiceTest extends \PHPUnit_Framework_TestCase $this->groupBuilder = $this->objectHelper->getObject( 'Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder' ); - $this->service = new WriteService($this->groupFactory, $this->groupBuilder); + $setFactoryMock = $this->getMock( + '\Magento\Eav\Model\Entity\Attribute\SetFactory', + array('create'), + array(), + '', + false + ); + $this->attributeSetMock = $this->getMock('\Magento\Eav\Model\Entity\Attribute\Set', [], [], '', false); + $this->attributeSetMock->expects($this->any())->method('load')->will($this->returnSelf()); + $setFactoryMock->expects($this->any())->method('create')->will($this->returnValue($this->attributeSetMock)); + $this->service = new WriteService($this->groupFactory, $setFactoryMock, $this->groupBuilder); } /** @@ -85,14 +101,26 @@ class WriteServiceTest extends \PHPUnit_Framework_TestCase */ public function testCreateThrowsException() { + $this->attributeSetMock->expects($this->once())->method('getId')->will($this->returnValue(1)); $this->group->expects($this->once())->method('save')->will($this->throwException(new \Exception())); $groupDataBuilder = $this->objectHelper->getObject('Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder'); $groupDataBuilder->setName('testName'); $this->service->create(1, $groupDataBuilder->create()); } + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + */ + public function testCreateThrowsExceptionIfNoSuchAttributeSetExists() + { + $this->attributeSetMock->expects($this->once())->method('getId')->will($this->returnValue(null)); + $groupDataBuilder = $this->objectHelper->getObject('Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder'); + $this->service->create(1, $groupDataBuilder->create()); + } + public function testCreateCreatesNewAttributeGroup() { + $this->attributeSetMock->expects($this->once())->method('getId')->will($this->returnValue(1)); $this->group->expects($this->once())->method('setAttributeGroupName')->with('testName'); $this->group->expects($this->once())->method('save'); $groupDataBuilder = $this->objectHelper->getObject('Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder'); @@ -107,30 +135,46 @@ class WriteServiceTest extends \PHPUnit_Framework_TestCase { $groupDataBuilder = $this->objectHelper->getObject('Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder'); $groupDataBuilder->setName('testName'); - $this->service->update(1, $groupDataBuilder->create()); + $this->service->update(1, 1, $groupDataBuilder->create()); + } + + /** + * @expectedException \Magento\Framework\Exception\StateException + * @expectedExceptionMessage Attribute group does not belong to provided attribute set + */ + public function testUpdateThrowsExceptionIfTryToUpdateGroupFromWrongAttributeSet() + { + $this->group->expects($this->once())->method('getId')->will($this->returnValue(1)); + $this->group->expects($this->once())->method('getAttributeSetId')->will($this->returnValue(2)); + $groupDataBuilder = $this->objectHelper->getObject('Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder'); + $groupDataBuilder->setName('testName'); + $this->service->update(1, 1, $groupDataBuilder->create()); } /** * @expectedException \Magento\Framework\Exception\CouldNotSaveException + * @expectedExceptionMessage Could not update attribute group */ public function testUpdateThrowsExceptionIfEntityWasNotSaved() { $this->group->expects($this->once())->method('save')->will($this->throwException(new \Exception())); $this->group->expects($this->once())->method('getId')->will($this->returnValue(1)); + $this->group->expects($this->once())->method('getAttributeSetId')->will($this->returnValue(1)); $groupDataBuilder = $this->objectHelper->getObject('Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder'); $groupDataBuilder->setName('testName'); - $this->service->update(1, $groupDataBuilder->create()); + $this->service->update(1, 1, $groupDataBuilder->create()); } public function testUpdateSavesEntity() { $this->group->expects($this->once())->method('save'); $this->group->expects($this->once())->method('getId')->will($this->returnValue(1)); - $this->group->expects($this->once())->method('setId')->with(null); + $this->group->expects($this->once())->method('setId')->with(1); + $this->group->expects($this->once())->method('getAttributeSetId')->will($this->returnValue(1)); $this->group->expects($this->once())->method('setAttributeGroupName')->with('testName'); $groupDataBuilder = $this->objectHelper->getObject('Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder'); $groupDataBuilder->setName('testName'); - $this->service->update(1, $groupDataBuilder->create()); + $this->service->update(1, 1, $groupDataBuilder->create()); } /** @@ -141,23 +185,39 @@ class WriteServiceTest extends \PHPUnit_Framework_TestCase $this->group->expects($this->once())->method('getId')->will($this->returnValue(null)); $groupDataBuilder = $this->objectHelper->getObject('Magento\Catalog\Service\V1\Data\Eav\AttributeGroupBuilder'); $groupDataBuilder->setName('testName'); - $this->service->delete(1, $groupDataBuilder->create()); + $this->service->delete(1, 1); } /** * @expectedException \Magento\Framework\Exception\StateException + * @expectedExceptionMessage Attribute group that contains system attributes can not be deleted */ public function testDeleteThrowsStateExceptionIfTryToDeleteGroupWithSystemAttributes() { + $this->group->expects($this->once())->method('getId')->will($this->returnValue(1)); $this->group->expects($this->once())->method('hasSystemAttributes')->will($this->returnValue(true)); $this->group->expects($this->never())->method('delete'); - $this->service->delete(1); + $this->service->delete(1, 1); + } + + /** + * @expectedException \Magento\Framework\Exception\StateException + * @expectedExceptionMessage Attribute group does not belong to provided attribute set + */ + public function testDeleteThrowsStateExceptionIfTryToDeleteGroupFromWrongAttributeSet() + { + $this->group->expects($this->once())->method('getId')->will($this->returnValue(1)); + $this->group->expects($this->once())->method('hasSystemAttributes')->will($this->returnValue(false)); + $this->group->expects($this->once())->method('getAttributeSetId')->will($this->returnValue(0)); + $this->group->expects($this->never())->method('delete'); + $this->service->delete(1, 1); } public function testDeleteRemovesEntity() { + $this->group->expects($this->once())->method('getAttributeSetId')->will($this->returnValue(1)); $this->group->expects($this->once())->method('getId')->will($this->returnValue(1)); $this->group->expects($this->once())->method('delete'); - $this->service->delete(1); + $this->service->delete(1, 1); } } diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/GroupPriceServiceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/GroupPriceServiceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..20f35475e105b70b2e096b7b8e10abdc4d95d26c --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/GroupPriceServiceTest.php @@ -0,0 +1,338 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product; + +use Magento\Framework\Exception\NoSuchEntityException; + +class GroupPriceServiceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var GroupPriceService + */ + protected $service; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $repositoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $priceBuilderMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeManagerMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $groupServiceMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $priceModifierMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $websiteMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $configMock; + + protected function setUp() + { + $this->repositoryMock = $this->getMock( + '\Magento\Catalog\Model\ProductRepository', array(), array(), '', false + ); + $this->priceBuilderMock = $this->getMock( + 'Magento\Catalog\Service\V1\Data\Product\GroupPriceBuilder', array(), array(), '', false + ); + $this->storeManagerMock = $this->getMock('\Magento\Store\Model\StoreManagerInterface'); + $this->groupServiceMock = $this->getMock('\Magento\Customer\Service\V1\CustomerGroupServiceInterface'); + + $this->priceModifierMock = + $this->getMock('Magento\Catalog\Model\Product\PriceModifier', array(), array(), '', false); + $this->websiteMock = + $this->getMock('Magento\Store\Model\Website', array('getId', '__wakeup'), array(), '', false); + $this->productMock = $this->getMock('Magento\Catalog\Model\Product', + array('getData', 'setData', 'validate', 'save', 'getIdBySku', 'load', '__wakeup'), array(), '', false); + $this->repositoryMock->expects($this->any())->method('get')->with('product_sku') + ->will($this->returnValue($this->productMock)); + $this->configMock = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface'); + $this->service = new GroupPriceService( + $this->repositoryMock, + $this->priceBuilderMock, + $this->storeManagerMock, + $this->groupServiceMock, + $this->priceModifierMock, + $this->configMock + ); + } + + /** + * @param string $configValue + * @param array $groupData + * @param array $expected + * @dataProvider getListDataProvider + */ + public function testGetList($configValue, $groupData, $expected) + { + $this->repositoryMock->expects($this->once())->method('get')->with('product_sku') + ->will($this->returnValue($this->productMock)); + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('group_price') + ->will($this->returnValue(array($groupData))); + $this->configMock + ->expects($this->once()) + ->method('getValue') + ->with('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) + ->will($this->returnValue($configValue)); + $this->priceBuilderMock + ->expects($this->once()) + ->method('populateWithArray') + ->with($expected); + $this->priceBuilderMock + ->expects($this->once()) + ->method('create') + ->will($this->returnValue('data')); + $prices = $this->service->getList('product_sku'); + $this->assertCount(1, $prices); + $this->assertEquals('data', $prices[0]); + } + + public function getListDataProvider() + { + return array( + array( + 1, + array('website_price' => 10, 'price' => 5, 'all_groups' => 1), + array('customer_group_id' => 'all', 'value' => 10) + ), + array( + 0, + array('website_price' => 10, 'price' => 5, 'all_groups' => 0, 'cust_group' => 1), + array('customer_group_id' => 1, 'value' => 5) + ) + ); + } + + public function testSuccessDeleteGroupPrice() + { + $this->storeManagerMock + ->expects($this->never()) + ->method('getWebsite'); + $this->configMock + ->expects($this->once()) + ->method('getValue') + ->with('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) + ->will($this->returnValue(0)); + $this->priceModifierMock->expects($this->once())->method('removeGroupPrice')->with($this->productMock, 4, 0); + + $this->assertEquals(true, $this->service->delete('product_sku', 4)); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @message Such product doesn't exist + */ + public function testDeleteGroupPriceFromNonExistingProduct() + { + $this->repositoryMock->expects($this->once())->method('get') + ->will($this->throwException(new NoSuchEntityException())); + $this->priceModifierMock->expects($this->never())->method('removeGroupPrice'); + $this->storeManagerMock + ->expects($this->never()) + ->method('getWebsite'); + $this->service->delete('product_sku', null, 10); + } + + public function testSuccessDeleteGroupPriceFromWebsiteLevel() + { + $this->storeManagerMock + ->expects($this->once()) + ->method('getWebsite') + ->will($this->returnValue($this->websiteMock)); + $this->websiteMock->expects($this->once())->method('getId')->will($this->returnValue(1)); + $this->configMock + ->expects($this->once()) + ->method('getValue') + ->with('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) + ->will($this->returnValue(1)); + $this->priceModifierMock->expects($this->once())->method('removeGroupPrice')->with($this->productMock, 4, 1); + + $this->assertEquals(true, $this->service->delete('product_sku', 4)); + } + + public function testSetNewPriceWithGlobalPriceScope() + { + $priceBuilder = $this->getMock( + '\Magento\Catalog\Service\V1\Data\Product\GroupPriceBuilder', array(), array(), '', false + ); + $priceBuilder->expects($this->any())->method('getData')->will($this->returnValue(array( + 'customer_group_id' => 1, + 'value' => 100 + ))); + $price = new \Magento\Catalog\Service\V1\Data\Product\GroupPrice($priceBuilder); + $groupBuilder = $this->getMock( + '\Magento\Customer\Service\V1\Data\CustomerGroupBuilder', array(), array(), '', false + ); + $groupBuilder->expects($this->any())->method('getData')->will($this->returnValue(array('id' => 1))); + $group = new \Magento\Customer\Service\V1\Data\CustomerGroup($groupBuilder); + $this->groupServiceMock->expects($this->once())->method('getGroup')->will($this->returnValue($group)); + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('group_price') + ->will($this->returnValue(array(array('cust_group' => 2, 'website_id' => 0, 'price' => 50)))); + $this->configMock + ->expects($this->once()) + ->method('getValue') + ->with('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) + ->will($this->returnValue(0)); + + $this->productMock->expects($this->once())->method('setData')->with( + 'group_price', + array( + array('cust_group' => 2, 'website_id' => 0, 'price' => 50), + array('cust_group' => 1, 'website_id' => 0, 'price' => 100) + ) + ); + $this->productMock->expects($this->once())->method('save'); + $this->service->set('product_sku', $price); + } + + public function testSetUpdatedPriceWithGlobalPriceScope() + { + $priceBuilder = $this->getMock( + '\Magento\Catalog\Service\V1\Data\Product\GroupPriceBuilder', array(), array(), '', false + ); + $priceBuilder->expects($this->any())->method('getData')->will($this->returnValue(array( + 'customer_group_id' => 2, + 'value' => 100 + ))); + $price = new \Magento\Catalog\Service\V1\Data\Product\GroupPrice($priceBuilder); + $groupBuilder = $this->getMock( + '\Magento\Customer\Service\V1\Data\CustomerGroupBuilder', array(), array(), '', false + ); + $groupBuilder->expects($this->any())->method('getData')->will($this->returnValue(array('id' => 1))); + $group = new \Magento\Customer\Service\V1\Data\CustomerGroup($groupBuilder); + $this->groupServiceMock->expects($this->once())->method('getGroup')->will($this->returnValue($group)); + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('group_price') + ->will($this->returnValue(array(array('cust_group' => 2, 'website_id' => 0, 'price' => 50)))); + $this->configMock + ->expects($this->once()) + ->method('getValue') + ->with('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) + ->will($this->returnValue(0)); + + $this->productMock->expects($this->once())->method('setData')->with( + 'group_price', + array( + array('cust_group' => 2, 'website_id' => 0, 'price' => 100), + ) + ); + $this->productMock->expects($this->once())->method('save'); + $this->service->set('product_sku', $price); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage Values of following attributes are invalid: attr1, attr2 + */ + public function testSetThrowsExceptionIfDoesntValidate() + { + $priceBuilder = $this->getMock( + '\Magento\Catalog\Service\V1\Data\Product\GroupPriceBuilder', array(), array(), '', false + ); + $priceBuilder->expects($this->any())->method('getData')->will($this->returnValue(array( + 'customer_group_id' => 2, + 'value' => 100 + ))); + $price = new \Magento\Catalog\Service\V1\Data\Product\GroupPrice($priceBuilder); + $groupBuilder = $this->getMock( + '\Magento\Customer\Service\V1\Data\CustomerGroupBuilder', array(), array(), '', false + ); + $groupBuilder->expects($this->any())->method('getData')->will($this->returnValue(array('id' => 1))); + $group = new \Magento\Customer\Service\V1\Data\CustomerGroup($groupBuilder); + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('group_price') + ->will($this->returnValue(array())); + + $this->groupServiceMock->expects($this->once())->method('getGroup')->will($this->returnValue($group)); + $this->productMock->expects($this->once())->method('validate')->will($this->returnValue( + array('attr1' => '', 'attr2' => '') + )); + $this->productMock->expects($this->never())->method('save'); + $this->service->set('product_sku', $price); + } + + /** + * @expectedException \Magento\Framework\Exception\CouldNotSaveException + */ + public function testSetThrowsExceptionIfCantSave() + { + $priceBuilder = $this->getMock( + '\Magento\Catalog\Service\V1\Data\Product\GroupPriceBuilder', array(), array(), '', false + ); + $priceBuilder->expects($this->any())->method('getData')->will($this->returnValue(array( + 'customer_group_id' => 2, + 'value' => 100 + ))); + $price = new \Magento\Catalog\Service\V1\Data\Product\GroupPrice($priceBuilder); + $groupBuilder = $this->getMock( + '\Magento\Customer\Service\V1\Data\CustomerGroupBuilder', array(), array(), '', false + ); + $groupBuilder->expects($this->any())->method('getData')->will($this->returnValue(array('id' => 1))); + $group = new \Magento\Customer\Service\V1\Data\CustomerGroup($groupBuilder); + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('group_price') + ->will($this->returnValue(array())); + + $this->groupServiceMock->expects($this->once())->method('getGroup')->will($this->returnValue($group)); + $this->productMock->expects($this->once())->method('save')->will($this->throwException(new \Exception())); + $this->service->set('product_sku', $price); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/TierPriceServiceTest.php b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/TierPriceServiceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..476cc986eda16264b912a25c1bf2af1233e39a28 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Catalog/Service/V1/Product/TierPriceServiceTest.php @@ -0,0 +1,357 @@ +<?php +/** + * + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Catalog\Service\V1\Product; + +use Magento\Framework\Exception\NoSuchEntityException; + +class TierPriceServiceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var TierPriceService + */ + protected $service; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $repositoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $priceBuilderMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeManagerMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $groupServiceMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $priceModifierMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $websiteMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $configMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $productMock; + + protected function setUp() + { + $this->repositoryMock = $this->getMock( + '\Magento\Catalog\Model\ProductRepository', array(), array(), '', false + ); + $this->priceBuilderMock = $this->getMock( + '\Magento\Catalog\Service\V1\Data\Product\TierPriceBuilder', array(), array(), '', false + ); + $this->storeManagerMock = $this->getMock('\Magento\Store\Model\StoreManagerInterface'); + $this->groupServiceMock = $this->getMock('\Magento\Customer\Service\V1\CustomerGroupServiceInterface'); + $this->websiteMock = + $this->getMock('Magento\Store\Model\Website', array('getId', '__wakeup'), array(), '', false); + $this->productMock = $this->getMock('Magento\Catalog\Model\Product', + array('getData', 'getIdBySku', 'load', '__wakeup', 'save', 'validate', 'setData'), array(), '', false); + $this->configMock = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface'); + $this->priceModifierMock = + $this->getMock('Magento\Catalog\Model\Product\PriceModifier', array(), array(), '', false); + $this->repositoryMock->expects($this->any())->method('get')->with('product_sku') + ->will($this->returnValue($this->productMock)); + + $this->service = new TierPriceService( + $this->repositoryMock, + $this->priceBuilderMock, + $this->storeManagerMock, + $this->priceModifierMock, + $this->configMock, + $this->groupServiceMock + ); + } + + /** + * @param $configValue + * @param $customerGroupId + * @param $groupData + * @param $expected + * @dataProvider getListDataProvider + */ + public function testGetList($configValue, $customerGroupId, $groupData, $expected) + { + $this->repositoryMock->expects($this->once())->method('get')->with('product_sku') + ->will($this->returnValue($this->productMock)); + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('tier_price') + ->will($this->returnValue(array($groupData))); + $this->configMock + ->expects($this->once()) + ->method('getValue') + ->with('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) + ->will($this->returnValue($configValue)); + if ($expected) { + $this->priceBuilderMock + ->expects($this->once()) + ->method('populateWithArray') + ->with($expected); + $this->priceBuilderMock + ->expects($this->once()) + ->method('create') + ->will($this->returnValue('data')); + } else { + $this->priceBuilderMock->expects($this->never())->method('populateWithArray'); + } + $prices = $this->service->getList('product_sku', $customerGroupId); + $this->assertCount($expected ? 1 : 0, $prices); + if ($expected) { + $this->assertEquals('data', $prices[0]); + } + } + + public function getListDataProvider() + { + return array( + array( + 1, + 'all', + array('website_price' => 10, 'price' => 5, 'all_groups' => 1, 'price_qty' => 5), + array('value' => 10, 'qty' => 5) + ), + array( + 0, + 1, + array('website_price' => 10, 'price' => 5, 'all_groups' => 0, 'cust_group' => 1, 'price_qty' => 5), + array('value' => 5, 'qty' => 5) + ), + array( + 0, + 'all', + array('website_price' => 10, 'price' => 5, 'all_groups' => 0, 'cust_group' => 1, 'price_qty' => 5), + array() + ) + ); + } + + public function testSuccessDeleteTierPrice() + { + $this->storeManagerMock + ->expects($this->never()) + ->method('getWebsite'); + $this->configMock + ->expects($this->once()) + ->method('getValue') + ->with('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) + ->will($this->returnValue(0)); + $this->priceModifierMock->expects($this->once())->method('removeTierPrice')->with($this->productMock, 4, 5, 0); + + $this->assertEquals(true, $this->service->delete('product_sku', 4, 5, 0)); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @message Such product doesn't exist + */ + public function testDeleteTierPriceFromNonExistingProduct() + { + $this->repositoryMock->expects($this->once())->method('get') + ->will($this->throwException(new NoSuchEntityException())); + $this->priceModifierMock->expects($this->never())->method('removeTierPrice'); + $this->storeManagerMock + ->expects($this->never()) + ->method('getWebsite'); + $this->service->delete('product_sku', null, 10, 5); + } + + public function testSuccessDeleteTierPriceFromWebsiteLevel() + { + $this->storeManagerMock + ->expects($this->once()) + ->method('getWebsite') + ->will($this->returnValue($this->websiteMock)); + $this->websiteMock->expects($this->once())->method('getId')->will($this->returnValue(1)); + $this->configMock + ->expects($this->once()) + ->method('getValue') + ->with('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) + ->will($this->returnValue(1)); + $this->priceModifierMock->expects($this->once())->method('removeTierPrice')->with($this->productMock, 4, 5, 1); + + $this->assertEquals(true, $this->service->delete('product_sku', 4, 5, 6)); + } + + public function testSetNewPriceWithGlobalPriceScope() + { + $priceBuilder = $this->getMock( + '\Magento\Catalog\Service\V1\Data\Product\TierPriceBuilder', array(), array(), '', false + ); + $priceBuilder->expects($this->any())->method('getData')->will($this->returnValue(array( + 'qty' => 3, + 'value' => 100 + ))); + $price = new \Magento\Catalog\Service\V1\Data\Product\TierPrice($priceBuilder); + $groupBuilder = $this->getMock( + '\Magento\Customer\Service\V1\Data\CustomerGroupBuilder', array(), array(), '', false + ); + $groupBuilder->expects($this->any())->method('getData')->will($this->returnValue(array('id' => 1))); + $group = new \Magento\Customer\Service\V1\Data\CustomerGroup($groupBuilder); + $this->groupServiceMock->expects($this->once())->method('getGroup')->will($this->returnValue($group)); + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('tier_price') + ->will($this->returnValue( + array(array('cust_group' => 1, 'website_id' => 0, 'price_qty' => 4, 'price' => 50)) + )); + $this->configMock + ->expects($this->once()) + ->method('getValue') + ->with('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) + ->will($this->returnValue(0)); + + $this->productMock->expects($this->once())->method('setData')->with( + 'tier_price', + array( + array('cust_group' => 1, 'website_id' => 0, 'price_qty' => 4, 'price' => 50), + array('cust_group' => 1, 'website_id' => 0, 'price_qty' => 3, 'price' => 100, 'website_price' => 100) + ) + ); + $this->productMock->expects($this->once())->method('save'); + $this->service->set('product_sku', 1, $price); + } + + public function testSetUpdatedPriceWithGlobalPriceScope() + { + $priceBuilder = $this->getMock( + '\Magento\Catalog\Service\V1\Data\Product\TierPriceBuilder', array(), array(), '', false + ); + $priceBuilder->expects($this->any())->method('getData')->will($this->returnValue(array( + 'qty' => 3, + 'value' => 100 + ))); + $price = new \Magento\Catalog\Service\V1\Data\Product\TierPrice($priceBuilder); + $groupBuilder = $this->getMock( + '\Magento\Customer\Service\V1\Data\CustomerGroupBuilder', array(), array(), '', false + ); + $groupBuilder->expects($this->any())->method('getData')->will($this->returnValue(array('id' => 1))); + $group = new \Magento\Customer\Service\V1\Data\CustomerGroup($groupBuilder); + $this->groupServiceMock->expects($this->once())->method('getGroup')->will($this->returnValue($group)); + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('tier_price') + ->will($this->returnValue( + array(array('cust_group' => 1, 'website_id' => 0, 'price_qty' => 3, 'price' => 50))) + ); + $this->configMock + ->expects($this->once()) + ->method('getValue') + ->with('catalog/price/scope', \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE) + ->will($this->returnValue(0)); + + $this->productMock->expects($this->once())->method('setData')->with( + 'tier_price', + array( + array('cust_group' => 1, 'website_id' => 0, 'price_qty' => 3, 'price' => 100) + ) + ); + $this->productMock->expects($this->once())->method('save'); + $this->service->set('product_sku', 1, $price); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage Values of following attributes are invalid: attr1, attr2 + */ + public function testSetThrowsExceptionIfDoesntValidate() + { + $priceBuilder = $this->getMock( + '\Magento\Catalog\Service\V1\Data\Product\TierPriceBuilder', array(), array(), '', false + ); + $priceBuilder->expects($this->any())->method('getData')->will($this->returnValue(array( + 'qty' => 2, + 'value' => 100 + ))); + $price = new \Magento\Catalog\Service\V1\Data\Product\TierPrice($priceBuilder); + $groupBuilder = $this->getMock( + '\Magento\Customer\Service\V1\Data\CustomerGroupBuilder', array(), array(), '', false + ); + $groupBuilder->expects($this->any())->method('getData')->will($this->returnValue(array('id' => 1))); + $group = new \Magento\Customer\Service\V1\Data\CustomerGroup($groupBuilder); + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('tier_price') + ->will($this->returnValue(array())); + + $this->groupServiceMock->expects($this->once())->method('getGroup')->will($this->returnValue($group)); + $this->productMock->expects($this->once())->method('validate')->will($this->returnValue( + array('attr1' => '', 'attr2' => '') + )); + $this->productMock->expects($this->never())->method('save'); + $this->service->set('product_sku', 1, $price); + } + + /** + * @expectedException \Magento\Framework\Exception\CouldNotSaveException + */ + public function testSetThrowsExceptionIfCantSave() + { + $priceBuilder = $this->getMock( + '\Magento\Catalog\Service\V1\Data\Product\TierPriceBuilder', array(), array(), '', false + ); + $priceBuilder->expects($this->any())->method('getData')->will($this->returnValue(array( + 'qty' => 2, + 'value' => 100 + ))); + $price = new \Magento\Catalog\Service\V1\Data\Product\TierPrice($priceBuilder); + $groupBuilder = $this->getMock( + '\Magento\Customer\Service\V1\Data\CustomerGroupBuilder', array(), array(), '', false + ); + $groupBuilder->expects($this->any())->method('getData')->will($this->returnValue(array('id' => 1))); + $group = new \Magento\Customer\Service\V1\Data\CustomerGroup($groupBuilder); + $this->productMock + ->expects($this->once()) + ->method('getData') + ->with('tier_price') + ->will($this->returnValue(array())); + + $this->groupServiceMock->expects($this->once())->method('getGroup')->will($this->returnValue($group)); + $this->productMock->expects($this->once())->method('save')->will($this->throwException(new \Exception())); + $this->service->set('product_sku', 1, $price); + } +} diff --git a/dev/tests/unit/testsuite/Magento/Eav/Model/Resource/Attribute/CollectionTest.php b/dev/tests/unit/testsuite/Magento/Eav/Model/Resource/Attribute/CollectionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..056c44d6fc5279322ae8bba72bd9fcbb52ecd427 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Eav/Model/Resource/Attribute/CollectionTest.php @@ -0,0 +1,230 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +namespace Magento\Eav\Model\Resource\Attribute; + +class CollectionTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Eav\Model\Resource\Attribute\Collection|\PHPUnit_Framework_MockObject_MockObject + */ + protected $model; + + /** + * @var \Magento\Core\Model\EntityFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $entityFactoryMock; + + /** + * @var \Magento\Framework\Logger|\PHPUnit_Framework_MockObject_MockObject + */ + protected $loggerMock; + + /** + * @var \Magento\Framework\Data\Collection\Db\FetchStrategyInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $fetchStrategyMock; + + /** + * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $eventManagerMock; + + /** + * @var \Magento\Eav\Model\Config|\PHPUnit_Framework_MockObject_MockObject + */ + protected $eavConfigMock; + + /** + * @var \Magento\Eav\Model\Entity\Type + */ + protected $entityTypeMock; + + /** + * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $storeManagerMock; + + /** + * @var \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject + */ + protected $connectionMock; + + /** + * @var \Magento\Framework\Model\Resource\Db\AbstractDb|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceMock; + + /** + * @var \Zend_Db_Select|\PHPUnit_Framework_MockObject_MockObject + */ + protected $selectMock; + + protected function setUp() + { + $this->entityFactoryMock = $this->getMock('Magento\Core\Model\EntityFactory', array(), array(), '', false); + $this->loggerMock = $this->getMock('Magento\Framework\Logger', array(), array(), '', false); + $this->fetchStrategyMock = $this->getMock('Magento\Framework\Data\Collection\Db\FetchStrategyInterface'); + $this->eventManagerMock = $this->getMock('Magento\Framework\Event\ManagerInterface'); + + $this->eavConfigMock = $this->getMock('Magento\Eav\Model\Config', array(), array(), '', false); + $this->entityTypeMock = $this->getMock('Magento\Eav\Model\Entity\Type', array('__wakeup'), array(), '', false); + $this->entityTypeMock->setAdditionalAttributeTable('some_extra_table'); + $this->eavConfigMock->expects($this->any()) + ->method('getEntityType') + ->will($this->returnValue($this->entityTypeMock)); + + $this->storeManagerMock = $this->getMock('Magento\Store\Model\StoreManagerInterface'); + $this->storeManagerMock->expects($this->any()) + ->method('getStore') + ->will($this->returnSelf()); + + $adapter = $this->getMockForAbstractClass('Zend_Db_Adapter_Abstract', array(), '', false); + + $this->selectMock = $this->getMock('Zend_Db_Select', null, array($adapter)); + + $this->connectionMock = $this->getMock( + 'Magento\Framework\DB\Adapter\Pdo\Mysql', + array('select','describeTable', 'quoteIdentifier', '_connect', '_quote'), + array(), + '', + false); + + $this->resourceMock = $this->getMockForAbstractClass( + 'Magento\Framework\Model\Resource\Db\AbstractDb', + array(), + '', + false, + true, + true, + array('__wakeup', 'getReadConnection', 'getMainTable', 'getTable') + ); + + $this->connectionMock->expects($this->any()) + ->method('select') + ->will($this->returnValue($this->selectMock)); + $this->connectionMock->expects($this->any()) + ->method('quoteIdentifier') + ->will($this->returnArgument(0)); + $this->connectionMock->expects($this->any()) + ->method('describeTable') + ->will($this->returnvalueMap( + array( + array( + 'some_main_table', + null, + array( + 'col1' => array(), + 'col2' => array(), + ) + ), + array( + 'some_extra_table', + null, + array( + 'col2' => array(), + 'col3' => array(), + ) + ), + array( + null, + null, + array( + 'col2' => array(), + 'col3' => array(), + 'col4' => array(), + ) + ), + ) + )); + $this->connectionMock->expects($this->any()) + ->method('_quote') + ->will($this->returnArgument(0)); + + $this->resourceMock->expects($this->any()) + ->method('getReadConnection') + ->will($this->returnValue($this->connectionMock)); + $this->resourceMock->expects($this->any()) + ->method('getMainTable') + ->will($this->returnValue('some_main_table')); + $this->resourceMock->expects($this->any()) + ->method('getTable') + ->will( + $this->returnValue('some_extra_table') + ); + } + + /** + * Test that Magento\Eav\Model\Resource\Attribute\Collection::_initSelect sets expressions + * that can be properly quoted by Zend_Db_Expr::quoteIdentifier + * + * @dataProvider initSelectDataProvider + */ + public function testInitSelect($column, $value, $expected) + { + $helper = new \Magento\TestFramework\Helper\ObjectManager($this); + $this->model = $helper->getObject('\Magento\Customer\Model\Resource\Attribute\Collection', + array( + 'entityFactory' => $this->entityFactoryMock, + 'logger' => $this->loggerMock, + 'fetchStrategy' => $this->fetchStrategyMock, + 'eventManager' => $this->eventManagerMock, + 'eavConfig' => $this->eavConfigMock, + 'storeManager' => $this->storeManagerMock, + 'connection' => $this->connectionMock, + 'resource' => $this->resourceMock + ) + ); + + $this->model->addFieldToFilter($column, $value); + $this->assertEquals($expected, $this->model->getSelectCountSql()->assemble()); + } + + public function initSelectDataProvider() + { + return array( + 'main_table_expression' => array( + 'col2', '1', + 'SELECT COUNT(*) FROM "some_main_table" AS "main_table"' . "\n" + . ' INNER JOIN "some_extra_table" AS "additional_table"' + . ' ON additional_table.attribute_id = main_table.attribute_id' . "\n" + . ' LEFT JOIN "some_extra_table" AS "scope_table"' + . ' ON scope_table.attribute_id = main_table.attribute_id' + . ' AND scope_table.website_id = :scope_website_id' + . ' WHERE (main_table.entity_type_id = :mt_entity_type_id)' + . ' AND (IF(main_table.col2 IS NULL, scope_table.col2, main_table.col2) = 1)' + ), + 'additional_table_expression' => array( + 'col3', '2', + 'SELECT COUNT(*) FROM "some_main_table" AS "main_table"' . "\n" + . ' INNER JOIN "some_extra_table" AS "additional_table"' + . ' ON additional_table.attribute_id = main_table.attribute_id'. "\n" + . ' LEFT JOIN "some_extra_table" AS "scope_table"' + . ' ON scope_table.attribute_id = main_table.attribute_id' + . ' AND scope_table.website_id = :scope_website_id' + . ' WHERE (main_table.entity_type_id = :mt_entity_type_id)' + . ' AND (IF(additional_table.col3 IS NULL, scope_table.col3, additional_table.col3) = 2)' + ) + ); + } +} diff --git a/dev/tests/unit/testsuite/Magento/SalesRule/Model/ValidatorTest.php b/dev/tests/unit/testsuite/Magento/SalesRule/Model/ValidatorTest.php index dbd6d6b4e23ad6926830afcb10eec246e7099f60..3d8e21bf9d0b5d02ec85e3e9e4522c182fffe976 100644 --- a/dev/tests/unit/testsuite/Magento/SalesRule/Model/ValidatorTest.php +++ b/dev/tests/unit/testsuite/Magento/SalesRule/Model/ValidatorTest.php @@ -32,6 +32,7 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase protected function setUp() { + // @TODO Re-write test according to standards of writing test (e.g do not mock tested class) $this->model = $this->getMock( 'Magento\SalesRule\Model\Validator', array('_getRules', '_getItemOriginalPrice', '_getItemBaseOriginalPrice', '__wakeup'), @@ -97,8 +98,6 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase $quote->setVirtualItemsQty(2); $this->assertTrue($this->model->canApplyRules($item)); - - return true; } public function testProcess() @@ -449,4 +448,47 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase return $validator; } + + public function testInit() + { + $websiteId = 1; + $customerGroupId = 2; + $couponCode = 'code'; + + $ruleCollection = $this->getMockBuilder('Magento\SalesRule\Model\Resource\Rule\Collection') + ->disableOriginalConstructor() + ->getMock(); + $ruleCollection->expects($this->once()) + ->method('setValidationFilter') + ->with($websiteId, $customerGroupId, $couponCode) + ->will($this->returnSelf()); + $ruleCollection->expects($this->once()) + ->method('addFieldToFilter') + ->with('is_active', 1) + ->will($this->returnSelf()); + $ruleCollection->expects($this->once()) + ->method('load') + ->will($this->returnSelf()); + + $ruleCollectionFactoryMock = $this->getMockBuilder('Magento\SalesRule\Model\Resource\Rule\CollectionFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $ruleCollectionFactoryMock->expects($this->once()) + ->method('create') + ->will($this->returnValue($ruleCollection)); + + $helper = new \Magento\TestFramework\Helper\ObjectManager($this); + $model = $helper->getObject( + 'Magento\SalesRule\Model\Validator', + [ + 'collectionFactory' => $ruleCollectionFactoryMock + ] + ); + + $this->assertInstanceOf( + 'Magento\SalesRule\Model\Validator', + $model->init($websiteId, $customerGroupId, $couponCode) + ); + } } diff --git a/dev/tests/unit/testsuite/Magento/Tax/Model/ConfigTest.php b/dev/tests/unit/testsuite/Magento/Tax/Model/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3502632adeb076bb3cb6a07574ff8523f59561dc --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Tax/Model/ConfigTest.php @@ -0,0 +1,405 @@ +<?php +/** + * Magento + * + * NOTICE OF LICENSE + * + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available through the world-wide-web at this URL: + * http://opensource.org/licenses/osl-3.0.php + * If you did not receive a copy of the license and are unable to + * obtain it through the world-wide-web, please send an email + * to license@magentocommerce.com so we can send you a copy immediately. + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Magento to newer + * versions in the future. If you wish to customize Magento for your + * needs please refer to http://www.magentocommerce.com for more information. + * + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ + +/** + * Test class for \Magento\Tax\Model\Config + */ +namespace Magento\Tax\Model; + +use Magento\Tax\Model\Config; + +class ConfigTest extends \PHPUnit_Framework_TestCase +{ + /** + * Tests the setter/getter methods that bypass the ScopeConfigInterface object + * + * @param string $setterMethod + * @param string $getterMethod + * @param bool $value + * @dataProvider dataProviderDirectSettersGettersMethods + */ + public function testDirectSettersGettersMethods($setterMethod, $getterMethod, $value) + { + // Need a mocked object with only dummy methods. It is just needed for construction. + // The setter/getter methods do not use this object (for this set of tests). + $scopeConfigMock = $this->getMockForAbstractClass('Magento\Framework\App\Config\ScopeConfigInterface'); + + /** @var \Magento\Tax\Model\Config */ + $model = new Config($scopeConfigMock); + $model->{$setterMethod}($value); + $this->assertEquals($value, $model->{$getterMethod}()); + } + + /** + * Returns a set of 'true' and 'false' parameters for each of the setter/getter method pairs + * + * @return array + */ + public function dataProviderDirectSettersGettersMethods() + { + return $this->_buildTrueFalsePairs( + [ + [ + 'setShippingPriceIncludeTax', + 'shippingPriceIncludesTax' + ], + [ + 'setNeedUseShippingExcludeTax', + 'getNeedUseShippingExcludeTax' + ], + [ + 'setPriceIncludesTax', + 'priceIncludesTax' + ] + ] + ); + } + + /** + * Returns an output array that is twice the size of the input array by adding 'true' and then 'false' to the + * set of parameters given + * + * @param array $arrayIn + * @return array + */ + protected function _buildTrueFalsePairs($arrayIn) + { + $arrayOut = []; + + foreach ($arrayIn as $paramArray) { + // replicate the paramArray, append 'true', and add the new array to the output array + $arrayT = $paramArray; + $arrayT[] = true; + $arrayOut[] = $arrayT; + // replicate the paramArray, append 'false', and add the new array to the output array + $arrayF = $paramArray; + $arrayF[] = false; + $arrayOut[] = $arrayF; + } + + return $arrayOut; + } + + + /** + * Tests the getCalculationSequence method + * + * @param bool $applyTaxAfterDiscount + * @param bool $discountTaxIncl + * @param string $expectedValue + * @dataProvider dataProviderGetCalculationSequence + */ + public function testGetCalculationSequence($applyTaxAfterDiscount, $discountTaxIncl, $expectedValue) + { + $scopeConfigMock = $this->getMockForAbstractClass('Magento\Framework\App\Config\ScopeConfigInterface'); + $scopeConfigMock->expects( + $this->at(0))->method('getValue')->will($this->returnValue($applyTaxAfterDiscount)); + $scopeConfigMock->expects( + $this->at(1))->method('getValue')->will($this->returnValue($discountTaxIncl)); + + /** @var \Magento\Tax\Model\Config */ + $model = new Config($scopeConfigMock); + $this->assertEquals($expectedValue, $model->getCalculationSequence()); + } + + /** + * @return array + */ + public function dataProviderGetCalculationSequence() + { + return [ + [true, true, \Magento\Tax\Model\Calculation::CALC_TAX_AFTER_DISCOUNT_ON_INCL], + [true, false, \Magento\Tax\Model\Calculation::CALC_TAX_AFTER_DISCOUNT_ON_EXCL], + [false, true, \Magento\Tax\Model\Calculation::CALC_TAX_BEFORE_DISCOUNT_ON_INCL], + [false, false, \Magento\Tax\Model\Calculation::CALC_TAX_BEFORE_DISCOUNT_ON_EXCL] + ]; + } + + + /** + * Tests the methods that rely on the ScopeConfigInterface object to provide their return values + * + * @param string $method + * @param string $path + * @param bool|int $configValue + * @param bool $expectedValue + * @dataProvider dataProviderScopeConfigMethods + */ + public function testScopeConfigMethods($method, $path, $configValue, $expectedValue) + { + $scopeConfigMock = $this->getMockForAbstractClass('Magento\Framework\App\Config\ScopeConfigInterface'); + $scopeConfigMock->expects($this->once()) + ->method('getValue') + ->with($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, null) + ->will($this->returnValue($configValue)); + + /** @var \Magento\Tax\Model\Config */ + $model = new Config($scopeConfigMock); + $this->assertEquals($expectedValue, $model->{$method}()); + } + + /** + * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function dataProviderScopeConfigMethods() + { + return [ + [ + 'priceIncludesTax', + Config::CONFIG_XML_PATH_PRICE_INCLUDES_TAX, + true, + true + ], + [ + 'applyTaxAfterDiscount', + Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT, + true, + true + ], + [ + 'getPriceDisplayType', + Config::CONFIG_XML_PATH_PRICE_DISPLAY_TYPE, + true, + true + ], + [ + 'discountTax', + Config::CONFIG_XML_PATH_DISCOUNT_TAX, + 1, + true + ], + [ + 'getAlgorithm', + Config::XML_PATH_ALGORITHM, + true, + true + ], + [ + 'getShippingTaxClass', + Config::CONFIG_XML_PATH_SHIPPING_TAX_CLASS, + true, + true + ], + [ + 'getShippingPriceDisplayType', + Config::CONFIG_XML_PATH_DISPLAY_SHIPPING, + true, + true + ], + [ + 'shippingPriceIncludesTax', + Config::CONFIG_XML_PATH_SHIPPING_INCLUDES_TAX, + true, + true + ], + [ + 'displayCartPricesInclTax', + Config::XML_PATH_DISPLAY_CART_PRICE, + Config::DISPLAY_TYPE_INCLUDING_TAX, + true + ], + [ + 'displayCartPricesExclTax', + Config::XML_PATH_DISPLAY_CART_PRICE, + Config::DISPLAY_TYPE_EXCLUDING_TAX, + true + ], + [ + 'displayCartPricesBoth', + Config::XML_PATH_DISPLAY_CART_PRICE, + Config::DISPLAY_TYPE_BOTH, + true + ], + [ + 'displayCartSubtotalInclTax', + Config::XML_PATH_DISPLAY_CART_SUBTOTAL, + Config::DISPLAY_TYPE_INCLUDING_TAX, + true + ], + [ + 'displayCartSubtotalExclTax', + Config::XML_PATH_DISPLAY_CART_SUBTOTAL, + Config::DISPLAY_TYPE_EXCLUDING_TAX, + true + ], + [ + 'displayCartSubtotalBoth', + Config::XML_PATH_DISPLAY_CART_SUBTOTAL, + Config::DISPLAY_TYPE_BOTH, + true + ], + [ + 'displayCartShippingInclTax', + Config::XML_PATH_DISPLAY_CART_SHIPPING, + Config::DISPLAY_TYPE_INCLUDING_TAX, + true + ], + [ + 'displayCartShippingExclTax', + Config::XML_PATH_DISPLAY_CART_SHIPPING, + Config::DISPLAY_TYPE_EXCLUDING_TAX, + true + ], + [ + 'displayCartShippingBoth', + Config::XML_PATH_DISPLAY_CART_SHIPPING, + Config::DISPLAY_TYPE_BOTH, + true + ], + [ + 'displayCartDiscountInclTax', + Config::XML_PATH_DISPLAY_CART_DISCOUNT, + Config::DISPLAY_TYPE_INCLUDING_TAX, + true + ], + [ + 'displayCartDiscountExclTax', + Config::XML_PATH_DISPLAY_CART_DISCOUNT, + Config::DISPLAY_TYPE_EXCLUDING_TAX, + true + ], + [ + 'displayCartDiscountBoth', + Config::XML_PATH_DISPLAY_CART_DISCOUNT, + Config::DISPLAY_TYPE_BOTH, + true + ], + [ + 'displayCartTaxWithGrandTotal', + Config::XML_PATH_DISPLAY_CART_GRANDTOTAL, + true, + true + ], + [ + 'displayCartFullSummary', + Config::XML_PATH_DISPLAY_CART_FULL_SUMMARY, + true, + true + ], + [ + 'displayCartZeroTax', + Config::XML_PATH_DISPLAY_CART_ZERO_TAX, + true, + true + ], + [ + 'displaySalesPricesInclTax', + Config::XML_PATH_DISPLAY_SALES_PRICE, + Config::DISPLAY_TYPE_INCLUDING_TAX, + true + ], + [ + 'displaySalesPricesExclTax', + Config::XML_PATH_DISPLAY_SALES_PRICE, + Config::DISPLAY_TYPE_EXCLUDING_TAX, + true + ], + [ + 'displaySalesPricesBoth', + Config::XML_PATH_DISPLAY_SALES_PRICE, + Config::DISPLAY_TYPE_BOTH, + true + ], + [ + 'displaySalesSubtotalInclTax', + Config::XML_PATH_DISPLAY_SALES_SUBTOTAL, + Config::DISPLAY_TYPE_INCLUDING_TAX, + true + ], + [ + 'displaySalesSubtotalExclTax', + Config::XML_PATH_DISPLAY_SALES_SUBTOTAL, + Config::DISPLAY_TYPE_EXCLUDING_TAX, + true + ], + [ + 'displaySalesSubtotalBoth', + Config::XML_PATH_DISPLAY_SALES_SUBTOTAL, + Config::DISPLAY_TYPE_BOTH, + true + ], + [ + 'displaySalesShippingInclTax', + Config::XML_PATH_DISPLAY_SALES_SHIPPING, + Config::DISPLAY_TYPE_INCLUDING_TAX, + true + ], + [ + 'displaySalesShippingExclTax', + Config::XML_PATH_DISPLAY_SALES_SHIPPING, + Config::DISPLAY_TYPE_EXCLUDING_TAX, + true + ], + [ + 'displaySalesShippingBoth', + Config::XML_PATH_DISPLAY_SALES_SHIPPING, + Config::DISPLAY_TYPE_BOTH, + true + ], + [ + 'displaySalesDiscountInclTax', + Config::XML_PATH_DISPLAY_SALES_DISCOUNT, + Config::DISPLAY_TYPE_INCLUDING_TAX, + true + ], + [ + 'displaySalesDiscountExclTax', + Config::XML_PATH_DISPLAY_SALES_DISCOUNT, + Config::DISPLAY_TYPE_EXCLUDING_TAX, + true + ], + [ + 'displaySalesDiscountBoth', + Config::XML_PATH_DISPLAY_SALES_DISCOUNT, + Config::DISPLAY_TYPE_BOTH, + true + ], + [ + 'displaySalesTaxWithGrandTotal', + Config::XML_PATH_DISPLAY_SALES_GRANDTOTAL, + true, + true + ], + [ + 'displaySalesFullSummary', + Config::XML_PATH_DISPLAY_SALES_FULL_SUMMARY, + true, + true + ], + [ + 'displaySalesZeroTax', + Config::XML_PATH_DISPLAY_SALES_ZERO_TAX, + true, + true + ], + [ + 'crossBorderTradeEnabled', + Config::CONFIG_XML_PATH_CROSS_BORDER_TRADE_ENABLED, + true, + true + ] + ]; + } +} diff --git a/dev/tests/unit/testsuite/Magento/Tax/Pricing/AdjustmentTest.php b/dev/tests/unit/testsuite/Magento/Tax/Pricing/AdjustmentTest.php index 74ea74b8a9059fd6e87fd0f067bd227b65908d10..ed4708b27ca52b1ad1eaeab53a2ff7c11b942c1b 100644 --- a/dev/tests/unit/testsuite/Magento/Tax/Pricing/AdjustmentTest.php +++ b/dev/tests/unit/testsuite/Magento/Tax/Pricing/AdjustmentTest.php @@ -119,6 +119,10 @@ class AdjustmentTest extends \PHPUnit_Framework_TestCase ->method('getPrice') ->with($object, $amount) ->will($this->returnValue($price)); + $this->taxHelper->expects($this->any()) + ->method('getPriceUnrounded') + ->with($object, $amount) + ->will($this->returnValue($price)); $this->assertEquals($expectedResult, $this->adjustment->extractAdjustment($amount, $object)); } @@ -151,6 +155,10 @@ class AdjustmentTest extends \PHPUnit_Framework_TestCase ->method('getPrice') ->with($object, $amount, !$isPriceIncludesTax) ->will($this->returnValue($price)); + $this->taxHelper->expects($this->any()) + ->method('getPriceUnrounded') + ->with($object, $amount, !$isPriceIncludesTax) + ->will($this->returnValue($price)); $this->assertEquals($expectedResult, $this->adjustment->applyAdjustment($amount, $object)); } diff --git a/lib/internal/Magento/Framework/AppInterface.php b/lib/internal/Magento/Framework/AppInterface.php index 3800dabc2ff017e344791521dce2355ee4146945..0c82cf557f8ce0e2d685d0227a6dcfd64a8e65d4 100644 --- a/lib/internal/Magento/Framework/AppInterface.php +++ b/lib/internal/Magento/Framework/AppInterface.php @@ -35,7 +35,7 @@ interface AppInterface /** * Magento version */ - const VERSION = '2.0.0.0-dev82'; + const VERSION = '2.0.0.0-dev83'; /** * Launch application