diff --git a/lib/features/modeling/behavior/DataStoreBehavior.js b/lib/features/modeling/behavior/DataStoreBehavior.js index 8689d2ad..ce3d0d96 100644 --- a/lib/features/modeling/behavior/DataStoreBehavior.js +++ b/lib/features/modeling/behavior/DataStoreBehavior.js @@ -2,7 +2,10 @@ import inherits from 'inherits'; import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor'; -import { is } from '../../../util/ModelUtil'; +import { + getBusinessObject, + is +} from '../../../util/ModelUtil'; import { isAny } from '../util/ModelingUtil'; @@ -20,9 +23,9 @@ export default function DataStoreBehavior( commandStack.registerHandler('dataStore.updateContainment', UpdateSemanticParentHandler); - function getFirstParticipant() { + function getFirstParticipantWithProcessRef() { return elementRegistry.filter(function(element) { - return is(element, 'bpmn:Participant'); + return is(element, 'bpmn:Participant') && getBusinessObject(element).processRef; })[0]; } @@ -35,7 +38,7 @@ export default function DataStoreBehavior( function updateDataStoreParent(dataStore, newDataStoreParent) { var dataStoreBo = dataStore.businessObject || dataStore; - newDataStoreParent = newDataStoreParent || getFirstParticipant(); + newDataStoreParent = newDataStoreParent || getFirstParticipantWithProcessRef(); if (newDataStoreParent) { var newDataStoreParentBo = newDataStoreParent.businessObject || newDataStoreParent; diff --git a/lib/features/rules/BpmnRules.js b/lib/features/rules/BpmnRules.js index 24e3b67d..19ec96d1 100644 --- a/lib/features/rules/BpmnRules.js +++ b/lib/features/rules/BpmnRules.js @@ -494,6 +494,13 @@ function canDrop(element, target, position) { return isAny(target, [ 'bpmn:Participant', 'bpmn:Lane' ]); } + // disallow dropping data store reference if there is no process to append to + if (is(element, 'bpmn:DataStoreReference') && is(target, 'bpmn:Collaboration')) { + return some(getBusinessObject(target).get('participants'), function(participant) { + return !!participant.get('processRef'); + }); + } + // account for the fact that data associations are always // rendered and moved to top (Process or Collaboration level) // diff --git a/tasks/wiredeps b/tasks/wiredeps index 02d8bbc7..8b768d05 100755 --- a/tasks/wiredeps +++ b/tasks/wiredeps @@ -9,7 +9,8 @@ if [[ $GITHUB_REF =~ ^refs/heads/master$ ]] || [[ $GITHUB_REF =~ ^refs/tags/ ]]; exit 0; fi -FEATURE_BRANCH=$(echo "$GITHUB_REF" | cut -d"/" -f3) +# GITHUB_HEAD_REF is set for pull request +FEATURE_BRANCH=$([ $GITHUB_HEAD_REF != "" ] && echo $GITHUB_HEAD_REF || echo "$GITHUB_REF" | cut -d"/" -f3) echo "Attempting to install diagram-js@$FEATURE_BRANCH"; diff --git a/test/spec/features/modeling/behavior/DataStoreBehavior.empty-pool.bpmn b/test/spec/features/modeling/behavior/DataStoreBehavior.empty-pool.bpmn new file mode 100644 index 00000000..a3a13064 --- /dev/null +++ b/test/spec/features/modeling/behavior/DataStoreBehavior.empty-pool.bpmn @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/test/spec/features/modeling/behavior/DataStoreBehaviorSpec.js b/test/spec/features/modeling/behavior/DataStoreBehaviorSpec.js index 1a50c65f..74c3d890 100644 --- a/test/spec/features/modeling/behavior/DataStoreBehaviorSpec.js +++ b/test/spec/features/modeling/behavior/DataStoreBehaviorSpec.js @@ -45,7 +45,7 @@ describe('features/modeling/behavior - data store', function() { })); - it('should create DataStoreReference on sub process', inject(function(elementRegistry, modeling, bpmnjs) { + it('should create DataStoreReference on sub process', inject(function(elementRegistry, modeling) { // give var subProcessElement = elementRegistry.get('SubProcess'), @@ -70,7 +70,7 @@ describe('features/modeling/behavior - data store', function() { })); - it('should create DataStoreReference on collaboration', inject(function(elementRegistry, modeling, bpmnjs) { + it('should create DataStoreReference on collaboration', inject(function(elementRegistry, modeling) { // give var collaborationElement = elementRegistry.get('Collaboration'), @@ -95,6 +95,41 @@ describe('features/modeling/behavior - data store', function() { expect(dataStoreReference.dataStoreRef).not.to.exist; })); + + describe('empty pool', function() { + + var processDiagramXML = require('./DataStoreBehavior.empty-pool.bpmn'); + + beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules })); + + it('should create DataStoreReference on collaboration if first participant is an empty pool', + inject(function(elementRegistry, modeling) { + + // give + var collaboration = elementRegistry.get('Collaboration'), + participantWithProcess = elementRegistry.get('Participant_2').businessObject; + + // when + var dataStoreShape = modeling.createShape( + { type: 'bpmn:DataStoreReference' }, + { x: 420, y: 370 }, + collaboration + ); + + var dataStoreReference = dataStoreShape.businessObject; + + // then + // reference correctly wired + expect(dataStoreReference.$parent).to.exist; + expect(dataStoreReference.$parent).to.eql(participantWithProcess.processRef); + expect(participantWithProcess.processRef.flowElements).to.contain(dataStoreReference); + + // no actual data store created + expect(dataStoreReference.dataStoreRef).not.to.exist; + }) + ); + }); + }); @@ -105,7 +140,7 @@ describe('features/modeling/behavior - data store', function() { beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules })); - it('should move DataStoreReference to Participant', inject(function(elementRegistry, modeling, bpmnjs) { + it('should move DataStoreReference to Participant', inject(function(elementRegistry, modeling) { // give var participantElement = elementRegistry.get('Participant'), @@ -123,7 +158,7 @@ describe('features/modeling/behavior - data store', function() { it('should move DataStoreReference from partipant to Collaboration keeping parent particpant', inject( - function(elementRegistry, modeling, bpmnjs) { + function(elementRegistry, modeling) { // give var collaborationElement = elementRegistry.get('Collaboration'), @@ -143,7 +178,7 @@ describe('features/modeling/behavior - data store', function() { it('should move DataStoreReference from subprocess to Collaboration keeping parent particpant', inject( - function(elementRegistry, modeling, bpmnjs) { + function(elementRegistry, modeling) { // give var collaborationElement = elementRegistry.get('Collaboration'), @@ -163,7 +198,7 @@ describe('features/modeling/behavior - data store', function() { it('should move without changing parent', inject( - function(elementRegistry, modeling, bpmnjs) { + function(elementRegistry, modeling) { // give var collaborationElement = elementRegistry.get('Collaboration'), diff --git a/test/spec/features/rules/BpmnRules.collaboration-empty.bpmn b/test/spec/features/rules/BpmnRules.collaboration-empty.bpmn new file mode 100644 index 00000000..ebc7d252 --- /dev/null +++ b/test/spec/features/rules/BpmnRules.collaboration-empty.bpmn @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/test/spec/features/rules/BpmnRulesSpec.js b/test/spec/features/rules/BpmnRulesSpec.js index a449caf8..1d229d9d 100644 --- a/test/spec/features/rules/BpmnRulesSpec.js +++ b/test/spec/features/rules/BpmnRulesSpec.js @@ -123,6 +123,26 @@ describe('features/modeling/rules - BpmnRules', function() { expectCanCreate([task1, task2], 'SequenceFlow', false); })); + + describe('empty pool', function() { + + var testXML = require('./BpmnRules.collaboration-empty.bpmn'); + + beforeEach(bootstrapModeler(testXML, { modules: testModules })); + + + it('should not allow to drop DataStoreReference when there is no process to append to', + inject(function(elementFactory) { + + // given + var dataStoreReference = elementFactory.createShape({ type: 'bpmn:DataStoreReference' }); + + // then + expectCanCreate(dataStoreReference, 'Collaboration', false); + }) + ); + }); + });