diff --git a/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/info.phtml b/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/info.phtml index bf674f8d5f3b480f0892b7273a04e82e2fb804ed..cb7200cad183c26c1d5c5ec8d4baae1477d57feb 100644 --- a/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/info.phtml +++ b/app/code/Magento/Authorizenet/view/adminhtml/templates/directpost/info.phtml @@ -35,8 +35,12 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); </label> <div class="admin__field-control"> <select id="<?php /* @noEscape */ echo $code; ?>_cc_type" name="payment[cc_type]" - class="required-entry validate-cc-type-select admin__control-select"> - <option value=""></option> + class="admin__control-select" + data-validate="{ + 'required':true, + 'validate-cc-type-select':'#<?php /* @noEscape */ echo $code; ?>_cc_number' + }"> + <option value=""><?php echo $block->escapeHtml(__('Please Select')); ?></option> <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName): ?> <option value="<?php echo $block->escapeHtml($typeCode); ?>" <?php if ($typeCode == $ccType): ?>selected="selected"<?php endif; ?>> @@ -46,19 +50,25 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); </select> </div> </div> + <div class="admin__field _required"> <label for="<?php /* @noEscape */ echo $code; ?>_cc_number" class="admin__field-label"> <span><?php echo $block->escapeHtml(__('Credit Card Number')); ?></span> </label> - <div class="admin__field-control"> <input type="text" id="<?php /* @noEscape */ echo $code; ?>_cc_number" name="payment[cc_number]" - class="input-text required-entry validate-cc-number admin__control-text" + data-validate="{ + 'required-number':true, + 'validate-cc-number':'#<?php /* @noEscape */ echo $code; ?>_cc_type', + 'validate-cc-type':'#<?php /* @noEscape */ echo $code; ?>_cc_type' + }" + class="admin__control-text" value="<?php /* @noEscape */ echo $block->getInfoData('cc_number'); ?>"/> </div> </div> - <div class="admin__field _required"> + + <div class="admin__field _required field-date" id="<?php /* @noEscape */ echo $code; ?>_cc_type_exp_div"> <label for="<?php /* @noEscape */ echo $code; ?>_expiration" class="admin__field-label"> <span><?php echo $block->escapeHtml(__('Expiration Date')); ?></span> </label> @@ -66,7 +76,11 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); <div class="admin__field-control"> <select id="<?php /* @noEscape */ echo $code; ?>_expiration" name="payment[cc_exp_month]" - class="validate-cc-exp required-entry admin__control-select admin__control-select-month"> + class="admin__control-select admin__control-select-month" + data-validate="{ + 'required':true, + 'validate-cc-exp':'#<?php /* @noEscape */ echo $code; ?>_expiration_yr' + }"> <?php foreach ($block->getCcMonths() as $k => $v): ?> <option value="<?php echo $block->escapeHtml($k); ?>" <?php if ($k == $ccExpMonth): ?>selected="selected"<?php endif; ?>> @@ -76,7 +90,9 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); </select> <select id="<?php /* @noEscape */ echo $code; ?>_expiration_yr" name="payment[cc_exp_year]" - class="required-entry admin__control-select admin__control-select-year"> + class="admin__control-select admin__control-select-year" + data-container="<?php /* @noEscape */ echo $code; ?>-cc-year" + data-validate="{required:true}"> <?php foreach ($block->getCcYears() as $k => $v): ?> <option value="<?php /* @noEscape */ echo $k ? $block->escapeHtml($k) : ''; ?>" <?php if ($k == $ccExpYear): ?>selected="selected"<?php endif; ?>> @@ -86,17 +102,27 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); </select> </div> </div> + <?php if ($block->hasVerification()): ?> - <div class="admin__field _required"> - <label for="<?php /* @noEscape */ echo $code; ?>_cc_cid"> + <div class="admin__field _required field-cvv"> + <label class="admin__field-label" + for="<?php /* @noEscape */ echo $code; ?>_cc_cid" + id="<?php /* @noEscape */ echo $code; ?>_cc_type_cvv_div"> <span><?php echo $block->escapeHtml(__('Card Verification Number')); ?></span> </label> <div class="admin__field-control"> <input type="text" - class="required-entry input-text validate-cc-cvn admin__control-text" + data-container="<?php /* @noEscape */ echo $code; ?>-cc-cvv" + title="<?php echo $block->escapeHtml(__('Card Verification Number')); ?>" + class="admin__control-text cvv" id="<?php /* @noEscape */ echo $code; ?>_cc_cid" name="payment[cc_cid]" - value="<?php /* @noEscape */ echo $block->getInfoData('cc_cid') ?>"/> + value="<?php /* @noEscape */ echo $block->getInfoData('cc_cid') ?>" + data-validate="{ + 'required-number':true, + 'validate-cc-cvn':'#<?php /* @noEscape */ echo $code; ?>_cc_type' + }" + autocomplete="off"/> </div> </div> <?php endif; ?> @@ -105,7 +131,7 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); require([ 'prototype', 'Magento_Sales/order/create/scripts', - "Magento_Sales/order/create/form", + 'Magento_Sales/order/create/form', 'Magento_Authorizenet/js/direct-post' ], function(){ diff --git a/app/code/Magento/Catalog/Helper/Product/Compare.php b/app/code/Magento/Catalog/Helper/Product/Compare.php index 3a7ce70cbff528239712a353cb5f939f9a0878c4..69f4a613a5b9555e2c46038c2a6cc620b291ef60 100644 --- a/app/code/Magento/Catalog/Helper/Product/Compare.php +++ b/app/code/Magento/Catalog/Helper/Product/Compare.php @@ -231,6 +231,8 @@ class Compare extends \Magento\Framework\Url\Helper\Data $data = [ \Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED => '', 'product' => $product->getId(), + 'confirmation' => true, + 'confirmationMessage' => __('Are you sure you want to remove this item from your Compare Products list?') ]; return $this->postHelper->getPostData($this->getRemoveUrl(), $data); } @@ -254,6 +256,8 @@ class Compare extends \Magento\Framework\Url\Helper\Data { $params = [ \Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED => '', + 'confirmation' => true, + 'confirmationMessage' => __('Are you sure you want to remove all items from your Compare Products list?'), ]; return $this->postHelper->getPostData($this->getClearListUrl(), $params); } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php index 39a67f9722e185894640178329d008de10cb574e..42456a396178c1a1001c45f49a0150612cdd566f 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php @@ -33,6 +33,11 @@ class Value extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb */ protected $_config; + /** + * @var \Magento\Framework\Locale\FormatInterface + */ + private $localeFormat; + /** * Class constructor * @@ -91,8 +96,9 @@ class Value extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb protected function _saveValuePrices(\Magento\Framework\Model\AbstractModel $object) { $priceTable = $this->getTable('catalog_product_option_type_price'); + $formattedPrice = $this->getLocaleFormatter()->getNumber($object->getPrice()); - $price = (double)sprintf('%F', $object->getPrice()); + $price = (double)sprintf('%F', $formattedPrice); $priceType = $object->getPriceType(); if ($object->getPrice() && $priceType) { @@ -410,4 +416,19 @@ class Value extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb return $object; } + + /** + * Get FormatInterface to convert price from string to number format + * + * @return \Magento\Framework\Locale\FormatInterface + * @deprecated + */ + private function getLocaleFormatter() + { + if ($this->localeFormat === null) { + $this->localeFormat = \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Framework\Locale\FormatInterface::class); + } + return $this->localeFormat; + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Helper/Product/CompareTest.php b/app/code/Magento/Catalog/Test/Unit/Helper/Product/CompareTest.php index 9f4d41aefd6bb8d1fd02d8990bcdd12c33191035..51388c3725ba9dc430137514ba3c3fc103237d1f 100644 --- a/app/code/Magento/Catalog/Test/Unit/Helper/Product/CompareTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Helper/Product/CompareTest.php @@ -115,7 +115,9 @@ class CompareTest extends \PHPUnit_Framework_TestCase $removeUrl = 'catalog/product_compare/remove'; $postParams = [ Action::PARAM_NAME_URL_ENCODED => '', - 'product' => $productId + 'product' => $productId, + 'confirmation' => true, + 'confirmationMessage' => __('Are you sure you want to remove this item from your Compare Products list?'), ]; //Verification @@ -156,7 +158,9 @@ class CompareTest extends \PHPUnit_Framework_TestCase //Data $clearUrl = 'catalog/product_compare/clear'; $postParams = [ - Action::PARAM_NAME_URL_ENCODED => '' + Action::PARAM_NAME_URL_ENCODED => '', + 'confirmation' => true, + 'confirmationMessage' => __('Are you sure you want to remove all items from your Compare Products list?'), ]; //Verification diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php index dd858fa571ae1d10ce6021f7f257579bc803cf5a..b586436b5680d942daa4f9fc6f884138f0a7eeb5 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php @@ -831,20 +831,6 @@ class ProductTest extends \PHPUnit_Framework_TestCase ]; } - public function testStatusAfterLoad() - { - $this->resource->expects($this->once())->method('load')->with($this->model, 1, null); - $this->eventManagerMock->expects($this->exactly(4))->method('dispatch'); - $this->model->load(1); - $this->assertEquals( - Status::STATUS_ENABLED, - $this->model->getData(\Magento\Catalog\Model\Product::STATUS) - ); - $this->assertFalse($this->model->hasDataChanges()); - $this->model->setStatus(Status::STATUS_DISABLED); - $this->assertTrue($this->model->hasDataChanges()); - } - /** * Test retrieving price Info */ diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js index fd69874c318e21606361d503cc55ea900ad604cf..e67bde152475f62769d6eaff73548893f98ed7d0 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js @@ -4,8 +4,9 @@ */ define([ + 'underscore', 'Magento_Ui/js/form/element/textarea' -], function (Textarea) { +], function (_, Textarea) { 'use strict'; return Textarea.extend({ @@ -123,24 +124,21 @@ define([ * Update field value, if it's allowed */ updateValue: function () { - var str = this.mask, + var str = this.mask || '', nonEmptyValueFlag = false, - placeholder, - property, tmpElement; if (!this.allowImport) { return; } - for (property in this.values) { - if (this.values.hasOwnProperty(property)) { - placeholder = ''; - placeholder = placeholder.concat('{{', property, '}}'); - str = str.replace(placeholder, this.values[property]); - nonEmptyValueFlag = nonEmptyValueFlag || !!this.values[property]; - } + if (str) { + _.each(this.values, function (propertyValue, propertyName) { + str = str.replace('{{' + propertyName + '}}', propertyValue); + nonEmptyValueFlag = nonEmptyValueFlag || !!propertyValue; + }); } + // strip tags tmpElement = document.createElement('div'); tmpElement.innerHTML = str; diff --git a/app/code/Magento/Catalog/view/frontend/requirejs-config.js b/app/code/Magento/Catalog/view/frontend/requirejs-config.js index c0d05a322b7cd9e0a0603cdbef8505963ead80fa..6c7a8d3a969fff3090e0c24bbb431eebf83b9e6b 100644 --- a/app/code/Magento/Catalog/view/frontend/requirejs-config.js +++ b/app/code/Magento/Catalog/view/frontend/requirejs-config.js @@ -6,7 +6,6 @@ var config = { map: { '*': { - compareItems: 'Magento_Catalog/js/compare', compareList: 'Magento_Catalog/js/list', relatedProducts: 'Magento_Catalog/js/related-products', upsellProducts: 'Magento_Catalog/js/upsell-products', diff --git a/app/code/Magento/Catalog/view/frontend/web/js/compare.js b/app/code/Magento/Catalog/view/frontend/web/js/compare.js deleted file mode 100644 index 66f8767bf2b8830c4229588d7c0a7ac5a8b6a422..0000000000000000000000000000000000000000 --- a/app/code/Magento/Catalog/view/frontend/web/js/compare.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global confirm:true*/ -define([ - "jquery", - "jquery/ui", - "mage/decorate" -], function($){ - "use strict"; - - $.widget('mage.compareItems', { - _create: function() { - this.element.decorate('list', true); - this._confirm(this.options.removeSelector, this.options.removeConfirmMessage); - this._confirm(this.options.clearAllSelector, this.options.clearAllConfirmMessage); - }, - - /** - * Set up a click event on the given selector to display a confirmation request message - * and ask for that confirmation. - * @param selector Selector for the confirmation on click event - * @param message Message to display asking for confirmation to perform action - * @private - */ - _confirm: function(selector, message) { - $(selector).on('click', function() { - return confirm(message); - }); - } - }); - - return $.mage.compareItems; -}); \ No newline at end of file diff --git a/app/code/Magento/Catalog/view/frontend/web/js/view/compare-products.js b/app/code/Magento/Catalog/view/frontend/web/js/view/compare-products.js index 5dba397d9bc43d7e149887fe5519c54469d09b0e..9662b3fc7268b7366b9a448e90ca75690506b13a 100644 --- a/app/code/Magento/Catalog/view/frontend/web/js/view/compare-products.js +++ b/app/code/Magento/Catalog/view/frontend/web/js/view/compare-products.js @@ -2,37 +2,32 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ + define([ 'uiComponent', 'Magento_Customer/js/customer-data', - 'mage/translate' -], function (Component, customerData) { + 'jquery', + 'mage/mage', + 'mage/decorate' +], function (Component, customerData, $) { 'use strict'; var sidebarInitialized = false; + /** + * Initialize sidebar + */ function initSidebar() { if (sidebarInitialized) { return; } - sidebarInitialized = true; - require([ - 'jquery', - 'mage/mage' - ], function ($) { - /*eslint-disable max-len*/ - $('[data-role=compare-products-sidebar]').mage('compareItems', { - 'removeConfirmMessage': $.mage.__('Are you sure you want to remove this item from your Compare Products list?'), - 'removeSelector': '#compare-items a.action.delete', - 'clearAllConfirmMessage': $.mage.__('Are you sure you want to remove all items from your Compare Products list?'), - 'clearAllSelector': '#compare-clear-all' - }); - /*eslint-enable max-len*/ - }); + sidebarInitialized = true; + $('[data-role=compare-products-sidebar]').decorate('list', true); } return Component.extend({ + /** @inheritdoc */ initialize: function () { this._super(); this.compareProducts = customerData.get('compare-products'); diff --git a/app/code/Magento/Customer/view/frontend/requirejs-config.js b/app/code/Magento/Customer/view/frontend/requirejs-config.js index 53f12373bfd928a1fcea86ee50ba4038caf0cf6a..508737742cafe2e2cf9905571ae3655bba440ad5 100644 --- a/app/code/Magento/Customer/view/frontend/requirejs-config.js +++ b/app/code/Magento/Customer/view/frontend/requirejs-config.js @@ -10,7 +10,8 @@ var config = { address: 'Magento_Customer/address', changeEmailPassword: 'Magento_Customer/change-email-password', passwordStrengthIndicator: 'Magento_Customer/js/password-strength-indicator', - zxcvbn: 'Magento_Customer/js/zxcvbn' + zxcvbn: 'Magento_Customer/js/zxcvbn', + addressValidation: 'Magento_Customer/js/addressValidation' } } }; diff --git a/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml b/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml index 2de971bf6a9c05d1c07cb5745272fcad7a135e23..17d7c9852fc4b5e0efa4ba8342a9bcff0d97d805 100644 --- a/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/address/edit.phtml @@ -203,7 +203,7 @@ <script type="text/x-magento-init"> { "#form-validate": { - "validation": {} + "addressValidation": {} }, "#country": { "regionUpdater": { diff --git a/app/code/Magento/Customer/view/frontend/web/js/addressValidation.js b/app/code/Magento/Customer/view/frontend/web/js/addressValidation.js new file mode 100644 index 0000000000000000000000000000000000000000..c01463b4046aebc4277fcaf6d8765d1d7a785893 --- /dev/null +++ b/app/code/Magento/Customer/view/frontend/web/js/addressValidation.js @@ -0,0 +1,43 @@ +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +define([ + 'jquery', + 'jquery/ui', + 'validation' +], function ($) { + 'use strict'; + + $.widget('mage.addressValidation', { + options: { + selectors: { + button: '[data-action=save-address]' + } + }, + + /** + * Validation creation + * @protected + */ + _create: function () { + var button = $(this.options.selectors.button, this.element); + + this.element.validation({ + + /** + * Submit Handler + * @param {Element} form - address form + */ + submitHandler: function (form) { + + button.attr('disabled', true); + form.submit(); + } + }); + } + }); + + return $.mage.addressValidation; +}); diff --git a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php index c3e5a4b0c4d462b2f7e6576e7c8666e71b18be58..878ddf812028825267297aac958c22c14070f7b9 100644 --- a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php +++ b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php @@ -950,6 +950,7 @@ abstract class AbstractEntity extends AbstractResource implements EntityInterfac /** * Load object base row data */ + $object->beforeLoad($entityId); $select = $this->_getLoadRowSelect($object, $entityId); $row = $this->getConnection()->fetchRow($select); @@ -962,11 +963,10 @@ abstract class AbstractEntity extends AbstractResource implements EntityInterfac $this->loadAttributesMetadata($attributes); $this->_loadModelAttributes($object); - - $object->setOrigData(); - $this->_afterLoad($object); - + $object->afterLoad(); + $object->setOrigData(); + $object->setHasDataChanges(false); \Magento\Framework\Profiler::stop('EAV:load_entity'); return $this; } diff --git a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php index c4d9657a322dab4b48a1668f908021de223f050b..d176b5be6a4551d9d7162ebf5d9436f99aadcd37 100644 --- a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php +++ b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php @@ -151,25 +151,28 @@ class Tablerate extends \Magento\Shipping\Model\Carrier\AbstractCarrier implemen $request->setPackageQty($oldQty); if (!empty($rate) && $rate['price'] >= 0) { - /** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */ - $method = $this->_resultMethodFactory->create(); - - $method->setCarrier('tablerate'); - $method->setCarrierTitle($this->getConfigData('title')); - - $method->setMethod('bestway'); - $method->setMethodTitle($this->getConfigData('name')); - if ($request->getFreeShipping() === true || $request->getPackageQty() == $freeQty) { $shippingPrice = 0; } else { $shippingPrice = $this->getFinalPriceWithHandlingFee($rate['price']); } - - $method->setPrice($shippingPrice); - $method->setCost($rate['cost']); - + $method = $this->createShippingMethod($shippingPrice, $rate['cost']); $result->append($method); + } elseif (empty($rate) && $request->getFreeShipping() === true || $request->getPackageQty() == $freeQty) { + + /** + * Promotion rule was applied for the whole cart. + * In this case all other shipping methods could be omitted + * Table rate shipping method with 0$ price must be shown if grand total is more than minimal value. + * Free package weight has been already taken into account. + */ + $request->setPackageValue($freePackageValue); + $request->setPackageQty($freeQty); + $rate = $this->getRate($request); + if (!empty($rate) && $rate['price'] >= 0) { + $method = $this->createShippingMethod(0, 0); + $result->append($method); + } } else { /** @var \Magento\Quote\Model\Quote\Address\RateResult\Error $error */ $error = $this->_rateErrorFactory->create( @@ -241,4 +244,27 @@ class Tablerate extends \Magento\Shipping\Model\Carrier\AbstractCarrier implemen { return ['bestway' => $this->getConfigData('name')]; } + + /** + * Get the method object based on the shipping price and cost + * + * @param float $shippingPrice + * @param float $cost + * @return \Magento\Quote\Model\Quote\Address\RateResult\Method + */ + private function createShippingMethod($shippingPrice, $cost) + { + /** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */ + $method = $this->_resultMethodFactory->create(); + + $method->setCarrier('tablerate'); + $method->setCarrierTitle($this->getConfigData('title')); + + $method->setMethod('bestway'); + $method->setMethodTitle($this->getConfigData('name')); + + $method->setPrice($shippingPrice); + $method->setCost($cost); + return $method; + } } diff --git a/app/code/Magento/Payment/view/adminhtml/web/transparent.js b/app/code/Magento/Payment/view/adminhtml/web/transparent.js index 583945d39612e67ad99318dafca192a9355bd453..b94e9bd4b2673465e807fda1c54edf6af36f5980 100644 --- a/app/code/Magento/Payment/view/adminhtml/web/transparent.js +++ b/app/code/Magento/Payment/view/adminhtml/web/transparent.js @@ -6,12 +6,14 @@ define([ 'jquery', 'mage/template', - 'Magento_Ui/js/modal/alert' + 'Magento_Ui/js/modal/alert', + 'Magento_Payment/js/model/credit-card-validation/validator' ], function ($, mageTemplate, alert) { 'use strict'; $.widget('mage.transparent', { options: { + editFormSelector: '#edit_form', hiddenFormTmpl: '<form target="<%= data.target %>" action="<%= data.action %>"' + 'method="POST" hidden' + @@ -33,37 +35,51 @@ define([ * @private */ _create: function () { + this.hiddenFormTmpl = mageTemplate(this.options.hiddenFormTmpl); - /** - * @param {Object} event - * @param {String} method - */ - var prepare = function (event, method) { - if (method === this.options.gateway) { - $('#edit_form') - .off('submitOrder') - .on('submitOrder.' + this.options.gateway, this._orderSave.bind(this)); - } else { - $('#edit_form') - .off('submitOrder.' + this.options.gateway); - } - }, - $editForm = $('#edit_form'); + $(this.options.editFormSelector).on('changePaymentMethod', this._setPlaceOrderHandler.bind(this)); + $(this.options.editFormSelector).trigger('changePaymentMethod', [ + $(this.options.editFormSelector).find(':radio[name="payment[method]"]:checked').val() + ]); + }, - this.hiddenFormTmpl = mageTemplate(this.options.hiddenFormTmpl); - $editForm.on('changePaymentMethod', prepare.bind(this)); - - $editForm.trigger( - 'changePaymentMethod', - [ - $editForm.find(':radio[name="payment[method]"]:checked').val() - ] - ); + /** + * Handler for form submit. + * + * @param {Object} event + * @param {String} method + */ + _setPlaceOrderHandler: function (event, method) { + if (method === this.options.gateway) { + $(this.options.editFormSelector) + .off('submitOrder') + .on('submitOrder.' + this.options.gateway, this._placeOrderHandler.bind(this)); + } else { + $(this.options.editFormSelector) + .off('submitOrder.' + this.options.gateway); + } + }, + + /** + * Handler for form submit to call gateway for credit card validation. + * + * @return {Boolean} + * @private + */ + _placeOrderHandler: function () { + if ($(this.options.editFormSelector).valid()) { + this._orderSave(); + } else { + $('body').trigger('processStop'); + } + + return false; }, /** - * handler for Place Order button to call gateway for credit card validation - * Save order and generate post data for gateway call + * Handler for Place Order button to call gateway for credit card validation. + * Save order and generate post data for gateway call. + * * @private */ _orderSave: function () { @@ -99,7 +115,8 @@ define([ }, /** - * Post data to gateway for credit card validation + * Post data to gateway for credit card validation. + * * @param {Object} response * @private */ @@ -136,7 +153,7 @@ define([ }, /** - * Add credit card fields to post data for gateway + * Add credit card fields to post data for gateway. * * @param {Object} response * @private diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-data.js b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-data.js similarity index 100% rename from app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-data.js rename to app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-data.js diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator.js b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator.js similarity index 100% rename from app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator.js rename to app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator.js diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js similarity index 100% rename from app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js rename to app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js similarity index 100% rename from app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js rename to app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/cvv-validator.js b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/cvv-validator.js similarity index 100% rename from app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/cvv-validator.js rename to app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/cvv-validator.js diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator.js b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/expiration-date-validator.js similarity index 100% rename from app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator.js rename to app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/expiration-date-validator.js diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js similarity index 100% rename from app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js rename to app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js similarity index 100% rename from app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js rename to app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js similarity index 100% rename from app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js rename to app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js b/app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/validator.js similarity index 100% rename from app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js rename to app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/validator.js diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/transparent/form.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/transparent/form.phtml index b1a50bcb1bf73db9232cf3457e26215bebe92eff..4c1a3d8e4a41007ade8e32ebf1371c1b55278c32 100644 --- a/app/code/Magento/Paypal/view/adminhtml/templates/transparent/form.phtml +++ b/app/code/Magento/Paypal/view/adminhtml/templates/transparent/form.phtml @@ -129,12 +129,12 @@ $ccExpMonth = $block->getInfoData('cc_exp_month'); <?php endif; ?> <?php if($block->isVaultEnabled()): ?> - <div class="field-tooltip-content"> + <div class="admin__field admin__field-option field-tooltip-content"> <input type="checkbox" id="<?php /* @noEscape */ echo $code; ?>_vault" name="payment[is_active_payment_token_enabler]" class="admin__control-checkbox"/> - <label class="label" for="<?php /* @noEscape */ echo $code; ?>_vault"> + <label class="admin__field-label" for="<?php /* @noEscape */ echo $code; ?>_vault"> <span><?php echo $block->escapeHtml('Save for later use.'); ?></span> </label> </div> diff --git a/app/code/Magento/Review/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ReviewTest.php b/app/code/Magento/Review/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ReviewTest.php index 7685fc0fed94df32b0e0638e65d6d15f6de1d5ce..b93cb70fdda3d9cc9b6d8d9f7bb565d576392de4 100644 --- a/app/code/Magento/Review/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ReviewTest.php +++ b/app/code/Magento/Review/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ReviewTest.php @@ -8,6 +8,8 @@ namespace Magento\Review\Test\Unit\Ui\DataProvider\Product\Form\Modifier; use Magento\Catalog\Test\Unit\Ui\DataProvider\Product\Form\Modifier\AbstractModifierTest; use Magento\Framework\UrlInterface; use Magento\Review\Ui\DataProvider\Product\Form\Modifier\Review; +use Magento\Framework\Module\Manager as ModuleManager; +use Magento\Ui\DataProvider\Modifier\ModifierInterface; /** * Class ReviewTest @@ -19,36 +21,73 @@ class ReviewTest extends AbstractModifierTest */ protected $urlBuilderMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $moduleManagerMock; + protected function setUp() { parent::setUp(); $this->urlBuilderMock = $this->getMockBuilder(UrlInterface::class) ->getMockForAbstractClass(); + $this->moduleManagerMock = $this->getMock(ModuleManager::class, [], [], '', false); } + /** + * @return ModifierInterface + */ protected function createModel() { - return $this->objectManager->getObject(Review::class, [ + $model = $this->objectManager->getObject(Review::class, [ 'locator' => $this->locatorMock, 'urlBuilder' => $this->urlBuilderMock, ]); + + $reviewClass = new \ReflectionClass(Review::class); + $moduleManagerProperty = $reviewClass->getProperty('moduleManager'); + $moduleManagerProperty->setAccessible(true); + $moduleManagerProperty->setValue( + $model, + $this->moduleManagerMock + ); + + return $model; } - public function testModifyMetaToBeEmpty() + public function testModifyMetaDoesNotAddReviewSectionForNewProduct() + { + $this->productMock->expects($this->once()) + ->method('getId'); + + $this->assertSame([], $this->getModel()->modifyMeta([])); + } + + public function testModifyMetaDoesNotAddReviewSectionIfReviewModuleOutputIsDisabled() { $this->productMock->expects($this->once()) ->method('getId') - ->willReturn(0); + ->willReturn(1); + + $this->moduleManagerMock->expects($this->any()) + ->method('isOutputEnabled') + ->with('Magento_Review') + ->willReturn(false); $this->assertSame([], $this->getModel()->modifyMeta([])); } - public function testModifyMeta() + public function testModifyMetaAddsReviewSectionForExistingProductIfReviewModuleOutputIsEnabled() { $this->productMock->expects($this->once()) ->method('getId') ->willReturn(1); + $this->moduleManagerMock->expects($this->any()) + ->method('isOutputEnabled') + ->with('Magento_Review') + ->willReturn(true); + $this->assertArrayHasKey(Review::GROUP_REVIEW, $this->getModel()->modifyMeta([])); } diff --git a/app/code/Magento/Review/Ui/DataProvider/Product/Form/Modifier/Review.php b/app/code/Magento/Review/Ui/DataProvider/Product/Form/Modifier/Review.php index 82141b5ab2f12a03e44463555e7b0a302630b0d2..0ef1057eb4be7ffd23fe794bef67663dc247b5c6 100644 --- a/app/code/Magento/Review/Ui/DataProvider/Product/Form/Modifier/Review.php +++ b/app/code/Magento/Review/Ui/DataProvider/Product/Form/Modifier/Review.php @@ -12,6 +12,8 @@ use Magento\Catalog\Model\Locator\LocatorInterface; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; use Magento\Ui\Component\Form; use Magento\Framework\UrlInterface; +use Magento\Framework\Module\Manager as ModuleManager; +use Magento\Framework\App\ObjectManager; /** * Class Review @@ -34,6 +36,11 @@ class Review extends AbstractModifier */ protected $urlBuilder; + /** + * @var ModuleManager + */ + private $moduleManager; + /** * @param LocatorInterface $locator * @param UrlInterface $urlBuilder @@ -51,7 +58,7 @@ class Review extends AbstractModifier */ public function modifyMeta(array $meta) { - if (!$this->locator->getProduct()->getId()) { + if (!$this->locator->getProduct()->getId() || !$this->getModuleManager()->isOutputEnabled('Magento_Review')) { return $meta; } @@ -114,4 +121,19 @@ class Review extends AbstractModifier return $data; } + + /** + * Retrieve module manager instance using dependency lookup to keep this class backward compatible. + * + * @return ModuleManager + * + * @deprecated + */ + private function getModuleManager() + { + if ($this->moduleManager === null) { + $this->moduleManager = ObjectManager::getInstance()->get(ModuleManager::class); + } + return $this->moduleManager; + } } diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form.phtml index 4b53e0ccb1e9fefd91ea23c555dc64c7f617ca72..fe212490a2fd00c9e18fc6fea8ab28b01e34e45d 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form.phtml @@ -8,7 +8,7 @@ /** @var \Magento\Sales\Block\Adminhtml\Order\Create\Form $block */ ?> -<form id="edit_form" data-order-config='<?php /* @escapeNotVerified */ echo $block->getOrderDataJson() ?>' data-load-base-url="<?php /* @escapeNotVerified */ echo $block->getLoadBlockUrl() ?>" action="<?php /* @escapeNotVerified */ echo $block->getSaveUrl() ?>" method="post" enctype="multipart/form-data"> +<form id="edit_form" data-order-config='<?php echo $block->escapeHtml($block->getOrderDataJson()) ?>' data-load-base-url="<?php /* @escapeNotVerified */ echo $block->getLoadBlockUrl() ?>" action="<?php /* @escapeNotVerified */ echo $block->getSaveUrl() ?>" method="post" enctype="multipart/form-data"> <?php echo $block->getBlockHtml('formkey')?> <div id="order-message"> <?php echo $block->getChildHtml('message') ?> diff --git a/app/code/Magento/SalesRule/etc/di.xml b/app/code/Magento/SalesRule/etc/di.xml index 2c731823b778fabe6faab37024f4e9ea60247538..83364f924397d857030a9f039ed1ab59dc0fd5f0 100644 --- a/app/code/Magento/SalesRule/etc/di.xml +++ b/app/code/Magento/SalesRule/etc/di.xml @@ -78,7 +78,7 @@ <type name="Magento\Framework\Model\Entity\RepositoryFactory"> <arguments> <argument name="entities" xsi:type="array"> - <item name="Magento\SalesRule\Api\Data\RuleInterface" xsi:type="string">Magento\SalesRule\Api\RuleRepositoryInterface</item> + <item name="Magento\SalesRule\Api\Data\RuleInterface" xsi:type="string">Magento\SalesRule\Model\ResourceModel\Rule</item> </argument> </arguments> </type> diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/MetaTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/MetaTest.php index 42f4d098ebcba34d91b6eac8944ebb5072040af3..7a842b8d1c908309c887b2fb5dc5f85f1e36213a 100644 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/MetaTest.php +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/MetaTest.php @@ -161,6 +161,7 @@ class MetaTest extends \PHPUnit_Framework_TestCase ->willReturn($metaId); $this->metaFactory->expects($this->once())->method('create')->willReturn($this->meta); $this->stepCheckSaveWithActiveProfile($metaData); + $this->meta->expects($this->once())->method('beforeLoad'); $this->assertEquals($this->meta, $this->resource->loadByEntityTypeAndStore($entityType, $storeId)); } @@ -177,7 +178,5 @@ class MetaTest extends \PHPUnit_Framework_TestCase ->method('quoteIdentifier'); $this->connectionMock->expects($this->once())->method('fetchRow')->willReturn($metaData); $this->resourceProfile->expects($this->once())->method('loadActiveProfile')->willReturn($this->profile); - $this->meta->expects($this->at(0))->method('setData')->with($metaData); - $this->meta->expects($this->at(2))->method('setData')->with('active_profile', $this->profile); } } diff --git a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/ProfileTest.php b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/ProfileTest.php index c3c827ba2f97a4e795a8f4d5633ebbf0736ba58e..b17445e7014fa618d2eb9c014f5a6b9bbc7d7f43 100644 --- a/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/ProfileTest.php +++ b/app/code/Magento/SalesSequence/Test/Unit/Model/ResourceModel/ProfileTest.php @@ -156,7 +156,7 @@ class ProfileTest extends \PHPUnit_Framework_TestCase $this->connectionMock->expects($this->any()) ->method('quoteIdentifier'); $this->connectionMock->expects($this->once())->method('fetchRow')->willReturn($profileData); - $this->profile->expects($this->at(0))->method('setData')->with($profileData); + $this->profile->expects($this->at(1))->method('setData')->with($profileData); $this->assertEquals($this->profile, $this->resource->loadActiveProfile($metaId)); } } diff --git a/composer.json b/composer.json index a5f4b8c427ffffcbf85d9be78bcd89bf0928625a..63d02e7c0a8b47dcadcd7444faa17a2d0435950c 100644 --- a/composer.json +++ b/composer.json @@ -31,9 +31,9 @@ "zendframework/zend-serializer": "~2.4.6", "zendframework/zend-log": "~2.4.6", "zendframework/zend-http": "~2.4.6", - "magento/zendframework1": "1.12.16", + "magento/zendframework1": "~1.12.16", "colinmollenhour/credis": "1.6", - "colinmollenhour/php-redis-session-abstract": "1.1", + "colinmollenhour/php-redis-session-abstract": "1.2", "colinmollenhour/cache-backend-redis": "1.9", "colinmollenhour/cache-backend-file": "1.4", "composer/composer": "1.0.0-beta1", diff --git a/composer.lock b/composer.lock index d842cdec858b705c27295b5b1b1d6e89ae5a6b19..54a2b572c024bda51e7c7c2458fab8c45e2acb37 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "1c5d7ca4fa68bea1ab7490cb8ac62342", - "content-hash": "ecfa548096f500a6a98a5fc41c21e53b", + "hash": "0cd85c424e865c554b2f8db093192cfd", + "content-hash": "d74ec028da2018e1a161a2e1b70d3f87", "packages": [ { "name": "braintree/braintree_php", @@ -167,21 +167,21 @@ }, { "name": "colinmollenhour/php-redis-session-abstract", - "version": "v1.1", + "version": "v1.2", "source": { "type": "git", "url": "https://github.com/colinmollenhour/php-redis-session-abstract.git", - "reference": "95330b7f29663dab81f53d1a438e4d927b6c5f66" + "reference": "2b552c9bbe06967329dd41e1bd3e0aed02313ddb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/colinmollenhour/php-redis-session-abstract/zipball/95330b7f29663dab81f53d1a438e4d927b6c5f66", - "reference": "95330b7f29663dab81f53d1a438e4d927b6c5f66", + "url": "https://api.github.com/repos/colinmollenhour/php-redis-session-abstract/zipball/2b552c9bbe06967329dd41e1bd3e0aed02313ddb", + "reference": "2b552c9bbe06967329dd41e1bd3e0aed02313ddb", "shasum": "" }, "require": { "colinmollenhour/credis": "1.6", - "magento/zendframework1": "1.12.16", + "magento/zendframework1": "~1.12.0", "php": "~5.5.0|~5.6.0|~7.0.0" }, "type": "library", @@ -201,7 +201,7 @@ ], "description": "A Redis-based session handler with optimistic locking", "homepage": "https://github.com/colinmollenhour/php-redis-session-abstract", - "time": "2016-02-03 18:13:49" + "time": "2016-08-04 18:05:51" }, { "name": "composer/composer", @@ -280,16 +280,16 @@ }, { "name": "composer/semver", - "version": "1.4.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "03c9de5aa25e7672c4ad251eeaba0c47a06c8b98" + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/03c9de5aa25e7672c4ad251eeaba0c47a06c8b98", - "reference": "03c9de5aa25e7672c4ad251eeaba0c47a06c8b98", + "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", "shasum": "" }, "require": { @@ -338,7 +338,7 @@ "validation", "versioning" ], - "time": "2016-06-02 09:04:51" + "time": "2016-08-30 16:08:34" }, { "name": "composer/spdx-licenses", @@ -633,16 +633,16 @@ }, { "name": "magento/zendframework1", - "version": "1.12.16", + "version": "1.12.16-patch1", "source": { "type": "git", "url": "https://github.com/magento/zf1.git", - "reference": "c9d607bfd9454bc18b9deff737ccd5d044e2ab10" + "reference": "b4502f38f88ff2bc22a906c108cc3da18dcce12f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/magento/zf1/zipball/c9d607bfd9454bc18b9deff737ccd5d044e2ab10", - "reference": "c9d607bfd9454bc18b9deff737ccd5d044e2ab10", + "url": "https://api.github.com/repos/magento/zf1/zipball/b4502f38f88ff2bc22a906c108cc3da18dcce12f", + "reference": "b4502f38f88ff2bc22a906c108cc3da18dcce12f", "shasum": "" }, "require": { @@ -676,7 +676,7 @@ "ZF1", "framework" ], - "time": "2015-10-29 14:34:55" + "time": "2016-09-14 12:04:33" }, { "name": "monolog/monolog", @@ -1014,22 +1014,30 @@ }, { "name": "psr/log", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + "reference": "5277094ed527a1c4477177d102fe4c53551953e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", - "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "url": "https://api.github.com/repos/php-fig/log/zipball/5277094ed527a1c4477177d102fe4c53551953e0", + "reference": "5277094ed527a1c4477177d102fe4c53551953e0", "shasum": "" }, + "require": { + "php": ">=5.3.0" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { - "psr-0": { - "Psr\\Log\\": "" + "psr-4": { + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1043,12 +1051,13 @@ } ], "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", "keywords": [ "log", "psr", "psr-3" ], - "time": "2012-12-21 11:40:51" + "time": "2016-09-19 16:02:08" }, { "name": "ramsey/uuid", @@ -1180,16 +1189,16 @@ }, { "name": "seld/jsonlint", - "version": "1.4.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "66834d3e3566bb5798db7294619388786ae99394" + "reference": "e827b5254d3e58c736ea2c5616710983d80b0b70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/66834d3e3566bb5798db7294619388786ae99394", - "reference": "66834d3e3566bb5798db7294619388786ae99394", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/e827b5254d3e58c736ea2c5616710983d80b0b70", + "reference": "e827b5254d3e58c736ea2c5616710983d80b0b70", "shasum": "" }, "require": { @@ -1222,7 +1231,7 @@ "parser", "validator" ], - "time": "2015-11-21 02:21:41" + "time": "2016-09-14 15:17:56" }, { "name": "seld/phar-utils", @@ -1381,7 +1390,7 @@ }, { "name": "symfony/event-dispatcher", - "version": "v2.8.9", + "version": "v2.8.11", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -1441,16 +1450,16 @@ }, { "name": "symfony/filesystem", - "version": "v2.8.9", + "version": "v2.8.11", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "ab4c3f085c8f5a56536845bf985c4cef30bf75fd" + "reference": "44b499521defddf2eae17a18c811bbdae4f98bdf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/ab4c3f085c8f5a56536845bf985c4cef30bf75fd", - "reference": "ab4c3f085c8f5a56536845bf985c4cef30bf75fd", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/44b499521defddf2eae17a18c811bbdae4f98bdf", + "reference": "44b499521defddf2eae17a18c811bbdae4f98bdf", "shasum": "" }, "require": { @@ -1486,20 +1495,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2016-07-20 05:41:28" + "time": "2016-09-06 10:55:00" }, { "name": "symfony/finder", - "version": "v3.1.3", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "8201978de88a9fa0923e18601bb17f1df9c721e7" + "reference": "e568ef1784f447a0e54dcb6f6de30b9747b0f577" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8201978de88a9fa0923e18601bb17f1df9c721e7", - "reference": "8201978de88a9fa0923e18601bb17f1df9c721e7", + "url": "https://api.github.com/repos/symfony/finder/zipball/e568ef1784f447a0e54dcb6f6de30b9747b0f577", + "reference": "e568ef1784f447a0e54dcb6f6de30b9747b0f577", "shasum": "" }, "require": { @@ -1535,20 +1544,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2016-06-29 05:41:56" + "time": "2016-08-26 12:04:02" }, { "name": "symfony/process", - "version": "v2.8.9", + "version": "v2.8.11", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "d20332e43e8774ff8870b394f3dd6020cc7f8e0c" + "reference": "05a03ed27073638658cab9405d99a67dd1014987" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/d20332e43e8774ff8870b394f3dd6020cc7f8e0c", - "reference": "d20332e43e8774ff8870b394f3dd6020cc7f8e0c", + "url": "https://api.github.com/repos/symfony/process/zipball/05a03ed27073638658cab9405d99a67dd1014987", + "reference": "05a03ed27073638658cab9405d99a67dd1014987", "shasum": "" }, "require": { @@ -1584,7 +1593,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-07-28 11:13:19" + "time": "2016-09-06 10:55:00" }, { "name": "tedivm/jshrink", @@ -3233,16 +3242,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v1.12.0", + "version": "v1.12.1", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "ddac737e1c06a310a0bb4b3da755a094a31a916a" + "reference": "d33ee60f3d3e6152888b7f3a385f49e5c43bf1bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/ddac737e1c06a310a0bb4b3da755a094a31a916a", - "reference": "ddac737e1c06a310a0bb4b3da755a094a31a916a", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/d33ee60f3d3e6152888b7f3a385f49e5c43bf1bf", + "reference": "d33ee60f3d3e6152888b7f3a385f49e5c43bf1bf", "shasum": "" }, "require": { @@ -3287,7 +3296,7 @@ } ], "description": "A tool to automatically fix PHP code style", - "time": "2016-08-17 00:17:27" + "time": "2016-09-07 06:48:24" }, { "name": "lusitanian/oauth", @@ -4320,16 +4329,16 @@ }, { "name": "symfony/config", - "version": "v2.8.9", + "version": "v2.8.11", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "4275ef5b59f18959df0eee3991e9ca0cc208ffd4" + "reference": "005bf10c156335ede2e89fb9a9ee10a0b742bc84" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/4275ef5b59f18959df0eee3991e9ca0cc208ffd4", - "reference": "4275ef5b59f18959df0eee3991e9ca0cc208ffd4", + "url": "https://api.github.com/repos/symfony/config/zipball/005bf10c156335ede2e89fb9a9ee10a0b742bc84", + "reference": "005bf10c156335ede2e89fb9a9ee10a0b742bc84", "shasum": "" }, "require": { @@ -4369,20 +4378,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2016-07-26 08:02:44" + "time": "2016-08-16 14:56:08" }, { "name": "symfony/dependency-injection", - "version": "v2.8.9", + "version": "v2.8.11", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "f2b5a00d176f6a201dc430375c0ef37706ea3d12" + "reference": "0a732a9cafc30e54077967da4d019e1d618a8cb9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f2b5a00d176f6a201dc430375c0ef37706ea3d12", - "reference": "f2b5a00d176f6a201dc430375c0ef37706ea3d12", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/0a732a9cafc30e54077967da4d019e1d618a8cb9", + "reference": "0a732a9cafc30e54077967da4d019e1d618a8cb9", "shasum": "" }, "require": { @@ -4432,11 +4441,11 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2016-07-30 07:20:35" + "time": "2016-09-06 23:19:39" }, { "name": "symfony/stopwatch", - "version": "v3.1.3", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -4485,16 +4494,16 @@ }, { "name": "symfony/yaml", - "version": "v2.8.9", + "version": "v2.8.11", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "0ceab136f43ed9d3e97b3eea32a7855dc50c121d" + "reference": "e7540734bad981fe59f8ef14b6fc194ae9df8d9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/0ceab136f43ed9d3e97b3eea32a7855dc50c121d", - "reference": "0ceab136f43ed9d3e97b3eea32a7855dc50c121d", + "url": "https://api.github.com/repos/symfony/yaml/zipball/e7540734bad981fe59f8ef14b6fc194ae9df8d9c", + "reference": "e7540734bad981fe59f8ef14b6fc194ae9df8d9c", "shasum": "" }, "require": { @@ -4530,7 +4539,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-07-17 09:06:15" + "time": "2016-09-02 01:57:56" }, { "name": "theseer/fdomdocument", diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/ListCompare.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/ListCompare.php index 546b055b0045b29d6cfe216b1b0efdc7407ebc0a..4de51f3e2ca9b8d5089cb6818d380f0ac9465e46 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/ListCompare.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/ListCompare.php @@ -86,6 +86,13 @@ class ListCompare extends Block */ protected $messageBlock = '#messages'; + /** + * Selector for confirm. + * + * @var string + */ + protected $confirmModal = '.confirm._show[data-role=modal]'; + /** * Get product info. * @@ -189,6 +196,13 @@ class ListCompare extends Block public function removeProduct($index = 1) { $this->_rootElement->find(sprintf($this->removeButton, $index), Locator::SELECTOR_XPATH)->click(); + $modalElement = $this->browser->find($this->confirmModal); + /** @var \Magento\Ui\Test\Block\Adminhtml\Modal $modal */ + $modal = $this->blockFactory->create( + \Magento\Ui\Test\Block\Adminhtml\Modal::class, + ['element' => $modalElement] + ); + $modal->acceptAlert(); } /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/Sidebar.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/Sidebar.php index 596dbd38664b3b097302e6f6f0e62d13fbe96017..ab65865af6534c2b2478490b7f08fd7f108496fe 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/Sidebar.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/Sidebar.php @@ -32,6 +32,13 @@ class Sidebar extends ListCompare */ protected $clearAll = '#compare-clear-all'; + /** + * Selector for confirm. + * + * @var string + */ + protected $confirmModal = '.confirm._show[data-role=modal]'; + /** * Get compare products block content. * @@ -79,5 +86,12 @@ class Sidebar extends ListCompare } ); $this->_rootElement->find($this->clearAll)->click(); + $modalElement = $this->browser->find($this->confirmModal); + /** @var \Magento\Ui\Test\Block\Adminhtml\Modal $modal */ + $modal = $this->blockFactory->create( + \Magento\Ui\Test\Block\Adminhtml\Modal::class, + ['element' => $modalElement] + ); + $modal->acceptAlert(); } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/ConfigData.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/ConfigData.xml index 0b3452cc147824b89443c33ca86d29cbebcb7ae7..9ae1e2ebfacca405f8505496f546cf2182e2dd3f 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/ConfigData.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/ConfigData.xml @@ -23,5 +23,16 @@ <item name="value" xsi:type="number">0</item> </field> </dataset> + <dataset name="empty_product_mask_sku"> + <field name="catalog/fields_masks/sku" xsi:type="array"> + <item name="value" xsi:type="string"/> + </field> + </dataset> + <dataset name="empty_product_mask_sku_rollback"> + <field name="catalog/fields_masks/sku" xsi:type="array"> + <item name="value" xsi:type="string">{{name}}</item> + <item name="inherit" xsi:type="number">1</item> + </field> + </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml index e46ad32551e7496f8ffb443543612567304ce5ee..77d4ee802e1373570a77f5e136c18c5ba393ae4d 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml @@ -461,5 +461,22 @@ <data name="product/data/country_of_manufacture" xsi:type="string">Antarctica</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" /> </variation> + <variation name="CreateSimpleProductEntityWithEmptySkuMaskTest1" summary="Create Simple Product Entity With Empty Sku Mask" ticketId="MAGETWO-58951"> + <data name="configData" xsi:type="string">empty_product_mask_sku</data> + <data name="description" xsi:type="string">Create product with custom options(fixed price)</data> + <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data> + <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data> + <data name="product/data/sku" xsi:type="string">simple_sku_%isolation%</data> + <data name="product/data/price/value" xsi:type="string">10000</data> + <data name="product/data/weight" xsi:type="string">50</data> + <data name="product/data/quantity_and_stock_status/qty" xsi:type="string">657</data> + <data name="product/data/checkout_data/dataset" xsi:type="string">simple_drop_down_with_one_option_fixed_price</data> + <data name="product/data/price/dataset" xsi:type="string">drop_down_with_one_option_fixed_price</data> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductInGrid" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductInCategory" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductPage" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductInCart" /> + </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml index 58435b066261ed28cc7f33ff01fc250940b6eb17..da44fd2eaf99e55e925d9c946b6d7e8ee8370408 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.xml @@ -110,7 +110,7 @@ <constraint name="Magento\ConfigurableProduct\Test\Constraint\AssertConfigurableProductPage" /> </variation> <variation name="CreateConfigurableProductEntityTestVariation6" summary="Create Configurable Product with Creating New Category and New Attribute (Required Fields Only)" ticketId="MAGETWO-13361"> - <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test</data> + <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test, stable:no</data> <data name="product/data/configurable_attributes_data/dataset" xsi:type="string">two_searchable_options</data> <data name="product/data/name" xsi:type="string">Configurable Product %isolation%</data> <data name="product/data/sku" xsi:type="string">configurable_sku_%isolation%</data> diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Constraint/AssertCardRequiredFields.php b/dev/tests/functional/tests/app/Magento/Payment/Test/Constraint/AssertCardRequiredFields.php new file mode 100644 index 0000000000000000000000000000000000000000..2b1d9bdcf2df8fdb32869731b7b3af05d47bc417 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/Constraint/AssertCardRequiredFields.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Payment\Test\Constraint; + +use Magento\Mtf\Constraint\AbstractConstraint; +use Magento\Payment\Test\Repository\CreditCardAdmin; +use Magento\Sales\Test\Page\Adminhtml\OrderCreateIndex; + +/** + * Class AssertCardRequiredFields + * + * Assert that fields are active. + */ +class AssertCardRequiredFields extends AbstractConstraint +{ + /** + * Expected required field message. + */ + const REQUIRE_MESSAGE = 'This is a required field.'; + + /** + * Expected required valid number message. + */ + const VALID_NUMBER_MESSAGE = 'Please enter a valid number in this field.'; + + /** + * Assert required fields on credit card payment method in backend. + * @param OrderCreateIndex $orderCreateIndex + * @param CreditCardAdmin $creditCard + * @return void + */ + public function processAssert(OrderCreateIndex $orderCreateIndex, CreditCardAdmin $creditCard) + { + $actualRequiredFields = $orderCreateIndex->getCreateBlock()->getBillingMethodBlock() + ->getJsErrors(); + $creditCardEmpty = $creditCard->get('visa_empty'); + foreach (array_keys($creditCardEmpty) as $field) { + \PHPUnit_Framework_Assert::assertTrue( + isset($actualRequiredFields[$field]), + "Field '$field' is not highlighted with an JS error." + ); + $expected = self::REQUIRE_MESSAGE; + if (in_array($field, ['cc_number', 'cc_cid'])) { + $expected = self::VALID_NUMBER_MESSAGE; + } + \PHPUnit_Framework_Assert::assertEquals( + $expected, + $actualRequiredFields[$field], + "Field '$field' is not highlighted as required." + ); + } + } + + /** + * Returns string representation of successful assertion. + * + * @return string + */ + public function toString() + { + return 'All required fields on customer form are highlighted.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCardAdmin.xml b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCardAdmin.xml index 1109b70eec7cc14dd343e06fb21c8d8f0eb9c52b..371c8f350c6af028ddc544c23142f2886d699dbd 100644 --- a/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCardAdmin.xml +++ b/dev/tests/functional/tests/app/Magento/Payment/Test/Repository/CreditCardAdmin.xml @@ -22,5 +22,11 @@ <field name="cc_exp_year" xsi:type="string">2020</field> <field name="cc_cid" xsi:type="string">123</field> </dataset> + <dataset name="visa_empty"> + <field name="cc_type" xsi:type="string">Please Select</field> + <field name="cc_number" xsi:type="string" /> + <field name="cc_exp_month" xsi:type="string">Month</field> + <field name="cc_cid" xsi:type="string" /> + </dataset> </repository> </config> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.php b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d4ec11acd51bf53c38de3be6e927b8a24037c1d8 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.php @@ -0,0 +1,49 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Paypal\Test\TestCase; + +use Magento\Mtf\TestCase\Scenario; + +/** + * Preconditions: + * 1. Create customer. + * 2. Create product. + * + * Steps: + * 1. Open Backend. + * 2. Open Sales -> Orders. + * 3. Click Create New Order. + * 4. Select Customer created in preconditions. + * 5. Add Product. + * 6. Fill data according dataset. + * 7. Click Update Product qty. + * 8. Fill data according dataset. + * 9. Click Get Shipping Method and rates. + * 10. Fill data according dataset. + * 11. Select payment method Credit Card (PayFlow Pro) + * 12. Leave empty required fields for credit card + * 13. Click Submit order button + * + * @group PayPal + * @ZephyrId MAGETWO-58934 + */ +class CreatePayFlowOrderBackendNegativeTest extends Scenario +{ + /* tags */ + const MVP = 'yes'; + const TEST_TYPE = '3rd_party_test'; + /* end tags */ + + /** + * Runs sales order on backend. + * + * @return void + */ + public function test() + { + $this->executeScenario(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.xml new file mode 100644 index 0000000000000000000000000000000000000000..04b34813e59ceacd332657d66366d2789f469e71 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/CreatePayFlowOrderBackendNegativeTest.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> + <testCase name="Magento\Paypal\Test\TestCase\CreatePayFlowOrderBackendNegativeTest" summary="Verify required fields validation for PayPal Payflow Pro credit card on admin order creation" ticketId="MAGETWO-58934"> + <variation name="CreatePayFlowOrderBackendNegativeTestPayflowProVariation1" summary="Verify required fields validation for credit card on admin order creation" ticketId="MAGETWO-58934"> + <data name="tag" xsi:type="string">test_type:3rd_party_test</data> + <data name="products/0" xsi:type="string">catalogProductSimple::product_10_dollar</data> + <data name="customer/dataset" xsi:type="string">default</data> + <data name="billingAddress/dataset" xsi:type="string">US_address_1_without_email</data> + <data name="saveAddress" xsi:type="string">No</data> + <data name="shipping/shipping_service" xsi:type="string">Flat Rate</data> + <data name="shipping/shipping_method" xsi:type="string">Fixed</data> + <data name="prices" xsi:type="array"> + <item name="grandTotal" xsi:type="string">15.00</item> + </data> + <data name="payment/method" xsi:type="string">payflowpro</data> + <data name="creditCardClass" xsi:type="string">credit_card_admin</data> + <data name="creditCard/dataset" xsi:type="string">visa_empty</data> + <data name="creditCardSave" xsi:type="string">Yes</data> + <data name="configData" xsi:type="string">payflowpro, payflowpro_use_vault</data> + <constraint name="Magento\Payment\Test\Constraint\AssertCardRequiredFields" /> + </variation> + </testCase> +</config> diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/etc/testcase.xml index f361530def8617d5e4d13451b24e329d31794ef2..53f10b10d38b6329a9b5119088e89443fb85105c 100644 --- a/dev/tests/functional/tests/app/Magento/Paypal/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/etc/testcase.xml @@ -69,4 +69,19 @@ <step name="checkPayflowProConfig" module="Magento_Paypal" next="checkPayflowLinkConfig" /> <step name="checkPayflowLinkConfig" module="Magento_Paypal" /> </scenario> + <scenario name="CreatePayFlowOrderBackendNegativeTest" firstStep="setupConfiguration"> + <step name="setupConfiguration" module="Magento_Config" next="createProducts" /> + <step name="createProducts" module="Magento_Catalog" next="createCustomer" /> + <step name="createCustomer" module="Magento_Customer" next="openSalesOrders" /> + <step name="openSalesOrders" module="Magento_Sales" next="createNewOrder" /> + <step name="createNewOrder" module="Magento_Sales" next="selectCustomerOrder" /> + <step name="selectCustomerOrder" module="Magento_Sales" next="selectStore" /> + <step name="selectStore" module="Magento_Sales" next="addProducts" /> + <step name="addProducts" module="Magento_Sales" next="fillAccountInformation" /> + <step name="fillAccountInformation" module="Magento_Sales" next="fillBillingAddress" /> + <step name="fillBillingAddress" module="Magento_Sales" next="selectShippingMethodForOrder" /> + <step name="selectShippingMethodForOrder" module="Magento_Sales" next="saveCreditCardOnBackend" /> + <step name="saveCreditCardOnBackend" module="Magento_Vault" next="submitOrderNegative" /> + <step name="submitOrderNegative" module="Magento_Sales" /> + </scenario> </config> diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create.php index 874fe2844c476cd530b682143b3099c41646e28d..ae6631eff9a24c9f323bee5bdc91b99dc355972b 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create.php @@ -165,7 +165,7 @@ class Create extends Block * * @return \Magento\Sales\Test\Block\Adminhtml\Order\Create\Billing\Method */ - protected function getBillingMethodBlock() + public function getBillingMethodBlock() { return $this->blockFactory->create( \Magento\Sales\Test\Block\Adminhtml\Order\Create\Billing\Method::class, diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Billing/Method.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Billing/Method.php index 280211c7ef20f54e43f31227551a2b832d7c1ea6..8477af0087fd47e07b8fee3e6c5138c690369d05 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Billing/Method.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Block/Adminhtml/Order/Create/Billing/Method.php @@ -8,6 +8,7 @@ namespace Magento\Sales\Test\Block\Adminhtml\Order\Create\Billing; use Magento\Mtf\Block\Block; use Magento\Mtf\Fixture\InjectableFixture; +use Magento\Mtf\Client\Locator; /** * Adminhtml sales order create payment method block. @@ -42,6 +43,20 @@ class Method extends Block */ protected $loader = '[data-role=loader]'; + /** + * Field with Mage error. + * + * @var string + */ + protected $mageErrorField = '//fieldset/*[contains(@class,"field ")][.//*[contains(@class,"error")]]'; + + /** + * Mage error text. + * + * @var string + */ + protected $mageErrorText = './/label[contains(@class,"error")]'; + /** * Select payment method. * @@ -69,4 +84,23 @@ class Method extends Block $formBlock->fill($creditCard); } } + + /** + * @return array + */ + public function getJsErrors() + { + $data = []; + $elements = $this->_rootElement->getElements($this->mageErrorField, Locator::SELECTOR_XPATH); + foreach ($elements as $element) { + $error = $element->find($this->mageErrorText, Locator::SELECTOR_XPATH); + if ($error->isVisible()) { + $label = $element->find('.//*[contains(@name,"payment")]', Locator::SELECTOR_XPATH); + $label = $label->getAttribute('name'); + $label = preg_replace('/payment\[(.*)\]/u', '$1', $label); + $data[$label] = $error->getText(); + } + } + return $data; + } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/SubmitOrderNegativeStep.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/SubmitOrderNegativeStep.php new file mode 100644 index 0000000000000000000000000000000000000000..ece554eee9c9c32fdc94c74c48589e804aa9090f --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestStep/SubmitOrderNegativeStep.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\TestStep; + +use Magento\Sales\Test\Page\Adminhtml\OrderCreateIndex; +use Magento\Mtf\TestStep\TestStepInterface; + +/** + * Submit Order step. + */ +class SubmitOrderNegativeStep implements TestStepInterface +{ + /** + * Sales order create index page. + * + * @var OrderCreateIndex + */ + protected $orderCreateIndex; + + /** + * @constructor + * @param OrderCreateIndex $orderCreateIndex + */ + public function __construct( + OrderCreateIndex $orderCreateIndex + ) { + $this->orderCreateIndex = $orderCreateIndex; + } + + /** + * Fill Sales Data. + * + * @return void + */ + public function run() + { + $this->orderCreateIndex->getCreateBlock()->submitOrder(); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php index f610ee5e15473c89cc2f4fe4f6f3cc9e92a48eac..3c27a65c4a74385f546c108c077c128ebb4edcfb 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php @@ -476,13 +476,24 @@ class ProductTest extends \PHPUnit_Framework_TestCase } /** - * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @magentoDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php * @magentoAppIsolation enabled */ public function testGetOptions() { - $this->_model = $this->productRepository->get('simple'); - - $this->assertEquals(4, count($this->_model->getOptions())); + $this->_model = $this->productRepository->get('simple_with_custom_options'); + $options = $this->_model->getOptions(); + $this->assertNotEmpty($options); + $expectedValue = [ + '3-1-select' => 3000.00, + '3-2-select' => 5000.00, + '4-1-radio' => 600.234, + '4-2-radio' => 40000.00 + ]; + foreach ($options as $option) { + foreach ($option->getValues() as $value) { + $this->assertEquals($expectedValue[$value->getSku()], floatval($value->getPrice())); + } + } } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options.php new file mode 100644 index 0000000000000000000000000000000000000000..0366e90cd9772036315678f6e3b10d1f59b615fb --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options.php @@ -0,0 +1,114 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +\Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize(); + +/** @var \Magento\TestFramework\ObjectManager $objectManager */ +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + +/** @var \Magento\Catalog\Api\CategoryLinkManagementInterface $categoryLinkManagement */ +$categoryLinkManagement = $objectManager->create(\Magento\Catalog\Api\CategoryLinkManagementInterface::class); + +/** @var $product \Magento\Catalog\Model\Product */ +$product = $objectManager->create(\Magento\Catalog\Model\Product::class); +$product->isObjectNew(true); +$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) + ->setAttributeSetId(4) + ->setWebsiteIds([1]) + ->setName('Simple Product') + ->setSku('simple_with_custom_options') + ->setPrice(10) + ->setWeight(1) + ->setShortDescription("Short description") + ->setTaxClassId(0) + ->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) + ->setStockData( + [ + 'use_config_manage_stock' => 1, + 'qty' => 100, + 'is_qty_decimal' => 0, + 'is_in_stock' => 1, + ] + )->setCanSaveCustomOptions(true) + ->setHasOptions(true); + +$oldOptions = [ + [ + 'previous_group' => 'select', + 'title' => 'Test Select', + 'type' => 'drop_down', + 'is_require' => 1, + 'sort_order' => 0, + 'values' => [ + [ + 'option_type_id' => -1, + 'title' => 'Option 1', + 'price' => '3,000.00', + 'price_type' => 'fixed', + 'sku' => '3-1-select', + ], + [ + 'option_type_id' => -1, + 'title' => 'Option 2', + 'price' => '5,000.00', + 'price_type' => 'fixed', + 'sku' => '3-2-select', + ], + ] + ], + [ + 'previous_group' => 'select', + 'title' => 'Test Radio', + 'type' => 'radio', + 'is_require' => 1, + 'sort_order' => 0, + 'values' => [ + [ + 'option_type_id' => -1, + 'title' => 'Option 1', + 'price' => '600.234', + 'price_type' => 'fixed', + 'sku' => '4-1-radio', + ], + [ + 'option_type_id' => -1, + 'title' => 'Option 2', + 'price' => '40,000.00', + 'price_type' => 'fixed', + 'sku' => '4-2-radio', + ], + ] + ] +]; + +$options = []; + +/** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */ +$customOptionFactory = $objectManager->create(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class); + +foreach ($oldOptions as $option) { + /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterface $option */ + $option = $customOptionFactory->create(['data' => $option]); + $option->setProductSku($product->getSku()); + + $options[] = $option; +} + +$product->setOptions($options); + +/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepositoryFactory */ +$productRepositoryFactory = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class); +$productRepositoryFactory->save($product); + +$categoryLinkManagement->assignProductToCategories( + $product->getSku(), + [2] +); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..88e0fb198576060eb8295e633a985d9d6e3ff96a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options_rollback.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +use Magento\Framework\Exception\NoSuchEntityException; + +\Magento\TestFramework\Helper\Bootstrap::getInstance()->getInstance()->reinitialize(); + +/** @var \Magento\Framework\Registry $registry */ +$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ +$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); +try { + $product = $productRepository->get('simple_with_custom_options', false, null, true); + $productRepository->delete($product); +} catch (NoSuchEntityException $e) { + +} +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates.php b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates.php new file mode 100644 index 0000000000000000000000000000000000000000..5cac40809565e1ed28df9529446550975b39f9f3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); +$resource = $objectManager->get(\Magento\Framework\App\ResourceConnection::class); +$connection = $resource->getConnection(); +$resourceModel = $objectManager->create(\Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate::class); +$entityTable = $resourceModel->getTable('shipping_tablerate'); +$data = + [ + 'website_id' => 1, + 'dest_country_id' => 'US', + 'dest_region_id' => 0, + 'dest_zip' => '*', + 'condition_name' => 'package_qty', + 'condition_value' => 1, + 'price' => 10, + 'cost' => 10 + ]; +$connection->query( + "INSERT INTO {$entityTable} (`website_id`, `dest_country_id`, `dest_region_id`, `dest_zip`, `condition_name`," + . "`condition_value`, `price`, `cost`) VALUES (:website_id, :dest_country_id, :dest_region_id, :dest_zip," + . " :condition_name, :condition_value, :price, :cost);", + $data +); diff --git a/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_rollback.php b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..10f5563eee8aae9c826a8967e93658b59d9c2eca --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_rollback.php @@ -0,0 +1,12 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); +$resource = $objectManager->get(\Magento\Framework\App\ResourceConnection::class); +$connection = $resource->getConnection(); +$resourceModel = $objectManager->create(\Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate::class); +$entityTable = $resourceModel->getTable('shipping_tablerate'); +$connection->query("DELETE FROM {$entityTable};"); diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7ed966d0c9b998a23145bde4f2432019628a3c6f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php @@ -0,0 +1,95 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Quote\Model; + +/** + * Class ShippingMethodManagementTest + */ +class ShippingMethodManagementTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + * @magentoConfigFixture current_store carriers/tablerate/active 1 + * @magentoConfigFixture current_store carriers/tablerate/condition_name package_qty + * @magentoDataFixture Magento/SalesRule/_files/cart_rule_free_shipping.php + * @magentoDataFixture Magento/Sales/_files/quote.php + * @magentoDataFixture Magento/OfflineShipping/_files/tablerates.php + */ + public function testEstimateByAddressWithCartPriceRule() + { + $this->executeTestFlow(0, 0); + } + + /** + * @magentoAppIsolation enabled + * @magentoDbIsolation enabled + * @magentoConfigFixture current_store carriers/tablerate/active 1 + * @magentoConfigFixture current_store carriers/tablerate/condition_name package_qty + * @magentoDataFixture Magento/Sales/_files/quote.php + * @magentoDataFixture Magento/OfflineShipping/_files/tablerates.php + */ + public function testEstimateByAddress() + { + $this->executeTestFlow(5, 10); + } + + /** + * Provide testing of shipping method estimation based on address + * + * @param int $flatRateAmount + * @param int $tableRateAmount + */ + private function executeTestFlow($flatRateAmount, $tableRateAmount) + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + /** @var \Magento\Quote\Model\Quote $quote */ + $quote = $objectManager->get(\Magento\Quote\Model\Quote::class); + $quote->load('test01', 'reserved_order_id'); + $cartId = $quote->getId(); + if (!$cartId) { + $this->fail('quote fixture failed'); + } + /** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */ + $quoteIdMask = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create(\Magento\Quote\Model\QuoteIdMaskFactory::class) + ->create(); + $quoteIdMask->load($cartId, 'quote_id'); + //Use masked cart Id + $cartId = $quoteIdMask->getMaskedId(); + $data = [ + 'data' => [ + 'country_id' => "US", + 'postcode' => null, + 'region' => null, + 'region_id' => null + ] + ]; + /** @var \Magento\Quote\Api\Data\EstimateAddressInterface $address */ + $address = $objectManager->create(\Magento\Quote\Api\Data\EstimateAddressInterface::class, $data); + /** @var \Magento\Quote\Api\GuestShippingMethodManagementInterface $shippingEstimation */ + $shippingEstimation = $objectManager->get(\Magento\Quote\Api\GuestShippingMethodManagementInterface::class); + $result = $shippingEstimation->estimateByAddress($cartId, $address); + $this->assertNotEmpty($result); + $expectedResult = [ + 'tablerate' => + [ + 'method_code' => 'bestway', + 'amount' => $tableRateAmount + ], + 'flatrate' => [ + 'method_code' => 'flatrate', + 'amount' => $flatRateAmount + ] + ]; + foreach ($result as $rate) { + $this->assertEquals($expectedResult[$rate->getCarrierCode()]['amount'], $rate->getAmount()); + $this->assertEquals($expectedResult[$rate->getCarrierCode()]['method_code'], $rate->getMethodCode()); + } + } +} diff --git a/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt b/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt index 77cf93864b0bd4e172da599e9ad854c7b14a5b0a..29b5280ec6693f70c8d65a1f40e25c644897ace1 100644 --- a/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt +++ b/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt @@ -41,13 +41,11 @@ app/code/Magento/Catalog/view/base/web/js/price-utils.js app/code/Magento/Catalog/view/base/web/js/tier-price.js app/code/Magento/Catalog/view/frontend/requirejs-config.js app/code/Magento/Catalog/view/frontend/web/js/catalog-add-to-cart.js -app/code/Magento/Catalog/view/frontend/web/js/compare.js app/code/Magento/Catalog/view/frontend/web/js/gallery.js app/code/Magento/Catalog/view/frontend/web/js/list.js app/code/Magento/Catalog/view/frontend/web/js/product/list/toolbar.js app/code/Magento/Catalog/view/frontend/web/js/related-products.js app/code/Magento/Catalog/view/frontend/web/js/upsell-products.js -app/code/Magento/Catalog/view/frontend/web/js/view/compare-products.js app/code/Magento/Catalog/view/frontend/web/js/view/image.js app/code/Magento/Catalog/view/frontend/web/js/zoom.js app/code/Magento/Catalog/view/frontend/web/product/view/validation.js @@ -218,16 +216,16 @@ app/code/Magento/PageCache/view/frontend/web/js/page-cache.js app/code/Magento/Payment/view/adminhtml/web/transparent.js app/code/Magento/Payment/view/frontend/requirejs-config.js app/code/Magento/Payment/view/frontend/web/cc-type.js -app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-data.js -app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator.js -app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js -app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js -app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/cvv-validator.js -app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator.js -app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js -app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js -app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js -app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js +app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-data.js +app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator.js +app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js +app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js +app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/cvv-validator.js +app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/expiration-date-validator.js +app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js +app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js +app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js +app/code/Magento/Payment/view/base/web/js/model/credit-card-validation/validator.js app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js app/code/Magento/Payment/view/frontend/web/js/view/payment/iframe.js app/code/Magento/Payment/view/frontend/web/js/view/payment/method-renderer/free-method.js @@ -511,7 +509,6 @@ lib/web/mage/captcha.js lib/web/mage/collapsible.js lib/web/mage/common.js lib/web/mage/cookies.js -lib/web/mage/dataPost.js lib/web/mage/decorate.js lib/web/mage/deletable-item.js lib/web/mage/dialog.js @@ -603,13 +600,11 @@ vendor/magento/module-catalog/view/base/web/js/price-utils.js vendor/magento/module-catalog/view/base/web/js/tier-price.js vendor/magento/module-catalog/view/frontend/requirejs-config.js vendor/magento/module-catalog/view/frontend/web/js/catalog-add-to-cart.js -vendor/magento/module-catalog/view/frontend/web/js/compare.js vendor/magento/module-catalog/view/frontend/web/js/gallery.js vendor/magento/module-catalog/view/frontend/web/js/list.js vendor/magento/module-catalog/view/frontend/web/js/product/list/toolbar.js vendor/magento/module-catalog/view/frontend/web/js/related-products.js vendor/magento/module-catalog/view/frontend/web/js/upsell-products.js -vendor/magento/module-catalog/view/frontend/web/js/view/compare-products.js vendor/magento/module-catalog/view/frontend/web/js/view/image.js vendor/magento/module-catalog/view/frontend/web/js/zoom.js vendor/magento/module-catalog/view/frontend/web/product/view/validation.js @@ -776,16 +771,16 @@ vendor/magento/module-page-cache/view/frontend/web/js/page-cache.js vendor/magento/module-payment/view/adminhtml/web/transparent.js vendor/magento/module-payment/view/frontend/requirejs-config.js vendor/magento/module-payment/view/frontend/web/cc-type.js -vendor/magento/module-payment/view/frontend/web/js/model/credit-card-validation/credit-card-data.js -vendor/magento/module-payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator.js -vendor/magento/module-payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js -vendor/magento/module-payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js -vendor/magento/module-payment/view/frontend/web/js/model/credit-card-validation/cvv-validator.js -vendor/magento/module-payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator.js -vendor/magento/module-payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js -vendor/magento/module-payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js -vendor/magento/module-payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js -vendor/magento/module-payment/view/frontend/web/js/model/credit-card-validation/validator.js +vendor/magento/module-payment/view/base/web/js/model/credit-card-validation/credit-card-data.js +vendor/magento/module-payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator.js +vendor/magento/module-payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js +vendor/magento/module-payment/view/base/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js +vendor/magento/module-payment/view/base/web/js/model/credit-card-validation/cvv-validator.js +vendor/magento/module-payment/view/base/web/js/model/credit-card-validation/expiration-date-validator.js +vendor/magento/module-payment/view/base/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js +vendor/magento/module-payment/view/base/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js +vendor/magento/module-payment/view/base/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js +vendor/magento/module-payment/view/base/web/js/model/credit-card-validation/validator.js vendor/magento/module-payment/view/frontend/web/js/view/payment/cc-form.js vendor/magento/module-payment/view/frontend/web/js/view/payment/iframe.js vendor/magento/module-payment/view/frontend/web/js/view/payment/method-renderer/free-method.js diff --git a/lib/internal/Magento/Framework/EntityManager/Observer/AfterEntityLoad.php b/lib/internal/Magento/Framework/EntityManager/Observer/AfterEntityLoad.php index 010cafdd2f7148156bd02b0f2c28db5e469c0f54..3de6bd8fbcdd55840c39d31bf449f1f3ae5c6486 100644 --- a/lib/internal/Magento/Framework/EntityManager/Observer/AfterEntityLoad.php +++ b/lib/internal/Magento/Framework/EntityManager/Observer/AfterEntityLoad.php @@ -32,6 +32,7 @@ class AfterEntityLoad implements ObserverInterface } $entity->getResource()->afterLoad($entity); $entity->afterLoad(); + $entity->setOrigData(); $entity->setHasDataChanges(false); } } diff --git a/lib/internal/Magento/Framework/EntityManager/Observer/BeforeEntityLoad.php b/lib/internal/Magento/Framework/EntityManager/Observer/BeforeEntityLoad.php new file mode 100644 index 0000000000000000000000000000000000000000..1d292a2e5b3f81516563336f11dbf195b93b64d1 --- /dev/null +++ b/lib/internal/Magento/Framework/EntityManager/Observer/BeforeEntityLoad.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\EntityManager\Observer; + +use Magento\Framework\Event\Observer; +use Magento\Framework\Model\AbstractModel; + +/** + * Class BeforeEntityLoad + */ +class BeforeEntityLoad +{ + /** + * Apply model before load operation + * + * @param Observer $observer + * @throws \Magento\Framework\Validator\Exception + * @return void + */ + public function execute(Observer $observer) + { + $identifier = $observer->getEvent()->getIdentifier(); + $entity = $observer->getEvent()->getEntity(); + if ($entity instanceof AbstractModel) { + $entity->beforeLoad($identifier); + } + } +} diff --git a/lib/internal/Magento/Framework/EntityManager/Operation/Read.php b/lib/internal/Magento/Framework/EntityManager/Operation/Read.php index 1cd988f53a0050aeaffa1e55b96270a2eb84ce2c..19a3912890db5af5f50cfab964e0c2ca0de572c4 100644 --- a/lib/internal/Magento/Framework/EntityManager/Operation/Read.php +++ b/lib/internal/Magento/Framework/EntityManager/Operation/Read.php @@ -5,7 +5,6 @@ */ namespace Magento\Framework\EntityManager\Operation; -use Magento\Framework\EntityManager\Operation\ReadInterface; use Magento\Framework\EntityManager\Operation\Read\ReadMain; use Magento\Framework\EntityManager\Operation\Read\ReadAttributes; use Magento\Framework\EntityManager\Operation\Read\ReadExtensions; @@ -13,7 +12,6 @@ use Magento\Framework\EntityManager\HydratorPool; use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\EntityManager\EventManager; use Magento\Framework\EntityManager\TypeResolver; -use Magento\Framework\App\ResourceConnection; /** * Class Read @@ -83,11 +81,7 @@ class Read implements ReadInterface } /** - * @param object $entity - * @param string $identifier - * @param array $arguments - * @return object - * @throws \Exception + * {@inheritDoc} */ public function execute($entity, $identifier, $arguments = []) { @@ -107,6 +101,7 @@ class Read implements ReadInterface 'load_before', [ 'identifier' => $identifier, + 'entity' => $entity, 'arguments' => $arguments ] ); diff --git a/lib/internal/Magento/Framework/Interception/PluginList/PluginList.php b/lib/internal/Magento/Framework/Interception/PluginList/PluginList.php index befff770156178dd2324e42365b62ac52414c9e8..ecfb67320cb0d58decdf67de64d2058814f1eaf8 100644 --- a/lib/internal/Magento/Framework/Interception/PluginList/PluginList.php +++ b/lib/internal/Magento/Framework/Interception/PluginList/PluginList.php @@ -75,6 +75,11 @@ class PluginList extends Scoped implements InterceptionPluginList */ protected $_pluginInstances = []; + /** + * @var \Psr\Log\LoggerInterface + */ + private $logger; + /** * @param ReaderInterface $reader * @param ScopeInterface $configScope @@ -149,6 +154,7 @@ class PluginList extends Scoped implements InterceptionPluginList } $this->_inherited[$type] = null; if (is_array($plugins) && count($plugins)) { + $this->filterPlugins($plugins); uasort($plugins, [$this, '_sort']); $this->trimInstanceStartingBackslash($plugins); $this->_inherited[$type] = $plugins; @@ -348,4 +354,34 @@ class PluginList extends Scoped implements InterceptionPluginList } } } + + /** + * Remove from list not existing plugins + * + * @param array $plugins + * @return void + */ + private function filterPlugins(array &$plugins) + { + foreach ($plugins as $name => $plugin) { + if (empty($plugin['instance'])) { + unset($plugins[$name]); + $this->getLogger()->info("Reference to undeclared plugin with name '{$name}'."); + } + } + } + + /** + * Returns logger instance + * + * @deprecated + * @return \Psr\Log\LoggerInterface + */ + private function getLogger() + { + if ($this->logger === null) { + $this->logger = $this->_objectManager->get(\Psr\Log\LoggerInterface::class); + } + return $this->logger; + } } diff --git a/lib/internal/Magento/Framework/Interception/Test/Unit/PluginList/PluginListTest.php b/lib/internal/Magento/Framework/Interception/Test/Unit/PluginList/PluginListTest.php index 1291ae44bce6522bf61f1bdbc42c3089a09abd48..b3fe011a0a490727c0682f1863aa731622753264 100644 --- a/lib/internal/Magento/Framework/Interception/Test/Unit/PluginList/PluginListTest.php +++ b/lib/internal/Magento/Framework/Interception/Test/Unit/PluginList/PluginListTest.php @@ -60,7 +60,6 @@ class PluginListTest extends \PHPUnit_Framework_TestCase $omConfigMock->expects($this->any())->method('getOriginalInstanceType')->will($this->returnArgument(0)); $this->_objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class); - $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0)); $definitions = new \Magento\Framework\ObjectManager\Definition\Runtime(); @@ -80,6 +79,7 @@ class PluginListTest extends \PHPUnit_Framework_TestCase public function testGetPlugin() { + $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0)); $this->_configScopeMock->expects($this->any())->method('getCurrentScope')->will($this->returnValue('backend')); $this->_model->getNext(\Magento\Framework\Interception\Test\Unit\Custom\Module\Model\Item::class, 'getName'); $this->_model->getNext( @@ -131,6 +131,7 @@ class PluginListTest extends \PHPUnit_Framework_TestCase */ public function testGetPlugins($expectedResult, $type, $method, $scopeCode, $code = '__self') { + $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0)); $this->_configScopeMock->expects( $this->any() )->method( @@ -206,6 +207,7 @@ class PluginListTest extends \PHPUnit_Framework_TestCase */ public function testInheritPluginsWithNonExistingClass() { + $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0)); $this->_configScopeMock->expects($this->any()) ->method('getCurrentScope') ->will($this->returnValue('frontend')); @@ -213,12 +215,34 @@ class PluginListTest extends \PHPUnit_Framework_TestCase $this->_model->getNext('SomeType', 'someMethod'); } + /** + * @covers \Magento\Framework\Interception\PluginList\PluginList::getNext + * @covers \Magento\Framework\Interception\PluginList\PluginList::_inheritPlugins + */ + public function testInheritPluginsWithNotExistingPlugin() + { + $loggerMock = $this->getMock(\Psr\Log\LoggerInterface::class); + $this->_objectManagerMock->expects($this->once()) + ->method('get') + ->with(\Psr\Log\LoggerInterface::class) + ->willReturn($loggerMock); + $loggerMock->expects($this->once()) + ->method('info') + ->with("Reference to undeclared plugin with name 'simple_plugin'."); + $this->_configScopeMock->expects($this->any()) + ->method('getCurrentScope') + ->will($this->returnValue('frontend')); + + $this->assertNull($this->_model->getNext('typeWithoutInstance', 'someMethod')); + } + /** * @covers \Magento\Framework\Interception\PluginList\PluginList::getNext * @covers \Magento\Framework\Interception\PluginList\PluginList::_loadScopedData */ public function testLoadScopedDataCached() { + $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0)); $this->_configScopeMock->expects($this->once()) ->method('getCurrentScope') ->will($this->returnValue('scope')); diff --git a/lib/internal/Magento/Framework/Interception/Test/Unit/_files/reader_mock_map.php b/lib/internal/Magento/Framework/Interception/Test/Unit/_files/reader_mock_map.php index 832a5a67599da7f9dbfe46e2732324b536f267c8..87bbe0d35dd2561799cd5d2024347c8fb48c2b73 100644 --- a/lib/internal/Magento/Framework/Interception/Test/Unit/_files/reader_mock_map.php +++ b/lib/internal/Magento/Framework/Interception/Test/Unit/_files/reader_mock_map.php @@ -70,6 +70,11 @@ return [ 'instance' => 'NonExistingPluginClass', ], ], + ], + 'typeWithoutInstance' => [ + 'plugins' => [ + 'simple_plugin' => [], + ], ] ] ] diff --git a/lib/internal/Magento/Framework/Model/AbstractModel.php b/lib/internal/Magento/Framework/Model/AbstractModel.php index dbbb20021b9f4dcc03765aee89bdbd81339bac08..34536d47097796d18e1ff517f2fd1ad2a7317735 100644 --- a/lib/internal/Magento/Framework/Model/AbstractModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractModel.php @@ -527,12 +527,7 @@ abstract class AbstractModel extends \Magento\Framework\DataObject */ public function load($modelId, $field = null) { - $this->_beforeLoad($modelId, $field); $this->_getResource()->load($this, $modelId, $field); - $this->_afterLoad(); - $this->setOrigData(); - $this->_hasDataChanges = false; - $this->updateStoredData(); return $this; } @@ -577,6 +572,18 @@ abstract class AbstractModel extends \Magento\Framework\DataObject return $this; } + /** + * Process operation before object load + * + * @param string $identifier + * @param string|null $field + * @return void + */ + public function beforeLoad($identifier, $field = null) + { + $this->_beforeLoad($identifier, $field); + } + /** * Object after load processing. Implemented as public interface for supporting objects after load in collections * @@ -584,7 +591,6 @@ abstract class AbstractModel extends \Magento\Framework\DataObject */ public function afterLoad() { - $this->getResource()->afterLoad($this); $this->_afterLoad(); $this->updateStoredData(); return $this; diff --git a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php index fc189473505abd258acb159f32ff9d2b77d44958..7febcb450f9720d9999f19704808df90ca69deea 100644 --- a/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php +++ b/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php @@ -332,6 +332,7 @@ abstract class AbstractDb extends AbstractResource */ public function load(\Magento\Framework\Model\AbstractModel $object, $value, $field = null) { + $object->beforeLoad($value, $field); if ($field === null) { $field = $this->getIdFieldName(); } @@ -348,7 +349,10 @@ abstract class AbstractDb extends AbstractResource $this->unserializeFields($object); $this->_afterLoad($object); - + $object->afterLoad(); + $object->setOrigData(); + $object->setHasDataChanges(false); + return $this; } diff --git a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/Db/AbstractDbTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/Db/AbstractDbTest.php index 1dcb84d276840185af916c1bc6036cc4b1ea5071..0a2e6f2262173f244dc0dddf8c53fa44c9bf3558 100644 --- a/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/Db/AbstractDbTest.php +++ b/lib/internal/Magento/Framework/Model/Test/Unit/ResourceModel/Db/AbstractDbTest.php @@ -269,29 +269,19 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase public function testLoad() { - $contextMock = $this->getMock(\Magento\Framework\Model\Context::class, [], [], '', false); - $registryMock = $this->getMock(\Magento\Framework\Registry::class, [], [], '', false); - $abstractModelMock = $this->getMockForAbstractClass( - \Magento\Framework\Model\AbstractModel::class, - [$contextMock, $registryMock], - '', - false, - true, - true, - ['__wakeup'] - ); - - $value = 'some_value'; - $idFieldName = new \ReflectionProperty( - \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, - '_idFieldName' - ); - $idFieldName->setAccessible(true); - $idFieldName->setValue($this->_model, 'field_value'); - + /** @var \Magento\Framework\Model\AbstractModel|\PHPUnit_Framework_MockObject_MockObject $object */ + $object = $this->getMockBuilder(\Magento\Framework\Model\AbstractModel::class) + ->disableOriginalConstructor() + ->getMock(); + $object->expects($this->once())->method('beforeLoad')->with('some_value', 'field_name'); + $object->expects($this->once())->method('afterLoad')->willReturnSelf(); + $object->expects($this->once())->method('setOrigData')->willReturnSelf(); + $object->expects($this->once())->method('setHasDataChanges')->with(false)->willReturnSelf(); + $result = $this->_model->load($object, 'some_value', 'field_name'); + $this->assertEquals($this->_model, $result); $this->assertInstanceOf( \Magento\Framework\Model\ResourceModel\Db\AbstractDb::class, - $this->_model->load($abstractModelMock, $value, $idFieldName) + $result ); } @@ -497,7 +487,6 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase $idFieldNameReflection->setValue($this->_model, 'idFieldName'); $connectionMock->expects($this->any())->method('save')->with('tableName', 'idFieldName'); $connectionMock->expects($this->any())->method('quoteInto')->will($this->returnValue('idFieldName')); - $abstractModelMock->setIdFieldName('id'); $abstractModelMock->setData( [ diff --git a/lib/web/mage/dataPost.js b/lib/web/mage/dataPost.js index e1c297ffcef4b9a6a3d64806d5f93eb57e938644..2d47929f57213c338c5b121310c544b3876331ec 100644 --- a/lib/web/mage/dataPost.js +++ b/lib/web/mage/dataPost.js @@ -2,50 +2,88 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ -/*jshint browser:true jquery:true*/ -/*global confirm:true*/ + define([ - "jquery", - "mage/template", - "jquery/ui" -], function($,mageTemplate){ - + 'jquery', + 'mage/template', + 'Magento_Ui/js/modal/confirm', + 'jquery/ui' +], function ($, mageTemplate, uiConfirm) { + 'use strict'; + $.widget('mage.dataPost', { options: { - formTemplate: '<form action="<%- data.action %>" method="post">' - + '<% _.each(data.data, function(value, index) { %>' - + '<input name="<%- index %>" value="<%- value %>">' - + '<% }) %></form>', + formTemplate: '<form action="<%- data.action %>" method="post">' + + '<% _.each(data.data, function(value, index) { %>' + + '<input name="<%- index %>" value="<%- value %>">' + + '<% }) %></form>', postTrigger: ['a[data-post]', 'button[data-post]', 'span[data-post]'], formKeyInputSelector: 'input[name="form_key"]' }, - _create: function() { + + /** @inheritdoc */ + _create: function () { this._bind(); }, - _bind: function() { + + /** @inheritdoc */ + _bind: function () { var events = {}; - $.each(this.options.postTrigger, function(index, value) { + + $.each(this.options.postTrigger, function (index, value) { events['click ' + value] = '_postDataAction'; }); + this._on(events); }, - _postDataAction: function(e) { - e.preventDefault(); + + /** + * Handler for click. + * + * @param {Object} e + * @private + */ + _postDataAction: function (e) { var params = $(e.currentTarget).data('post'); + + e.preventDefault(); this.postData(params); }, - postData: function(params) { - var formKey = $(this.options.formKeyInputSelector).val(); + + /** + * Data post action. + * + * @param {Object} params + */ + postData: function (params) { + var formKey = $(this.options.formKeyInputSelector).val(), + $form; + if (formKey) { - params.data.form_key = formKey; + params.data['form_key'] = formKey; } - $(mageTemplate(this.options.formTemplate, { + + $form = $(mageTemplate(this.options.formTemplate, { data: params - })).appendTo('body').hide().submit(); + })); + + if (params.data.confirmation) { + uiConfirm({ + content: params.data.confirmationMessage, + actions: { + /** @inheritdoc */ + confirm: function () { + $form.appendTo('body').hide().submit(); + } + } + }); + } else { + $form.appendTo('body').hide().submit(); + } } }); - + $(document).dataPost(); return $.mage.dataPost; -}); \ No newline at end of file +});