bpmn-js/test/spec/features/copy-paste/ModdleCopySpec.js

797 lines
24 KiB
JavaScript

import {
bootstrapModeler,
inject
} from 'test/TestHelper';
import copyPasteModule from 'lib/features/copy-paste';
import coreModule from 'lib/core';
import modelingModule from 'lib/features/modeling';
import camundaModdleModule from 'camunda-bpmn-moddle/lib';
import camundaPackage from 'camunda-bpmn-moddle/resources/camunda.json';
import {
getBusinessObject,
is
} from 'lib/util/ModelUtil';
var HIGH_PRIORITY = 3000;
describe('features/copy-paste/ModdleCopy', function() {
var testModules = [
camundaModdleModule,
copyPasteModule,
coreModule,
modelingModule
];
var basicXML = require('../../../fixtures/bpmn/basic.bpmn');
beforeEach(bootstrapModeler(basicXML, {
modules: testModules,
moddleExtensions: {
camunda: camundaPackage
}
}));
describe('simple', function() {
it('should copy primitive properties', inject(function(moddle, moddleCopy) {
// given
var userTask = moddle.create('bpmn:UserTask', {
asyncBefore: true
});
// when
var serviceTask = moddleCopy.copyElement(userTask, moddle.create('bpmn:ServiceTask'));
// then
expect(serviceTask.asyncBefore).to.be.true;
expectNoAttrs(serviceTask);
}));
it('should copy arrays of properties', inject(function(moddle, moddleCopy) {
// given
var messageEventDefinition = moddle.create('bpmn:MessageEventDefinition'),
signalEventDefinition = moddle.create('bpmn:SignalEventDefinition'),
startEvent = moddle.create('bpmn:StartEvent');
startEvent.eventDefinitions = [ messageEventDefinition, signalEventDefinition ];
// when
var endEvent = moddleCopy.copyElement(startEvent, moddle.create('bpmn:EndEvent'));
// then
var eventDefinitions = endEvent.eventDefinitions;
expect(eventDefinitions).to.have.length(2);
expect(eventDefinitions[0].$type).to.equal('bpmn:MessageEventDefinition');
expect(eventDefinitions[1].$type).to.equal('bpmn:SignalEventDefinition');
expectNoAttrs(endEvent);
}));
it('should NOT copy properties that are not allowed in target element', inject(
function(moddle, moddleCopy) {
// given
var userTask = moddle.create('bpmn:UserTask', {
assignee: 'foobar'
});
// when
var serviceTask = moddleCopy.copyElement(userTask, moddle.create('bpmn:ServiceTask'));
// then
expect(serviceTask.assignee).not.to.exist;
expectNoAttrs(serviceTask);
}
));
it('should NOT copy IDs if taken', inject(function(moddle, moddleCopy, canvas, modeling) {
// given
var task = modeling.createShape({ type: 'bpmn:Task' },
{ x: 0, y: 0 }, canvas.getRootElement());
var taskId = task.id;
// when
var userTask = moddleCopy.copyElement(task.businessObject, moddle.create('bpmn:UserTask'));
// then
expect(userTask.id).not.to.equal(taskId);
expectNoAttrs(userTask);
}));
it('should copy IDs if free', inject(function(moddle, moddleCopy, canvas, modeling) {
// given
var task = modeling.createShape({ type: 'bpmn:Task' },
{ x: 0, y: 0 }, canvas.getRootElement());
var taskId = task.id;
// when
modeling.removeShape(task);
var userTask = moddleCopy.copyElement(task.businessObject, moddle.create('bpmn:UserTask'));
// then
expect(userTask.id).to.equal(taskId);
expectNoAttrs(userTask);
}));
it('should NOT copy references', inject(function(moddle, moddleCopy) {
// given
var processRef = moddle.create('bpmn:Process'),
participant = moddle.create('bpmn:Participant');
participant.processRef = processRef;
// when
participant = moddleCopy.copyElement(participant, moddle.create('bpmn:Participant'));
// then
expect(participant.processRef).not.to.equal(processRef);
}));
it('should copy extension elements last', inject(function(moddleCopy, eventBus, moddle) {
// given
var connector = moddle.create('camunda:Connector'),
extensionElements = moddle.create('bpmn:ExtensionElements'),
messageEventDefinition = moddle.create('bpmn:MessageEventDefinition'),
messageEndEvent = moddle.create('bpmn:EndEvent');
connector.$parent = extensionElements;
extensionElements.$parent = messageEventDefinition;
extensionElements.values = [ connector ];
messageEventDefinition.$parent = messageEndEvent;
messageEventDefinition.extensionElements = extensionElements;
messageEndEvent.eventDefinitions = [ messageEventDefinition ];
var propertyNames = [];
eventBus.on('moddleCopy.canCopyProperty', function(context) {
var propertyName = context.propertyName;
propertyNames.push(propertyName);
});
moddleCopy.copyElement(messageEndEvent, moddle.create('bpmn:EndEvent'), [
'extensionElements',
'name'
]);
expect(propertyNames).to.eql([
'name',
'extensionElements'
]);
}));
it('should NOT copy empty extension elements', inject(function(moddle, moddleCopy) {
// given
var connector = moddle.create('camunda:Connector'),
extensionElements = moddle.create('bpmn:ExtensionElements'),
messageEventDefinition = moddle.create('bpmn:MessageEventDefinition'),
messageEndEvent = moddle.create('bpmn:EndEvent');
connector.$parent = extensionElements;
extensionElements.$parent = messageEventDefinition;
extensionElements.values = [ connector ];
messageEventDefinition.$parent = messageEndEvent;
messageEventDefinition.extensionElements = extensionElements;
messageEndEvent.eventDefinitions = [ messageEventDefinition ];
var startEvent = moddleCopy.copyElement(messageEndEvent, moddle.create('bpmn:StartEvent'));
// connector not allowed in start event
expect(startEvent.eventDefinitions[0].extensionElements).not.to.exist;
}));
it('should only copy specified properties', inject(function(moddle, moddleCopy) {
// given
var userTask = moddle.create('bpmn:UserTask', {
asyncBefore: true,
name: 'foo'
});
// when
var serviceTask = moddleCopy.copyElement(
userTask,
moddle.create('bpmn:ServiceTask'),
'asyncBefore'
);
// then
expect(serviceTask.asyncBefore).to.be.true;
expect(serviceTask.name).not.to.exist;
expectNoAttrs(serviceTask);
}));
});
describe('nested', function() {
it('should copy documentation', inject(function(moddle, moddleCopy) {
// given
var documentation = [
moddle.create('bpmn:Documentation', { text: 'FOO\nBAR', textFormat: 'xyz' }),
moddle.create('bpmn:Documentation', { text: '<html></html>' })
];
var userTask = moddle.create('bpmn:UserTask');
userTask.documentation = documentation;
// when
var serviceTask = moddleCopy.copyElement(userTask, moddle.create('bpmn:ServiceTask'));
expect(serviceTask.documentation[0].$parent).to.equal(serviceTask);
expect(serviceTask.documentation[0].text).to.equal('FOO\nBAR');
expect(serviceTask.documentation[0].textFormat).to.equal('xyz');
expect(serviceTask.documentation[1].$parent).to.equal(serviceTask);
expect(serviceTask.documentation[1].text).to.equal('<html></html>');
}));
it('should copy execution listener', inject(function(moddle, moddleCopy) {
// given
var script = moddle.create('camunda:Script', {
scriptFormat: 'groovy',
value: 'foo = bar;'
});
var executionListener = moddle.create('camunda:ExecutionListener', {
event: 'start',
script: script
});
var extensionElements = moddle.create('bpmn:ExtensionElements'),
userTask = moddle.create('bpmn:UserTask');
executionListener.$parent = extensionElements;
extensionElements.$parent = userTask;
extensionElements.values = [ executionListener ];
userTask.extensionElements = extensionElements;
// when
var serviceTask = moddleCopy.copyElement(userTask, moddle.create('bpmn:ServiceTask'));
// then
executionListener = serviceTask.extensionElements.values[0];
expect(executionListener).to.exist;
expect(executionListener.$type).to.equal('camunda:ExecutionListener');
expect(executionListener.$parent).to.equal(serviceTask.extensionElements);
expect(executionListener.event).to.equal('start');
script = executionListener.script;
expect(script).to.exist;
expect(script.$type).to.equal('camunda:Script');
expect(script.$parent).to.equal(executionListener);
expect(script.scriptFormat).to.equal('groovy');
expect(script.value).to.equal('foo = bar;');
}));
it('should copy output parameter', inject(function(moddle, moddleCopy) {
// given
var outputParameter = moddle.create('camunda:OutputParameter', {
name: 'foo',
definition: moddle.create('camunda:List', {
items: [
moddle.create('camunda:Value', { value: '${1+1}' }),
moddle.create('camunda:Value', { value: '${1+2}' }),
moddle.create('camunda:Value', { value: '${1+3}' })
]
})
});
var inputOutput = moddle.create('camunda:InputOutput', {
outputParameters: [ outputParameter ]
});
var extensionElements = moddle.create('bpmn:ExtensionElements'),
userTask = moddle.create('bpmn:UserTask');
extensionElements.$parent = userTask;
extensionElements.values = [ inputOutput ];
userTask.extensionElements = extensionElements;
// when
var subProcess = moddleCopy.copyElement(userTask, moddle.create('bpmn:SubProcess'));
// then
extensionElements = subProcess.extensionElements;
inputOutput = extensionElements.values[0];
expect(inputOutput.$type).to.equal('camunda:InputOutput');
expect(inputOutput.$parent).to.equal(extensionElements);
outputParameter = inputOutput.outputParameters[0];
expect(outputParameter.$type).to.equal('camunda:OutputParameter');
expect(outputParameter.$parent).to.equal(inputOutput);
expect(outputParameter.name).to.equal('foo');
var definition = outputParameter.definition;
expect(definition.$type).to.equal('camunda:List');
expect(definition.$parent).to.equal(outputParameter);
var items = definition.items;
expect(items[0].$type).to.equal('camunda:Value');
expect(items[0].$parent).to.equal(definition);
expect(items[0].value).to.equal('${1+1}');
expect(items[1].$type).to.equal('camunda:Value');
expect(items[1].$parent).to.equal(definition);
expect(items[1].value).to.equal('${1+2}');
expect(items[2].$type).to.equal('camunda:Value');
expect(items[2].$parent).to.equal(definition);
expect(items[2].value).to.equal('${1+3}');
}));
});
describe('integration', function() {
describe('camunda:Connector', function() {
it('should copy if parent is message event definition and is child of end event', inject(
function(moddle, moddleCopy) {
// given
var connector = moddle.create('camunda:Connector', {
connectorId: 'foo'
});
var extensionElements = moddle.create('bpmn:ExtensionElements'),
messageEventDefinition = moddle.create('bpmn:MessageEventDefinition'),
messageIntermediateThrowEvent = moddle.create('bpmn:IntermediateThrowEvent');
connector.$parent = extensionElements;
extensionElements.$parent = messageEventDefinition;
extensionElements.values = [ connector ];
messageEventDefinition.$parent = messageIntermediateThrowEvent;
messageEventDefinition.extensionElements = extensionElements;
messageIntermediateThrowEvent.eventDefinitions = [ messageEventDefinition ];
// when
var endEvent =
moddleCopy.copyElement(messageIntermediateThrowEvent, moddle.create('bpmn:EndEvent'));
// then
extensionElements = endEvent.eventDefinitions[0].extensionElements;
expect(extensionElements.values[0].$type).to.equal('camunda:Connector');
expect(extensionElements.values[0].connectorId).to.equal('foo');
}
));
});
describe('camunda:Field', function() {
it('should copy if parent is message event definition and is child of end event', inject(
function(moddle, moddleCopy) {
// given
var field = moddle.create('camunda:Field', {
name: 'foo'
});
var extensionElements = moddle.create('bpmn:ExtensionElements'),
messageEventDefinition = moddle.create('bpmn:MessageEventDefinition'),
messageIntermediateThrowEvent = moddle.create('bpmn:IntermediateThrowEvent');
field.$parent = extensionElements;
extensionElements.$parent = messageEventDefinition;
extensionElements.values = [ field ];
messageEventDefinition.$parent = messageIntermediateThrowEvent;
messageEventDefinition.extensionElements = extensionElements;
messageIntermediateThrowEvent.eventDefinitions = [ messageEventDefinition ];
// when
var endEvent =
moddleCopy.copyElement(messageIntermediateThrowEvent, moddle.create('bpmn:EndEvent'));
// then
extensionElements = endEvent.eventDefinitions[0].extensionElements;
expect(extensionElements.values[0].$type).to.equal('camunda:Field');
expect(extensionElements.values[0].name).to.equal('foo');
}
));
});
describe('camunda:FailedJobRetryTimeCycle', function() {
it('should copy if parent is SignalEventDefinition and is intermediate throwing', inject(
function(moddle, moddleCopy) {
// given
var retryCycle = moddle.create('camunda:FailedJobRetryTimeCycle', {
body: 'foo'
});
var extensionElements = moddle.create('bpmn:ExtensionElements'),
signalEventDefinition = moddle.create('bpmn:SignalEventDefinition'),
signalIntermediateThrowEvent = moddle.create('bpmn:IntermediateThrowEvent');
retryCycle.$parent = extensionElements;
extensionElements.$parent = signalEventDefinition;
extensionElements.values = [ retryCycle ];
signalEventDefinition.$parent = signalIntermediateThrowEvent;
signalEventDefinition.extensionElements = extensionElements;
signalIntermediateThrowEvent.eventDefinitions = [ signalEventDefinition ];
// when
var intermediateThrowEvent = moddleCopy.copyElement(
signalIntermediateThrowEvent,
moddle.create('bpmn:IntermediateThrowEvent')
);
// then
extensionElements = intermediateThrowEvent.eventDefinitions[0].extensionElements;
expect(extensionElements.values[0].$type).to.equal('camunda:FailedJobRetryTimeCycle');
expect(extensionElements.values[0].body).to.equal('foo');
}
));
it('should copy if parent is TimerEventDefinition and is catching', inject(
function(moddle, moddleCopy) {
// given
var retryCycle = moddle.create('camunda:FailedJobRetryTimeCycle', {
body: 'foo'
});
var extensionElements = moddle.create('bpmn:ExtensionElements'),
timerEventDefinition = moddle.create('bpmn:TimerEventDefinition'),
timerStartEvent = moddle.create('bpmn:StartEvent');
retryCycle.$parent = extensionElements;
extensionElements.$parent = timerEventDefinition;
extensionElements.values = [ retryCycle ];
timerEventDefinition.$parent = timerStartEvent;
timerEventDefinition.extensionElements = extensionElements;
timerStartEvent.eventDefinitions = [ timerEventDefinition ];
// when
var intermediateCatchEvent =
moddleCopy.copyElement(timerStartEvent, moddle.create('bpmn:IntermediateCatchEvent'));
// then
extensionElements = intermediateCatchEvent.eventDefinitions[0].extensionElements;
expect(extensionElements.values[0].$type).to.equal('camunda:FailedJobRetryTimeCycle');
expect(extensionElements.values[0].body).to.equal('foo');
}
));
it('should copy if parent is call activity', inject(function(moddle, moddleCopy) {
// given
var retryCycle = moddle.create('camunda:FailedJobRetryTimeCycle', {
body: 'foo'
});
var extensionElements = moddle.create('bpmn:ExtensionElements'),
loopCharacteristics = moddle.create('bpmn:MultiInstanceLoopCharacteristics'),
subProcess = moddle.create('bpmn:SubProcess');
retryCycle.$parent = extensionElements;
extensionElements.$parent = loopCharacteristics;
extensionElements.values = [ retryCycle ];
loopCharacteristics.$parent = subProcess;
loopCharacteristics.extensionElements = extensionElements;
subProcess.loopCharacteristics = loopCharacteristics;
// when
var callActivity = moddleCopy.copyElement(subProcess, moddle.create('bpmn:CallActivity'));
// then
extensionElements = callActivity.loopCharacteristics.extensionElements;
expect(extensionElements.values[0].$type).to.equal('camunda:FailedJobRetryTimeCycle');
expect(extensionElements.values[0].body).to.equal('foo');
}));
});
describe('generic properties', function() {
it('should not copy generic extension elements', inject(function(moddle, moddleCopy) {
// given
var genericExtensionElement = moddle.createAny('foo:property', {
value: 'foo'
});
var extensionElements = moddle.create('bpmn:ExtensionElements'),
startEvent = moddle.create('bpmn:StartEvent');
genericExtensionElement.$parent = extensionElements;
extensionElements.$parent = startEvent;
extensionElements.values = [ genericExtensionElement ];
startEvent.extensionElements = extensionElements;
// when
var endEvent = moddleCopy.copyElement(startEvent, moddle.create('bpmn:EndEvent'));
// then
expect(endEvent.extensionElements).not.to.exist;
}));
});
});
describe('events', function() {
it('should disallow copying properties', inject(function(moddleCopy, eventBus, moddle) {
// given
var task = moddle.create('bpmn:Task', {
name: 'foo'
});
eventBus.on('moddleCopy.canCopyProperties', HIGH_PRIORITY, function(context) {
var sourceElement = context.sourceElement;
if (is(sourceElement, 'bpmn:Task')) {
return false;
}
});
// when
var userTask = moddleCopy.copyElement(task, moddle.create('bpmn:UserTask'));
// then
expect(userTask.name).not.to.exist;
}));
it('should disallow copying property', inject(function(moddleCopy, eventBus, moddle) {
// given
var task = moddle.create('bpmn:Task', {
name: 'foo'
});
eventBus.on('moddleCopy.canCopyProperty', HIGH_PRIORITY, function(context) {
// verify provided properties
expect(context).to.have.property('parent');
expect(context).to.have.property('property');
expect(context).to.have.property('propertyName');
var propertyName = context.propertyName;
if (propertyName === 'name') {
return false;
}
});
// when
var userTask = moddleCopy.copyElement(task, moddle.create('bpmn:UserTask'));
// then
expect(userTask.name).not.to.exist;
}));
it('should disallow setting copied property', inject(function(moddleCopy, eventBus, moddle) {
// given
var task = moddle.create('bpmn:Task', {
name: 'foo'
});
eventBus.on('moddleCopy.canSetCopiedProperty', HIGH_PRIORITY, function(context) {
// verify provided properties
expect(context).to.have.property('parent');
expect(context).to.have.property('property');
expect(context).to.have.property('propertyName');
var property = context.property;
if (property === 'foo') {
return false;
}
});
// when
var userTask = moddleCopy.copyElement(task, moddle.create('bpmn:UserTask'));
// then
expect(userTask.name).not.to.exist;
}));
it('should copy primitive property', inject(function(moddleCopy, eventBus, moddle) {
// given
var task = moddle.create('bpmn:Task', {
name: 'foo'
});
eventBus.on('moddleCopy.canCopyProperty', HIGH_PRIORITY, function(context) {
var propertyName = context.propertyName;
if (propertyName === 'name') {
return 'bar';
}
});
// when
var userTask = moddleCopy.copyElement(task, moddle.create('bpmn:UserTask'));
// then
expect(userTask.name).to.equal('bar');
}));
describe('copy model element property', function() {
it('should copy and set parent', inject(function(moddleCopy, eventBus, moddle) {
// given
var startEvent = moddle.create('bpmn:StartEvent'),
messageEventDefinition = moddle.create('bpmn:MessageEventDefinition');
messageEventDefinition.$parent = startEvent;
startEvent.eventDefinitions = [ messageEventDefinition ];
eventBus.on('moddleCopy.canCopyProperty', HIGH_PRIORITY, function(context) {
var property = context.property;
if (is(property, 'bpmn:MessageEventDefinition')) {
return moddle.create('bpmn:MessageEventDefinition');
}
});
// when
var endEvent = moddleCopy.copyElement(startEvent, moddle.create('bpmn:EndEvent'));
// then
expect(endEvent.eventDefinitions).to.have.length(1);
expect(endEvent.eventDefinitions[0]).not.to.equal(messageEventDefinition);
expect(endEvent.eventDefinitions[0].$type).to.equal('bpmn:MessageEventDefinition');
}));
});
it('should copy and NOT set parent', inject(function(canvas, moddleCopy, eventBus, moddle) {
// given
var definitions = getDefinitions(canvas.getRootElement()),
categoryValue = moddle.create('bpmn:CategoryValue'),
category = moddle.create('bpmn:Category'),
group = moddle.create('bpmn:Group'),
newCategoryValue,
newCategory,
newGroup;
categoryValue.$parent = category;
category.$parent = definitions;
category.categoryValue = [ categoryValue ];
definitions.rootElements.push(category);
group.categoryValueRef = categoryValue;
eventBus.on('moddleCopy.canCopyProperty', HIGH_PRIORITY, function(context) {
var propertyName = context.propertyName;
if (propertyName !== 'categoryValueRef') {
return;
}
newCategoryValue = moddle.create('bpmn:CategoryValue');
newCategory = moddle.create('bpmn:Category');
newCategoryValue.$parent = newCategory;
newCategory.$parent = definitions;
newCategory.categoryValue = [ newCategoryValue ];
definitions.rootElements.push(newCategory);
return newCategoryValue;
});
// when
newGroup = moddleCopy.copyElement(group, moddle.create('bpmn:Group'));
// then
expect(newGroup.categoryValueRef).to.exist;
expect(newGroup.categoryValueRef).not.to.equal(categoryValue);
expect(newGroup.categoryValueRef.$parent).to.equal(newCategory);
}));
});
});
// helpers //////////
function expectNoAttrs(element) {
expect(element.$attrs).to.be.empty;
}
function getDefinitions(rootElement) {
var businessObject = getBusinessObject(rootElement);
return businessObject.$parent;
}