blob: c1387ff6adb5e173d62a23a6f21247e8359a6481 [file] [log] [blame]
Matteo Scandolo7bc39c42016-04-20 11:38:42 -07001/**
2 * © OpenCORD
3 *
4 * Created by teone on 4/18/16.
5 */
6
7(function () {
8 'use strict';
9
Matteo Scandolob9fb6252016-05-26 15:09:55 -070010 let element, scope, isolatedScope, rootScope, compile;
11
12 const compileElement = () => {
13
14 if(!scope){
15 scope = rootScope.$new();
16 }
17
18 element = angular.element(`<xos-form config="config" ng-model="model"></xos-form>`);
19 compile(element)(scope);
20 scope.$digest();
21 isolatedScope = element.isolateScope().vm;
22 }
23
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070024 describe('The xos.helper module', function(){
25
Matteo Scandolo6ba12872016-04-27 16:29:33 -070026 describe('The xos-form component', () => {
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070027
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070028
29 beforeEach(module('xos.helpers'));
30
Matteo Scandolob9fb6252016-05-26 15:09:55 -070031 beforeEach(inject(($compile, $rootScope) => {
32 rootScope = $rootScope;
33 compile = $compile;
34 }));
35
Matteo Scandolob6ca3012016-06-03 16:58:43 -070036 it('should throw an error if no config is specified', () => {
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070037 function errorFunctionWrapper(){
Matteo Scandolob9fb6252016-05-26 15:09:55 -070038 compileElement();
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070039 }
40 expect(errorFunctionWrapper).toThrow(new Error('[xosForm] Please provide a configuration via the "config" attribute'));
Matteo Scandolob6ca3012016-06-03 16:58:43 -070041 });
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070042
Matteo Scandolob6ca3012016-06-03 16:58:43 -070043 it('should throw an error if no actions is specified', () => {
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070044 function errorFunctionWrapper(){
Matteo Scandolob6ca3012016-06-03 16:58:43 -070045 scope = rootScope.$new();
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070046 scope.config = 'green';
Matteo Scandolob9fb6252016-05-26 15:09:55 -070047 compileElement();
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070048 }
49 expect(errorFunctionWrapper).toThrow(new Error('[xosForm] Please provide an action list in the configuration'));
Matteo Scandolob6ca3012016-06-03 16:58:43 -070050 });
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070051
52 describe('when correctly configured', () => {
53
54 let cb = jasmine.createSpy('callback');
55
Matteo Scandolob9fb6252016-05-26 15:09:55 -070056 beforeEach(inject(($rootScope) => {
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070057
58 scope = $rootScope.$new();
59
60 scope.config = {
61 exclude: ['excludedField'],
Matteo Scandolob3d686f2016-04-22 14:14:03 -070062 formName: 'testForm',
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070063 actions: [
64 {
65 label: 'Save',
66 icon: 'ok', // refers to bootstraps glyphicon
67 cb: cb,
68 class: 'success'
69 }
70 ],
Matteo Scandolo9f0e5ae2016-04-20 12:24:52 -070071 fields: {
72 first_name: {
73 label: 'Custom Label'
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070074 }
Matteo Scandolo9f0e5ae2016-04-20 12:24:52 -070075 }
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070076 };
77
78 scope.model = {
79 id: 1,
80 first_name: 'Jhon',
81 last_name: 'Snow',
82 age: 25,
Matteo Scandolo4ba4cf12016-04-20 16:36:17 -070083 email: 'test@onlab.us',
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070084 birthDate: '2016-04-18T23:44:16.883181Z',
85 enabled: true,
86 role: 'user', //select
87 a_permissions: [
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070088 ],
Matteo Scandolo974c0e42016-05-25 16:02:16 -070089 object_field: {
90 string: 'bar',
91 number: 1,
92 email: 'teo@onlab.us'
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070093 }
94 };
95
Matteo Scandolob9fb6252016-05-26 15:09:55 -070096 compileElement();
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070097 }));
98
99 it('should add excluded properties to the list', () => {
100 let expected = ['id', 'validators', 'created', 'updated', 'deleted', 'backend_status', 'excludedField'];
101 expect(isolatedScope.excludedField).toEqual(expected);
102 });
103
Matteo Scandolo03d8b8e2016-05-25 17:37:37 -0700104 it('should render 10 input field', () => {
Matteo Scandolo4ba4cf12016-04-20 16:36:17 -0700105 // boolean are in the form model, but are not input
106 expect(Object.keys(isolatedScope.formField).length).toEqual(9);
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700107 var field = element[0].getElementsByTagName('input');
Matteo Scandolo974c0e42016-05-25 16:02:16 -0700108 expect(field.length).toEqual(10);
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700109 });
110
Matteo Scandolo4ba4cf12016-04-20 16:36:17 -0700111 it('should render 1 boolean field', () => {
arpiagariu10bd9cb2016-06-10 13:28:34 -0700112 expect($(element).find('.boolean-field > a').length).toEqual(2)
Matteo Scandolo4ba4cf12016-04-20 16:36:17 -0700113 });
114
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700115 it('when clicking on action should invoke callback', () => {
Matteo Scandolo4ba4cf12016-04-20 16:36:17 -0700116 var link = $(element).find('[role="button"]');
arpiagariu10bd9cb2016-06-10 13:28:34 -0700117 //console.log(link);
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700118 link.click();
arpiagariu10bd9cb2016-06-10 13:28:34 -0700119 // TODO : Check correct parameters
120 expect(cb).toHaveBeenCalled();
121
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700122 });
123
124 it('should set a custom label', () => {
125 let nameField = element[0].getElementsByClassName('form-group')[0];
126 let label = angular.element(nameField.getElementsByTagName('label')[0]).text()
127 expect(label).toEqual('Custom Label:');
128 });
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700129
Matteo Scandolo6e2e6ff2016-04-20 14:59:39 -0700130 it('should use the correct input type', () => {
131 expect($(element).find('[name="age"]')).toHaveAttr('type', 'number');
132 expect($(element).find('[name="birthDate"]')).toHaveAttr('type', 'date');
Matteo Scandolo4ba4cf12016-04-20 16:36:17 -0700133 expect($(element).find('[name="email"]')).toHaveAttr('type', 'email');
134 });
135
arpiagariu10bd9cb2016-06-10 13:28:34 -0700136 xdescribe('the boolean field test', () => {
Matteo Scandolo4ba4cf12016-04-20 16:36:17 -0700137
138 let setFalse, setTrue;
139
140 beforeEach(() => {
141 setFalse= $(element).find('.boolean-field > button:first-child');
142 setTrue = $(element).find('.boolean-field > button:last-child');
143 });
144
145 it('should change value to false', () => {
146 expect(isolatedScope.ngModel.enabled).toEqual(true);
arpiagariu10bd9cb2016-06-10 13:28:34 -0700147 setFalse.click();
Matteo Scandolo4ba4cf12016-04-20 16:36:17 -0700148 expect(isolatedScope.ngModel.enabled).toEqual(false);
149 });
150
Matteo Scandolo974c0e42016-05-25 16:02:16 -0700151 it('should change value to true', () => {
Matteo Scandolo4ba4cf12016-04-20 16:36:17 -0700152 isolatedScope.ngModel.enabled = false;
153 scope.$apply();
154 expect(isolatedScope.ngModel.enabled).toEqual(false);
155 setTrue.click()
156 expect(isolatedScope.ngModel.enabled).toEqual(true);
157 });
Matteo Scandolo6e2e6ff2016-04-20 14:59:39 -0700158 });
Matteo Scandolob3d686f2016-04-22 14:14:03 -0700159
Matteo Scandolo6ba12872016-04-27 16:29:33 -0700160 // NOTE not sure why this tests are failing
161 xdescribe('the custom validation options', () => {
Matteo Scandolob3d686f2016-04-22 14:14:03 -0700162 beforeEach(() => {
163 scope.config.fields.first_name.validators = {
164 minlength: 10,
165 maxlength: 15,
166 required: true
167 };
168
Matteo Scandolo01c87572016-04-25 08:15:24 -0700169 scope.config.fields.age = {
170 validators: {
171 min: 10,
172 max: 20
173 }
174 };
175
Matteo Scandolob3d686f2016-04-22 14:14:03 -0700176 scope.$digest();
177 });
178
179 it('should validate required', () => {
180 scope.model.first_name = null;
181 scope.$digest();
182
183 expect(isolatedScope.testForm.first_name.$valid).toBeFalsy();
184 expect(isolatedScope.testForm.first_name.$error.required).toBeTruthy();
185 });
186
187 it('should validate minlength', () => {
188 scope.model.first_name = 'short';
189 scope.$digest();
190
191 expect(isolatedScope.testForm.first_name.$valid).toBeFalsy();
192 expect(isolatedScope.testForm.first_name.$error.minlength).toBeTruthy();
193 });
194
195 it('should validate maxlength', () => {
196 scope.model.first_name = 'this is way too long!';
197 scope.$digest();
198
199 expect(isolatedScope.testForm.first_name.$valid).toBeFalsy();
200 expect(isolatedScope.testForm.first_name.$error.maxlength).toBeTruthy();
201 });
Matteo Scandolo01c87572016-04-25 08:15:24 -0700202
Matteo Scandolo6ba12872016-04-27 16:29:33 -0700203 it('should validate min', () => {
Matteo Scandolo01c87572016-04-25 08:15:24 -0700204 // not validating min and max for now
205 scope.model.age = 8;
206 scope.$digest();
207
208 expect(isolatedScope.testForm.age.$valid).toBeFalsy();
209 expect(isolatedScope.testForm.age.$error.min).toBeTruthy();
210 });
Matteo Scandolob3d686f2016-04-22 14:14:03 -0700211 });
Matteo Scandolob9fb6252016-05-26 15:09:55 -0700212
213 describe('when a deep model is passed', () => {
214
215 beforeEach(inject(($rootScope) => {
216
217 scope = $rootScope.$new();
218
219 scope.config = {
220 exclude: ['excludedField'],
221 formName: 'testForm',
222 actions: [
223 {
224 label: 'Save',
225 icon: 'ok', // refers to bootstraps glyphicon
226 cb: cb,
227 class: 'success'
228 }
229 ],
230 fields: {
231 object_field: {
232 field_one: {
233 label: 'Custom Label'
234 }
235 }
236 }
237 };
238
239 scope.model = {
240 object_field: {
241 field_one: 'bar',
242 number: 1,
243 email: 'teo@onlab.us'
244 }
245 };
246
247 compileElement();
248 }));
249
250 it('should print nested field', () => {
251 expect($(element).find('input').length).toBe(3);
252 });
253
254 xit('should configure nested fields', () => {
255 let custom_label = $(element).find('input[name=field_one]').parent().find('label');
256 expect(custom_label.text()).toBe('Custom Label');
257 });
258 });
Matteo Scandolo6e2e6ff2016-04-20 14:59:39 -0700259 });
arpiagariu10bd9cb2016-06-10 13:28:34 -0700260 describe('when correctly configured for feedback', () => {
261
262 let cb = jasmine.createSpy('callback');
263
264 beforeEach(inject(($rootScope) => {
265
266 scope = $rootScope.$new();
267
268 scope.config = {
269 exclude: ['excludedField'],
270 formName: 'testForm',
271 feedback: {
272 show: false,
273 message: 'Form submitted successfully !!!',
274 type: 'success'
275 },
276 actions: [
277 {
278 label: 'Save',
279 icon: 'ok', // refers to bootstraps glyphicon
280 cb: cb,
281 class: 'success'
282 }
283 ],
284 fields: {
285 first_name: {
286 label: 'Custom Label'
287 }
288 }
289 };
290
291 scope.model = {
292 id: 1,
293 first_name: 'Jhon',
294 last_name: 'Snow',
295 age: 25,
296 email: 'test@onlab.us',
297 birthDate: '2016-04-18T23:44:16.883181Z',
298 enabled: true,
299 role: 'user', //select
300 a_permissions: [
301 ],
302 object_field: {
303 string: 'bar',
304 number: 1,
305 email: 'teo@onlab.us'
306 }
307 };
308
309 compileElement();
310 }));
311
312 it('should add excluded properties to the list', () => {
313 let expected = ['id', 'validators', 'created', 'updated', 'deleted', 'backend_status', 'excludedField'];
314 expect(isolatedScope.excludedField).toEqual(expected);
315 });
316
317 it('should render 10 input field', () => {
318 // boolean are in the form model, but are not input
319 expect(Object.keys(isolatedScope.formField).length).toEqual(9);
320 var field = element[0].getElementsByTagName('input');
321 expect(field.length).toEqual(10);
322 });
323
324 it('should render 1 boolean field', () => {
325 expect($(element).find('.boolean-field > a').length).toEqual(2)
326 });
327
328 it('when clicking on action should invoke callback', () => {
329 var link = $(element).find('[role="button"]');
330 //console.log(link);
331 link.click();
332 // TODO : Check correct parameters
333 expect(cb).toHaveBeenCalled();
334
335 });
336
337 it('should set a custom label', () => {
338 let nameField = element[0].getElementsByClassName('form-group')[0];
339 let label = angular.element(nameField.getElementsByTagName('label')[0]).text()
340 expect(label).toEqual('Custom Label:');
341 });
342
343 it('should use the correct input type', () => {
344 expect($(element).find('[name="age"]')).toHaveAttr('type', 'number');
345 expect($(element).find('[name="birthDate"]')).toHaveAttr('type', 'date');
346 expect($(element).find('[name="email"]')).toHaveAttr('type', 'email');
347 });
348
349
350
351 describe('A spy,configured with an alternate config implementation for Feedback', function() {
352 var feedbackParams, statusFlag, fetchedBar;
353
354 let fb = jasmine.createSpy('feedback').and.callFake(function(statusFlag) {
355 //console.log(statusFlag , '------------------------------------------------------');
356 if(statusFlag){
357 scope.config.feedback.show = true;
358 scope.config.feedback.message = 'Form Submitted';
359 scope.config.feedback.type = 'success';
360 }
361 else {
362 scope.config.feedback.show = true;
363 scope.config.feedback.message = 'Error';
364 scope.config.feedback.type = 'danger';
365
366 }
367 console.log(scope.config.feedback, '################################');
368
369
370
371 });
372
373 beforeEach(()=> {
374 scope = rootScope.$new();
375 scope.config =
376 {
377
378 feedback: {
379 show: false,
380 message: 'Form submitted successfully !!!',
381 type: 'success'
382 },
383 actions: [
384 {
385 label: 'Save',
386 icon: 'ok', // refers to bootstraps glyphicon
387 cb: cb,
388 class: 'success'
389 }
390 ]
391 };
392 scope.model={};
393 compileElement();
394 })
395
396 it('tracks that the spy was called', function() {
397 expect($(element).find('xos-alert > div')).toHaveClass('alert alert-success ng-hide');
398 scope.$digest();
399 fb(true);
400 scope.$digest();
401 expect(isolatedScope.config.feedback.type).toEqual('success');
402 expect(fb).toHaveBeenCalledWith(true);
403 expect($(element).find('xos-alert > div')).toHaveClass('alert alert-success');
404 fb(false);
405 scope.$digest();
406 expect(isolatedScope.config.feedback.type).toEqual('danger');
407 expect(fb).toHaveBeenCalledWith(false);
408 expect($(element).find('xos-alert > div')).toHaveClass('alert alert-danger');
409 });
410 });
411 xdescribe('the boolean field test', () => {
412
413 let setFalse, setTrue;
414
415 beforeEach(() => {
416 setFalse= $(element).find('.boolean-field > button:first-child');
417 setTrue = $(element).find('.boolean-field > button:last-child');
418 });
419
420 it('should change value to false', () => {
421 expect(isolatedScope.ngModel.enabled).toEqual(true);
422 setFalse.click();
423 expect(isolatedScope.ngModel.enabled).toEqual(false);
424 });
425
426 it('should change value to true', () => {
427 isolatedScope.ngModel.enabled = false;
428 scope.$apply();
429 expect(isolatedScope.ngModel.enabled).toEqual(false);
430 setTrue.click()
431 expect(isolatedScope.ngModel.enabled).toEqual(true);
432 });
433 });
434
435 // NOTE not sure why this tests are failing
436 xdescribe('the custom validation options', () => {
437 beforeEach(() => {
438 scope.config.fields.first_name.validators = {
439 minlength: 10,
440 maxlength: 15,
441 required: true
442 };
443
444 scope.config.fields.age = {
445 validators: {
446 min: 10,
447 max: 20
448 }
449 };
450
451 scope.$digest();
452 });
453
454 it('should validate required', () => {
455 scope.model.first_name = null;
456 scope.$digest();
457
458 expect(isolatedScope.testForm.first_name.$valid).toBeFalsy();
459 expect(isolatedScope.testForm.first_name.$error.required).toBeTruthy();
460 });
461
462 it('should validate minlength', () => {
463 scope.model.first_name = 'short';
464 scope.$digest();
465
466 expect(isolatedScope.testForm.first_name.$valid).toBeFalsy();
467 expect(isolatedScope.testForm.first_name.$error.minlength).toBeTruthy();
468 });
469
470 it('should validate maxlength', () => {
471 scope.model.first_name = 'this is way too long!';
472 scope.$digest();
473
474 expect(isolatedScope.testForm.first_name.$valid).toBeFalsy();
475 expect(isolatedScope.testForm.first_name.$error.maxlength).toBeTruthy();
476 });
477
478 it('should validate min', () => {
479 // not validating min and max for now
480 scope.model.age = 8;
481 scope.$digest();
482
483 expect(isolatedScope.testForm.age.$valid).toBeFalsy();
484 expect(isolatedScope.testForm.age.$error.min).toBeTruthy();
485 });
486 });
487
488 describe('when a deep model is passed', () => {
489
490 beforeEach(inject(($rootScope) => {
491
492 scope = $rootScope.$new();
493
494 scope.config = {
495 exclude: ['excludedField'],
496 formName: 'testForm',
497 actions: [
498 {
499 label: 'Save',
500 icon: 'ok', // refers to bootstraps glyphicon
501 cb: cb,
502 class: 'success'
503 }
504 ],
505 fields: {
506 object_field: {
507 field_one: {
508 label: 'Custom Label'
509 }
510 }
511 }
512 };
513
514 scope.model = {
515 object_field: {
516 field_one: 'bar',
517 number: 1,
518 email: 'teo@onlab.us'
519 }
520 };
521
522 compileElement();
523 }));
524
525 it('should print nested field', () => {
526 expect($(element).find('input').length).toBe(3);
527 });
528
529 xit('should configure nested fields', () => {
530 let custom_label = $(element).find('input[name=field_one]').parent().find('label');
531 expect(custom_label.text()).toBe('Custom Label');
532 });
533 });
534 });
535
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700536 });
537 });
538})();