aboutsummaryrefslogtreecommitdiffstats
path: root/test/widget/formSpec.js
diff options
context:
space:
mode:
authorVojta Jina2012-02-15 17:16:02 -0800
committerVojta Jina2012-02-28 17:46:58 -0800
commit21c725f1a12d1de758cab6e4c4fafc5c420eb565 (patch)
tree4d1b362387de2c41748a63b5baee0f18c3c8e5ec /test/widget/formSpec.js
parente23fa768aaf6d1d966c335979fe8316330c2fe28 (diff)
downloadangular.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.js207
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();
+ });
+ });
});