blob: 7120a6bc5a5b2b54af4714a5accb8fc9a97ff068 [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 Scandolod58d5042016-12-16 16:59:21 -080019import * as angular from 'angular';
20import 'angular-mocks';
21import 'angular-ui-router';
22
Matteo Scandolo07e2f622017-01-09 10:54:13 -080023import {IXosConfigHelpersService, ConfigHelpers, IXosModelDefsField} from './config.helpers';
Matteo Scandolo1aee1982017-02-17 08:33:23 -080024import {IXosModeldef} from '../../../datasources/rest/modeldefs.rest';
Matteo Scandolocb466ed2017-01-04 17:16:24 -080025import {IXosTableCfg} from '../../table/table';
Matteo Scandolo1aee1982017-02-17 08:33:23 -080026import {IXosFormInput, IXosFormCfg} from '../../form/form';
Matteo Scandolo07e2f622017-01-09 10:54:13 -080027import {BehaviorSubject} from 'rxjs';
Matteo Scandolo63498472017-09-26 17:21:41 -070028import {XosFormHelpers} from '../../form/form-helpers';
Matteo Scandolod58d5042016-12-16 16:59:21 -080029
30let service: IXosConfigHelpersService;
Matteo Scandolocb466ed2017-01-04 17:16:24 -080031
Matteo Scandolo1aee1982017-02-17 08:33:23 -080032const model: IXosModeldef = {
Matteo Scandolocb466ed2017-01-04 17:16:24 -080033 name: 'Test',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080034 app: 'test',
Matteo Scandolocb466ed2017-01-04 17:16:24 -080035 fields: [
36 {
37 type: 'number',
38 name: 'id',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080039 validators: []
Matteo Scandolocb466ed2017-01-04 17:16:24 -080040 },
41 {
42 type: 'string',
43 name: 'name',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080044 validators: [
45 {
46 bool_value: true,
47 name: 'required'
48 }
49 ]
Matteo Scandolocb466ed2017-01-04 17:16:24 -080050 },
51 {
52 type: 'string',
53 name: 'something',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080054 validators: [
55 {
56 int_value: 30,
57 name: 'maxlength'
58 }
59 ]
Matteo Scandolo80c3a652017-01-06 10:48:31 -080060 },
61 {
62 type: 'number',
63 name: 'else',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080064 validators: [
65 {
66 int_value: 20,
67 name: 'min'
68 },
69 {
70 int_value: 40,
71 name: 'max'
72 }
73 ]
Matteo Scandolocb466ed2017-01-04 17:16:24 -080074 },
75 {
76 type: 'date',
77 name: 'updated',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080078 validators: []
Matteo Scandolocb466ed2017-01-04 17:16:24 -080079 },
Matteo Scandolo580033a2017-08-17 11:16:39 -070080 ],
81 description: '',
82 verbose_name: ''
Matteo Scandolocb466ed2017-01-04 17:16:24 -080083};
84
Matteo Scandolod58d5042016-12-16 16:59:21 -080085describe('The ConfigHelpers service', () => {
86
Matteo Scandolo0a8b02e2017-01-06 14:43:36 -080087 beforeEach(() => {
88 angular
89 .module('test', ['toastr'])
90 .service('ConfigHelpers', ConfigHelpers)
91 .value('AuthService', {
92 getUser: () => {
93 return {id: 1};
94 }
Matteo Scandolo04964232017-01-07 12:53:46 -080095 })
Matteo Scandolo1aee1982017-02-17 08:33:23 -080096 .value('XosModelStore', {
Matteo Scandolo04964232017-01-07 12:53:46 -080097
Matteo Scandoloa242c872017-01-12 15:13:00 -080098 })
Matteo Scandolo63498472017-09-26 17:21:41 -070099 .service('XosFormHelpers', XosFormHelpers)
Matteo Scandoloa242c872017-01-12 15:13:00 -0800100 .value('$state', {
101 get: () => {
102 return [
103 {
104 name: 'xos.core.tests',
105 data: {model: 'Test'}
106 },
107 {
108 name: 'xos.core.slices',
109 data: {model: 'Slices'}
110 }
111 ];
112 }
Matteo Scandolo0a8b02e2017-01-06 14:43:36 -0800113 });
114 angular.mock.module('test');
115 });
Matteo Scandolod58d5042016-12-16 16:59:21 -0800116
117 beforeEach(angular.mock.inject((
118 ConfigHelpers: IXosConfigHelpersService,
119 ) => {
120 service = ConfigHelpers;
121 }));
122
123 describe('The pluralize function', () => {
124 it('should pluralize string', () => {
125 expect(service.pluralize('test')).toEqual('tests');
126 expect(service.pluralize('test', 1)).toEqual('test');
Matteo Scandolo08464e52017-01-17 13:35:27 -0800127 expect(service.pluralize('xos')).toEqual('xoses');
Matteo Scandolod58d5042016-12-16 16:59:21 -0800128 expect(service.pluralize('slice')).toEqual('slices');
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800129 expect(service.pluralize('Slice', 1)).toEqual('Slice');
Matteo Scandolod58d5042016-12-16 16:59:21 -0800130 });
131
132 it('should preprend count to string', () => {
133 expect(service.pluralize('test', 6, true)).toEqual('6 tests');
134 expect(service.pluralize('test', 1, true)).toEqual('1 test');
135 });
136 });
137
138 describe('the label formatter', () => {
139 it('should format a camel case string', () => {
140 expect(service.toLabel('camelCase')).toEqual('Camel case');
141 });
142
143 it('should format a snake case string', () => {
144 expect(service.toLabel('snake_case')).toEqual('Snake case');
145 });
146
147 it('should format a kebab case string', () => {
148 expect(service.toLabel('kebab-case')).toEqual('Kebab case');
149 });
150
151 it('should set plural', () => {
152 expect(service.toLabel('kebab-case', true)).toEqual('Kebab cases');
153 });
154
155 it('should format an array of strings', () => {
156 let strings: string[] = ['camelCase', 'snake_case', 'kebab-case'];
157 let labels = ['Camel case', 'Snake case', 'Kebab case'];
Matteo Scandoloe0d71ea2016-12-19 11:56:12 -0800158 expect(service.toLabels(strings)).toEqual(labels);
Matteo Scandolod58d5042016-12-16 16:59:21 -0800159 });
160
161 it('should set plural on an array of strings', () => {
162 let strings: string[] = ['camelCase', 'snake_case', 'kebab-case'];
163 let labels = ['Camel cases', 'Snake cases', 'Kebab cases'];
Matteo Scandoloe0d71ea2016-12-19 11:56:12 -0800164 expect(service.toLabels(strings, true)).toEqual(labels);
Matteo Scandolod58d5042016-12-16 16:59:21 -0800165 });
166 });
167
Matteo Scandoloa242c872017-01-12 15:13:00 -0800168 describe('the navigation methods', () => {
Matteo Scandoloa242c872017-01-12 15:13:00 -0800169 describe('stateFromCoreModels', () => {
170
171 let state: ng.ui.IStateService;
172
173 beforeEach(angular.mock.inject(($state) => {
174 state = $state;
175 }));
176
177 it('should return the state for a given model', () => {
178 expect(service.stateFromCoreModel('Test')).toBe('xos.core.tests');
179 });
Matteo Scandolo8248bca2017-08-09 13:46:04 -0700180 });
181 describe('stateWithParams', () => {
Matteo Scandoloa242c872017-01-12 15:13:00 -0800182 it('should return the state with params for a given model', () => {
183 expect(service.stateWithParams('Test', {id: 1})).toBe('xos.core.tests({id: 1})');
184 });
Matteo Scandolo8248bca2017-08-09 13:46:04 -0700185 it('should return the state with params for a given relation', () => {
186 expect(service.relatedStateWithParams('Test', '1')).toBe('xos.core.tests({id: 1})');
187 });
188
189 it('should return the state with params for usage in js', () => {
190 expect(service.stateWithParamsForJs('Test', {id: 1})).toEqual({ name: 'xos.core.tests', params: Object({ id: 1 }) });
191 });
Matteo Scandoloa242c872017-01-12 15:13:00 -0800192 });
193 });
194
Matteo Scandolocb466ed2017-01-04 17:16:24 -0800195 describe('the modelFieldsToColumnsCfg method', () => {
196 it('should return an array of columns', () => {
Matteo Scandolo580033a2017-08-17 11:16:39 -0700197 const cols = service.modelFieldsToColumnsCfg({fields: model.fields, name: 'testUrl', app: 'test', description: '', verbose_name: ''});
Matteo Scandolocb466ed2017-01-04 17:16:24 -0800198 expect(cols[0].label).toBe('Id');
199 expect(cols[0].prop).toBe('id');
200 expect(cols[0].link).toBeDefined();
201
202 expect(cols[1].label).toBe('Name');
203 expect(cols[1].prop).toBe('name');
204 expect(cols[1].link).toBeDefined();
205
206 expect(cols[2].label).toBe('Something');
207 expect(cols[2].prop).toBe('something');
208 expect(cols[2].link).not.toBeDefined();
209
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800210 expect(cols[3].label).toBe('Else');
211 expect(cols[3].prop).toBe('else');
212 expect(cols[3].link).not.toBeDefined();
213
214 expect(cols[4]).not.toBeDefined();
Matteo Scandolocb466ed2017-01-04 17:16:24 -0800215 });
Matteo Scandolof1e68cd2017-09-05 17:30:34 -0700216
Matteo Scandolocb466ed2017-01-04 17:16:24 -0800217 });
218
219 describe('the modelToTableCfg method', () => {
220 it('should return a table config', () => {
221 const cfg: IXosTableCfg = service.modelToTableCfg(model, 'testUrl/:id?');
222 expect(cfg.columns).toBeDefined();
223 expect(cfg.filter).toBe('fulltext');
224 expect(cfg.order).toEqual({field: 'id', reverse: false});
Matteo Scandolocc4bce82017-08-07 13:11:47 -0700225 expect(cfg.actions.length).toBe(2);
226 expect(cfg.actions[0].label).toEqual('details');
227 expect(cfg.actions[1].label).toEqual('delete');
Matteo Scandolocb466ed2017-01-04 17:16:24 -0800228 });
229 });
Matteo Scandolo1c5905f2017-01-04 17:41:15 -0800230
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800231 describe('the modelFieldToInputConfig', () => {
232 it('should return an array of inputs', () => {
233 const inputs: IXosFormInput[] = service.modelFieldToInputCfg(model.fields);
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800234
Matteo Scandolod53ac1d2017-08-01 15:06:09 -0700235 expect(inputs[0].name).toBe('name');
236 expect(inputs[0].type).toBe('string');
237 expect(inputs[0].label).toBe('Name');
238 expect(inputs[0].validators.required).toBe(true);
239
240 expect(inputs[1].name).toBe('something');
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800241 expect(inputs[1].type).toBe('string');
Matteo Scandolod53ac1d2017-08-01 15:06:09 -0700242 expect(inputs[1].label).toBe('Something');
243 expect(inputs[1].validators.maxlength).toBe(30);
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800244
Matteo Scandolod53ac1d2017-08-01 15:06:09 -0700245 expect(inputs[2].name).toBe('else');
246 expect(inputs[2].type).toBe('number');
247 expect(inputs[2].label).toBe('Else');
248 expect(inputs[2].validators.min).toBe(20);
249 expect(inputs[2].validators.max).toBe(40);
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800250 });
Matteo Scandolof1e68cd2017-09-05 17:30:34 -0700251
252 it('should convert boolean defaults to real booleans', () => {
253 const fields: IXosModelDefsField[] = [
254 {
255 type: 'boolean',
256 name: 'active',
257 default: '"True"',
258 validators: []
259 },
260 {
261 type: 'boolean',
262 name: 'disabled',
263 default: '"False"',
264 validators: []
265 },
266 ];
267 const form_fields = service.modelFieldToInputCfg(fields);
268 expect(form_fields[0].default).toBe(true);
269 expect(form_fields[1].default).toBe(false);
270 });
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800271 });
272
273 describe('the modelToFormCfg method', () => {
274 it('should return a form config', () => {
Matteo Scandolo1aee1982017-02-17 08:33:23 -0800275 const config: IXosFormCfg = service.modelToFormCfg(model);
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800276 expect(config.formName).toBe('TestForm');
277 expect(config.actions.length).toBe(1);
278 expect(config.actions[0].label).toBe('Save');
279 expect(config.actions[0].class).toBe('success');
280 expect(config.actions[0].icon).toBe('ok');
281 expect(config.actions[0].cb).toBeDefined();
Matteo Scandolod53ac1d2017-08-01 15:06:09 -0700282 // NOTE 'id' and 'updated' are hidden fields
283 expect(config.inputs.length).toBe(3);
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800284 });
285 });
Matteo Scandolo07e2f622017-01-09 10:54:13 -0800286
287 describe('the private methods', () => {
Matteo Scandolo63498472017-09-26 17:21:41 -0700288 let modelStoreMock, q, toastr, auth, stateMock, XosFormHelpersMock;
Matteo Scandolo07e2f622017-01-09 10:54:13 -0800289
Matteo Scandolo63498472017-09-26 17:21:41 -0700290 beforeEach(angular.mock.inject(($q, _toastr_, AuthService, XosFormHelpers) => {
Matteo Scandolo07e2f622017-01-09 10:54:13 -0800291 modelStoreMock = {
292 query: () => {
293 const subject = new BehaviorSubject([
294 {id: 1, humanReadableName: 'test'},
295 {id: 2, humanReadableName: 'second'}
296 ]);
297 return subject.asObservable();
298 }
299 };
300 toastr = _toastr_;
301 auth = AuthService;
Matteo Scandolo63498472017-09-26 17:21:41 -0700302 XosFormHelpersMock = XosFormHelpers;
Matteo Scandoloa242c872017-01-12 15:13:00 -0800303 stateMock = {
304 get: ''
305 };
Matteo Scandolo63498472017-09-26 17:21:41 -0700306 q = $q;
Matteo Scandolo07e2f622017-01-09 10:54:13 -0800307 }));
308
309 const field: IXosModelDefsField = {
310 name: 'test',
311 type: 'number',
312 relation: {
313 model: 'Test',
314 type: 'many_to_one'
315 }
316 };
317
318 describe('the populateRelated method', () => {
319 const item = {
320 test: 2
321 };
322 it('should add the formatted data to the column definition', () => {
Matteo Scandolo63498472017-09-26 17:21:41 -0700323 service = new ConfigHelpers(q, stateMock, toastr, modelStoreMock, XosFormHelpersMock);
Matteo Scandolo07e2f622017-01-09 10:54:13 -0800324 service['populateRelated'](item, item.test, field);
325 expect(item['test-formatted']).toBe('second');
326 });
327 });
328
329 describe('the populateSelectField', () => {
330
331 const input: IXosFormInput = {
332 name: 'test',
333 label: 'Test',
334 type: 'select',
335 validators: {}
336 };
337
338 it('should add the available choice to the select', () => {
Matteo Scandolo63498472017-09-26 17:21:41 -0700339 service = new ConfigHelpers(q, stateMock, toastr, modelStoreMock, XosFormHelpersMock);
Matteo Scandolo07e2f622017-01-09 10:54:13 -0800340 service['populateSelectField'](field, input);
341 expect(input.options).toEqual([
342 {id: 1, label: 'test'},
343 {id: 2, label: 'second'}
344 ]);
345 });
346 });
347 });
Matteo Scandolod58d5042016-12-16 16:59:21 -0800348});
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800349