diff options
| author | Vojta Jina | 2012-02-15 17:16:02 -0800 | 
|---|---|---|
| committer | Vojta Jina | 2012-02-28 17:46:58 -0800 | 
| commit | 21c725f1a12d1de758cab6e4c4fafc5c420eb565 (patch) | |
| tree | 4d1b362387de2c41748a63b5baee0f18c3c8e5ec /test/widget/formSpec.js | |
| parent | e23fa768aaf6d1d966c335979fe8316330c2fe28 (diff) | |
| download | angular.js-21c725f1a12d1de758cab6e4c4fafc5c420eb565.tar.bz2 | |
refactor(forms): Even better forms
- remove $formFactory completely
- remove parallel scope hierarchy (forms, widgets)
- use new compiler features (widgets, forms are controllers)
- any directive can add formatter/parser (validators, convertors)
Breaks no custom input types
Breaks removed integer input type
Breaks remove list input type (ng-list directive instead)
Breaks inputs bind only blur event by default (added ng:bind-change directive)
Diffstat (limited to 'test/widget/formSpec.js')
| -rw-r--r-- | test/widget/formSpec.js | 207 | 
1 files changed, 145 insertions, 62 deletions
| diff --git a/test/widget/formSpec.js b/test/widget/formSpec.js index f2e90d9e..bc5f3ea7 100644 --- a/test/widget/formSpec.js +++ b/test/widget/formSpec.js @@ -1,122 +1,205 @@  'use strict';  describe('form', function() { -  var doc; +  var doc, widget, scope, $compile; + +  beforeEach(module(function($compileProvider) { +    $compileProvider.directive('storeModelCtrl', function() { +      return { +        require: 'ngModel', +        link: function(scope, elm, attr, ctrl) { +          widget = ctrl; +        } +      }; +    }); +  })); + +  beforeEach(inject(function($injector) { +    $compile = $injector.get('$compile'); +    scope = $injector.get('$rootScope'); +  }));    afterEach(function() {      dealoc(doc);    }); -  it('should attach form to DOM', inject(function($rootScope, $compile) { -    doc = angular.element('<form>'); -    $compile(doc)($rootScope); +  it('should instantiate form and attach it to DOM', function() { +    doc = $compile('<form>')(scope);      expect(doc.data('$form')).toBeTruthy(); -  })); +    expect(doc.data('$form') instanceof FormController).toBe(true); +  }); + +  it('should remove the widget when element removed', function() { +    doc = $compile( +        '<form name="form">' + +          '<input type="text" name="alias" ng:model="value" store-model-ctrl/>' + +        '</form>')(scope); -  it('should prevent form submission', inject(function($rootScope, $compile) { +    var form = scope.form; +    widget.emitValidity('REQUIRED', false); +    expect(form.alias).toBe(widget); +    expect(form.error.REQUIRED).toEqual([widget]); + +    doc.find('input').remove(); +    expect(form.error.REQUIRED).toBeUndefined(); +    expect(form.alias).toBeUndefined(); +  }); + + +  it('should prevent form submission', function() {      var startingUrl = '' + window.location; -    doc = angular.element('<form name="myForm"><input type=submit val=submit>'); -    $compile(doc)($rootScope); +    doc = jqLite('<form name="myForm"><input type="submit" value="submit" />'); +    $compile(doc)(scope); +      browserTrigger(doc.find('input'));      waitsFor(          function() { return true; },          'let browser breath, so that the form submision can manifest itself', 10); +      runs(function() {        expect('' + window.location).toEqual(startingUrl);      }); -  })); +  }); -  it('should not prevent form submission if action attribute present', -      inject(function($compile, $rootScope) { +  it('should not prevent form submission if action attribute present', function() {      var callback = jasmine.createSpy('submit').andCallFake(function(event) {        expect(event.isDefaultPrevented()).toBe(false);        event.preventDefault();      }); -    doc = angular.element('<form name="x" action="some.py" />'); -    $compile(doc)($rootScope); +    doc = $compile('<form name="x" action="some.py" />')(scope);      doc.bind('submit', callback);      browserTrigger(doc, 'submit');      expect(callback).toHaveBeenCalledOnce(); -  })); +  }); -  it('should publish form to scope', inject(function($rootScope, $compile) { -    doc = angular.element('<form name="myForm"></form>'); -    $compile(doc)($rootScope); -    expect($rootScope.myForm).toBeTruthy(); +  it('should publish form to scope', function() { +    doc = $compile('<form name="myForm"></form>')(scope); +    expect(scope.myForm).toBeTruthy();      expect(doc.data('$form')).toBeTruthy(); -    expect(doc.data('$form')).toEqual($rootScope.myForm); -  })); - +    expect(doc.data('$form')).toEqual(scope.myForm); +  }); -  it('should have ng-valide/ng-invalid style', inject(function($rootScope, $compile) { -    doc = angular.element('<form name="myForm"><input type=text ng:model=text required>'); -    $compile(doc)($rootScope); -    $rootScope.text = 'misko'; -    $rootScope.$digest(); -    expect(doc.hasClass('ng-valid')).toBe(true); -    expect(doc.hasClass('ng-invalid')).toBe(false); +  it('should allow name to be an expression', function() { +    doc = $compile('<form name="obj.myForm"></form>')(scope); -    $rootScope.text = ''; -    $rootScope.$digest(); -    expect(doc.hasClass('ng-valid')).toBe(false); -    expect(doc.hasClass('ng-invalid')).toBe(true); -  })); +    expect(scope.obj).toBeDefined(); +    expect(scope.obj.myForm).toBeTruthy(); +  }); -  it('should chain nested forms', inject(function($rootScope, $compile) { -    doc = angular.element( -        '<ng:form name=parent>' + -          '<ng:form name=child>' + -            '<input type=text ng:model=text name=text>' + +  it('should chain nested forms', function() { +    doc = jqLite( +        '<ng:form name="parent">' + +          '<ng:form name="child">' + +            '<input type="text" ng:model="text" name="text">' +            '</ng:form>' +          '</ng:form>'); -    $compile(doc)($rootScope); -    var parent = $rootScope.parent; -    var child = $rootScope.child; +    $compile(doc)(scope); + +    var parent = scope.parent; +    var child = scope.child;      var input = child.text; -    input.$emit('$invalid', 'MyError'); -    expect(parent.$error.MyError).toEqual([input]); -    expect(child.$error.MyError).toEqual([input]); +    input.emitValidity('MyError', false); +    expect(parent.error.MyError).toEqual([input]); +    expect(child.error.MyError).toEqual([input]); -    input.$emit('$valid', 'MyError'); -    expect(parent.$error.MyError).toBeUndefined(); -    expect(child.$error.MyError).toBeUndefined(); -  })); +    input.emitValidity('MyError', true); +    expect(parent.error.MyError).toBeUndefined(); +    expect(child.error.MyError).toBeUndefined(); +  }); -  it('should chain nested forms in repeater', inject(function($rootScope, $compile) { -    doc = angular.element( +  it('should chain nested forms in repeater', function() { +    doc = jqLite(         '<ng:form name=parent>' +          '<ng:form ng:repeat="f in forms" name=child>' +            '<input type=text ng:model=text name=text>' +           '</ng:form>' +         '</ng:form>'); -    $compile(doc)($rootScope); -    $rootScope.forms = [1]; -    $rootScope.$digest(); +    $compile(doc)(scope); -    var parent = $rootScope.parent; +    scope.$apply(function() { +      scope.forms = [1]; +    }); + +    var parent = scope.parent;      var child = doc.find('input').scope().child;      var input = child.text; +      expect(parent).toBeDefined();      expect(child).toBeDefined();      expect(input).toBeDefined(); -    input.$emit('$invalid', 'myRule'); -    expect(input.$error.myRule).toEqual(true); -    expect(child.$error.myRule).toEqual([input]); -    expect(parent.$error.myRule).toEqual([input]); +    input.emitValidity('myRule', false); +    expect(input.error.myRule).toEqual(true); +    expect(child.error.myRule).toEqual([input]); +    expect(parent.error.myRule).toEqual([input]); -    input.$emit('$valid', 'myRule'); -    expect(parent.$error.myRule).toBeUndefined(); -    expect(child.$error.myRule).toBeUndefined(); -  })); +    input.emitValidity('myRule', true); +    expect(parent.error.myRule).toBeUndefined(); +    expect(child.error.myRule).toBeUndefined(); +  }); + + +  it('should publish widgets', function() { +    doc = jqLite('<form name="form"><input type="text" name="w1" ng:model="some" /></form>'); +    $compile(doc)(scope); + +    var widget = scope.form.w1; +    expect(widget).toBeDefined(); +    expect(widget.pristine).toBe(true); +    expect(widget.dirty).toBe(false); +    expect(widget.valid).toBe(true); +    expect(widget.invalid).toBe(false); +  }); + + +  describe('validation', function() { + +    beforeEach(function() { +      doc = $compile( +          '<form name="form">' + +            '<input type="text" ng:model="name" name="name" store-model-ctrl/>' + +          '</form>')(scope); + +      scope.$digest(); +    }); + + +    it('should have ng-valid/ng-invalid css class', function() { +      expect(doc).toBeValid(); + +      widget.emitValidity('ERROR', false); +      scope.$apply(); +      expect(doc).toBeInvalid(); + +      widget.emitValidity('ANOTHER', false); +      scope.$apply(); + +      widget.emitValidity('ERROR', true); +      scope.$apply(); +      expect(doc).toBeInvalid(); + +      widget.emitValidity('ANOTHER', true); +      scope.$apply(); +      expect(doc).toBeValid(); +    }); + + +    it('should have ng-pristine/ng-dirty css class', function() { +      expect(doc).toBePristine(); + +      widget.touch(); +      scope.$apply(); +      expect(doc).toBeDirty(); +    }); +  });  }); | 
