Skip to content

Commit

Permalink
feat: add task-schedule and no-task-schedule rules
Browse files Browse the repository at this point in the history
Closes #84
  • Loading branch information
philippfromme committed Mar 15, 2023
1 parent 88617aa commit eea90f0
Show file tree
Hide file tree
Showing 13 changed files with 477 additions and 9 deletions.
9 changes: 7 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const camundaCloud10Rules = withConfig({
'message-reference': 'error',
'no-candidate-users': 'error',
'no-expression': 'error',
'no-task-schedule': 'error',
'no-template': 'error',
'no-zeebe-properties': 'error',
'sequence-flow-condition': 'error',
Expand All @@ -37,8 +38,12 @@ const camundaCloud81Rules = withConfig({
}, { version: '8.1' });

const camundaCloud82Rules = withConfig({
...omit(camundaCloud81Rules, 'no-candidate-users'),
'escalation-reference': 'error'
...omit(camundaCloud81Rules, [
'no-candidate-users',
'no-task-schedule'
]),
'escalation-reference': 'error',
'task-schedule': 'error'
}, { version: '8.2' });

const camundaPlatform719Rules = withConfig({
Expand Down
19 changes: 19 additions & 0 deletions rules/no-task-schedule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { hasNoExtensionElement } = require('./utils/element');

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

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

module.exports = skipInNonExecutableProcess(function() {
function check(node, reporter) {
const errors = hasNoExtensionElement(node, 'zeebe:TaskSchedule', node, '8.2');

if (errors && errors.length) {
reportErrors(node, reporter, errors);
}
}

return {
check
};
});
68 changes: 68 additions & 0 deletions rules/task-schedule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const { is } = require('bpmnlint-utils');

const { isDefined } = require('min-dash');

const {
findExtensionElement,
hasExpression
} = require('./utils/element');

const { validateDate: validateISO8601Date } = require('./utils/iso8601');

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

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

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

const taskSchedule = findExtensionElement(node, 'zeebe:TaskSchedule');

if (!taskSchedule) {
return;
}

const dueDate = taskSchedule.get('dueDate');

let errors = [];

if (isDefined(dueDate)) {
errors = [
...errors,
...hasExpression(taskSchedule, 'dueDate', {
allowed: date => isValidDate(date)
}, node)
];
}

const followUpDate = taskSchedule.get('followUpDate');

if (isDefined(followUpDate)) {
errors = [
...errors,
...hasExpression(taskSchedule, 'followUpDate', {
allowed: date => isValidDate(date)
}, node)
];
}

if (errors.length) {
reportErrors(node, reporter, errors);
}
}

return {
check
};
});

function isValidDate(value) {
return isExpression(value) || validateISO8601Date(value);
}

function isExpression(value) {
return value.startsWith('=');
}
18 changes: 11 additions & 7 deletions rules/utils/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,15 @@ module.exports.hasExpression = function(node, propertyName, check, parentNode =
throw new Error('Expression not found');
}

const body = expression.get('body');
let propertyValue = expression;

if (is(expression, 'bpmn:Expression')) {
propertyValue = expression.get('body');
}

const path = getPath(node, parentNode);

if (!body) {
if (!propertyValue) {
if (check.required !== false) {
return [
{
Expand All @@ -377,7 +381,7 @@ module.exports.hasExpression = function(node, propertyName, check, parentNode =
: null,
data: {
type: ERROR_TYPES.EXPRESSION_REQUIRED,
node: expression,
node: is(expression, 'bpmn:Expression') ? expression : node,
parentNode,
property: propertyName
}
Expand All @@ -388,7 +392,7 @@ module.exports.hasExpression = function(node, propertyName, check, parentNode =
return [];
}

const allowed = check.allowed(body);
const allowed = check.allowed(propertyValue);

if (allowed !== true) {
let allowedVersion = null;
Expand All @@ -400,14 +404,14 @@ module.exports.hasExpression = function(node, propertyName, check, parentNode =
return [
{
message: allowedVersion
? `Expression value of <${ body }> only allowed by Camunda Platform ${ allowedVersion }`
: `Expression value of <${ body }> not allowed`,
? `Expression value of <${ propertyValue }> only allowed by Camunda Platform ${ allowedVersion }`
: `Expression value of <${ propertyValue }> not allowed`,
path: path
? [ ...path, propertyName ]
: null,
data: addAllowedVersion({
type: ERROR_TYPES.EXPRESSION_VALUE_NOT_ALLOWED,
node: expression,
node: is(expression, 'bpmn:Expression') ? expression : node,
parentNode,
property: propertyName
}, allowedVersion)
Expand Down
17 changes: 17 additions & 0 deletions test/camunda-cloud/integration/no-task-schedule-errors.bpmn
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?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_0q117j9" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.8.0-rc.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.1.0">
<bpmn:process id="Process_1" isExecutable="true">
<bpmn:userTask id="UserTask_1">
<bpmn:extensionElements>
<zeebe:TaskSchedule dueDate="2022-09-21T00:00:00Z" followUpDate="2022-09-21T00:00:00Z" />
</bpmn:extensionElements>
</bpmn:userTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="Activity_1hsskmv_di" bpmnElement="UserTask_1">
<dc:Bounds x="160" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
13 changes: 13 additions & 0 deletions test/camunda-cloud/integration/no-task-schedule.bpmn
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_0q117j9" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.8.0-rc.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.1.0">
<bpmn:process id="Process_1" isExecutable="true">
<bpmn:userTask id="UserTask_1" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="Activity_1hsskmv_di" bpmnElement="UserTask_1">
<dc:Bounds x="160" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
73 changes: 73 additions & 0 deletions test/camunda-cloud/integration/no-task-schedule.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const { expect } = require('chai');

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

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

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

const versions = [
'1.0',
'1.1',
'1.2',
'1.3',
'8.0',
'8.1'
];

describe('integration - no-task-schedule', 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/no-task-schedule.bpmn');

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

// then
expect(reports[ 'camunda-compat/no-task-schedule' ]).not.to.exist;
});

});


describe('errors', function() {

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

// given
const { root } = await readModdle('test/camunda-cloud/integration/no-task-schedule-errors.bpmn');

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

// then
expect(reports[ 'camunda-compat/no-task-schedule' ]).to.exist;
});

});

});

});

});
17 changes: 17 additions & 0 deletions test/camunda-cloud/integration/task-schedule-errors.bpmn
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?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_0q117j9" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.8.0-rc.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.1.0">
<bpmn:process id="Process_1" isExecutable="true">
<bpmn:userTask id="UserTask_1">
<bpmn:extensionElements>
<zeebe:TaskSchedule dueDate="invalid" followUpDate="invalid" />
</bpmn:extensionElements>
</bpmn:userTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="Activity_1hsskmv_di" bpmnElement="UserTask_1">
<dc:Bounds x="160" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
17 changes: 17 additions & 0 deletions test/camunda-cloud/integration/task-schedule.bpmn
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?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_0q117j9" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.8.0-rc.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.1.0">
<bpmn:process id="Process_1" isExecutable="true">
<bpmn:userTask id="UserTask_1">
<bpmn:extensionElements>
<zeebe:TaskSchedule dueDate="2022-09-21T00:00:00Z" followUpDate="2022-09-21T00:00:00Z" />
</bpmn:extensionElements>
</bpmn:userTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="Activity_1hsskmv_di" bpmnElement="UserTask_1">
<dc:Bounds x="160" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
68 changes: 68 additions & 0 deletions test/camunda-cloud/integration/task-schedule.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.2'
];

describe('integration - task schedule', 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/task-schedule.bpmn');

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

// then
expect(reports[ 'camunda-compat/task-schedule' ]).not.to.exist;
});

});


describe('errors', function() {

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

// given
const { root } = await readModdle('test/camunda-cloud/integration/task-schedule-errors.bpmn');

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

// then
expect(reports[ 'camunda-compat/task-schedule' ]).to.exist;
});

});

});

});

});
Loading

0 comments on commit eea90f0

Please sign in to comment.