New tests for processlist components

Refs #849
This commit is contained in:
Will Abson
2016-11-11 17:24:10 +00:00
committed by Mario Romano
parent 7fa92e250d
commit 5f60760cd5
21 changed files with 1138 additions and 181 deletions

View File

@@ -1,123 +0,0 @@
/*!
* @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 { DatePipe } from '@angular/common';
import {
DataTableAdapter, ObjectDataTableAdapter, ObjectDataColumn,
DataRow, DataColumn, DataSorting
} from 'ng2-alfresco-datatable';
export class ProcessListDataTableAdapter extends ObjectDataTableAdapter implements DataTableAdapter {
ERR_ROW_NOT_FOUND: string = 'Row not found';
ERR_COL_NOT_FOUND: string = 'Column not found';
DEFAULT_DATE_FORMAT: string = 'medium';
private sorting: DataSorting;
private rows: DataRow[];
private columns: DataColumn[];
constructor(rows: any, schema: DataColumn[]) {
super(rows, schema);
this.rows = rows;
this.columns = schema || [];
}
getRows(): Array<DataRow> {
return this.rows;
}
// TODO: disable this api
setRows(rows: Array<DataRow>) {
this.rows = rows || [];
this.sort();
}
getColumns(): Array<DataColumn> {
return this.columns;
}
setColumns(columns: Array<DataColumn>) {
this.columns = columns || [];
}
getValue(row: DataRow, col: DataColumn): any {
if (!row) {
throw new Error(this.ERR_ROW_NOT_FOUND);
}
if (!col) {
throw new Error(this.ERR_COL_NOT_FOUND);
}
let value = row.getValue(col.key);
if (col.type === 'date') {
let datePipe = new DatePipe('en-US');
let format = (<ActivitiDataColumn>(col)).format || this.DEFAULT_DATE_FORMAT;
try {
return datePipe.transform(value, format);
} catch (err) {
console.error(`Error parsing date ${value} to format ${format}`);
}
}
return value;
}
getSorting(): DataSorting {
return this.sorting;
}
setSorting(sorting: DataSorting): void {
this.sorting = sorting;
if (sorting && sorting.key && this.rows && this.rows.length > 0) {
this.rows.sort((a: DataRow, b: DataRow) => {
let left = a.getValue(sorting.key);
if (left) {
left = (left instanceof Date) ? left.valueOf().toString() : left.toString();
} else {
left = '';
}
let right = b.getValue(sorting.key);
if (right) {
right = (right instanceof Date) ? right.valueOf().toString() : right.toString();
} else {
right = '';
}
return sorting.direction === 'asc'
? left.localeCompare(right)
: right.localeCompare(left);
});
}
}
sort(key?: string, direction?: string): void {
let sorting = this.sorting || new DataSorting();
if (key) {
sorting.key = key;
sorting.direction = direction || 'asc';
}
this.setSorting(sorting);
}
}
export class ActivitiDataColumn extends ObjectDataColumn {
format: string;
}

View File

@@ -45,7 +45,7 @@ module.exports = function (config) {
// ng2-components
{ pattern: 'node_modules/ng2-alfresco-core/dist/**/*.*', included: false, served: true, watched: false },
{ pattern: 'node_modules/ng2-alfresco-datatable/dist/**/*.*', included: false, served: true, watched: false },
{ pattern: 'node_modules/ng2-activiti-tasklist/dist/**/*.js', included: false, served: true, watched: false },
{ pattern: 'node_modules/ng2-activiti-tasklist/dist/**/*.*', included: false, served: true, watched: false },
{ pattern: 'node_modules/ng2-activiti-form/dist/**/*.*', included: false, served: true, watched: false },
// paths to support debugging with source maps in dev tools

View File

