From 0ad2c10930b26f78ef9a7c37dc6c2b2289da66c7 Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Wed, 26 Oct 2016 10:26:58 +0100 Subject: [PATCH] Unit tests --- .../widgets/core/dynamic-table.model.ts | 8 +- .../dynamic-table.widget.spec.ts | 209 ++++++++++++++++++ .../dynamic-table/dynamic-table.widget.ts | 42 ++-- .../editors/boolean/boolean.editor.spec.ts | 38 ++++ .../editors/boolean/boolean.editor.ts | 2 +- .../dynamic-table/editors/cell.editor.spec.ts | 42 ++++ .../dynamic-table/editors/cell.editor.ts | 2 +- .../editors/date/date.editor.spec.ts | 138 ++++++++++++ .../dynamic-table/editors/date/date.editor.ts | 13 +- .../editors/dropdown/dropdown.editor.spec.ts | 154 +++++++++++++ .../editors/dropdown/dropdown.editor.ts | 4 +- .../dynamic-table/editors/row.editor.spec.ts | 76 +++++++ .../editors/text/text.editor.spec.ts | 47 ++++ .../dynamic-table/editors/text/text.editor.ts | 2 +- 14 files changed, 747 insertions(+), 30 deletions(-) create mode 100644 ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.spec.ts create mode 100644 ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.spec.ts create mode 100644 ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/cell.editor.spec.ts create mode 100644 ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/date/date.editor.spec.ts create mode 100644 ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts create mode 100644 ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/row.editor.spec.ts create mode 100644 ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.spec.ts diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table.model.ts b/ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table.model.ts index 8c6e748848..175f0a2fdb 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table.model.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/core/dynamic-table.model.ts @@ -74,8 +74,10 @@ export class DynamicTableModel extends FormWidgetModel { } flushValue() { - this.field.value = this.rows.map(r => r.value); - this.field.updateForm(); + if (this.field) { + this.field.value = this.rows.map(r => r.value); + this.field.updateForm(); + } } moveRow(row: DynamicTableRow, offset: number) { @@ -152,7 +154,7 @@ export class DynamicTableModel extends FormWidgetModel { if (column.type === 'Date') { if (result) { - return moment(result.split('T')[0], 'YYYY-M-D').format('DD-MM-YYYY'); + return moment(result.split('T')[0], 'YYYY-MM-DD').format('DD-MM-YYYY'); } } diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.spec.ts new file mode 100644 index 0000000000..c2653378b6 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.spec.ts @@ -0,0 +1,209 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DynamicTableWidget } from './dynamic-table.widget'; +import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './../core/index'; + +describe('DynamicTableWidget', () => { + + let widget: DynamicTableWidget; + let table: DynamicTableModel; + + beforeEach(() => { + table = new DynamicTableModel(null); + widget = new DynamicTableWidget(null); + widget.content = table; + }); + + it('should select row on click', () => { + let row = { selected: false }; + widget.onRowClicked(row); + + expect(row.selected).toBeTruthy(); + expect(widget.content.selectedRow).toBe(row); + }); + + it('should requre table to select clicked row', () => { + let row = { selected: false }; + widget.content = null; + widget.onRowClicked(row); + + expect(row.selected).toBeFalsy(); + }); + + it('should reset selected row', () => { + let row = { selected: false }; + widget.content.rows.push(row); + widget.content.selectedRow = row; + expect(widget.content.selectedRow).toBe(row); + expect(row.selected).toBeTruthy(); + + widget.onRowClicked(null); + expect(widget.content.selectedRow).toBeNull(); + expect(row.selected).toBeFalsy(); + }); + + it('should check selection', () => { + let row = { selected: false }; + widget.content.rows.push(row); + widget.content.selectedRow = row; + expect(widget.hasSelection()).toBeTruthy(); + + widget.content.selectedRow = null; + expect(widget.hasSelection()).toBeFalsy(); + + widget.content = null; + expect(widget.hasSelection()).toBeFalsy(); + }); + + it('should require table to move selection up', () => { + widget.content = null; + expect(widget.moveSelectionUp()).toBeFalsy(); + }); + + it('should move selection up', () => { + let row1 = {}; + let row2 = {}; + widget.content.rows.push(...[row1, row2]); + widget.content.selectedRow = row2; + + expect(widget.moveSelectionUp()).toBeTruthy(); + expect(widget.content.rows.indexOf(row2)).toBe(0); + }); + + it('should require table to move selection down', () => { + widget.content = null; + expect(widget.moveSelectionDown()).toBeFalsy(); + }); + + it('should move selection down', () => { + let row1 = { }; + let row2 = { }; + widget.content.rows.push(...[row1, row2]); + widget.content.selectedRow = row1; + + expect(widget.moveSelectionDown()).toBeTruthy(); + expect(widget.content.rows.indexOf(row1)).toBe(1); + }); + + it('should require table to delete selection', () => { + widget.content = null; + expect(widget.deleteSelection()).toBeFalsy(); + }); + + it('should delete selected row', () => { + let row = {}; + widget.content.rows.push(row); + widget.content.selectedRow = row; + widget.deleteSelection(); + expect(widget.content.rows.length).toBe(0); + }); + + it('should require table to add new row', () => { + widget.content = null; + expect(widget.addNewRow()).toBeFalsy(); + }); + + it('should start editing new row', () => { + expect(widget.editMode).toBeFalsy(); + expect(widget.editRow).toBeNull(); + + expect(widget.addNewRow()).toBeTruthy(); + expect(widget.editRow).not.toBeNull(); + expect(widget.editMode).toBeTruthy(); + }); + + it('should require table to edit selected row', () => { + widget.content = null; + expect(widget.editSelection()).toBeFalsy(); + }); + + it('should start editing selected row', () => { + expect(widget.editMode).toBeFalsy(); + expect(widget.editRow).toBeFalsy(); + + let row = { value: true }; + widget.content.selectedRow = row; + + expect(widget.editSelection()).toBeTruthy(); + expect(widget.editMode).toBeTruthy(); + expect(widget.editRow).not.toBeNull(); + expect(widget.editRow.value).toEqual(row.value); + }); + + it('should copy row', () => { + let row = { value: { opt: { key: '1', value: 1 } } }; + let copy = widget.copyRow(row); + expect(copy.value).toEqual(row.value); + }); + + it('should require table to retrieve cell value', () => { + widget.content = null; + expect(widget.getCellValue(null, null)).toBeNull(); + }); + + it('should retrieve cell value', () => { + const value = ''; + let row = { value: { key: value } }; + let column = { id: 'key' }; + + expect(widget.getCellValue(row, column)).toBe(value); + }); + + it('should save changes and add new row', () => { + let row = { isNew: true, value: { key: 'value' } }; + widget.editMode = true; + widget.editRow = row; + + widget.onSaveChanges(); + + expect(row.isNew).toBeFalsy(); + expect(widget.content.selectedRow).toBeNull(); + expect(widget.content.rows.length).toBe(1); + expect(widget.content.rows[0].value).toEqual(row.value); + }); + + it('should save changes and update row', () => { + let row = { isNew: false, value: { key: 'value' } }; + widget.editMode = true; + widget.editRow = row; + widget.content.selectedRow = row; + + widget.onSaveChanges(); + expect(widget.content.selectedRow.value).toEqual(row.value); + }); + + it('should require table to save changes', () => { + spyOn(console, 'log').and.stub(); + widget.editMode = true; + widget.content = null; + widget.onSaveChanges(); + + expect(widget.editMode).toBeFalsy(); + expect(console.log).toHaveBeenCalledWith(widget.ERROR_MODEL_NOT_FOUND); + }); + + it('should cancel changes', () => { + widget.editMode = true; + widget.editRow = {}; + widget.onCancelChanges(); + + expect(widget.editMode).toBeFalsy(); + expect(widget.editRow).toBeNull(); + }); + +}); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.ts index 2eeddbc277..47ff3e2a0f 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/dynamic-table.widget.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, Input, OnInit, ElementRef } from '@angular/core'; +import { Component, Input, ElementRef } from '@angular/core'; import { WidgetComponent } from './../widget.component'; import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './../core/index'; @@ -25,23 +25,20 @@ import { DynamicTableModel, DynamicTableRow, DynamicTableColumn } from './../cor templateUrl: './dynamic-table.widget.html', styleUrls: ['./dynamic-table.widget.css'] }) -export class DynamicTableWidget extends WidgetComponent implements OnInit { +export class DynamicTableWidget extends WidgetComponent { + + ERROR_MODEL_NOT_FOUND = 'Table model not found'; @Input() content: DynamicTableModel; - editMode: boolean; - editRow: DynamicTableRow; - validationSummary: string; + editMode: boolean = false; + editRow: DynamicTableRow = null; constructor(private elementRef: ElementRef) { super(); } - ngOnInit() { - this.validationSummary = 'hello world'; - } - onRowClicked(row: DynamicTableRow) { if (this.content) { this.content.selectedRow = row; @@ -52,25 +49,31 @@ export class DynamicTableWidget extends WidgetComponent implements OnInit { return !!(this.content && this.content.selectedRow); } - moveSelectionUp() { + moveSelectionUp(): boolean { if (this.content) { this.content.moveRow(this.content.selectedRow, -1); + return true; } + return false; } - moveSelectionDown() { + moveSelectionDown(): boolean { if (this.content) { this.content.moveRow(this.content.selectedRow, 1); + return true; } + return false; } - deleteSelection() { + deleteSelection(): boolean { if (this.content) { this.content.deleteRow(this.content.selectedRow); + return true; } + return false; } - addNewRow() { + addNewRow(): boolean { if (this.content) { this.editRow = { isNew: true, @@ -78,14 +81,18 @@ export class DynamicTableWidget extends WidgetComponent implements OnInit { value: {} }; this.editMode = true; + return true; } + return false; } - editSelection() { + editSelection(): boolean { if (this.content) { this.editRow = this.copyRow(this.content.selectedRow); this.editMode = true; + return true; } + return false; } getCellValue(row: DynamicTableRow, column: DynamicTableColumn): any { @@ -106,6 +113,8 @@ export class DynamicTableWidget extends WidgetComponent implements OnInit { this.content.selectedRow.value = this.copyObject(this.editRow.value); } this.content.flushValue(); + } else { + this.handleError(this.ERROR_MODEL_NOT_FOUND); } this.editMode = false; } @@ -115,16 +124,17 @@ export class DynamicTableWidget extends WidgetComponent implements OnInit { this.editRow = null; } - private copyRow(row: DynamicTableRow): DynamicTableRow { + copyRow(row: DynamicTableRow): DynamicTableRow { return { value: this.copyObject(row.value) }; } private copyObject(obj: any): any { - let result = Object.assign({}, obj); + let result = obj; if (typeof obj === 'object' && obj !== null && obj !== undefined) { + result = Object.assign({}, obj); Object.keys(obj).forEach(key => { if (typeof obj[key] === 'object') { result[key] = this.copyObject(obj[key]); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.spec.ts new file mode 100644 index 0000000000..5899693d6c --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.spec.ts @@ -0,0 +1,38 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BooleanEditorComponent } from './boolean.editor'; +import { DynamicTableRow, DynamicTableColumn } from './../../../core/index'; + +describe('BooleanEditorComponent', () => { + + let component: BooleanEditorComponent; + + beforeEach(() => { + component = new BooleanEditorComponent(); + }); + + it('should update row value on change', () => { + let row = { value: {} }; + let column = { id: 'key' }; + let event = { srcElement: { checked: true } }; + + component.onValueChanged(row, column, event); + expect(row.value[column.id]).toBeTruthy(); + }); + +}); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.ts index 8a322801d6..d13846dbea 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/boolean/boolean.editor.ts @@ -27,7 +27,7 @@ import { DynamicTableRow, DynamicTableColumn } from './../../../core/index'; }) export class BooleanEditorComponent extends CellEditorComponent { - onValueChanged(row: DynamicTableRow, column: DynamicTableColumn, event: Event) { + onValueChanged(row: DynamicTableRow, column: DynamicTableColumn, event: any) { let value: boolean = (event.srcElement).checked; row.value[column.id] = value; } diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/cell.editor.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/cell.editor.spec.ts new file mode 100644 index 0000000000..239ce25eee --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/cell.editor.spec.ts @@ -0,0 +1,42 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CellEditorComponent } from './cell.editor'; + +describe('CellEditorComponent', () => { + + class CustomEditor extends CellEditorComponent { + onError(error: any) { + this.handleError(error); + } + } + + let component: CustomEditor; + + beforeEach(() => { + component = new CustomEditor(); + }); + + it('should handle error', () => { + const error = 'error'; + spyOn(console, 'error').and.stub(); + + component.onError(error); + expect(console.error).toHaveBeenCalledWith(error); + }); + +}); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/cell.editor.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/cell.editor.ts index c39ac33f77..ed3bbab266 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/cell.editor.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/cell.editor.ts @@ -29,7 +29,7 @@ export abstract class CellEditorComponent { @Input() column: DynamicTableColumn; - protected handleError(error: any) { + handleError(error: any) { console.error(error); } diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/date/date.editor.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/date/date.editor.spec.ts new file mode 100644 index 0000000000..dedc853952 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/date/date.editor.spec.ts @@ -0,0 +1,138 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ElementRef } from '@angular/core'; +import { DateEditorComponent } from './date.editor'; +import { DynamicTableModel, DynamicTableRow, DynamicTableColumn/*, DynamicRowValidationSummary*/ } from './../../../core/index'; + +describe('DateEditorComponent', () => { + + let nativeElement: any; + let elementRef: ElementRef; + let component: DateEditorComponent; + let row: DynamicTableRow; + let column: DynamicTableColumn; + let table: DynamicTableModel; + + beforeEach(() => { + nativeElement = { + querySelector: function () { return null; } + }; + + row = { value: { date: '1879-03-14T00:00:00.000Z' } }; + column = { id: 'date', type: 'Date' }; + table = new DynamicTableModel(null); + table.rows.push(row); + table.columns.push(column); + + elementRef = new ElementRef(nativeElement); + component = new DateEditorComponent(elementRef); + component.table = table; + component.row = row; + component.column = column; + }); + + it('should setup date picker on init', () => { + let trigger = {}; + spyOn(nativeElement, 'querySelector').and.returnValue(trigger); + + component.ngOnInit(); + + let settings = component.settings; + expect(settings.type).toBe('date'); + expect(settings.future.year()).toBe(moment().year() + 21); + expect(settings.init.isSame(moment('14-03-1879', component.DATE_FORMAT))).toBeTruthy(); + expect(component.datePicker.trigger).toBe(trigger); + }); + + it('should require cell value to setup initial date', () => { + row.value[column.id] = null; + component.ngOnInit(); + expect(component.settings.init).toBeUndefined(); + }); + + it('should require dom element to setup trigger', () => { + component = new DateEditorComponent(null); + component.table = table; + component.row = row; + component.column = column; + component.ngOnInit(); + expect(component.datePicker.trigger).toBeFalsy(); + }); + + it('should update fow value on change', () => { + component.ngOnInit(); + component.datePicker.time = moment('14-03-1879', 'DD-MM-YYYY'); + component.onDateSelected(null); + expect(row.value[column.id]).toBe('1879-03-14T00:00:00.000Z'); + }); + + it('should update material textfield on date selected', () => { + component.ngOnInit(); + component.datePicker.time = moment('14-03-1879', 'DD-MM-YYYY'); + spyOn(component, 'updateMaterialTextField').and.stub(); + component.onDateSelected(null); + expect(component.updateMaterialTextField).toHaveBeenCalled(); + }); + + it('should require dom element to update material textfield on change', () => { + component = new DateEditorComponent(null); + component.table = table; + component.row = row; + component.column = column; + component.ngOnInit(); + + component.datePicker.time = moment('14-03-1879', 'DD-MM-YYYY'); + spyOn(component, 'updateMaterialTextField').and.stub(); + component.onDateSelected(null); + expect(component.updateMaterialTextField).not.toHaveBeenCalled(); + }); + + it('should require dom element to update material textfield', () => { + let result = component.updateMaterialTextField(null, 'value'); + expect(result).toBeFalsy(); + }); + + it('should require native dom element to update material textfield', () => { + elementRef.nativeElement = null; + let result = component.updateMaterialTextField(elementRef, 'value'); + expect(result).toBeFalsy(); + }); + + it('should require input element to update material textfield', () => { + spyOn(nativeElement, 'querySelector').and.returnValue(null); + let result = component.updateMaterialTextField(elementRef, 'value'); + expect(result).toBeFalsy(); + }); + + it('should update material textfield with new value', () => { + let called = false; + const value = ''; + + spyOn(nativeElement, 'querySelector').and.returnValue({ + MaterialTextfield: { + change: function (val) { + called = true; + expect(val).toBe(value); + } + } + }); + component.updateMaterialTextField(elementRef, value); + expect(called).toBeTruthy(); + }); + +}); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/date/date.editor.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/date/date.editor.ts index 96293332b3..5b2b2c2ecc 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/date/date.editor.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/date/date.editor.ts @@ -29,23 +29,24 @@ export class DateEditorComponent extends CellEditorComponent implements OnInit { DATE_FORMAT: string = 'DD-MM-YYYY'; datePicker: any; + settings: any; constructor(private elementRef: ElementRef) { super(); } ngOnInit() { - let settings: any = { + this.settings = { type: 'date', future: moment().add(21, 'years') }; let value = this.table.getCellValue(this.row, this.column); if (value) { - settings.init = moment(value, this.DATE_FORMAT); + this.settings.init = moment(value, this.DATE_FORMAT); } - this.datePicker = new mdDateTimePicker.default(settings); + this.datePicker = new mdDateTimePicker.default(this.settings); if (this.elementRef) { this.datePicker.trigger = this.elementRef.nativeElement.querySelector('#dateInput'); } @@ -57,12 +58,12 @@ export class DateEditorComponent extends CellEditorComponent implements OnInit { this.table.flushValue(); if (this.elementRef) { - this.setupMaterialTextField(this.elementRef, componentHandler, newValue); + this.updateMaterialTextField(this.elementRef, newValue); } } - setupMaterialTextField(elementRef: ElementRef, handler: any, value: string): boolean { - if (elementRef && handler) { + updateMaterialTextField(elementRef: ElementRef, value: string): boolean { + if (elementRef) { let el = elementRef.nativeElement; if (el) { let container = el.querySelector('.mdl-textfield'); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts new file mode 100644 index 0000000000..f2c5d7e89d --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts @@ -0,0 +1,154 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Observable } from 'rxjs/Rx'; +import { DropdownEditorComponent } from './dropdown.editor'; +import { + DynamicTableModel, + DynamicTableRow, + DynamicTableColumn, + DynamicTableColumnOption, + FormFieldModel, + FormModel +} from './../../../core/index'; +import { FormService } from './../../../../../services/form.service'; + +describe('DropdownEditorComponent', () => { + + let component: DropdownEditorComponent; + let formService: FormService; + let form: FormModel; + let table: DynamicTableModel; + let column: DynamicTableColumn; + let row: DynamicTableRow; + + beforeEach(() => { + formService = new FormService(null, null); + + row = { value: { dropdown: 'one' } }; + column = { + id: 'dropdown', + options: [ + { id: '1', name: 'one' }, + { id: '2', name: 'two' } + ] + }; + + table = new DynamicTableModel(null); + form = new FormModel({ taskId: '' }); + table.field = new FormFieldModel(form, { id: '' }); + table.rows.push(row); + table.columns.push(column); + + component = new DropdownEditorComponent(formService); + component.table = table; + component.row = row; + component.column = column; + }); + + it('should require table field to setup', () => { + table.field = null; + component.ngOnInit(); + expect(component.value).toBeNull(); + expect(component.options).toEqual([]); + }); + + it('should setup with manual mode', () => { + row.value[column.id] = 'two'; + component.ngOnInit(); + expect(component.options).toEqual(column.options); + expect(component.value).toBe(row.value[column.id]); + }); + + it('should setup empty columns for manual mode', () => { + column.options = null; + component.ngOnInit(); + expect(component.options).toEqual([]); + }); + + it('should setup with REST mode', () => { + column.optionType = 'rest'; + row.value[column.id] = 'twelve'; + + let restResults = [ + { id: '11', name: 'eleven' }, + { id: '12', name: 'twelve' } + ]; + + spyOn(formService, 'getRestFieldValuesColumn').and.returnValue( + Observable.create(observer => { + observer.next(restResults); + observer.complete(); + }) + ); + + component.ngOnInit(); + + expect(formService.getRestFieldValuesColumn).toHaveBeenCalledWith( + form.taskId, + table.field.id, + column.id + ); + + expect(column.options).toEqual(restResults); + expect(component.options).toEqual(restResults); + expect(component.value).toBe(row.value[column.id]); + }); + + it('should create empty options array on REST response', () => { + column.optionType = 'rest'; + + spyOn(formService, 'getRestFieldValuesColumn').and.returnValue( + Observable.create(observer => { + observer.next(null); + observer.complete(); + }) + ); + + component.ngOnInit(); + + expect(formService.getRestFieldValuesColumn).toHaveBeenCalledWith( + form.taskId, + table.field.id, + column.id + ); + + expect(column.options).toEqual([]); + expect(component.options).toEqual([]); + expect(component.value).toBe(row.value[column.id]); + }); + + it('should handle REST error', () => { + column.optionType = 'rest'; + const error = 'error'; + + spyOn(formService, 'getRestFieldValuesColumn').and.returnValue( + Observable.throw(error) + ); + spyOn(component, 'handleError').and.stub(); + + component.ngOnInit(); + expect(component.handleError).toHaveBeenCalledWith(error); + }); + + it('should update row on value change', () => { + let event = { srcElement: { value: 'two' } }; + component.onValueChanged(row, column, event); + expect(row.value[column.id]).toBe(column.options[1]); + }); + +}); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.ts index 3fdb1c6204..88e86bada5 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.ts @@ -28,7 +28,7 @@ import { FormService } from './../../../../../services/form.service'; }) export class DropdownEditorComponent extends CellEditorComponent implements OnInit { - value: any; + value: any = null; options: DynamicTableColumnOption[] = []; constructor(private formService: FormService) { @@ -60,7 +60,7 @@ export class DropdownEditorComponent extends CellEditorComponent implements OnIn } } - onValueChanged(row: DynamicTableRow, column: DynamicTableColumn, event: Event) { + onValueChanged(row: DynamicTableRow, column: DynamicTableColumn, event: any) { let value: any = (event.srcElement).value; value = column.options.find(opt => opt.name === value); row.value[column.id] = value; diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/row.editor.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/row.editor.spec.ts new file mode 100644 index 0000000000..c460d25fc5 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/row.editor.spec.ts @@ -0,0 +1,76 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { RowEditorComponent } from './row.editor'; +import { DynamicTableModel, DynamicTableRow, DynamicTableColumn, DynamicRowValidationSummary } from './../../core/index'; + +describe('RowEditorComponent', () => { + + let component: RowEditorComponent; + + beforeEach(() => { + component = new RowEditorComponent(); + component.table = new DynamicTableModel(null); + component.row = {}; + component.column = {}; + }); + + it('should be valid upon init', () => { + expect(component.validationSummary.isValid).toBeTruthy(); + expect(component.validationSummary.text).toBeNull(); + }); + + it('should emit [cancel] event', (done) => { + component.cancel.subscribe(e => { + expect(e.table).toBe(component.table); + expect(e.row).toBe(component.row); + expect(e.column).toBe(component.column); + done(); + }); + component.onCancelChanges(); + }); + + it('should validate row on save', () => { + spyOn(component.table, 'validateRow').and.callThrough(); + component.onSaveChanges(); + expect(component.table.validateRow).toHaveBeenCalledWith(component.row); + }); + + it('should emit [save] event', (done) => { + spyOn(component.table, 'validateRow').and.returnValue( + { isValid: true, text: null } + ); + component.save.subscribe(e => { + expect(e.table).toBe(component.table); + expect(e.row).toBe(component.row); + expect(e.column).toBe(component.column); + done(); + }); + component.onSaveChanges(); + }); + + it('should not emit [save] event for invalid row', () => { + spyOn(component.table, 'validateRow').and.returnValue( + { isValid: false, text: 'error' } + ); + let raised = false; + component.save.subscribe(e => raised = true); + component.onSaveChanges(); + expect(raised).toBeFalsy(); + }); + +}); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.spec.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.spec.ts new file mode 100644 index 0000000000..70873eaf01 --- /dev/null +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.spec.ts @@ -0,0 +1,47 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TextEditorComponent } from './text.editor'; +import { + // DynamicTableModel, + DynamicTableRow, + DynamicTableColumn// , + // DynamicTableColumnOption, + // FormFieldModel, + // FormModel +} from './../../../core/index'; + +describe('TextEditorComponent', () => { + + let editor: TextEditorComponent; + + beforeEach(() => { + editor = new TextEditorComponent(); + }); + + it('should update row value on change', () => { + let row = { value: {} }; + let column = { id: 'key' }; + + const value = ''; + let event = { srcElement: { value } }; + + editor.onValueChanged(row, column, event); + expect(row.value[column.id]).toBe(value); + }); + +}); diff --git a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.ts b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.ts index 3f57684ad9..dc76cf90fd 100644 --- a/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.ts +++ b/ng2-components/ng2-activiti-form/src/components/widgets/dynamic-table/editors/text/text.editor.ts @@ -27,7 +27,7 @@ import { DynamicTableRow, DynamicTableColumn } from './../../../core/index'; }) export class TextEditorComponent extends CellEditorComponent { - onValueChanged(row: DynamicTableRow, column: DynamicTableColumn, event: Event) { + onValueChanged(row: DynamicTableRow, column: DynamicTableColumn, event: any) { let value: any = (event.srcElement).value; row.value[column.id] = value; }