diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js index 1c3f38a37c7f9..fe8d7782e5eae 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js @@ -60,7 +60,10 @@ define([ template: 'Magento_Checkout/shipping', shippingFormTemplate: 'Magento_Checkout/shipping-address/form', shippingMethodListTemplate: 'Magento_Checkout/shipping-address/shipping-method-list', - shippingMethodItemTemplate: 'Magento_Checkout/shipping-address/shipping-method-item' + shippingMethodItemTemplate: 'Magento_Checkout/shipping-address/shipping-method-item', + imports: { + countryOptions: '${ $.parentName }.shippingAddress.shipping-address-fieldset.country_id:indexedOptions' + } }, visible: ko.observable(!quote.isVirtual()), errorValidationMessage: ko.observable(false), @@ -276,9 +279,7 @@ define([ loginFormSelector = 'form[data-role=email-with-possible-login]', emailValidationResult = customer.isLoggedIn(), field, - country = registry.get(this.parentName + '.shippingAddress.shipping-address-fieldset.country_id'), - countryIndexedOptions = country.indexedOptions, - option = countryIndexedOptions[quote.shippingAddress().countryId], + option = _.isObject(this.countryOptions) && this.countryOptions[quote.shippingAddress().countryId], messageContainer = registry.get('checkout.errors').messageContainer; if (!quote.shippingMethod()) { diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/post-code.js b/app/code/Magento/Ui/view/base/web/js/form/element/post-code.js index 0eaacdc32567b..72c352f353239 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/post-code.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/post-code.js @@ -8,14 +8,14 @@ */ define([ 'underscore', - 'uiRegistry', './abstract' -], function (_, registry, Abstract) { +], function (_, Abstract) { 'use strict'; return Abstract.extend({ defaults: { imports: { + countryOptions: '${ $.parentName }.country_id:indexedOptions', update: '${ $.parentName }.country_id:value' } }, @@ -41,31 +41,32 @@ define([ }, /** - * @param {String} value + * Method called every time country selector's value gets changed. + * Updates all validations and requirements for certain country. + * @param {String} value - Selected country ID. */ update: function (value) { - var country = registry.get(this.parentName + '.' + 'country_id'), - options = country.indexedOptions, - option = null; + var isZipCodeOptional, + option; if (!value) { return; } - option = options[value]; + option = _.isObject(this.countryOptions) && this.countryOptions[value]; if (!option) { return; } - if (option['is_zipcode_optional']) { + isZipCodeOptional = !!option['is_zipcode_optional']; + + if (isZipCodeOptional) { this.error(false); - this.validation = _.omit(this.validation, 'required-entry'); - } else { - this.validation['required-entry'] = true; } - this.required(!option['is_zipcode_optional']); + this.validation['required-entry'] = !isZipCodeOptional; + this.required(!isZipCodeOptional); } }); }); diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/region.js b/app/code/Magento/Ui/view/base/web/js/form/element/region.js index f6eafcf49284d..cd9c2aee85dc6 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/region.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/region.js @@ -18,81 +18,54 @@ define([ defaults: { skipValidation: false, imports: { + countryOptions: '${ $.parentName }.country_id:indexedOptions', update: '${ $.parentName }.country_id:value' } }, /** - * @param {String} value + * Method called every time country selector's value gets changed. + * Updates all validations and requirements for certain country. + * @param {String} value - Selected country ID. */ update: function (value) { - var country = registry.get(this.parentName + '.' + 'country_id'), - options = country.indexedOptions, - isRegionRequired, + var isRegionRequired, option; if (!value) { return; } - option = options[value]; - if (typeof option === 'undefined') { + option = _.isObject(this.countryOptions) && this.countryOptions[value]; + + if (!option) { return; } defaultPostCodeResolver.setUseDefaultPostCode(!option['is_zipcode_optional']); - if (this.skipValidation) { - this.validation['required-entry'] = false; - this.required(false); - } else { - if (option && !option['is_region_required']) { - this.error(false); - this.validation = _.omit(this.validation, 'required-entry'); - registry.get(this.customName, function (input) { - input.validation['required-entry'] = false; - input.required(false); - }); - } else { - this.validation['required-entry'] = true; - } + if (option['is_region_visible'] === false) { + // Hide select and corresponding text input field if region must not be shown for selected country. + this.setVisible(false); - if (option && !this.options().length) { - registry.get(this.customName, function (input) { - isRegionRequired = !!option['is_region_required']; - input.validation['required-entry'] = isRegionRequired; - input.validation['validate-not-number-first'] = true; - input.required(isRegionRequired); - }); + if (this.customEntry) { // eslint-disable-line max-depth + this.toggleInput(false); } - - this.required(!!option['is_region_required']); } - }, - /** - * Filters 'initialOptions' property by 'field' and 'value' passed, - * calls 'setOptions' passing the result to it - * - * @param {*} value - * @param {String} field - */ - filter: function (value, field) { - var superFn = this._super; - - registry.get(this.parentName + '.' + 'country_id', function (country) { - var option = country.indexedOptions[value]; + isRegionRequired = !this.skipValidation && !!option['is_region_required']; - superFn.call(this, value, field); + if (!isRegionRequired) { + this.error(false); + } - if (option && option['is_region_visible'] === false) { - // hide select and corresponding text input field if region must not be shown for selected country - this.setVisible(false); + this.required(isRegionRequired); + this.validation['required-entry'] = isRegionRequired; - if (this.customEntry) {// eslint-disable-line max-depth - this.toggleInput(false); - } - } + registry.get(this.customName, function (input) { + input.required(isRegionRequired); + input.validation['required-entry'] = isRegionRequired; + input.validation['validate-not-number-first'] = !this.options().length; }.bind(this)); } }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/shipping.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/shipping.test.js index 9b9b1ce5b1614..46d9e1974bdb7 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/shipping.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Checkout/frontend/js/view/shipping.test.js @@ -174,16 +174,13 @@ define(['squire', 'ko', 'jquery', 'uiRegistry', 'jquery/validate'], function (Sq describe('"validateShippingInformation" method', function () { it('Check method call on negative cases.', function () { + /* jscs:disable */ var country = { - 'indexedOptions': { - 'AD': - { - label: 'Andorra', - labeltitle: 'Andorra', - value: 'AD' - } - } + on: function () {}, + get: function () {}, + set: function () {} }; + /* jscs:enable */ registry.set('test.shippingAddress.shipping-address-fieldset.country_id', country); registry.set('checkout.errors', {}); @@ -202,9 +199,20 @@ define(['squire', 'ko', 'jquery', 'uiRegistry', 'jquery/validate'], function (Sq expect(obj.validateShippingInformation()).toBeFalsy(); }); it('Check method call on positive case.', function () { + /* jscs:disable */ + var country = { + on: function () {}, + get: function () {}, + set: function () {} + }; + /* jscs:enable */ + $('body').append('
' + '' + '
'); + + registry.set('test.shippingAddress.shipping-address-fieldset.country_id', country); + registry.set('checkout.errors', {}); obj.source = { get: jasmine.createSpy().and.returnValue(true), set: jasmine.createSpy(), diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/post-code.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/post-code.test.js index 96bca1bbd8c6b..d369d66a92225 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/post-code.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/post-code.test.js @@ -47,22 +47,71 @@ define([ }); describe('update method', function () { - it('check for default', function () { - var value = 'Value', - country = { - indexedOptions: { - 'Value': { - 'is_zipcode_optional': true - } - } - }; - - spyOn(mocks['Magento_Ui/js/lib/registry/registry'], 'get').and.returnValue(country); + it('makes field optional when there is no corresponding country', function () { + var value = 'Value'; + + model.countryOptions = {}; + + model.update(value); + + expect(model.required()).toEqual(false); + }); + + it('makes field optional when post code is optional for certain country', function () { + var value = 'Value'; + + model.countryOptions = { + 'Value': { + 'is_zipcode_optional': true + } + }; + model.update(value); - expect(mocks['Magento_Ui/js/lib/registry/registry'].get).toHaveBeenCalled(); - expect(model.error()).toEqual(false); + expect(model.required()).toEqual(false); }); + + it('removes field required validation when post code is optional for certain country', function () { + var value = 'Value'; + + model.countryOptions = { + 'Value': { + 'is_zipcode_optional': true + } + }; + + model.update(value); + + expect(model.validation['required-entry']).toBeFalsy(); + }); + + it('makes field required when post code is required for certain country', function () { + var value = 'Value'; + + model.countryOptions = { + 'Value': { + 'is_zipcode_optional': false + } + }; + + model.update(value); + + expect(model.required()).toEqual(true); + }); + + it('sets field required validation when post code is required for certain country', function () { + var value = 'Value'; + + model.countryOptions = { + 'Value': { + 'is_zipcode_optional': false + } + }; + + model.update(value); + + expect(model.validation['required-entry']).toEqual(true); + }); }); }); }); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/region.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/region.test.js index a36d3b0b7fefa..a957db5d1c119 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/region.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/form/element/region.test.js @@ -48,22 +48,127 @@ define([ }); describe('update method', function () { - it('check for default', function () { - var value = 'Value', - country = { - indexedOptions: { - 'Value': { - 'is_zipcode_optional': true - } - } - }; - - spyOn(mocks['Magento_Ui/js/lib/registry/registry'], 'get').and.returnValue(country); + it('makes field optional when there is no corresponding country', function () { + var value = 'Value'; + + model.countryOptions = {}; + + model.update(value); + + expect(model.required()).toEqual(false); + }); + + it('makes field optional when region is optional for certain country', function () { + var value = 'Value'; + + model.countryOptions = { + 'Value': { + 'is_region_required': false + } + }; + model.update(value); - expect(mocks['Magento_Ui/js/lib/registry/registry'].get).toHaveBeenCalled(); - expect(model.error()).toEqual(false); + expect(model.required()).toEqual(false); }); + + it('removes field required validation when region is optional for certain country', function () { + var value = 'Value'; + + model.countryOptions = { + 'Value': { + 'is_region_required': false + } + }; + + model.update(value); + + expect(model.validation['required-entry']).toBeFalsy(); + }); + + it('makes field required when region is required for certain country', function () { + var value = 'Value'; + + model.countryOptions = { + 'Value': { + 'is_region_required': true + } + }; + + model.update(value); + + expect(model.required()).toEqual(true); + }); + + it('sets field required validation when region is required for certain country', function () { + var value = 'Value'; + + model.countryOptions = { + 'Value': { + 'is_region_required': true + } + }; + + model.update(value); + + expect(model.validation['required-entry']).toEqual(true); + }); + + it('keeps region visible by default', function () { + var value = 'Value'; + + model.countryOptions = { + 'Value': {} + }; + + model.update(value); + + expect(model.visible()).toEqual(true); + }); + + it('hides region field when it should be hidden for certain country', function () { + var value = 'Value'; + + model.countryOptions = { + 'Value': { + 'is_region_visible': false + } + }; + + model.update(value); + + expect(model.visible()).toEqual(false); + }); + + it('makes field optional when validation should be skipped', function () { + var value = 'Value'; + + model.countryOptions = { + 'Value': { + 'is_region_required': true + } + }; + + model.skipValidation = true; + model.update(value); + + expect(model.required()).toEqual(false); + }); + + it('removes field validation when validation should be skipped', function () { + var value = 'Value'; + + model.countryOptions = { + 'Value': { + 'is_region_required': true + } + }; + + model.skipValidation = true; + model.update(value); + + expect(model.validation['required-entry']).toBeFalsy(); + }); }); }); });