mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-10-31 02:28:35 +08:00 
			
		
		
		
	Merge pull request #19909 from tim-fischer-maschinensucher/13920-validation-marks-valid-field-as-invalid
Fix #13920: Fixed erroneous validation for specific cases
This commit is contained in:
		| @ -4,6 +4,7 @@ Yii Framework 2 Change Log | |||||||
| 2.0.50 under development | 2.0.50 under development | ||||||
| ------------------------ | ------------------------ | ||||||
|  |  | ||||||
|  | - Bug #13920: Fixed erroneous validation for specific cases (tim-fischer-maschinensucher) | ||||||
| - Bug #19927: Fixed `console\controllers\MessageController` when saving translations to database: fixed FK error when adding new string and language at the same time, checking/regenerating all missing messages and dropping messages for unused languages (atrandafir) | - Bug #19927: Fixed `console\controllers\MessageController` when saving translations to database: fixed FK error when adding new string and language at the same time, checking/regenerating all missing messages and dropping messages for unused languages (atrandafir) | ||||||
| - Enh #12743: Added new methods `BaseActiveRecord::loadRelations()` and `BaseActiveRecord::loadRelationsFor()` to eager load related models for existing primary model instances (PowerGamer1) | - Enh #12743: Added new methods `BaseActiveRecord::loadRelations()` and `BaseActiveRecord::loadRelationsFor()` to eager load related models for existing primary model instances (PowerGamer1) | ||||||
|  |  | ||||||
|  | |||||||
| @ -395,9 +395,11 @@ | |||||||
|                         data: $form.serialize() + extData, |                         data: $form.serialize() + extData, | ||||||
|                         dataType: data.settings.ajaxDataType, |                         dataType: data.settings.ajaxDataType, | ||||||
|                         complete: function (jqXHR, textStatus) { |                         complete: function (jqXHR, textStatus) { | ||||||
|  |                             currentAjaxRequest = null; | ||||||
|                             $form.trigger(events.ajaxComplete, [jqXHR, textStatus]); |                             $form.trigger(events.ajaxComplete, [jqXHR, textStatus]); | ||||||
|                         }, |                         }, | ||||||
|                         beforeSend: function (jqXHR, settings) { |                         beforeSend: function (jqXHR, settings) { | ||||||
|  |                             currentAjaxRequest = jqXHR; | ||||||
|                             $form.trigger(events.ajaxBeforeSend, [jqXHR, settings]); |                             $form.trigger(events.ajaxBeforeSend, [jqXHR, settings]); | ||||||
|                         }, |                         }, | ||||||
|                         success: function (msgs) { |                         success: function (msgs) { | ||||||
| @ -563,6 +565,9 @@ | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if (currentAjaxRequest !== null) { | ||||||
|  |             currentAjaxRequest.abort(); | ||||||
|  |         } | ||||||
|         if (data.settings.timer !== undefined) { |         if (data.settings.timer !== undefined) { | ||||||
|             clearTimeout(data.settings.timer); |             clearTimeout(data.settings.timer); | ||||||
|         } |         } | ||||||
| @ -929,4 +934,7 @@ | |||||||
|             $form.find(attribute.input).attr('aria-invalid', hasError ? 'true' : 'false'); |             $form.find(attribute.input).attr('aria-invalid', hasError ? 'true' : 'false'); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     var currentAjaxRequest = null; | ||||||
|  |  | ||||||
| })(window.jQuery); | })(window.jQuery); | ||||||
|  | |||||||
| @ -48,3 +48,15 @@ | |||||||
|         <div class="help-block"></div> |         <div class="help-block"></div> | ||||||
|     </div> |     </div> | ||||||
| </form> | </form> | ||||||
|  | <form id="w3"> | ||||||
|  |     <div class="form-group field-test-text2 required"> | ||||||
|  |         <label class="control-label" for="test-text2">Test text</label> | ||||||
|  |         <input type="text" id="test-text2" class="form-control" name="Test[text2]" aria-required="true"> | ||||||
|  |         <div class="help-block"></div> | ||||||
|  |     </div> | ||||||
|  |     <div class="form-group field-test-text3 required"> | ||||||
|  |         <label class="control-label" for="test-text3">Test text</label> | ||||||
|  |         <input type="text" id="test-text3" class="form-control" name="Test[text3]" aria-required="true"> | ||||||
|  |         <div class="help-block"></div> | ||||||
|  |     </div> | ||||||
|  | </form> | ||||||
|  | |||||||
| @ -27,6 +27,21 @@ describe('yii.activeForm', function () { | |||||||
|         var script = new vm.Script(code); |         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); |         script.runInContext(context); | ||||||
|  |         /** This is a workaround for a jsdom issue, that prevents :hidden and :visible from working as expected. | ||||||
|  |          * @see https://github.com/jsdom/jsdom/issues/1048 */ | ||||||
|  |         context.window.Element.prototype.getClientRects = function () { | ||||||
|  |             var node = this; | ||||||
|  |             while(node) { | ||||||
|  |                 if(node === document) { | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 if (!node.style || node.style.display === 'none' || node.style.visibility === 'hidden') { | ||||||
|  |                     return []; | ||||||
|  |                 } | ||||||
|  |                 node = node.parentNode; | ||||||
|  |             } | ||||||
|  |             return [{width: 100, height: 100}]; | ||||||
|  |         }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     var activeFormHtml = fs.readFileSync('tests/js/data/yii.activeForm.html', 'utf-8'); |     var activeFormHtml = fs.readFileSync('tests/js/data/yii.activeForm.html', 'utf-8'); | ||||||
| @ -117,6 +132,60 @@ describe('yii.activeForm', function () { | |||||||
|                 assert.isFalse($activeForm.data('yiiActiveForm').validated); |                 assert.isFalse($activeForm.data('yiiActiveForm').validated); | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|  |         describe('with ajax validation', function () { | ||||||
|  |             describe('with rapid validation of multiple fields', function () { | ||||||
|  |                 it('should cancel overlapping ajax requests and not display outdated validation results', function () { | ||||||
|  |                     $activeForm = $('#w3'); | ||||||
|  |                     $activeForm.yiiActiveForm([{ | ||||||
|  |                         id: 'test-text2', | ||||||
|  |                         input: '#test-text2', | ||||||
|  |                         container: '.field-test-text2', | ||||||
|  |                         enableAjaxValidation: true | ||||||
|  |                     }, { | ||||||
|  |                         id: 'test-text3', | ||||||
|  |                         input: '#test-text3', | ||||||
|  |                         container: '.field-test-text3', | ||||||
|  |                         enableAjaxValidation: true | ||||||
|  |                     }], { | ||||||
|  |                         validationUrl: '' | ||||||
|  |                     }); | ||||||
|  |  | ||||||
|  |                     let requests = []; | ||||||
|  |                     function fakeAjax(object) { | ||||||
|  |                         const request = { | ||||||
|  |                             jqXHR: { | ||||||
|  |                                 abort: function () { | ||||||
|  |                                     request.aborted = true; | ||||||
|  |                                 } | ||||||
|  |                             }, | ||||||
|  |                             aborted: false, | ||||||
|  |                             respond: function (response) { | ||||||
|  |                                 if (this.aborted) { | ||||||
|  |                                     return; | ||||||
|  |                                 } | ||||||
|  |                                 object.success(response); | ||||||
|  |                                 object.complete(this.jqXHR, ''); | ||||||
|  |                             } | ||||||
|  |                         }; | ||||||
|  |                         requests.push(request); | ||||||
|  |                         object.beforeSend(request.jqXHR, ''); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     const ajaxStub = sinon.stub($, 'ajax', fakeAjax); | ||||||
|  |                     $activeForm.yiiActiveForm('validateAttribute', 'test-text2'); | ||||||
|  |                     assert.isTrue(requests.length === 1); | ||||||
|  |                     $activeForm.yiiActiveForm('validateAttribute', 'test-text3'); | ||||||
|  |                     // When validateAttribute was called on text2, its value was valid. | ||||||
|  |                     // The value of text3 wasn't. | ||||||
|  |                     requests[0].respond({'test-text3': ['Field cannot be empty']}); | ||||||
|  |                     // When validateAttribute was called on text3, its value was valid. | ||||||
|  |                     requests[1].respond([]); | ||||||
|  |                     assert.isTrue($activeForm.find('.field-test-text3').hasClass('has-success')); | ||||||
|  |                     ajaxStub.restore(); | ||||||
|  |                 }); | ||||||
|  |             }); | ||||||
|  |         }) | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     describe('resetForm method', function () { |     describe('resetForm method', function () { | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Bizley
					Bizley