Skip to content

Commit

Permalink
feat: add task-schedule rule
Browse files Browse the repository at this point in the history
  • Loading branch information
philippfromme committed Mar 15, 2023
1 parent 88617aa commit 9e6cd15
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 8 deletions.
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ const camundaCloud81Rules = withConfig({

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

const camundaPlatform719Rules = withConfig({
Expand Down
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
93 changes: 93 additions & 0 deletions test/camunda-cloud/task-schedule.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
const RuleTester = require('bpmnlint/lib/testers/rule-tester');

const rule = require('../../rules/task-schedule');

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

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

const valid = [
{
name: 'user task (due date)',
moddleElement: createModdle(createProcess(`
<bpmn:userTask id="UserTask_1">
<bpmn:extensionElements>
<zeebe:TaskSchedule dueDate="2022-09-21T00:00:00Z" />
</bpmn:extensionElements>
</bpmn:userTask>
`))
},
{
name: 'user task (follow-up date)',
moddleElement: createModdle(createProcess(`
<bpmn:userTask id="UserTask_1">
<bpmn:extensionElements>
<zeebe:TaskSchedule followUpDate="2022-09-21T00:00:00Z" />
</bpmn:extensionElements>
</bpmn:userTask>
`))
}
];

const invalid = [
{
name: 'user task (invalid due date)',
moddleElement: createModdle(createProcess(`
<bpmn:userTask id="UserTask_1">
<bpmn:extensionElements>
<zeebe:TaskSchedule dueDate="invalid" />
</bpmn:extensionElements>
</bpmn:userTask>
`)),
report: {
id: 'UserTask_1',
message: 'Expression value of <invalid> not allowed',
path: [
'extensionElements',
'values',
0,
'dueDate'
],
data: {
type: ERROR_TYPES.EXPRESSION_VALUE_NOT_ALLOWED,
node: 'zeebe:TaskSchedule',
parentNode: 'UserTask_1',
property: 'dueDate'
}
}
},
{
name: 'user task (invalid follow-up date)',
moddleElement: createModdle(createProcess(`
<bpmn:userTask id="UserTask_1">
<bpmn:extensionElements>
<zeebe:TaskSchedule followUpDate="invalid" />
</bpmn:extensionElements>
</bpmn:userTask>
`)),
report: {
id: 'UserTask_1',
message: 'Expression value of <invalid> not allowed',
path: [
'extensionElements',
'values',
0,
'followUpDate'
],
data: {
type: ERROR_TYPES.EXPRESSION_VALUE_NOT_ALLOWED,
node: 'zeebe:TaskSchedule',
parentNode: 'UserTask_1',
property: 'followUpDate'
}
}
}
];

RuleTester.verify('task-schedule', rule, {
valid,
invalid
});

0 comments on commit 9e6cd15

Please sign in to comment.