mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-26 17:24:56 +00:00
Merge pull request #901 from Alfresco/dev-denys--activiti-form-tests
Unit tests for Activiti Form component
This commit is contained in:
commit
ad6da9a657
@ -33,6 +33,9 @@ module.exports = function (config) {
|
||||
{pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: false},
|
||||
|
||||
'node_modules/alfresco-js-api/dist/alfresco-js-api.js',
|
||||
'node_modules/moment/min/moment.min.js',
|
||||
'node_modules/md-date-time-picker/dist/js/mdDateTimePicker.min.js',
|
||||
'node_modules/md-date-time-picker/dist/js/draggabilly.pkgd.min.js',
|
||||
{pattern: 'node_modules/ng2-translate/**/*.js', included: false, watched: false},
|
||||
{pattern: 'node_modules/ng2-translate/**/*.js.map', included: false, watched: false},
|
||||
|
||||
|
@ -21,6 +21,7 @@ import { ActivitiForm } from './activiti-form.component';
|
||||
import { FormModel, FormOutcomeModel, FormFieldModel, FormOutcomeEvent } from './widgets/index';
|
||||
import { FormService } from './../services/form.service';
|
||||
import { WidgetVisibilityService } from './../services/widget-visibility.service';
|
||||
import { NodeService } from './../services/node.service';
|
||||
|
||||
describe('ActivitiForm', () => {
|
||||
|
||||
@ -28,6 +29,7 @@ describe('ActivitiForm', () => {
|
||||
let formService: FormService;
|
||||
let formComponent: ActivitiForm;
|
||||
let visibilityService: WidgetVisibilityService;
|
||||
let nodeService: NodeService;
|
||||
|
||||
beforeEach(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
@ -39,7 +41,8 @@ describe('ActivitiForm', () => {
|
||||
window['componentHandler'] = componentHandler;
|
||||
|
||||
formService = new FormService(null, null);
|
||||
formComponent = new ActivitiForm(formService, visibilityService, null, null);
|
||||
nodeService = new NodeService(null);
|
||||
formComponent = new ActivitiForm(formService, visibilityService, null, nodeService);
|
||||
});
|
||||
|
||||
it('should upgrade MDL content on view checked', () => {
|
||||
@ -633,4 +636,84 @@ describe('ActivitiForm', () => {
|
||||
expect(visibilityService.refreshVisibility).toHaveBeenCalledWith(field.form);
|
||||
});
|
||||
|
||||
it('should load form for ecm node', () => {
|
||||
let metadata = {};
|
||||
spyOn(nodeService, 'getNodeMetadata').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next({ metadata: metadata });
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
spyOn(formComponent, 'loadFormFromActiviti').and.stub();
|
||||
|
||||
const nodeId = '<id>';
|
||||
formComponent.nodeId = nodeId;
|
||||
formComponent.ngOnInit();
|
||||
|
||||
expect(nodeService.getNodeMetadata).toHaveBeenCalledWith(nodeId);
|
||||
expect(formComponent.loadFormFromActiviti).toHaveBeenCalled();
|
||||
expect(formComponent.data).toBe(metadata);
|
||||
});
|
||||
|
||||
it('should disable outcome buttons for readonly form', () => {
|
||||
let formModel = new FormModel();
|
||||
formModel.readOnly = true;
|
||||
formComponent.form = formModel;
|
||||
|
||||
let outcome = new FormOutcomeModel(new FormModel(), {
|
||||
id: ActivitiForm.CUSTOM_OUTCOME_ID,
|
||||
name: 'Custom'
|
||||
});
|
||||
|
||||
expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should require outcome to eval button state', () => {
|
||||
formComponent.form = new FormModel();
|
||||
expect(formComponent.isOutcomeButtonEnabled(null)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should always enable save outcome for writeable form', () => {
|
||||
let formModel = new FormModel();
|
||||
let field = new FormFieldModel(formModel, {
|
||||
type: 'text',
|
||||
value: null,
|
||||
required: true
|
||||
});
|
||||
|
||||
formComponent.form = formModel;
|
||||
formModel.onFormFieldChanged(field);
|
||||
|
||||
expect(formModel.isValid).toBeFalsy();
|
||||
|
||||
let outcome = new FormOutcomeModel(new FormModel(), {
|
||||
id: ActivitiForm.SAVE_OUTCOME_ID,
|
||||
name: FormOutcomeModel.SAVE_ACTION
|
||||
});
|
||||
|
||||
formComponent.readOnly = true;
|
||||
expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should disable oucome buttons for invalid form', () => {
|
||||
let formModel = new FormModel();
|
||||
let field = new FormFieldModel(formModel, {
|
||||
type: 'text',
|
||||
value: null,
|
||||
required: true
|
||||
});
|
||||
|
||||
formComponent.form = formModel;
|
||||
formModel.onFormFieldChanged(field);
|
||||
|
||||
expect(formModel.isValid).toBeFalsy();
|
||||
|
||||
let outcome = new FormOutcomeModel(new FormModel(), {
|
||||
id: ActivitiForm.CUSTOM_OUTCOME_ID,
|
||||
name: 'Custom'
|
||||
});
|
||||
|
||||
expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeFalsy();
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -194,7 +194,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
|
||||
ngOnInit() {
|
||||
if (this.nodeId) {
|
||||
this.loadActivitiFormForEcmNode();
|
||||
this.loadFormForEcmNode();
|
||||
} else {
|
||||
this.loadForm();
|
||||
}
|
||||
@ -418,7 +418,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
private loadActivitiFormForEcmNode(): void {
|
||||
private loadFormForEcmNode(): void {
|
||||
this.nodeService.getNodeMetadata(this.nodeId).subscribe(data => {
|
||||
this.data = data.metadata;
|
||||
this.loadFormFromActiviti(data.nodeType);
|
||||
@ -426,7 +426,7 @@ export class ActivitiForm implements OnInit, AfterViewChecked, OnChanges {
|
||||
this.handleError);
|
||||
}
|
||||
|
||||
public loadFormFromActiviti(nodeType: string): any {
|
||||
loadFormFromActiviti(nodeType: string): any {
|
||||
this.formService.searchFrom(nodeType).subscribe(
|
||||
form => {
|
||||
if (!form) {
|
||||
|
@ -0,0 +1,45 @@
|
||||
/*!
|
||||
* @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 { AmountWidget } from './amount.widget';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
|
||||
describe('AmountWidget', () => {
|
||||
|
||||
let widget: AmountWidget;
|
||||
|
||||
beforeEach(() => {
|
||||
widget = new AmountWidget(null);
|
||||
});
|
||||
|
||||
it('should setup currentcy from field', () => {
|
||||
const currency = 'UAH';
|
||||
widget.field = new FormFieldModel(null, {
|
||||
currency: currency
|
||||
});
|
||||
|
||||
widget.ngOnInit();
|
||||
expect(widget.currency).toBe(currency);
|
||||
});
|
||||
|
||||
it('should setup default currency', () => {
|
||||
widget.field = null;
|
||||
widget.ngOnInit();
|
||||
expect(widget.currency).toBe(AmountWidget.DEFAULT_CURRENCY);
|
||||
});
|
||||
|
||||
});
|
@ -26,7 +26,9 @@ import { TextFieldWidgetComponent } from './../textfield-widget.component';
|
||||
})
|
||||
export class AmountWidget extends TextFieldWidgetComponent implements OnInit {
|
||||
|
||||
currency: string = '$';
|
||||
static DEFAULT_CURRENCY: string = '$';
|
||||
|
||||
currency: string = AmountWidget.DEFAULT_CURRENCY;
|
||||
|
||||
constructor(elementRef: ElementRef) {
|
||||
super(elementRef);
|
||||
|
@ -0,0 +1,293 @@
|
||||
/*!
|
||||
* @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 { AttachWidget } from './attach.widget';
|
||||
import { ActivitiAlfrescoContentService } from '../../../services/activiti-alfresco.service';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { FormFieldTypes } from '../core/form-field-types';
|
||||
import { ExternalContent } from '../core/external-content';
|
||||
import { ExternalContentLink } from '../core/external-content-link';
|
||||
|
||||
describe('AttachWidget', () => {
|
||||
|
||||
let widget: AttachWidget;
|
||||
let contentService: ActivitiAlfrescoContentService;
|
||||
let dialogPolyfill: any;
|
||||
|
||||
beforeEach(() => {
|
||||
contentService = new ActivitiAlfrescoContentService(null);
|
||||
widget = new AttachWidget(contentService);
|
||||
|
||||
dialogPolyfill = {
|
||||
registerDialog(obj: any) {
|
||||
obj.showModal = function () {};
|
||||
}
|
||||
};
|
||||
window['dialogPolyfill'] = dialogPolyfill;
|
||||
});
|
||||
|
||||
it('should require field value to check file', () => {
|
||||
widget.hasFile = false;
|
||||
widget.field = null;
|
||||
widget.ngOnInit();
|
||||
expect(widget.hasFile).toBeFalsy();
|
||||
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.UPLOAD,
|
||||
value: null
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.hasFile).toBeFalsy();
|
||||
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.UPLOAD,
|
||||
value: [{ name: 'file' }]
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.hasFile).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should setup with form field', () => {
|
||||
let nodes = [{}];
|
||||
spyOn(contentService, 'getAlfrescoNodes').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next(nodes);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
|
||||
let config = {
|
||||
siteId: '<id>',
|
||||
site: '<site>',
|
||||
pathId: '<pathId>',
|
||||
accountId: '<accountId>'
|
||||
};
|
||||
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.UPLOAD,
|
||||
params: {
|
||||
fileSource: {
|
||||
selectedFolder: config
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
|
||||
expect(widget.selectedFolderSiteId).toBe(config.siteId);
|
||||
expect(widget.selectedFolderSiteName).toBe(config.site);
|
||||
expect(widget.selectedFolderPathId).toBe(config.pathId);
|
||||
expect(widget.selectedFolderAccountId).toBe(config.accountId);
|
||||
expect(widget.selectedFolderNodes).toEqual(nodes);
|
||||
});
|
||||
|
||||
it('should link file on select', () => {
|
||||
let link = <ExternalContentLink> {};
|
||||
spyOn(contentService, 'linkAlfrescoNode').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next(link);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.UPLOAD
|
||||
});
|
||||
widget.ngOnInit();
|
||||
|
||||
let node = <ExternalContent> {};
|
||||
widget.selectFile(node, null);
|
||||
|
||||
expect(contentService.linkAlfrescoNode).toHaveBeenCalled();
|
||||
expect(widget.selectedFile).toBe(node);
|
||||
expect(widget.field.value).toEqual([link]);
|
||||
expect(widget.field.json.value).toEqual([link]);
|
||||
});
|
||||
|
||||
it('should reset', () => {
|
||||
widget.hasFile = true;
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.UPLOAD,
|
||||
value: [{ name: 'filename' }]
|
||||
});
|
||||
|
||||
widget.reset();
|
||||
expect(widget.hasFile).toBeFalsy();
|
||||
expect(widget.field.value).toBeNull();
|
||||
expect(widget.field.json.value).toBeNull();
|
||||
});
|
||||
|
||||
it('should close dialog on cancel', () => {
|
||||
let closed = false;
|
||||
widget.dialog = {
|
||||
nativeElement: {
|
||||
close: function() {
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
widget.cancel();
|
||||
expect(closed).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show modal dialog', () => {
|
||||
spyOn(contentService, 'getAlfrescoNodes').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next([]);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.UPLOAD,
|
||||
params: {
|
||||
fileSource: {
|
||||
selectedFolder: {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let modalShown = false;
|
||||
widget.dialog = {
|
||||
nativeElement: {
|
||||
showModal: function() {
|
||||
modalShown = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
widget.showDialog();
|
||||
expect(modalShown).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should select folder and load nodes', () => {
|
||||
let nodes = [{}];
|
||||
spyOn(contentService, 'getAlfrescoNodes').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next(nodes);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
|
||||
let node = <ExternalContent> { id: '<id>' };
|
||||
widget.selectFolder(node, null);
|
||||
|
||||
expect(widget.selectedFolderPathId).toBe(node.id);
|
||||
expect(widget.selectedFolderNodes).toEqual(nodes);
|
||||
});
|
||||
|
||||
it('should get linked file name via local variable', () => {
|
||||
widget.fileName = '<fileName>';
|
||||
widget.selectedFile = null;
|
||||
widget.field = null;
|
||||
expect(widget.getLinkedFileName()).toBe(widget.fileName);
|
||||
});
|
||||
|
||||
it('should get linked file name via selected file', () => {
|
||||
widget.fileName = null;
|
||||
widget.selectedFile = <ExternalContent> { title: '<title>' };
|
||||
widget.field = null;
|
||||
expect(widget.getLinkedFileName()).toBe(widget.selectedFile.title);
|
||||
});
|
||||
|
||||
it('should get linked file name via form field', () => {
|
||||
widget.fileName = null;
|
||||
widget.selectedFile = null;
|
||||
|
||||
let name = '<file>';
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.UPLOAD,
|
||||
value: [{ name: name }]
|
||||
});
|
||||
|
||||
expect(widget.getLinkedFileName()).toBe(name);
|
||||
});
|
||||
|
||||
it('should require form field to setup file browser', () => {
|
||||
widget.field = null;
|
||||
widget.setupFileBrowser();
|
||||
|
||||
expect(widget.selectedFolderPathId).toBeUndefined();
|
||||
expect(widget.selectedFolderAccountId).toBeUndefined();
|
||||
|
||||
const pathId = '<pathId>';
|
||||
const accountId = '<accountId>';
|
||||
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.UPLOAD,
|
||||
params: {
|
||||
fileSource: {
|
||||
selectedFolder: {
|
||||
pathId: pathId,
|
||||
accountId: accountId
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.setupFileBrowser();
|
||||
expect(widget.selectedFolderPathId).toBe(pathId);
|
||||
expect(widget.selectedFolderAccountId).toBe(accountId);
|
||||
});
|
||||
|
||||
it('should get external content nodes', () => {
|
||||
let nodes = [{}];
|
||||
spyOn(contentService, 'getAlfrescoNodes').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next(nodes);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
|
||||
const accountId = '<accountId>';
|
||||
const pathId = '<pathId>';
|
||||
widget.selectedFolderAccountId = accountId;
|
||||
widget.selectedFolderPathId = pathId;
|
||||
widget.getExternalContentNodes();
|
||||
|
||||
expect(contentService.getAlfrescoNodes).toHaveBeenCalledWith(accountId, pathId);
|
||||
expect(widget.selectedFolderNodes).toEqual(nodes);
|
||||
});
|
||||
|
||||
it('should handle error', () => {
|
||||
let error = 'error';
|
||||
spyOn(contentService, 'getAlfrescoNodes').and.returnValue(
|
||||
Observable.throw(error)
|
||||
);
|
||||
|
||||
spyOn(console, 'log').and.stub();
|
||||
widget.getExternalContentNodes();
|
||||
expect(console.log).toHaveBeenCalledWith(error);
|
||||
});
|
||||
|
||||
it('should register dialog via polyfill', () => {
|
||||
widget.dialog = {
|
||||
nativeElement: {}
|
||||
};
|
||||
spyOn(dialogPolyfill, 'registerDialog').and.callThrough();
|
||||
spyOn(widget, 'setupFileBrowser').and.stub();
|
||||
spyOn(widget, 'getExternalContentNodes').and.stub();
|
||||
widget.showDialog();
|
||||
expect(dialogPolyfill.registerDialog).toHaveBeenCalledWith(widget.dialog.nativeElement);
|
||||
});
|
||||
|
||||
it('should require configured dialog to show modal', () => {
|
||||
widget.dialog = null;
|
||||
spyOn(widget, 'setupFileBrowser').and.stub();
|
||||
spyOn(widget, 'getExternalContentNodes').and.stub();
|
||||
expect(widget.showDialog()).toBeFalsy();
|
||||
});
|
||||
});
|
@ -53,24 +53,30 @@ export class AttachWidget extends WidgetComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.field &&
|
||||
this.field.value) {
|
||||
this.hasFile = true;
|
||||
}
|
||||
if (this.field &&
|
||||
this.field.params &&
|
||||
this.field.params.fileSource &&
|
||||
this.field.params.fileSource.selectedFolder) {
|
||||
this.selectedFolderSiteId = this.field.params.fileSource.selectedFolder.siteId;
|
||||
this.selectedFolderSiteName = this.field.params.fileSource.selectedFolder.site;
|
||||
this.setupFileBrowser();
|
||||
this.getExternalContentNodes();
|
||||
if (this.field) {
|
||||
if (this.field.value) {
|
||||
this.hasFile = true;
|
||||
}
|
||||
|
||||
let params = this.field.params;
|
||||
|
||||
if (params &&
|
||||
params.fileSource &&
|
||||
params.fileSource.selectedFolder) {
|
||||
this.selectedFolderSiteId = params.fileSource.selectedFolder.siteId;
|
||||
this.selectedFolderSiteName = params.fileSource.selectedFolder.site;
|
||||
this.setupFileBrowser();
|
||||
this.getExternalContentNodes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private setupFileBrowser() {
|
||||
this.selectedFolderPathId = this.field.params.fileSource.selectedFolder.pathId;
|
||||
this.selectedFolderAccountId = this.field.params.fileSource.selectedFolder.accountId;
|
||||
setupFileBrowser() {
|
||||
if (this.field) {
|
||||
let params = this.field.params;
|
||||
this.selectedFolderPathId = params.fileSource.selectedFolder.pathId;
|
||||
this.selectedFolderAccountId = params.fileSource.selectedFolder.accountId;
|
||||
}
|
||||
}
|
||||
|
||||
getLinkedFileName(): string {
|
||||
@ -80,7 +86,8 @@ export class AttachWidget extends WidgetComponent implements OnInit {
|
||||
this.selectedFile.title) {
|
||||
result = this.selectedFile.title;
|
||||
}
|
||||
if (this.field.value &&
|
||||
if (this.field &&
|
||||
this.field.value &&
|
||||
this.field.value.length > 0 &&
|
||||
this.field.value[0].name) {
|
||||
result = this.field.value[0].name;
|
||||
@ -89,14 +96,12 @@ export class AttachWidget extends WidgetComponent implements OnInit {
|
||||
return result;
|
||||
}
|
||||
|
||||
private getExternalContentNodes() {
|
||||
|
||||
getExternalContentNodes() {
|
||||
this.contentService.getAlfrescoNodes(this.selectedFolderAccountId, this.selectedFolderPathId)
|
||||
.subscribe(
|
||||
(nodes) => {
|
||||
this.selectedFolderNodes = nodes;
|
||||
},
|
||||
error => console.error(error));
|
||||
nodes => this.selectedFolderNodes = nodes,
|
||||
error => this.handleError(error)
|
||||
);
|
||||
}
|
||||
|
||||
selectFile(node: ExternalContent, $event: any) {
|
||||
@ -116,17 +121,19 @@ export class AttachWidget extends WidgetComponent implements OnInit {
|
||||
this.getExternalContentNodes();
|
||||
}
|
||||
|
||||
public showDialog() {
|
||||
showDialog(): boolean {
|
||||
this.setupFileBrowser();
|
||||
this.getExternalContentNodes();
|
||||
|
||||
if (!this.dialog.nativeElement.showModal) {
|
||||
dialogPolyfill.registerDialog(this.dialog.nativeElement);
|
||||
}
|
||||
|
||||
if (this.dialog) {
|
||||
if (!this.dialog.nativeElement.showModal) {
|
||||
dialogPolyfill.registerDialog(this.dialog.nativeElement);
|
||||
}
|
||||
|
||||
this.dialog.nativeElement.showModal();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private closeDialog() {
|
||||
@ -135,7 +142,7 @@ export class AttachWidget extends WidgetComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
public cancel() {
|
||||
cancel() {
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,7 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
*/
|
||||
if (json.type === FormFieldTypes.DATE) {
|
||||
if (value) {
|
||||
let d = moment(value.split('T')[0]);
|
||||
let d = moment(value.split('T')[0], 'YYYY-M-D');
|
||||
if (d.isValid()) {
|
||||
value = d.format('D-M-YYYY');
|
||||
}
|
||||
|
@ -0,0 +1,146 @@
|
||||
/*!
|
||||
* @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 { DateWidget } from './date.widget';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
|
||||
describe('DateWidget', () => {
|
||||
|
||||
let widget: DateWidget;
|
||||
let nativeElement: any;
|
||||
let elementRef: ElementRef;
|
||||
|
||||
beforeEach(() => {
|
||||
nativeElement = {
|
||||
querySelector: function () {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
elementRef = new ElementRef(nativeElement);
|
||||
widget = new DateWidget(elementRef);
|
||||
});
|
||||
|
||||
it('should setup basic date picker settings on init ', () => {
|
||||
expect(widget.datePicker).toBeUndefined();
|
||||
widget.ngOnInit();
|
||||
expect(widget.datePicker).toBeDefined();
|
||||
});
|
||||
|
||||
it('should setup min value for date picker', () => {
|
||||
let minValue = '13-03-1982';
|
||||
widget.field = new FormFieldModel(null, {
|
||||
minValue: minValue
|
||||
});
|
||||
widget.ngOnInit();
|
||||
|
||||
let expected = moment(minValue, widget.DATE_FORMAT);
|
||||
expect(widget.datePicker._past.isSame(expected)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should setup max value for date picker', () => {
|
||||
let maxValue = '31-03-1982';
|
||||
widget.field = new FormFieldModel(null, {
|
||||
maxValue: maxValue
|
||||
});
|
||||
widget.ngOnInit();
|
||||
|
||||
let expected = moment(maxValue, widget.DATE_FORMAT);
|
||||
expect(widget.datePicker._future.isSame(expected)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should setup default time value for date picker', () => {
|
||||
let dateValue = '13-03-1982';
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: 'date',
|
||||
value: '1982-03-13'
|
||||
});
|
||||
widget.ngOnInit();
|
||||
|
||||
let expected = moment(dateValue, widget.DATE_FORMAT);
|
||||
expect(widget.datePicker.time.isSame(expected)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should setup trigger element', () => {
|
||||
let el = {};
|
||||
spyOn(nativeElement, 'querySelector').and.returnValue(el);
|
||||
widget.ngOnInit();
|
||||
expect(widget.datePicker.trigger).toBe(el);
|
||||
});
|
||||
|
||||
it('should not setup trigger element', () => {
|
||||
let w = new DateWidget(null);
|
||||
w.ngOnInit();
|
||||
expect(w.datePicker.trigger).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should eval visibility on date changed', () => {
|
||||
spyOn(widget, 'checkVisibility').and.callThrough();
|
||||
|
||||
let field = new FormFieldModel(null);
|
||||
widget.field = field;
|
||||
|
||||
widget.onDateChanged();
|
||||
expect(widget.checkVisibility).toHaveBeenCalledWith(field);
|
||||
});
|
||||
|
||||
it('should update picker value on input date changed', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: 'date',
|
||||
value: '13-03-1982'
|
||||
});
|
||||
widget.ngOnInit();
|
||||
widget.field.value = '31-03-1982';
|
||||
widget.onDateChanged();
|
||||
|
||||
let expected = moment('31-03-1982', widget.DATE_FORMAT);
|
||||
expect(widget.datePicker.time.isSame(expected)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should update field value on date selected', () => {
|
||||
widget.field = new FormFieldModel(null, { type: 'date' });
|
||||
widget.ngOnInit();
|
||||
|
||||
let date = '13-3-1982';
|
||||
widget.datePicker.time = moment(date, widget.DATE_FORMAT);
|
||||
widget.onDateSelected();
|
||||
expect(widget.field.value).toBe(date);
|
||||
});
|
||||
|
||||
it('should update material textfield on date selected', () => {
|
||||
spyOn(widget, 'setupMaterialTextField').and.callThrough();
|
||||
|
||||
widget.field = new FormFieldModel(null, { type: 'date' });
|
||||
widget.ngOnInit();
|
||||
|
||||
widget.datePicker.time = moment();
|
||||
widget.onDateSelected();
|
||||
expect(widget.setupMaterialTextField).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not update material textfield on date selected', () => {
|
||||
let w = new DateWidget(null);
|
||||
spyOn(w, 'setupMaterialTextField').and.callThrough();
|
||||
|
||||
w.field = new FormFieldModel(null, { type: 'date' });
|
||||
w.ngOnInit();
|
||||
|
||||
w.datePicker.time = moment();
|
||||
w.onDateSelected();
|
||||
expect(w.setupMaterialTextField).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -26,7 +26,7 @@ import { TextFieldWidgetComponent } from './../textfield-widget.component';
|
||||
})
|
||||
export class DateWidget extends TextFieldWidgetComponent implements OnInit {
|
||||
|
||||
private dateFormat: string = 'D-M-YYYY';
|
||||
DATE_FORMAT: string = 'D-M-YYYY';
|
||||
|
||||
datePicker: any;
|
||||
|
||||
@ -44,41 +44,37 @@ export class DateWidget extends TextFieldWidgetComponent implements OnInit {
|
||||
if (this.field) {
|
||||
|
||||
if (this.field.minValue) {
|
||||
let min = moment(this.field.minValue, this.dateFormat);
|
||||
if (min.isValid()) {
|
||||
settings.past = min;
|
||||
}
|
||||
settings.past = moment(this.field.minValue, this.DATE_FORMAT);
|
||||
}
|
||||
|
||||
if (this.field.maxValue) {
|
||||
let max = moment(this.field.maxValue, this.dateFormat);
|
||||
if (max.isValid()) {
|
||||
settings.future = max;
|
||||
}
|
||||
settings.future = moment(this.field.maxValue, this.DATE_FORMAT);
|
||||
}
|
||||
|
||||
if (this.field.value) {
|
||||
settings.time = moment(this.field.value, this.dateFormat);
|
||||
settings.init = moment(this.field.value, this.DATE_FORMAT);
|
||||
}
|
||||
}
|
||||
|
||||
this.datePicker = new mdDateTimePicker.default(settings);
|
||||
this.datePicker.trigger = this.elementRef.nativeElement.querySelector('#dateInput');
|
||||
if (this.elementRef) {
|
||||
this.datePicker.trigger = this.elementRef.nativeElement.querySelector('#dateInput');
|
||||
}
|
||||
}
|
||||
|
||||
onDateChanged() {
|
||||
if (this.field.value) {
|
||||
this.datePicker.time = moment(this.field.value, this.dateFormat);
|
||||
this.datePicker.time = moment(this.field.value, this.DATE_FORMAT);
|
||||
}
|
||||
this.checkVisibility(this.field);
|
||||
}
|
||||
|
||||
onDateSelected() {
|
||||
this.field.value = this.datePicker.time.format('DD-MM-YYYY');
|
||||
let el = this.elementRef.nativeElement;
|
||||
let container = el.querySelector('.mdl-textfield');
|
||||
if (container) {
|
||||
container.MaterialTextfield.change(this.field.value.toString());
|
||||
let newValue = this.datePicker.time.format(this.DATE_FORMAT);
|
||||
this.field.value = newValue;
|
||||
|
||||
if (this.elementRef) {
|
||||
this.setupMaterialTextField(this.elementRef, componentHandler, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,542 @@
|
||||
/*!
|
||||
* @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 { DisplayValueWidget } from './display-value.widget';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { FormFieldTypes } from '../core/form-field-types';
|
||||
import { FormModel } from '../core/form.model';
|
||||
|
||||
describe('DisplayValueWidget', () => {
|
||||
|
||||
let widget: DisplayValueWidget;
|
||||
let formService: FormService;
|
||||
|
||||
beforeEach(() => {
|
||||
formService = new FormService(null, null);
|
||||
widget = new DisplayValueWidget(formService);
|
||||
});
|
||||
|
||||
it('should require field to setup default value', () => {
|
||||
widget.field = null;
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should take field value on init', () => {
|
||||
let value = '<value>';
|
||||
widget.field = new FormFieldModel(null, { value: value });
|
||||
widget.field.params = null;
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe(value);
|
||||
});
|
||||
|
||||
it('should setup [BOOLEAN] field', () => {
|
||||
expect(widget.value).toBeUndefined();
|
||||
|
||||
// test TRUE value
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: 'true',
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.BOOLEAN
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBeTruthy();
|
||||
|
||||
// test FALSE value
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: 'false',
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.BOOLEAN
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBeFalsy();
|
||||
});
|
||||
|
||||
it ('should setup [FUNCTIONAL-GROUP] field', () => {
|
||||
let groupName: '<group>';
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: {
|
||||
name: groupName
|
||||
},
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.FUNCTIONAL_GROUP
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe(groupName);
|
||||
});
|
||||
|
||||
it('should not setup [FUNCTIONAL-GROUP] field when missing value', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.FUNCTIONAL_GROUP
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBeNull();
|
||||
});
|
||||
|
||||
it('should setup [PEOPLE] field', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe'
|
||||
},
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.PEOPLE
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe('John Doe');
|
||||
});
|
||||
|
||||
it('should not setup [PEOPLE] field whem missing value', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.PEOPLE
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should setup [UPLOAD] field', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: [
|
||||
{ name: 'file1' }
|
||||
],
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.UPLOAD
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe('file1');
|
||||
});
|
||||
|
||||
it('should not setup [UPLOAD] field when missing value', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
value: null,
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.UPLOAD
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBeNull();
|
||||
});
|
||||
|
||||
it('should not setup [UPLOAD] field when empty value', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
value: [],
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.UPLOAD
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBeNull();
|
||||
});
|
||||
|
||||
it('should setup [TYPEAHEAD] field', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.TYPEAHEAD
|
||||
}
|
||||
}
|
||||
});
|
||||
spyOn(widget, 'loadRestFieldValue').and.stub();
|
||||
widget.ngOnInit();
|
||||
expect(widget.loadRestFieldValue).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should setup [DROPDOWN] field with REST config', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.DROPDOWN
|
||||
}
|
||||
}
|
||||
});
|
||||
spyOn(widget, 'loadRestFieldValue').and.stub();
|
||||
widget.ngOnInit();
|
||||
expect(widget.loadRestFieldValue).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should setup [RADIO_BUTTONS] field', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
restUrl: null,
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.RADIO_BUTTONS
|
||||
}
|
||||
}
|
||||
});
|
||||
spyOn(widget, 'loadRadioButtonValue').and.stub();
|
||||
widget.ngOnInit();
|
||||
expect(widget.loadRadioButtonValue).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should setup [RADIO_BUTTONS] value by options', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
restUrl: null,
|
||||
value: '2',
|
||||
options: [
|
||||
{ id: '1', name: 'option 1' },
|
||||
{ id: '2', name: 'option 2' }
|
||||
],
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.RADIO_BUTTONS
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe('option 2');
|
||||
});
|
||||
|
||||
it('should not setup [RADIO_BUTTONS] value with missing option', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
restUrl: null,
|
||||
value: '100',
|
||||
options: [
|
||||
{ id: '1', name: 'option 1' },
|
||||
{ id: '2', name: 'option 2' }
|
||||
],
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.RADIO_BUTTONS
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe('100');
|
||||
});
|
||||
|
||||
it('should not setup [RADIO_BUTTONS] when missing options', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
restUrl: null,
|
||||
value: '100',
|
||||
options: null,
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.RADIO_BUTTONS
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.field.options = null;
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe('100');
|
||||
});
|
||||
|
||||
it('should setup [RADIO_BUTTONS] field with REST config', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
restUrl: '<url>',
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.RADIO_BUTTONS
|
||||
}
|
||||
}
|
||||
});
|
||||
spyOn(widget, 'loadRestFieldValue').and.stub();
|
||||
widget.ngOnInit();
|
||||
expect(widget.loadRestFieldValue).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should setup rest field values with REST options', () => {
|
||||
spyOn(formService, 'getRestFieldValues').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next([
|
||||
{ id: '1', name: 'option 1' },
|
||||
{ id: '2', name: 'option 2' }
|
||||
]);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
|
||||
let form = new FormModel({ taskId: '<id>' });
|
||||
|
||||
widget.field = new FormFieldModel(form, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
restUrl: '<url>',
|
||||
value: '2',
|
||||
options: [
|
||||
{ id: '1', name: 'option 1' },
|
||||
{ id: '2', name: 'option 2' }
|
||||
],
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.RADIO_BUTTONS
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(formService.getRestFieldValues).toHaveBeenCalled();
|
||||
expect(widget.value).toBe('option 2');
|
||||
});
|
||||
|
||||
it('should not setup rest field values with missing REST option', () => {
|
||||
spyOn(formService, 'getRestFieldValues').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next([
|
||||
{ id: '1', name: 'option 1' },
|
||||
{ id: '2', name: 'option 2' }
|
||||
]);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
|
||||
let form = new FormModel({ taskId: '<id>' });
|
||||
|
||||
widget.field = new FormFieldModel(form, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
restUrl: '<url>',
|
||||
value: '100',
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.RADIO_BUTTONS
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(formService.getRestFieldValues).toHaveBeenCalled();
|
||||
expect(widget.value).toBe('100');
|
||||
});
|
||||
|
||||
it('should not setup rest field values with no REST response', () => {
|
||||
spyOn(formService, 'getRestFieldValues').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next(null);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
|
||||
let form = new FormModel({ taskId: '<id>' });
|
||||
|
||||
widget.field = new FormFieldModel(form, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
restUrl: '<url>',
|
||||
value: '100',
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.RADIO_BUTTONS
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(formService.getRestFieldValues).toHaveBeenCalled();
|
||||
expect(widget.value).toBe('100');
|
||||
});
|
||||
|
||||
it('should handle rest error', () => {
|
||||
const error = 'ERROR';
|
||||
spyOn(formService, 'getRestFieldValues').and.returnValue(
|
||||
Observable.throw(error)
|
||||
);
|
||||
|
||||
spyOn(console, 'log').and.stub();
|
||||
|
||||
let form = new FormModel({ taskId: '<id>' });
|
||||
|
||||
widget.field = new FormFieldModel(form, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
restUrl: '<url>',
|
||||
value: '100',
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.RADIO_BUTTONS
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(formService.getRestFieldValues).toHaveBeenCalled();
|
||||
expect(console.log).toHaveBeenCalledWith(error);
|
||||
expect(widget.value).toBe('100');
|
||||
});
|
||||
|
||||
it('should setup [DATE] field with valid date', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: '1982-03-13T00:00:00.000Z',
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.DATE
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe('13-3-1982');
|
||||
});
|
||||
|
||||
it('should setup [DATE] field with invalid date', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: '<invalid value>',
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.DATE
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe('<invalid value>');
|
||||
});
|
||||
|
||||
it('should not setup [DATE] field when missing value', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.DATE
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should setup [AMOUNT] field with default currency', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: 11,
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.AMOUNT
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe('$ 11');
|
||||
});
|
||||
|
||||
it('should setup [AMOUNT] field with custom currency', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: 12.6,
|
||||
currency: 'UAH',
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.AMOUNT
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe('UAH 12.6');
|
||||
});
|
||||
|
||||
it('should not setup [AMOUNT] field when missing value', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.AMOUNT
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should setup [HYPERLINK] field', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
hyperlinkUrl: 'www.some-url.com',
|
||||
displayText: 'Custom URL',
|
||||
params: {
|
||||
field: {
|
||||
type: FormFieldTypes.HYPERLINK
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.linkUrl).toBe(`http://${widget.field.hyperlinkUrl}`);
|
||||
expect(widget.linkText).toBe(widget.field.displayText);
|
||||
});
|
||||
|
||||
it('should take default value for unknown field type', () => {
|
||||
const value = '<value>';
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: value,
|
||||
params: {
|
||||
field: {
|
||||
type: '<unknown type>'
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe(value);
|
||||
});
|
||||
|
||||
it('should take default value when missing params', () => {
|
||||
const value = '<value>';
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: value
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe(value);
|
||||
});
|
||||
|
||||
it('should take default value when missing enclosed field type', () => {
|
||||
const value = '<value>';
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.DISPLAY_VALUE,
|
||||
value: value,
|
||||
params: {
|
||||
field: {
|
||||
}
|
||||
}
|
||||
});
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe(value);
|
||||
});
|
||||
|
||||
});
|
@ -53,6 +53,8 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
|
||||
case FormFieldTypes.FUNCTIONAL_GROUP:
|
||||
if (this.field.value) {
|
||||
this.value = this.field.value.name;
|
||||
} else {
|
||||
this.value = null;
|
||||
}
|
||||
break;
|
||||
case FormFieldTypes.PEOPLE:
|
||||
@ -66,6 +68,8 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
|
||||
let files = this.field.value || [];
|
||||
if (files.length > 0) {
|
||||
this.value = decodeURI(files[0].name);
|
||||
} else {
|
||||
this.value = null;
|
||||
}
|
||||
break;
|
||||
case FormFieldTypes.TYPEAHEAD:
|
||||
@ -83,7 +87,7 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
|
||||
break;
|
||||
case FormFieldTypes.DATE:
|
||||
if (this.value) {
|
||||
let d = moment(this.value.split('T')[0]);
|
||||
let d = moment(this.value.split('T')[0], 'YYYY-M-D');
|
||||
if (d.isValid()) {
|
||||
this.value = d.format('D-M-YYYY');
|
||||
}
|
||||
@ -96,10 +100,8 @@ export class DisplayValueWidget extends WidgetComponent implements OnInit {
|
||||
}
|
||||
break;
|
||||
case FormFieldTypes.HYPERLINK:
|
||||
if (this.value) {
|
||||
this.linkUrl = this.getHyperlinkUrl(this.field);
|
||||
this.linkText = this.getHyperlinkText(this.field);
|
||||
}
|
||||
this.linkUrl = this.getHyperlinkUrl(this.field);
|
||||
this.linkText = this.getHyperlinkText(this.field);
|
||||
break;
|
||||
default:
|
||||
this.value = this.field.value;
|
||||
|
@ -20,6 +20,7 @@ import { FormService } from '../../../services/form.service';
|
||||
import { DropdownWidget } from './dropdown.widget';
|
||||
import { FormModel } from './../core/form.model';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { FormFieldOption } from './../core/form-field-option';
|
||||
|
||||
describe('DropdownWidget', () => {
|
||||
|
||||
@ -32,6 +33,18 @@ describe('DropdownWidget', () => {
|
||||
widget.field = new FormFieldModel(new FormModel());
|
||||
});
|
||||
|
||||
it('should require field with restUrl', () => {
|
||||
spyOn(formService, 'getRestFieldValues').and.stub();
|
||||
|
||||
widget.field = null;
|
||||
widget.ngOnInit();
|
||||
expect(formService.getRestFieldValues).not.toHaveBeenCalled();
|
||||
|
||||
widget.field = new FormFieldModel(null, { restUrl: null });
|
||||
widget.ngOnInit();
|
||||
expect(formService.getRestFieldValues).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should request field values from service', () => {
|
||||
const taskId = '<form-id>';
|
||||
const fieldId = '<field-id>';
|
||||
@ -45,10 +58,12 @@ describe('DropdownWidget', () => {
|
||||
restUrl: '<url>'
|
||||
});
|
||||
|
||||
spyOn(formService, 'getRestFieldValues').and.returnValue(Observable.create(observer => {
|
||||
observer.next(null);
|
||||
observer.complete();
|
||||
}));
|
||||
spyOn(formService, 'getRestFieldValues').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next(null);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
widget.ngOnInit();
|
||||
expect(formService.getRestFieldValues).toHaveBeenCalledWith(taskId, fieldId);
|
||||
});
|
||||
@ -58,4 +73,29 @@ describe('DropdownWidget', () => {
|
||||
widget.handleError('Err');
|
||||
expect(console.error).toHaveBeenCalledWith('Err');
|
||||
});
|
||||
|
||||
it('should preserve empty option when loading fields', () => {
|
||||
let restFieldValue: FormFieldOption = <FormFieldOption> { id: '1', name: 'Option1' };
|
||||
spyOn(formService, 'getRestFieldValues').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next([restFieldValue]);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
|
||||
let form = new FormModel({ taskId: '<id>' });
|
||||
let emptyOption: FormFieldOption = <FormFieldOption> { id: 'empty', name: 'Empty' };
|
||||
widget.field = new FormFieldModel(form, {
|
||||
id: '<id>',
|
||||
restUrl: '/some/url/address',
|
||||
hasEmptyValue: true,
|
||||
options: [emptyOption]
|
||||
});
|
||||
widget.ngOnInit();
|
||||
|
||||
expect(formService.getRestFieldValues).toHaveBeenCalled();
|
||||
expect(widget.field.options.length).toBe(2);
|
||||
expect(widget.field.options[0]).toBe(emptyOption);
|
||||
expect(widget.field.options[1]).toBe(restFieldValue);
|
||||
});
|
||||
});
|
||||
|
@ -15,6 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ElementRef } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { FunctionalGroupWidget } from './functional-group.widget';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
@ -24,12 +25,20 @@ import { GroupModel } from '../core/group.model';
|
||||
|
||||
describe('FunctionalGroupWidget', () => {
|
||||
|
||||
let componentHandler;
|
||||
let formService: FormService;
|
||||
let elementRef: ElementRef;
|
||||
let widget: FunctionalGroupWidget;
|
||||
|
||||
beforeEach(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
'upgradeAllRegistered'
|
||||
]);
|
||||
window['componentHandler'] = componentHandler;
|
||||
|
||||
formService = new FormService(null, null);
|
||||
widget = new FunctionalGroupWidget(formService, null);
|
||||
elementRef = new ElementRef(null);
|
||||
widget = new FunctionalGroupWidget(formService, elementRef);
|
||||
widget.field = new FormFieldModel(new FormModel());
|
||||
});
|
||||
|
||||
@ -39,7 +48,7 @@ describe('FunctionalGroupWidget', () => {
|
||||
|
||||
spyOn(formService, 'getWorkflowGroups').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next([]);
|
||||
observer.next(null);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
@ -219,4 +228,37 @@ describe('FunctionalGroupWidget', () => {
|
||||
expect(formService.getWorkflowGroups).not.toHaveBeenCalled();
|
||||
expect(widget.popupVisible).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should setup mdl textfield on view init', () => {
|
||||
spyOn(widget, 'setupMaterialComponents').and.callThrough();
|
||||
spyOn(widget, 'setupMaterialTextField').and.callThrough();
|
||||
|
||||
widget.value = '<value>';
|
||||
widget.ngAfterViewInit();
|
||||
|
||||
expect(widget.setupMaterialComponents).toHaveBeenCalledWith(componentHandler);
|
||||
expect(widget.setupMaterialTextField).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should require component handler to setup textfield', () => {
|
||||
expect(widget.setupMaterialComponents(null)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should require element reference to setup textfield', () => {
|
||||
let w = new FunctionalGroupWidget(formService, null);
|
||||
w.value = '<value>';
|
||||
expect(w.setupMaterialComponents(componentHandler)).toBeFalsy();
|
||||
|
||||
w = new FunctionalGroupWidget(formService, elementRef);
|
||||
w.value = '<value>';
|
||||
expect(w.setupMaterialComponents(componentHandler)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should require value to setup textfield', () => {
|
||||
widget.value = '<value>';
|
||||
expect(widget.setupMaterialComponents(componentHandler)).toBeTruthy();
|
||||
|
||||
widget.value = null;
|
||||
expect(widget.setupMaterialComponents(componentHandler)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
@ -109,16 +109,12 @@ export class FunctionalGroupWidget extends WidgetComponent implements OnInit {
|
||||
}
|
||||
|
||||
setupMaterialComponents(handler: any): boolean {
|
||||
// workaround for MDL issues with dynamic components
|
||||
super.setupMaterialComponents(handler);
|
||||
if (handler) {
|
||||
handler.upgradeAllRegistered();
|
||||
if (this.elementRef && this.value) {
|
||||
let container = this.elementRef.nativeElement.querySelector('.mdl-textfield');
|
||||
if (container) {
|
||||
container.MaterialTextfield.change(this.value);
|
||||
}
|
||||
this.setupMaterialTextField(this.elementRef, handler, this.value);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
/*!
|
||||
* @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 { MultilineTextWidget } from './multiline-text.widget';
|
||||
|
||||
describe('MultilineTextWidget', () => {
|
||||
|
||||
let widget: MultilineTextWidget;
|
||||
|
||||
beforeEach(() => {
|
||||
widget = new MultilineTextWidget(null);
|
||||
});
|
||||
|
||||
it('should exist', () => {
|
||||
expect(widget).toBeDefined();
|
||||
});
|
||||
});
|
@ -0,0 +1,31 @@
|
||||
/*!
|
||||
* @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 { NumberWidget } from './number.widget';
|
||||
|
||||
describe('NumberWidget', () => {
|
||||
|
||||
let widget: NumberWidget;
|
||||
|
||||
beforeEach(() => {
|
||||
widget = new NumberWidget(null);
|
||||
});
|
||||
|
||||
it('should exist', () => {
|
||||
expect(widget).toBeDefined();
|
||||
});
|
||||
});
|
@ -15,6 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ElementRef } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { PeopleWidget } from './people.widget';
|
||||
import { FormService } from '../../../services/form.service';
|
||||
@ -24,12 +25,20 @@ import { GroupUserModel } from '../core/group-user.model';
|
||||
|
||||
describe('PeopleWidget', () => {
|
||||
|
||||
let componentHandler;
|
||||
let elementRef: ElementRef;
|
||||
let formService: FormService;
|
||||
let widget: PeopleWidget;
|
||||
|
||||
beforeEach(() => {
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
'upgradeAllRegistered'
|
||||
]);
|
||||
window['componentHandler'] = componentHandler;
|
||||
|
||||
formService = new FormService(null, null);
|
||||
widget = new PeopleWidget(formService, null);
|
||||
elementRef = new ElementRef(null);
|
||||
widget = new PeopleWidget(formService, elementRef);
|
||||
widget.field = new FormFieldModel(new FormModel());
|
||||
});
|
||||
|
||||
@ -45,6 +54,16 @@ describe('PeopleWidget', () => {
|
||||
expect(widget.getDisplayName(model)).toBe('John Doe');
|
||||
});
|
||||
|
||||
it('should skip first name for display name', () => {
|
||||
let model = new GroupUserModel({ firstName: null, lastName: 'Doe' });
|
||||
expect(widget.getDisplayName(model)).toBe('Doe');
|
||||
});
|
||||
|
||||
it('should skip last name for display name', () => {
|
||||
let model = new GroupUserModel({ firstName: 'John', lastName: null });
|
||||
expect(widget.getDisplayName(model)).toBe('John');
|
||||
});
|
||||
|
||||
it('should flush value on blur', (done) => {
|
||||
spyOn(widget, 'flushValue').and.stub();
|
||||
widget.onBlur();
|
||||
@ -61,10 +80,12 @@ describe('PeopleWidget', () => {
|
||||
lastName: 'Doe'
|
||||
});
|
||||
|
||||
spyOn(formService, 'getWorkflowUsers').and.returnValue(Observable.create(observer => {
|
||||
observer.next([]);
|
||||
observer.complete();
|
||||
}));
|
||||
spyOn(formService, 'getWorkflowUsers').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next(null);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
|
||||
widget.ngOnInit();
|
||||
expect(widget.value).toBe('John Doe');
|
||||
@ -103,10 +124,12 @@ describe('PeopleWidget', () => {
|
||||
|
||||
it('should fetch users by search term', () => {
|
||||
let users = [{}, {}];
|
||||
spyOn(formService, 'getWorkflowUsers').and.returnValue(Observable.create(observer => {
|
||||
observer.next(users);
|
||||
observer.complete();
|
||||
}));
|
||||
spyOn(formService, 'getWorkflowUsers').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next(users);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
|
||||
widget.value = 'user1';
|
||||
widget.onKeyUp(null);
|
||||
@ -118,10 +141,12 @@ describe('PeopleWidget', () => {
|
||||
|
||||
it('should fetch users by search term and group id', () => {
|
||||
let users = [{}, {}];
|
||||
spyOn(formService, 'getWorkflowUsers').and.returnValue(Observable.create(observer => {
|
||||
observer.next(users);
|
||||
observer.complete();
|
||||
}));
|
||||
spyOn(formService, 'getWorkflowUsers').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next(users);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
|
||||
widget.value = 'user1';
|
||||
widget.groupId = '1001';
|
||||
@ -133,10 +158,12 @@ describe('PeopleWidget', () => {
|
||||
});
|
||||
|
||||
it('should fetch users and show no popup', () => {
|
||||
spyOn(formService, 'getWorkflowUsers').and.returnValue(Observable.create(observer => {
|
||||
observer.next(null);
|
||||
observer.complete();
|
||||
}));
|
||||
spyOn(formService, 'getWorkflowUsers').and.returnValue(
|
||||
Observable.create(observer => {
|
||||
observer.next(null);
|
||||
observer.complete();
|
||||
})
|
||||
);
|
||||
|
||||
widget.value = 'user1';
|
||||
widget.onKeyUp(null);
|
||||
@ -209,4 +236,37 @@ describe('PeopleWidget', () => {
|
||||
expect(widget.value).toBeNull();
|
||||
expect(widget.field.value).toBeNull();
|
||||
});
|
||||
|
||||
it('should setup mdl textfield on view init', () => {
|
||||
spyOn(widget, 'setupMaterialComponents').and.callThrough();
|
||||
spyOn(widget, 'setupMaterialTextField').and.callThrough();
|
||||
|
||||
widget.value = '<value>';
|
||||
widget.ngAfterViewInit();
|
||||
|
||||
expect(widget.setupMaterialComponents).toHaveBeenCalledWith(componentHandler);
|
||||
expect(widget.setupMaterialTextField).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should require component handler to setup textfield', () => {
|
||||
expect(widget.setupMaterialComponents(null)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should require element reference to setup textfield', () => {
|
||||
let w = new PeopleWidget(formService, null);
|
||||
w.value = '<value>';
|
||||
expect(w.setupMaterialComponents(componentHandler)).toBeFalsy();
|
||||
|
||||
w = new PeopleWidget(formService, elementRef);
|
||||
w.value = '<value>';
|
||||
expect(w.setupMaterialComponents(componentHandler)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should require value to setup textfield', () => {
|
||||
widget.value = '<value>';
|
||||
expect(widget.setupMaterialComponents(componentHandler)).toBeTruthy();
|
||||
|
||||
widget.value = null;
|
||||
expect(widget.setupMaterialComponents(componentHandler)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
@ -122,16 +122,12 @@ export class PeopleWidget extends WidgetComponent implements OnInit {
|
||||
}
|
||||
|
||||
setupMaterialComponents(handler: any): boolean {
|
||||
// workaround for MDL issues with dynamic components
|
||||
super.setupMaterialComponents(handler);
|
||||
if (handler) {
|
||||
handler.upgradeAllRegistered();
|
||||
if (this.elementRef && this.value) {
|
||||
let container = this.elementRef.nativeElement.querySelector('.mdl-textfield');
|
||||
if (container) {
|
||||
container.MaterialTextfield.change(this.value);
|
||||
}
|
||||
this.setupMaterialTextField(this.elementRef, handler, this.value);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
import { TabsWidget } from './tabs.widget';
|
||||
import { TabModel } from './../core/tab.model';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
|
||||
describe('TabsWidget', () => {
|
||||
|
||||
@ -56,4 +57,13 @@ describe('TabsWidget', () => {
|
||||
expect(widget.setupMaterialComponents()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should emit tab changed event', (done) => {
|
||||
let field = new FormFieldModel(null);
|
||||
widget.formTabChanged.subscribe(tab => {
|
||||
expect(tab).toBe(field);
|
||||
done();
|
||||
});
|
||||
widget.tabChanged(field);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -0,0 +1,68 @@
|
||||
/*!
|
||||
* @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 { TextWidget } from './text.widget';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { FormFieldTypes } from '../core/form-field-types';
|
||||
|
||||
describe('TextWidget', () => {
|
||||
|
||||
let widget: TextWidget;
|
||||
let elementRef: ElementRef;
|
||||
let componentHandler;
|
||||
|
||||
beforeEach(() => {
|
||||
elementRef = new ElementRef(null);
|
||||
widget = new TextWidget(elementRef);
|
||||
|
||||
componentHandler = jasmine.createSpyObj('componentHandler', [
|
||||
'upgradeAllRegistered'
|
||||
]);
|
||||
|
||||
window['componentHandler'] = componentHandler;
|
||||
});
|
||||
|
||||
it('should upgrade material textfield', () => {
|
||||
spyOn(widget, 'setupMaterialTextField').and.stub();
|
||||
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.TEXT,
|
||||
value: '<text>'
|
||||
});
|
||||
widget.ngAfterViewInit();
|
||||
expect(widget.setupMaterialTextField).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should require mdl component handler to setup textfield', () => {
|
||||
expect(widget.setupMaterialComponents(null)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should require element reference to setup textfield', () => {
|
||||
widget = new TextWidget(null);
|
||||
expect(widget.setupMaterialComponents(componentHandler)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should require field value to setup textfield', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.TEXT,
|
||||
value: null
|
||||
});
|
||||
expect(widget.setupMaterialComponents(componentHandler)).toBeFalsy();
|
||||
});
|
||||
|
||||
});
|
@ -27,19 +27,13 @@ export abstract class TextFieldWidgetComponent extends WidgetComponent {
|
||||
this.elementRef = elementRef;
|
||||
}
|
||||
|
||||
// Overrides base implementation
|
||||
setupMaterialComponents(handler: any): boolean {
|
||||
super.setupMaterialComponents(handler);
|
||||
// workaround for MDL issues with dynamic components
|
||||
if (handler) {
|
||||
handler.upgradeAllRegistered();
|
||||
if (this.elementRef && this.hasValue()) {
|
||||
let el = this.elementRef.nativeElement;
|
||||
let container = el.querySelector('.mdl-textfield');
|
||||
if (container) {
|
||||
container.MaterialTextfield.change(this.field.value.toString());
|
||||
}
|
||||
return this.setupMaterialTextField(this.elementRef, handler, this.field.value.toString());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
<label class="upload-widget__label" [attr.for]="field.id">{{field.name}}</label>
|
||||
<div>
|
||||
<i *ngIf="hasFile" class="material-icons upload-widget__icon">attachment</i>
|
||||
<span *ngIf="hasFile" class="upload-widget__file">{{getUploadedFileName()}}</span>
|
||||
<span *ngIf="hasFile" class="upload-widget__file">{{displayText}}</span>
|
||||
<input *ngIf="!hasFile"
|
||||
#file
|
||||
type="file"
|
||||
|
@ -0,0 +1,84 @@
|
||||
/*!
|
||||
* @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 { UploadWidget } from './upload.widget';
|
||||
import { AlfrescoSettingsService, AlfrescoAuthenticationService, AlfrescoApiService } from 'ng2-alfresco-core';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { FormFieldTypes } from '../core/form-field-types';
|
||||
|
||||
describe('UploadWidget', () => {
|
||||
|
||||
let widget: UploadWidget;
|
||||
let settingsService: AlfrescoSettingsService;
|
||||
let authService: AlfrescoAuthenticationService;
|
||||
|
||||
beforeEach(() => {
|
||||
settingsService = new AlfrescoSettingsService();
|
||||
authService = new AlfrescoAuthenticationService(settingsService, new AlfrescoApiService());
|
||||
widget = new UploadWidget(settingsService, authService);
|
||||
});
|
||||
|
||||
it('should setup with field data', () => {
|
||||
const fileName = 'hello world';
|
||||
const encodedFileName = encodeURI(fileName);
|
||||
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.UPLOAD,
|
||||
value: [
|
||||
{ name: encodedFileName }
|
||||
]
|
||||
});
|
||||
|
||||
widget.ngOnInit();
|
||||
expect(widget.hasFile).toBeTruthy();
|
||||
expect(widget.fileName).toBe(encodeURI(fileName));
|
||||
expect(widget.displayText).toBe(fileName);
|
||||
});
|
||||
|
||||
it('should require form field to setup', () => {
|
||||
widget.field = null;
|
||||
widget.ngOnInit();
|
||||
|
||||
expect(widget.hasFile).toBeFalsy();
|
||||
expect(widget.fileName).toBeUndefined();
|
||||
expect(widget.displayText).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should reset local properties', () => {
|
||||
widget.hasFile = true;
|
||||
widget.fileName = '<fileName>';
|
||||
widget.displayText = '<displayText>';
|
||||
|
||||
widget.reset();
|
||||
expect(widget.hasFile).toBeFalsy();
|
||||
expect(widget.fileName).toBeNull();
|
||||
expect(widget.displayText).toBeNull();
|
||||
});
|
||||
|
||||
it('should reset field value', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
type: FormFieldTypes.UPLOAD,
|
||||
value: [
|
||||
{ name: 'filename' }
|
||||
]
|
||||
});
|
||||
widget.reset();
|
||||
expect(widget.field.value).toBeNull();
|
||||
expect(widget.field.json.value).toBeNull();
|
||||
});
|
||||
|
||||
});
|
@ -29,6 +29,7 @@ export class UploadWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
hasFile: boolean;
|
||||
fileName: string;
|
||||
displayText: string;
|
||||
|
||||
constructor(private settingsService: AlfrescoSettingsService,
|
||||
private authService: AlfrescoAuthenticationService) {
|
||||
@ -42,18 +43,19 @@ export class UploadWidget extends WidgetComponent implements OnInit {
|
||||
this.hasFile = true;
|
||||
let file = this.field.value[0];
|
||||
this.fileName = file.name;
|
||||
this.displayText = decodeURI(file.name);
|
||||
}
|
||||
}
|
||||
|
||||
getUploadedFileName(): string {
|
||||
return decodeURI(this.fileName);
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.field.value = null;
|
||||
this.field.json.value = null;
|
||||
this.hasFile = false;
|
||||
this.fileName = null;
|
||||
this.displayText = null;
|
||||
|
||||
if (this.field) {
|
||||
this.field.value = null;
|
||||
this.field.json.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
onFileChanged(event: any) {
|
||||
@ -64,6 +66,7 @@ export class UploadWidget extends WidgetComponent implements OnInit {
|
||||
|
||||
this.hasFile = true;
|
||||
this.fileName = encodeURI(file.name);
|
||||
this.displayText = file.name;
|
||||
|
||||
let formData: FormData = new FormData();
|
||||
formData.append('file', file, this.fileName);
|
||||
|
@ -15,6 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ElementRef } from '@angular/core';
|
||||
import { WidgetComponent } from './widget.component';
|
||||
import { FormFieldModel } from './core/form-field.model';
|
||||
import { FormModel } from './core/form.model';
|
||||
@ -80,4 +81,53 @@ describe('WidgetComponent', () => {
|
||||
|
||||
component.checkVisibility(fakeField);
|
||||
});
|
||||
|
||||
it('should eval isRequired state of the field', () => {
|
||||
let widget = new WidgetComponent();
|
||||
expect(widget.isRequired()).toBeFalsy();
|
||||
|
||||
widget.field = new FormFieldModel(null);
|
||||
expect(widget.isRequired()).toBeFalsy();
|
||||
|
||||
widget.field = new FormFieldModel(null, { required: false });
|
||||
expect(widget.isRequired()).toBeFalsy();
|
||||
|
||||
widget.field = new FormFieldModel(null, { required: true });
|
||||
expect(widget.isRequired()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should require element reference to setup textfield', () => {
|
||||
let widget = new WidgetComponent();
|
||||
expect(widget.setupMaterialTextField(null, {}, 'value')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should require component handler to setup textfield', () => {
|
||||
let elementRef = new ElementRef(null);
|
||||
let widget = new WidgetComponent();
|
||||
expect(widget.setupMaterialTextField(elementRef, null, 'value')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should require field value to setup textfield', () => {
|
||||
let elementRef = new ElementRef(null);
|
||||
let widget = new WidgetComponent();
|
||||
expect(widget.setupMaterialTextField(elementRef, {}, null)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should setup textfield', () => {
|
||||
let changeCalled = false;
|
||||
let elementRef = new ElementRef({
|
||||
querySelector: function () {
|
||||
return {
|
||||
MaterialTextfield: {
|
||||
change: function() {
|
||||
changeCalled = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
let widget = new WidgetComponent();
|
||||
expect(widget.setupMaterialTextField(elementRef, {}, 'value')).toBeTruthy();
|
||||
expect(changeCalled).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Input, AfterViewInit, Output, EventEmitter } from '@angular/core';
|
||||
import { Input, AfterViewInit, Output, EventEmitter, ElementRef } from '@angular/core';
|
||||
import { FormFieldModel } from './core/index';
|
||||
|
||||
/**
|
||||
@ -36,6 +36,8 @@ export class WidgetComponent implements AfterViewInit {
|
||||
return this.field ? true : false;
|
||||
}
|
||||
|
||||
// Note for developers:
|
||||
// returns <any> object to be able binding it to the <element reguired="required"> attribute
|
||||
isRequired(): any {
|
||||
if (this.field && this.field.required) {
|
||||
return true;
|
||||
@ -63,6 +65,20 @@ export class WidgetComponent implements AfterViewInit {
|
||||
return false;
|
||||
}
|
||||
|
||||
setupMaterialTextField(elementRef: ElementRef, handler: any, value: string): boolean {
|
||||
if (elementRef && handler) {
|
||||
let el = elementRef.nativeElement;
|
||||
if (el) {
|
||||
let container = el.querySelector('.mdl-textfield');
|
||||
if (container) {
|
||||
container.MaterialTextfield.change(value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
checkVisibility(field: FormFieldModel) {
|
||||
this.fieldChanged.emit(field);
|
||||
}
|
||||
@ -85,4 +101,10 @@ export class WidgetComponent implements AfterViewInit {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected handleError(error: any) {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user