Skip to content

Commit

Permalink
feat: add escalation-boundary-event-attached-to-ref rule
Browse files Browse the repository at this point in the history
Closes #110
  • Loading branch information
philippfromme committed Jul 25, 2023
1 parent 30044bb commit 16ab601
Show file tree
Hide file tree
Showing 10 changed files with 246 additions and 5 deletions.
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const camundaCloud82Rules = withConfig({
'no-candidate-users',
'no-task-schedule'
]),
'escalation-boundary-event-attached-to-ref': 'error',
'escalation-reference': 'error',
'no-signal-event-sub-process': 'error',
'task-schedule': 'error'
Expand Down Expand Up @@ -72,6 +73,7 @@ const rules = {
'collapsed-subprocess': './rules/camunda-cloud/collapsed-subprocess',
'duplicate-task-headers': './rules/camunda-cloud/duplicate-task-headers',
'error-reference': './rules/camunda-cloud/error-reference',
'escalation-boundary-event-attached-to-ref': './rules/camunda-cloud/escalation-boundary-event-attached-to-ref',
'escalation-reference': './rules/camunda-cloud/escalation-reference',
'event-based-gateway-target': './rules/camunda-cloud/event-based-gateway-target',
'executable-process': './rules/camunda-cloud/executable-process',
Expand Down
2 changes: 1 addition & 1 deletion rules/camunda-cloud/collapsed-subprocess.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module.exports = skipInNonExecutableProcess(function() {
const node = di.bpmnElement;

const error = {
message: `A <${ node.$type }> must be expanded.`,
message: `A <${ node.$type }> must be expanded`,
data: {
type: ERROR_TYPES.ELEMENT_COLLAPSED_NOT_ALLOWED,
node: node,
Expand Down
48 changes: 48 additions & 0 deletions rules/camunda-cloud/escalation-boundary-event-attached-to-ref.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const {
is,
isAny
} = require('bpmnlint-utils');

const {
getEventDefinition,
isAnyExactly
} = require('../utils/element');

const { ERROR_TYPES } = require('../utils/error-types');

const { reportErrors } = require('../utils/reporter');

const { skipInNonExecutableProcess } = require('../utils/rule');

module.exports = skipInNonExecutableProcess(function() {
function check(node, reporter) {
if (!isAny(node, [ 'bpmn:CatchEvent', 'bpmn:ThrowEvent' ])) {
return;
}

const eventDefinition = getEventDefinition(node);

if (!eventDefinition || !is(eventDefinition, 'bpmn:EscalationEventDefinition')) {
return;
}

const attachedToRef = node.get('attachedToRef');

if (attachedToRef && !isAnyExactly(attachedToRef, [ 'bpmn:CallActivity', 'bpmn:SubProcess' ])) {
reportErrors(node, reporter, {
message: `Element of type <bpmn:BoundaryEvent> with event definition of type <bpmn:EscalationEventDefinition> is not allowed to be attached to element of type <${ attachedToRef.$type }>`,
path: null,
data: {
type: ERROR_TYPES.ATTACHED_TO_REF_ELEMENT_TYPE_NOT_ALLOWED,
node,
parentNode: null,
attachedToRef
}
});
}
}

return {
check
};
});
1 change: 1 addition & 0 deletions rules/utils/error-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports.ERROR_TYPES = Object.freeze({
EXTENSION_ELEMENT_NOT_ALLOWED: 'camunda.extensionElementNotAllowed',
EXTENSION_ELEMENT_REQUIRED: 'camunda.extensionElementRequired',
FEEL_EXPRESSION_INVALID: 'camunda.feelExpressionInvalid',
ATTACHED_TO_REF_ELEMENT_TYPE_NOT_ALLOWED: 'camunda.attachedToRefElementTypeNotAllowed',
PROPERTY_DEPENDENT_REQUIRED: 'camunda.propertyDependentRequired',
PROPERTY_NOT_ALLOWED: 'camunda.propertyNotAllowed',
PROPERTY_REQUIRED: 'camunda.propertyRequired',
Expand Down
8 changes: 4 additions & 4 deletions test/camunda-cloud/collapsed-subprocess.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const invalid = [
`)),
report: {
id: 'SubProcess_1',
message: 'A <bpmn:SubProcess> must be expanded.',
message: 'A <bpmn:SubProcess> must be expanded',
data: {
type: ERROR_TYPES.ELEMENT_COLLAPSED_NOT_ALLOWED,
node: 'SubProcess_1',
Expand All @@ -101,7 +101,7 @@ const invalid = [
`)),
report: {
id: 'SubProcess_1',
message: 'A <bpmn:SubProcess> must be expanded.',
message: 'A <bpmn:SubProcess> must be expanded',
data: {
type: ERROR_TYPES.ELEMENT_COLLAPSED_NOT_ALLOWED,
node: 'SubProcess_1',
Expand All @@ -124,7 +124,7 @@ const invalid = [
`)),
report: {
id: 'SubProcess_1',
message: 'A <bpmn:SubProcess> must be expanded.',
message: 'A <bpmn:SubProcess> must be expanded',
data: {
type: ERROR_TYPES.ELEMENT_COLLAPSED_NOT_ALLOWED,
node: 'SubProcess_1',
Expand All @@ -150,7 +150,7 @@ const invalid = [
`)),
report: {
id: 'SubProcess_1',
message: 'A <bpmn:AdHocSubProcess> must be expanded.',
message: 'A <bpmn:AdHocSubProcess> must be expanded',
data: {
type: ERROR_TYPES.ELEMENT_COLLAPSED_NOT_ALLOWED,
node: 'SubProcess_1',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
const RuleTester = require('bpmnlint/lib/testers/rule-tester');

const rule = require('../../rules/camunda-cloud/escalation-boundary-event-attached-to-ref');

const {
createDefinitions,
createModdle,
createProcess
} = require('../helper');

const { ERROR_TYPES } = require('../../rules/utils/element');

const valid = [
{
name: 'escalation boundary event (attached to call activity)',
moddleElement: createModdle(createProcess(`
<bpmn:callActivity id="CallActivity_1" />
<bpmn:boundaryEvent id="BoundaryEvent_1" attachedToRef="CallActivity_1">
<bpmn:escalationEventDefinition id="EscalationEventDefinition_1" />
</bpmn:boundaryEvent>
`))
},
{
name: 'escalation boundary event (attached to sub process)',
moddleElement: createModdle(createProcess(`
<bpmn:subProcess id="SubProcess_1" />
<bpmn:boundaryEvent id="BoundaryEvent_1" attachedToRef="SubProcess_1">
<bpmn:escalationEventDefinition id="EscalationEventDefinition_1" />
</bpmn:boundaryEvent>
`))
},
{
name: 'task',
moddleElement: createModdle(createProcess('<bpmn:task id="Task_1" />'))
},
{
name: 'escalation boundary event (attached to task) (non-executable process)',
config: { version: '8.2' },
moddleElement: createModdle(createDefinitions(`
<bpmn:process id="Process_1">
<bpmn:task id="Task_1" />
<bpmn:boundaryEvent id="BoundaryEvent_1" attachedToRef="Task_1">
<bpmn:escalationEventDefinition id="EscalationEventDefinition_1" />
</bpmn:boundaryEvent>
</bpmn:process>
`))
}
];

const invalid = [
{
name: 'escalation boundary event (attached to task)',
moddleElement: createModdle(createProcess(`
<bpmn:task id="Task_1" />
<bpmn:boundaryEvent id="BoundaryEvent_1" attachedToRef="Task_1">
<bpmn:escalationEventDefinition id="EscalationEventDefinition_1" />
</bpmn:boundaryEvent>
`)),
report: {
id: 'BoundaryEvent_1',
message: 'Element of type <bpmn:BoundaryEvent> with event definition of type <bpmn:EscalationEventDefinition> is not allowed to be attached to element of type <bpmn:Task>',
path: null,
data: {
type: ERROR_TYPES.ATTACHED_TO_REF_ELEMENT_TYPE_NOT_ALLOWED,
node: 'BoundaryEvent_1',
parentNode: null,
attachedToRef: 'Task_1'
}
}
}
];

RuleTester.verify('escalation-boundary-event-attached-to-ref', rule, {
valid,
invalid
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="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:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0n9flo1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.14.0-dev" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.2.0">
<bpmn:process id="Process_1" isExecutable="true">
<bpmn:task id="Task_1" />
<bpmn:boundaryEvent id="EscalationBoundaryEvent_1" attachedToRef="Task_1">
<bpmn:escalationEventDefinition id="EscalationEventDefinition_1n0kjrs" />
</bpmn:boundaryEvent>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="Activity_03iss7o_di" bpmnElement="Task_1">
<dc:Bounds x="160" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1i5x106_di" bpmnElement="EscalationBoundaryEvent_1">
<dc:Bounds x="242" y="142" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="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:zeebe="http://camunda.org/schema/zeebe/1.0" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0n9flo1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.14.0-dev" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.2.0">
<bpmn:process id="Process_1" isExecutable="true">
<bpmn:boundaryEvent id="EscalationBoundaryEvent_1" attachedToRef="CallActivity_1">
<bpmn:escalationEventDefinition id="EscalationEventDefinition_1n0kjrs" />
</bpmn:boundaryEvent>
<bpmn:callActivity id="CallActivity_1">
<bpmn:extensionElements>
<zeebe:calledElement processId="foo" propagateAllChildVariables="false" />
</bpmn:extensionElements>
</bpmn:callActivity>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="Activity_04f9rp4_di" bpmnElement="CallActivity_1">
<dc:Bounds x="160" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1i5x106_di" bpmnElement="EscalationBoundaryEvent_1">
<dc:Bounds x="242" y="142" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
const { expect } = require('chai');

const Linter = require('bpmnlint/lib/linter');

const NodeResolver = require('bpmnlint/lib/resolver/node-resolver');

const { readModdle } = require('../../helper');

const versions = [
'8.2',
'8.3'
];

describe('integration - escalation-boundary-event-attached-to-ref', function() {

versions.forEach(function(version) {

let linter;

beforeEach(function() {
linter = new Linter({
config: {
extends: `plugin:camunda-compat/camunda-cloud-${ version.replace('.', '-') }`
},
resolver: new NodeResolver()
});
});


describe(`Camunda Cloud ${ version }`, function() {

describe('no errors', function() {

it('should not have errors', async function() {

// given
const { root } = await readModdle('test/camunda-cloud/integration/escalation-boundary-event-attached-to-ref.bpmn');

// when
const reports = await linter.lint(root);

// then
expect(reports[ 'camunda-compat/escalation-boundary-event-attached-to-ref' ]).not.to.exist;
});

});


describe('errors', function() {

it('should have errors', async function() {

// given
const { root } = await readModdle('test/camunda-cloud/integration/escalation-boundary-event-attached-to-ref-errors.bpmn');

// when
const reports = await linter.lint(root);

// then
expect(reports[ 'camunda-compat/escalation-boundary-event-attached-to-ref' ]).to.exist;
});

});

});

});

});
3 changes: 3 additions & 0 deletions test/config/configs.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ describe('configs', function() {
'duplicate-task-headers': [ 'error', { version: '8.2' } ],
'element-type': [ 'error', { version: '8.2' } ],
'error-reference': [ 'error', { version: '8.2' } ],
'escalation-boundary-event-attached-to-ref': [ 'error', { version: '8.2' } ],
'escalation-reference': [ 'error', { version: '8.2' } ],
'event-based-gateway-target': [ 'error', { version: '8.2' } ],
'executable-process': [ 'error', { version: '8.2' } ],
Expand All @@ -184,6 +185,7 @@ describe('configs', function() {
'duplicate-task-headers': [ 'error', { version: '8.3' } ],
'element-type': [ 'error', { version: '8.3' } ],
'error-reference': [ 'error', { version: '8.3' } ],
'escalation-boundary-event-attached-to-ref': [ 'error', { version: '8.3' } ],
'escalation-reference': [ 'error', { version: '8.3' } ],
'event-based-gateway-target': [ 'error', { version: '8.3' } ],
'executable-process': [ 'error', { version: '8.3' } ],
Expand Down Expand Up @@ -218,6 +220,7 @@ describe('configs', function() {
'collapsed-subprocess': 'error',
'duplicate-task-headers': 'error',
'error-reference': 'error',
'escalation-boundary-event-attached-to-ref': 'error',
'escalation-reference': 'error',
'event-based-gateway-target': 'error',
'executable-process': 'error',
Expand Down

0 comments on commit 16ab601

Please sign in to comment.