blob: 7718a4468bb551a8ce8fae0d38d1ed0c30dc6de1 [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 Scandolod58d5042016-12-16 16:59:21 -080028
29let service: IXosConfigHelpersService;
Matteo Scandolocb466ed2017-01-04 17:16:24 -080030
Matteo Scandolo1aee1982017-02-17 08:33:23 -080031const model: IXosModeldef = {
Matteo Scandolocb466ed2017-01-04 17:16:24 -080032 name: 'Test',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080033 app: 'test',
Matteo Scandolocb466ed2017-01-04 17:16:24 -080034 fields: [
35 {
36 type: 'number',
37 name: 'id',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080038 validators: []
Matteo Scandolocb466ed2017-01-04 17:16:24 -080039 },
40 {
41 type: 'string',
42 name: 'name',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080043 validators: [
44 {
45 bool_value: true,
46 name: 'required'
47 }
48 ]
Matteo Scandolocb466ed2017-01-04 17:16:24 -080049 },
50 {
51 type: 'string',
52 name: 'something',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080053 validators: [
54 {
55 int_value: 30,
56 name: 'maxlength'
57 }
58 ]
Matteo Scandolo80c3a652017-01-06 10:48:31 -080059 },
60 {
61 type: 'number',
62 name: 'else',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080063 validators: [
64 {
65 int_value: 20,
66 name: 'min'
67 },
68 {
69 int_value: 40,
70 name: 'max'
71 }
72 ]
Matteo Scandolocb466ed2017-01-04 17:16:24 -080073 },
74 {
75 type: 'date',
76 name: 'updated',
Matteo Scandolo1aee1982017-02-17 08:33:23 -080077 validators: []
Matteo Scandolocb466ed2017-01-04 17:16:24 -080078 },
Matteo Scandolo580033a2017-08-17 11:16:39 -070079 ],
80 description: '',
81 verbose_name: ''
Matteo Scandolocb466ed2017-01-04 17:16:24 -080082};
83
Matteo Scandolod58d5042016-12-16 16:59:21 -080084describe('The ConfigHelpers service', () => {
85
Matteo Scandolo0a8b02e2017-01-06 14:43:36 -080086 beforeEach(() => {
87 angular
88 .module('test', ['toastr'])
89 .service('ConfigHelpers', ConfigHelpers)
90 .value('AuthService', {
91 getUser: () => {
92 return {id: 1};
93 }
Matteo Scandolo04964232017-01-07 12:53:46 -080094 })
Matteo Scandolo1aee1982017-02-17 08:33:23 -080095 .value('XosModelStore', {
Matteo Scandolo04964232017-01-07 12:53:46 -080096
Matteo Scandoloa242c872017-01-12 15:13:00 -080097 })
98 .value('$state', {
99 get: () => {
100 return [
101 {
102 name: 'xos.core.tests',
103 data: {model: 'Test'}
104 },
105 {
106 name: 'xos.core.slices',
107 data: {model: 'Slices'}
108 }
109 ];
110 }
Matteo Scandolo0a8b02e2017-01-06 14:43:36 -0800111 });
112 angular.mock.module('test');
113 });
Matteo Scandolod58d5042016-12-16 16:59:21 -0800114
115 beforeEach(angular.mock.inject((
116 ConfigHelpers: IXosConfigHelpersService,
117 ) => {
118 service = ConfigHelpers;
119 }));
120
121 describe('The pluralize function', () => {
122 it('should pluralize string', () => {
123 expect(service.pluralize('test')).toEqual('tests');
124 expect(service.pluralize('test', 1)).toEqual('test');
Matteo Scandolo08464e52017-01-17 13:35:27 -0800125 expect(service.pluralize('xos')).toEqual('xoses');
Matteo Scandolod58d5042016-12-16 16:59:21 -0800126 expect(service.pluralize('slice')).toEqual('slices');
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800127 expect(service.pluralize('Slice', 1)).toEqual('Slice');
Matteo Scandolod58d5042016-12-16 16:59:21 -0800128 });
129
130 it('should preprend count to string', () => {
131 expect(service.pluralize('test', 6, true)).toEqual('6 tests');
132 expect(service.pluralize('test', 1, true)).toEqual('1 test');
133 });
134 });
135
136 describe('the label formatter', () => {
137 it('should format a camel case string', () => {
138 expect(service.toLabel('camelCase')).toEqual('Camel case');
139 });
140
141 it('should format a snake case string', () => {
142 expect(service.toLabel('snake_case')).toEqual('Snake case');
143 });
144
145 it('should format a kebab case string', () => {
146 expect(service.toLabel('kebab-case')).toEqual('Kebab case');
147 });
148
149 it('should set plural', () => {
150 expect(service.toLabel('kebab-case', true)).toEqual('Kebab cases');
151 });
152
153 it('should format an array of strings', () => {
154 let strings: string[] = ['camelCase', 'snake_case', 'kebab-case'];
155 let labels = ['Camel case', 'Snake case', 'Kebab case'];
Matteo Scandoloe0d71ea2016-12-19 11:56:12 -0800156 expect(service.toLabels(strings)).toEqual(labels);
Matteo Scandolod58d5042016-12-16 16:59:21 -0800157 });
158
159 it('should set plural on an array of strings', () => {
160 let strings: string[] = ['camelCase', 'snake_case', 'kebab-case'];
161 let labels = ['Camel cases', 'Snake cases', 'Kebab cases'];
Matteo Scandoloe0d71ea2016-12-19 11:56:12 -0800162 expect(service.toLabels(strings, true)).toEqual(labels);
Matteo Scandolod58d5042016-12-16 16:59:21 -0800163 });
164 });
165
Matteo Scandoloa242c872017-01-12 15:13:00 -0800166 describe('the navigation methods', () => {
Matteo Scandoloa242c872017-01-12 15:13:00 -0800167 describe('stateFromCoreModels', () => {
168
169 let state: ng.ui.IStateService;
170
171 beforeEach(angular.mock.inject(($state) => {
172 state = $state;
173 }));
174
175 it('should return the state for a given model', () => {
176 expect(service.stateFromCoreModel('Test')).toBe('xos.core.tests');
177 });
Matteo Scandolo8248bca2017-08-09 13:46:04 -0700178 });
179 describe('stateWithParams', () => {
Matteo Scandoloa242c872017-01-12 15:13:00 -0800180 it('should return the state with params for a given model', () => {
181 expect(service.stateWithParams('Test', {id: 1})).toBe('xos.core.tests({id: 1})');
182 });
Matteo Scandolo8248bca2017-08-09 13:46:04 -0700183 it('should return the state with params for a given relation', () => {
184 expect(service.relatedStateWithParams('Test', '1')).toBe('xos.core.tests({id: 1})');
185 });
186
187 it('should return the state with params for usage in js', () => {
188 expect(service.stateWithParamsForJs('Test', {id: 1})).toEqual({ name: 'xos.core.tests', params: Object({ id: 1 }) });
189 });
Matteo Scandoloa242c872017-01-12 15:13:00 -0800190 });
191 });
192
Matteo Scandolocb466ed2017-01-04 17:16:24 -0800193 describe('the modelFieldsToColumnsCfg method', () => {
194 it('should return an array of columns', () => {
Matteo Scandolo580033a2017-08-17 11:16:39 -0700195 const cols = service.modelFieldsToColumnsCfg({fields: model.fields, name: 'testUrl', app: 'test', description: '', verbose_name: ''});
Matteo Scandolocb466ed2017-01-04 17:16:24 -0800196 expect(cols[0].label).toBe('Id');
197 expect(cols[0].prop).toBe('id');
198 expect(cols[0].link).toBeDefined();
199
200 expect(cols[1].label).toBe('Name');
201 expect(cols[1].prop).toBe('name');
202 expect(cols[1].link).toBeDefined();
203
204 expect(cols[2].label).toBe('Something');
205 expect(cols[2].prop).toBe('something');
206 expect(cols[2].link).not.toBeDefined();
207
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800208 expect(cols[3].label).toBe('Else');
209 expect(cols[3].prop).toBe('else');
210 expect(cols[3].link).not.toBeDefined();
211
212 expect(cols[4]).not.toBeDefined();
Matteo Scandolocb466ed2017-01-04 17:16:24 -0800213 });
Matteo Scandolof1e68cd2017-09-05 17:30:34 -0700214
Matteo Scandolocb466ed2017-01-04 17:16:24 -0800215 });
216
217 describe('the modelToTableCfg method', () => {
218 it('should return a table config', () => {
219 const cfg: IXosTableCfg = service.modelToTableCfg(model, 'testUrl/:id?');
220 expect(cfg.columns).toBeDefined();
221 expect(cfg.filter).toBe('fulltext');
222 expect(cfg.order).toEqual({field: 'id', reverse: false});
Matteo Scandolocc4bce82017-08-07 13:11:47 -0700223 expect(cfg.actions.length).toBe(2);
224 expect(cfg.actions[0].label).toEqual('details');
225 expect(cfg.actions[1].label).toEqual('delete');
Matteo Scandolocb466ed2017-01-04 17:16:24 -0800226 });
227 });
Matteo Scandolo1c5905f2017-01-04 17:41:15 -0800228
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800229 describe('the modelFieldToInputConfig', () => {
230 it('should return an array of inputs', () => {
231 const inputs: IXosFormInput[] = service.modelFieldToInputCfg(model.fields);
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800232
Matteo Scandolod53ac1d2017-08-01 15:06:09 -0700233 expect(inputs[0].name).toBe('name');
234 expect(inputs[0].type).toBe('string');
235 expect(inputs[0].label).toBe('Name');
236 expect(inputs[0].validators.required).toBe(true);
237
238 expect(inputs[1].name).toBe('something');
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800239 expect(inputs[1].type).toBe('string');
Matteo Scandolod53ac1d2017-08-01 15:06:09 -0700240 expect(inputs[1].label).toBe('Something');
241 expect(inputs[1].validators.maxlength).toBe(30);
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800242
Matteo Scandolod53ac1d2017-08-01 15:06:09 -0700243 expect(inputs[2].name).toBe('else');
244 expect(inputs[2].type).toBe('number');
245 expect(inputs[2].label).toBe('Else');
246 expect(inputs[2].validators.min).toBe(20);
247 expect(inputs[2].validators.max).toBe(40);
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800248 });
Matteo Scandolof1e68cd2017-09-05 17:30:34 -0700249
250 it('should convert boolean defaults to real booleans', () => {
251 const fields: IXosModelDefsField[] = [
252 {
253 type: 'boolean',
254 name: 'active',
255 default: '"True"',
256 validators: []
257 },
258 {
259 type: 'boolean',
260 name: 'disabled',
261 default: '"False"',
262 validators: []
263 },
264 ];
265 const form_fields = service.modelFieldToInputCfg(fields);
266 expect(form_fields[0].default).toBe(true);
267 expect(form_fields[1].default).toBe(false);
268 });
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800269 });
270
271 describe('the modelToFormCfg method', () => {
272 it('should return a form config', () => {
Matteo Scandolo1aee1982017-02-17 08:33:23 -0800273 const config: IXosFormCfg = service.modelToFormCfg(model);
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800274 expect(config.formName).toBe('TestForm');
275 expect(config.actions.length).toBe(1);
276 expect(config.actions[0].label).toBe('Save');
277 expect(config.actions[0].class).toBe('success');
278 expect(config.actions[0].icon).toBe('ok');
279 expect(config.actions[0].cb).toBeDefined();
Matteo Scandolod53ac1d2017-08-01 15:06:09 -0700280 // NOTE 'id' and 'updated' are hidden fields
281 expect(config.inputs.length).toBe(3);
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800282 });
283 });
Matteo Scandolo07e2f622017-01-09 10:54:13 -0800284
285 describe('the private methods', () => {
Matteo Scandoloa242c872017-01-12 15:13:00 -0800286 let modelStoreMock, toastr, auth, stateMock;
Matteo Scandolo07e2f622017-01-09 10:54:13 -0800287
288 beforeEach(angular.mock.inject((_toastr_, AuthService) => {
289 modelStoreMock = {
290 query: () => {
291 const subject = new BehaviorSubject([
292 {id: 1, humanReadableName: 'test'},
293 {id: 2, humanReadableName: 'second'}
294 ]);
295 return subject.asObservable();
296 }
297 };
298 toastr = _toastr_;
299 auth = AuthService;
Matteo Scandoloa242c872017-01-12 15:13:00 -0800300 stateMock = {
301 get: ''
302 };
Matteo Scandolo07e2f622017-01-09 10:54:13 -0800303 }));
304
305 const field: IXosModelDefsField = {
306 name: 'test',
307 type: 'number',
308 relation: {
309 model: 'Test',
310 type: 'many_to_one'
311 }
312 };
313
314 describe('the populateRelated method', () => {
315 const item = {
316 test: 2
317 };
318 it('should add the formatted data to the column definition', () => {
Matteo Scandolo02229382017-04-18 11:52:23 -0700319 service = new ConfigHelpers(stateMock, toastr, modelStoreMock);
Matteo Scandolo07e2f622017-01-09 10:54:13 -0800320 service['populateRelated'](item, item.test, field);
321 expect(item['test-formatted']).toBe('second');
322 });
323 });
324
325 describe('the populateSelectField', () => {
326
327 const input: IXosFormInput = {
328 name: 'test',
329 label: 'Test',
330 type: 'select',
331 validators: {}
332 };
333
334 it('should add the available choice to the select', () => {
Matteo Scandolo02229382017-04-18 11:52:23 -0700335 service = new ConfigHelpers(stateMock, toastr, modelStoreMock);
Matteo Scandolo07e2f622017-01-09 10:54:13 -0800336 service['populateSelectField'](field, input);
337 expect(input.options).toEqual([
338 {id: 1, label: 'test'},
339 {id: 2, label: 'second'}
340 ]);
341 });
342 });
343 });
Matteo Scandolod58d5042016-12-16 16:59:21 -0800344});
Matteo Scandolo80c3a652017-01-06 10:48:31 -0800345