Index: third_party/pkg/angular/test/directive/ng_form_spec.dart |
diff --git a/third_party/pkg/angular/test/directive/ng_form_spec.dart b/third_party/pkg/angular/test/directive/ng_form_spec.dart |
index 8ebff1b6456049592192816f7bbe2c84ec9275c4..64cc1b82e601396316b0ee13ac22b674407743aa 100644 |
--- a/third_party/pkg/angular/test/directive/ng_form_spec.dart |
+++ b/third_party/pkg/angular/test/directive/ng_form_spec.dart |
@@ -2,428 +2,736 @@ library form_spec; |
import '../_specs.dart'; |
-main() => |
-describe('form', () { |
- TestBed _; |
+void main() { |
+ describe('form', () { |
+ TestBed _; |
- it('should set the name of the form and attach it to the scope', inject((Scope scope, TestBed _) { |
- var element = $('<form name="myForm"></form>'); |
+ it('should set the name of the form and attach it to the scope', (Scope scope, TestBed _) { |
+ expect(scope.context['myForm']).toBeNull(); |
- expect(scope.context['myForm']).toBeNull(); |
+ _.compile('<form name="myForm"></form>'); |
+ scope.apply(); |
- _.compile(element); |
- scope.apply(); |
+ expect(scope.context['myForm']).toBeDefined(); |
- expect(scope.context['myForm']).toBeDefined(); |
+ var form = scope.context['myForm']; |
+ expect(form.name).toEqual('myForm'); |
+ }); |
- var form = scope.context['myForm']; |
- expect(form.name).toEqual('myForm'); |
- })); |
+ it('should return the first control with the given name when accessed using map notation', |
+ (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' |
+ ' <input type="text" name="model" ng-model="modelOne" probe="a" />' |
+ ' <input type="text" name="model" ng-model="modelTwo" probe="b" />' |
+ '</form>'); |
+ scope.apply(); |
- describe('pristine / dirty', () { |
- it('should be set to pristine by default', inject((Scope scope, TestBed _) { |
- var element = $('<form name="myForm"></form>'); |
+ NgForm form = _.rootScope.context['myForm']; |
+ NgModel one = _.rootScope.context['a'].directive(NgModel); |
+ NgModel two = _.rootScope.context['b'].directive(NgModel); |
- _.compile(element); |
+ expect(one).not.toBe(two); |
+ expect(form['model']).toBe(one); |
+ expect(scope.eval("myForm['model']")).toBe(one); |
+ }); |
+ |
+ it('should return the all the controls with the given name', (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' |
+ ' <input type="text" name="model" ng-model="modelOne" probe="a" />' |
+ ' <input type="text" name="model" ng-model="modelTwo" probe="b" />' |
+ '</form>'); |
scope.apply(); |
- var form = scope.context['myForm']; |
- expect(form.pristine).toEqual(true); |
- expect(form.dirty).toEqual(false); |
- })); |
+ NgForm form = _.rootScope.context['myForm']; |
+ NgModel one = _.rootScope.context['a'].directive(NgModel); |
+ NgModel two = _.rootScope.context['b'].directive(NgModel); |
- it('should add and remove the correct CSS classes when set to dirty and to pristine', inject((Scope scope, TestBed _) { |
- var element = $('<form name="myForm"></form>'); |
+ expect(one).not.toBe(two); |
- _.compile(element); |
- scope.apply(); |
+ var controls = form.controls['model']; |
+ expect(controls[0]).toBe(one); |
+ expect(controls[1]).toBe(two); |
- var form = scope.context['myForm']; |
+ expect(scope.eval("myForm.controls['model'][0]")).toBe(one); |
+ expect(scope.eval("myForm.controls['model'][1]")).toBe(two); |
+ }); |
- form.dirty = true; |
- expect(form.pristine).toEqual(false); |
- expect(form.dirty).toEqual(true); |
- expect(element.hasClass('ng-pristine')).toBe(false); |
- expect(element.hasClass('ng-dirty')).toBe(true); |
- |
- form.pristine = true; |
- expect(form.pristine).toEqual(true); |
- expect(form.dirty).toEqual(false); |
- expect(element.hasClass('ng-pristine')).toBe(true); |
- expect(element.hasClass('ng-dirty')).toBe(false); |
- })); |
- }); |
- describe('valid / invalid', () { |
- it('should add and remove the correct flags when set to valid and to invalid', inject((Scope scope, TestBed _) { |
- var element = $('<form name="myForm"></form>'); |
+ describe('pristine / dirty', () { |
+ it('should be set to pristine by default', (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm"></form>'); |
+ scope.apply(); |
- _.compile(element); |
- scope.apply(); |
+ var form = scope.context['myForm']; |
+ expect(form).toBePristine(); |
+ }); |
- var form = scope.context['myForm']; |
+ it('should add and remove the correct CSS classes when set to dirty and to pristine', (Scope scope, TestBed _) { |
+ var element = e('<form name="myForm"><input ng-model="m" probe="m" /></form>'); |
- form.invalid = true; |
- expect(form.valid).toEqual(false); |
- expect(form.invalid).toEqual(true); |
- expect(element.hasClass('ng-valid')).toBe(false); |
- expect(element.hasClass('ng-invalid')).toBe(true); |
- |
- form.valid = true; |
- expect(form.valid).toEqual(true); |
- expect(form.invalid).toEqual(false); |
- expect(element.hasClass('ng-invalid')).toBe(false); |
- expect(element.hasClass('ng-valid')).toBe(true); |
- })); |
- |
- it('should set the validity with respect to all existing validations when setValidity() is used', inject((Scope scope, TestBed _) { |
- var element = $('<form name="myForm">' |
- ' <input type="text" ng-model="one" name="one" />' + |
- ' <input type="text" ng-model="two" name="two" />' + |
- ' <input type="text" ng-model="three" name="three" />' + |
- '</form>'); |
- |
- _.compile(element); |
- scope.apply(); |
+ _.compile(element); |
+ scope.apply(); |
- var form = scope.context['myForm']; |
- NgModel one = form['one']; |
- NgModel two = form['two']; |
- NgModel three = form['three']; |
+ Probe probe = _.rootScope.context['m']; |
+ var input = probe.directive(NgModel); |
+ var form = scope.context['myForm']; |
- form.updateControlValidity(one, "some error", false); |
- expect(form.valid).toBe(false); |
- expect(form.invalid).toBe(true); |
+ input.addInfo('ng-dirty'); |
+ input.validate(); |
+ scope.apply(); |
- form.updateControlValidity(two, "some error", false); |
- expect(form.valid).toBe(false); |
- expect(form.invalid).toBe(true); |
+ expect(form).not.toBePristine(); |
+ expect(element).not.toHaveClass('ng-pristine'); |
+ expect(element).toHaveClass('ng-dirty'); |
- form.updateControlValidity(one, "some error", true); |
- expect(form.valid).toBe(false); |
- expect(form.invalid).toBe(true); |
+ input.removeInfo('ng-dirty'); |
+ input.validate(); |
+ scope.apply(); |
- form.updateControlValidity(two, "some error", true); |
- expect(form.valid).toBe(true); |
- expect(form.invalid).toBe(false); |
- })); |
+ expect(form).toBePristine(); |
+ expect(element).toHaveClass('ng-pristine'); |
+ expect(element).not.toHaveClass('ng-dirty'); |
+ }); |
- it('should not handle the control errorType pair more than once', inject((Scope scope, TestBed _) { |
- var element = $('<form name="myForm">' |
- ' <input type="text" ng-model="one" name="one" />' + |
- '</form>'); |
+ it('should revert back to pristine on the form if the value is reset on the model', |
+ (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' + |
+ ' <input type="text" ng-model="myModel1" probe="m" />' + |
+ ' <input type="text" ng-model="myModel2" probe="n" />' + |
+ '</form>'); |
+ scope.apply(); |
- _.compile(element); |
- scope.apply(); |
+ var form = scope.context['myForm']; |
+ var model1 = scope.context['m'].directive(NgModel); |
+ var model2 = scope.context['n'].directive(NgModel); |
- var form = scope.context['myForm']; |
- NgModel one = form['one']; |
+ expect(model1).toBePristine(); |
+ expect(model2).toBePristine(); |
- form.updateControlValidity(one, "validation error", false); |
- expect(form.valid).toBe(false); |
- expect(form.invalid).toBe(true); |
+ var m1value = model1.viewValue; |
+ var m2value = model2.viewValue; |
- form.updateControlValidity(one, "validation error", false); |
- expect(form.valid).toBe(false); |
- expect(form.invalid).toBe(true); |
+ model1.viewValue = 'some value'; |
+ expect(model1).not.toBePristine(); |
- form.updateControlValidity(one, "validation error", true); |
- expect(form.valid).toBe(true); |
- expect(form.invalid).toBe(false); |
- })); |
+ model2.viewValue = 'some value 123'; |
- it('should update the validity of the parent form when the inner model changes', inject((Scope scope, TestBed _) { |
- var element = $('<form name="myForm">' |
- ' <input type="text" ng-model="one" name="one" />' + |
- ' <input type="text" ng-model="two" name="two" />' + |
- '</form>'); |
+ model1.viewValue = m1value; |
+ expect(model1).toBePristine(); |
+ expect(form).not.toBePristine(); |
- _.compile(element); |
- scope.apply(); |
+ model2.viewValue = m2value; |
+ expect(model2).toBePristine(); |
+ expect(form).toBePristine(); |
+ }); |
+ }); |
- var form = scope.context['myForm']; |
- NgModel one = form['one']; |
- NgModel two = form['two']; |
- |
- one.setValidity("required", false); |
- expect(form.valid).toBe(false); |
- expect(form.invalid).toBe(true); |
- |
- two.setValidity("required", false); |
- expect(form.valid).toBe(false); |
- expect(form.invalid).toBe(true); |
- |
- one.setValidity("required", true); |
- expect(form.valid).toBe(false); |
- expect(form.invalid).toBe(true); |
- |
- two.setValidity("required", true); |
- expect(form.valid).toBe(true); |
- expect(form.invalid).toBe(false); |
- })); |
- |
- it('should set the validity for the parent form when fieldsets are used', inject((Scope scope, TestBed _) { |
- var element = $('<form name="myForm">' |
- ' <fieldset probe="f">' + |
- ' <input type="text" ng-model="one" name="one" probe="m" />' + |
- ' </fieldset>' + |
- '</form>'); |
- |
- _.compile(element); |
- scope.apply(); |
+ describe('valid / invalid', () { |
+ it('should be valid when empty', (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm"></form>'); |
+ scope.apply(); |
- var form = scope.context['myForm']; |
- var fieldset = _.rootScope.context['f'].directive(NgForm); |
- var model = _.rootScope.context['m'].directive(NgModel); |
+ var form = scope.context['myForm']; |
+ expect(form).toBeValid(); |
+ }); |
- model.setValidity("error", false); |
+ it('should be valid by default', (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm"><input type="text" /></form>'); |
+ scope.apply(); |
- expect(model.valid).toBe(false); |
- expect(fieldset.valid).toBe(false); |
- expect(form.valid).toBe(false); |
+ var form = scope.context['myForm']; |
+ expect(form).toBeValid(); |
+ }); |
- model.setValidity("error", true); |
+ it('should add and remove the correct flags when set to valid and to invalid', |
+ (Scope scope, TestBed _) { |
- expect(model.valid).toBe(true); |
- expect(fieldset.valid).toBe(true); |
- expect(form.valid).toBe(true); |
+ var element = e('<form name="myForm"><input ng-model="m" probe="m" /></form>'); |
+ _.compile(element); |
+ scope.apply(); |
- form.updateControlValidity(fieldset, "error", false); |
- expect(model.valid).toBe(true); |
- expect(fieldset.valid).toBe(true); |
- expect(form.valid).toBe(false); |
+ Probe probe = _.rootScope.context['m']; |
+ var model = probe.directive(NgModel); |
+ var form = scope.context['myForm']; |
- fieldset.updateControlValidity(model, "error", false); |
- expect(model.valid).toBe(true); |
- expect(fieldset.valid).toBe(false); |
- expect(form.valid).toBe(false); |
- })); |
- }); |
+ model.addError('some-error'); |
+ model.validate(); |
+ scope.apply(); |
- describe('controls', () { |
- it('should add each contained ng-model as a control upon compile', inject((Scope scope, TestBed _) { |
- var element = $('<form name="myForm">' |
- ' <input type="text" ng-model="mega_model" name="mega_name" />' + |
- ' <select ng-model="fire_model" name="fire_name">' + |
- ' <option>value</option>' |
- ' </select>' + |
- '</form>'); |
+ expect(form).not.toBeValid(); |
- _.compile(element); |
+ expect(element).toHaveClass('ng-invalid'); |
+ expect(element).not.toHaveClass('ng-valid'); |
- scope.context['mega_model'] = 'mega'; |
- scope.context['fire_model'] = 'fire'; |
- scope.apply(); |
+ model.removeError('some-error'); |
+ model.validate(); |
+ scope.apply(); |
- var form = scope.context['myForm']; |
- expect(form['mega_name'].modelValue).toBe('mega'); |
- expect(form['fire_name'].modelValue).toBe('fire'); |
- })); |
+ expect(form).toBeValid(); |
+ expect(element).not.toHaveClass('ng-invalid'); |
+ //expect(element).toHaveClass('ng-valid'); |
+ }); |
- it('should properly remove controls directly from the ngForm instance', inject((Scope scope, TestBed _) { |
- var element = $('<form name="myForm">' |
- ' <input type="text" ng-model="mega_model" name="mega_control" />' + |
- '</form>'); |
+ it('should set the validity with respect to all existing validations when error states are set is used', (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' |
+ ' <input type="text" ng-model="one" name="one" />' |
+ ' <input type="text" ng-model="two" name="two" />' |
+ ' <input type="text" ng-model="three" name="three" />' |
+ '</form>'); |
+ scope.apply(); |
+ |
+ var form = scope.context['myForm']; |
+ NgModel one = form['one']; |
+ NgModel two = form['two']; |
+ NgModel three = form['three']; |
+ |
+ one.addError("some error"); |
+ one.validate(); |
+ expect(form).not.toBeValid(); |
+ |
+ two.addError("some error"); |
+ two.validate(); |
+ expect(form).not.toBeValid(); |
+ |
+ one.removeError("some error"); |
+ one.validate(); |
+ expect(form).not.toBeValid(); |
+ |
+ two.removeError("some error"); |
+ two.validate(); |
+ expect(form).toBeValid(); |
+ }); |
- _.compile(element); |
- scope.apply(); |
+ it('should collect the invalid models upon failed validation', (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' |
+ ' <input type="text" ng-model="one" name="one" />' + |
+ ' <input type="text" ng-model="two" name="two" />' + |
+ ' <input type="text" ng-model="three" name="three" />' + |
+ '</form>'); |
+ scope.apply(); |
+ |
+ var form = scope.context['myForm']; |
+ NgModel one = form['one']; |
+ NgModel two = form['two']; |
+ NgModel three = form['three']; |
+ |
+ one.addError("email"); |
+ two.removeError("number"); |
+ three.addError("format"); |
+ |
+ expect(form.errorStates.keys.length).toBe(2); |
+ expect(form.errorStates['email'].elementAt(0)).toBe(one); |
+ expect(form.errorStates['format'].elementAt(0)).toBe(three); |
+ }); |
- var form = scope.context['myForm']; |
- var control = form['mega_control']; |
- form.removeControl(control); |
- expect(form['mega_control']).toBeNull(); |
- })); |
- |
- it('should remove all controls when the scope is destroyed', inject((Scope scope, TestBed _) { |
- Scope childScope = scope.createChild({}); |
- var element = $('<form name="myForm">' + |
- ' <input type="text" ng-model="one" name="one" />' + |
- ' <input type="text" ng-model="two" name="two" />' + |
- ' <input type="text" ng-model="three" name="three" />' + |
- '</form>'); |
- |
- _.compile(element, scope: childScope); |
- childScope.apply(); |
- |
- var form = childScope.context['myForm']; |
- expect(form['one']).toBeDefined(); |
- expect(form['two']).toBeDefined(); |
- expect(form['three']).toBeDefined(); |
- |
- childScope.destroy(); |
- |
- expect(form['one']).toBeNull(); |
- expect(form['two']).toBeNull(); |
- expect(form['three']).toBeNull(); |
- })); |
- }); |
- describe('onSubmit', () { |
- it('should suppress the submission event if no action is provided within the form', inject((Scope scope, TestBed _) { |
- var element = $('<form name="myForm"></form>'); |
+ it('should not handle the control errorType pair more than once', (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' |
+ ' <input type="text" ng-model="one" name="one" />' |
+ '</form>'); |
+ scope.apply(); |
- _.compile(element); |
- scope.apply(); |
+ var form = scope.context['myForm']; |
+ NgModel one = form['one']; |
- Event submissionEvent = new Event.eventType('CustomEvent', 'submit'); |
+ one.addError('validation error'); |
+ one.validate(); |
+ expect(form).not.toBeValid(); |
- expect(submissionEvent.defaultPrevented).toBe(false); |
- element[0].dispatchEvent(submissionEvent); |
- expect(submissionEvent.defaultPrevented).toBe(true); |
+ one.addError('validation error'); |
+ one.validate(); |
- Event fakeEvent = new Event.eventType('CustomEvent', 'running'); |
+ expect(form).not.toBeValid(); |
- expect(fakeEvent.defaultPrevented).toBe(false); |
- element[0].dispatchEvent(submissionEvent); |
- expect(fakeEvent.defaultPrevented).toBe(false); |
- })); |
+ one.removeError('validation error'); |
+ one.validate(); |
+ expect(form).toBeValid(); |
+ }); |
- it('should not prevent the submission event if an action is defined', inject((Scope scope, TestBed _) { |
- var element = $('<form name="myForm" action="..."></form>'); |
+ it('should update the validity of the parent form when the inner model changes', (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' |
+ ' <input type="text" ng-model="one" name="one" />' |
+ ' <input type="text" ng-model="two" name="two" />' |
+ '</form>'); |
+ scope.apply(); |
- _.compile(element); |
- scope.apply(); |
+ var form = scope.context['myForm']; |
+ NgModel one = form['one']; |
+ NgModel two = form['two']; |
- Event submissionEvent = new Event.eventType('CustomEvent', 'submit'); |
+ one.addError("required"); |
+ expect(form).not.toBeValid(); |
- expect(submissionEvent.defaultPrevented).toBe(false); |
- element[0].dispatchEvent(submissionEvent); |
- expect(submissionEvent.defaultPrevented).toBe(false); |
- })); |
+ two.addError("required"); |
+ expect(form).not.toBeValid(); |
- it('should execute the ng-submit expression if provided upon form submission', inject((Scope scope, TestBed _) { |
- var element = $('<form name="myForm" ng-submit="submitted = true"></form>'); |
+ one.removeError("required"); |
+ expect(form).not.toBeValid(); |
- _.compile(element); |
- scope.apply(); |
+ two.removeError("required"); |
+ expect(form).toBeValid(); |
+ }); |
- _.rootScope.context['submitted'] = false; |
+ it('should register the name of inner forms that contain the ng-form attribute', |
+ (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' |
+ ' <div ng-form="myInnerForm" probe="f">' |
+ ' <input type="text" ng-model="one" name="one" probe="m" />' |
+ ' </div>' |
+ '</form>'); |
+ scope.apply(() { |
+ scope.context['one'] = 'it works!'; |
+ }); |
+ |
+ var form = scope.context['myForm']; |
+ var inner = _.rootScope.context['f'].directive(NgForm); |
+ |
+ expect(inner.name).toEqual('myInnerForm'); |
+ expect(scope.eval('myForm["myInnerForm"]["one"].viewValue')) |
+ .toEqual('it works!'); |
+ }); |
- Event submissionEvent = new Event.eventType('CustomEvent', 'submit'); |
- element[0].dispatchEvent(submissionEvent); |
+ it('should set the validity for the parent form when fieldsets are used', (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' |
+ ' <fieldset probe="f">' |
+ ' <input type="text" ng-model="one" name="one" probe="m" />' |
+ ' </fieldset>' |
+ '</form>'); |
+ scope.apply(); |
- expect(_.rootScope.context['submitted']).toBe(true); |
- })); |
+ var form = scope.context['myForm']; |
+ var fieldset = _.rootScope.context['f'].directive(NgForm); |
+ var model = _.rootScope.context['m'].directive(NgModel); |
- it('should apply the valid and invalid prefixed submit CSS classes to the element', inject((TestBed _) { |
- _.compile('<form name="superForm">' + |
- ' <input type="text" ng-model="myModel" probe="i" required />' + |
- '</form>'); |
+ model.addError("error"); |
- NgForm form = _.rootScope.context['superForm']; |
- Probe probe = _.rootScope.context['i']; |
- var model = probe.directive(NgModel); |
+ expect(model).not.toBeValid(); |
+ expect(fieldset).not.toBeValid(); |
+ expect(form).not.toBeValid(); |
- expect(form.submitted).toBe(false); |
- expect(form.valid_submit).toBe(false); |
- expect(form.invalid_submit).toBe(false); |
- expect(form.element.classes.contains('ng-submit-invalid')).toBe(false); |
- expect(form.element.classes.contains('ng-submit-valid')).toBe(false); |
+ model.removeError("error"); |
- Event submissionEvent = new Event.eventType('CustomEvent', 'submit'); |
+ expect(model).toBeValid(); |
+ expect(fieldset).toBeValid(); |
+ expect(form).toBeValid(); |
+ }); |
- form.element.dispatchEvent(submissionEvent); |
- _.rootScope.apply(); |
+ it('should revalidate itself when an inner model is removed', (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' |
+ ' <input ng-model="m" ng-if="on" required />' |
+ '</form>'); |
+ scope.context['on'] = true; |
+ scope.apply(); |
- expect(form.submitted).toBe(true); |
- expect(form.valid_submit).toBe(false); |
- expect(form.invalid_submit).toBe(true); |
- expect(form.element.classes.contains('ng-submit-invalid')).toBe(true); |
- expect(form.element.classes.contains('ng-submit-valid')).toBe(false); |
+ var form = scope.context['myForm']; |
- _.rootScope.apply('myModel = "man"'); |
- form.element.dispatchEvent(submissionEvent); |
+ expect(form).not.toBeValid(); |
- expect(form.submitted).toBe(true); |
- expect(form.valid_submit).toBe(true); |
- expect(form.invalid_submit).toBe(false); |
- expect(form.element.classes.contains('ng-submit-invalid')).toBe(false); |
- expect(form.element.classes.contains('ng-submit-valid')).toBe(true); |
- })); |
- }); |
+ scope.context['on'] = false; |
+ scope.apply(); |
- describe('reset()', () { |
- it('should reset the model value to its original state', inject((TestBed _) { |
- _.compile('<form name="superForm">' + |
- ' <input type="text" ng-model="myModel" probe="i" />' + |
- '</form>'); |
- _.rootScope.apply('myModel = "animal"'); |
+ expect(form).toBeValid(); |
+ |
+ scope.context['on'] = true; |
+ scope.apply(); |
+ |
+ expect(form).not.toBeValid(); |
+ }); |
+ }); |
- NgForm form = _.rootScope.context['superForm']; |
+ describe('controls', () { |
+ it('should add each contained ng-model as a control upon compile', (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' |
+ ' <input type="text" ng-model="mega_model" name="mega_name" />' |
+ ' <select ng-model="fire_model" name="fire_name">' |
+ ' <option>value</option>' |
+ ' </select>' |
+ '</form>'); |
+ |
+ scope.context['mega_model'] = 'mega'; |
+ scope.context['fire_model'] = 'fire'; |
+ scope.apply(); |
+ |
+ var form = scope.context['myForm']; |
+ expect(form['mega_name'].modelValue).toBe('mega'); |
+ expect(form['fire_name'].modelValue).toBe('fire'); |
+ }); |
- Probe probe = _.rootScope.context['i']; |
- var model = probe.directive(NgModel); |
+ it('should properly remove controls directly from the ngForm instance', (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' |
+ ' <input type="text" ng-model="mega_model" name="mega_control" />' + |
+ '</form>'); |
+ scope.apply(); |
- expect(_.rootScope.context['myModel']).toEqual('animal'); |
- expect(model.modelValue).toEqual('animal'); |
- expect(model.viewValue).toEqual('animal'); |
+ var form = scope.context['myForm']; |
+ var control = form['mega_control']; |
+ form.removeControl(control); |
+ expect(form['mega_control']).toBeNull(); |
+ }); |
- _.rootScope.apply('myModel = "man"'); |
+ it('should remove all controls when the scope is destroyed', (Scope scope, TestBed _) { |
+ Scope childScope = scope.createChild({}); |
+ _.compile('<form name="myForm">' |
+ ' <input type="text" ng-model="one" name="one" />' |
+ ' <input type="text" ng-model="two" name="two" />' |
+ ' <input type="text" ng-model="three" name="three" />' |
+ '</form>', scope: childScope); |
+ childScope.apply(); |
+ |
+ var form = childScope.context['myForm']; |
+ expect(form['one']).toBeDefined(); |
+ expect(form['two']).toBeDefined(); |
+ expect(form['three']).toBeDefined(); |
+ |
+ childScope.destroy(); |
+ |
+ expect(form['one']).toBeNull(); |
+ expect(form['two']).toBeNull(); |
+ expect(form['three']).toBeNull(); |
+ }); |
- expect(_.rootScope.context['myModel']).toEqual('man'); |
- expect(model.modelValue).toEqual('man'); |
- expect(model.viewValue).toEqual('man'); |
+ it('should remove from parent when child is removed', (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' |
+ ' <input type="text" name="mega_name" ng-if="mega_visible" ng-model="value"/>' |
+ '</form>'); |
- form.reset(); |
- _.rootScope.apply(); |
+ scope.context['mega_visible'] = true; |
+ scope.apply(); |
- expect(_.rootScope.context['myModel']).toEqual('animal'); |
- expect(model.modelValue).toEqual('animal'); |
- expect(model.viewValue).toEqual('animal'); |
- })); |
+ var form = scope.context['myForm']; |
+ expect(form['mega_name']).toBeDefined(); |
- it('should set the form control to be untouched when the model is reset or submitted', inject((TestBed _) { |
- var form = _.compile('<form name="duperForm">' + |
- ' <input type="text" ng-model="myModel" probe="i" />' + |
- '</form>'); |
- var model = _.rootScope.context['i'].directive(NgModel); |
- var input = model.element; |
+ scope.context['mega_visible'] = false; |
+ scope.apply(); |
+ expect(form['mega_name']).toBeNull(); |
+ }); |
+ }); |
- NgForm formModel = _.rootScope.context['duperForm']; |
+ describe('onSubmit', () { |
+ it('should suppress the submission event if no action is provided within the form', (Scope scope, TestBed _) { |
+ var element = e('<form name="myForm"></form>'); |
- expect(formModel.touched).toBe(false); |
- expect(formModel.untouched).toBe(true); |
- expect(form.classes.contains('ng-touched')).toBe(false); |
- expect(form.classes.contains('ng-untouched')).toBe(true); |
+ _.compile(element); |
+ scope.apply(); |
- _.triggerEvent(input, 'blur'); |
+ Event submissionEvent = new Event.eventType('CustomEvent', 'submit'); |
- expect(formModel.touched).toBe(true); |
- expect(formModel.untouched).toBe(false); |
- expect(form.classes.contains('ng-touched')).toBe(true); |
- expect(form.classes.contains('ng-untouched')).toBe(false); |
+ expect(submissionEvent.defaultPrevented).toBe(false); |
+ element.dispatchEvent(submissionEvent); |
+ expect(submissionEvent.defaultPrevented).toBe(true); |
- formModel.reset(); |
+ Event fakeEvent = new Event.eventType('CustomEvent', 'running'); |
- expect(formModel.touched).toBe(false); |
- expect(formModel.untouched).toBe(true); |
- expect(form.classes.contains('ng-touched')).toBe(false); |
- expect(form.classes.contains('ng-untouched')).toBe(true); |
+ expect(fakeEvent.defaultPrevented).toBe(false); |
+ element.dispatchEvent(submissionEvent); |
+ expect(fakeEvent.defaultPrevented).toBe(false); |
+ }); |
- _.triggerEvent(input, 'blur'); |
+ it('should not prevent the submission event if an action is defined', (Scope scope, TestBed _) { |
+ var element = e('<form name="myForm" action="..."></form>'); |
- expect(formModel.touched).toBe(true); |
+ _.compile(element); |
+ scope.apply(); |
- _.triggerEvent(form, 'submit'); |
+ Event submissionEvent = new Event.eventType('CustomEvent', 'submit'); |
- expect(formModel.touched).toBe(false); |
- expect(formModel.untouched).toBe(true); |
- expect(form.classes.contains('ng-touched')).toBe(false); |
- expect(form.classes.contains('ng-untouched')).toBe(true); |
- })); |
- }); |
+ expect(submissionEvent.defaultPrevented).toBe(false); |
+ element.dispatchEvent(submissionEvent); |
+ expect(submissionEvent.defaultPrevented).toBe(false); |
+ }); |
+ |
+ it('should execute the ng-submit expression if provided upon form submission', (Scope scope, TestBed _) { |
+ var element = e('<form name="myForm" ng-submit="submitted = true"></form>'); |
+ |
+ _.compile(element); |
+ scope.apply(); |
+ |
+ _.rootScope.context['submitted'] = false; |
+ |
+ Event submissionEvent = new Event.eventType('CustomEvent', 'submit'); |
+ element.dispatchEvent(submissionEvent); |
+ |
+ expect(_.rootScope.context['submitted']).toBe(true); |
+ }); |
+ |
+ it('should apply the valid and invalid prefixed submit CSS classes to the element', |
+ (TestBed _, Scope scope) { |
+ |
+ _.compile('<form name="superForm">' |
+ ' <input type="text" ng-model="myModel" probe="i" required />' |
+ '</form>'); |
+ scope.apply(); |
+ |
+ NgForm form = _.rootScope.context['superForm']; |
+ Probe probe = _.rootScope.context['i']; |
+ var model = probe.directive(NgModel); |
+ var formElement = form.element.node; |
+ |
+ expect(form.submitted).toBe(false); |
+ expect(form.validSubmit).toBe(false); |
+ expect(form.invalidSubmit).toBe(false); |
+ expect(formElement).not.toHaveClass('ng-submit-invalid'); |
+ expect(formElement).not.toHaveClass('ng-submit-valid'); |
+ |
+ Event submissionEvent = new Event.eventType('CustomEvent', 'submit'); |
+ |
+ formElement.dispatchEvent(submissionEvent); |
+ scope.apply(); |
+ |
+ expect(form.submitted).toBe(true); |
+ expect(form.validSubmit).toBe(false); |
+ expect(form.invalidSubmit).toBe(true); |
+ expect(formElement).toHaveClass('ng-submit-invalid'); |
+ expect(formElement).not.toHaveClass('ng-submit-valid'); |
+ |
+ _.rootScope.apply('myModel = "man"'); |
+ formElement.dispatchEvent(submissionEvent); |
+ scope.apply(); |
+ |
+ expect(form.submitted).toBe(true); |
+ expect(form.validSubmit).toBe(true); |
+ expect(form.invalidSubmit).toBe(false); |
+ expect(formElement).not.toHaveClass('ng-submit-invalid'); |
+ expect(formElement).toHaveClass('ng-submit-valid'); |
+ }); |
+ }); |
- describe('regression tests: form', () { |
- it('should be resolvable by injector if configured by user.', () { |
- module((Module module) { |
+ describe('error handling', () { |
+ it('should return true or false depending on if an error exists on a form', |
+ (Scope scope, TestBed _) { |
+ _.compile('<form name="myForm">' |
+ ' <input type="text" ng-model="input" name="input" />' |
+ '</form>'); |
+ scope.apply(); |
+ |
+ var form = scope.context['myForm']; |
+ NgModel input = form['input']; |
+ |
+ expect(form.hasErrorState('big-failure')).toBe(false); |
+ |
+ input.addError('big-failure'); |
+ input.validate(); |
+ |
+ expect(form.hasErrorState('big-failure')).toBe(true); |
+ |
+ input.removeError('big-failure'); |
+ input.validate(); |
+ |
+ expect(form.hasErrorState('big-failure')).toBe(false); |
+ }); |
+ }); |
+ |
+ describe('validators', () { |
+ it('should display the valid and invalid CSS classes on the element for each validation', |
+ (TestBed _, Scope scope) { |
+ |
+ var form = _.compile( |
+ '<form name="myForm">' + |
+ ' <input type="text" ng-model="myModel" required />' + |
+ '</form>' |
+ ); |
+ |
+ scope.apply(); |
+ |
+ expect(form).toHaveClass('ng-required-invalid'); |
+ expect(form).not.toHaveClass('ng-required-valid'); |
+ |
+ scope.apply(() { |
+ scope.context['myModel'] = 'value'; |
+ }); |
+ |
+ expect(form).toHaveClass('ng-required-valid'); |
+ expect(form).not.toHaveClass('ng-required-invalid'); |
+ }); |
+ |
+ it('should re-validate itself when validators are toggled on and off', |
+ (TestBed _, Scope scope) { |
+ |
+ scope.context['required'] = true; |
+ _.compile('<form name="myForm">' |
+ '<input type="text" ng-model="model" ng-required="required" probe="i" />' |
+ '</form>'); |
+ scope.apply(); |
+ |
+ var form = scope.context['myForm']; |
+ var model = scope.context['i'].directive(NgModel); |
+ |
+ expect(form).not.toBeValid(); |
+ expect(model).not.toBeValid(); |
+ |
+ scope.context['required'] = false; |
+ scope.apply(); |
+ |
+ expect(form).toBeValid(); |
+ expect(model).toBeValid(); |
+ }); |
+ |
+ |
+ describe('custom validators', () { |
+ beforeEachModule((Module module) { |
+ module.type(MyCustomFormValidator); |
+ }); |
+ |
+ it('should display the valid and invalid CSS classes on the element for custom validations', (TestBed _, Scope scope) { |
+ var form = _.compile('<form name="myForm">' |
+ ' <input type="text" ng-model="myModel" custom-form-validation />' |
+ '</form>'); |
+ |
+ scope.apply(); |
+ |
+ expect(form).toHaveClass('custom-invalid'); |
+ expect(form).not.toHaveClass('custom-valid'); |
+ |
+ scope.apply(() { |
+ scope.context['myModel'] = 'yes'; |
+ }); |
+ |
+ expect(form).not.toHaveClass('custom-invalid'); |
+ expect(form).toHaveClass('custom-valid'); |
+ }); |
+ }); |
+ }); |
+ |
+ describe('reset()', () { |
+ it('should reset the model value to its original state', (TestBed _) { |
+ _.compile('<form name="superForm">' + |
+ ' <input type="text" ng-model="myModel" probe="i" />' |
+ '</form>'); |
+ _.rootScope.apply('myModel = "animal"'); |
+ |
+ NgForm form = _.rootScope.context['superForm']; |
+ |
+ Probe probe = _.rootScope.context['i']; |
+ var model = probe.directive(NgModel); |
+ |
+ expect(_.rootScope.context['myModel']).toEqual('animal'); |
+ expect(model.modelValue).toEqual('animal'); |
+ expect(model.viewValue).toEqual('animal'); |
+ |
+ _.rootScope.apply('myModel = "man"'); |
+ |
+ expect(_.rootScope.context['myModel']).toEqual('man'); |
+ expect(model.modelValue).toEqual('man'); |
+ expect(model.viewValue).toEqual('man'); |
+ |
+ form.reset(); |
+ _.rootScope.apply(); |
+ |
+ expect(_.rootScope.context['myModel']).toEqual('animal'); |
+ expect(model.modelValue).toEqual('animal'); |
+ expect(model.viewValue).toEqual('animal'); |
+ }); |
+ |
+ // TODO(matias): special-base form_valid |
+ it('should set the form control to be untouched when the model is reset', |
+ (TestBed _, Scope scope) { |
+ |
+ var form = _.compile('<form name="duperForm">' |
+ ' <input type="text" ng-model="myModel" probe="i" />' |
+ '</form>'); |
+ var model = _.rootScope.context['i'].directive(NgModel); |
+ var input = model.element.node; |
+ |
+ NgForm formModel = _.rootScope.context['duperForm']; |
+ scope.apply(); |
+ |
+ expect(formModel.touched).toBe(false); |
+ expect(formModel.untouched).toBe(true); |
+ expect(form).not.toHaveClass('ng-touched'); |
+ expect(form).toHaveClass('ng-untouched'); |
+ |
+ _.triggerEvent(input, 'blur'); |
+ scope.apply(); |
+ |
+ expect(formModel.touched).toBe(true); |
+ expect(formModel.untouched).toBe(false); |
+ expect(form).toHaveClass('ng-touched'); |
+ expect(form).not.toHaveClass('ng-untouched'); |
+ |
+ formModel.reset(); |
+ scope.apply(); |
+ |
+ expect(formModel.touched).toBe(false); |
+ expect(formModel.untouched).toBe(true); |
+ expect(form).not.toHaveClass('ng-touched'); |
+ expect(form).toHaveClass('ng-untouched'); |
+ |
+ _.triggerEvent(input, 'blur'); |
+ |
+ expect(formModel.touched).toBe(true); |
+ }); |
+ |
+ it('should reset each of the controls to be untouched only when the form has a valid submission', (Scope scope, TestBed _) { |
+ var form = _.compile('<form name="duperForm">' |
+ ' <input type="text" ng-model="myModel" probe="i" required />' |
+ '</form>'); |
+ |
+ NgForm formModel = _.rootScope.context['duperForm']; |
+ var model = _.rootScope.context['i'].directive(NgModel); |
+ var input = model.element.node; |
+ _.triggerEvent(input, 'blur'); |
+ |
+ expect(formModel.touched).toBe(true); |
+ expect(model.touched).toBe(true); |
+ expect(formModel.invalid).toBe(true); |
+ |
+ _.triggerEvent(form, 'submit'); |
+ |
+ expect(formModel.touched).toBe(true); |
+ expect(model.touched).toBe(true); |
+ expect(formModel.invalid).toBe(true); |
+ |
+ scope.apply(() { |
+ scope.context['myModel'] = 'value'; |
+ }); |
+ _.triggerEvent(form, 'submit'); |
+ |
+ expect(formModel).toBeValid(); |
+ expect(model.touched).toBe(false); |
+ }); |
+ }); |
+ |
+ it("should use map notation to fetch controls", (TestBed _) { |
+ Scope s = _.rootScope; |
+ s.context['name'] = 'cool'; |
+ |
+ var form = _.compile('<form name="myForm">' |
+ ' <input type="text" ng-model="someModel" probe="i" name="name" />' |
+ '</form>'); |
+ |
+ NgForm formModel = s.context['myForm']; |
+ Probe probe = s.context['i']; |
+ var model = probe.directive(NgModel); |
+ |
+ expect(s.eval('name')).toEqual('cool'); |
+ expect(s.eval('myForm.name')).toEqual('myForm'); |
+ expect(s.eval('myForm["name"]')).toBe(model); |
+ expect(s.eval('myForm["name"].name')).toEqual("name"); |
+ }); |
+ |
+ describe('regression tests: form', () { |
+ beforeEachModule((Module module) { |
module.type(NgForm); |
}); |
- inject((Injector injector, Compiler compiler, DirectiveMap directives) { |
- var element = $('<form></form>'); |
- compiler(element, directives)(injector, element); |
- // The only expectation is that this doesn't throw |
+ it('should be resolvable by injector if configured by user.', |
+ (Injector injector, Compiler compiler, DirectiveMap directives) { |
+ var element = es('<form></form>'); |
+ expect(() => compiler(element, directives)(injector, element)) |
+ .not.toThrow(); |
}); |
}); |
}); |
-}); |
+} |
+ |
+@Decorator( |
+ selector: '[custom-form-validation]') |
+class MyCustomFormValidator extends NgValidator { |
+ final String name = 'custom'; |
+ |
+ MyCustomFormValidator(NgModel ngModel) { |
+ ngModel.addValidator(this); |
+ } |
+ |
+ bool isValid(name) => name != null && name == 'yes'; |
+} |