feat(modeling): crop connections on shape boundaries

Behind the scenes changes:

* use diagram-js Matcher util in tests
* add test cases for LayoutConnection
* add test cases for CreateConnection
* cleanup unused test diagram

Related to #2
This commit is contained in:
Nico Rehwaldt 2014-07-30 16:06:32 +02:00
parent 7347e484ba
commit 4afe3a80ed
22 changed files with 398 additions and 198 deletions

View File

@ -304,7 +304,9 @@ function BpmnRenderer(events, styles, pathMap) {
);
}
function createPathFromWaypoints(waypoints) {
function createPathFromConnection(connection) {
var waypoints = connection.waypoints;
var pathData = 'm ' + waypoints[0].x + ',' + waypoints[0].y;
for (var i = 1; i < waypoints.length; i++) {
pathData += 'L' + waypoints[i].x + ',' + waypoints[i].y + ' ';
@ -1014,7 +1016,7 @@ function BpmnRenderer(events, styles, pathMap) {
return drawDiamond(p, element.width, element.height);
},
'bpmn:SequenceFlow': function(p, element) {
var pathData = createPathFromWaypoints(element.waypoints);
var pathData = createPathFromConnection(element);
var path = drawPath(p, pathData, {
markerEnd: marker('sequenceflow-end')
});
@ -1062,7 +1064,7 @@ function BpmnRenderer(events, styles, pathMap) {
var di = getDi(element);
var pathData = createPathFromWaypoints(element.waypoints);
var pathData = createPathFromConnection(element);
var path = drawPath(p, pathData, {
markerEnd: marker('messageflow-end'),
markerStart: marker('messageflow-start'),

View File

@ -9,13 +9,40 @@ var Collections = require('diagram-js/lib/util/Collections');
* A handler responsible for updating the underlying BPMN 2.0 XML + DI
* once changes on the diagram happen
*/
function BpmnUpdater(eventBus, bpmnFactory) {
function BpmnUpdater(eventBus, bpmnFactory, connectionDocking) {
this._eventBus = eventBus;
this._bpmnFactory = bpmnFactory;
var self = this;
////// connection cropping /////////////////////////
// crop connection ends during create/update
function cropConnection(e) {
var context = e.context,
connection;
if (!context.cropped) {
connection = context.connection;
connection.waypoints = connectionDocking.getCroppedWaypoints(connection);
context.cropped = true;
}
}
this.executed([ 'connection.layout', 'connection.create' ], cropConnection);
this.reverted([ 'connection.layout' ], function(e) {
delete e.context.cropped;
});
////// BPMN + DI update /////////////////////////
// create DI
this.executed('shape.create', function(e) {
self.createShapeDi(e.context.shape);
});
@ -25,6 +52,7 @@ function BpmnUpdater(eventBus, bpmnFactory) {
});
// update parent
function updateShapeParent(e) {
self.updateShapeParent(e.context.shape || e.context.connection);
}
@ -33,6 +61,7 @@ function BpmnUpdater(eventBus, bpmnFactory) {
this.reverted([ 'shape.move', 'shape.create', 'connection.create' ], updateShapeParent);
// update bounds
function updateBounds(e) {
self.updateBounds(e.context.shape);
}
@ -40,17 +69,28 @@ function BpmnUpdater(eventBus, bpmnFactory) {
this.executed([ 'shape.move' ], updateBounds);
this.reverted([ 'shape.move' ], updateBounds);
// attach / detach connection
function updateConnection(e) {
self.updateConnection(e.context.connection);
}
this.executed([ 'connection.create' ], updateConnection);
this.reverted([ 'connection.create' ], updateConnection);
// update waypoints
function updateConnectionWaypoints(e) {
self.updateConnectionWaypoints(e.context.connection);
}
this.executed([ 'connection.layout' ], updateConnectionWaypoints);
this.reverted([ 'connection.layout' ], updateConnectionWaypoints);
}
module.exports = BpmnUpdater;
BpmnUpdater.$inject = [ 'eventBus', 'bpmnFactory' ];
BpmnUpdater.$inject = [ 'eventBus', 'bpmnFactory', 'connectionDocking'];
/////// implementation //////////////////////////////////
@ -65,6 +105,7 @@ BpmnUpdater.prototype.createShapeDi = function(shape) {
}
};
BpmnUpdater.prototype.createConnectionDi = function(connection) {
var businessObject = connection.businessObject;
if (!businessObject.di) {
@ -74,6 +115,7 @@ BpmnUpdater.prototype.createConnectionDi = function(connection) {
}
};
BpmnUpdater.prototype.updateShapeParent = function(shape) {
var parentShape = shape.parent;
@ -86,6 +128,7 @@ BpmnUpdater.prototype.updateShapeParent = function(shape) {
this.updateDiParent(businessObject.di, parentDi);
};
BpmnUpdater.prototype.updateBounds = function(shape) {
var di = shape.businessObject.di;
@ -98,6 +141,7 @@ BpmnUpdater.prototype.updateBounds = function(shape) {
});
};
BpmnUpdater.prototype.updateDiParent = function(di, parentDi) {
if (parentDi && !parentDi.$instanceOf('bpmndi:BPMNPlane')) {
@ -145,6 +189,11 @@ BpmnUpdater.prototype.updateSemanticParent = function(businessObject, newParent)
};
BpmnUpdater.prototype.updateConnectionWaypoints = function(connection) {
connection.businessObject.di.set('waypoint', this._bpmnFactory.createDiWaypoints(connection.waypoints));
};
BpmnUpdater.prototype.updateConnection = function(connection) {
var businessObject = connection.businessObject,

View File

@ -11,5 +11,5 @@ module.exports = {
modeling: [ 'type', require('./Modeling') ],
labelSupport: [ 'type', require('./LabelSupport') ],
layouter: [ 'type', require('diagram-js/lib/features/modeling/Layouter') ],
connectionLayouter: [ 'type', require('diagram-js/lib/layout/CroppingConnectionLayouter') ]
connectionDocking: [ 'type', require('diagram-js/lib/layout/CroppingConnectionDocking') ]
};

61
test/fixtures/bpmn/sequence-flows.bpmn vendored Normal file
View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" id="simple" targetNamespace="http://bpmn.io/schema/bpmn">
<bpmn2:process id="Process_1" isExecutable="false">
<bpmn2:endEvent id="EndEvent_1" name="End Event 1">
<bpmn2:incoming>SequenceFlow_2</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:task id="Task_1" name="Task 1"/>
<bpmn2:exclusiveGateway id="Gateway_1" name="Gateway 1&#xD;&#xA;">
<bpmn2:outgoing>SequenceFlow_2</bpmn2:outgoing>
<bpmn2:outgoing>SequenceFlow_1</bpmn2:outgoing>
</bpmn2:exclusiveGateway>
<bpmn2:sequenceFlow id="SequenceFlow_2" name="Sequence Flow 2" sourceRef="Gateway_1" targetRef="EndEvent_1"/>
<bpmn2:task id="Task_2" name="Task 3">
<bpmn2:incoming>SequenceFlow_1</bpmn2:incoming>
</bpmn2:task>
<bpmn2:sequenceFlow id="SequenceFlow_1" name="Sequence Flow 1" sourceRef="Gateway_1" targetRef="Task_2"/>
<bpmn2:task id="Task_3" name="Task 2"/>
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="_BPMNShape_EndEvent_2" bpmnElement="EndEvent_1">
<dc:Bounds height="36.0" width="36.0" x="708.0" y="144.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="22.0" width="65.0" x="694.0" y="185.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Task_3" bpmnElement="Task_2">
<dc:Bounds height="80.0" width="100.0" x="732.0" y="396.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Task_4" bpmnElement="Task_1">
<dc:Bounds height="80.0" width="100.0" x="192.0" y="336.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_ExclusiveGateway_2" bpmnElement="Gateway_1" isMarkerVisible="true">
<dc:Bounds height="50.0" width="50.0" x="528.0" y="316.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="0.0" width="0.0" x="553.0" y="371.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Task_6" bpmnElement="Task_3">
<dc:Bounds height="80.0" width="100.0" x="348.0" y="122.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_6" bpmnElement="SequenceFlow_2" sourceElement="_BPMNShape_ExclusiveGateway_2" targetElement="_BPMNShape_EndEvent_2">
<di:waypoint xsi:type="dc:Point" x="553.0" y="316.0"/>
<di:waypoint xsi:type="dc:Point" x="553.0" y="162.0"/>
<di:waypoint xsi:type="dc:Point" x="708.0" y="162.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="22.0" width="106.0" x="564.0" y="240.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_7" bpmnElement="SequenceFlow_1" sourceElement="_BPMNShape_ExclusiveGateway_2" targetElement="_BPMNShape_Task_3">
<di:waypoint xsi:type="dc:Point" x="578.0" y="341.0"/>
<di:waypoint xsi:type="dc:Point" x="934.0" y="341.0"/>
<di:waypoint xsi:type="dc:Point" x="934.0" y="436.0"/>
<di:waypoint xsi:type="dc:Point" x="832.0" y="436.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="22.0" width="47.0" x="831.0" y="312.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>

View File

@ -1,120 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" id="_zQGpIK9BEeOZpaQF18vcig" targetNamespace="http://activiti.org/bpmn">
<bpmn2:process id="Process_1" isExecutable="false">
<bpmn2:startEvent id="StartEvent_1" name="Process&#xD;&#xA;started">
<bpmn2:outgoing>SequenceFlow_1</bpmn2:outgoing>
</bpmn2:startEvent>
<bpmn2:task id="Task_1" name="First task in the process">
<bpmn2:incoming>SequenceFlow_1</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_2</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:sequenceFlow id="SequenceFlow_1" name="" sourceRef="StartEvent_1" targetRef="Task_1"/>
<bpmn2:exclusiveGateway id="ExclusiveGateway_1" name="question?">
<bpmn2:incoming>SequenceFlow_2</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_3</bpmn2:outgoing>
<bpmn2:outgoing>SequenceFlow_4</bpmn2:outgoing>
</bpmn2:exclusiveGateway>
<bpmn2:sequenceFlow id="SequenceFlow_2" name="" sourceRef="Task_1" targetRef="ExclusiveGateway_1"/>
<bpmn2:task id="Task_2" name="task for ok">
<bpmn2:incoming>SequenceFlow_3</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_5</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:sequenceFlow id="SequenceFlow_3" name="ok" sourceRef="ExclusiveGateway_1" targetRef="Task_2"/>
<bpmn2:task id="Task_3" name="task for not ok">
<bpmn2:incoming>SequenceFlow_4</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_6</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:sequenceFlow id="SequenceFlow_4" name="not ok" sourceRef="ExclusiveGateway_1" targetRef="Task_3"/>
<bpmn2:exclusiveGateway id="ExclusiveGateway_2">
<bpmn2:incoming>SequenceFlow_5</bpmn2:incoming>
<bpmn2:incoming>SequenceFlow_6</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_7</bpmn2:outgoing>
</bpmn2:exclusiveGateway>
<bpmn2:sequenceFlow id="SequenceFlow_5" name="" sourceRef="Task_2" targetRef="ExclusiveGateway_2"/>
<bpmn2:sequenceFlow id="SequenceFlow_6" name="" sourceRef="Task_3" targetRef="ExclusiveGateway_2"/>
<bpmn2:task id="Task_4" name="task with crazy characters &#xD;&#xA;*+üäö/!?">
<bpmn2:incoming>SequenceFlow_7</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_8</bpmn2:outgoing>
</bpmn2:task>
<bpmn2:sequenceFlow id="SequenceFlow_7" name="" sourceRef="ExclusiveGateway_2" targetRef="Task_4"/>
<bpmn2:endEvent id="EndEvent_1" name="Process&#xD;&#xA;ended">
<bpmn2:incoming>SequenceFlow_8</bpmn2:incoming>
</bpmn2:endEvent>
<bpmn2:sequenceFlow id="SequenceFlow_8" name="" sourceRef="Task_4" targetRef="EndEvent_1"/>
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_5" bpmnElement="StartEvent_1">
<dc:Bounds height="36.0" width="36.0" x="250.0" y="252.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_Task_2" bpmnElement="Task_1">
<dc:Bounds height="80.0" width="100.0" x="336.0" y="230.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_1" bpmnElement="SequenceFlow_1" sourceElement="_BPMNShape_StartEvent_5" targetElement="_BPMNShape_Task_2">
<di:waypoint xsi:type="dc:Point" x="286.0" y="270.0"/>
<di:waypoint xsi:type="dc:Point" x="336.0" y="270.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_ExclusiveGateway_2" bpmnElement="ExclusiveGateway_1" isMarkerVisible="true">
<dc:Bounds height="50.0" width="50.0" x="486.0" y="245.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="22.0" width="62.0" x="480.0" y="216.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_2" bpmnElement="SequenceFlow_2" sourceElement="_BPMNShape_Task_2" targetElement="_BPMNShape_ExclusiveGateway_2">
<di:waypoint xsi:type="dc:Point" x="436.0" y="270.0"/>
<di:waypoint xsi:type="dc:Point" x="486.0" y="270.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_Task_3" bpmnElement="Task_2">
<dc:Bounds height="80.0" width="100.0" x="586.0" y="230.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_3" bpmnElement="SequenceFlow_3" sourceElement="_BPMNShape_ExclusiveGateway_2" targetElement="_BPMNShape_Task_3">
<di:waypoint xsi:type="dc:Point" x="536.0" y="270.0"/>
<di:waypoint xsi:type="dc:Point" x="586.0" y="270.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="22.0" width="20.0" x="540.0" y="270.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_Task_4" bpmnElement="Task_3">
<dc:Bounds height="80.0" width="100.0" x="586.0" y="330.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_4" bpmnElement="SequenceFlow_4" sourceElement="_BPMNShape_ExclusiveGateway_2" targetElement="_BPMNShape_Task_4">
<di:waypoint xsi:type="dc:Point" x="511.0" y="295.0"/>
<di:waypoint xsi:type="dc:Point" x="511.0" y="370.0"/>
<di:waypoint xsi:type="dc:Point" x="586.0" y="370.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="22.0" width="42.0" x="516.0" y="374.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_ExclusiveGateway_3" bpmnElement="ExclusiveGateway_2" isMarkerVisible="true">
<dc:Bounds height="50.0" width="50.0" x="736.0" y="245.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_5" bpmnElement="SequenceFlow_5" sourceElement="_BPMNShape_Task_3" targetElement="_BPMNShape_ExclusiveGateway_3">
<di:waypoint xsi:type="dc:Point" x="686.0" y="270.0"/>
<di:waypoint xsi:type="dc:Point" x="736.0" y="270.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_6" bpmnElement="SequenceFlow_6" sourceElement="_BPMNShape_Task_4" targetElement="_BPMNShape_ExclusiveGateway_3">
<di:waypoint xsi:type="dc:Point" x="686.0" y="370.0"/>
<di:waypoint xsi:type="dc:Point" x="711.0" y="370.0"/>
<di:waypoint xsi:type="dc:Point" x="761.0" y="370.0"/>
<di:waypoint xsi:type="dc:Point" x="761.0" y="295.0"/>
<bpmndi:BPMNLabel>
<dc:Bounds height="6.0" width="6.0" x="758.0" y="370.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_Task_5" bpmnElement="Task_4">
<dc:Bounds height="80.0" width="100.0" x="836.0" y="230.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_7" bpmnElement="SequenceFlow_7" sourceElement="_BPMNShape_ExclusiveGateway_3" targetElement="_BPMNShape_Task_5">
<di:waypoint xsi:type="dc:Point" x="786.0" y="270.0"/>
<di:waypoint xsi:type="dc:Point" x="836.0" y="270.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_EndEvent_8" bpmnElement="EndEvent_1">
<dc:Bounds height="36.0" width="36.0" x="986.0" y="252.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_8" bpmnElement="SequenceFlow_8" sourceElement="_BPMNShape_Task_5" targetElement="_BPMNShape_EndEvent_8">
<di:waypoint xsi:type="dc:Point" x="936.0" y="270.0"/>
<di:waypoint xsi:type="dc:Point" x="986.0" y="270.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>

View File

@ -1,52 +1 @@
var jsondiffpatch = require('jsondiffpatch'),
_ = require('lodash');
var compare = jsondiffpatch.create({
objectHash: function (obj) {
return JSON.stringify(obj);
}
});
function deepEquals(actual, expected) {
var actualClone = _.cloneDeep(actual);
var expectedClone = _.cloneDeep(expected);
var result = {
pass: _.isEqual(actualClone, expectedClone)
};
if (!result.pass) {
console.error('[to-deep-equal] elements do not equal. diff: ', compare.diff(actualClone, expectedClone), false, 4);
}
return result;
}
function wrap(isOld, callback) {
if (isOld) {
return function(expected) {
return callback(expected, this.actual).pass;
};
} else {
return callback;
}
}
function addMatchers() {
// DIRTY HACK DDDSZZZ
// Remove when we got jasmin 2.x in browser AND node env
var old = !jasmine.addMatchers;
(old ? this : jasmine).addMatchers({
toDeepEqual: wrap(old, function(actual, expected) {
return deepEquals(actual, expected);
})
});
}
module.exports.add = addMatchers;
module.exports = require('diagram-js/test/Matchers');

View File

@ -13,7 +13,7 @@ var Modeler = require('../../../lib/Modeler');
describe('modeler', function() {
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
var container;

View File

@ -13,7 +13,7 @@ var Viewer = require('../../../lib/Viewer');
describe('viewer', function() {
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
var container;

View File

@ -11,7 +11,7 @@ var fs = require('fs');
describe('draw - bpmn renderer', function() {
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
it('should render activity markers', function(done) {

View File

@ -14,7 +14,7 @@ var contextPadModule = require('../../../../../lib/features/context-pad'),
describe('features - context-pad', function() {
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
var diagramXML = fs.readFileSync('test/fixtures/bpmn/complex.bpmn', 'utf-8');

View File

@ -19,7 +19,7 @@ var LabelUtil = require('../../../../../lib/features/label-editing/LabelUtil');
describe('features - label-editing', function() {
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
var diagramXML = fs.readFileSync('test/fixtures/bpmn/features/label-editing/labels.bpmn', 'utf-8');

View File

@ -16,7 +16,7 @@ var labelEditingModule = require('../../../../../lib/features/label-editing'),
describe('direct editing - touch integration', function() {
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
var container;

View File

@ -15,7 +15,7 @@ var modelingModule = require('../../../../../lib/features/modeling'),
describe('features/modeling - append shape', function() {
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
var diagramXML = fs.readFileSync('test/fixtures/bpmn/simple.bpmn', 'utf-8');
@ -315,13 +315,13 @@ describe('features/modeling - append shape', function() {
describe('ExclusiveGateway', function() {
it('should append', inject(function(elementRegistry, bpmnModeling) {
it('should append', inject(function(elementRegistry, modeling) {
// given
var startEventShape = elementRegistry.getById('StartEvent_1');
// when
var targetShape = bpmnModeling.appendFlowNode(startEventShape, null, 'bpmn:ExclusiveGateway'),
var targetShape = modeling.appendFlowNode(startEventShape, 'bpmn:ExclusiveGateway'),
target = targetShape.businessObject;
// then
@ -330,7 +330,7 @@ describe('features/modeling - append shape', function() {
}));
it('should add to parent (sub process)', inject(function(elementRegistry, bpmnModeling) {
it('should add to parent (sub process)', inject(function(elementRegistry, modeling) {
// given
var startEventShape = elementRegistry.getById('StartEvent_1');
@ -340,7 +340,7 @@ describe('features/modeling - append shape', function() {
subProcess = subProcessShape.businessObject;
// when
var targetShape = bpmnModeling.appendFlowNode(startEventShape, null, 'bpmn:ExclusiveGateway'),
var targetShape = modeling.appendFlowNode(startEventShape, 'bpmn:ExclusiveGateway'),
target = targetShape.businessObject;
// then
@ -348,7 +348,7 @@ describe('features/modeling - append shape', function() {
}));
it('should undo append', inject(function(elementRegistry, bpmnModeling, commandStack) {
it('should undo append', inject(function(elementRegistry, modeling, commandStack) {
// given
var startEventShape = elementRegistry.getById('StartEvent_1');
@ -357,7 +357,7 @@ describe('features/modeling - append shape', function() {
var startEvent = startEventShape.businessObject,
subProcess = subProcessShape.businessObject;
var targetShape = bpmnModeling.appendFlowNode(startEventShape, null, 'bpmn:ExclusiveGateway'),
var targetShape = modeling.appendFlowNode(startEventShape, 'bpmn:ExclusiveGateway'),
target = targetShape.businessObject;
// when

View File

@ -13,7 +13,7 @@ var modelingModule = require('../../../../../lib/features/modeling');
xdescribe('features - bpmn-factory', function() {
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
var diagramXML = fs.readFileSync('test/fixtures/bpmn/simple.bpmn', 'utf-8');

View File

@ -0,0 +1,153 @@
'use strict';
var Matchers = require('../../../Matchers'),
TestHelper = require('../../../TestHelper');
/* global bootstrapBpmnJS, inject */
var _ = require('lodash');
var fs = require('fs');
var modelingModule = require('../../../../../lib/features/modeling'),
drawModule = require('../../../../../lib/draw');
describe('features/modeling - create connection', function() {
beforeEach(Matchers.addDeepEquals);
var diagramXML = fs.readFileSync('test/fixtures/bpmn/sequence-flows.bpmn', 'utf-8');
var testModules = [ drawModule, modelingModule ];
beforeEach(bootstrapBpmnJS(diagramXML, { modules: testModules }));
describe('connection handling', function() {
it('should execute', inject(function(elementRegistry, modeling) {
// given
var taskShape = elementRegistry.getById('Task_1'),
task = taskShape.businessObject,
gatewayShape = elementRegistry.getById('Gateway_1'),
gateway = gatewayShape.businessObject;
// when
var sequenceFlowConnection = modeling.createConnection(taskShape, gatewayShape, {
type: 'bpmn:SequenceFlow',
}, taskShape.parent);
var sequenceFlow = sequenceFlowConnection.businessObject;
// then
expect(sequenceFlowConnection).toBeDefined();
expect(sequenceFlow).toBeDefined();
expect(sequenceFlow.sourceRef).toBe(task);
expect(sequenceFlow.targetRef).toBe(gateway);
expect(task.outgoing).toContain(sequenceFlow);
expect(gateway.incoming).toContain(sequenceFlow);
expect(sequenceFlow.di.$parent).toBe(task.di.$parent);
expect(sequenceFlow.di.$parent.planeElement).toContain(sequenceFlow.di);
// expect cropped connection
expect(sequenceFlowConnection.waypoints).toDeepEqual([
{ original: { x: 242, y: 376 }, x: 292, y: 370 },
{ original: { x: 553, y: 341 }, x: 531, y: 344 }
]);
// expect cropped waypoints in di
expect(sequenceFlow.di.waypoint).toDeepEqual([
{ $type: 'dc:Point', x: 292, y: 370 },
{ $type: 'dc:Point', x: 531, y: 344 }
]);
}));
});
describe('undo support', function() {
it('should undo', inject(function(elementRegistry, commandStack, modeling) {
// given
var taskShape = elementRegistry.getById('Task_1'),
task = taskShape.businessObject,
gatewayShape = elementRegistry.getById('Gateway_1'),
gateway = gatewayShape.businessObject;
var sequenceFlowConnection = modeling.createConnection(taskShape, gatewayShape, {
type: 'bpmn:SequenceFlow',
}, taskShape.parent);
var sequenceFlow = sequenceFlowConnection.businessObject;
// when
commandStack.undo();
// then
expect(sequenceFlow.$parent).toBe(null);
expect(sequenceFlow.sourceRef).toBe(null);
expect(sequenceFlow.targetRef).toBe(null);
expect(task.outgoing).not.toContain(sequenceFlow);
expect(gateway.incoming).not.toContain(sequenceFlow);
}));
});
describe('redo support', function() {
it('should redo', inject(function(elementRegistry, commandStack, modeling) {
// given
var taskShape = elementRegistry.getById('Task_1'),
task = taskShape.businessObject,
gatewayShape = elementRegistry.getById('Gateway_1'),
gateway = gatewayShape.businessObject;
var sequenceFlowConnection = modeling.createConnection(taskShape, gatewayShape, {
type: 'bpmn:SequenceFlow',
}, taskShape.parent);
var sequenceFlow = sequenceFlowConnection.businessObject;
// when
commandStack.undo();
commandStack.redo();
// then
expect(sequenceFlow.sourceRef).toBe(task);
expect(sequenceFlow.targetRef).toBe(gateway);
expect(task.outgoing).toContain(sequenceFlow);
expect(gateway.incoming).toContain(sequenceFlow);
expect(sequenceFlow.di.$parent).toBe(task.di.$parent);
expect(sequenceFlow.di.$parent.planeElement).toContain(sequenceFlow.di);
// expect cropped connection
expect(sequenceFlowConnection.waypoints).toDeepEqual([
{ original: { x: 242, y: 376 }, x: 292, y: 370 },
{ original: { x: 553, y: 341 }, x: 531, y: 344 }
]);
// expect cropped waypoints in di
expect(sequenceFlow.di.waypoint).toDeepEqual([
{ $type: 'dc:Point', x: 292, y: 370 },
{ $type: 'dc:Point', x: 531, y: 344 }
]);
}));
});
});

View File

@ -0,0 +1,106 @@
'use strict';
var Matchers = require('../../../Matchers'),
TestHelper = require('../../../TestHelper');
/* global bootstrapBpmnJS, inject */
var _ = require('lodash');
var fs = require('fs');
var modelingModule = require('../../../../../lib/features/modeling'),
drawModule = require('../../../../../lib/draw');
describe('features/modeling - layout connection', function() {
beforeEach(Matchers.addDeepEquals);
var diagramXML = fs.readFileSync('test/fixtures/bpmn/sequence-flows.bpmn', 'utf-8');
var testModules = [ drawModule, modelingModule ];
beforeEach(bootstrapBpmnJS(diagramXML, { modules: testModules }));
describe('connection handling', function() {
it('should execute', inject(function(elementRegistry, modeling) {
// given
var sequenceFlowConnection = elementRegistry.getById('SequenceFlow_1'),
sequenceFlow = sequenceFlowConnection.businessObject;
// when
modeling.layoutConnection(sequenceFlowConnection);
// then
// expect cropped connection
expect(sequenceFlowConnection.waypoints).toDeepEqual([
{ original: { x: 553, y: 341 }, x: 571, y: 348 },
{ original: { x: 782, y: 436 }, x: 732, y: 415 }
]);
// expect cropped waypoints in di
expect(sequenceFlow.di.waypoint).toDeepEqual([
{ $type: 'dc:Point', x: 571, y: 348 },
{ $type: 'dc:Point', x: 732, y: 415 }
]);
}));
});
describe('undo support', function() {
it('should undo', inject(function(elementRegistry, commandStack, modeling) {
// given
var sequenceFlowConnection = elementRegistry.getById('SequenceFlow_1'),
sequenceFlow = sequenceFlowConnection.businessObject;
var oldWaypoints = sequenceFlowConnection.waypoints,
oldDiWaypoints = sequenceFlow.di.waypoint;
modeling.layoutConnection(sequenceFlowConnection);
// when
commandStack.undo();
// then
expect(sequenceFlowConnection.waypoints).toDeepEqual(oldWaypoints);
expect(sequenceFlow.di.waypoint).toDeepEqual(oldDiWaypoints);
}));
});
describe('redo support', function() {
it('should redo', inject(function(elementRegistry, commandStack, modeling) {
// given
var sequenceFlowConnection = elementRegistry.getById('SequenceFlow_1'),
sequenceFlow = sequenceFlowConnection.businessObject;
modeling.layoutConnection(sequenceFlowConnection);
var newWaypoints = sequenceFlowConnection.waypoints,
newDiWaypoints = sequenceFlow.di.waypoint;
// when
commandStack.undo();
commandStack.redo();
// then
expect(sequenceFlowConnection.waypoints).toDeepEqual(newWaypoints);
expect(sequenceFlow.di.waypoint).toDeepEqual(newDiWaypoints);
}));
});
});

View File

@ -15,7 +15,7 @@ var modelingModule = require('../../../../../lib/features/modeling'),
describe('features/modeling - move shape', function() {
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
var diagramXML = fs.readFileSync('test/fixtures/bpmn/simple.bpmn', 'utf-8');

View File

@ -15,7 +15,7 @@ var touchModule = require('../../../../../lib/features/touch'),
describe('features - touch', function() {
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
var diagramXML = fs.readFileSync('test/fixtures/bpmn/complex.bpmn', 'utf-8');

View File

@ -17,7 +17,7 @@ var zoomscrollModule = require('../../../../../lib/features/zoomscroll'),
describe('features - zoomscroll', function() {
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
var diagramXML = fs.readFileSync('test/fixtures/bpmn/complex.bpmn', 'utf-8');

View File

@ -22,7 +22,7 @@ describe('import - importer', function() {
return BpmnModel.fromXML(xml, 'bpmn:Definitions', opts, callback);
}
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
var container;

View File

@ -11,7 +11,7 @@ var fs = require('fs');
describe('import - collapsed container', function() {
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
describe('in process', function() {

View File

@ -11,7 +11,7 @@ var fs = require('fs');
describe('import - labels', function() {
beforeEach(Matchers.add);
beforeEach(Matchers.addDeepEquals);
describe('should import embedded labels', function() {