From 85db4c87491d43fa4d4de59c6fe3d6cc1486835b Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Mon, 16 Jan 2017 17:52:34 +0200 Subject: [PATCH 01/27] MAGETWO-54733: Unable to save product with all unchecked values for multiple select attribute #7687 --- .../Entity/Attribute/Backend/ArrayBackend.php | 2 ++ .../Magento/Ui/view/base/web/js/form/client.js | 3 ++- .../view/base/web/js/form/element/multiselect.js | 14 +++++++++++++- lib/web/mage/utils/misc.js | 16 ++++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Backend/ArrayBackend.php b/app/code/Magento/Eav/Model/Entity/Attribute/Backend/ArrayBackend.php index 47a998a95ecb5..c387631e693cd 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Backend/ArrayBackend.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Backend/ArrayBackend.php @@ -42,6 +42,8 @@ public function validate($object) $data = $object->getData($attributeCode); if (is_array($data)) { $object->setData($attributeCode, implode(',', array_filter($data))); + } elseif (empty($data)) { + $object->setData($attributeCode, null); } return parent::validate($object); } diff --git a/app/code/Magento/Ui/view/base/web/js/form/client.js b/app/code/Magento/Ui/view/base/web/js/form/client.js index 6b4c1a3262273..d1874508483e8 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/client.js +++ b/app/code/Magento/Ui/view/base/web/js/form/client.js @@ -22,7 +22,8 @@ define([ function beforeSave(data, url, selectorPrefix, messagesClass) { var save = $.Deferred(); - data = utils.serialize(data); + data = utils.filterFormData(data) + data = utils.serialize(utils.filterFormData(data)); data['form_key'] = window.FORM_KEY; diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js b/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js index 37b389dcba027..c5d66acda70f0 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js @@ -13,7 +13,10 @@ define([ return Select.extend({ defaults: { size: 5, - elementTmpl: 'ui/form/element/multiselect' + elementTmpl: 'ui/form/element/multiselect', + listens: { + value: 'setDifferedFromDefault setPrepareToSendData' + } }, /** @@ -38,6 +41,15 @@ define([ return _.isString(value) ? value.split(',') : value; }, + setPrepareToSendData: function (data) { + + if (!data.length) { + data = ''; + } + + this.source.set(this.dataScope + '-prepared-for-send', data); + }, + /** * @inheritdoc */ diff --git a/lib/web/mage/utils/misc.js b/lib/web/mage/utils/misc.js index 576c2244ad0cd..0aa07577f1df8 100644 --- a/lib/web/mage/utils/misc.js +++ b/lib/web/mage/utils/misc.js @@ -209,6 +209,22 @@ define([ return formData; }, + filterFormData: function (data, sufix, separator) { + sufix = sufix || 'prepared-for-send'; + separator = separator || '-'; + + _.each(data, function (value, key) { + if (_.isObject(value) && !value.length) { + this.filterFormData(value, sufix, separator) + } else if (_.isString(key) && ~key.indexOf(sufix)) { + data[key.split(separator)[0]] = value; + delete data[key]; + } + }, this); + + return data; + }, + /** * Converts PHP IntlFormatter format to moment format. * From b6c5198f20b64807b56397608b1b537b58366eae Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Tue, 17 Jan 2017 13:22:51 +0200 Subject: [PATCH 02/27] MAGETWO-54733: Unable to save product with all unchecked values for multiple select attribute #7687 --- .../Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayTest.php index 24969add7a3ad..f9bd041fc7c2f 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayTest.php @@ -37,9 +37,10 @@ protected function setUp() public function testValidate($data) { $this->_attribute->expects($this->atLeastOnce())->method('getAttributeCode')->will($this->returnValue('code')); - $product = new \Magento\Framework\DataObject(['code' => $data]); + $product = new \Magento\Framework\DataObject(['code' => $data, 'empty' => '']); $this->_model->validate($product); $this->assertEquals('1,2,3', $product->getCode()); + $this->assertEquals(null, $product->getEmpty()); } public static function attributeValueDataProvider() From 72bd339d2b97f5bd3d49fae48dcc1c668527d16b Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Tue, 17 Jan 2017 17:56:19 +0200 Subject: [PATCH 03/27] MAGETWO-54733: Unable to save product with all unchecked values for multiple select attribute #7687 --- .../base/web/js/form/element/multiselect.js | 8 ++- .../base/js/form/element/multiselect.test.js | 60 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/multiselect.test.js diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js b/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js index c5d66acda70f0..cea94114990cf 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js @@ -41,8 +41,14 @@ define([ return _.isString(value) ? value.split(',') : value; }, + /** + * Sets the prepared data to dataSource + * by path, where key is component link to dataSource with + * suffix "-prepared-for-send" + * + * @param {Array} data - current component value + */ setPrepareToSendData: function (data) { - if (!data.length) { data = ''; } diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/multiselect.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/multiselect.test.js new file mode 100644 index 0000000000000..c0f4b345509d0 --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/multiselect.test.js @@ -0,0 +1,60 @@ +/** + * Copyright © 2013-2017 Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +/* eslint max-nested-callbacks: 0 */ +define([ + 'squire' +], function (Squire) { + 'use strict'; + + var injector = new Squire(), + mocks = { + 'Magento_Ui/js/lib/core/events': { + on: jasmine.createSpy() + }, + 'Magento_Ui/js/lib/registry/registry': { + get: function() { + return { + get: jasmine.createSpy(), + set: jasmine.createSpy() + }; + }, + create: jasmine.createSpy(), + set: jasmine.createSpy(), + async: jasmine.createSpy() + }, + '/mage/utils/wrapper': jasmine.createSpy() + }, + obj, + dataScope = 'dataScope'; + + beforeEach(function (done) { + injector.mock(mocks); + injector.require(['Magento_Ui/js/form/element/multiselect'], function (Constr) { + obj = new Constr({ + provider: 'provName', + name: '', + index: '', + dataScope: dataScope + }); + + done(); + }); + }); + + describe('Magento_Ui/js/form/element/multiselect', function () { + describe('"setPrepareToSendData" method', function () { + it('Check method call with empty array as parameter.', function () { + expect(obj.setPrepareToSendData([])).toBeUndefined(); + expect(obj.source.set).toHaveBeenCalledWith(dataScope + '-prepared-for-send', ''); + }); + + it('Check method call with array with data as parameter.', function () { + expect(obj.setPrepareToSendData(['1', '2', '3'])).toBeUndefined(); + expect(obj.source.set).toHaveBeenCalledWith(dataScope + '-prepared-for-send', ['1', '2', '3']); + }); + }); + }); +}); From 146c1963dc4391fa3d9245e6fe173c45d0f5e567 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Tue, 17 Jan 2017 23:33:00 +0200 Subject: [PATCH 04/27] MAGETWO-54733: Unable to save product with all unchecked values for multiple select attribute #7687 --- dev/tests/js/jasmine/tests/lib/mage/misc.test.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dev/tests/js/jasmine/tests/lib/mage/misc.test.js b/dev/tests/js/jasmine/tests/lib/mage/misc.test.js index 02e94524aae41..0f399b13fe841 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/misc.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/misc.test.js @@ -19,6 +19,17 @@ define([ expect(utils.convertToMomentFormat(format)).toBe(momentFormat); }); + it('Check "filterFormData" method', function () { + var suffix = 'prepared-for-send', + separator = '-', + data = { + key: 'value-prepared-before-save' + }; + expect(utils.filterFormData(data, suffix, separator)).toEqual(data); + expect(utils.filterFormData(data, suffix)).toEqual(data); + expect(utils.filterFormData(data)).toEqual(data); + }); + it('Check convertToMomentFormat function for all Magento supported locales', function () { var fixture, From 07d6f1c654ccfd385e5191e37d01064b1af9f01f Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Wed, 18 Jan 2017 16:06:12 +0200 Subject: [PATCH 05/27] MAGETWO-54733: Unable to save product with all unchecked values for multiple select attribute #7687 --- .../{ArrayTest.php => ArrayBackendTest.php} | 0 .../Ui/view/base/web/js/form/client.js | 2 - .../Magento/Ui/base/js/form/client.test.js | 67 ++++++++++++++++++- .../js/jasmine/tests/lib/mage/misc.test.js | 1 + lib/web/mage/utils/misc.js | 19 ++++-- 5 files changed, 80 insertions(+), 9 deletions(-) rename app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/{ArrayTest.php => ArrayBackendTest.php} (100%) diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayBackendTest.php similarity index 100% rename from app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayTest.php rename to app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayBackendTest.php diff --git a/app/code/Magento/Ui/view/base/web/js/form/client.js b/app/code/Magento/Ui/view/base/web/js/form/client.js index d1874508483e8..1007c7bbd2b36 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/client.js +++ b/app/code/Magento/Ui/view/base/web/js/form/client.js @@ -22,9 +22,7 @@ define([ function beforeSave(data, url, selectorPrefix, messagesClass) { var save = $.Deferred(); - data = utils.filterFormData(data) data = utils.serialize(utils.filterFormData(data)); - data['form_key'] = window.FORM_KEY; if (!url || url === 'undefined') { diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js index 8a14feccd6910..285f2ac454584 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js @@ -10,18 +10,21 @@ define([ 'underscore', 'uiRegistry', - 'Magento_Ui/js/form/client' -], function (_, registry, Constr) { + 'Magento_Ui/js/form/client', + 'jquery', + 'mageUtils' +], function (_, registry, Constr, $, utils) { 'use strict'; describe('Magento_Ui/js/form/client', function () { - var obj = new Constr({ provider: 'provName', name: '', index: '' }); + window.FORM_KEY = 'magentoFormKey'; + registry.set('provName', { on: function () { }, @@ -50,7 +53,65 @@ define([ expect(type).toEqual('object'); }); + it('Check "beforeSave" method. Check call "filterFormData" inside themselves.', function () { + var data = { + key: { + anotherKey: 'value' + }, + anotherKey: [] + }; + + obj.urls.beforeSave = 'requestPath'; + obj.selectorPrefix = 'selectorPrefix'; + obj.messagesClass = 'messagesClass'; + utils.filterFormData = jasmine.createSpy().and.returnValue(utils.filterFormData(data)); + + obj.save(data); + expect(utils.filterFormData).toHaveBeenCalledWith(data); + }); + it('Check "beforeSave" method. Check call "serialize" inside themselves.', function () { + var data = { + key: { + anotherKey: 'value' + }, + anotherKey: [] + }; + + obj.urls.beforeSave = 'requestPath'; + obj.selectorPrefix = 'selectorPrefix'; + obj.messagesClass = 'messagesClass'; + utils.serialize = jasmine.createSpy().and.returnValue(utils.serialize(data)); + + obj.save(data); + expect(utils.serialize).toHaveBeenCalledWith(data); + }); + it('Check "beforeSave" method. Check call "ajax" inside themselves.', function () { + var data = { + key: { + anotherKey: 'value' + }, + 'anotherKey-prepared-for-send': [] + }, + result = { + url: obj.urls.beforeSave, + data: { + 'key[anotherKey]': 'value', + 'form_key': 'magentoFormKey' + }, + success: jasmine.any(Function), + complete: jasmine.any(Function) + }; + + obj.urls.beforeSave = 'requestPath'; + obj.selectorPrefix = 'selectorPrefix'; + obj.messagesClass = 'messagesClass'; + $.ajax = jasmine.createSpy(); + + obj.save(data); + expect($.ajax).toHaveBeenCalledWith(result); + }); }); + describe('"initialize" method', function () { it('Check for defined ', function () { expect(obj.hasOwnProperty('initialize')).toBeDefined(); diff --git a/dev/tests/js/jasmine/tests/lib/mage/misc.test.js b/dev/tests/js/jasmine/tests/lib/mage/misc.test.js index 0f399b13fe841..170177b42ccb0 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/misc.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/misc.test.js @@ -28,6 +28,7 @@ define([ expect(utils.filterFormData(data, suffix, separator)).toEqual(data); expect(utils.filterFormData(data, suffix)).toEqual(data); expect(utils.filterFormData(data)).toEqual(data); + expect(utils.filterFormData()).toEqual({}); }); it('Check convertToMomentFormat function for all Magento supported locales', function () { diff --git a/lib/web/mage/utils/misc.js b/lib/web/mage/utils/misc.js index 0aa07577f1df8..ed0452ceef64e 100644 --- a/lib/web/mage/utils/misc.js +++ b/lib/web/mage/utils/misc.js @@ -209,14 +209,25 @@ define([ return formData; }, - filterFormData: function (data, sufix, separator) { - sufix = sufix || 'prepared-for-send'; + /** + * Filters data. Find properties with suffix + * and set his value to original properties. + * + * @param {Object} data + * @param {String} suffix + * @param {String} separator + * + * @returns {Object} + */ + filterFormData: function (data, suffix, separator) { + data = data || {}; + suffix = suffix || 'prepared-for-send'; separator = separator || '-'; _.each(data, function (value, key) { if (_.isObject(value) && !value.length) { - this.filterFormData(value, sufix, separator) - } else if (_.isString(key) && ~key.indexOf(sufix)) { + this.filterFormData(value, suffix, separator) + } else if (_.isString(key) && ~key.indexOf(suffix)) { data[key.split(separator)[0]] = value; delete data[key]; } From cdab87a8a502fd772c2acfc63f1bb43275f27d05 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Wed, 18 Jan 2017 16:36:26 +0200 Subject: [PATCH 06/27] MAGETWO-54733: Unable to save product with all unchecked values for multiple select attribute #7687 --- .../Unit/Model/Entity/Attribute/Backend/ArrayBackendTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayBackendTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayBackendTest.php index f9bd041fc7c2f..e454f1f22f7bb 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayBackendTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayBackendTest.php @@ -5,7 +5,7 @@ */ namespace Magento\Eav\Test\Unit\Model\Entity\Attribute\Backend; -class ArrayTest extends \PHPUnit_Framework_TestCase +class ArrayBackendTest extends \PHPUnit_Framework_TestCase { /** * @var \Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend From b86644e5078c2c626ea3e1d2047c365778863f4f Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Wed, 18 Jan 2017 17:45:44 +0200 Subject: [PATCH 07/27] MAGETWO-54733: Unable to save product with all unchecked values for multiple select attribute #7687 --- .../Magento/Ui/base/js/form/client.test.js | 63 +++++++------------ lib/web/mage/utils/misc.js | 12 ++-- 2 files changed, 29 insertions(+), 46 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js index 285f2ac454584..33b8c203a7164 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js @@ -53,62 +53,45 @@ define([ expect(type).toEqual('object'); }); - it('Check "beforeSave" method. Check call "filterFormData" inside themselves.', function () { + it('Check "beforeSave" method. ' + + 'Check calls "filterFormData", "serialize" and "ajax" inside themselves.', function () { var data = { key: { anotherKey: 'value' }, anotherKey: [] - }; + }, + params; obj.urls.beforeSave = 'requestPath'; obj.selectorPrefix = 'selectorPrefix'; obj.messagesClass = 'messagesClass'; - utils.filterFormData = jasmine.createSpy().and.returnValue(utils.filterFormData(data)); - - obj.save(data); - expect(utils.filterFormData).toHaveBeenCalledWith(data); - }); - it('Check "beforeSave" method. Check call "serialize" inside themselves.', function () { - var data = { - key: { - anotherKey: 'value' - }, - anotherKey: [] - }; - obj.urls.beforeSave = 'requestPath'; - obj.selectorPrefix = 'selectorPrefix'; - obj.messagesClass = 'messagesClass'; - utils.serialize = jasmine.createSpy().and.returnValue(utils.serialize(data)); + params = { + url: obj.urls.beforeSave, + data: _.extend(data, { + form_key: 'magentoFormKey' + }), + success: jasmine.any(Function), + complete: jasmine.any(Function) + }; + + utils.filterFormData = jasmine.createSpy().and.returnValue(data); + utils.serialize = jasmine.createSpy().and.returnValue(data); + $.ajax = jasmine.createSpy(); obj.save(data); + expect(utils.filterFormData).toHaveBeenCalledWith(data); expect(utils.serialize).toHaveBeenCalledWith(data); - }); - it('Check "beforeSave" method. Check call "ajax" inside themselves.', function () { - var data = { - key: { - anotherKey: 'value' - }, - 'anotherKey-prepared-for-send': [] - }, - result = { - url: obj.urls.beforeSave, - data: { - 'key[anotherKey]': 'value', - 'form_key': 'magentoFormKey' - }, - success: jasmine.any(Function), - complete: jasmine.any(Function) - }; + expect($.ajax).toHaveBeenCalledWith(params); - obj.urls.beforeSave = 'requestPath'; - obj.selectorPrefix = 'selectorPrefix'; - obj.messagesClass = 'messagesClass'; + }); + it('Check call "beforeSave" method without parameters', function () { $.ajax = jasmine.createSpy(); + obj.urls.beforeSave = null; + obj.save(); - obj.save(data); - expect($.ajax).toHaveBeenCalledWith(result); + expect($.ajax).not.toHaveBeenCalled(); }); }); diff --git a/lib/web/mage/utils/misc.js b/lib/web/mage/utils/misc.js index ed0452ceef64e..0f04dab7e440a 100644 --- a/lib/web/mage/utils/misc.js +++ b/lib/web/mage/utils/misc.js @@ -210,14 +210,14 @@ define([ }, /** - * Filters data. Find properties with suffix - * and set his value to original properties. + * Filters data object. Finds properties with suffix + * and sets their values to properties with the same name without suffix. * - * @param {Object} data - * @param {String} suffix - * @param {String} separator + * @param {Object} data - The data object that should be filtered + * @param {String} suffix - The string by which data object should be filtered + * @param {String} separator - The string that is separator between property and suffix * - * @returns {Object} + * @returns {Object} Filtered data object */ filterFormData: function (data, suffix, separator) { data = data || {}; From efac4648c2d123cbd145fcda9eb11d73aeddec81 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Thu, 19 Jan 2017 13:58:35 +0200 Subject: [PATCH 08/27] MAGETWO-54733: Unable to save product with all unchecked values for multiple select attribute #7687 --- .../Magento/Ui/base/js/form/client.test.js | 55 ++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js index 33b8c203a7164..89d8d4abdec4f 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js @@ -12,7 +12,8 @@ define([ 'uiRegistry', 'Magento_Ui/js/form/client', 'jquery', - 'mageUtils' + 'mageUtils', + 'jquery/ui' ], function (_, registry, Constr, $, utils) { 'use strict'; @@ -78,8 +79,8 @@ define([ utils.filterFormData = jasmine.createSpy().and.returnValue(data); utils.serialize = jasmine.createSpy().and.returnValue(data); - $.ajax = jasmine.createSpy(); + $.ajax = jasmine.createSpy(); obj.save(data); expect(utils.filterFormData).toHaveBeenCalledWith(data); expect(utils.serialize).toHaveBeenCalledWith(data); @@ -93,6 +94,56 @@ define([ expect($.ajax).not.toHaveBeenCalled(); }); + it('Check call "beforeSave" method. Check "success" ajax callback with success response.' , function () { + var request; + + $.ajax = jasmine.createSpy().and.callFake(function (req) { + request = req.success; + }); + $.fn.notification = jasmine.createSpy(); + obj.urls.beforeSave = 'requestPath'; + obj.save(); + + expect(request({error: false})).toBe(true); + expect($('body').notification).not.toHaveBeenCalledWith('clear'); + }); + + it('Check call "beforeSave" method. Check "success" ajax callback with error response.' , function () { + var request, + notificationArguments; + + $.ajax = jasmine.createSpy().and.callFake(function (req) { + request = req.success; + }); + $.fn.notification = jasmine.createSpy(); + obj.urls.beforeSave = 'requestPath'; + obj.save(); + + notificationArguments = { + error: true, + message: 1, + insertMethod: jasmine.any(Function) + }; + + expect(request({ + error: true, + messages: [1] + })).toBeUndefined(); + expect($('body').notification.calls.allArgs()).toEqual([['clear'], ['add', notificationArguments]]); + }); + it('Check call "beforeSave" method. Check "complete" ajax callback with error response.' , function () { + var request; + + $.ajax = jasmine.createSpy().and.callFake(function (req) { + request = req.complete; + }); + $.fn.trigger = jasmine.createSpy(); + obj.urls.beforeSave = 'requestPath'; + obj.save(); + + expect(request()).toBeUndefined(); + expect($('body').trigger).toHaveBeenCalledWith('processStop'); + }); }); describe('"initialize" method', function () { From 535db29f8a83cab2b213c59486920c393e53eaa1 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Thu, 19 Jan 2017 14:00:12 +0200 Subject: [PATCH 09/27] MAGETWO-54733: Unable to save product with all unchecked values for multiple select attribute #7687 --- .../tests/app/code/Magento/Ui/base/js/form/client.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js index 89d8d4abdec4f..4b3bd1d51104d 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js @@ -131,7 +131,7 @@ define([ })).toBeUndefined(); expect($('body').notification.calls.allArgs()).toEqual([['clear'], ['add', notificationArguments]]); }); - it('Check call "beforeSave" method. Check "complete" ajax callback with error response.' , function () { + it('Check call "beforeSave" method. Check "complete" ajax callback.' , function () { var request; $.ajax = jasmine.createSpy().and.callFake(function (req) { From fd0986cca21c69f822890c3ca64a0cf6e5acff60 Mon Sep 17 00:00:00 2001 From: Sergii Kovalenko Date: Thu, 19 Jan 2017 14:00:33 +0200 Subject: [PATCH 10/27] MAGETWO-63022: [2.2] SCD does not work when multiple languages are specified. --- .../Magento/Framework/View/Design/Theme/FlyweightFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php index 30ae8581197e6..02b9b46ddbf67 100644 --- a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php +++ b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php @@ -61,7 +61,7 @@ public function create($themeKey, $area = \Magento\Framework\View\DesignInterfac } else { $themeModel = $this->_loadByPath($themeKey, $area); } - if (!$themeModel->getId()) { + if (!$themeModel->getCode()) { throw new \LogicException("Unable to load theme by specified key: '{$themeKey}'"); } $this->_addTheme($themeModel); From 85c612ec4c282c595944a215004d9ccac7908888 Mon Sep 17 00:00:00 2001 From: Sergii Kovalenko Date: Thu, 19 Jan 2017 15:15:19 +0200 Subject: [PATCH 11/27] MAGETWO-63022: [2.2] SCD does not work when multiple languages are specified. --- .../Framework/View/Design/Theme/FlyweightFactory.php | 11 ++++++++++- .../Test/Unit/Design/Theme/FlyweightFactoryTest.php | 9 ++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php index 02b9b46ddbf67..56c03c7e592d3 100644 --- a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php +++ b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php @@ -44,7 +44,16 @@ public function __construct(ThemeProviderInterface $themeProvider) /** * Creates or returns a shared model of theme * - * @param string $themeKey + * Tries to find theme in File System by specific path or load theme from DB + * by specific path (F.e. adminhtml/Magento/backend) or by identifier (theme primary key) + * + * $themeKey - Should looks like Magento/backend or Magento/admin, where Magento - is vendor and admin - is + * theme code + * $area - Can be adminhtml, frontend, etc... + * + * Can be used to deploy static or work with other setup commands, even if Magento is not installed yet. + * + * @param string $themeKey - Should looks like Magento/backend or Magento/admin, where Magento - is * @param string $area * @return \Magento\Framework\View\Design\ThemeInterface|null * @throws \InvalidArgumentException diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Design/Theme/FlyweightFactoryTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Design/Theme/FlyweightFactoryTest.php index 4d940dd345995..dfb43786768ef 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Design/Theme/FlyweightFactoryTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Design/Theme/FlyweightFactoryTest.php @@ -34,10 +34,10 @@ protected function setUp() public function testCreateById($path, $expectedId) { $theme = $this->getMock(\Magento\Theme\Model\Theme::class, [], [], '', false); - $theme->expects($this->exactly(3))->method('getId')->will($this->returnValue($expectedId)); + $theme->expects($this->exactly(2))->method('getId')->will($this->returnValue($expectedId)); $theme->expects($this->once())->method('getFullPath')->will($this->returnValue(null)); - + $theme->expects($this->once())->method('getCode')->willReturn($expectedId); $this->themeProviderMock->expects( $this->once() )->method( @@ -70,10 +70,10 @@ public function testCreateByPath() $path = 'frontend/Magento/luma'; $themeId = 7; $theme = $this->getMock(\Magento\Theme\Model\Theme::class, [], [], '', false); - $theme->expects($this->exactly(3))->method('getId')->will($this->returnValue($themeId)); + $theme->expects($this->exactly(2))->method('getId')->will($this->returnValue($themeId)); $theme->expects($this->once())->method('getFullPath')->will($this->returnValue($path)); - + $theme->expects($this->once())->method('getCode')->willReturn('Magento/luma'); $this->themeProviderMock->expects( $this->once() )->method( @@ -95,7 +95,6 @@ public function testCreateDummy() { $themeId = 0; $theme = $this->getMock(\Magento\Theme\Model\Theme::class, [], [], '', false); - $theme->expects($this->once())->method('getId')->will($this->returnValue($themeId)); $this->themeProviderMock->expects( $this->once() From a2a4bc62f784fc24b68dff09757ceb33ea9aab7d Mon Sep 17 00:00:00 2001 From: Sergii Kovalenko Date: Thu, 19 Jan 2017 15:29:24 +0200 Subject: [PATCH 12/27] MAGETWO-63022: [2.2] SCD does not work when multiple languages are specified. --- .../View/Design/Theme/FlyweightFactory.php | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php index 56c03c7e592d3..c32f35521d281 100644 --- a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php +++ b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php @@ -45,19 +45,14 @@ public function __construct(ThemeProviderInterface $themeProvider) * Creates or returns a shared model of theme * * Tries to find theme in File System by specific path or load theme from DB - * by specific path (F.e. adminhtml/Magento/backend) or by identifier (theme primary key) + * by specific path (e.g. adminhtml/Magento/backend) or by identifier (theme primary key) + * Can be used to deploy static or in other setup commands, even if Magento is not installed yet. * - * $themeKey - Should looks like Magento/backend or Magento/admin, where Magento - is vendor and admin - is - * theme code - * $area - Can be adminhtml, frontend, etc... - * - * Can be used to deploy static or work with other setup commands, even if Magento is not installed yet. - * - * @param string $themeKey - Should looks like Magento/backend or Magento/admin, where Magento - is - * @param string $area - * @return \Magento\Framework\View\Design\ThemeInterface|null - * @throws \InvalidArgumentException - * @throws \LogicException + * @param string $themeKey - Should looks like Magento/backend or should be theme primary key + * @param string $area - Can be adminhtml, frontend, etc... + * @return \Magento\Framework\View\Design\ThemeInterface + * @throws \InvalidArgumentException when incorrect themeKey was specified + * @throws \LogicException when theme with appropriate themeKey was not found */ public function create($themeKey, $area = \Magento\Framework\View\DesignInterface::DEFAULT_AREA) { From 767bfad7e8cb504038979001c7cb8f09244b2e7d Mon Sep 17 00:00:00 2001 From: Sergii Kovalenko Date: Thu, 19 Jan 2017 15:33:36 +0200 Subject: [PATCH 13/27] MAGETWO-63022: [2.2] SCD does not work when multiple languages are specified. --- .../testsuite/Magento/Theme/Model/Theme/Domain/VirtualTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/Theme/Model/Theme/Domain/VirtualTest.php b/dev/tests/integration/testsuite/Magento/Theme/Model/Theme/Domain/VirtualTest.php index f72e10d1bfea2..e4b3be7cb0aaa 100644 --- a/dev/tests/integration/testsuite/Magento/Theme/Model/Theme/Domain/VirtualTest.php +++ b/dev/tests/integration/testsuite/Magento/Theme/Model/Theme/Domain/VirtualTest.php @@ -19,6 +19,7 @@ class VirtualTest extends \PHPUnit_Framework_TestCase 'theme_title' => 'Test physical theme', 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'type' => ThemeInterface::TYPE_PHYSICAL, + 'code' => 'physical' ], 'virtual' => [ 'parent_id' => null, @@ -26,6 +27,7 @@ class VirtualTest extends \PHPUnit_Framework_TestCase 'theme_title' => 'Test virtual theme', 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'type' => ThemeInterface::TYPE_VIRTUAL, + 'code' => 'virtual' ], 'staging' => [ 'parent_id' => null, @@ -33,6 +35,7 @@ class VirtualTest extends \PHPUnit_Framework_TestCase 'theme_title' => 'Test staging theme', 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'type' => ThemeInterface::TYPE_STAGING, + 'code' => 'staging' ], ]; From 98c6f6efbe31d6cf8ef92d1c5c2f80e65f549f96 Mon Sep 17 00:00:00 2001 From: Sergii Kovalenko Date: Thu, 19 Jan 2017 15:35:23 +0200 Subject: [PATCH 14/27] MAGETWO-63022: [2.2] SCD does not work when multiple languages are specified. --- .../Magento/Framework/View/Design/Theme/FlyweightFactory.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php index c32f35521d281..708cd89bcfc80 100644 --- a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php +++ b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php @@ -44,8 +44,8 @@ public function __construct(ThemeProviderInterface $themeProvider) /** * Creates or returns a shared model of theme * - * Tries to find theme in File System by specific path or load theme from DB - * by specific path (e.g. adminhtml/Magento/backend) or by identifier (theme primary key) + * Search for theme in File System by specific path or load theme from DB + * by specific path (e.g. adminhtml/Magento/backend) or by identifier (theme primary key) and return it * Can be used to deploy static or in other setup commands, even if Magento is not installed yet. * * @param string $themeKey - Should looks like Magento/backend or should be theme primary key From 7f7acb4d93028606bf2bb126bcab372044c10598 Mon Sep 17 00:00:00 2001 From: Sergii Kovalenko Date: Thu, 19 Jan 2017 15:58:06 +0200 Subject: [PATCH 15/27] MAGETWO-63022: [2.2] SCD does not work when multiple languages are specified. --- .../Magento/Theme/Model/Theme/Domain/VirtualTest.php | 6 +++--- .../Framework/View/Design/Theme/FlyweightFactory.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Theme/Model/Theme/Domain/VirtualTest.php b/dev/tests/integration/testsuite/Magento/Theme/Model/Theme/Domain/VirtualTest.php index e4b3be7cb0aaa..6553543444955 100644 --- a/dev/tests/integration/testsuite/Magento/Theme/Model/Theme/Domain/VirtualTest.php +++ b/dev/tests/integration/testsuite/Magento/Theme/Model/Theme/Domain/VirtualTest.php @@ -19,7 +19,7 @@ class VirtualTest extends \PHPUnit_Framework_TestCase 'theme_title' => 'Test physical theme', 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'type' => ThemeInterface::TYPE_PHYSICAL, - 'code' => 'physical' + 'code' => 'physical', ], 'virtual' => [ 'parent_id' => null, @@ -27,7 +27,7 @@ class VirtualTest extends \PHPUnit_Framework_TestCase 'theme_title' => 'Test virtual theme', 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'type' => ThemeInterface::TYPE_VIRTUAL, - 'code' => 'virtual' + 'code' => 'virtual', ], 'staging' => [ 'parent_id' => null, @@ -35,7 +35,7 @@ class VirtualTest extends \PHPUnit_Framework_TestCase 'theme_title' => 'Test staging theme', 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'type' => ThemeInterface::TYPE_STAGING, - 'code' => 'staging' + 'code' => 'staging', ], ]; diff --git a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php index 708cd89bcfc80..fbdd9915e32ea 100644 --- a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php +++ b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php @@ -48,8 +48,8 @@ public function __construct(ThemeProviderInterface $themeProvider) * by specific path (e.g. adminhtml/Magento/backend) or by identifier (theme primary key) and return it * Can be used to deploy static or in other setup commands, even if Magento is not installed yet. * - * @param string $themeKey - Should looks like Magento/backend or should be theme primary key - * @param string $area - Can be adminhtml, frontend, etc... + * @param string $themeKey Should looks like Magento/backend or should be theme primary key + * @param string $area Can be adminhtml, frontend, etc... * @return \Magento\Framework\View\Design\ThemeInterface * @throws \InvalidArgumentException when incorrect themeKey was specified * @throws \LogicException when theme with appropriate themeKey was not found From 6b6a9ab2449600cd41b6c50063e5ae0cf4565206 Mon Sep 17 00:00:00 2001 From: Sergii Kovalenko Date: Thu, 19 Jan 2017 16:09:29 +0200 Subject: [PATCH 16/27] MAGETWO-63022: [2.2] SCD does not work when multiple languages are specified. --- .../Magento/Framework/View/Design/Theme/FlyweightFactory.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php index fbdd9915e32ea..4aad99564075a 100644 --- a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php +++ b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php @@ -48,8 +48,8 @@ public function __construct(ThemeProviderInterface $themeProvider) * by specific path (e.g. adminhtml/Magento/backend) or by identifier (theme primary key) and return it * Can be used to deploy static or in other setup commands, even if Magento is not installed yet. * - * @param string $themeKey Should looks like Magento/backend or should be theme primary key - * @param string $area Can be adminhtml, frontend, etc... + * @param string $themeKey Should looks like Magento/backend or should be theme primary key + * @param string $area Can be adminhtml, frontend, etc... * @return \Magento\Framework\View\Design\ThemeInterface * @throws \InvalidArgumentException when incorrect themeKey was specified * @throws \LogicException when theme with appropriate themeKey was not found From 40ed7645b99ac68638c9910987b6da5b3601e61c Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Mon, 23 Jan 2017 14:01:37 +0200 Subject: [PATCH 17/27] MAGETWO-62276: 'State/Province' isn't changed to input after selecting 'United Kingdom' while filling address on checkout --- app/code/Magento/Ui/view/base/web/js/form/element/select.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/select.js b/app/code/Magento/Ui/view/base/web/js/form/element/select.js index 8f77b9819e180..caa1a6c3567b4 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/select.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/select.js @@ -44,9 +44,9 @@ define([ if (_.isUndefined(caption)) { caption = node.label; } + } else { + return node; } - - return node; }); return { From a02b063ac43aceacc5e3aedc369253d217912aaf Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Mon, 23 Jan 2017 20:51:12 +0200 Subject: [PATCH 18/27] MAGETWO-60258: [Magento Cloud] - Product position set in the admin is not honored in the category when seen in the Frontend --- .../Indexer/Category/Product/Action/Full.php | 6 +- .../Magento/Catalog/Setup/UpgradeSchema.php | 74 +++++++++++++++++++ app/code/Magento/Catalog/etc/module.xml | 2 +- 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php b/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php index 5a5dced86f959..3cf7fdf8999ef 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php +++ b/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php @@ -10,9 +10,13 @@ class Full extends \Magento\Catalog\Model\Indexer\Category\Product\AbstractActio /** * Whether to use main or temporary index table * + * The value of useTempTable flag set to TRUE to force using of + * catalog_category_product_index_tmp table to avoid performance lag + * and DB locks while rebuilding catalog_category_product_index table. + * * @var bool */ - protected $useTempTable = false; + protected $useTempTable = true; /** * Refresh entities index diff --git a/app/code/Magento/Catalog/Setup/UpgradeSchema.php b/app/code/Magento/Catalog/Setup/UpgradeSchema.php index 6e7b10a44ba82..d0a1286b5b2db 100755 --- a/app/code/Magento/Catalog/Setup/UpgradeSchema.php +++ b/app/code/Magento/Catalog/Setup/UpgradeSchema.php @@ -65,6 +65,10 @@ public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $con $this->addSourceEntityIdToProductEavIndex($setup); } + if (version_compare($context->getVersion(), '2.1.4', '<')) { + $this->resetCatalogCategoryProductIndexTmpTable($setup); + } + $setup->endSetup(); } @@ -375,4 +379,74 @@ private function addPercentageValueColumn(SchemaSetupInterface $setup) ] ); } + + /** + * Drop and recreate catalog_category_product_index_tmp table + * + * Before this update the catalog_category_product_index_tmp table was created without usage of PK + * and with engine=MEMORY. Such structure of catalog_category_product_index_tmp table causes + * issues with MySQL DB replication. + * + * To avoid replication issues this method drops catalog_category_product_index_tmp table + * and creates new one with PK and engine=InnoDB + * + * @param SchemaSetupInterface $setup + * @return void + */ + private function resetCatalogCategoryProductIndexTmpTable(SchemaSetupInterface $setup) + { + $tableName = $setup->getTable('catalog_category_product_index_tmp'); + + // Drop catalog_category_product_index_tmp table + $setup->getConnection()->dropTable($tableName); + + // Create catalog_category_product_index_tmp table with PK and engine=InnoDB + $table = $setup->getConnection() + ->newTable($tableName) + ->addColumn( + 'category_id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['unsigned' => true, 'nullable' => false, 'primary' => true, 'default' => '0'], + 'Category ID' + ) + ->addColumn( + 'product_id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['unsigned' => true, 'nullable' => false, 'primary' => true, 'default' => '0'], + 'Product ID' + ) + ->addColumn( + 'position', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['nullable' => false, 'default' => '0'], + 'Position' + ) + ->addColumn( + 'is_parent', + \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, + null, + ['unsigned' => true, 'nullable' => false, 'default' => '0'], + 'Is Parent' + ) + ->addColumn( + 'store_id', + \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, + null, + ['unsigned' => true, 'nullable' => false, 'primary' => true, 'default' => '0'], + 'Store ID' + ) + ->addColumn( + 'visibility', + \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, + null, + ['unsigned' => true, 'nullable' => false], + 'Visibility' + ) + ->setComment('Catalog Category Product Indexer temporary table'); + + $setup->getConnection()->createTable($table); + } } diff --git a/app/code/Magento/Catalog/etc/module.xml b/app/code/Magento/Catalog/etc/module.xml index ffbd5bb6b206d..571176694547a 100644 --- a/app/code/Magento/Catalog/etc/module.xml +++ b/app/code/Magento/Catalog/etc/module.xml @@ -6,7 +6,7 @@ */ --> - + From e98deb723bc6b47e11ae5521e4c7496e55d790f2 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Tue, 24 Jan 2017 12:47:28 +0200 Subject: [PATCH 19/27] MAGETWO-62276: 'State/Province' isn't changed to input after selecting 'United Kingdom' while filling address on checkout --- .../Ui/base/js/form/element/select.test.js | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js index 2e82c877c10e3..13b764442108b 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/select.test.js @@ -188,6 +188,39 @@ define([ expect(model.setVisible).toHaveBeenCalled(); expect(model.toggleInput).toHaveBeenCalled(); }); + it('Check call "parseOptions" method without predefined "captionValue" property', function () { + var data = [{ + value: null, + label: 'label' + }, { + value: 'value' + }]; + + model.options = jasmine.createSpy(); + model.caption = jasmine.createSpy().and.returnValue(false); + + model.setOptions(data); + expect(model.options).toHaveBeenCalledWith([{ + value: 'value' + }]); + expect(model.caption.calls.allArgs()).toEqual([[], ['label']]); + + }); + it('Check call "parseOptions" method with predefined "captionValue" property', function () { + var data = [{ + value: 'value', + label: 'label' + }]; + + model.options = jasmine.createSpy(); + model.caption = jasmine.createSpy().and.returnValue(false); + model.captionValue = 'value'; + + model.setOptions(data); + expect(model.options).toHaveBeenCalledWith([]); + expect(model.caption.calls.allArgs()).toEqual([[], ['label']]); + + }); }); describe('getPreview method', function () { it('check for default preview', function () { From 3bd35a438727dc3445f9d17e9fce6d29898d22ce Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Tue, 24 Jan 2017 14:36:03 +0200 Subject: [PATCH 20/27] MAGETWO-60258: [Magento Cloud] - Product position set in the admin is not honored in the category when seen in the Frontend --- .../Model/Indexer/Category/Product/Action/Full.php | 11 ----------- app/code/Magento/Catalog/Setup/UpgradeSchema.php | 4 ++-- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php b/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php index 3cf7fdf8999ef..0f361ec64b1e0 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php +++ b/app/code/Magento/Catalog/Model/Indexer/Category/Product/Action/Full.php @@ -7,17 +7,6 @@ class Full extends \Magento\Catalog\Model\Indexer\Category\Product\AbstractAction { - /** - * Whether to use main or temporary index table - * - * The value of useTempTable flag set to TRUE to force using of - * catalog_category_product_index_tmp table to avoid performance lag - * and DB locks while rebuilding catalog_category_product_index table. - * - * @var bool - */ - protected $useTempTable = true; - /** * Refresh entities index * diff --git a/app/code/Magento/Catalog/Setup/UpgradeSchema.php b/app/code/Magento/Catalog/Setup/UpgradeSchema.php index d0a1286b5b2db..1be49fc30e4ef 100755 --- a/app/code/Magento/Catalog/Setup/UpgradeSchema.php +++ b/app/code/Magento/Catalog/Setup/UpgradeSchema.php @@ -66,7 +66,7 @@ public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $con } if (version_compare($context->getVersion(), '2.1.4', '<')) { - $this->resetCatalogCategoryProductIndexTmpTable($setup); + $this->recreateCatalogCategoryProductIndexTmpTable($setup); } $setup->endSetup(); @@ -393,7 +393,7 @@ private function addPercentageValueColumn(SchemaSetupInterface $setup) * @param SchemaSetupInterface $setup * @return void */ - private function resetCatalogCategoryProductIndexTmpTable(SchemaSetupInterface $setup) + private function recreateCatalogCategoryProductIndexTmpTable(SchemaSetupInterface $setup) { $tableName = $setup->getTable('catalog_category_product_index_tmp'); From 06b7e6ad9c95eb7c9550f66a9a5c3e77cb987080 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Wed, 25 Jan 2017 11:19:49 +0200 Subject: [PATCH 21/27] MAGETWO-63009: Jasmine test randomly fails on bamboo --- .../app/code/Magento/Ui/base/js/grid/paging/paging.test.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js index 2f9c747d181f0..241fddd427032 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js @@ -38,11 +38,9 @@ define([ describe('onPagesChange method', function () { it('pages amount became less than current', function () { - paging.current = 4; - expect(paging.current).toBe(4); - paging.pageSize = 3; + paging.updateCursor = jasmine.createSpy(); paging.onPagesChange(); - expect(paging.current).toBe(3); + expect(paging.updateCursor).toHaveBeenCalled(); }); }); From c5db5dc244d0775e2a9f27adf0773f7c01695ddb Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Wed, 25 Jan 2017 16:04:42 +0200 Subject: [PATCH 22/27] MAGETWO-63009: Jasmine test randomly fails on bamboo --- .../app/code/Magento/Ui/base/js/grid/paging/paging.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js index 241fddd427032..887b16c39e8a8 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js @@ -37,7 +37,7 @@ define([ }); describe('onPagesChange method', function () { - it('pages amount became less than current', function () { + it('Check calls "onPagesChange" method', function () { paging.updateCursor = jasmine.createSpy(); paging.onPagesChange(); expect(paging.updateCursor).toHaveBeenCalled(); From b1460e85b3a4a13ec9d7c518fd70f41a7e219ee8 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Wed, 25 Jan 2017 16:05:00 +0200 Subject: [PATCH 23/27] MAGETWO-63009: Jasmine test randomly fails on bamboo --- .../app/code/Magento/Ui/base/js/grid/paging/paging.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js index 887b16c39e8a8..f2d0119472647 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js @@ -37,7 +37,7 @@ define([ }); describe('onPagesChange method', function () { - it('Check calls "onPagesChange" method', function () { + it('Check call "onPagesChange" method', function () { paging.updateCursor = jasmine.createSpy(); paging.onPagesChange(); expect(paging.updateCursor).toHaveBeenCalled(); From 3dd4a0b58e5012c3a961f200f6fb2df3ef07e587 Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Thu, 26 Jan 2017 16:00:16 +0200 Subject: [PATCH 24/27] MAGETWO-59966: [SWAT][Magento Cloud] - Cache-miss when Fastly is enabled --- .../Theme/Controller/Result/MessagePlugin.php | 41 +++++++++++++- .../Controller/Result/MessagePluginTest.php | 55 ++++++++++++++++++- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Theme/Controller/Result/MessagePlugin.php b/app/code/Magento/Theme/Controller/Result/MessagePlugin.php index 59cd9508fbca3..a393d862ebf68 100644 --- a/app/code/Magento/Theme/Controller/Result/MessagePlugin.php +++ b/app/code/Magento/Theme/Controller/Result/MessagePlugin.php @@ -66,6 +66,11 @@ public function __construct( } /** + * Set 'mage-messages' cookie + * + * Checks the result that controller actions must return. If result is not JSON type, then + * sets 'mage-messages' cookie. + * * @param ResultInterface $subject * @param ResultInterface $result * @return ResultInterface @@ -75,18 +80,48 @@ public function afterRenderResult( ResultInterface $result ) { if (!($subject instanceof Json)) { + $this->setCookie($this->getMessages()); + } + return $result; + } + + /** + * Set 'mage-messages' cookie with 'messages' array + * + * Checks the $messages argument. If $messages is not an empty array, then + * sets 'mage-messages' public cookie: + * + * Cookie Name: 'mage-messages'; + * Cookie Duration: 1 year; + * Cookie Path: /; + * Cookie HTTP Only flag: FALSE. Cookie can be accessed by client-side APIs. + * + * The 'messages' list has format: + * [ + * [ + * 'type' => 'type_value', + * 'text' => 'cookie_value', + * ], + * ] + * + * + * @param array $messages List of Magento messages that must be set as 'mage-messages' cookie. + * @return void + */ + protected function setCookie(array $messages) + { + if (!empty($messages)) { $publicCookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata(); $publicCookieMetadata->setDurationOneYear(); $publicCookieMetadata->setPath('/'); $publicCookieMetadata->setHttpOnly(false); + $this->cookieManager->setPublicCookie( self::MESSAGES_COOKIES_NAME, - $this->jsonHelper->jsonEncode($this->getMessages()), + $this->jsonHelper->jsonEncode($messages), $publicCookieMetadata ); } - - return $result; } /** diff --git a/app/code/Magento/Theme/Test/Unit/Controller/Result/MessagePluginTest.php b/app/code/Magento/Theme/Test/Unit/Controller/Result/MessagePluginTest.php index 91a75ec9519d9..28800ac913453 100644 --- a/app/code/Magento/Theme/Test/Unit/Controller/Result/MessagePluginTest.php +++ b/app/code/Magento/Theme/Test/Unit/Controller/Result/MessagePluginTest.php @@ -79,7 +79,6 @@ public function testAfterRenderResultJson() public function testAfterRenderResult() { - $existingMessages = [ [ 'type' => 'message0type', @@ -125,14 +124,14 @@ public function testAfterRenderResult() ) ->willReturn(\Zend_Json::encode($existingMessages)); - $this->dataMock->expects($this->any()) + $this->dataMock->expects($this->once()) ->method('jsonDecode') ->willReturnCallback( function ($data) { return \Zend_Json::decode($data); } ); - $this->dataMock->expects($this->any()) + $this->dataMock->expects($this->exactly(2)) ->method('jsonEncode') ->willReturnCallback( function ($data) { @@ -168,6 +167,56 @@ function ($data) { $this->assertEquals($resultMock, $this->model->afterRenderResult($resultMock, $resultMock)); } + public function testAfterRenderResultWithNoMessages() + { + /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $resultMock */ + $resultMock = $this->getMockBuilder(Redirect::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->cookieManagerMock->expects($this->once()) + ->method('getCookie') + ->with( + MessagePlugin::MESSAGES_COOKIES_NAME, + \Zend_Json::encode([]) + ) + ->willReturn(\Zend_Json::encode([])); + + $this->dataMock->expects($this->once()) + ->method('jsonDecode') + ->willReturnCallback( + function ($data) { + return \Zend_Json::decode($data); + } + ); + $this->dataMock->expects($this->once()) + ->method('jsonEncode') + ->willReturnCallback( + function ($data) { + return \Zend_Json::encode($data); + } + ); + + /** @var Collection|\PHPUnit_Framework_MockObject_MockObject $collectionMock */ + $collectionMock = $this->getMockBuilder(Collection::class) + ->disableOriginalConstructor() + ->getMock(); + $collectionMock->expects($this->once()) + ->method('getItems') + ->willReturn([]); + + $this->managerMock->expects($this->once()) + ->method('getMessages') + ->with(true, null) + ->willReturn($collectionMock); + + $this->cookieMetadataFactoryMock->expects($this->never()) + ->method('createPublicCookieMetadata') + ->willReturn(null); + + $this->assertEquals($resultMock, $this->model->afterRenderResult($resultMock, $resultMock)); + } + public function testAfterRenderResultWithoutExisting() { $messageType = 'message1type'; From 45baf500a9e748c561f194ee68dbc0977daf1ab0 Mon Sep 17 00:00:00 2001 From: Sergey Semenov Date: Thu, 26 Jan 2017 16:40:13 +0200 Subject: [PATCH 25/27] MAGETWO-59966: [SWAT][Magento Cloud] - Cache-miss when Fastly is enabled --- app/code/Magento/Theme/Controller/Result/MessagePlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Theme/Controller/Result/MessagePlugin.php b/app/code/Magento/Theme/Controller/Result/MessagePlugin.php index a393d862ebf68..76d002d5073b5 100644 --- a/app/code/Magento/Theme/Controller/Result/MessagePlugin.php +++ b/app/code/Magento/Theme/Controller/Result/MessagePlugin.php @@ -108,7 +108,7 @@ public function afterRenderResult( * @param array $messages List of Magento messages that must be set as 'mage-messages' cookie. * @return void */ - protected function setCookie(array $messages) + private function setCookie(array $messages) { if (!empty($messages)) { $publicCookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata(); From ade5b1e9141ee4cbc66720871ec8ff68757dc835 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Fri, 27 Jan 2017 15:27:53 +0200 Subject: [PATCH 26/27] MAGETWO-54733: Unable to save product with all unchecked values for multiple select attribute #7687 - Fix JS unit test. --- .../Magento/Ui/base/js/form/client.test.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js index 4b3bd1d51104d..3493d0bdd8a0f 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/client.test.js @@ -19,10 +19,11 @@ define([ describe('Magento_Ui/js/form/client', function () { var obj = new Constr({ - provider: 'provName', - name: '', - index: '' - }); + provider: 'provName', + name: '', + index: '' + }), + jQueryMethods = {}; window.FORM_KEY = 'magentoFormKey'; @@ -35,6 +36,12 @@ define([ } }); + afterEach(function () { + _.each(jQueryMethods, function (value, key) { + $.fn[key] = value; + }); + }); + describe('"save" method', function () { it('Check for defined ', function () { expect(obj.hasOwnProperty('save')).toBeDefined(); @@ -115,6 +122,7 @@ define([ $.ajax = jasmine.createSpy().and.callFake(function (req) { request = req.success; }); + jQueryMethods.notification = $.fn.notification; $.fn.notification = jasmine.createSpy(); obj.urls.beforeSave = 'requestPath'; obj.save(); @@ -137,6 +145,8 @@ define([ $.ajax = jasmine.createSpy().and.callFake(function (req) { request = req.complete; }); + + jQueryMethods.trigger = $.fn.trigger; $.fn.trigger = jasmine.createSpy(); obj.urls.beforeSave = 'requestPath'; obj.save(); From 8f49deb00eec0c53036983c3a34c18e06be97959 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Mon, 30 Jan 2017 12:50:09 +0200 Subject: [PATCH 27/27] MAGETWO-63022: [2.2] SCD does not work when multiple languages are specified. - fix descriptions --- .../Magento/Framework/View/Design/Theme/FlyweightFactory.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php index 4aad99564075a..f46165b17424d 100644 --- a/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php +++ b/lib/internal/Magento/Framework/View/Design/Theme/FlyweightFactory.php @@ -51,8 +51,8 @@ public function __construct(ThemeProviderInterface $themeProvider) * @param string $themeKey Should looks like Magento/backend or should be theme primary key * @param string $area Can be adminhtml, frontend, etc... * @return \Magento\Framework\View\Design\ThemeInterface - * @throws \InvalidArgumentException when incorrect themeKey was specified - * @throws \LogicException when theme with appropriate themeKey was not found + * @throws \InvalidArgumentException when incorrect $themeKey was specified + * @throws \LogicException when theme with appropriate $themeKey was not found */ public function create($themeKey, $area = \Magento\Framework\View\DesignInterface::DEFAULT_AREA) {