Skip to content

Commit

Permalink
feat: add ad-hoc-sub-process-activity rule
Browse files Browse the repository at this point in the history
This rules ensures that an Ad-Hoc Sub-Process contains at least one activity.

Related to camunda/camunda-modeler#4811
  • Loading branch information
jarekdanielak committed Feb 17, 2025
1 parent 3e22027 commit 3b57a20
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 1 deletion.
4 changes: 3 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ const camundaCloud86Rules = withConfig({
}, { version: '8.6' });

const camundaCloud87Rules = withConfig({
...camundaCloud86Rules
...camundaCloud86Rules,
'ad-hoc-sub-process-activity': 'error',
}, { version: '8.7' });

const camundaCloud88Rules = withConfig({
Expand Down Expand Up @@ -132,6 +133,7 @@ const camundaPlatform723Rules = withConfig(camundaPlatform721Rules, {
});

const rules = {
'ad-hoc-sub-process-activity': './rules/camunda-cloud/ad-hoc-sub-process-activity',
'element-type': './rules/camunda-cloud/element-type',
'called-element': './rules/camunda-cloud/called-element',
'collapsed-subprocess': './rules/camunda-cloud/collapsed-subprocess',
Expand Down
34 changes: 34 additions & 0 deletions rules/camunda-cloud/ad-hoc-sub-process-activity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const { is, isAny } = require('bpmnlint-utils');

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

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

module.exports = skipInNonExecutableProcess(function() {
function check(node, reporter) {
if (!is(node, 'bpmn:AdHocSubProcess')) {
return;
}

// Ad-Hoc Sub-Process must contain at least one activity
if (node.get('flowElements').some(isActivity)) {
return;
}

reportErrors(node, reporter, {
message: 'Element of type <bpmn:AdHocSubProcess> must contain at least one activity',
data: {
node,
parentNode: null
}
});
}

return {
check
};
});

function isActivity(element) {
return isAny(element, [ 'bpmn:Task', 'bpmn:SubProcess' ]);
}
59 changes: 59 additions & 0 deletions test/camunda-cloud/ad-hoc-sub-process-activity.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const RuleTester = require('bpmnlint/lib/testers/rule-tester');

const rule = require('../../rules/camunda-cloud/ad-hoc-sub-process-activity');

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

const valid = [
{
name: 'ad hoc sub process (with task)',
moddleElement: createModdle(createProcess(`
<bpmn:adHocSubProcess id="Subprocess_1">
<bpmn:task id="Task_1" />
</bpmn:adHocSubProcess>
`))
}
];

const invalid = [
{
name: 'ad hoc sub process (empty)',
moddleElement: createModdle(createProcess(`
<bpmn:adHocSubProcess id="Subprocess_1">
</bpmn:adHocSubProcess>
`)),
report: {
id: 'Subprocess_1',
message: 'Element of type <bpmn:AdHocSubProcess> must contain at least one activity',
data: {
node: 'Subprocess_1',
parentNode: null
}
}
},
{
name: 'ad hoc sub process (no activity)',
moddleElement: createModdle(createProcess(`
<bpmn:adHocSubProcess id="Subprocess_1">
<bpmn:exclusiveGateway id="Gateway_1" />
<bpmn:intermediateThrowEvent id="Event_1" />
</bpmn:adHocSubProcess>
`)),
report: {
id: 'Subprocess_1',
message: 'Element of type <bpmn:AdHocSubProcess> must contain at least one activity',
data: {
node: 'Subprocess_1',
parentNode: null
}
}
}
];

RuleTester.verify('called-element', rule, {
valid,
invalid
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?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_00ka3lv" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.29.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.1.0">
<bpmn:process id="Process_0agkt49" isExecutable="true">
<bpmn:adHocSubProcess id="Subprocess_1" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0agkt49">
<bpmndi:BPMNShape id="Activity_0djbhry_di" bpmnElement="Subprocess_1" isExpanded="true">
<dc:Bounds x="190" y="80" width="350" height="200" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
18 changes: 18 additions & 0 deletions test/camunda-cloud/integration/ad-hoc-sub-process-activity.bpmn
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?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_00ka3lv" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.29.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.1.0">
<bpmn:process id="Process_0agkt49" isExecutable="true">
<bpmn:adHocSubProcess id="Subprocess_1">
<bpmn:task id="Task_1" />
</bpmn:adHocSubProcess>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0agkt49">
<bpmndi:BPMNShape id="Activity_0djbhry_di" bpmnElement="Subprocess_1" isExpanded="true">
<dc:Bounds x="190" y="80" width="350" height="200" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0b17sv2_di" bpmnElement="Task_1">
<dc:Bounds x="310" y="130" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
68 changes: 68 additions & 0 deletions test/camunda-cloud/integration/ad-hoc-sub-process-activity.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
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.7',
'8.8',
];

describe('integration - ad-hoc-sub-process-activity', function() {

let linter;

versions.forEach(function(version) {

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/ad-hoc-sub-process-activity.bpmn');

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

// then
expect(reports[ 'camunda-compat/ad-hoc-sub-process-activity' ]).not.to.exist;
});

});


describe('errors', function() {

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

// given
const { root } = await readModdle('test/camunda-cloud/integration/ad-hoc-sub-process-activity-errors.bpmn');

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

// then
expect(reports[ 'camunda-compat/ad-hoc-sub-process-activity' ]).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 @@ -401,6 +401,7 @@ describe('configs', function() {


it('camunda-cloud-8-7', expectRules(configs, 'camunda-cloud-8-7', {
'ad-hoc-sub-process-activity': [ 'error', { version: '8.7' } ],
'called-element': [ 'error', { version: '8.7' } ],
'connector-properties': [ 'warn', { version: '8.7' } ],
'duplicate-execution-listeners': [ 'error', { version: '8.7' } ],
Expand Down Expand Up @@ -438,6 +439,7 @@ describe('configs', function() {


it('camunda-cloud-8-8', expectRules(configs, 'camunda-cloud-8-8', {
'ad-hoc-sub-process-activity': [ 'error', { version: '8.8' } ],
'called-element': [ 'error', { version: '8.8' } ],
'connector-properties': [ 'warn', { version: '8.8' } ],
'duplicate-execution-listeners': [ 'error', { version: '8.8' } ],
Expand Down Expand Up @@ -499,6 +501,7 @@ describe('configs', function() {


it('all', expectRules(configs, 'all', {
'ad-hoc-sub-process-activity': 'error',
'element-type': 'error',
'called-element': 'error',
'collapsed-subprocess': 'error',
Expand Down

0 comments on commit 3b57a20

Please # to comment.