@@ -31,9 +31,22 @@ export class ProcessList {
export class SingleProcessList extends ProcessList {
constructor(name?: string) {
let instance = new ProcessInstance();
instance.id = '123';
instance.name = name;
let instance = new ProcessInstance({
id: '123',
name: name
});
super([instance]);
}
}
export var exampleProcess = new ProcessInstance({
id: '123',
name: 'Process 123',
started: '2016-11-10T03:37:30.010+0000',
startedBy: {
id: 1001,
firstName: 'Bob',
lastName: 'Jones',
email: 'bob@app.activiti.com'
}
});

View File

@@ -0,0 +1,192 @@
/*!
* @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.
*/
export var taskDetailsMock = {
'id': '91',
'name': 'Request translation',
'description': null,
'category': null,
'assignee': {'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com'},
'created': '2016-11-03T15:25:42.749+0000',
'dueDate': null,
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': '86',
'processInstanceName': null,
'processDefinitionId': 'TranslationProcess:2:8',
'processDefinitionName': 'Translation Process',
'processDefinitionDescription': null,
'processDefinitionKey': 'TranslationProcess',
'processDefinitionCategory': 'http://www.activiti.org/processdef',
'processDefinitionVersion': 2,
'processDefinitionDeploymentId': '5',
'formKey': '4',
'processInstanceStartUserId': '1001',
'initiatorCanCompleteTask': false,
'adhocTaskCanBeReassigned': false,
'taskDefinitionKey': 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE',
'executionId': '86',
'involvedPeople': [],
'memberOfCandidateUsers': false,
'managerOfCandidateGroup': false,
'memberOfCandidateGroup': false
};
export var taskFormMock = {
'id': 4,
'name': 'Translation request',
'processDefinitionId': 'TranslationProcess:2:8',
'processDefinitionName': 'Translation Process',
'processDefinitionKey': 'TranslationProcess',
'taskId': '91',
'taskName': 'Request translation',
'taskDefinitionKey': 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE',
'tabs': [],
'fields': [{
'fieldType': 'ContainerRepresentation',
'id': '1478093984155',
'name': 'Label',
'type': 'container',
'value': null,
'required': false,
'readOnly': false,
'overrideId': false,
'colspan': 1,
'placeholder': null,
'minLength': 0,
'maxLength': 0,
'minValue': null,
'maxValue': null,
'regexPattern': null,
'optionType': null,
'hasEmptyValue': null,
'options': null,
'restUrl': null,
'restResponsePath': null,
'restIdProperty': null,
'restLabelProperty': null,
'tab': null,
'className': null,
'dateDisplayFormat': null,
'layout': null,
'sizeX': 2,
'sizeY': 1,
'row': -1,
'col': -1,
'visibilityCondition': null,
'numberOfColumns': 2,
'fields': {
'1': [{
'fieldType': 'AttachFileFieldRepresentation',
'id': 'originalcontent',
'name': 'Original content',
'type': 'upload',
'value': [],
'required': true,
'readOnly': false,
'overrideId': false,
'colspan': 1,
'placeholder': null,
'minLength': 0,
'maxLength': 0,
'minValue': null,
'maxValue': null,
'regexPattern': null,
'optionType': null,
'hasEmptyValue': null,
'options': null,
'restUrl': null,
'restResponsePath': null,
'restIdProperty': null,
'restLabelProperty': null,
'tab': null,
'className': null,
'params': {
},
'dateDisplayFormat': null,
'layout': {'row': -1, 'column': -1, 'colspan': 1},
'sizeX': 1,
'sizeY': 1,
'row': -1,
'col': -1,
'visibilityCondition': null,
'metaDataColumnDefinitions': []
}],
'2': [{
'fieldType': 'RestFieldRepresentation',
'id': 'language',
'name': 'Language',
'type': 'dropdown',
'value': 'Choose one...',
'required': true,
'readOnly': false,
'overrideId': false,
'colspan': 1,
'placeholder': null,
'minLength': 0,
'maxLength': 0,
'minValue': null,
'maxValue': null,
'regexPattern': null,
'optionType': null,
'hasEmptyValue': true,
'options': [{'id': 'empty', 'name': 'Choose one...'}, {'id': 'fr', 'name': 'French'}, {
'id': 'de',
'name': 'German'
}, {'id': 'es', 'name': 'Spanish'}],
'restUrl': null,
'restResponsePath': null,
'restIdProperty': null,
'restLabelProperty': null,
'tab': null,
'className': null,
'params': {'existingColspan': 1, 'maxColspan': 1},
'dateDisplayFormat': null,
'layout': {'row': -1, 'column': -1, 'colspan': 1},
'sizeX': 1,
'sizeY': 1,
'row': -1,
'col': -1,
'visibilityCondition': null,
'endpoint': null,
'requestHeaders': null
}]
}
}],
'outcomes': [],
'javascriptEvents': [],
'className': '',
'style': '',
'customFieldTemplates': {},
'metadata': {},
'variables': [],
'gridsterForm': false,
'globalDateFormat': 'D-M-YYYY'
};
export var tasksMock = {
data: [
taskDetailsMock
]
};
export var noDataMock = {
data: []
};

View File

@@ -15,7 +15,7 @@
</li>
</ul>
</div>
<div *ngIf="comments?.length === 0">
<div *ngIf="comments?.length === 0" data-automation-id="comments-none">
{{ 'DETAILS.COMMENTS.NONE' | translate }}
</div>

View File

@@ -0,0 +1,191 @@
/*!
* @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 { SimpleChange } from '@angular/core';
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Observable } from 'rxjs/Rx';
import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core';
import { ActivitiFormModule } from 'ng2-activiti-form';
import { ActivitiComments } from './activiti-comments.component';
import { ActivitiProcessService } from './../services/activiti-process.service';
import { TranslationMock } from './../assets/translation.service.mock';
describe('ActivitiProcessInstanceComments', () => {
let componentHandler: any;
let service: ActivitiProcessService;
let component: ActivitiComments;
let fixture: ComponentFixture<ActivitiComments>;
let getCommentsSpy: jasmine.Spy;
let addCommentSpy: jasmine.Spy;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
CoreModule,
ActivitiFormModule
],
declarations: [
ActivitiComments
],
providers: [
{ provide: AlfrescoTranslationService, useClass: TranslationMock },
ActivitiProcessService
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ActivitiComments);
component = fixture.componentInstance;
service = fixture.debugElement.injector.get(ActivitiProcessService);
getCommentsSpy = spyOn(service, 'getProcessInstanceComments').and.returnValue(Observable.of([{
message: 'Test1'
}, {
message: 'Test2'
}, {
message: 'Test3'
}]));
addCommentSpy = spyOn(service, 'addProcessInstanceComment').and.returnValue(Observable.of({id: 123, message: 'Test'}));
componentHandler = jasmine.createSpyObj('componentHandler', [
'upgradeAllRegistered',
'upgradeElement'
]);
window['componentHandler'] = componentHandler;
});
it('should load comments when processInstanceId specified', () => {
component.processInstanceId = '123';
fixture.detectChanges();
expect(getCommentsSpy).toHaveBeenCalled();
});
it('should emit an error when an error occurs loading comments', () => {
let emitSpy = spyOn(component.error, 'emit');
getCommentsSpy.and.returnValue(Observable.throw({}));
component.processInstanceId = '123';
fixture.detectChanges();
expect(emitSpy).toHaveBeenCalled();
});
it('should not comments when no processInstanceId is specified', () => {
fixture.detectChanges();
expect(getCommentsSpy).not.toHaveBeenCalled();
});
it('should display comments when the process has comments', async(() => {
component.processInstanceId = '123';
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('ul.mdl-list li')).length).toBe(3);
});
}));
it('should not display comments when the process has no comments', async(() => {
component.processInstanceId = '123';
getCommentsSpy.and.returnValue(Observable.of([]));
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('ul.mdl-list li')).length).toBe(0);
});
}));
describe('change detection', () => {
let change = new SimpleChange('123', '456');
let nullChange = new SimpleChange('123', null);
beforeEach(async(() => {
component.processInstanceId = '123';
fixture.detectChanges();
fixture.whenStable().then(() => {
getCommentsSpy.calls.reset();
});
}));
it('should fetch new comments when processInstanceId changed', () => {
component.ngOnChanges({ 'processInstanceId': change });
expect(getCommentsSpy).toHaveBeenCalledWith('456');
});
it('should NOT fetch new comments when empty changeset made', () => {
component.ngOnChanges({});
expect(getCommentsSpy).not.toHaveBeenCalled();
});
it('should NOT fetch new comments when processInstanceId changed to null', () => {
component.ngOnChanges({ 'processInstanceId': nullChange });
expect(getCommentsSpy).not.toHaveBeenCalled();
});
it('should set a placeholder message when processInstanceId changed to null', () => {
component.ngOnChanges({ 'processInstanceId': nullChange });
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('[data-automation-id="comments-none"]'))).not.toBeNull();
});
});
describe('Add comment', () => {
beforeEach(async(() => {
component.processInstanceId = '123';
fixture.detectChanges();
fixture.whenStable();
}));
it('should display a dialog to the user when the Add button clicked', () => {
let dialogEl = fixture.debugElement.query(By.css('.mdl-dialog')).nativeElement;
let showSpy: jasmine.Spy = spyOn(dialogEl, 'showModal');
component.showDialog();
expect(showSpy).toHaveBeenCalled();
});
it('should call service to add a comment', () => {
component.showDialog();
component.message = 'Test comment';
component.add();
expect(addCommentSpy).toHaveBeenCalledWith('123', 'Test comment');
});
it('should emit an error when an error occurs adding the comment', () => {
let emitSpy = spyOn(component.error, 'emit');
addCommentSpy.and.returnValue(Observable.throw({}));
component.showDialog();
component.message = 'Test comment';
component.add();
expect(emitSpy).toHaveBeenCalled();
});
it('should close add dialog when close button clicked', () => {
let dialogEl = fixture.debugElement.query(By.css('.mdl-dialog')).nativeElement;
let closeSpy: jasmine.Spy = spyOn(dialogEl, 'close');
component.showDialog();
component.cancel();
expect(closeSpy).toHaveBeenCalled();
});
});
});

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, Input, OnInit, ViewChild, OnChanges, SimpleChanges } from '@angular/core';
import { Component, EventEmitter, Input, Output, OnInit, ViewChild, OnChanges, SimpleChanges } from '@angular/core';
import { AlfrescoTranslationService } from 'ng2-alfresco-core';
import { ActivitiProcessService } from './../services/activiti-process.service';
import { Comment } from 'ng2-activiti-tasklist';
@@ -23,6 +23,7 @@ import { Observer } from 'rxjs/Observer';
import { Observable } from 'rxjs/Observable';
declare let componentHandler: any;
declare let dialogPolyfill: any;
@Component({
selector: 'activiti-process-instance-comments',
@@ -36,6 +37,9 @@ export class ActivitiComments implements OnInit, OnChanges {
@Input()
processInstanceId: string;
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
@ViewChild('dialog')
dialog: any;
@@ -48,8 +52,8 @@ export class ActivitiComments implements OnInit, OnChanges {
/**
* Constructor
* @param auth
* @param translate
* @param translate Translation service
* @param activitiProcess Process service
*/
constructor(private translate: AlfrescoTranslationService,
private activitiProcess: ActivitiProcessService) {
@@ -66,17 +70,24 @@ export class ActivitiComments implements OnInit, OnChanges {
this.comment$.subscribe((comment: Comment) => {
this.comments.push(comment);
});
}
ngOnChanges(changes: SimpleChanges) {
let processInstanceId = changes['processInstanceId'];
if (processInstanceId && processInstanceId.currentValue) {
this.getProcessComments(processInstanceId.currentValue);
if (this.processInstanceId) {
this.getProcessComments(this.processInstanceId);
return;
}
}
public getProcessComments(processInstanceId: string) {
ngOnChanges(changes: SimpleChanges) {
let processInstanceId = changes['processInstanceId'];
if (processInstanceId) {
if (processInstanceId.currentValue) {
this.getProcessComments(processInstanceId.currentValue);
} else {
this.resetComments();
}
}
}
private getProcessComments(processInstanceId: string) {
this.comments = [];
if (processInstanceId) {
this.activitiProcess.getProcessInstanceComments(processInstanceId).subscribe(
@@ -86,15 +97,22 @@ export class ActivitiComments implements OnInit, OnChanges {
});
},
(err) => {
console.log(err);
this.error.emit(err);
}
);
} else {
this.comments = [];
this.resetComments();
}
}
private resetComments() {
this.comments = [];
}
public showDialog() {
if (!this.dialog.nativeElement.showModal) {
dialogPolyfill.registerDialog(this.dialog.nativeElement);
}
if (this.dialog) {
this.dialog.nativeElement.showModal();
}
@@ -107,7 +125,7 @@ export class ActivitiComments implements OnInit, OnChanges {
this.message = '';
},
(err) => {
console.log(err);
this.error.emit(err);
}
);
this.cancel();

View File

@@ -0,0 +1,160 @@
/*!
* @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 { SimpleChange } from '@angular/core';
import { ActivitiProcessFilters } from './activiti-filters.component';
import { ActivitiProcessService } from '../services/activiti-process.service';
import { Observable } from 'rxjs/Rx';
import { FilterRepresentationModel } from 'ng2-activiti-tasklist';
describe('ActivitiFilters', () => {
let filterList: ActivitiProcessFilters;
let activitiService: ActivitiProcessService;
let fakeGlobalFilter = [];
fakeGlobalFilter.push(new FilterRepresentationModel({name: 'FakeInvolvedTasks', filter: { state: 'open', assignment: 'fake-involved'}}));
fakeGlobalFilter.push(new FilterRepresentationModel({name: 'FakeMyTasks', filter: { state: 'open', assignment: 'fake-assignee'}}));
let fakeGlobalFilterPromise = new Promise(function (resolve, reject) {
resolve(fakeGlobalFilter);
});
let fakeErrorFilterList = {
error: 'wrong request'
};
let fakeErrorFilterPromise = new Promise(function (resolve, reject) {
reject(fakeErrorFilterList);
});
beforeEach(() => {
activitiService = new ActivitiProcessService(null);
filterList = new ActivitiProcessFilters(null, activitiService);
});
it('should return the filter task list', (done) => {
spyOn(activitiService, 'getProcessFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise));
filterList.onSuccess.subscribe((res) => {
expect(res).toBeDefined();
expect(filterList.filters).toBeDefined();
expect(filterList.filters.length).toEqual(2);
expect(filterList.filters[0].name).toEqual('FakeInvolvedTasks');
expect(filterList.filters[1].name).toEqual('FakeMyTasks');
done();
});
filterList.ngOnInit();
});
it('should return the filter task list, filtered By Name', (done) => {
let fakeDeployedApplicationsPromise = new Promise(function (resolve, reject) {
resolve({});
});
spyOn(activitiService, 'getDeployedApplications').and.returnValue(Observable.fromPromise(fakeDeployedApplicationsPromise));
spyOn(activitiService, 'getProcessFilters').and.returnValue(Observable.fromPromise(fakeGlobalFilterPromise));
filterList.appName = 'test';
filterList.onSuccess.subscribe((res) => {
let deployApp: any = activitiService.getDeployedApplications;
expect(deployApp.calls.count()).toEqual(1);
expect(res).toBeDefined();
done();
});
filterList.ngOnInit();
});
it('should emit an error with a bad response', (done) => {
filterList.appId = '1';
spyOn(activitiService, 'getProcessFilters').and.returnValue(Observable.fromPromise(fakeErrorFilterPromise));
filterList.onError.subscribe((err) => {
expect(err).toBeDefined();
done();
});
filterList.ngOnInit();
});
it('should emit an error with a bad response', (done) => {
filterList.appName = 'fake-app';
spyOn(activitiService, 'getDeployedApplications').and.returnValue(Observable.fromPromise(fakeErrorFilterPromise));
filterList.onError.subscribe((err) => {
expect(err).toBeDefined();
done();
});
filterList.ngOnInit();
});
it('should emit an event when a filter is selected', (done) => {
let currentFilter = new FilterRepresentationModel({filter: { state: 'open', assignment: 'fake-involved'}});
filterList.filterClick.subscribe((filter: FilterRepresentationModel) => {
expect(filter).toBeDefined();
expect(filter).toEqual(currentFilter);
expect(filterList.currentFilter).toEqual(currentFilter);
done();
});
filterList.selectFilter(currentFilter);
});
it('should reload filters by appId on binding changes', () => {
spyOn(filterList, 'getFiltersByAppId').and.stub();
const appId = '1';
let change = new SimpleChange(null, appId);
filterList.ngOnChanges({ 'appId': change });
expect(filterList.getFiltersByAppId).toHaveBeenCalledWith(appId);
});
it('should reload filters by appId null on binding changes', () => {
spyOn(filterList, 'getFiltersByAppId').and.stub();
const appId = null;
let change = new SimpleChange(null, appId);
filterList.ngOnChanges({ 'appId': change });
expect(filterList.getFiltersByAppId).toHaveBeenCalledWith(appId);
});
it('should reload filters by app name on binding changes', () => {
spyOn(filterList, 'getFiltersByAppName').and.stub();
const appName = 'fake-app-name';
let change = new SimpleChange(null, appName);
filterList.ngOnChanges({ 'appName': change });
expect(filterList.getFiltersByAppName).toHaveBeenCalledWith(appName);
});
it('should return the current filter after one is selected', () => {
let filter = new FilterRepresentationModel({name: 'FakeMyTasks', filter: { state: 'open', assignment: 'fake-assignee'}});
expect(filterList.currentFilter).toBeUndefined();
filterList.selectFilter(filter);
expect(filterList.getCurrentFilter()).toBe(filter);
});
});

View File

@@ -4,7 +4,11 @@
<activiti-process-instance-header [processInstance]="processInstanceDetails" (processCancelled)="bubbleProcessCancelled()" #activitiprocessheader></activiti-process-instance-header>
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--8-col">
<<<<<<< HEAD
<activiti-process-instance-tasks [processInstanceDetails]="processInstanceDetails" (taskFormCompleted)="bubbleTaskFormCompleted()" #activitiprocesstasks></activiti-process-instance-tasks>
=======
<activiti-process-instance-tasks [processInstanceId]="processInstanceDetails.id" (taskFormCompleted)="onTaskFormCompleted()" #activitiprocesstasks></activiti-process-instance-tasks>
>>>>>>> New tests for processlist components
</div>
<div class="mdl-cell mdl-cell--4-col">
<activiti-process-instance-comments [processInstanceId]="processInstanceDetails.id" #activitiprocesscomments></activiti-process-instance-comments>

View File

@@ -0,0 +1,165 @@
/*!
* @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 { NO_ERRORS_SCHEMA, DebugElement, SimpleChange } from '@angular/core';
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Observable } from 'rxjs/Rx';
import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core';
import { ActivitiFormModule, FormModel, FormOutcomeEvent, FormOutcomeModel, FormService } from 'ng2-activiti-form';
import { ActivitiTaskListModule } from 'ng2-activiti-tasklist';
import { ActivitiProcessInstanceDetails } from './activiti-process-instance-details.component';
import { ActivitiProcessService } from './../services/activiti-process.service';
import { TranslationMock } from './../assets/translation.service.mock';
import { exampleProcess } from './../assets/activiti-process.model.mock';
describe('ActivitiProcessInstanceDetails', () => {
let componentHandler: any;
let service: ActivitiProcessService;
let formService: FormService;
let component: ActivitiProcessInstanceDetails;
let fixture: ComponentFixture<ActivitiProcessInstanceDetails>;
let getProcessSpy: jasmine.Spy;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
CoreModule,
ActivitiFormModule,
ActivitiTaskListModule
],
declarations: [
ActivitiProcessInstanceDetails
],
providers: [
{ provide: AlfrescoTranslationService, useClass: TranslationMock },
ActivitiProcessService
],
schemas: [ NO_ERRORS_SCHEMA ]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ActivitiProcessInstanceDetails);
component = fixture.componentInstance;
service = fixture.debugElement.injector.get(ActivitiProcessService);
formService = fixture.debugElement.injector.get(FormService);
getProcessSpy = spyOn(service, 'getProcess').and.returnValue(Observable.of(exampleProcess));
componentHandler = jasmine.createSpyObj('componentHandler', [
'upgradeAllRegistered',
'upgradeElement'
]);
window['componentHandler'] = componentHandler;
});
it('should load task details when processInstanceId specified', () => {
component.processInstanceId = '123';
fixture.detectChanges();
expect(getProcessSpy).toHaveBeenCalled();
});
it('should not load task details when no processInstanceId is specified', () => {
fixture.detectChanges();
expect(getProcessSpy).not.toHaveBeenCalled();
});
it('should set a placeholder message when processInstanceId not initialised', () => {
fixture.detectChanges();
expect(fixture.nativeElement.innerText).toBe('DETAILS.MESSAGES.NONE');
});
it('should display a header when the processInstanceId is provided', async(() => {
component.processInstanceId = '123';
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
let headerEl: DebugElement = fixture.debugElement.query(By.css('h2'));
expect(headerEl).not.toBeNull();
expect(headerEl.nativeElement.innerText).toBe('Process 123');
});
}));
describe('change detection', () => {
let change = new SimpleChange('123', '456');
let nullChange = new SimpleChange('123', null);
beforeEach(async(() => {
component.processInstanceId = '123';
fixture.detectChanges();
component.tasksList = jasmine.createSpyObj('tasksList', ['load']);
fixture.whenStable().then(() => {
getProcessSpy.calls.reset();
});
}));
it('should fetch new process details when processInstanceId changed', () => {
component.ngOnChanges({ 'processInstanceId': change });
expect(getProcessSpy).toHaveBeenCalledWith('456');
});
it('should reload tasks list when processInstanceId changed', () => {
component.ngOnChanges({ 'processInstanceId': change });
expect(component.tasksList.load).toHaveBeenCalled();
});
it('should NOT fetch new process details when empty changeset made', () => {
component.ngOnChanges({});
expect(getProcessSpy).not.toHaveBeenCalled();
});
it('should NOT fetch new process details when processInstanceId changed to null', () => {
component.ngOnChanges({ 'processInstanceId': nullChange });
expect(getProcessSpy).not.toHaveBeenCalled();
});
it('should set a placeholder message when processInstanceId changed to null', () => {
component.ngOnChanges({ 'processInstanceId': nullChange });
fixture.detectChanges();
expect(fixture.nativeElement.innerText).toBe('DETAILS.MESSAGES.NONE');
});
});
describe('events', () => {
beforeEach(async(() => {
component.processInstanceId = '123';
fixture.detectChanges();
fixture.whenStable();
}));
it('should emit a task form completed event when task form completed', () => {
let emitSpy: jasmine.Spy = spyOn(component.taskFormCompleted, 'emit');
component.bubbleTaskFormCompleted(new FormModel());
expect(emitSpy).toHaveBeenCalled();
});
it('should emit a outcome execution event when task form outcome executed', () => {
let emitSpy: jasmine.Spy = spyOn(component.processCancelled, 'emit');
component.bubbleProcessCancelled(new FormOutcomeEvent(new FormOutcomeModel(new FormModel())));
expect(emitSpy).toHaveBeenCalled();
});
});
});

View File

@@ -61,9 +61,8 @@ export class ActivitiProcessInstanceDetails implements OnInit, OnChanges {
/**
* Constructor
* @param auth
* @param translate
* @param activitiProcess
* @param translate Translation service
* @param activitiProcess Process service
*/
constructor(private translate: AlfrescoTranslationService,
private activitiProcess: ActivitiProcessService) {

View File

@@ -1,15 +1,19 @@
<div *ngIf="processInstance">
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--4-col">
<div class="mdl-cell mdl-cell--4-col" data-automation-id="header-started-by">
<span class="activiti-label">{{ 'DETAILS.LABELS.STARTED_BY' | translate }}</span>:
{{getStartedByFullName()}}
<span class="activiti-process-header__value">{{getStartedByFullName()}}</span>
</div>
<div class="mdl-cell mdl-cell--4-col">
<div class="mdl-cell mdl-cell--4-col" data-automation-id="header-started">
<span class="activiti-label">{{ 'DETAILS.LABELS.STARTED' | translate }}</span>:
{{getFormatDate(processInstance.started, 'medium')}}
<span class="activiti-process-header__value">{{getFormatDate(processInstance.started, 'medium')}}</span>
</div>
<div class="mdl-cell mdl-cell--4-col">
<div class="mdl-cell mdl-cell--4-col" data-automation-id="header-status" *ngIf="isRunning()">
<button type="button" (click)="cancelProcess()" class="mdl-button">{{ 'DETAILS.BUTTON.CANCEL' | translate }}</button>
</div>
<div class="mdl-cell mdl-cell--4-col" data-automation-id="header-status" *ngIf="!isRunning()">
<span class="activiti-label">{{ 'DETAILS.LABELS.ENDED' | translate }}</span>:
<span class="activiti-process-header__value">{{getFormatDate(processInstance.ended, 'medium')}}</span>
</div>
</div>
</div>

View File

@@ -0,0 +1,108 @@
/*!
* @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 { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core';
import { ActivitiProcessInstanceHeader } from './activiti-process-instance-header.component';
import { TranslationMock } from './../assets/translation.service.mock';
import { exampleProcess } from './../assets/activiti-process.model.mock';
import { ProcessInstance } from './../models/process-instance';
import { ActivitiProcessService } from './../services/activiti-process.service';
describe('ActivitiProcessInstanceHeader', () => {
let componentHandler: any;
let component: ActivitiProcessInstanceHeader;
let fixture: ComponentFixture<ActivitiProcessInstanceHeader>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
CoreModule
],
declarations: [
ActivitiProcessInstanceHeader
],
providers: [
{ provide: AlfrescoTranslationService, useClass: TranslationMock },
ActivitiProcessService
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ActivitiProcessInstanceHeader);
component = fixture.componentInstance;
component.processInstance = new ProcessInstance(exampleProcess);
componentHandler = jasmine.createSpyObj('componentHandler', [
'upgradeAllRegistered',
'upgradeElement'
]);
window['componentHandler'] = componentHandler;
});
it('should render empty component if no form details provided', () => {
component.processInstance = undefined;
fixture.detectChanges();
expect(fixture.debugElement.children.length).toBe(0);
});
it('should display started by user', () => {
fixture.detectChanges();
let formValueEl = fixture.debugElement.query(By.css('[data-automation-id="header-started-by"] .activiti-process-header__value'));
expect(formValueEl).not.toBeNull();
expect(formValueEl.nativeElement.innerText).toBe('Bob Jones');
});
it('should display empty started by user if user unknown', () => {
component.processInstance.startedBy = null;
fixture.detectChanges();
let formValueEl = fixture.debugElement.query(By.css('[data-automation-id="header-started-by"] .activiti-process-header__value'));
expect(formValueEl).not.toBeNull();
expect(formValueEl.nativeElement.innerText).toBe('');
});
it('should display process start date', () => {
component.processInstance.started = '2016-11-10T03:37:30.010+0000';
fixture.detectChanges();
let formValueEl = fixture.debugElement.query(By.css('[data-automation-id="header-started"] .activiti-process-header__value'));
expect(formValueEl).not.toBeNull();
expect(formValueEl.nativeElement.innerText).toBe('Nov 10, 2016, 3:37:30 AM');
});
it('should display cancel button if process is running', () => {
component.processInstance.ended = null;
fixture.detectChanges();
let buttonEl = fixture.debugElement.query(By.css('[data-automation-id="header-status"] button'));
expect(buttonEl).not.toBeNull();
});
it('should display ended date if process is ended', () => {
component.processInstance.ended = '2016-11-10T03:37:30.010+0000';
fixture.detectChanges();
let formValueEl = fixture.debugElement.query(By.css('[data-automation-id="header-status"] .activiti-process-header__value'));
expect(formValueEl).not.toBeNull();
expect(formValueEl.nativeElement.innerText).toBe('Nov 10, 2016, 3:37:30 AM');
});
});

View File

@@ -48,7 +48,7 @@ export class ActivitiProcessInstanceHeader {
}
}
getStartedByFullName() {
getStartedByFullName(): string {
if (this.processInstance && this.processInstance.startedBy) {
return (this.processInstance.startedBy.firstName && this.processInstance.startedBy.firstName !== 'null'
? this.processInstance.startedBy.firstName + ' ' : '') +
@@ -66,6 +66,10 @@ export class ActivitiProcessInstanceHeader {
}
}
isRunning(): boolean {
return this.processInstance && !this.processInstance.ended;
}
cancelProcess() {
this.activitiProcess.cancelProcess(this.processInstance.id).subscribe(
(res) => {

View File

@@ -10,7 +10,7 @@
<span class="activiti-label mdl-badge"
[attr.data-badge]="activeTasks?.length">{{ 'DETAILS.LABELS.TASKS_ACTIVE'|translate }}</span>
<div class="menu-container" *ngIf="activeTasks?.length > 0">
<div class="menu-container" *ngIf="activeTasks?.length > 0" data-automation-id="active-tasks">
<ul class='mdl-list'>
<li class="mdl-list__item mdl-list__item--two-line" *ngFor="let task of activeTasks">
<span class="mdl-list__item-primary-content" (click)="clickTask($event, task)">
@@ -24,7 +24,7 @@
<!-- START FORM -->
<div *ngIf="activeTasks?.length === 0">
<div *ngIf="activeTasks?.length === 0" data-automation-id="active-tasks-none">
{{ 'DETAILS.TASKS.NO_ACTIVE' | translate }}
</div>
@@ -51,7 +51,7 @@
<span class="activiti-label mdl-badge"
[attr.data-badge]="completedTasks?.length">{{ 'DETAILS.LABELS.TASKS_COMPLETED'|translate }}</span>
<div class="menu-container" *ngIf="completedTasks?.length > 0">
<div class="menu-container" *ngIf="completedTasks?.length > 0" data-automation-id="completed-tasks">
<ul class='mdl-list'>
<li class="mdl-list__item mdl-list__item--two-line" *ngFor="let task of completedTasks">
<span class="mdl-list__item-primary-content" (click)="clickTask($event, task)">
@@ -64,7 +64,7 @@
</ul>
</div>
<div *ngIf="completedTasks?.length === 0">
<div *ngIf="completedTasks?.length === 0" data-automation-id="completed-tasks-none">
{{ 'DETAILS.TASKS.NO_COMPLETED' | translate }}
</div>

View File

@@ -0,0 +1,206 @@
/*!
* @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 { NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Observable } from 'rxjs/Rx';
import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core';
import { TaskDetailsModel } from 'ng2-activiti-tasklist';
import { ActivitiProcessInstanceTasks } from './activiti-process-instance-tasks.component';
import { TranslationMock } from './../assets/translation.service.mock';
import { taskDetailsMock } from './../assets/task-details.mock';
import { ProcessInstance } from './../models/process-instance';
import { ActivitiProcessService } from './../services/activiti-process.service';
describe('ActivitiProcessInstanceTasks', () => {
let componentHandler: any;
let component: ActivitiProcessInstanceTasks;
let fixture: ComponentFixture<ActivitiProcessInstanceTasks>;
let service: ActivitiProcessService;
let getProcessTasksSpy: jasmine.Spy;
let exampleProcessInstance = new ProcessInstance({ id: '123' });
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
CoreModule
],
declarations: [
ActivitiProcessInstanceTasks
],
providers: [
{ provide: AlfrescoTranslationService, useClass: TranslationMock },
ActivitiProcessService
],
schemas: [ NO_ERRORS_SCHEMA ]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ActivitiProcessInstanceTasks);
component = fixture.componentInstance;
service = fixture.debugElement.injector.get(ActivitiProcessService);
getProcessTasksSpy = spyOn(service, 'getProcessTasks').and.returnValue(Observable.of([new TaskDetailsModel(taskDetailsMock)]));
componentHandler = jasmine.createSpyObj('componentHandler', [
'upgradeAllRegistered',
'upgradeElement'
]);
window['componentHandler'] = componentHandler;
});
it('should initially render message about no active tasks if no process instance ID provided', async(() => {
component.processInstanceDetails = undefined;
fixture.detectChanges();
fixture.whenStable().then(() => {
let msgEl = fixture.debugElement.query(By.css('[data-automation-id="active-tasks-none"]'));
expect(msgEl).not.toBeNull();
});
}));
it('should initially render message about no completed tasks if no process instance ID provided', async(() => {
component.processInstanceDetails = undefined;
fixture.detectChanges();
fixture.whenStable().then(() => {
let msgEl = fixture.debugElement.query(By.css('[data-automation-id="completed-tasks-none"]'));
expect(msgEl).not.toBeNull();
});
}));
it('should not render active tasks list if no process instance ID provided', () => {
component.processInstanceDetails = undefined;
fixture.detectChanges();
let listEl = fixture.debugElement.query(By.css('[data-automation-id="active-tasks"]'));
expect(listEl).toBeNull();
});
it('should not render completed tasks list if no process instance ID provided', () => {
component.processInstanceDetails = undefined;
fixture.detectChanges();
let listEl = fixture.debugElement.query(By.css('[data-automation-id="completed-tasks"]'));
expect(listEl).toBeNull();
});
it('should call service to get tasks on init', () => {
component.processInstanceDetails = exampleProcessInstance;
fixture.detectChanges();
expect(getProcessTasksSpy).toHaveBeenCalled();
});
it('should display active tasks', () => {
component.processInstanceDetails = exampleProcessInstance;
fixture.detectChanges();
fixture.whenStable().then(() => {
let listEl = fixture.debugElement.query(By.css('[data-automation-id="active-tasks"]'));
expect(listEl).not.toBeNull();
expect(listEl.queryAll(By.css('li')).length).toBe(1);
});
});
it('should display completed tasks', () => {
component.processInstanceDetails = exampleProcessInstance;
fixture.detectChanges();
fixture.whenStable().then(() => {
let listEl = fixture.debugElement.query(By.css('[data-automation-id="completed-tasks"]'));
expect(listEl).not.toBeNull();
expect(listEl.queryAll(By.css('li')).length).toBe(1);
});
});
describe('task reloading', () => {
beforeEach(async(() => {
component.processInstanceDetails = exampleProcessInstance;
fixture.detectChanges();
fixture.whenStable();
}));
it('should render a refresh button by default', () => {
expect(fixture.debugElement.query(By.css('.process-tasks-refresh'))).not.toBeNull();
});
it('should render a refresh button if configured to', () => {
component.showRefreshButton = true;
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('.process-tasks-refresh'))).not.toBeNull();
});
it('should NOT render a refresh button if configured not to', () => {
component.showRefreshButton = false;
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('.process-tasks-refresh'))).toBeNull();
});
it('should call service to get tasks when reload button clicked', () => {
getProcessTasksSpy.calls.reset();
component.onRefreshClicked();
expect(getProcessTasksSpy).toHaveBeenCalled();
});
});
describe('task details', () => {
let closeSpy;
beforeEach(async(() => {
closeSpy = spyOn(component.dialog.nativeElement, 'close');
component.processInstanceDetails = exampleProcessInstance;
fixture.detectChanges();
fixture.whenStable();
component.taskdetails = jasmine.createSpyObj('taskdetails', [
'loadDetails'
]);
}));
it('should display task details dialog when task clicked', () => {
let showModalSpy = spyOn(component.dialog.nativeElement, 'showModal');
component.clickTask({}, new TaskDetailsModel(taskDetailsMock));
expect(showModalSpy).toHaveBeenCalled();
});
it('should close the task details dialog when close button clicked', () => {
component.clickTask({}, new TaskDetailsModel(taskDetailsMock));
fixture.detectChanges();
component.cancelDialog();
expect(closeSpy).toHaveBeenCalled();
});
it('should output event when task form completed', async(() => {
let emitSpy = spyOn(component.taskFormCompleted, 'emit');
fixture.detectChanges();
component.clickTask({}, new TaskDetailsModel(taskDetailsMock));
fixture.detectChanges();
component.onTaskFormCompleted();
expect(emitSpy).toHaveBeenCalled();
}));
it('should close dialog when task form completed', async(() => {
component.clickTask({}, new TaskDetailsModel(taskDetailsMock));
fixture.detectChanges();
component.onTaskFormCompleted();
expect(closeSpy).toHaveBeenCalled();
}));
});
});

View File

@@ -41,7 +41,7 @@ export class ActivitiProcessInstanceTasks implements OnInit {
showRefreshButton: boolean = true;
@Output()
taskFormCompletedEmitter = new EventEmitter();
taskFormCompleted = new EventEmitter();
activeTasks: TaskDetailsModel[] = [];
completedTasks: TaskDetailsModel[] = [];
@@ -191,10 +191,10 @@ export class ActivitiProcessInstanceTasks implements OnInit {
}
}
public taskFormCompleted() {
public onTaskFormCompleted() {
this.closeDialog();
this.load(this.processInstanceDetails.id);
this.taskFormCompletedEmitter.emit(this.processInstanceDetails.id);
this.taskFormCompleted.emit(this.processInstanceDetails.id);
}
public onRefreshClicked() {

View File

@@ -20,6 +20,7 @@ import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { Observable } from 'rxjs/Rx';
import { ActivitiProcessInstanceListComponent } from './activiti-processlist.component';
import { TranslationMock } from './../assets/translation.service.mock';
import { ObjectDataTableAdapter } from 'ng2-alfresco-datatable';
import { FilterRepresentationModel } from 'ng2-activiti-tasklist';
import { ActivitiProcessService } from '../services/activiti-process.service';
import { AlfrescoTranslationService, CoreModule } from 'ng2-alfresco-core';
@@ -60,8 +61,23 @@ describe('ActivitiProcessInstanceListComponent', () => {
});
}));
it('should initialise data table', () => {
fixture.detectChanges();
it('should use the default schemaColumn as default', () => {
component.ngOnInit();
expect(component.data.getColumns()).toBeDefined();
expect(component.data.getColumns().length).toEqual(4);
});
it('should use the schemaColumn passed in input', () => {
component.data = new ObjectDataTableAdapter(
[],
[
{type: 'text', key: 'fake-id', title: 'Name'}
]
);
component.ngOnInit();
expect(component.data.getColumns()).toBeDefined();
expect(component.data.getColumns().length).toEqual(1);
});
it('should fetch process instances when a filter is provided', () => {

View File

@@ -1,22 +0,0 @@
/*!
* @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.
*/
describe('Placeholder', () => {
it('test placeholder', () => {
expect(true).toBe(true);
});
});

View File

@@ -16,6 +16,7 @@
"LABELS": {
"STARTED_BY": "Started by",
"STARTED": "Started",
"ENDED": "Ended",
"COMMENTS": "Comments",
"START_FORM": "Start Form",
"TASKS_ACTIVE": "Active Tasks",

View File

@@ -36,4 +36,25 @@ export class ProcessInstance {
public tenantId: string;
public variables: any;
constructor(data?: any) {
this.businessKey = data && data.businessKey !== undefined ? data.businessKey : null;
this.ended = data && data.ended !== undefined ? data.ended : null;
this.graphicalNotationDefined = data && data.graphicalNotationDefined !== undefined ? data.graphicalNotationDefined : null;
this.id = data && data.id !== undefined ? data.id : null;
this.name = data && data.name !== undefined ? data.name : null;
this.processDefinitionCategory = data && data.processDefinitionCategory !== undefined ? data.processDefinitionCategory : null;
this.processDefinitionDeploymentId = data && data.processDefinitionDeploymentId !== undefined ? data.processDefinitionDeploymentId : null;
this.processDefinitionDescription = data && data.processDefinitionDescription !== undefined ? data.processDefinitionDescription : null;
this.processDefinitionId = data && data.processDefinitionId !== undefined ? data.processDefinitionId : null;
this.processDefinitionKey = data && data.processDefinitionKey !== undefined ? data.processDefinitionKey : null;
this.processDefinitionName = data && data.processDefinitionName !== undefined ? data.processDefinitionName : null;
this.processDefinitionVersion = data && data.processDefinitionVersion !== undefined ? data.processDefinitionVersion : null;
this.startFormDefined = data && data.startFormDefined !== undefined ? data.startFormDefined : null;
this.started = data && data.started !== undefined ? data.started : null;
this.startedBy = data && data.startedBy !== undefined ? data.startedBy : null;
this.suspended = data && data.suspended !== undefined ? data.suspended : null;
this.tenantId = data && data.tenantId !== undefined ? data.tenantId : null;
this.variables = data && data.variables !== undefined ? data.variables : null;
}
}