Skip to content

Commit

Permalink
fix: run task listener cleanup on properties change
Browse files Browse the repository at this point in the history
  • Loading branch information
misiekhardcore committed Nov 18, 2024
1 parent 5cb55ea commit 110dc0b
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 18 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ All notable changes to [camunda-bpmn-js-behaviors](https://github.com/camunda/ca

___Note:__ Yet to be released changes appear here._

* `FIX`: clean up `zeebe:TaskListeners` on user task properties update ([#90](https://github.com/camunda/camunda-bpmn-js-behaviors/pull/90))

## 1.7.0

* `FEAT`: support `zeebe:TaskListener` ([#88](https://github.com/camunda/camunda-bpmn-js-behaviors/pull/88))
Expand Down
34 changes: 25 additions & 9 deletions lib/camunda-cloud/CleanUpTaskListenersBehavior.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,22 @@ export default class CleanUpTaskListenersBehavior extends CommandInterceptor {
constructor(eventBus, modeling) {
super(eventBus);

// remove task listeners of disallowed type
// remove task listeners of disallowed type on shape replace
this.postExecuted('shape.replace', function(event) {
const element = event.context.newShape;
const taskListenersContainer = getTaskListenersContainer(element);
if (!taskListenersContainer) {
return;
}

const listeners = taskListenersContainer.get('listeners');
const newListeners = withoutDisallowedListeners(element, listeners);
updateListeners(element, modeling);
});

if (newListeners.length !== listeners.length) {
modeling.updateModdleProperties(element, taskListenersContainer, { listeners: newListeners });
// remove task listeners of disallowed type on user task properties update
this.postExecuted('element.updateModdleProperties', function(event) {
const element = event.context.element;

if (!is(element, 'bpmn:UserTask')) {
return;
}

updateListeners(element, modeling);
});

// remove empty task listener container
Expand Down Expand Up @@ -54,6 +56,20 @@ CleanUpTaskListenersBehavior.$inject = [
];

// helpers //////////
function updateListeners(element, modeling) {
const taskListenersContainer = getTaskListenersContainer(element);
if (!taskListenersContainer) {
return;
}

const listeners = taskListenersContainer.get('listeners');
const newListeners = withoutDisallowedListeners(element, listeners);

if (newListeners.length !== listeners.length) {
modeling.updateModdleProperties(element, taskListenersContainer, { listeners: newListeners });
}
}

function withoutDisallowedListeners(element, listeners) {
return listeners.filter(listener => {
if (
Expand Down
83 changes: 74 additions & 9 deletions test/camunda-cloud/CleanUpTaskListenersBehaviorSpec.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import {
bootstrapCamundaCloudModeler,
getBpmnJS,
inject
} from 'test/TestHelper';

import { getExtensionElementsList } from 'lib/util/ExtensionElementsUtil';

import { getBusinessObject } from 'bpmn-js/lib/util/ModelUtil';
import { getBusinessObject, is } from 'bpmn-js/lib/util/ModelUtil';

import diagramXML from './task-listeners.bpmn';

Expand Down Expand Up @@ -66,7 +67,7 @@ describe('camunda-cloud/features/modeling - CleanUpTaskListenersBehavior', funct

// then
el = elementRegistry.get(element);
const extensionElements = getBusinessObject(el).get('extensionElements');
const extensionElements = getElementExtensions(el);

expect(extensionElements.get('values')).to.have.lengthOf(2);
}));
Expand Down Expand Up @@ -106,7 +107,7 @@ describe('camunda-cloud/features/modeling - CleanUpTaskListenersBehavior', funct

// then
el = elementRegistry.get('UserTaskWrongType');
const container = getExtensionElementsList(getBusinessObject(el), 'zeebe:TaskListeners')[0];
const container = getFirstExtensionElement(el, 'zeebe:TaskListeners');

expect(container.get('listeners')).to.have.lengthOf(1);
}));
Expand All @@ -125,7 +126,7 @@ describe('camunda-cloud/features/modeling - CleanUpTaskListenersBehavior', funct

// then
el = elementRegistry.get('UserTaskWrongType');
const container = getExtensionElementsList(getBusinessObject(el), 'zeebe:TaskListeners')[0];
const container = getFirstExtensionElement(el, 'zeebe:TaskListeners');

expect(container.get('listeners')).to.have.lengthOf(2);
}));
Expand All @@ -145,7 +146,7 @@ describe('camunda-cloud/features/modeling - CleanUpTaskListenersBehavior', funct

// then
el = elementRegistry.get('UserTaskWrongType');
const container = getExtensionElementsList(getBusinessObject(el), 'zeebe:TaskListeners')[0];
const container = getFirstExtensionElement(el, 'zeebe:TaskListeners');

expect(container.get('listeners')).to.have.lengthOf(1);
}));
Expand All @@ -162,13 +163,13 @@ describe('camunda-cloud/features/modeling - CleanUpTaskListenersBehavior', funct

// then
el = elementRegistry.get('NonZeebeUserTask');
const extensionElements = getBusinessObject(el).get('extensionElements');
const extensionElements = getElementExtensions(el);

expect(extensionElements.get('values')).to.have.lengthOf(0);
}));


it('should remove zeebe:TaskListeners', inject(function(elementRegistry, modeling) {
it('should remove zeebe:TaskListeners container when empty', inject(function(elementRegistry, modeling) {

// given
const el = elementRegistry.get('UserTask');
Expand All @@ -178,13 +179,77 @@ describe('camunda-cloud/features/modeling - CleanUpTaskListenersBehavior', funct
modeling.updateModdleProperties(el, listenersContainer, { listeners: [] });

// then
const extensionElements = getBusinessObject(el).get('extensionElements');
const extensionElements = getElementExtensions(el);

expect(extensionElements.get('values')).to.have.lengthOf(1);
}));


it('should remove zeebe:TaskListeners when user task is not zeebe user task', inject(function(elementRegistry, modeling) {

// given
const el = elementRegistry.get('UserTask');

// when
const extensionElements = getElementExtensions(el);
modeling.updateModdleProperties(el, extensionElements, { values: removeZeebeUserTask(extensionElements) });

// then
const listenersContainer = getTaskListenersContainer(el);
expect(listenersContainer).not.to.exist;
}));


it('should NOT remove zeebe:TaskListeners when an unrelated property is added', inject(function(elementRegistry, modeling) {

// given
const el = elementRegistry.get('UserTask');

// when
addFormDefinition(el);

// then
const extensionElements = getElementExtensions(el);

const taskListeners = getFirstExtensionElement(el, 'zeebe:TaskListeners');
const userTask = getFirstExtensionElement(el, 'zeebe:UserTask');
const formDefinition = getFirstExtensionElement(el, 'zeebe:FormDefinition');

expect(extensionElements.get('values')).to.have.lengthOf(3);
expect(taskListeners).to.exist;
expect(userTask).to.exist;
expect(formDefinition).to.exist;
}));
});
});


// helpers

function getElementExtensions(element) {
return getBusinessObject(element).get('extensionElements');
}

function getFirstExtensionElement(element, type) {
return getExtensionElementsList(getBusinessObject(element), type)[0];
}

function getTaskListenersContainer(element) {
return getExtensionElementsList(getBusinessObject(element), 'zeebe:TaskListeners')[0];
return getFirstExtensionElement(element, 'zeebe:TaskListeners');
}

function removeZeebeUserTask(extensionElements) {
return extensionElements.get('values').filter(extensionElement => !is(extensionElement, 'zeebe:UserTask'));
}

function addFormDefinition(element) {
getBpmnJS().invoke(function(bpmnFactory, modeling) {
const extensionElements = getElementExtensions(element);
const values = extensionElements.get('values'),
formDefinition = bpmnFactory.create('zeebe:FormDefinition');

modeling.updateModdleProperties(element, extensionElements, {
values: values.concat(formDefinition)
});
});
}

0 comments on commit 110dc0b

Please sign in to comment.