blob: e0180b616ce064bd209b1c305509c3ce870f0311 [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
Matteo Scandolobddf31d2019-05-17 15:54:21 -0700178 it('should reset the feedback state $onDestroy', () => {
179 isolatedScope.config.feedback = 'foo';
180 expect(isolatedScope.config.feedback).toEqual('foo');
181 isolatedScope.$onDestroy();
182 expect(isolatedScope.config.feedback).toEqual(isolatedScope.hideFeedback);
183 });
184
Matteo Scandolob2225a02017-04-11 15:23:04 -0700185 it('should render 4 input field', () => {
186 // boolean and select are in the form model, but are not input
187 expect(Object.keys(isolatedScope.config.inputs).length).toEqual(6);
188 const htmlInputs = $('input', element);
189 expect(htmlInputs.length).toEqual(4);
190 });
191
192 it('should render 1 boolean field', () => {
193 expect($(element).find('.boolean-field > a').length).toEqual(2);
194 });
195
196 it('when clicking on action should invoke callback', () => {
197 const link = $(element).find('[role="button"]');
198 link.click();
199 // TODO : Check correct parameters
200 expect(cb).toHaveBeenCalled();
201
202 });
203
204 // TODO move in xosField test
205 it('should set a custom label', () => {
Matteo Scandolo80056232017-07-10 16:24:41 -0700206 let nameField = element[0].getElementsByClassName('form-group')[1];
Matteo Scandolob2225a02017-04-11 15:23:04 -0700207 let label = angular.element(nameField.getElementsByTagName('label')[0]).text();
Matteo Scandolo80056232017-07-10 16:24:41 -0700208 expect(label).toContain('Name:');
209 expect(label).not.toContain('*');
210 });
211
212 it('should print an * for required fields', () => {
213 let nameField = element[0].getElementsByClassName('form-group')[2];
214 let label = angular.element(nameField.getElementsByTagName('label')[0]).text();
215 expect(label).toContain('*');
Matteo Scandolob2225a02017-04-11 15:23:04 -0700216 });
217
218 // TODO move test in xos-field
219 xdescribe('the boolean field test', () => {
220
221 let setFalse, setTrue;
222
223 beforeEach(() => {
224 setFalse = $('.boolean-field > button:first-child', element);
225 setTrue = $('.boolean-field > button:last-child', element);
226 });
227
228 it('should change value to false', () => {
229 expect(isolatedScope.ngModel.enabled).toEqual(true);
230 setFalse.click();
231 expect(isolatedScope.ngModel.enabled).toEqual(false);
232 });
233
234 it('should change value to true', () => {
235 isolatedScope.ngModel.enabled = false;
236 scope.$apply();
237 expect(isolatedScope.ngModel.enabled).toEqual(false);
238 setTrue.click();
239 expect(isolatedScope.ngModel.enabled).toEqual(true);
240 });
241 });
242 });
243 describe('when correctly configured for feedback', () => {
244 // NOTE move this tests in xos-alert??
245 let fb = jasmine.createSpy('feedback').and.callFake(function(statusFlag: boolean) {
246 if (statusFlag) {
247 scope.config.feedback.show = true;
248 scope.config.feedback.message = 'Form Submitted';
249 scope.config.feedback.type = 'success';
250 }
251 else {
252 scope.config.feedback.show = true;
253 scope.config.feedback.message = 'Error';
254 scope.config.feedback.type = 'danger';
255 }
256 });
257
258 beforeEach(() => {
259 scope = rootScope.$new();
260 scope.config = {
261 formName: 'testForm',
262 feedback: {
263 show: false,
264 message: 'Form submitted successfully !!!',
265 type: 'success'
266 },
267 actions: [
268 {
269 label: 'Save',
270 icon: 'ok', // refers to bootstraps glyphicon
271 cb: () => null,
272 class: 'success'
273 }
274 ]
275 };
276 scope.model = {};
277 compileElement();
278 });
279
280 it('should not show feedback when loaded', () => {
281 expect($(element).find('xos-alert > div')).toHaveClass('alert alert-success ng-hide');
282 });
283
284 it('should show a success feedback', () => {
285 fb(true);
286 scope.$digest();
287 expect(isolatedScope.config.feedback.type).toEqual('success');
288 expect(fb).toHaveBeenCalledWith(true);
289 expect($(element).find('xos-alert > div')).toHaveClass('alert alert-success');
290 });
291
292 it('should show an error feedback', function() {
293 fb(false);
294 scope.$digest();
295 expect(isolatedScope.config.feedback.type).toEqual('danger');
296 expect(fb).toHaveBeenCalledWith(false);
297 expect($(element).find('xos-alert > div')).toHaveClass('alert alert-danger');
298 });
299 });
300});