From 8f2d9baf98003c912d91c1fad962e0835ff01f3f Mon Sep 17 00:00:00 2001 From: Alexey Rogachev Date: Sat, 29 Jul 2017 17:37:29 +0600 Subject: [PATCH] Fixes #14186, Fixes #14510: yiiActiveForm regressions - #14186: Forced validation in `yiiActiveForm` do not trigger `afterValidate` event - #14510: The state of a form is always "not validated" when using forced validation in `yiiActiveForm` --- framework/CHANGELOG.md | 2 + framework/assets/yii.activeForm.js | 10 ++-- tests/js/data/yii.activeForm.html | 4 +- tests/js/tests/yii.activeForm.test.js | 81 ++++++++++++++++++--------- 4 files changed, 65 insertions(+), 32 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 67cf8144ee1..181b5c8004d 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -112,6 +112,8 @@ Yii Framework 2 Change Log - Bug #14074: Fixed default value of `yii\console\controllers\FixtureController::$globalFixtures` to contain valid class name (lynicidn) - Bug #14094: Fixed bug when single `yii\web\UrlManager::createUrl()` call my result multiple calls of `yii\web\UrlRule::createUrl()` for the same rule (rossoneri) - Bug #14133: Fixed bug when calculating timings with mixed nested profile begin and end in `yii\log\Logger::calculateTimings()` (bizley) +- Bug #14186: Forced validation in `yiiActiveForm` do not trigger `afterValidate` event (arogachev) +- Bug #14510: The state of a form is always "not validated" when using forced validation in `yiiActiveForm` (arogachev) - Enh #4793: `yii\filters\AccessControl` now can be used without `user` component (bizley) - Enh #4999: Added support for wildcards at `yii\filters\AccessRule::$controllers` (klimov-paul) - Enh #5108: `yii\validators\DateValidator` now resets `$timestampAttribute` value on empty validated attribute value (klimov-paul) diff --git a/framework/assets/yii.activeForm.js b/framework/assets/yii.activeForm.js index 0678e72a995..b4417fa0d4a 100644 --- a/framework/assets/yii.activeForm.js +++ b/framework/assets/yii.activeForm.js @@ -306,9 +306,9 @@ needAjaxValidation = false, messages = {}, deferreds = deferredArray(), - submitting = data.submitting && !forceValidate; + submitting = data.submitting; - if (data.submitting) { + if (submitting) { var event = $.Event(events.beforeValidate); $form.trigger(event, [messages, deferreds]); @@ -391,7 +391,7 @@ }); } else if (data.submitting) { // delay callback so that the form can be submitted without problem - setTimeout(function () { + window.setTimeout(function () { updateInputs($form, messages, submitting); }, 200); } else { @@ -435,7 +435,7 @@ // Because we bind directly to a form reset event instead of a reset button (that may not exist), // when this function is executed form input values have not been reset yet. // Therefore we do the actual reset work through setTimeout. - setTimeout(function () { + window.setTimeout(function () { $.each(data.attributes, function () { // Without setTimeout() we would get the input values that are not reset yet. this.value = getValue($form, this); @@ -535,7 +535,7 @@ if (data.settings.timer !== undefined) { clearTimeout(data.settings.timer); } - data.settings.timer = setTimeout(function () { + data.settings.timer = window.setTimeout(function () { if (data.submitting || $form.is(':hidden')) { return; } diff --git a/tests/js/data/yii.activeForm.html b/tests/js/data/yii.activeForm.html index e31bdc9a7a2..912c549a181 100644 --- a/tests/js/data/yii.activeForm.html +++ b/tests/js/data/yii.activeForm.html @@ -1,3 +1,3 @@ -
- + +
diff --git a/tests/js/tests/yii.activeForm.test.js b/tests/js/tests/yii.activeForm.test.js index b7bb61f16c3..39815995b2e 100644 --- a/tests/js/tests/yii.activeForm.test.js +++ b/tests/js/tests/yii.activeForm.test.js @@ -10,7 +10,7 @@ describe('yii.activeForm', function () { var yiiPath = 'framework/assets/yii.js'; var jQueryPath = 'vendor/bower-asset/jquery/dist/jquery.js'; var $; - var $mainForm; + var $activeForm; function registerYii() { var code = fs.readFileSync(yiiPath); @@ -25,11 +25,7 @@ describe('yii.activeForm', function () { var yii = registerYii(); var code = fs.readFileSync(yiiActiveFormPath); var script = new vm.Script(code); - var context = new vm.createContext({ - window: window, - document: window.document, - yii: yii - }); + var context = new vm.createContext({window: window, document: window.document, yii: yii}); script.runInContext(context); } @@ -47,41 +43,76 @@ describe('yii.activeForm', function () { sinon = require('sinon'); }); - beforeEach(function () { - $mainForm = $('#main'); + describe('validate method', function () { + var windowSetTimeoutStub; + var afterValidateSpy; + + beforeEach(function () { + windowSetTimeoutStub = sinon.stub(window, 'setTimeout', function (callback) { + callback(); + }); + afterValidateSpy = sinon.spy(); + }); + + afterEach(function () { + windowSetTimeoutStub.restore(); + afterValidateSpy.reset(); + }); + + describe('with forceValidate parameter set to true', function () { + it('should trigger manual form validation', function () { + var inputId = 'name'; + + $activeForm = $('#w0'); + $activeForm.yiiActiveForm([ + { + id: inputId, + input: '#' + inputId + } + ]).on('afterValidate', afterValidateSpy); + + $activeForm.yiiActiveForm('validate', true); + // https://github.com/yiisoft/yii2/issues/14510 + assert.isTrue($activeForm.data('yiiActiveForm').validated); + // https://github.com/yiisoft/yii2/issues/14186 + assert.isTrue(afterValidateSpy.calledOnce); + }); + }); }); describe('events', function () { describe('afterValidateAttribute', function () { - var afterValidateAttributeEventSpy; - var dataForAssert; + var afterValidateAttributeSpy; + var eventData; before(function () { - afterValidateAttributeEventSpy = sinon.spy(function (event, data) { - dataForAssert = data.value; + afterValidateAttributeSpy = sinon.spy(function (event, data) { + eventData = data; }); }); after(function () { - afterValidateAttributeEventSpy.reset(); + afterValidateAttributeSpy.reset(); }); - it('should update attribute value', function () { - var inputId = 'nameInput', - $input = $('#' + inputId); - $mainForm.yiiActiveForm([ + // https://github.com/yiisoft/yii2/issues/14318 + + it('should allow to get updated attribute value', function () { + var inputId = 'name'; + var $input = $('#' + inputId); + + $activeForm = $('#w0'); + $activeForm.yiiActiveForm([ { - id : inputId, + id: inputId, input: '#' + inputId } - ]).on('afterValidateAttribute', afterValidateAttributeEventSpy); - - // Set new value, update attribute - $input.val('newValue'); - $mainForm.yiiActiveForm('updateAttribute', inputId); + ]).on('afterValidateAttribute', afterValidateAttributeSpy); - assert.equal('newValue', dataForAssert); + $input.val('New value'); + $activeForm.yiiActiveForm('updateAttribute', inputId); + assert.equal('New value', eventData.value); }); }); }); -}); \ No newline at end of file +});