From 2ca1dd3eabffee0aa8336cf601662a8f71abfc60 Mon Sep 17 00:00:00 2001 From: Cameron Edwards Date: Tue, 9 Sep 2014 15:17:21 -0400 Subject: [PATCH 1/8] Separate service test --- karma.conf.js | 3 +- test/schema-form-test.js | 417 -------------------------------------- test/service-test.js | 418 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 420 insertions(+), 418 deletions(-) create mode 100644 test/service-test.js diff --git a/karma.conf.js b/karma.conf.js index ab79e69c8..31f4bb2ba 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -25,7 +25,8 @@ module.exports = function(config) { 'src/directives/*.js', 'src/directives/decorators/bootstrap/*.js', 'src/**/*.html', - 'test/schema-form-test.js' + 'test/schema-form-test.js', + 'test/service-test.js' ], // list of files to exclude diff --git a/test/schema-form-test.js b/test/schema-form-test.js index 70dc6f65b..5ef17dcfa 100644 --- a/test/schema-form-test.js +++ b/test/schema-form-test.js @@ -1617,424 +1617,7 @@ describe('Schema form',function(){ }); - describe('service',function(){ - beforeEach(module('templates')); - beforeEach(module('schemaForm')); - - it('should generate default form def from a schema',function(){ - inject(function(schemaForm){ - - var schema = { - "type": "object", - "properties": { - "name": { - "title": "Name", - "description": "Gimme yea name lad", - "type": "string" - }, - "gender": { - "title": "Choose", - "type": "string", - "enum": [ - "undefined", - "null", - "NaN", - ] - }, - "overEighteen": { - "title": "Are you over 18 years old?", - "type": "boolean", - "default": false - }, - "attributes": { - "type": "object", - "required": ['eyecolor'], - "properties": { - "eyecolor": { "type": "string", "title": "Eye color" }, - "haircolor": { "type": "string", "title": "Hair color" }, - "shoulders": { - "type": "object", - "title": "Shoulders", - "properties": { - "left": { "type": "string" }, - "right": { "type": "string" }, - } - } - } - } - } - }; - - var form = [ - { - "title": "Name", - "description": "Gimme yea name lad", - "schema": { - "title": "Name", - "description": "Gimme yea name lad", - "type": "string" - }, - "ngModelOptions": {}, - "key": [ - "name" - ], - "type": "text" - }, - { - "title": "Choose", - "schema": { - "title": "Choose", - "type": "string", - "enum": [ - "undefined", - "null", - "NaN" - ] - }, - "ngModelOptions": {}, - "key": [ - "gender" - ], - "type": "select", - "titleMap": [ - { - "name": "undefined", - "value": "undefined" - }, - { - "name": "null", - "value": "null" - }, - { - "name": "NaN", - "value": "NaN" - } - ] - }, - { - "title": "Are you over 18 years old?", - "schema": { - "title": "Are you over 18 years old?", - "type": "boolean", - "default": false - }, - "ngModelOptions": {}, - "key": [ - "overEighteen" - ], - "type": "checkbox" - }, - { - "title": "attributes", - "schema": { - "type": "object", - "required": [ - "eyecolor" - ], - "properties": { - "eyecolor": { - "type": "string", - "title": "Eye color" - }, - "haircolor": { - "type": "string", - "title": "Hair color" - }, - "shoulders": { - "type": "object", - "title": "Shoulders", - "properties": { - "left": { - "type": "string" - }, - "right": { - "type": "string" - } - } - } - } - }, - "ngModelOptions": {}, - "type": "fieldset", - "items": [ - { - "title": "Eye color", - "required": true, - "schema": { - "type": "string", - "title": "Eye color" - }, - "ngModelOptions": {}, - "key": [ - "attributes", - "eyecolor" - ], - "type": "text" - }, - { - "title": "Hair color", - "schema": { - "type": "string", - "title": "Hair color" - }, - "ngModelOptions": {}, - "key": [ - "attributes", - "haircolor" - ], - "type": "text" - }, - { - "title": "Shoulders", - "schema": { - "type": "object", - "title": "Shoulders", - "properties": { - "left": { - "type": "string" - }, - "right": { - "type": "string" - } - } - }, - "ngModelOptions": {}, - "type": "fieldset", - "items": [ - { - "title": "left", - "schema": { - "type": "string" - }, - "ngModelOptions": {}, - "key": [ - "attributes", - "shoulders", - "left" - ], - "type": "text" - }, - { - "title": "right", - "schema": { - "type": "string" - }, - "ngModelOptions": {}, - "key": [ - "attributes", - "shoulders", - "right" - ], - "type": "text" - } - ] - } - ] - } - ]; - - - var f = schemaForm.defaults(schema); - f.form.should.be.deep.equal(form); - - }); - }); - - it('should handle global defaults',function(){ - inject(function(schemaForm){ - - var schema = { - "type": "object", - "properties": { - "name": { - "title": "Name", - "description": "Gimme yea name lad", - "type": "string" - } - } - }; - var form = [ - { - "title": "Name", - "description": "Gimme yea name lad", - "schema": { - "title": "Name", - "description": "Gimme yea name lad", - "type": "string" - }, - "ngModelOptions": { "updateOn": "blur"}, - "foo": "bar", - "key": [ - "name" - ], - "type": "text" - } - ]; - - var f = schemaForm.defaults(schema,{},{ formDefaults: { foo: "bar", ngModelOptions: { updateOn: 'blur' }}}); - f.form.should.be.deep.equal(form); - - }); - }); - - - - it('should be extendable with new defaults',function(){ - module(function(schemaFormProvider){ - schemaFormProvider.prependRule('string',function(name,schema,options){ - if (schema.format === 'foobar') { - var f = schemaFormProvider.createStandardForm(name,schema,options); - f.type = 'foobar'; - return f; - } - }); - - schemaFormProvider.appendRule('string',function(name,schema,options){ - var f = schemaFormProvider.createStandardForm(name,schema,options); - f.type = 'notused'; - return f; - }); - }); - - inject(function(schemaForm){ - - var schema = { - "type": "object", - "properties": { - "name": { - "title": "Name", - "format": "foobar", - "description": "Gimme yea name lad", - "type": "string" - }, - "gender": { - "title": "Choose", - "type": "string", - "enum": [ - "undefined", - "null", - "NaN", - ] - } - } - }; - - //no form is implicitly ['*'] - var defaults = schemaForm.defaults(schema).form; - defaults[0].type.should.be.equal('foobar'); - defaults[0].title.should.be.equal('Name'); - defaults[1].type.should.be.equal('select'); - defaults[1].title.should.be.equal('Choose'); - - }); - }); - - it('should be enable post-processing of forms',function(){ - module(function(schemaFormProvider){ - schemaFormProvider.postProcess(function(form){ - form.postProcess = true; - form.length.should.be.eq(1); - form[0].title.should.be.eq('Name'); - return form; - }); - - }); - - inject(function(schemaForm){ - - var schema = { - "type": "object", - "properties": { - "name": { - "title": "Name", - "format": "foobar", - "description": "Gimme yea name lad", - "type": "string" - } - } - }; - - var form = schemaForm.merge(schema,["name"]); - form.postProcess.should.be.true; - - }); - }); - - - it('should ignore parts of schema in ignore list',function(){ - inject(function(schemaForm){ - - var schema = { - "type": "object", - "properties": { - "name": { - "title": "Name", - "description": "Gimme yea name lad", - "type": "string" - }, - "gender": { - "title": "Choose", - "type": "string", - "enum": [ - "undefined", - "null", - "NaN", - ] - } - } - }; - - //no form is implicitly ['*'] - var defaults = schemaForm.defaults(schema).form; - schemaForm.merge(schema,["*"],{gender:true}).should.be.deep.equal([defaults[0]]); - }); - }); - - - it('should merge schema and form def',function(){ - inject(function(schemaForm){ - - var schema = { - "type": "object", - "properties": { - "name": { - "title": "Name", - "description": "Gimme yea name lad", - "type": "string" - }, - "gender": { - "title": "Choose", - "type": "string", - "enum": [ - "undefined", - "null", - "NaN", - ] - } - } - }; - - //no form is implicitly ['*'] - var defaults = schemaForm.defaults(schema).form; - schemaForm.merge(schema).should.be.deep.equal(defaults); - schemaForm.merge(schema,['*']).should.be.deep.equal(defaults); - schemaForm.merge(schema,['*',{type:'fieldset'}]).should.be.deep.equal(defaults.concat([{type:'fieldset'}])); - - //simple form - schemaForm.merge(schema,['gender']).should.be.deep.equal([defaults[1]]); - schemaForm.merge(schema,['gender','name']).should.be.deep.equal([defaults[1],defaults[0]]); - - //change it up - var f = angular.copy(defaults[0]); - f.title = 'Foobar'; - f.type = 'password'; - schemaForm.merge(schema,[{ key: 'name',title: 'Foobar',type: 'password'}]).should.be.deep.equal([f]); - - }); - }); - - }); describe('decorator factory service',function(){ beforeEach(module('templates')); diff --git a/test/service-test.js b/test/service-test.js new file mode 100644 index 000000000..df4b6f28f --- /dev/null +++ b/test/service-test.js @@ -0,0 +1,418 @@ +describe('service',function(){ + beforeEach(module('templates')); + beforeEach(module('schemaForm')); + + it('should generate default form def from a schema',function(){ + inject(function(schemaForm){ + + var schema = { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "Gimme yea name lad", + "type": "string" + }, + "gender": { + "title": "Choose", + "type": "string", + "enum": [ + "undefined", + "null", + "NaN", + ] + }, + "overEighteen": { + "title": "Are you over 18 years old?", + "type": "boolean", + "default": false + }, + "attributes": { + "type": "object", + "required": ['eyecolor'], + "properties": { + "eyecolor": { "type": "string", "title": "Eye color" }, + "haircolor": { "type": "string", "title": "Hair color" }, + "shoulders": { + "type": "object", + "title": "Shoulders", + "properties": { + "left": { "type": "string" }, + "right": { "type": "string" }, + } + } + } + } + } + }; + + var form = [ + { + "title": "Name", + "description": "Gimme yea name lad", + "schema": { + "title": "Name", + "description": "Gimme yea name lad", + "type": "string" + }, + "ngModelOptions": {}, + "key": [ + "name" + ], + "type": "text" + }, + { + "title": "Choose", + "schema": { + "title": "Choose", + "type": "string", + "enum": [ + "undefined", + "null", + "NaN" + ] + }, + "ngModelOptions": {}, + "key": [ + "gender" + ], + "type": "select", + "titleMap": [ + { + "name": "undefined", + "value": "undefined" + }, + { + "name": "null", + "value": "null" + }, + { + "name": "NaN", + "value": "NaN" + } + ] + }, + { + "title": "Are you over 18 years old?", + "schema": { + "title": "Are you over 18 years old?", + "type": "boolean", + "default": false + }, + "ngModelOptions": {}, + "key": [ + "overEighteen" + ], + "type": "checkbox" + }, + { + "title": "attributes", + "schema": { + "type": "object", + "required": [ + "eyecolor" + ], + "properties": { + "eyecolor": { + "type": "string", + "title": "Eye color" + }, + "haircolor": { + "type": "string", + "title": "Hair color" + }, + "shoulders": { + "type": "object", + "title": "Shoulders", + "properties": { + "left": { + "type": "string" + }, + "right": { + "type": "string" + } + } + } + } + }, + "ngModelOptions": {}, + "type": "fieldset", + "items": [ + { + "title": "Eye color", + "required": true, + "schema": { + "type": "string", + "title": "Eye color" + }, + "ngModelOptions": {}, + "key": [ + "attributes", + "eyecolor" + ], + "type": "text" + }, + { + "title": "Hair color", + "schema": { + "type": "string", + "title": "Hair color" + }, + "ngModelOptions": {}, + "key": [ + "attributes", + "haircolor" + ], + "type": "text" + }, + { + "title": "Shoulders", + "schema": { + "type": "object", + "title": "Shoulders", + "properties": { + "left": { + "type": "string" + }, + "right": { + "type": "string" + } + } + }, + "ngModelOptions": {}, + "type": "fieldset", + "items": [ + { + "title": "left", + "schema": { + "type": "string" + }, + "ngModelOptions": {}, + "key": [ + "attributes", + "shoulders", + "left" + ], + "type": "text" + }, + { + "title": "right", + "schema": { + "type": "string" + }, + "ngModelOptions": {}, + "key": [ + "attributes", + "shoulders", + "right" + ], + "type": "text" + } + ] + } + ] + } + ]; + + + var f = schemaForm.defaults(schema); + f.form.should.be.deep.equal(form); + + }); + }); + + it('should handle global defaults',function(){ + inject(function(schemaForm){ + + var schema = { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "Gimme yea name lad", + "type": "string" + } + } + }; + + var form = [ + { + "title": "Name", + "description": "Gimme yea name lad", + "schema": { + "title": "Name", + "description": "Gimme yea name lad", + "type": "string" + }, + "ngModelOptions": { "updateOn": "blur"}, + "foo": "bar", + "key": [ + "name" + ], + "type": "text" + } + ]; + + var f = schemaForm.defaults(schema,{},{ formDefaults: { foo: "bar", ngModelOptions: { updateOn: 'blur' }}}); + f.form.should.be.deep.equal(form); + + }); + }); + + + + it('should be extendable with new defaults',function(){ + module(function(schemaFormProvider){ + schemaFormProvider.prependRule('string',function(name,schema,options){ + if (schema.format === 'foobar') { + var f = schemaFormProvider.createStandardForm(name,schema,options); + f.type = 'foobar'; + return f; + } + }); + + schemaFormProvider.appendRule('string',function(name,schema,options){ + var f = schemaFormProvider.createStandardForm(name,schema,options); + f.type = 'notused'; + return f; + }); + }); + + inject(function(schemaForm){ + + var schema = { + "type": "object", + "properties": { + "name": { + "title": "Name", + "format": "foobar", + "description": "Gimme yea name lad", + "type": "string" + }, + "gender": { + "title": "Choose", + "type": "string", + "enum": [ + "undefined", + "null", + "NaN", + ] + } + } + }; + + //no form is implicitly ['*'] + var defaults = schemaForm.defaults(schema).form; + defaults[0].type.should.be.equal('foobar'); + defaults[0].title.should.be.equal('Name'); + defaults[1].type.should.be.equal('select'); + defaults[1].title.should.be.equal('Choose'); + + }); + }); + + it('should be enable post-processing of forms',function(){ + module(function(schemaFormProvider){ + schemaFormProvider.postProcess(function(form){ + form.postProcess = true; + form.length.should.be.eq(1); + form[0].title.should.be.eq('Name'); + return form; + }); + + }); + + inject(function(schemaForm){ + + var schema = { + "type": "object", + "properties": { + "name": { + "title": "Name", + "format": "foobar", + "description": "Gimme yea name lad", + "type": "string" + } + } + }; + + var form = schemaForm.merge(schema,["name"]); + form.postProcess.should.be.true; + + }); + }); + + + it('should ignore parts of schema in ignore list',function(){ + inject(function(schemaForm){ + + var schema = { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "Gimme yea name lad", + "type": "string" + }, + "gender": { + "title": "Choose", + "type": "string", + "enum": [ + "undefined", + "null", + "NaN", + ] + } + } + }; + + //no form is implicitly ['*'] + var defaults = schemaForm.defaults(schema).form; + schemaForm.merge(schema,["*"],{gender:true}).should.be.deep.equal([defaults[0]]); + }); + }); + + + it('should merge schema and form def',function(){ + inject(function(schemaForm){ + + var schema = { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "Gimme yea name lad", + "type": "string" + }, + "gender": { + "title": "Choose", + "type": "string", + "enum": [ + "undefined", + "null", + "NaN", + ] + } + } + }; + + //no form is implicitly ['*'] + var defaults = schemaForm.defaults(schema).form; + schemaForm.merge(schema).should.be.deep.equal(defaults); + schemaForm.merge(schema,['*']).should.be.deep.equal(defaults); + schemaForm.merge(schema,['*',{type:'fieldset'}]).should.be.deep.equal(defaults.concat([{type:'fieldset'}])); + + //simple form + schemaForm.merge(schema,['gender']).should.be.deep.equal([defaults[1]]); + schemaForm.merge(schema,['gender','name']).should.be.deep.equal([defaults[1],defaults[0]]); + + //change it up + var f = angular.copy(defaults[0]); + f.title = 'Foobar'; + f.type = 'password'; + schemaForm.merge(schema,[{ key: 'name',title: 'Foobar',type: 'password'}]).should.be.deep.equal([f]); + + }); + }); + +}); \ No newline at end of file From 6f1b6c271f7dd343536afecdc103c92b5c9b5a23 Mon Sep 17 00:00:00 2001 From: Cameron Edwards Date: Tue, 9 Sep 2014 15:19:45 -0400 Subject: [PATCH 2/8] Separate decorator-factory-service-test --- karma.conf.js | 3 ++- test/decorator-factory-service-test.js | 27 +++++++++++++++++++++ test/schema-form-test.js | 33 -------------------------- 3 files changed, 29 insertions(+), 34 deletions(-) create mode 100644 test/decorator-factory-service-test.js diff --git a/karma.conf.js b/karma.conf.js index 31f4bb2ba..ea3df7ed2 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -26,7 +26,8 @@ module.exports = function(config) { 'src/directives/decorators/bootstrap/*.js', 'src/**/*.html', 'test/schema-form-test.js', - 'test/service-test.js' + 'test/service-test.js', + 'test/decorator-factory-service-test.js', ], // list of files to exclude diff --git a/test/decorator-factory-service-test.js b/test/decorator-factory-service-test.js new file mode 100644 index 000000000..339bde411 --- /dev/null +++ b/test/decorator-factory-service-test.js @@ -0,0 +1,27 @@ +describe('decorator factory service',function(){ + beforeEach(module('templates')); + beforeEach(module('schemaForm')); + + it('should enable you to create new decorator directives',function(){ + module(function(schemaFormDecoratorsProvider){ + schemaFormDecoratorsProvider.createDecorator('foobar',{ 'foo':'/bar.html' },[angular.noop]); + }); + + inject(function($rootScope,$compile,$templateCache){ + $templateCache.put('/bar.html','
YES
'); + + //Since our directive does a replace we need a wrapper to actually check the content. + var templateWithWrap = angular.element('
'); + var template = templateWithWrap.children().eq(0); + + $compile(template)($rootScope); + $rootScope.$apply(); + templateWithWrap.children().length.should.equal(1); + templateWithWrap.children().is('foobar').should.be.true; + templateWithWrap.children().eq(0).children().length.should.equal(1); + templateWithWrap.children().eq(0).children().is('div').should.be.true; + templateWithWrap.children().eq(0).children().hasClass('yes').should.be.true; + + }); + }); +}); \ No newline at end of file diff --git a/test/schema-form-test.js b/test/schema-form-test.js index 5ef17dcfa..e6db68844 100644 --- a/test/schema-form-test.js +++ b/test/schema-form-test.js @@ -1615,37 +1615,4 @@ describe('Schema form',function(){ }); }); - - - - - describe('decorator factory service',function(){ - beforeEach(module('templates')); - beforeEach(module('schemaForm')); - - it('should enable you to create new decorator directives',function(){ - module(function(schemaFormDecoratorsProvider){ - schemaFormDecoratorsProvider.createDecorator('foobar',{ 'foo':'/bar.html' },[angular.noop]); - }); - - inject(function($rootScope,$compile,$templateCache){ - $templateCache.put('/bar.html','
YES
'); - - //Since our directive does a replace we need a wrapper to actually check the content. - var templateWithWrap = angular.element('
'); - var template = templateWithWrap.children().eq(0); - - $compile(template)($rootScope); - $rootScope.$apply(); - templateWithWrap.children().length.should.equal(1); - templateWithWrap.children().is('foobar').should.be.true; - templateWithWrap.children().eq(0).children().length.should.equal(1); - templateWithWrap.children().eq(0).children().is('div').should.be.true; - templateWithWrap.children().eq(0).children().hasClass('yes').should.be.true; - - }); - }); - }); - - }); From 135eb7ce8a88844d44243d1bdcd259d810b5c018 Mon Sep 17 00:00:00 2001 From: Cameron Edwards Date: Tue, 9 Sep 2014 15:23:57 -0400 Subject: [PATCH 3/8] Separate directive test --- karma.conf.js | 2 +- test/decorator-factory-service-test.js | 2 + test/directive-test.js | 1614 +++++++++++++++++++++++ test/schema-form-test.js | 1618 ------------------------ test/service-test.js | 2 + 5 files changed, 1619 insertions(+), 1619 deletions(-) create mode 100644 test/directive-test.js delete mode 100644 test/schema-form-test.js diff --git a/karma.conf.js b/karma.conf.js index ea3df7ed2..050bc1279 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -25,9 +25,9 @@ module.exports = function(config) { 'src/directives/*.js', 'src/directives/decorators/bootstrap/*.js', 'src/**/*.html', - 'test/schema-form-test.js', 'test/service-test.js', 'test/decorator-factory-service-test.js', + 'test/directive-test.js', ], // list of files to exclude diff --git a/test/decorator-factory-service-test.js b/test/decorator-factory-service-test.js index 339bde411..7e1f3fc08 100644 --- a/test/decorator-factory-service-test.js +++ b/test/decorator-factory-service-test.js @@ -1,3 +1,5 @@ +chai.should(); + describe('decorator factory service',function(){ beforeEach(module('templates')); beforeEach(module('schemaForm')); diff --git a/test/directive-test.js b/test/directive-test.js new file mode 100644 index 000000000..22ca872c2 --- /dev/null +++ b/test/directive-test.js @@ -0,0 +1,1614 @@ +chai.should(); + +describe('directive',function(){ + beforeEach(module('templates')); + beforeEach(module('schemaForm')); + beforeEach( + //We don't need no sanitation. We don't need no though control. + module(function($sceProvider){ + $sceProvider.enabled(false); + }) + ); + + + + var exampleSchema = { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "Gimme yea name lad", + "type": "string" + }, + "gender": { + "title": "Choose:", + "type": "string", + "enum": [ + "undefined", + "null", + "NaN", + ] + } + } + }; + + + it('should generate html and compile it',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = exampleSchema; + + scope.form = ["*"]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(2); + tmpl.children().eq(0).is('bootstrap-decorator').should.be.true; + tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model').should.be.equal('model[\'name\']'); + tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(1).children().eq(0).children('select').length.should.equal(1); + + }); + }); + + it('should generate html and compile it, deep structure',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + 'type': 'object', + 'properties': { + 'name': { + 'title': 'Name', + 'description': 'Gimme yea name lad', + 'type': 'string' + }, + 'ianal': { + 'type': 'boolean', + 'title':'IANAL' + }, + 'age': { + 'type': 'integer', + 'title':'Age', + 'minimum': 0 + }, + 'sum': { + 'type': 'number', + 'title': 'summa' + }, + 'gender': { + 'title': 'Choose', + 'type': 'string', + 'enum': [ + 'undefined', + 'null', + 'NaN', + ] + }, + 'attributes': { + 'type': 'object', + 'title': 'Attributes', + 'required': ['eyecolor'], + 'properties': { + 'eyecolor': { 'type': 'string', 'title': 'Eye color' }, + 'haircolor': { 'type': 'string', 'title': 'Hair color' }, + 'shoulders': { + 'type': 'object', + 'title': 'Shoulders', + 'properties': { + 'left': { 'type': 'string' }, + 'right': { 'type': 'string' }, + } + } + } + } + } + }; + + scope.form = ['*']; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + + tmpl.children().length.should.be.equal(6); + tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model').should.be.equal('model[\'name\']'); + + tmpl.children().eq(1).children().eq(0).is('div.checkbox').should.be.true; + tmpl.children().eq(1).children().eq(0).find('input[type="checkbox"]').length.should.be.eq(1); + + tmpl.children().eq(2).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(2).children().eq(0).find('input[type="number"]').length.should.be.eq(1); + + tmpl.children().eq(3).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(3).children().eq(0).find('input[type="number"]').length.should.be.eq(1); + + tmpl.children().eq(4).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(4).children().eq(0).find('select').length.should.be.eq(1); + + tmpl.children().eq(5).children().eq(0).is('fieldset').should.be.true; + tmpl.children().eq(5).children().eq(0).children().eq(0).is('legend').should.be.true; + tmpl.children().eq(5).children().eq(0).children().eq(3).is('sf-decorator').should.be.true; + + tmpl.children().eq(5).children().eq(0).children().eq(4).children().eq(0).is('fieldset').should.be.true; + tmpl.children().eq(5).children().eq(0).children().eq(4).children().eq(0).children().length.should.be.eq(4); + tmpl.children().eq(5).children().eq(0).children().eq(4).children().eq(0).find('input[ng-model="model[\'attributes\'][\'shoulders\'][\'left\']"]').length.should.be.eq(1); + tmpl.children().eq(5).children().eq(0).children().eq(4).children().eq(0).find('input[ng-model="model[\'attributes\'][\'shoulders\'][\'right\']"]').length.should.be.eq(1); + + }); + }); + + + it('should generate html and compile it, leaving existing inputs intact',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = exampleSchema; + + scope.form = ["*"]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + tmpl.children().length.should.be.equal(2); + tmpl.children().eq(0).is('input[type="text"]').should.be.true; + tmpl.children().eq(0).attr('ng-model').should.be.equal('person.name'); + tmpl.children().eq(1).is('bootstrap-decorator').should.be.true; + tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(1).children().eq(0).children('select').length.should.equal(1); + + }); + }); + + it('should handle submit buttons',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.obj = {}; + + scope.schema = exampleSchema; + + //just a button + scope.form = [{ type: 'submit',title: 'Okidoki'}]; + var tmpl = angular.element('
'); + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.find('input').is('input[type=submit]').should.be.true; + tmpl.find('input').val().should.be.equal('Okidoki'); + + //with the rest of the schema + scope.form = ["*",{ type: 'submit',title: 'Okidoki'}]; + + tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + tmpl.children().length.should.be.equal(3); + tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; + tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(1).children().eq(0).children('select').length.should.equal(1); + tmpl.children().eq(2).children().eq(0).find('input').is('input[type=submit]').should.be.true; + tmpl.children().eq(2).children().eq(0).find('input').val().should.be.equal('Okidoki'); + }); + }); + + it('should handle buttons',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.obj = {}; + + scope.schema = exampleSchema; + + scope.form = ["*",{ type: 'button',title: 'Okidoki', onClick: sinon.spy()}]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(3); + tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; + tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(1).children().eq(0).children('select').length.should.equal(1); + tmpl.children().eq(2).children().eq(0).find('button').length.should.be.equal(1); + tmpl.children().eq(2).children().eq(0).find('button').text().should.be.equal('Okidoki'); + + scope.form[1].onClick.should.not.have.beenCalled; + tmpl.children().eq(2).children().eq(0).find('button').click(); + scope.form[1].onClick.should.have.beenCalledOnce; + }); + + }); + + it('should style submit buttons',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.obj = {}; + + scope.schema = exampleSchema; + + //A submit button with default style + scope.form = [{ type: 'submit',title: 'Okidoki'}]; + var tmpl = angular.element('
'); + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.find('input').hasClass('btn-primary').should.be.true; + tmpl.find('input').hasClass('btn-success').should.be.false; + + //A submit button with default style + scope.form = [{ type: 'submit', style: 'btn-success', title: 'Okidoki'}]; + var tmpl = angular.element('
'); + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.find('input').hasClass('btn-primary').should.be.false; + tmpl.find('input').hasClass('btn-success').should.be.true; + + //A button with default style + scope.form = [{ type: 'button',title: 'Okidoki'}]; + var tmpl = angular.element('
'); + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.find('button').hasClass('btn-default').should.be.true; + tmpl.find('button').hasClass('btn-success').should.be.false; + + //A button with default style + scope.form = [{ type: 'button', style: 'btn-success', title: 'Okidoki'}]; + tmpl = angular.element('
'); + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.find('button').hasClass('btn-default').should.be.false; + tmpl.find('button').hasClass('btn-success').should.be.true; + + }); + }); + + it('should use disable readonly input fields, v3 style',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "properties": { + "name": { "type": "string", "readonly": true }, + "nick": { "type": "string" } + } + }; + + scope.form = ["*"]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + tmpl.children().length.should.be.equal(2); + tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').attr('disabled').should.be.equal('disabled'); + tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(1).children().eq(0).children('input').length.should.equal(1); + expect(tmpl.children().eq(1).children().eq(0).children('input').attr('disabled')).to.be.undefined; + }); + }); + + it('should use disable readonly input fields, v4 style',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "properties": { + "name": { "type": "string", "readOnly": true }, + "nick": { "type": "string" } + } + }; + + scope.form = ["*"]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(2); + tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').attr('disabled').should.be.equal('disabled'); + tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(1).children().eq(0).children('input').length.should.equal(1); + expect(tmpl.children().eq(1).children().eq(0).children('input').attr('disabled')).to.be.undefined; + }); + }); + + it('should use disable readonly input fields, form override',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "properties": { + "name": { "type": "string" }, + "nick": { "type": "string", "readOnly": true } + } + }; + + scope.form = [ + { key: 'name', readonly: true }, + { key: 'nick', readonly: false }, + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(2); + tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').attr('disabled').should.be.equal('disabled'); + tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(1).children().eq(0).children('input').length.should.equal(1); + expect(tmpl.children().eq(1).children().eq(0).children('input').attr('disabled')).to.be.undefined; + }); + }); + + it('should display custom validationMessages when specified',function(done){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "properties": { + "name": { + "type": "string", + "pattern": "^[a-z]+", + "validationMessage": "You are only allowed lower case letters in name." + }, + "nick": { + "type": "string", + "pattern": "^[a-z]+", + }, + } + }; + + scope.form = [ + "name", + { + key: 'nick', + validationMessage: 'Foobar' + } + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + tmpl.find('input').each(function(){ + $(this).scope().ngModel.$setViewValue('AÖ'); + }); + + var errors = tmpl.find('.help-block'); + + //timeout so we can do a second $apply + setTimeout(function(){ + $rootScope.$apply(); //this actually updates the view with error messages + errors.eq(0).text().should.be.equal("You are only allowed lower case letters in name."); + errors.eq(1).text().should.be.equal("Foobar"); + done(); + },0); + + }); + }); + + + it('should use ng-required on required fields',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "required": ["name"], + "properties": { + "name": { "type": "string" }, + "nick": { "type": "string" } + } + }; + + scope.form = ["*"]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(2); + tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model-options').should.be.equal('form.ngModelOptions') + tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model').should.be.equal('model[\'name\']'); + tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(1).children().eq(0).children('input').length.should.equal(1); + expect(tmpl.children().eq(1).children().eq(0).children('input').attr('required')).to.be.undefined; + }); + }); + + it('should use ng-required on required fields, json schema v3',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "properties": { + "name": { "type": "string", "required": true }, + "nick": { "type": "string" } + } + }; + + scope.form = ["*"]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(2); + tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model-options').should.be.equal('form.ngModelOptions') + tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model').should.be.equal('model[\'name\']'); + tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(1).children().eq(0).children('input').length.should.equal(1); + expect(tmpl.children().eq(1).children().eq(0).children('input').attr('required')).to.be.undefined; + }); + }); + + it('should use ng-required on required fields, form override',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "properties": { + "name": { "type": "string" }, + "nick": { "type": "string", "required": true } + } + }; + + scope.form = [ + { key: 'name', required: true }, + { key: 'nick', required: false }, + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(2); + tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; + tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model-options').should.be.equal('form.ngModelOptions'); + tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model').should.be.equal('model[\'name\']'); + tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; + tmpl.children().eq(1).children().eq(0).children('input').length.should.equal(1); + expect(tmpl.children().eq(1).children().eq(0).children('input').attr('required')).to.be.undefined; + }); + }); + + it('should honor defaults in schema',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = { + name: 'Foobar' + }; + + scope.schema = { + "type": "object", + "properties": { + "name": { + "type": "string", + "default": "Bar" + }, + "nick": { + "type": "string", + "default": "Zeb" + }, + "alias": { + "type": "string" + }, + } + }; + + scope.form = ["*"]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + scope.person.name.should.be.equal('Foobar'); + scope.person.nick.should.be.equal('Zeb'); + expect(scope.person.alias).to.be.undefined; + + }); + }); + + it('should handle schema form defaults in deep structure',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = { + name: 'Foobar' + }; + + scope.schema = { + "type": "object", + "properties": { + "props" : { + "type": "object", + "title": "Person", + "properties": { + "name": { + "type": "string", + "title": "Name" + }, + "nick": { + "type": "string", + "title": "Nick" + }, + "alias": { + "type": "string", + "title": "Alias" + } + } + } + } + }; + + //The form defines a fieldset for person, and changes the order of fields + //but titles should come from the schema + scope.form = [{ + type: 'fieldset', + key: 'props', + items: [ + 'props.nick', + 'props.name', + 'props.alias' + ] + }]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.eq(1); + var labels = tmpl.children().children().find('label'); + labels.eq(0).text().should.equal('Nick'); + labels.eq(1).text().should.equal('Name'); + labels.eq(2).text().should.equal('Alias'); + + }); + }); + + + it('should skip title if form says "notitle"',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = exampleSchema; + + scope.form = [{ + key: 'name', + notitle: true + },{ + key: 'gender', + notitle: true + }]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(2); + tmpl.children().eq(0).children().eq(0).find('label').hasClass('ng-hide').should.be.true; + tmpl.children().eq(1).children().eq(0).find('label').hasClass('ng-hide').should.be.true; + }); + }); + + + it('should generate checkboxes for arrays with enums',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "properties": { + "names": { + "type": "array", + "items": { + "type": "string", + "enum": ["foo","bar"] + } + } } + }; + + scope.form = [ + "names", + { key: "foobars", type: "checkboxes", titleMap:{ 'foo':'Foo','bar':'Bar'}} + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + //TODO: more asserts + tmpl.children().length.should.be.equal(2); + tmpl.children().eq(0).children().eq(0).find('input[type=checkbox]').length.should.be.eq(2); + }); + }); + + it('should initialize checkboxes to the model values',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = { + "names": ["foo"] + }; + + scope.schema = { + "type": "object", + "properties": { + "names": { + "type": "array", + "items": { + "type": "string", + "enum": ["foo"] + } + } } + }; + + scope.form = [ + "names", + { key: "foobars", type: "checkboxes", titleMap:{ 'foo':'Foo'} } + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().eq(0).find('input[type=checkbox]').prop('checked').should.be.true; + }); + }); + + it('should use radio buttons when they are wanted',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "properties": { + "names": { + "type": "string", + "enum": ["one","two"] + }, + "opts": { + "type": "string", + "enum": ["one","two"] + }, + } + }; + + scope.form = [ + { key: "names", type: "radios",titleMap: { one: "One", two: "The rest" }}, + { key: "opts", type: "radiobuttons",titleMap: { one: "One", two: "The rest" }} + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + //TODO: more asserts + + tmpl.children().length.should.be.equal(2); + tmpl.children().eq(0).children().eq(0).find('input[type=radio]').length.should.be.eq(2); + tmpl.children().eq(0).children().eq(0).find('.radio').length.should.be.eq(2); + tmpl.children().eq(1).children().eq(0).find('input[type=radio]').length.should.be.eq(2); + tmpl.children().eq(1).children().eq(0).find('.btn').length.should.be.eq(2); + + }); + }); + + it('should use radio buttons with HTML',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "properties": { + "names": { + "type": "string", + "enum": ["one","two"], + "description": "Cats are so cool.", + "title": "testlokol" + }, + "opts": { + "type": "string", + "enum": ["one","two"] + }, + "boxe": { + "type": "boolean", + "title": "whavre", + "description": "Cats are so cool." + }, + } + }; + + scope.form = [ + { key: "names", type: "radios",titleMap: { one: "onedirection", two: "
Baby spice
" }}, + { key: "opts", type: "radiobuttons",titleMap: { one: "One", two: "The rest" }}, + "boxe" + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.find('.spicegirls').length.should.be.equal(1); + tmpl.find('#testerish').length.should.be.equal(1); + tmpl.find('#bawkses').length.should.be.equal(1); + tmpl.find('#gh').length.should.be.equal(2); + + }); + }); + + it('should style radio buttons',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "properties": { + "opts": { + "type": "string", + "enum": ["one","two"] + }, + } + }; + + scope.form = [ + { + key: "opts", + type: "radiobuttons", + titleMap: [ + { value: "one", name: "One" }, + { value: "two", name: "The rest" } + ] + } + ]; + + var styles = { + any: {}, + both: { + selected: "btn-success", + unselected: "btn-default" + }, + onlySelected: { + selected: "btn-success" + }, + onlyUnselected: { + unselected: "btn-default" + } + }; + + //Radiobuttons uninitialized and default styles + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.true; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.false; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.true; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; + + //Radiobuttons uninitialized and both styles + var tmpl = angular.element('
'); + scope.form[0].style = styles.both; + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.false; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.true; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.true; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; + + //Radiobuttons uninitialized and only selected style + var tmpl = angular.element('
'); + scope.form[0].style = styles.onlySelected; + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.true; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.false; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.true; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; + + //Radiobuttons uninitialized and only unselected style + var tmpl = angular.element('
'); + scope.form[0].style = styles.onlyUnselected; + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.false; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.true; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.true; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; + + //Radiobuttons initialized and default styles + scope.person = { opts: "one" }; + var tmpl = angular.element('
'); + scope.form[0].style = ''; + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.true; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.false; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.true; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; + + //Radiobuttons initialized and both styles + var tmpl = angular.element('
'); + scope.form[0].style = styles.both; + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.false; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.false; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.true; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.true; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; + + //Radiobuttons initialized and only selected style + var tmpl = angular.element('
'); + scope.form[0].style = styles.onlySelected; + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.false; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.false; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.true; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.true; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; + + //Radiobuttons initialized and only unselected style + var tmpl = angular.element('
'); + scope.form[0].style = styles.onlyUnselected; + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.true; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.false; + tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.false; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.true; + tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; + + }); + }); + + it('should handle a simple div when type "section" is specified',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = exampleSchema; + + scope.form = [{ + type: "section", + items: [ + { + key: 'name', + notitle: true + }, + { + key: 'gender', + notitle: true + } + ] + }]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.children().eq(0).children().eq(0).is('div').should.be.true; + tmpl.children().eq(0).children().eq(0).hasClass('btn-group').should.be.false; + tmpl.children().eq(0).children().eq(0).children().length.should.be.eq(2); + }); + }); + + it('should handle a simple div with a condition if "conditional" is specified',function(done){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = { show: false }; + + scope.schema = exampleSchema; + + scope.form = [{ + type: "conditional", + condition: "person.show", + items: [ + { + key: 'name', + notitle: true + }, + { + key: 'gender', + notitle: true + } + ] + }]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.children().eq(0).children().length.should.be.equal(0); + + //Do a setTimeout so we kan do another $apply + setTimeout(function(){ + scope.person.show = true; + scope.$apply(); + tmpl.children().length.should.be.equal(1); + tmpl.children().eq(0).children().eq(0).is('div').should.be.true; + tmpl.children().eq(0).children().eq(0).hasClass('btn-group').should.be.false; + tmpl.children().eq(0).children().eq(0).children().length.should.be.eq(2); + done(); + },10); + + }); + }); + + + + + it('should handle "action" groups, same as "section" but with a bootstrap class "btn-group"',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = exampleSchema; + + scope.form = [{ + type: "actions", + items: [ + { + type: 'submit', + title: 'yes' + }, + { + type: 'button', + title: 'no' + } + ] + }]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.children().eq(0).children().eq(0).is('div').should.be.true; + tmpl.children().eq(0).children().eq(0).hasClass('btn-group').should.be.true; + tmpl.children().eq(0).children().eq(0).children().length.should.be.eq(2); + tmpl.children().eq(0).children().eq(0).children().eq(0).is('input').should.be.true; + tmpl.children().eq(0).children().eq(0).children().eq(1).is('button').should.be.true; + }); + }); + + it('should style "action" groups',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = exampleSchema; + + scope.form = [{ + type: "actions", + items: [ + { + type: 'submit', + title: 'yes1' + }, + { + type: 'button', + title: 'no1' + }, + { + type: 'submit', + style: 'btn-success', + title: 'yes2' + }, + { + type: 'button', + style: 'btn-danger', + title: 'no2' + } + ] + }]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(1); + tmpl.children().eq(0).children().length.should.be.equal(1); + tmpl.children().eq(0).children().eq(0).children().length.should.be.eq(4); + tmpl.children().eq(0).children().eq(0).children().eq(0).hasClass('btn-primary').should.be.true; + tmpl.children().eq(0).children().eq(0).children().eq(0).hasClass('btn-success').should.be.false; + tmpl.children().eq(0).children().eq(0).children().eq(1).hasClass('btn-default').should.be.true; + tmpl.children().eq(0).children().eq(0).children().eq(1).hasClass('btn-danger').should.be.false; + tmpl.children().eq(0).children().eq(0).children().eq(2).hasClass('btn-primary').should.be.false; + tmpl.children().eq(0).children().eq(0).children().eq(2).hasClass('btn-success').should.be.true; + tmpl.children().eq(0).children().eq(0).children().eq(3).hasClass('btn-default').should.be.false; + tmpl.children().eq(0).children().eq(0).children().eq(3).hasClass('btn-danger').should.be.true; + + + + }); + }); + + it('should render custom html when type "help" is specified',function(){ + + //We don't need no sanitation. We don't need no though control. + module(function($sceProvider){ + $sceProvider.enabled(false); + }); + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = { }; + + scope.schema = { + type: "object", + properties: { + name: { + type: "string", + } + } + }; + + + scope.form = [ + { + type: "help", + helpvalue: "

Yo Ninja!

" + }, + "name" + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.eq(2); + tmpl.children().eq(0).children().eq(0).is('div').should.be.true; + tmpl.children().eq(0).children().eq(0).children().length.should.eq(1); + tmpl.children().eq(0).children().eq(0).children().html().should.be.eq("Yo Ninja!"); + + }); + }); + + it('should render tabs with items in them when specified',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = { }; + + scope.schema = { + type: "object", + properties: { + name: { type: "string", title: "Name" }, + alias: { type: "string", title: "Alias" }, + nick: { type: "string", title: "Nickname" }, + tag: { type: "string", title: "Tag" }, + } + }; + + scope.form = [ + { + type: "tabs", + tabs: [ + { + title: "Tab 1", + items: [ + "name", + "tag" + ] + }, + { + title: "Tab 2", + items: [ + "alias", + "nick" + ] + } + ] + }, + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.eq(1); + var tabs = tmpl.children().children().eq(0).children().eq(0); + var panes = tmpl.children().children().eq(0).children().eq(1); + + tabs.is('ul').should.be.true; + tabs.children().length.should.be.eq(2); + tabs.children().eq(0).children().html().should.equal('Tab 1'); + tabs.children().eq(1).children().html().should.equal('Tab 2'); + + panes.is('div').should.be.true; + + panes.children().length.should.be.eq(2); + panes.children().eq(0).children().length.should.be.eq(2); + panes.children().eq(0).children().eq(0).find('label').html().should.eq('Name'); + panes.children().eq(0).children().eq(1).find('label').html().should.eq('Tag'); + + panes.children().eq(1).children().length.should.be.eq(2); + panes.children().eq(1).children().eq(0).find('label').html().should.eq('Alias'); + panes.children().eq(1).children().eq(1).find('label').html().should.eq('Nickname'); + + }); + }); + + + it('should render a list of subforms when schema type is array',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "properties": { + "names": { + "type": "array", + "items": { + "type": "string", + "title": "Name" + } + }, + "subforms": { + "type": "array", + "items": { + "type": "object", + "title": "subform", + "properties": { + "one": { "type": "string" }, + "two": { "type": "number", "title": "Two" } + } + } + }, + "subsubforms": { + "type": "array", + "items": { + "type": "object", + "title": "subform", + "properties": { + "one": { "type": "string" }, + "list": { + "type": "array", + "items": { + "type": "number", + "title": "sublist numbers" + } + } + } + } + } + } + }; + + scope.form = [ + "names", + { + key: "subforms", + type: "array", + items: [ + "subforms[].one" + ] + }, + "subsubforms" + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + //TODO: more asserts + tmpl.children().length.should.be.equal(3); + tmpl.children().eq(0).children().eq(0).find('input').length.should.be.eq(1); + tmpl.children().eq(0).children().eq(0).find('button').length.should.be.eq(2); + tmpl.children().eq(0).children().eq(0).find('button').eq(1).text().trim().should.be.eq('Add'); + + tmpl.children().eq(1).children().eq(0).find('input').length.should.be.eq(1); + tmpl.children().eq(1).children().eq(0).find('fieldset').length.should.be.eq(0); + tmpl.children().eq(1).children().eq(0).find('button').length.should.be.eq(2); + tmpl.children().eq(1).children().eq(0).find('button').eq(1).text().trim().should.be.eq('Add'); + + tmpl.children().eq(2).children().eq(0).find('input').length.should.be.eq(2); + tmpl.children().eq(2).children().eq(0).find('fieldset').length.should.be.eq(1); + tmpl.children().eq(2).children().eq(0).find('button').length.should.be.eq(4); + tmpl.children().eq(2).children().eq(0).find('button').eq(3).text().trim().should.be.eq('Add'); + + + }); + }); + + it('should style an array',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "properties": { + "names": { + "type": "array", + "items": { + "type": "string", + "title": "Name" + } + }, + "subforms": { + "type": "array", + "items": { + "type": "object", + "title": "subform", + "properties": { + "one": { "type": "string" }, + "two": { "type": "number", "title": "Two" } + } + } + }, + "subsubforms": { + "type": "array", + "items": { + "type": "object", + "title": "subform", + "properties": { + "one": { "type": "string" }, + "list": { + "type": "array", + "items": { + "type": "number", + "title": "sublist numbers" + } + } + } + } + } + } + }; + + scope.form = [ + { + key: "names", + add: "New" + }, + { + key: "subforms", + add: "New", + style: { add: "btn-info" }, + type: "array", + items: [ + "subforms[].one" + ] + }, + "subsubforms" + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(3); + tmpl.children().eq(0).find('button').eq(1).text().trim().should.be.eq('New'); + tmpl.children().eq(0).find('button').eq(1).hasClass('btn-default').should.be.true; + tmpl.children().eq(0).find('button').eq(1).hasClass('btn-info').should.be.false; + tmpl.children().eq(1).find('button').eq(1).text().trim().should.be.eq('New'); + tmpl.children().eq(1).find('button').eq(1).hasClass('btn-default').should.be.false; + tmpl.children().eq(1).find('button').eq(1).hasClass('btn-info').should.be.true; + tmpl.children().eq(2).find('button').eq(3).text().trim().should.be.eq('Add'); + tmpl.children().eq(2).find('button').eq(3).hasClass('btn-default').should.be.true; + tmpl.children().eq(2).find('button').eq(3).hasClass('btn-info').should.be.false; + + }); + }); + + it('should render a tabarray of subforms when asked',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = { + names: ['me','you','another'] + }; + + scope.schema = { + "type": "object", + "properties": { + "names": { + "type": "array", + "items": { + "type": "string", + "title": "Name" + } + }, + "subforms": { + "type": "array", + "items": { + "type": "object", + "title": "subform", + "properties": { + "one": { "type": "string" }, + "two": { "type": "number", "title": "Two" } + } + } + } + } + }; + + scope.form = [ + { key: "names", type: "tabarray" }, + { + key: "subforms", + type: "tabarray", + tabType: "right", + items: [ + "subforms[].one" + ] + } + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + //TODO: more asserts + tmpl.children().length.should.be.equal(2); + tmpl.children().eq(0).children().eq(0).find('input').length.should.be.eq(3); + tmpl.children().eq(0).children().eq(0).find('button').length.should.be.eq(3); + tmpl.children().eq(0).children().eq(0).find('button').eq(0).text().trim().should.be.eq('Remove'); + tmpl.children().eq(0).children().eq(0).is('div').should.be.true; + tmpl.children().eq(0).children().eq(0).attr('sf-array').should.be.thruthy; + tmpl.children().eq(0).children().eq(0).find('.tabs-left').length.should.be.eq(1); + + tmpl.children().eq(1).children().eq(0).find('input').length.should.be.eq(1); + tmpl.children().eq(1).children().eq(0).find('fieldset').length.should.be.eq(0); + tmpl.children().eq(1).children().eq(0).find('button').length.should.be.eq(1); + tmpl.children().eq(1).children().eq(0).find('button').text().trim().should.be.eq('Remove'); + tmpl.children().eq(1).children().eq(0).attr('sf-array').should.be.thruthy; + tmpl.children().eq(1).children().eq(0).find('.tabs-left').length.should.be.eq(0); + tmpl.children().eq(1).children().eq(0).find('.tabs-right').length.should.be.eq(1); + + }); + }); + + it('should style a tabarray',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = { + names: ['me','you','another'] + }; + + scope.schema = { + "type": "object", + "properties": { + "names": { + "type": "array", + "items": { + "type": "string", + "title": "Name" + } + }, + "subforms": { + "type": "array", + "items": { + "type": "object", + "title": "subform", + "properties": { + "one": { "type": "string" }, + "two": { "type": "number", "title": "Two" } + } + } + } + } + }; + + scope.form = [ + { + key: "names", + type: "tabarray", + add: "New", + style: { remove: "btn-danger" }, + }, + { + key: "subforms", + type: "tabarray", + remove: "Delete", + tabType: "right", + items: [ + "subforms[].one" + ] + } + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.be.equal(2); + tmpl.children().eq(0).find('button').eq(0).text().trim().should.be.eq('Remove'); + tmpl.children().eq(0).find('button').eq(0).hasClass('btn-default').should.be.false; + tmpl.children().eq(0).find('button').eq(0).hasClass('btn-danger').should.be.true; + tmpl.children().eq(0).find('li:not([ng-repeat]) > a').text().trim().should.be.eq('New'); + + tmpl.children().eq(1).find('button').text().trim().should.be.eq('Delete'); + tmpl.children().eq(1).find('button').eq(0).hasClass('btn-default').should.be.true; + tmpl.children().eq(1).find('button').eq(0).hasClass('btn-danger').should.be.false; + tmpl.children().eq(1).find('li:not([ng-repeat]) > a').text().trim().should.be.eq('Add'); + + }); + }); + + it('should sort select options by enum',function(){ + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = {}; + + scope.schema = { + "type": "object", + "properties": { + "thing": { + "type": "string", + "title": "Thing", + "enum": [ + // Intentionally non-alphabetical + // https://github.com/Textalk/angular-schema-form/issues/82 + // https://github.com/Textalk/angular-schema-form/issues/83 + "b", + "a" + ], + "enumNames": { + // Intentionally not the same order as the `enum` + "a": "The A", + "b": "The B" + } + } + } + }; + + scope.form = ["*"]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().eq(0).find('select').eq(0).find('option').eq(0).text().trim().should.be.eq(''); + tmpl.children().eq(0).find('select').eq(0).find('option').eq(1).text().trim().should.be.eq('The B'); + tmpl.children().eq(0).find('select').eq(0).find('option').eq(2).text().trim().should.be.eq('The A'); + }); + }); + +}); \ No newline at end of file diff --git a/test/schema-form-test.js b/test/schema-form-test.js deleted file mode 100644 index e6db68844..000000000 --- a/test/schema-form-test.js +++ /dev/null @@ -1,1618 +0,0 @@ -/* jshint expr: true */ -chai.should(); - -describe('Schema form',function(){ - - describe('directive',function(){ - beforeEach(module('templates')); - beforeEach(module('schemaForm')); - beforeEach( - //We don't need no sanitation. We don't need no though control. - module(function($sceProvider){ - $sceProvider.enabled(false); - }) - ); - - - - var exampleSchema = { - "type": "object", - "properties": { - "name": { - "title": "Name", - "description": "Gimme yea name lad", - "type": "string" - }, - "gender": { - "title": "Choose:", - "type": "string", - "enum": [ - "undefined", - "null", - "NaN", - ] - } - } - }; - - - it('should generate html and compile it',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = exampleSchema; - - scope.form = ["*"]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(2); - tmpl.children().eq(0).is('bootstrap-decorator').should.be.true; - tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model').should.be.equal('model[\'name\']'); - tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(1).children().eq(0).children('select').length.should.equal(1); - - }); - }); - - it('should generate html and compile it, deep structure',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - 'type': 'object', - 'properties': { - 'name': { - 'title': 'Name', - 'description': 'Gimme yea name lad', - 'type': 'string' - }, - 'ianal': { - 'type': 'boolean', - 'title':'IANAL' - }, - 'age': { - 'type': 'integer', - 'title':'Age', - 'minimum': 0 - }, - 'sum': { - 'type': 'number', - 'title': 'summa' - }, - 'gender': { - 'title': 'Choose', - 'type': 'string', - 'enum': [ - 'undefined', - 'null', - 'NaN', - ] - }, - 'attributes': { - 'type': 'object', - 'title': 'Attributes', - 'required': ['eyecolor'], - 'properties': { - 'eyecolor': { 'type': 'string', 'title': 'Eye color' }, - 'haircolor': { 'type': 'string', 'title': 'Hair color' }, - 'shoulders': { - 'type': 'object', - 'title': 'Shoulders', - 'properties': { - 'left': { 'type': 'string' }, - 'right': { 'type': 'string' }, - } - } - } - } - } - }; - - scope.form = ['*']; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - - tmpl.children().length.should.be.equal(6); - tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model').should.be.equal('model[\'name\']'); - - tmpl.children().eq(1).children().eq(0).is('div.checkbox').should.be.true; - tmpl.children().eq(1).children().eq(0).find('input[type="checkbox"]').length.should.be.eq(1); - - tmpl.children().eq(2).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(2).children().eq(0).find('input[type="number"]').length.should.be.eq(1); - - tmpl.children().eq(3).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(3).children().eq(0).find('input[type="number"]').length.should.be.eq(1); - - tmpl.children().eq(4).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(4).children().eq(0).find('select').length.should.be.eq(1); - - tmpl.children().eq(5).children().eq(0).is('fieldset').should.be.true; - tmpl.children().eq(5).children().eq(0).children().eq(0).is('legend').should.be.true; - tmpl.children().eq(5).children().eq(0).children().eq(3).is('sf-decorator').should.be.true; - - tmpl.children().eq(5).children().eq(0).children().eq(4).children().eq(0).is('fieldset').should.be.true; - tmpl.children().eq(5).children().eq(0).children().eq(4).children().eq(0).children().length.should.be.eq(4); - tmpl.children().eq(5).children().eq(0).children().eq(4).children().eq(0).find('input[ng-model="model[\'attributes\'][\'shoulders\'][\'left\']"]').length.should.be.eq(1); - tmpl.children().eq(5).children().eq(0).children().eq(4).children().eq(0).find('input[ng-model="model[\'attributes\'][\'shoulders\'][\'right\']"]').length.should.be.eq(1); - - }); - }); - - - it('should generate html and compile it, leaving existing inputs intact',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = exampleSchema; - - scope.form = ["*"]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - tmpl.children().length.should.be.equal(2); - tmpl.children().eq(0).is('input[type="text"]').should.be.true; - tmpl.children().eq(0).attr('ng-model').should.be.equal('person.name'); - tmpl.children().eq(1).is('bootstrap-decorator').should.be.true; - tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(1).children().eq(0).children('select').length.should.equal(1); - - }); - }); - - it('should handle submit buttons',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.obj = {}; - - scope.schema = exampleSchema; - - //just a button - scope.form = [{ type: 'submit',title: 'Okidoki'}]; - var tmpl = angular.element('
'); - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.find('input').is('input[type=submit]').should.be.true; - tmpl.find('input').val().should.be.equal('Okidoki'); - - //with the rest of the schema - scope.form = ["*",{ type: 'submit',title: 'Okidoki'}]; - - tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - tmpl.children().length.should.be.equal(3); - tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; - tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(1).children().eq(0).children('select').length.should.equal(1); - tmpl.children().eq(2).children().eq(0).find('input').is('input[type=submit]').should.be.true; - tmpl.children().eq(2).children().eq(0).find('input').val().should.be.equal('Okidoki'); - }); - }); - - it('should handle buttons',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.obj = {}; - - scope.schema = exampleSchema; - - scope.form = ["*",{ type: 'button',title: 'Okidoki', onClick: sinon.spy()}]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(3); - tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; - tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(1).children().eq(0).children('select').length.should.equal(1); - tmpl.children().eq(2).children().eq(0).find('button').length.should.be.equal(1); - tmpl.children().eq(2).children().eq(0).find('button').text().should.be.equal('Okidoki'); - - scope.form[1].onClick.should.not.have.beenCalled; - tmpl.children().eq(2).children().eq(0).find('button').click(); - scope.form[1].onClick.should.have.beenCalledOnce; - }); - - }); - - it('should style submit buttons',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.obj = {}; - - scope.schema = exampleSchema; - - //A submit button with default style - scope.form = [{ type: 'submit',title: 'Okidoki'}]; - var tmpl = angular.element('
'); - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.find('input').hasClass('btn-primary').should.be.true; - tmpl.find('input').hasClass('btn-success').should.be.false; - - //A submit button with default style - scope.form = [{ type: 'submit', style: 'btn-success', title: 'Okidoki'}]; - var tmpl = angular.element('
'); - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.find('input').hasClass('btn-primary').should.be.false; - tmpl.find('input').hasClass('btn-success').should.be.true; - - //A button with default style - scope.form = [{ type: 'button',title: 'Okidoki'}]; - var tmpl = angular.element('
'); - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.find('button').hasClass('btn-default').should.be.true; - tmpl.find('button').hasClass('btn-success').should.be.false; - - //A button with default style - scope.form = [{ type: 'button', style: 'btn-success', title: 'Okidoki'}]; - tmpl = angular.element('
'); - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.find('button').hasClass('btn-default').should.be.false; - tmpl.find('button').hasClass('btn-success').should.be.true; - - }); - }); - - it('should use disable readonly input fields, v3 style',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "properties": { - "name": { "type": "string", "readonly": true }, - "nick": { "type": "string" } - } - }; - - scope.form = ["*"]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - tmpl.children().length.should.be.equal(2); - tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').attr('disabled').should.be.equal('disabled'); - tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(1).children().eq(0).children('input').length.should.equal(1); - expect(tmpl.children().eq(1).children().eq(0).children('input').attr('disabled')).to.be.undefined; - }); - }); - - it('should use disable readonly input fields, v4 style',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "properties": { - "name": { "type": "string", "readOnly": true }, - "nick": { "type": "string" } - } - }; - - scope.form = ["*"]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(2); - tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').attr('disabled').should.be.equal('disabled'); - tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(1).children().eq(0).children('input').length.should.equal(1); - expect(tmpl.children().eq(1).children().eq(0).children('input').attr('disabled')).to.be.undefined; - }); - }); - - it('should use disable readonly input fields, form override',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "properties": { - "name": { "type": "string" }, - "nick": { "type": "string", "readOnly": true } - } - }; - - scope.form = [ - { key: 'name', readonly: true }, - { key: 'nick', readonly: false }, - ]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(2); - tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').attr('disabled').should.be.equal('disabled'); - tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(1).children().eq(0).children('input').length.should.equal(1); - expect(tmpl.children().eq(1).children().eq(0).children('input').attr('disabled')).to.be.undefined; - }); - }); - - it('should display custom validationMessages when specified',function(done){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "properties": { - "name": { - "type": "string", - "pattern": "^[a-z]+", - "validationMessage": "You are only allowed lower case letters in name." - }, - "nick": { - "type": "string", - "pattern": "^[a-z]+", - }, - } - }; - - scope.form = [ - "name", - { - key: 'nick', - validationMessage: 'Foobar' - } - ]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - tmpl.find('input').each(function(){ - $(this).scope().ngModel.$setViewValue('AÖ'); - }); - - var errors = tmpl.find('.help-block'); - - //timeout so we can do a second $apply - setTimeout(function(){ - $rootScope.$apply(); //this actually updates the view with error messages - errors.eq(0).text().should.be.equal("You are only allowed lower case letters in name."); - errors.eq(1).text().should.be.equal("Foobar"); - done(); - },0); - - }); - }); - - - it('should use ng-required on required fields',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "required": ["name"], - "properties": { - "name": { "type": "string" }, - "nick": { "type": "string" } - } - }; - - scope.form = ["*"]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(2); - tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model-options').should.be.equal('form.ngModelOptions') - tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model').should.be.equal('model[\'name\']'); - tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(1).children().eq(0).children('input').length.should.equal(1); - expect(tmpl.children().eq(1).children().eq(0).children('input').attr('required')).to.be.undefined; - }); - }); - - it('should use ng-required on required fields, json schema v3',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "properties": { - "name": { "type": "string", "required": true }, - "nick": { "type": "string" } - } - }; - - scope.form = ["*"]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(2); - tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model-options').should.be.equal('form.ngModelOptions') - tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model').should.be.equal('model[\'name\']'); - tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(1).children().eq(0).children('input').length.should.equal(1); - expect(tmpl.children().eq(1).children().eq(0).children('input').attr('required')).to.be.undefined; - }); - }); - - it('should use ng-required on required fields, form override',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "properties": { - "name": { "type": "string" }, - "nick": { "type": "string", "required": true } - } - }; - - scope.form = [ - { key: 'name', required: true }, - { key: 'nick', required: false }, - ]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(2); - tmpl.children().eq(0).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').is('input[type="text"]').should.be.true; - tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model-options').should.be.equal('form.ngModelOptions'); - tmpl.children().eq(0).children().eq(0).find('input').attr('ng-model').should.be.equal('model[\'name\']'); - tmpl.children().eq(1).children().eq(0).is('div.form-group').should.be.true; - tmpl.children().eq(1).children().eq(0).children('input').length.should.equal(1); - expect(tmpl.children().eq(1).children().eq(0).children('input').attr('required')).to.be.undefined; - }); - }); - - it('should honor defaults in schema',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = { - name: 'Foobar' - }; - - scope.schema = { - "type": "object", - "properties": { - "name": { - "type": "string", - "default": "Bar" - }, - "nick": { - "type": "string", - "default": "Zeb" - }, - "alias": { - "type": "string" - }, - } - }; - - scope.form = ["*"]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - scope.person.name.should.be.equal('Foobar'); - scope.person.nick.should.be.equal('Zeb'); - expect(scope.person.alias).to.be.undefined; - - }); - }); - - it('should handle schema form defaults in deep structure',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = { - name: 'Foobar' - }; - - scope.schema = { - "type": "object", - "properties": { - "props" : { - "type": "object", - "title": "Person", - "properties": { - "name": { - "type": "string", - "title": "Name" - }, - "nick": { - "type": "string", - "title": "Nick" - }, - "alias": { - "type": "string", - "title": "Alias" - } - } - } - } - }; - - //The form defines a fieldset for person, and changes the order of fields - //but titles should come from the schema - scope.form = [{ - type: 'fieldset', - key: 'props', - items: [ - 'props.nick', - 'props.name', - 'props.alias' - ] - }]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.eq(1); - var labels = tmpl.children().children().find('label'); - labels.eq(0).text().should.equal('Nick'); - labels.eq(1).text().should.equal('Name'); - labels.eq(2).text().should.equal('Alias'); - - }); - }); - - - it('should skip title if form says "notitle"',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = exampleSchema; - - scope.form = [{ - key: 'name', - notitle: true - },{ - key: 'gender', - notitle: true - }]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(2); - tmpl.children().eq(0).children().eq(0).find('label').hasClass('ng-hide').should.be.true; - tmpl.children().eq(1).children().eq(0).find('label').hasClass('ng-hide').should.be.true; - }); - }); - - - it('should generate checkboxes for arrays with enums',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "properties": { - "names": { - "type": "array", - "items": { - "type": "string", - "enum": ["foo","bar"] - } - } } - }; - - scope.form = [ - "names", - { key: "foobars", type: "checkboxes", titleMap:{ 'foo':'Foo','bar':'Bar'}} - ]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - //TODO: more asserts - tmpl.children().length.should.be.equal(2); - tmpl.children().eq(0).children().eq(0).find('input[type=checkbox]').length.should.be.eq(2); - }); - }); - - it('should initialize checkboxes to the model values',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = { - "names": ["foo"] - }; - - scope.schema = { - "type": "object", - "properties": { - "names": { - "type": "array", - "items": { - "type": "string", - "enum": ["foo"] - } - } } - }; - - scope.form = [ - "names", - { key: "foobars", type: "checkboxes", titleMap:{ 'foo':'Foo'} } - ]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().eq(0).find('input[type=checkbox]').prop('checked').should.be.true; - }); - }); - - it('should use radio buttons when they are wanted',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "properties": { - "names": { - "type": "string", - "enum": ["one","two"] - }, - "opts": { - "type": "string", - "enum": ["one","two"] - }, - } - }; - - scope.form = [ - { key: "names", type: "radios",titleMap: { one: "One", two: "The rest" }}, - { key: "opts", type: "radiobuttons",titleMap: { one: "One", two: "The rest" }} - ]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - //TODO: more asserts - - tmpl.children().length.should.be.equal(2); - tmpl.children().eq(0).children().eq(0).find('input[type=radio]').length.should.be.eq(2); - tmpl.children().eq(0).children().eq(0).find('.radio').length.should.be.eq(2); - tmpl.children().eq(1).children().eq(0).find('input[type=radio]').length.should.be.eq(2); - tmpl.children().eq(1).children().eq(0).find('.btn').length.should.be.eq(2); - - }); - }); - - it('should use radio buttons with HTML',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "properties": { - "names": { - "type": "string", - "enum": ["one","two"], - "description": "Cats are so cool.", - "title": "testlokol" - }, - "opts": { - "type": "string", - "enum": ["one","two"] - }, - "boxe": { - "type": "boolean", - "title": "whavre", - "description": "Cats are so cool." - }, - } - }; - - scope.form = [ - { key: "names", type: "radios",titleMap: { one: "onedirection", two: "
Baby spice
" }}, - { key: "opts", type: "radiobuttons",titleMap: { one: "One", two: "The rest" }}, - "boxe" - ]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.find('.spicegirls').length.should.be.equal(1); - tmpl.find('#testerish').length.should.be.equal(1); - tmpl.find('#bawkses').length.should.be.equal(1); - tmpl.find('#gh').length.should.be.equal(2); - - }); - }); - - it('should style radio buttons',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "properties": { - "opts": { - "type": "string", - "enum": ["one","two"] - }, - } - }; - - scope.form = [ - { - key: "opts", - type: "radiobuttons", - titleMap: [ - { value: "one", name: "One" }, - { value: "two", name: "The rest" } - ] - } - ]; - - var styles = { - any: {}, - both: { - selected: "btn-success", - unselected: "btn-default" - }, - onlySelected: { - selected: "btn-success" - }, - onlyUnselected: { - unselected: "btn-default" - } - }; - - //Radiobuttons uninitialized and default styles - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.true; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.false; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.true; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; - - //Radiobuttons uninitialized and both styles - var tmpl = angular.element('
'); - scope.form[0].style = styles.both; - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.false; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.true; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.true; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; - - //Radiobuttons uninitialized and only selected style - var tmpl = angular.element('
'); - scope.form[0].style = styles.onlySelected; - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.true; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.false; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.true; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; - - //Radiobuttons uninitialized and only unselected style - var tmpl = angular.element('
'); - scope.form[0].style = styles.onlyUnselected; - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.false; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.true; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.true; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; - - //Radiobuttons initialized and default styles - scope.person = { opts: "one" }; - var tmpl = angular.element('
'); - scope.form[0].style = ''; - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.true; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.false; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.true; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; - - //Radiobuttons initialized and both styles - var tmpl = angular.element('
'); - scope.form[0].style = styles.both; - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.false; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.false; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.true; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.true; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; - - //Radiobuttons initialized and only selected style - var tmpl = angular.element('
'); - scope.form[0].style = styles.onlySelected; - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.false; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.false; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.true; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.true; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; - - //Radiobuttons initialized and only unselected style - var tmpl = angular.element('
'); - scope.form[0].style = styles.onlyUnselected; - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-primary').should.be.true; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-default').should.be.false; - tmpl.children().eq(0).find('.btn').eq(0).hasClass('btn-success').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-primary').should.be.false; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-default').should.be.true; - tmpl.children().eq(0).find('.btn').eq(1).hasClass('btn-success').should.be.false; - - }); - }); - - it('should handle a simple div when type "section" is specified',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = exampleSchema; - - scope.form = [{ - type: "section", - items: [ - { - key: 'name', - notitle: true - }, - { - key: 'gender', - notitle: true - } - ] - }]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.children().eq(0).children().eq(0).is('div').should.be.true; - tmpl.children().eq(0).children().eq(0).hasClass('btn-group').should.be.false; - tmpl.children().eq(0).children().eq(0).children().length.should.be.eq(2); - }); - }); - - it('should handle a simple div with a condition if "conditional" is specified',function(done){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = { show: false }; - - scope.schema = exampleSchema; - - scope.form = [{ - type: "conditional", - condition: "person.show", - items: [ - { - key: 'name', - notitle: true - }, - { - key: 'gender', - notitle: true - } - ] - }]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.children().eq(0).children().length.should.be.equal(0); - - //Do a setTimeout so we kan do another $apply - setTimeout(function(){ - scope.person.show = true; - scope.$apply(); - tmpl.children().length.should.be.equal(1); - tmpl.children().eq(0).children().eq(0).is('div').should.be.true; - tmpl.children().eq(0).children().eq(0).hasClass('btn-group').should.be.false; - tmpl.children().eq(0).children().eq(0).children().length.should.be.eq(2); - done(); - },10); - - }); - }); - - - - - it('should handle "action" groups, same as "section" but with a bootstrap class "btn-group"',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = exampleSchema; - - scope.form = [{ - type: "actions", - items: [ - { - type: 'submit', - title: 'yes' - }, - { - type: 'button', - title: 'no' - } - ] - }]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.children().eq(0).children().eq(0).is('div').should.be.true; - tmpl.children().eq(0).children().eq(0).hasClass('btn-group').should.be.true; - tmpl.children().eq(0).children().eq(0).children().length.should.be.eq(2); - tmpl.children().eq(0).children().eq(0).children().eq(0).is('input').should.be.true; - tmpl.children().eq(0).children().eq(0).children().eq(1).is('button').should.be.true; - }); - }); - - it('should style "action" groups',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = exampleSchema; - - scope.form = [{ - type: "actions", - items: [ - { - type: 'submit', - title: 'yes1' - }, - { - type: 'button', - title: 'no1' - }, - { - type: 'submit', - style: 'btn-success', - title: 'yes2' - }, - { - type: 'button', - style: 'btn-danger', - title: 'no2' - } - ] - }]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(1); - tmpl.children().eq(0).children().length.should.be.equal(1); - tmpl.children().eq(0).children().eq(0).children().length.should.be.eq(4); - tmpl.children().eq(0).children().eq(0).children().eq(0).hasClass('btn-primary').should.be.true; - tmpl.children().eq(0).children().eq(0).children().eq(0).hasClass('btn-success').should.be.false; - tmpl.children().eq(0).children().eq(0).children().eq(1).hasClass('btn-default').should.be.true; - tmpl.children().eq(0).children().eq(0).children().eq(1).hasClass('btn-danger').should.be.false; - tmpl.children().eq(0).children().eq(0).children().eq(2).hasClass('btn-primary').should.be.false; - tmpl.children().eq(0).children().eq(0).children().eq(2).hasClass('btn-success').should.be.true; - tmpl.children().eq(0).children().eq(0).children().eq(3).hasClass('btn-default').should.be.false; - tmpl.children().eq(0).children().eq(0).children().eq(3).hasClass('btn-danger').should.be.true; - - - - }); - }); - - it('should render custom html when type "help" is specified',function(){ - - //We don't need no sanitation. We don't need no though control. - module(function($sceProvider){ - $sceProvider.enabled(false); - }); - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = { }; - - scope.schema = { - type: "object", - properties: { - name: { - type: "string", - } - } - }; - - - scope.form = [ - { - type: "help", - helpvalue: "

