diff --git a/openbis_ng_ui/src/js/components/types/objectType/ObjectType.jsx b/openbis_ng_ui/src/js/components/types/objectType/ObjectType.jsx index 679e93880a8be4ab65df2dbd17f0574f7a832c4c..71bcb46cee38a068c7bafb5c41c439818c53c873 100644 --- a/openbis_ng_ui/src/js/components/types/objectType/ObjectType.jsx +++ b/openbis_ng_ui/src/js/components/types/objectType/ObjectType.jsx @@ -140,14 +140,14 @@ class ObjectType extends React.PureComponent { new ObjectTypeHandlerRemove( this.state, this.setState.bind(this) - ).executeRemoveConfirm() + ).executeRemove(true) } handleRemoveCancel() { new ObjectTypeHandlerRemove( this.state, this.setState.bind(this) - ).executeRemoveCancel() + ).executeCancel() } handleSave() { diff --git a/openbis_ng_ui/src/js/components/types/objectType/ObjectTypeHandlerRemove.js b/openbis_ng_ui/src/js/components/types/objectType/ObjectTypeHandlerRemove.js index 3ab191f52e6e6568794475f8c4dda78e3419b15c..4a7be869ab2ff2018e922c7c26b5a903ba66a016 100644 --- a/openbis_ng_ui/src/js/components/types/objectType/ObjectTypeHandlerRemove.js +++ b/openbis_ng_ui/src/js/components/types/objectType/ObjectTypeHandlerRemove.js @@ -6,37 +6,39 @@ export default class ObjectTypeHandlerRemove { this.setState = setState } - executeRemove() { + executeRemove(confirmed = false) { const { selection } = this.state if (selection.type === 'section') { - this.handleRemoveSection(selection.params.id) + this.handleRemoveSection(selection.params.id, confirmed) } else if (selection.type === 'property') { - this.handleRemoveProperty(selection.params.id) + this.handleRemoveProperty(selection.params.id, confirmed) } } - executeRemoveConfirm() { - this.setState({ - removeSectionDialogOpen: false, - removePropertyDialogOpen: false - }) - this.executeRemove() - } - - executeRemoveCancel() { - this.setState({ - removeSectionDialogOpen: false, - removePropertyDialogOpen: false - }) + executeCancel() { + const { selection } = this.state + if (selection.type === 'section') { + this.setState({ + removeSectionDialogOpen: false + }) + } else if (selection.type === 'property') { + this.setState({ + removePropertyDialogOpen: false + }) + } } - handleRemoveSection(sectionId) { - const { sections, properties, removeSectionDialogOpen } = this.state + handleRemoveSection(sectionId, confirmed) { + const { sections, properties } = this.state const sectionIndex = sections.findIndex(section => section.id === sectionId) const section = sections[sectionIndex] - if (this.isSectionUsed(section) && !removeSectionDialogOpen) { + if (confirmed) { + this.setState({ + removeSectionDialogOpen: false + }) + } else if (this.isSectionUsed(section)) { this.setState({ removeSectionDialogOpen: true }) @@ -60,15 +62,19 @@ export default class ObjectTypeHandlerRemove { })) } - handleRemoveProperty(propertyId) { - const { sections, properties, removePropertyDialogOpen } = this.state + handleRemoveProperty(propertyId, confirmed) { + const { sections, properties } = this.state const propertyIndex = properties.findIndex( property => property.id === propertyId ) const property = properties[propertyIndex] - if (this.isPropertyUsed(property) && !removePropertyDialogOpen) { + if (confirmed) { + this.setState({ + removePropertyDialogOpen: false + }) + } else if (this.isPropertyUsed(property)) { this.setState({ removePropertyDialogOpen: true }) @@ -114,6 +120,6 @@ export default class ObjectTypeHandlerRemove { } isPropertyUsed(property) { - return property.usages !== 0 + return _.isFinite(property.usages) && property.usages !== 0 } } diff --git a/openbis_ng_ui/src/js/components/types/objectType/ObjectTypeHandlerValidate.js b/openbis_ng_ui/src/js/components/types/objectType/ObjectTypeHandlerValidate.js index 4a2ad1c417289bbee32b1a3f07013d002ed56ab6..1be4cfa73b8d41146bd68225a30d89dabe2fd6b8 100644 --- a/openbis_ng_ui/src/js/components/types/objectType/ObjectTypeHandlerValidate.js +++ b/openbis_ng_ui/src/js/components/types/objectType/ObjectTypeHandlerValidate.js @@ -24,7 +24,7 @@ export default class ObjectTypeHandlerValidate { const { validate, type, properties } = this.getState() if (!validate) { - return + return true } const [typeErrors, typeErrorsMap] = this.validateType(type) @@ -66,11 +66,16 @@ export default class ObjectTypeHandlerValidate { return { type: newType, - properties: newProperties, - selection: errorSelection ? errorSelection : state.selection + properties: newProperties } }) + if (errorSelection) { + this.setState({ + selection: errorSelection + }) + } + return _.isEmpty(typeErrors) && _.isEmpty(propertiesErrors) } diff --git a/openbis_ng_ui/srcTest/js/common/ComponentState.js b/openbis_ng_ui/srcTest/js/common/ComponentState.js index 1996729c2449cfab294b380a62a42ed8081034d3..c4f443c6c9ec0fa1864362794f3f4e1e9e3f1dff 100644 --- a/openbis_ng_ui/srcTest/js/common/ComponentState.js +++ b/openbis_ng_ui/srcTest/js/common/ComponentState.js @@ -11,8 +11,14 @@ class ComponentState { return this.state } + getGetState() { + return () => { + return this.getState() + } + } + getSetState() { - return newStateOrFunction => { + return (newStateOrFunction, callback) => { let changes if (_.isFunction(newStateOrFunction)) { @@ -22,6 +28,10 @@ class ComponentState { } this.state = { ...this.state, ...changes } + + if (callback) { + callback() + } } } diff --git a/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerLoad.test.js b/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerLoad.test.js new file mode 100644 index 0000000000000000000000000000000000000000..20961dd41fbfcdb187221873b57a7feb0720be6b --- /dev/null +++ b/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerLoad.test.js @@ -0,0 +1,225 @@ +import ObjectTypeHandlerLoad from '../../../../../src/js/components/types/objectType/ObjectTypeHandlerLoad.js' +import ComponentState from '../../../common/ComponentState.js' + +describe('ObjectTypeHandlerLoadTest', () => { + test('load success', done => { + const componentState = new ComponentState({}) + const facade = { + loadType: jest.fn(), + loadUsages: jest.fn() + } + + facade.loadType.mockReturnValueOnce( + Promise.resolve({ + code: 'TYPE_CODE', + description: 'TYPE_DESCRIPTION', + listable: true, + showContainer: true, + showParents: true, + showParentMetadata: true, + autoGeneratedCode: true, + generatedCodePrefix: 'TYPE_CODE_PREFIX', + subcodeUnique: true, + validationPlugin: { name: 'TYPE_VALIDATION_PLUGIN' }, + propertyAssignments: [ + { + propertyType: { + code: 'PROPERTY_0_CODE', + label: 'PROPERTY_0_LABEL', + description: 'PROPERTY_0_DESCRIPTION', + dataType: 'VARCHAR', + schema: null, + transformation: null + }, + plugin: { name: 'PROPERTY_0_PLUGIN' }, + mandatory: true, + section: 'SECTION_0', + showInEditView: true, + showRawValueInForms: true + }, + { + propertyType: { + code: 'PROPERTY_1_CODE', + label: 'PROPERTY_1_LABEL', + description: 'PROPERTY_1_DESCRIPTION', + dataType: 'CONTROLLED_VOCABULARY', + vocabulary: { + code: 'PROPERTY_1_VOCABULARY_CODE' + }, + schema: null, + transformation: null + }, + plugin: null, + mandatory: false, + section: 'SECTION_0', + showInEditView: false, + showRawValueInForms: false + }, + { + propertyType: { + code: 'PROPERTY_2_CODE', + label: 'PROPERTY_2_LABEL', + description: 'PROPERTY_2_DESCRIPTION', + dataType: 'MATERIAL', + materialType: { + code: 'PROPERTY_2_MATERIAL_TYPE_CODE' + }, + schema: null, + transformation: null + }, + plugin: null, + mandatory: false, + section: null, + showInEditView: false, + showRawValueInForms: false + } + ] + }) + ) + facade.loadUsages.mockReturnValueOnce( + Promise.resolve({ + type: 3, + property: { + PROPERTY_0_CODE: 2, + PROPERTY_1_CODE: 1 + } + }) + ) + + execute(123, componentState, facade).finally(() => { + expect(facade.loadType).toBeCalledWith(123) + expect(facade.loadUsages).toBeCalledWith(123) + + const state = componentState.getState() + + delete state.type.original + state.properties.forEach(property => { + delete property.original + }) + + componentState.assertState({ + loading: false, + selection: null, + sections: [ + { + id: 'section-0', + name: 'SECTION_0', + properties: ['property-0', 'property-1'] + }, + { + id: 'section-1', + name: null, + properties: ['property-2'] + } + ], + properties: [ + { + code: 'PROPERTY_0_CODE', + dataType: 'VARCHAR', + description: 'PROPERTY_0_DESCRIPTION', + errors: {}, + id: 'property-0', + label: 'PROPERTY_0_LABEL', + mandatory: true, + materialType: null, + plugin: 'PROPERTY_0_PLUGIN', + schema: null, + section: 'section-0', + showInEditView: true, + showRawValueInForms: true, + transformation: null, + usages: 2, + vocabulary: null + }, + { + code: 'PROPERTY_1_CODE', + dataType: 'CONTROLLED_VOCABULARY', + description: 'PROPERTY_1_DESCRIPTION', + errors: {}, + id: 'property-1', + label: 'PROPERTY_1_LABEL', + mandatory: false, + materialType: null, + plugin: null, + schema: null, + section: 'section-0', + showInEditView: false, + showRawValueInForms: false, + transformation: null, + usages: 1, + vocabulary: 'PROPERTY_1_VOCABULARY_CODE' + }, + { + code: 'PROPERTY_2_CODE', + dataType: 'MATERIAL', + description: 'PROPERTY_2_DESCRIPTION', + errors: {}, + id: 'property-2', + label: 'PROPERTY_2_LABEL', + mandatory: false, + materialType: 'PROPERTY_2_MATERIAL_TYPE_CODE', + plugin: null, + schema: null, + section: 'section-1', + showInEditView: false, + showRawValueInForms: false, + transformation: null, + usages: 0, + vocabulary: null + } + ], + type: { + autoGeneratedCode: true, + code: 'TYPE_CODE', + description: 'TYPE_DESCRIPTION', + errors: {}, + generatedCodePrefix: 'TYPE_CODE_PREFIX', + listable: true, + showContainer: true, + showParentMetadata: true, + showParents: true, + subcodeUnique: true, + usages: 3, + validationPlugin: 'TYPE_VALIDATION_PLUGIN' + }, + propertiesCounter: 3, + sectionsCounter: 2, + removePropertyDialogOpen: false, + removeSectionDialogOpen: false + }) + + done() + }) + }) + + test('load failure', done => { + const componentState = new ComponentState({}) + const facade = { + loadType: jest.fn(), + loadUsages: jest.fn(), + catch: jest.fn() + } + + facade.loadType.mockReturnValueOnce(Promise.reject('Server unavailable')) + facade.loadUsages.mockReturnValueOnce(Promise.resolve({})) + + execute(123, componentState, facade).finally(() => { + expect(facade.loadType).toBeCalledWith(123) + expect(facade.loadUsages).toBeCalledWith(123) + expect(facade.catch).toBeCalledWith('Server unavailable') + + componentState.assertState({ loading: false }) + + done() + }) + }) +}) + +const execute = (objectId, componentState, facade) => { + return new ObjectTypeHandlerLoad( + objectId, + componentState.getState(), + componentState.getSetState(), + facade + ).execute() +} diff --git a/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerOrderChange.test.js b/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerOrderChange.test.js new file mode 100644 index 0000000000000000000000000000000000000000..b20e2b7f39b9331e8ef3d0b83367c8c0b540d48a --- /dev/null +++ b/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerOrderChange.test.js @@ -0,0 +1,134 @@ +import ObjectTypeHandlerOrderChange from '../../../../../src/js/components/types/objectType/ObjectTypeHandlerOrderChange.js' +import ComponentState from '../../../common/ComponentState.js' + +describe('ObjectTypeHandlerOrderChangeTest', () => { + test('section', () => { + const componentState = new ComponentState({ + sections: [ + { + id: 'section-0' + }, + { + id: 'section-1' + }, + { + id: 'section-2' + } + ] + }) + + execute(componentState, 'section', { + fromIndex: 2, + toIndex: 0 + }) + + componentState.assertState({ + sections: [ + { + id: 'section-2' + }, + { + id: 'section-0' + }, + { + id: 'section-1' + } + ] + }) + }) + + test('property', () => { + const componentState = new ComponentState({ + sections: [ + { + id: 'section-0', + properties: ['property-0', 'property-1'] + }, + { + id: 'section-1', + properties: [] + }, + { + id: 'section-2', + properties: ['property-2', 'property-3', 'property-4'] + } + ], + properties: [ + { id: 'property-0', section: 'section-0' }, + { id: 'property-1', section: 'section-0' }, + { id: 'property-2', section: 'section-2' }, + { id: 'property-3', section: 'section-2' }, + { id: 'property-4', section: 'section-2' } + ] + }) + + execute(componentState, 'property', { + fromSectionId: 'section-2', + toSectionId: 'section-2', + fromIndex: 0, + toIndex: 1 + }) + + componentState.assertState({ + sections: [ + { + id: 'section-0', + properties: ['property-0', 'property-1'] + }, + { + id: 'section-1', + properties: [] + }, + { + id: 'section-2', + properties: ['property-3', 'property-2', 'property-4'] + } + ], + properties: [ + { id: 'property-0', section: 'section-0' }, + { id: 'property-1', section: 'section-0' }, + { id: 'property-2', section: 'section-2' }, + { id: 'property-3', section: 'section-2' }, + { id: 'property-4', section: 'section-2' } + ] + }) + + execute(componentState, 'property', { + fromSectionId: 'section-2', + toSectionId: 'section-0', + fromIndex: 1, + toIndex: 1 + }) + + componentState.assertState({ + sections: [ + { + id: 'section-0', + properties: ['property-0', 'property-2', 'property-1'] + }, + { + id: 'section-1', + properties: [] + }, + { + id: 'section-2', + properties: ['property-3', 'property-4'] + } + ], + properties: [ + { id: 'property-0', section: 'section-0' }, + { id: 'property-1', section: 'section-0' }, + { id: 'property-2', section: 'section-0' }, + { id: 'property-3', section: 'section-2' }, + { id: 'property-4', section: 'section-2' } + ] + }) + }) +}) + +const execute = (componentState, type, params) => { + new ObjectTypeHandlerOrderChange( + componentState.getState(), + componentState.getSetState() + ).execute(type, params) +} diff --git a/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerRemove.test.js b/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerRemove.test.js new file mode 100644 index 0000000000000000000000000000000000000000..8b8622681f6ddcf549350e555d93b6addba43157 --- /dev/null +++ b/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerRemove.test.js @@ -0,0 +1,326 @@ +import ObjectTypeHandlerRemove from '../../../../../src/js/components/types/objectType/ObjectTypeHandlerRemove.js' +import ComponentState from '../../../common/ComponentState.js' + +describe('ObjectTypeHandlerRemoveTest', () => { + test('section not used', () => { + const componentState = new ComponentState({ + selection: { + type: 'section', + params: { + id: 'section-0' + } + }, + sections: [ + { + id: 'section-0', + properties: ['property-0', 'property-1'] + }, + { + id: 'section-1', + properties: ['property-2', 'property-3', 'property-4'] + } + ], + properties: [ + { id: 'property-0', section: 'section-0' }, + { id: 'property-1', section: 'section-0' }, + { id: 'property-2', section: 'section-1' }, + { id: 'property-3', section: 'section-1' }, + { id: 'property-4', section: 'section-1' } + ] + }) + + executeRemove(componentState) + + componentState.assertState({ + selection: null, + sections: [ + { + id: 'section-1', + properties: ['property-2', 'property-3', 'property-4'] + } + ], + properties: [ + { id: 'property-2', section: 'section-1' }, + { id: 'property-3', section: 'section-1' }, + { id: 'property-4', section: 'section-1' } + ] + }) + }) + + test('section used and confirmed', () => { + const componentState = new ComponentState({ + selection: { + type: 'section', + params: { + id: 'section-0' + } + }, + sections: [ + { + id: 'section-0', + properties: ['property-0'] + } + ], + properties: [{ id: 'property-0', section: 'section-0', usages: 1 }] + }) + + executeRemove(componentState) + executeRemove(componentState) + + componentState.assertState({ + removeSectionDialogOpen: true, + selection: { + type: 'section', + params: { + id: 'section-0' + } + }, + sections: [ + { + id: 'section-0', + properties: ['property-0'] + } + ], + properties: [{ id: 'property-0', section: 'section-0', usages: 1 }] + }) + + executeRemove(componentState, true) + + componentState.assertState({ + removeSectionDialogOpen: false, + selection: null, + sections: [], + properties: [] + }) + }) + + test('section used and cancelled', () => { + const componentState = new ComponentState({ + selection: { + type: 'section', + params: { + id: 'section-0' + } + }, + sections: [ + { + id: 'section-0', + properties: ['property-0'] + } + ], + properties: [{ id: 'property-0', section: 'section-0', usages: 1 }] + }) + + executeRemove(componentState) + executeRemove(componentState) + + componentState.assertState({ + removeSectionDialogOpen: true, + selection: { + type: 'section', + params: { + id: 'section-0' + } + }, + sections: [ + { + id: 'section-0', + properties: ['property-0'] + } + ], + properties: [{ id: 'property-0', section: 'section-0', usages: 1 }] + }) + + executeCancel(componentState) + + componentState.assertState({ + removeSectionDialogOpen: false, + selection: { + type: 'section', + params: { + id: 'section-0' + } + }, + sections: [ + { + id: 'section-0', + properties: ['property-0'] + } + ], + properties: [{ id: 'property-0', section: 'section-0', usages: 1 }] + }) + }) + + test('property not used', () => { + const componentState = new ComponentState({ + selection: { + type: 'property', + params: { + id: 'property-3' + } + }, + sections: [ + { + id: 'section-0', + properties: ['property-0', 'property-1'] + }, + { + id: 'section-1', + properties: ['property-2', 'property-3', 'property-4'] + } + ], + properties: [ + { id: 'property-0', section: 'section-0' }, + { id: 'property-1', section: 'section-0' }, + { id: 'property-2', section: 'section-1' }, + { id: 'property-3', section: 'section-1' }, + { id: 'property-4', section: 'section-1' } + ] + }) + + executeRemove(componentState) + + componentState.assertState({ + selection: null, + sections: [ + { + id: 'section-0', + properties: ['property-0', 'property-1'] + }, + { + id: 'section-1', + properties: ['property-2', 'property-4'] + } + ], + properties: [ + { id: 'property-0', section: 'section-0' }, + { id: 'property-1', section: 'section-0' }, + { id: 'property-2', section: 'section-1' }, + { id: 'property-4', section: 'section-1' } + ] + }) + }) + + test('property used and confirmed', () => { + const componentState = new ComponentState({ + selection: { + type: 'property', + params: { + id: 'property-0' + } + }, + sections: [ + { + id: 'section-0', + properties: ['property-0'] + } + ], + properties: [{ id: 'property-0', section: 'section-0', usages: 1 }] + }) + + executeRemove(componentState) + executeRemove(componentState) + + componentState.assertState({ + removePropertyDialogOpen: true, + selection: { + type: 'property', + params: { + id: 'property-0' + } + }, + sections: [ + { + id: 'section-0', + properties: ['property-0'] + } + ], + properties: [{ id: 'property-0', section: 'section-0', usages: 1 }] + }) + + executeRemove(componentState, true) + + componentState.assertState({ + removePropertyDialogOpen: false, + selection: null, + sections: [ + { + id: 'section-0', + properties: [] + } + ], + properties: [] + }) + }) + + test('property used and cancelled', () => { + const componentState = new ComponentState({ + selection: { + type: 'property', + params: { + id: 'property-0' + } + }, + sections: [ + { + id: 'section-0', + properties: ['property-0'] + } + ], + properties: [{ id: 'property-0', section: 'section-0', usages: 1 }] + }) + + executeRemove(componentState) + executeRemove(componentState) + + componentState.assertState({ + removePropertyDialogOpen: true, + selection: { + type: 'property', + params: { + id: 'property-0' + } + }, + sections: [ + { + id: 'section-0', + properties: ['property-0'] + } + ], + properties: [{ id: 'property-0', section: 'section-0', usages: 1 }] + }) + + executeCancel(componentState) + + componentState.assertState({ + removePropertyDialogOpen: false, + selection: { + type: 'property', + params: { + id: 'property-0' + } + }, + sections: [ + { + id: 'section-0', + properties: ['property-0'] + } + ], + properties: [{ id: 'property-0', section: 'section-0', usages: 1 }] + }) + }) +}) + +const executeRemove = (componentState, confirmed) => { + new ObjectTypeHandlerRemove( + componentState.getState(), + componentState.getSetState() + ).executeRemove(confirmed) +} + +const executeCancel = componentState => { + new ObjectTypeHandlerRemove( + componentState.getState(), + componentState.getSetState() + ).executeCancel() +} diff --git a/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerSelectionChange.test.js b/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerSelectionChange.test.js new file mode 100644 index 0000000000000000000000000000000000000000..834e128f3bb7227a5ad17e2e5d61c69a45f1224a --- /dev/null +++ b/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerSelectionChange.test.js @@ -0,0 +1,49 @@ +import ObjectTypeHandlerSelectionChange from '../../../../../src/js/components/types/objectType/ObjectTypeHandlerSelectionChange.js' +import ComponentState from '../../../common/ComponentState.js' + +describe('ObjectTypeHandlerSelectionChangeTest', () => { + test('section', () => { + const componentState = new ComponentState({ + selection: null + }) + + execute(componentState, 'section', { + id: 'section-0' + }) + + componentState.assertState({ + selection: { + type: 'section', + params: { + id: 'section-0' + } + } + }) + }) + + test('property', () => { + const componentState = new ComponentState({ + selection: null + }) + + execute(componentState, 'property', { + id: 'property-0' + }) + + componentState.assertState({ + selection: { + type: 'property', + params: { + id: 'property-0' + } + } + }) + }) +}) + +const execute = (componentState, type, params) => { + new ObjectTypeHandlerSelectionChange( + componentState.getState(), + componentState.getSetState() + ).execute(type, params) +} diff --git a/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerValidate.test.js b/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerValidate.test.js new file mode 100644 index 0000000000000000000000000000000000000000..4e1d143faf95b2e3f9ba5bfc0825332494e822f0 --- /dev/null +++ b/openbis_ng_ui/srcTest/js/components/types/objectType/ObjectTypeHandlerValidate.test.js @@ -0,0 +1,255 @@ +import ObjectTypeHandlerValidate from '../../../../../src/js/components/types/objectType/ObjectTypeHandlerValidate.js' +import ComponentState from '../../../common/ComponentState.js' +import { dto } from '../../../../../src/js/services/openbis.js' + +jest.mock('../../../../../src/js/services/openbis.js') + +beforeEach(() => { + jest.resetAllMocks() + dto.DataType.CONTROLLEDVOCABULARY = 'CONTROLLEDVOCABULARY' + dto.DataType.MATERIAL = 'MATERIAL' +}) + +describe('ObjectTypeHandlerValidateTest', () => { + test('validation enabled with autofocus fails', done => { + const componentState = new ComponentState({ + validate: false, + selection: { + type: 'testtype' + }, + type: { usages: 1 }, + properties: [ + { id: 'property-0' }, + { id: 'property-1', dataType: dto.DataType.CONTROLLEDVOCABULARY }, + { id: 'property-2', dataType: dto.DataType.MATERIAL }, + { id: 'property-3', mandatory: true } + ] + }) + + execute(componentState, true, true).then(result => { + componentState.assertState({ + validate: true, + selection: { + type: 'type', + params: { + part: 'code' + } + }, + type: { + usages: 1, + errors: { + code: 'Code cannot be empty', + generatedCodePrefix: 'Generated code prefix cannot be empty' + } + }, + properties: [ + { + id: 'property-0', + errors: { + code: 'Code cannot be empty', + dataType: 'Data Type cannot be empty', + description: 'Description cannot be empty', + label: 'Label cannot be empty' + } + }, + { + id: 'property-1', + dataType: dto.DataType.CONTROLLEDVOCABULARY, + errors: { + code: 'Code cannot be empty', + description: 'Description cannot be empty', + label: 'Label cannot be empty', + vocabulary: 'Vocabulary cannot be empty' + } + }, + { + id: 'property-2', + dataType: dto.DataType.MATERIAL, + errors: { + code: 'Code cannot be empty', + description: 'Description cannot be empty', + label: 'Label cannot be empty', + materialType: 'Material Type cannot be empty' + } + }, + { + id: 'property-3', + mandatory: true, + errors: { + code: 'Code cannot be empty', + dataType: 'Data Type cannot be empty', + description: 'Description cannot be empty', + label: 'Label cannot be empty', + initialValueForExistingEntities: 'Initial Value cannot be empty' + } + } + ] + }) + expect(result).toBe(false) + done() + }) + }) + + test('validation enabled without autofocus fails', done => { + const componentState = new ComponentState({ + validate: false, + selection: { + type: 'testtype' + }, + type: {}, + properties: [{ id: 'property-0' }] + }) + + execute(componentState, true, false).then(result => { + componentState.assertState({ + validate: true, + selection: { + type: 'testtype' + }, + type: { + errors: { + code: 'Code cannot be empty', + generatedCodePrefix: 'Generated code prefix cannot be empty' + } + }, + properties: [ + { + id: 'property-0', + errors: { + code: 'Code cannot be empty', + dataType: 'Data Type cannot be empty', + description: 'Description cannot be empty', + label: 'Label cannot be empty' + } + } + ] + }) + expect(result).toBe(false) + done() + }) + }) + + test('validation enabled with autofocus succeeds', done => { + const componentState = new ComponentState({ + validate: false, + selection: { + type: 'testtype' + }, + type: { code: 'TYPE_CODE', generatedCodePrefix: 'TYPE_CODE_PREFIX' }, + properties: [ + { + id: 'property-0', + code: 'PROPERTY_CODE', + dataType: 'PROPERTY_DATA_TYPE', + description: 'PROPERTY_DESCRIPTION', + label: 'PROPERTY_LABEL' + } + ] + }) + + execute(componentState, true, true).then(result => { + componentState.assertState({ + validate: true, + selection: { + type: 'testtype' + }, + type: { + code: 'TYPE_CODE', + generatedCodePrefix: 'TYPE_CODE_PREFIX', + errors: {} + }, + properties: [ + { + id: 'property-0', + code: 'PROPERTY_CODE', + dataType: 'PROPERTY_DATA_TYPE', + description: 'PROPERTY_DESCRIPTION', + label: 'PROPERTY_LABEL', + errors: {} + } + ] + }) + expect(result).toBe(true) + done() + }) + }) + + test('validation enabled without autofocus succeeds', done => { + const componentState = new ComponentState({ + validate: false, + selection: { + type: 'testtype' + }, + type: { code: 'TYPE_CODE', generatedCodePrefix: 'TYPE_CODE_PREFIX' }, + properties: [ + { + id: 'property-0', + code: 'PROPERTY_CODE', + dataType: 'PROPERTY_DATA_TYPE', + description: 'PROPERTY_DESCRIPTION', + label: 'PROPERTY_LABEL' + } + ] + }) + + execute(componentState, true, false).then(result => { + componentState.assertState({ + validate: true, + selection: { + type: 'testtype' + }, + type: { + code: 'TYPE_CODE', + generatedCodePrefix: 'TYPE_CODE_PREFIX', + errors: {} + }, + properties: [ + { + id: 'property-0', + code: 'PROPERTY_CODE', + dataType: 'PROPERTY_DATA_TYPE', + description: 'PROPERTY_DESCRIPTION', + label: 'PROPERTY_LABEL', + errors: {} + } + ] + }) + expect(result).toBe(true) + done() + }) + }) + + test('validation disabled', done => { + const componentState = new ComponentState({ + validate: false, + selection: { + type: 'testtype' + }, + type: {}, + properties: [{ id: 'property-0' }] + }) + + execute(componentState, false, true).then(result => { + componentState.assertState({ + validate: false, + selection: { + type: 'testtype' + }, + type: {}, + properties: [{ id: 'property-0' }] + }) + expect(result).toBe(true) + done() + }) + }) +}) + +const execute = (componentState, enabled, autofocus) => { + const handler = new ObjectTypeHandlerValidate( + componentState.getGetState(), + componentState.getSetState() + ) + return handler.setEnabled(enabled).then(() => { + return handler.execute(autofocus) + }) +}