blob: 1be9a43e5b338490bb6bc778942fd478bae71e80 [file] [log] [blame]
Matteo Scandolofb46ae62017-08-08 09:10:50 -07001
2/*
3 * Copyright 2017-present Open Networking Foundation
4
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8
9 * http://www.apache.org/licenses/LICENSE-2.0
10
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
Matteo Scandolob2225a02017-04-11 15:23:04 -070019import * as angular from 'angular';
20import * as $ from 'jquery';
21import 'angular-mocks';
22import {xosForm, IXosFormCfg, IXosFormInput} from './form';
23import {XosFormHelpers} from './form-helpers';
24import {xosField} from '../field/field';
25import {xosAlert} from '../alert/alert';
26
27describe('The Xos Form component', () => {
28
29 let element, scope, isolatedScope, rootScope, compile;
30
31 const compileElement = () => {
32
33 if (!scope) {
34 scope = rootScope.$new();
35 }
36
37 element = angular.element(`<xos-form config="config" ng-model="model"></xos-form>`);
38 compile(element)(scope);
39 scope.$digest();
40 isolatedScope = element.isolateScope().vm;
41 };
42
43 const MockConfigHelpers = {
44 toLabel: string => string
45 };
46
47 beforeEach(() => {
48
49 angular
50 .module('form', [])
51 .component('xosForm', xosForm)
52 .service('XosFormHelpers', XosFormHelpers)
53 .component('xosField', xosField) // NOTE does it make sense to mock it?
54 .component('xosAlert', xosAlert)
55 .value('ConfigHelpers', MockConfigHelpers);
56
57 angular.mock.module('form');
58
59 inject(($compile: ng.ICompileService, $rootScope: ng.IScope) => {
60 rootScope = $rootScope;
61 compile = $compile;
62 });
63 });
64
65 it('should throw an error if no config is specified', () => {
66 function errorFunctionWrapper() {
67 compileElement();
68 }
69 expect(errorFunctionWrapper).toThrow(new Error('[xosForm] Please provide a configuration via the "config" attribute'));
70 });
71
72 it('should throw an error if no actions are specified in config', () => {
73 function errorFunctionWrapper() {
74 scope = rootScope.$new();
75 scope.config = 'green';
76 compileElement();
77 }
78 expect(errorFunctionWrapper).toThrow(new Error('[xosForm] Please provide an action list in the configuration'));
79 });
80
81 it('should throw an error if no formName is specified in config', () => {
82 function errorFunctionWrapper() {
83 scope = rootScope.$new();
84 scope.config = {
85 actions: []
86 };
87 compileElement();
88 }
89 expect(errorFunctionWrapper).toThrow(new Error('[xosForm] Please provide a formName property in the config'));
90 });
91
92 describe('when correctly configured', () => {
93
94 let cb = jasmine.createSpy('callback');
95
96 beforeEach(inject(($rootScope) => {
97
98 scope = $rootScope.$new();
99
100 let inputs: IXosFormInput[] = [
101 {
102 name: 'id',
103 label: 'Id:',
104 type: 'number',
Matteo Scandolod67adee2018-03-08 16:27:05 -0800105 validators: {},
106 read_only: false
Matteo Scandolob2225a02017-04-11 15:23:04 -0700107 },
108 {
109 name: 'first_name',
110 label: 'Name:',
111 type: 'text',
Matteo Scandolod67adee2018-03-08 16:27:05 -0800112 validators: {},
113 read_only: false
Matteo Scandolob2225a02017-04-11 15:23:04 -0700114 },
115 {
116 name: 'email',
117 label: 'Mail:',
118 type: 'email',
Matteo Scandolo80056232017-07-10 16:24:41 -0700119 validators: {
120 required: true
Matteo Scandolod67adee2018-03-08 16:27:05 -0800121 },
122 read_only: false
Matteo Scandolob2225a02017-04-11 15:23:04 -0700123 },
124 {
125 name: 'birthDate',
126 label: 'DOB:',
127 type: 'date',
Matteo Scandolod67adee2018-03-08 16:27:05 -0800128 validators: {},
129 read_only: false
Matteo Scandolob2225a02017-04-11 15:23:04 -0700130 },
131 {
132 name: 'enabled',
133 label: 'Status:',
134 type: 'boolean',
Matteo Scandolod67adee2018-03-08 16:27:05 -0800135 validators: {},
136 read_only: false
Matteo Scandolob2225a02017-04-11 15:23:04 -0700137 },
138 {
139 name: 'role',
140 label: 'Role:',
141 type: 'select',
142 options: [
143 {id: 1, label: 'user'},
144 {id: 2, label: 'admin'}
145 ],
Matteo Scandolod67adee2018-03-08 16:27:05 -0800146 validators: {},
147 read_only: false
Matteo Scandolob2225a02017-04-11 15:23:04 -0700148 }
149 ];
150
151 let config: IXosFormCfg = {
152 formName: 'testForm',
153 actions: [
154 {
155 label: 'Save',
156 icon: 'ok',
157 cb: cb,
158 class: 'success'
159 }
160 ],
161 inputs: inputs
162 };
163
164 scope.config = config;
165
166 scope.model = {
167 id: 1,
168 first_name: 'Jhon',
169 email: 'test@onlab.us',
170 birthDate: new Date('2016-04-18T23:44:16.883181Z'),
171 enabled: true,
172 role: 1, // select
173 };
174
175 compileElement();
176 }));
177
178 it('should render 4 input field', () => {
179 // boolean and select are in the form model, but are not input
180 expect(Object.keys(isolatedScope.config.inputs).length).toEqual(6);
181 const htmlInputs = $('input', element);
182 expect(htmlInputs.length).toEqual(4);
183 });
184
185 it('should render 1 boolean field', () => {
186 expect($(element).find('.boolean-field > a').length).toEqual(2);
187 });
188
189 it('when clicking on action should invoke callback', () => {
190 const link = $(element).find('[role="button"]');
191 link.click();
192 // TODO : Check correct parameters
193 expect(cb).toHaveBeenCalled();
194
195 });
196
197 // TODO move in xosField test
198 it('should set a custom label', () => {
Matteo Scandolo80056232017-07-10 16:24:41 -0700199 let nameField = element[0].getElementsByClassName('form-group')[1];
Matteo Scandolob2225a02017-04-11 15:23:04 -0700200 let label = angular.element(nameField.getElementsByTagName('label')[0]).text();
Matteo Scandolo80056232017-07-10 16:24:41 -0700201 expect(label).toContain('Name:');
202 expect(label).not.toContain('*');
203 });
204
205 it('should print an * for required fields', () => {
206 let nameField = element[0].getElementsByClassName('form-group')[2];
207 let label = angular.element(nameField.getElementsByTagName('label')[0]).text();
208 expect(label).toContain('*');
Matteo Scandolob2225a02017-04-11 15:23:04 -0700209 });
210
211 // TODO move test in xos-field
212 xdescribe('the boolean field test', () => {
213
214 let setFalse, setTrue;
215
216 beforeEach(() => {
217 setFalse = $('.boolean-field > button:first-child', element);
218 setTrue = $('.boolean-field > button:last-child', element);
219 });
220
221 it('should change value to false', () => {
222 expect(isolatedScope.ngModel.enabled).toEqual(true);
223 setFalse.click();
224 expect(isolatedScope.ngModel.enabled).toEqual(false);
225 });
226
227 it('should change value to true', () => {
228 isolatedScope.ngModel.enabled = false;
229 scope.$apply();
230 expect(isolatedScope.ngModel.enabled).toEqual(false);
231 setTrue.click();
232 expect(isolatedScope.ngModel.enabled).toEqual(true);
233 });
234 });
235 });
236 describe('when correctly configured for feedback', () => {
237 // NOTE move this tests in xos-alert??
238 let fb = jasmine.createSpy('feedback').and.callFake(function(statusFlag: boolean) {
239 if (statusFlag) {
240 scope.config.feedback.show = true;
241 scope.config.feedback.message = 'Form Submitted';
242 scope.config.feedback.type = 'success';
243 }
244 else {
245 scope.config.feedback.show = true;
246 scope.config.feedback.message = 'Error';
247 scope.config.feedback.type = 'danger';
248 }
249 });
250
251 beforeEach(() => {
252 scope = rootScope.$new();
253 scope.config = {
254 formName: 'testForm',
255 feedback: {
256 show: false,
257 message: 'Form submitted successfully !!!',
258 type: 'success'
259 },
260 actions: [
261 {
262 label: 'Save',
263 icon: 'ok', // refers to bootstraps glyphicon
264 cb: () => null,
265 class: 'success'
266 }
267 ]
268 };
269 scope.model = {};
270 compileElement();
271 });
272
273 it('should not show feedback when loaded', () => {
274 expect($(element).find('xos-alert > div')).toHaveClass('alert alert-success ng-hide');
275 });
276
277 it('should show a success feedback', () => {
278 fb(true);
279 scope.$digest();
280 expect(isolatedScope.config.feedback.type).toEqual('success');
281 expect(fb).toHaveBeenCalledWith(true);
282 expect($(element).find('xos-alert > div')).toHaveClass('alert alert-success');
283 });
284
285 it('should show an error feedback', function() {
286 fb(false);
287 scope.$digest();
288 expect(isolatedScope.config.feedback.type).toEqual('danger');
289 expect(fb).toHaveBeenCalledWith(false);
290 expect($(element).find('xos-alert > div')).toHaveClass('alert alert-danger');
291 });
292 });
293});