Yo Ninja!

" - }, - "name" - ]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.eq(2); - tmpl.children().eq(0).children().eq(0).is('div').should.be.true; - tmpl.children().eq(0).children().eq(0).children().length.should.eq(1); - tmpl.children().eq(0).children().eq(0).children().html().should.be.eq("Yo Ninja!"); - - }); - }); - - it('should render tabs with items in them when specified',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = { }; - - scope.schema = { - type: "object", - properties: { - name: { type: "string", title: "Name" }, - alias: { type: "string", title: "Alias" }, - nick: { type: "string", title: "Nickname" }, - tag: { type: "string", title: "Tag" }, - } - }; - - scope.form = [ - { - type: "tabs", - tabs: [ - { - title: "Tab 1", - items: [ - "name", - "tag" - ] - }, - { - title: "Tab 2", - items: [ - "alias", - "nick" - ] - } - ] - }, - ]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.eq(1); - var tabs = tmpl.children().children().eq(0).children().eq(0); - var panes = tmpl.children().children().eq(0).children().eq(1); - - tabs.is('ul').should.be.true; - tabs.children().length.should.be.eq(2); - tabs.children().eq(0).children().html().should.equal('Tab 1'); - tabs.children().eq(1).children().html().should.equal('Tab 2'); - - panes.is('div').should.be.true; - - panes.children().length.should.be.eq(2); - panes.children().eq(0).children().length.should.be.eq(2); - panes.children().eq(0).children().eq(0).find('label').html().should.eq('Name'); - panes.children().eq(0).children().eq(1).find('label').html().should.eq('Tag'); - - panes.children().eq(1).children().length.should.be.eq(2); - panes.children().eq(1).children().eq(0).find('label').html().should.eq('Alias'); - panes.children().eq(1).children().eq(1).find('label').html().should.eq('Nickname'); - - }); - }); - - - it('should render a list of subforms when schema type is array',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "properties": { - "names": { - "type": "array", - "items": { - "type": "string", - "title": "Name" - } - }, - "subforms": { - "type": "array", - "items": { - "type": "object", - "title": "subform", - "properties": { - "one": { "type": "string" }, - "two": { "type": "number", "title": "Two" } - } - } - }, - "subsubforms": { - "type": "array", - "items": { - "type": "object", - "title": "subform", - "properties": { - "one": { "type": "string" }, - "list": { - "type": "array", - "items": { - "type": "number", - "title": "sublist numbers" - } - } - } - } - } - } - }; - - scope.form = [ - "names", - { - key: "subforms", - type: "array", - items: [ - "subforms[].one" - ] - }, - "subsubforms" - ]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - //TODO: more asserts - tmpl.children().length.should.be.equal(3); - tmpl.children().eq(0).children().eq(0).find('input').length.should.be.eq(1); - tmpl.children().eq(0).children().eq(0).find('button').length.should.be.eq(2); - tmpl.children().eq(0).children().eq(0).find('button').eq(1).text().trim().should.be.eq('Add'); - - tmpl.children().eq(1).children().eq(0).find('input').length.should.be.eq(1); - tmpl.children().eq(1).children().eq(0).find('fieldset').length.should.be.eq(0); - tmpl.children().eq(1).children().eq(0).find('button').length.should.be.eq(2); - tmpl.children().eq(1).children().eq(0).find('button').eq(1).text().trim().should.be.eq('Add'); - - tmpl.children().eq(2).children().eq(0).find('input').length.should.be.eq(2); - tmpl.children().eq(2).children().eq(0).find('fieldset').length.should.be.eq(1); - tmpl.children().eq(2).children().eq(0).find('button').length.should.be.eq(4); - tmpl.children().eq(2).children().eq(0).find('button').eq(3).text().trim().should.be.eq('Add'); - - - }); - }); - - it('should style an array',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "properties": { - "names": { - "type": "array", - "items": { - "type": "string", - "title": "Name" - } - }, - "subforms": { - "type": "array", - "items": { - "type": "object", - "title": "subform", - "properties": { - "one": { "type": "string" }, - "two": { "type": "number", "title": "Two" } - } - } - }, - "subsubforms": { - "type": "array", - "items": { - "type": "object", - "title": "subform", - "properties": { - "one": { "type": "string" }, - "list": { - "type": "array", - "items": { - "type": "number", - "title": "sublist numbers" - } - } - } - } - } - } - }; - - scope.form = [ - { - key: "names", - add: "New" - }, - { - key: "subforms", - add: "New", - style: { add: "btn-info" }, - type: "array", - items: [ - "subforms[].one" - ] - }, - "subsubforms" - ]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(3); - tmpl.children().eq(0).find('button').eq(1).text().trim().should.be.eq('New'); - tmpl.children().eq(0).find('button').eq(1).hasClass('btn-default').should.be.true; - tmpl.children().eq(0).find('button').eq(1).hasClass('btn-info').should.be.false; - tmpl.children().eq(1).find('button').eq(1).text().trim().should.be.eq('New'); - tmpl.children().eq(1).find('button').eq(1).hasClass('btn-default').should.be.false; - tmpl.children().eq(1).find('button').eq(1).hasClass('btn-info').should.be.true; - tmpl.children().eq(2).find('button').eq(3).text().trim().should.be.eq('Add'); - tmpl.children().eq(2).find('button').eq(3).hasClass('btn-default').should.be.true; - tmpl.children().eq(2).find('button').eq(3).hasClass('btn-info').should.be.false; - - }); - }); - - it('should render a tabarray of subforms when asked',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = { - names: ['me','you','another'] - }; - - scope.schema = { - "type": "object", - "properties": { - "names": { - "type": "array", - "items": { - "type": "string", - "title": "Name" - } - }, - "subforms": { - "type": "array", - "items": { - "type": "object", - "title": "subform", - "properties": { - "one": { "type": "string" }, - "two": { "type": "number", "title": "Two" } - } - } - } - } - }; - - scope.form = [ - { key: "names", type: "tabarray" }, - { - key: "subforms", - type: "tabarray", - tabType: "right", - items: [ - "subforms[].one" - ] - } - ]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - //TODO: more asserts - tmpl.children().length.should.be.equal(2); - tmpl.children().eq(0).children().eq(0).find('input').length.should.be.eq(3); - tmpl.children().eq(0).children().eq(0).find('button').length.should.be.eq(3); - tmpl.children().eq(0).children().eq(0).find('button').eq(0).text().trim().should.be.eq('Remove'); - tmpl.children().eq(0).children().eq(0).is('div').should.be.true; - tmpl.children().eq(0).children().eq(0).attr('sf-array').should.be.thruthy; - tmpl.children().eq(0).children().eq(0).find('.tabs-left').length.should.be.eq(1); - - tmpl.children().eq(1).children().eq(0).find('input').length.should.be.eq(1); - tmpl.children().eq(1).children().eq(0).find('fieldset').length.should.be.eq(0); - tmpl.children().eq(1).children().eq(0).find('button').length.should.be.eq(1); - tmpl.children().eq(1).children().eq(0).find('button').text().trim().should.be.eq('Remove'); - tmpl.children().eq(1).children().eq(0).attr('sf-array').should.be.thruthy; - tmpl.children().eq(1).children().eq(0).find('.tabs-left').length.should.be.eq(0); - tmpl.children().eq(1).children().eq(0).find('.tabs-right').length.should.be.eq(1); - - }); - }); - - it('should style a tabarray',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = { - names: ['me','you','another'] - }; - - scope.schema = { - "type": "object", - "properties": { - "names": { - "type": "array", - "items": { - "type": "string", - "title": "Name" - } - }, - "subforms": { - "type": "array", - "items": { - "type": "object", - "title": "subform", - "properties": { - "one": { "type": "string" }, - "two": { "type": "number", "title": "Two" } - } - } - } - } - }; - - scope.form = [ - { - key: "names", - type: "tabarray", - add: "New", - style: { remove: "btn-danger" }, - }, - { - key: "subforms", - type: "tabarray", - remove: "Delete", - tabType: "right", - items: [ - "subforms[].one" - ] - } - ]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().length.should.be.equal(2); - tmpl.children().eq(0).find('button').eq(0).text().trim().should.be.eq('Remove'); - tmpl.children().eq(0).find('button').eq(0).hasClass('btn-default').should.be.false; - tmpl.children().eq(0).find('button').eq(0).hasClass('btn-danger').should.be.true; - tmpl.children().eq(0).find('li:not([ng-repeat]) > a').text().trim().should.be.eq('New'); - - tmpl.children().eq(1).find('button').text().trim().should.be.eq('Delete'); - tmpl.children().eq(1).find('button').eq(0).hasClass('btn-default').should.be.true; - tmpl.children().eq(1).find('button').eq(0).hasClass('btn-danger').should.be.false; - tmpl.children().eq(1).find('li:not([ng-repeat]) > a').text().trim().should.be.eq('Add'); - - }); - }); - - it('should sort select options by enum',function(){ - - inject(function($compile,$rootScope){ - var scope = $rootScope.$new(); - scope.person = {}; - - scope.schema = { - "type": "object", - "properties": { - "thing": { - "type": "string", - "title": "Thing", - "enum": [ - // Intentionally non-alphabetical - // https://github.com/Textalk/angular-schema-form/issues/82 - // https://github.com/Textalk/angular-schema-form/issues/83 - "b", - "a" - ], - "enumNames": { - // Intentionally not the same order as the `enum` - "a": "The A", - "b": "The B" - } - } - } - }; - - scope.form = ["*"]; - - var tmpl = angular.element('
'); - - $compile(tmpl)(scope); - $rootScope.$apply(); - - tmpl.children().eq(0).find('select').eq(0).find('option').eq(0).text().trim().should.be.eq(''); - tmpl.children().eq(0).find('select').eq(0).find('option').eq(1).text().trim().should.be.eq('The B'); - tmpl.children().eq(0).find('select').eq(0).find('option').eq(2).text().trim().should.be.eq('The A'); - }); - }); - - }); -}); diff --git a/test/service-test.js b/test/service-test.js index df4b6f28f..5000526a9 100644 --- a/test/service-test.js +++ b/test/service-test.js @@ -1,3 +1,5 @@ +chai.should(); + describe('service',function(){ beforeEach(module('templates')); beforeEach(module('schemaForm')); From 6505f06fbc0ba9a6495098706c8063a64f05da7c Mon Sep 17 00:00:00 2001 From: Cameron Edwards Date: Tue, 9 Sep 2014 16:39:48 -0400 Subject: [PATCH 4/8] Move schemaForm service test into test/services --- karma.conf.js | 2 +- test/service-test.js | 420 ------------------------------ test/services/schema-form-test.js | 417 +++++++++++++++++++++++++++++ 3 files changed, 418 insertions(+), 421 deletions(-) delete mode 100644 test/service-test.js create mode 100644 test/services/schema-form-test.js diff --git a/karma.conf.js b/karma.conf.js index 050bc1279..dba750f99 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -25,7 +25,7 @@ module.exports = function(config) { 'src/directives/*.js', 'src/directives/decorators/bootstrap/*.js', 'src/**/*.html', - 'test/service-test.js', + 'test/services/schema-form-test.js', 'test/decorator-factory-service-test.js', 'test/directive-test.js', ], diff --git a/test/service-test.js b/test/service-test.js deleted file mode 100644 index 5000526a9..000000000 --- a/test/service-test.js +++ /dev/null @@ -1,420 +0,0 @@ -chai.should(); - -describe('service',function(){ - beforeEach(module('templates')); - beforeEach(module('schemaForm')); - - it('should generate default form def from a schema',function(){ - inject(function(schemaForm){ - - var schema = { - "type": "object", - "properties": { - "name": { - "title": "Name", - "description": "Gimme yea name lad", - "type": "string" - }, - "gender": { - "title": "Choose", - "type": "string", - "enum": [ - "undefined", - "null", - "NaN", - ] - }, - "overEighteen": { - "title": "Are you over 18 years old?", - "type": "boolean", - "default": false - }, - "attributes": { - "type": "object", - "required": ['eyecolor'], - "properties": { - "eyecolor": { "type": "string", "title": "Eye color" }, - "haircolor": { "type": "string", "title": "Hair color" }, - "shoulders": { - "type": "object", - "title": "Shoulders", - "properties": { - "left": { "type": "string" }, - "right": { "type": "string" }, - } - } - } - } - } - }; - - var form = [ - { - "title": "Name", - "description": "Gimme yea name lad", - "schema": { - "title": "Name", - "description": "Gimme yea name lad", - "type": "string" - }, - "ngModelOptions": {}, - "key": [ - "name" - ], - "type": "text" - }, - { - "title": "Choose", - "schema": { - "title": "Choose", - "type": "string", - "enum": [ - "undefined", - "null", - "NaN" - ] - }, - "ngModelOptions": {}, - "key": [ - "gender" - ], - "type": "select", - "titleMap": [ - { - "name": "undefined", - "value": "undefined" - }, - { - "name": "null", - "value": "null" - }, - { - "name": "NaN", - "value": "NaN" - } - ] - }, - { - "title": "Are you over 18 years old?", - "schema": { - "title": "Are you over 18 years old?", - "type": "boolean", - "default": false - }, - "ngModelOptions": {}, - "key": [ - "overEighteen" - ], - "type": "checkbox" - }, - { - "title": "attributes", - "schema": { - "type": "object", - "required": [ - "eyecolor" - ], - "properties": { - "eyecolor": { - "type": "string", - "title": "Eye color" - }, - "haircolor": { - "type": "string", - "title": "Hair color" - }, - "shoulders": { - "type": "object", - "title": "Shoulders", - "properties": { - "left": { - "type": "string" - }, - "right": { - "type": "string" - } - } - } - } - }, - "ngModelOptions": {}, - "type": "fieldset", - "items": [ - { - "title": "Eye color", - "required": true, - "schema": { - "type": "string", - "title": "Eye color" - }, - "ngModelOptions": {}, - "key": [ - "attributes", - "eyecolor" - ], - "type": "text" - }, - { - "title": "Hair color", - "schema": { - "type": "string", - "title": "Hair color" - }, - "ngModelOptions": {}, - "key": [ - "attributes", - "haircolor" - ], - "type": "text" - }, - { - "title": "Shoulders", - "schema": { - "type": "object", - "title": "Shoulders", - "properties": { - "left": { - "type": "string" - }, - "right": { - "type": "string" - } - } - }, - "ngModelOptions": {}, - "type": "fieldset", - "items": [ - { - "title": "left", - "schema": { - "type": "string" - }, - "ngModelOptions": {}, - "key": [ - "attributes", - "shoulders", - "left" - ], - "type": "text" - }, - { - "title": "right", - "schema": { - "type": "string" - }, - "ngModelOptions": {}, - "key": [ - "attributes", - "shoulders", - "right" - ], - "type": "text" - } - ] - } - ] - } - ]; - - - var f = schemaForm.defaults(schema); - f.form.should.be.deep.equal(form); - - }); - }); - - it('should handle global defaults',function(){ - inject(function(schemaForm){ - - var schema = { - "type": "object", - "properties": { - "name": { - "title": "Name", - "description": "Gimme yea name lad", - "type": "string" - } - } - }; - - var form = [ - { - "title": "Name", - "description": "Gimme yea name lad", - "schema": { - "title": "Name", - "description": "Gimme yea name lad", - "type": "string" - }, - "ngModelOptions": { "updateOn": "blur"}, - "foo": "bar", - "key": [ - "name" - ], - "type": "text" - } - ]; - - var f = schemaForm.defaults(schema,{},{ formDefaults: { foo: "bar", ngModelOptions: { updateOn: 'blur' }}}); - f.form.should.be.deep.equal(form); - - }); - }); - - - - it('should be extendable with new defaults',function(){ - module(function(schemaFormProvider){ - schemaFormProvider.prependRule('string',function(name,schema,options){ - if (schema.format === 'foobar') { - var f = schemaFormProvider.createStandardForm(name,schema,options); - f.type = 'foobar'; - return f; - } - }); - - schemaFormProvider.appendRule('string',function(name,schema,options){ - var f = schemaFormProvider.createStandardForm(name,schema,options); - f.type = 'notused'; - return f; - }); - }); - - inject(function(schemaForm){ - - var schema = { - "type": "object", - "properties": { - "name": { - "title": "Name", - "format": "foobar", - "description": "Gimme yea name lad", - "type": "string" - }, - "gender": { - "title": "Choose", - "type": "string", - "enum": [ - "undefined", - "null", - "NaN", - ] - } - } - }; - - //no form is implicitly ['*'] - var defaults = schemaForm.defaults(schema).form; - defaults[0].type.should.be.equal('foobar'); - defaults[0].title.should.be.equal('Name'); - defaults[1].type.should.be.equal('select'); - defaults[1].title.should.be.equal('Choose'); - - }); - }); - - it('should be enable post-processing of forms',function(){ - module(function(schemaFormProvider){ - schemaFormProvider.postProcess(function(form){ - form.postProcess = true; - form.length.should.be.eq(1); - form[0].title.should.be.eq('Name'); - return form; - }); - - }); - - inject(function(schemaForm){ - - var schema = { - "type": "object", - "properties": { - "name": { - "title": "Name", - "format": "foobar", - "description": "Gimme yea name lad", - "type": "string" - } - } - }; - - var form = schemaForm.merge(schema,["name"]); - form.postProcess.should.be.true; - - }); - }); - - - it('should ignore parts of schema in ignore list',function(){ - inject(function(schemaForm){ - - var schema = { - "type": "object", - "properties": { - "name": { - "title": "Name", - "description": "Gimme yea name lad", - "type": "string" - }, - "gender": { - "title": "Choose", - "type": "string", - "enum": [ - "undefined", - "null", - "NaN", - ] - } - } - }; - - //no form is implicitly ['*'] - var defaults = schemaForm.defaults(schema).form; - schemaForm.merge(schema,["*"],{gender:true}).should.be.deep.equal([defaults[0]]); - }); - }); - - - it('should merge schema and form def',function(){ - inject(function(schemaForm){ - - var schema = { - "type": "object", - "properties": { - "name": { - "title": "Name", - "description": "Gimme yea name lad", - "type": "string" - }, - "gender": { - "title": "Choose", - "type": "string", - "enum": [ - "undefined", - "null", - "NaN", - ] - } - } - }; - - //no form is implicitly ['*'] - var defaults = schemaForm.defaults(schema).form; - schemaForm.merge(schema).should.be.deep.equal(defaults); - schemaForm.merge(schema,['*']).should.be.deep.equal(defaults); - schemaForm.merge(schema,['*',{type:'fieldset'}]).should.be.deep.equal(defaults.concat([{type:'fieldset'}])); - - //simple form - schemaForm.merge(schema,['gender']).should.be.deep.equal([defaults[1]]); - schemaForm.merge(schema,['gender','name']).should.be.deep.equal([defaults[1],defaults[0]]); - - //change it up - var f = angular.copy(defaults[0]); - f.title = 'Foobar'; - f.type = 'password'; - schemaForm.merge(schema,[{ key: 'name',title: 'Foobar',type: 'password'}]).should.be.deep.equal([f]); - - }); - }); - -}); \ No newline at end of file diff --git a/test/services/schema-form-test.js b/test/services/schema-form-test.js new file mode 100644 index 000000000..c9d125cf9 --- /dev/null +++ b/test/services/schema-form-test.js @@ -0,0 +1,417 @@ +chai.should(); + +describe('schemaForm', function() { + beforeEach(module('schemaForm')); + + describe('#defaults()', function() { + it('should generate default form def from a schema',function(){ + inject(function(schemaForm){ + var schema = { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "Gimme yea name lad", + "type": "string" + }, + "gender": { + "title": "Choose", + "type": "string", + "enum": [ + "undefined", + "null", + "NaN", + ] + }, + "overEighteen": { + "title": "Are you over 18 years old?", + "type": "boolean", + "default": false + }, + "attributes": { + "type": "object", + "required": ['eyecolor'], + "properties": { + "eyecolor": { "type": "string", "title": "Eye color" }, + "haircolor": { "type": "string", "title": "Hair color" }, + "shoulders": { + "type": "object", + "title": "Shoulders", + "properties": { + "left": { "type": "string" }, + "right": { "type": "string" }, + } + } + } + } + } + }; + + var form = [ + { + "title": "Name", + "description": "Gimme yea name lad", + "schema": { + "title": "Name", + "description": "Gimme yea name lad", + "type": "string" + }, + "ngModelOptions": {}, + "key": [ + "name" + ], + "type": "text" + }, + { + "title": "Choose", + "schema": { + "title": "Choose", + "type": "string", + "enum": [ + "undefined", + "null", + "NaN" + ] + }, + "ngModelOptions": {}, + "key": [ + "gender" + ], + "type": "select", + "titleMap": [ + { + "name": "undefined", + "value": "undefined" + }, + { + "name": "null", + "value": "null" + }, + { + "name": "NaN", + "value": "NaN" + } + ] + }, + { + "title": "Are you over 18 years old?", + "schema": { + "title": "Are you over 18 years old?", + "type": "boolean", + "default": false + }, + "ngModelOptions": {}, + "key": [ + "overEighteen" + ], + "type": "checkbox" + }, + { + "title": "attributes", + "schema": { + "type": "object", + "required": [ + "eyecolor" + ], + "properties": { + "eyecolor": { + "type": "string", + "title": "Eye color" + }, + "haircolor": { + "type": "string", + "title": "Hair color" + }, + "shoulders": { + "type": "object", + "title": "Shoulders", + "properties": { + "left": { + "type": "string" + }, + "right": { + "type": "string" + } + } + } + } + }, + "ngModelOptions": {}, + "type": "fieldset", + "items": [ + { + "title": "Eye color", + "required": true, + "schema": { + "type": "string", + "title": "Eye color" + }, + "ngModelOptions": {}, + "key": [ + "attributes", + "eyecolor" + ], + "type": "text" + }, + { + "title": "Hair color", + "schema": { + "type": "string", + "title": "Hair color" + }, + "ngModelOptions": {}, + "key": [ + "attributes", + "haircolor" + ], + "type": "text" + }, + { + "title": "Shoulders", + "schema": { + "type": "object", + "title": "Shoulders", + "properties": { + "left": { + "type": "string" + }, + "right": { + "type": "string" + } + } + }, + "ngModelOptions": {}, + "type": "fieldset", + "items": [ + { + "title": "left", + "schema": { + "type": "string" + }, + "ngModelOptions": {}, + "key": [ + "attributes", + "shoulders", + "left" + ], + "type": "text" + }, + { + "title": "right", + "schema": { + "type": "string" + }, + "ngModelOptions": {}, + "key": [ + "attributes", + "shoulders", + "right" + ], + "type": "text" + } + ] + } + ] + } + ]; + + var f = schemaForm.defaults(schema); + f.form.should.be.deep.equal(form); + }); + }); + + it('should handle global defaults',function(){ + inject(function(schemaForm){ + + var schema = { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "Gimme yea name lad", + "type": "string" + } + } + }; + + var form = [ + { + "title": "Name", + "description": "Gimme yea name lad", + "schema": { + "title": "Name", + "description": "Gimme yea name lad", + "type": "string" + }, + "ngModelOptions": { "updateOn": "blur"}, + "foo": "bar", + "key": [ + "name" + ], + "type": "text" + } + ]; + + var f = schemaForm.defaults(schema,{},{ formDefaults: { foo: "bar", ngModelOptions: { updateOn: 'blur' }}}); + f.form.should.be.deep.equal(form); + }); + }); + + it('should ignore parts of schema in ignore list',function(){ + inject(function(schemaForm){ + + var schema = { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "Gimme yea name lad", + "type": "string" + }, + "gender": { + "title": "Choose", + "type": "string", + "enum": [ + "undefined", + "null", + "NaN", + ] + } + } + }; + + //no form is implicitly ['*'] + var defaults = schemaForm.defaults(schema).form; + schemaForm.merge(schema,["*"],{gender:true}).should.be.deep.equal([defaults[0]]); + }); + }); + }); + + describe('#appendRule() and #prependRule()', function() { + it('should extend with new defaults',function(){ + module(function(schemaFormProvider){ + schemaFormProvider.prependRule('string',function(name,schema,options){ + if (schema.format === 'foobar') { + var f = schemaFormProvider.createStandardForm(name,schema,options); + f.type = 'foobar'; + return f; + } + }); + + schemaFormProvider.appendRule('string',function(name,schema,options){ + var f = schemaFormProvider.createStandardForm(name,schema,options); + f.type = 'notused'; + return f; + }); + }); + + inject(function(schemaForm){ + + var schema = { + "type": "object", + "properties": { + "name": { + "title": "Name", + "format": "foobar", + "description": "Gimme yea name lad", + "type": "string" + }, + "gender": { + "title": "Choose", + "type": "string", + "enum": [ + "undefined", + "null", + "NaN", + ] + } + } + }; + + //no form is implicitly ['*'] + var defaults = schemaForm.defaults(schema).form; + defaults[0].type.should.be.equal('foobar'); + defaults[0].title.should.be.equal('Name'); + defaults[1].type.should.be.equal('select'); + defaults[1].title.should.be.equal('Choose'); + + }); + }); + }); + + describe('#postProcess()', function() { + it('should be enable post-processing of forms',function(){ + module(function(schemaFormProvider){ + schemaFormProvider.postProcess(function(form){ + form.postProcess = true; + form.length.should.be.eq(1); + form[0].title.should.be.eq('Name'); + return form; + }); + + }); + + inject(function(schemaForm){ + + var schema = { + "type": "object", + "properties": { + "name": { + "title": "Name", + "format": "foobar", + "description": "Gimme yea name lad", + "type": "string" + } + } + }; + + var form = schemaForm.merge(schema,["name"]); + form.postProcess.should.be.true; + + }); + }); + }); + + describe('#merge()', function() { + it('should merge schema and form def',function(){ + inject(function(schemaForm){ + var schema = { + "type": "object", + "properties": { + "name": { + "title": "Name", + "description": "Gimme yea name lad", + "type": "string" + }, + "gender": { + "title": "Choose", + "type": "string", + "enum": [ + "undefined", + "null", + "NaN", + ] + } + } + }; + + //no form is implicitly ['*'] + var defaults = schemaForm.defaults(schema).form; + schemaForm.merge(schema).should.be.deep.equal(defaults); + schemaForm.merge(schema,['*']).should.be.deep.equal(defaults); + schemaForm.merge(schema,['*',{type:'fieldset'}]).should.be.deep.equal(defaults.concat([{type:'fieldset'}])); + + //simple form + schemaForm.merge(schema,['gender']).should.be.deep.equal([defaults[1]]); + schemaForm.merge(schema,['gender','name']).should.be.deep.equal([defaults[1],defaults[0]]); + + //change it up + var f = angular.copy(defaults[0]); + f.title = 'Foobar'; + f.type = 'password'; + schemaForm.merge(schema,[{ key: 'name',title: 'Foobar',type: 'password'}]).should.be.deep.equal([f]); + + }); + }); + }); +}); \ No newline at end of file From ecce358850ead42f61b4082961fcc96c6c36be65 Mon Sep 17 00:00:00 2001 From: Cameron Edwards Date: Tue, 9 Sep 2014 16:42:40 -0400 Subject: [PATCH 5/8] Move decorators-test into test/services --- .../decorators-test.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{decorator-factory-service-test.js => services/decorators-test.js} (100%) diff --git a/test/decorator-factory-service-test.js b/test/services/decorators-test.js similarity index 100% rename from test/decorator-factory-service-test.js rename to test/services/decorators-test.js From 59b1c5a57198214e86a79494b0c3d9bd29a48c86 Mon Sep 17 00:00:00 2001 From: Cameron Edwards Date: Tue, 9 Sep 2014 16:44:11 -0400 Subject: [PATCH 6/8] Fix test path --- karma.conf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/karma.conf.js b/karma.conf.js index dba750f99..fb108906d 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -26,7 +26,7 @@ module.exports = function(config) { 'src/directives/decorators/bootstrap/*.js', 'src/**/*.html', 'test/services/schema-form-test.js', - 'test/decorator-factory-service-test.js', + 'test/services/decorators-test.js', 'test/directive-test.js', ], From e385a3e49da439872c2de66d5eb053f21f078478 Mon Sep 17 00:00:00 2001 From: Cameron Edwards Date: Tue, 9 Sep 2014 16:47:18 -0400 Subject: [PATCH 7/8] Make notation more unit-test-like --- test/services/decorators-test.js | 40 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/test/services/decorators-test.js b/test/services/decorators-test.js index 7e1f3fc08..cab6e77fa 100644 --- a/test/services/decorators-test.js +++ b/test/services/decorators-test.js @@ -1,29 +1,29 @@ chai.should(); -describe('decorator factory service',function(){ - beforeEach(module('templates')); +describe('schemaFormDecorators', function() { beforeEach(module('schemaForm')); - it('should enable you to create new decorator directives',function(){ - module(function(schemaFormDecoratorsProvider){ - schemaFormDecoratorsProvider.createDecorator('foobar',{ 'foo':'/bar.html' },[angular.noop]); - }); - - inject(function($rootScope,$compile,$templateCache){ - $templateCache.put('/bar.html','
YES
'); + describe('#createDecorator', function() { + it('should enable you to create new decorator directives',function(){ + module(function(schemaFormDecoratorsProvider){ + schemaFormDecoratorsProvider.createDecorator('foobar',{ 'foo':'/bar.html' },[angular.noop]); + }); - //Since our directive does a replace we need a wrapper to actually check the content. - var templateWithWrap = angular.element('
'); - var template = templateWithWrap.children().eq(0); + inject(function($rootScope,$compile,$templateCache){ + $templateCache.put('/bar.html','
YES
'); - $compile(template)($rootScope); - $rootScope.$apply(); - templateWithWrap.children().length.should.equal(1); - templateWithWrap.children().is('foobar').should.be.true; - templateWithWrap.children().eq(0).children().length.should.equal(1); - templateWithWrap.children().eq(0).children().is('div').should.be.true; - templateWithWrap.children().eq(0).children().hasClass('yes').should.be.true; + //Since our directive does a replace we need a wrapper to actually check the content. + var templateWithWrap = angular.element('
'); + var template = templateWithWrap.children().eq(0); + $compile(template)($rootScope); + $rootScope.$apply(); + templateWithWrap.children().length.should.equal(1); + templateWithWrap.children().is('foobar').should.be.true; + templateWithWrap.children().eq(0).children().length.should.equal(1); + templateWithWrap.children().eq(0).children().is('div').should.be.true; + templateWithWrap.children().eq(0).children().hasClass('yes').should.be.true; + }); }); }); -}); \ No newline at end of file +}); From 5029c096f7555b4542f294fefa49588976598d98 Mon Sep 17 00:00:00 2001 From: Cameron Edwards Date: Tue, 9 Sep 2014 16:59:20 -0400 Subject: [PATCH 8/8] Rename directive test to directive it is testing --- karma.conf.js | 2 +- .../schema-form-test.js} | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) rename test/{directive-test.js => directives/schema-form-test.js} (99%) diff --git a/karma.conf.js b/karma.conf.js index fb108906d..79b657762 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -27,7 +27,7 @@ module.exports = function(config) { 'src/**/*.html', 'test/services/schema-form-test.js', 'test/services/decorators-test.js', - 'test/directive-test.js', + 'test/directives/schema-form-test.js', ], // list of files to exclude diff --git a/test/directive-test.js b/test/directives/schema-form-test.js similarity index 99% rename from test/directive-test.js rename to test/directives/schema-form-test.js index 22ca872c2..ff87b7c77 100644 --- a/test/directive-test.js +++ b/test/directives/schema-form-test.js @@ -10,8 +10,6 @@ describe('directive',function(){ }) ); - - var exampleSchema = { "type": "object", "properties": { @@ -32,7 +30,6 @@ describe('directive',function(){ } }; - it('should generate html and compile it',function(){ inject(function($compile,$rootScope){ @@ -152,7 +149,6 @@ describe('directive',function(){ }); }); - it('should generate html and compile it, leaving existing inputs intact',function(){ inject(function($compile,$rootScope){ @@ -239,7 +235,6 @@ describe('directive',function(){ tmpl.children().eq(2).children().eq(0).find('button').click(); scope.form[1].onClick.should.have.beenCalledOnce; }); - }); it('should style submit buttons',function(){ @@ -438,7 +433,6 @@ describe('directive',function(){ }); }); - it('should use ng-required on required fields',function(){ inject(function($compile,$rootScope){ @@ -636,7 +630,6 @@ describe('directive',function(){ }); }); - it('should skip title if form says "notitle"',function(){ inject(function($compile,$rootScope){ @@ -664,7 +657,6 @@ describe('directive',function(){ }); }); - it('should generate checkboxes for arrays with enums',function(){ inject(function($compile,$rootScope){ @@ -1063,9 +1055,6 @@ describe('directive',function(){ }); }); - - - it('should handle "action" groups, same as "section" but with a bootstrap class "btn-group"',function(){ inject(function($compile,$rootScope){ @@ -1264,7 +1253,6 @@ describe('directive',function(){ }); }); - it('should render a list of subforms when schema type is array',function(){ inject(function($compile,$rootScope){