blob: 9d8e90d0cba3c16e6d0d56d2b8991388fa71c0d5 [file] [log] [blame]
Matteo Scandolo686547a2017-08-08 13:05:25 -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
Arpit Agarwal441284b2016-08-04 17:12:55 -070019/**
20 * © OpenCORD
21 *
22 * Created by teone on 5/25/16.
23 */
24
25(function () {
26 'use strict';
27
28 describe('The xos.helper module', function(){
29
30 describe('The xosField component', () => {
31 let element, scope, isolatedScope, rootScope, compile;
32 const compileElement = (el) => {
33 element = el;
34
35 if(!scope){
36 scope = rootScope.$new();
37 }
38 if(angular.isUndefined(element)){
39 element = angular.element('<xos-field name="name" field="field" ng-model="ngModel"></xos-field>');
40 }
41 compile(element)(scope);
42 scope.$digest();
43 isolatedScope = element.isolateScope().vm;
44 };
45
46 beforeEach(module('xos.helpers'));
47
48 beforeEach(inject(function ($compile, $rootScope) {
49 compile = $compile;
50 rootScope = $rootScope;
51 }));
52
53 it('should throw an error if no name is passed', inject(($compile, $rootScope) => {
54 function errorFunctionWrapper(){
55 // setup the parent scope
56 scope = $rootScope.$new();
57 scope.field = {
58 label: 'Label',
59 type: 'number',
60 validators: {}
61 };
62 scope.ngModel = 1;
63 compileElement();
64 }
65 expect(errorFunctionWrapper).toThrow(new Error('[xosField] Please provide a field name'));
66 }));
67
68 it('should throw an error if no field definition is passed', inject(($compile, $rootScope) => {
69 function errorFunctionWrapper(){
70 // setup the parent scope
71 scope = $rootScope.$new();
72 scope.name = 'label';
73 scope.ngModel = 1;
74 compileElement();
75 }
76 expect(errorFunctionWrapper).toThrow(new Error('[xosField] Please provide a field definition'));
77 }));
78
79 it('should throw an error if no field type is passed', inject(($compile, $rootScope) => {
80 function errorFunctionWrapper(){
81 // setup the parent scope
82 scope = $rootScope.$new();
83 scope.name = 'label';
84 scope.ngModel = 1;
85 scope.field = {label: 'Label:'}
86 compileElement();
87 }
88 expect(errorFunctionWrapper).toThrow(new Error('[xosField] Please provide a type in the field definition'));
89 }));
90
91 it('should throw an error if no field model is passed', inject(($compile, $rootScope) => {
92 function errorFunctionWrapper(){
93 // setup the parent scope
94 scope = $rootScope.$new();
95 scope.name = 'label';
96 scope.field = {
97 label: 'Label',
98 type: 'number',
99 validators: {}
100 };
101 compileElement(angular.element('<xos-field name="name" field="field"></xos-field>'));
102 }
103 expect(errorFunctionWrapper).toThrow(new Error('[xosField] Please provide an ng-model'));
104 }));
105
106 describe('when a text input is passed', () => {
107 beforeEach(() => {
108 scope = rootScope.$new();
109 scope.name = 'label';
110 scope.field = {
111 label: 'Label',
112 type: 'text',
113 validators: {
114 custom: 'fake'
115 }
116 };
117 scope.ngModel = 'label';
118 compileElement();
119 });
120
121 it('should print a text field', () => {
122 expect($(element).find('[name="label"]')).toHaveAttr('type', 'text');
123 });
124
125 it('should attach the custom validator directive', () => {
126 let input = $(element).find('[name="label"]');
127 expect(input).toHaveAttr('xos-custom-validator');
128 expect(input).toHaveAttr('custom-validator', 'vm.field.validators.custom || null');
129 });
130 });
131
132 describe('when a option is selected in dropdown', () => {
133 beforeEach(() => {
134 scope = rootScope.$new();
135 scope.name = 'label';
136 scope.field = {
137 label: 'Label',
138 type: 'select',
139 validators: {},
140 options: [
141 {
142 id: 0,
143 label: '---Site---'
144 },
145 {
146 id: 1,
147 label: '---Site1---'
148 }
149 ]
150 };
151 scope.ngModel = 0;
152 compileElement();
153 });
154
155 it('No of select elements', () => {
156 expect($(element).find('select').children('option').length).toEqual(2);
157 });
158
159 it('should show the selected value', () => {
160 const elem = angular.element($(element).find('select').children('option')[0]);
161 expect(elem.text()).toEqual('---Site---');
162 expect(elem).toHaveAttr('selected');
163 });
164 });
165
166 describe('when a number input is passed', () => {
167 beforeEach(() => {
168 scope = rootScope.$new();
169 scope.name = 'label';
170 scope.field = {
171 label: 'Label',
172 type: 'number',
173 validators: {}
174 };
175 scope.ngModel = 10;
176 compileElement();
177 });
178
179 it('should print a number field', () => {
180 expect($(element).find('[name="label"]')).toHaveAttr('type', 'number');
181 });
182 });
183
184 describe('when a boolean input is passed', () => {
185 beforeEach(() => {
186 scope = rootScope.$new();
187 scope.name = 'label';
188 scope.field = {
189 label: 'Label',
190 type: 'boolean',
191 validators: {}
192 };
193 scope.ngModel = true;
194 compileElement();
195 });
196
197 let setFalse, setTrue;
198
199 beforeEach(() => {
200 setFalse= $(element).find('.boolean-field > a:first-child');
201 setTrue = $(element).find('.boolean-field > a:last-child');
202 });
203
204 it('should print two buttons', () => {
205 expect($(element).find('.boolean-field > a').length).toEqual(2)
206 });
207
208 it('should change value to false', () => {
209 expect(isolatedScope.ngModel).toEqual(true);
210 clickElement(setFalse[0]);
211 expect(isolatedScope.ngModel).toEqual(false);
212 });
213
214 it('should change value to true', () => {
215 isolatedScope.ngModel = false;
216 scope.$apply();
217 expect(isolatedScope.ngModel).toEqual(false);
218 clickElement(setTrue[0]);
219 expect(isolatedScope.ngModel).toEqual(true);
220 });
221 });
222
223 describe('when an object input is passed', () => {
224 beforeEach(() => {
225 scope = rootScope.$new();
226 scope.name = 'label';
227 scope.field = {
228 label: 'Label',
229 type: 'object',
230 validators: {}
231 };
232 scope.ngModel = {
233 baz: true,
234 foo: 'bar',
235 foz: 1,
236 };
237 compileElement();
238 });
239
240 it('should print a panel to contain object property field', () => {
241 expect($(element).find('.panel.object-field')).toExist()
242 });
243
244 it('should print the right input type for each property', () => {
245 expect($(element).find('input').length).toBe(2);
246 expect($(element).find('.boolean-field > a').length).toEqual(2);
247 });
248
249 it('should format labels', () => {
250 expect($(element).find('input[name="foo"]').parent().find('label').text()).toBe('Foo:');
251 });
252
253 describe('and the model is empty', () => {
254 beforeEach(() => {
255 scope.ngModel = {
256 };
257 compileElement();
258 });
259
260 it('should not print the panel', () => {
261 expect($(element).find('.panel.object-field')).not.toExist()
262 });
263
264 describe('but field is configured', () => {
265 beforeEach(() => {
266 scope.field.properties = {
267 foo: {
268 label: 'FooLabel:',
269 type: 'string',
270 validators: {
271 required: true
272 }
273 },
274 bar: {
275 type: 'number'
276 }
277 };
278 compileElement();
279 });
280 it('should render panel and configured fields', () => {
281 expect($(element).find('.panel.object-field')).toExist();
282 expect($(element).find('input[name="foo"]').parent().find('label').text()).toBe('FooLabel:');
283 expect($(element).find('input[name="foo"]')).toHaveAttr('type', 'string');
284 expect($(element).find('input[name="foo"]')).toHaveAttr('required');
285
286 expect($(element).find('input[name="bar"]').parent().find('label').text()).toBe('Bar:');
287 expect($(element).find('input[name="bar"]')).toHaveAttr('type', 'number');
288
289 });
290 });
291 });
292 });
293
Matteo Scandolo65116c42016-09-21 17:06:23 -0700294 describe('when an array input is passed', () => {
295 beforeEach(() => {
296 scope = rootScope.$new();
297 scope.name = 'label';
298 scope.field = {
299 label: 'Label',
300 type: 'array',
301 validators: {},
302 options: ['1', '2', '3', '4', '5']
303 };
304 scope.ngModel = ['1', '2', '3'];
305 compileElement();
306 });
307
308 it('should print a panel to contain array values', () => {
309 expect($(element).find('.panel.array-field')).toExist()
310 });
311
312 it('should print selected values', () => {
313 expect($(element).find('.panel.array-field .selected .array-element')).toHaveLength(3)
314 });
315
316 it('should print un-selected values', () => {
317 expect($(element).find('.panel.array-field .unselected .array-element')).toHaveLength(2)
318 });
319
320 describe('when a value is added', () => {
321 it('should be removed from unselected', () => {
322 isolatedScope.ngModel.push('4');
323 scope.$apply();
324 expect($(element).find('.panel.array-field .unselected .array-element')).toHaveLength(1)
325 });
326 });
327
328 describe('when a value is removed', () => {
329 it('should be added to unselected', () => {
330 isolatedScope.ngModel.pop();
331 scope.$apply();
332 expect($(element).find('.panel.array-field .unselected .array-element')).toHaveLength(3)
333 });
334 });
335 });
336
Arpit Agarwal441284b2016-08-04 17:12:55 -0700337 describe('when validation options are passed', () => {
338 let input;
339 describe('given a a text field', () => {
340 beforeEach(() => {
341 scope = rootScope.$new();
342 scope.name='label';
343 scope.field = {
344 label: 'Label',
345 type: 'text',
346 validators: {
347 minlength: 10,
348 maxlength: 15,
349 required: true
350 }
351 };
352
353 compileElement();
354 scope.$digest();
355 input = $(element).find('input');
356 });
357
358 it('should validate required', () => {
359 scope.ngModel= null;
360 scope.$digest();
361 expect(input).toHaveClass('ng-invalid-required');
362
363 scope.ngModel= 'not too short';
364 scope.$digest();
365 expect(input).not.toHaveClass('ng-invalid-required');
366 expect(input).not.toHaveClass('ng-invalid');
367 });
368
369 it('should validate minlength', () => {
370 scope.ngModel= 'short';
371 scope.$digest();
372 expect(input).toHaveClass('ng-invalid-minlength');
373
374 scope.ngModel= 'not too short';
375 scope.$digest();
376 expect(input).not.toHaveClass('ng-invalid-minlength');
377 expect(input).not.toHaveClass('ng-invalid');
378 });
379
380 it('should validate maxlength', () => {
381 scope.ngModel= 'this is definitely too long!!';
382 scope.$digest();
383 expect(input).toHaveClass('ng-invalid-maxlength');
384
385 scope.ngModel= 'not too short';
386 scope.$digest();
387 expect(input).not.toHaveClass('ng-invalid-maxlength');
388 expect(input).not.toHaveClass('ng-invalid');
389 });
390 });
391 });
392 });
393 });
Matteo Scandoloa5d03d52016-07-21 11:35:46 -0700394})();