From 6ea1f8dc064bf17a4194bafc1658bf8bc66850b9 Mon Sep 17 00:00:00 2001 From: Maciej Barelkowski Date: Tue, 27 Feb 2024 16:49:50 +0100 Subject: [PATCH] feat: handle missing form property for Zeebe User Task --- lib/compiled-config.js | 41 +++++++++-------- lib/utils/error-messages.js | 17 ++++++- lib/utils/properties-panel.js | 16 +++++-- test/spec/utils/error-messages.spec.js | 52 ++++++++++++++++++++++ test/spec/utils/properties-panel.spec.js | 56 ++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 23 deletions(-) diff --git a/lib/compiled-config.js b/lib/compiled-config.js index 8c8e1aa..38d36e1 100644 --- a/lib/compiled-config.js +++ b/lib/compiled-config.js @@ -54,6 +54,7 @@ const rules = { "camunda-compat/no-task-schedule": "error", "camunda-compat/no-template": "error", "camunda-compat/no-zeebe-properties": "error", + "camunda-compat/no-zeebe-user-task": "error", "camunda-compat/secrets": "warn", "camunda-compat/sequence-flow-condition": "error", "camunda-compat/signal-reference": "error", @@ -178,38 +179,42 @@ import rule_24 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-zeebe cache['bpmnlint-plugin-camunda-compat/no-zeebe-properties'] = rule_24; -import rule_25 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/secrets'; +import rule_25 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/no-zeebe-user-task'; -cache['bpmnlint-plugin-camunda-compat/secrets'] = rule_25; +cache['bpmnlint-plugin-camunda-compat/no-zeebe-user-task'] = rule_25; -import rule_26 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/sequence-flow-condition'; +import rule_26 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/secrets'; -cache['bpmnlint-plugin-camunda-compat/sequence-flow-condition'] = rule_26; +cache['bpmnlint-plugin-camunda-compat/secrets'] = rule_26; -import rule_27 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/signal-reference'; +import rule_27 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/sequence-flow-condition'; -cache['bpmnlint-plugin-camunda-compat/signal-reference'] = rule_27; +cache['bpmnlint-plugin-camunda-compat/sequence-flow-condition'] = rule_27; -import rule_28 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/start-event-form'; +import rule_28 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/signal-reference'; -cache['bpmnlint-plugin-camunda-compat/start-event-form'] = rule_28; +cache['bpmnlint-plugin-camunda-compat/signal-reference'] = rule_28; -import rule_29 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/subscription'; +import rule_29 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/start-event-form'; -cache['bpmnlint-plugin-camunda-compat/subscription'] = rule_29; +cache['bpmnlint-plugin-camunda-compat/start-event-form'] = rule_29; -import rule_30 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/task-schedule'; +import rule_30 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/subscription'; -cache['bpmnlint-plugin-camunda-compat/task-schedule'] = rule_30; +cache['bpmnlint-plugin-camunda-compat/subscription'] = rule_30; -import rule_31 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/timer'; +import rule_31 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/task-schedule'; -cache['bpmnlint-plugin-camunda-compat/timer'] = rule_31; +cache['bpmnlint-plugin-camunda-compat/task-schedule'] = rule_31; -import rule_32 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/user-task-definition'; +import rule_32 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/timer'; -cache['bpmnlint-plugin-camunda-compat/user-task-definition'] = rule_32; +cache['bpmnlint-plugin-camunda-compat/timer'] = rule_32; -import rule_33 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/user-task-form'; +import rule_33 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/user-task-definition'; -cache['bpmnlint-plugin-camunda-compat/user-task-form'] = rule_33; \ No newline at end of file +cache['bpmnlint-plugin-camunda-compat/user-task-definition'] = rule_33; + +import rule_34 from 'bpmnlint-plugin-camunda-compat/rules/camunda-cloud/user-task-form'; + +cache['bpmnlint-plugin-camunda-compat/user-task-form'] = rule_34; \ No newline at end of file diff --git a/lib/utils/error-messages.js b/lib/utils/error-messages.js index cbe5c43..1df6a2c 100644 --- a/lib/utils/error-messages.js +++ b/lib/utils/error-messages.js @@ -500,6 +500,15 @@ function getPropertyRequiredErrorMessage(report, executionPlatform, executionPla return `${ getIndefiniteArticle(typeString) } <${ typeString }> with
must have a defined `; } + // Zeebe User Task + if (is(node, 'zeebe:FormDefinition') && isZeebeUserTask(parentNode)) { + if (isEmptyString(node.get('externalReference'))) { + return `${ getIndefiniteArticle(typeString) } <${ typeString }> with must have a defined `; + } else if (isEmptyString(node.get('formId'))) { + return `${ getIndefiniteArticle(typeString) } <${ typeString }> with must have a defined `; + } + } + if (is(node, 'zeebe:FormDefinition') && isArray(requiredProperty) && requiredProperty.includes('formId') && isEmptyString(node.get('formId'))) { return `${ getIndefiniteArticle(typeString) } <${ typeString }> with must have a defined `; } @@ -693,4 +702,10 @@ function getLoopNotAllowedErrorMessage(report) { function isEmptyString(value) { return isString(value) && value.trim() === ''; -} \ No newline at end of file +} + +function isZeebeUserTask(node) { + return node.get('extensionElements').get('values').some(extensionElement => { + return is(extensionElement, 'zeebe:UserTask'); + }); +} diff --git a/lib/utils/properties-panel.js b/lib/utils/properties-panel.js index 13317c8..ee2dd7a 100644 --- a/lib/utils/properties-panel.js +++ b/lib/utils/properties-panel.js @@ -168,10 +168,14 @@ export function getEntryIds(report) { requiredProperty } = data; - if (isArray(requiredProperty) && requiredProperty.includes('formKey') && isEmptyString(node.get('formKey'))) { - return [ 'customFormKey' ]; - } else if (isArray(requiredProperty) && requiredProperty.includes('formId') && isEmptyString(node.get('formId'))) { - return [ 'formId' ]; + if (isArray(requiredProperty)) { + if (requiredProperty.includes('formKey') && isEmptyString(node.get('formKey'))) { + return [ 'customFormKey' ]; + } else if (requiredProperty.includes('formId') && isEmptyString(node.get('formId'))) { + return [ 'formId' ]; + } else if (requiredProperty.includes('externalReference') && isEmptyString(node.get('externalReference'))) { + return [ 'externalReference' ]; + } } } @@ -424,6 +428,10 @@ export function getErrorMessage(id, report) { } } + if (id === 'externalReference') { + return 'External reference must be defined.'; + } + if (id === 'formConfiguration') { return 'Form JSON configuration must be defined.'; } diff --git a/test/spec/utils/error-messages.spec.js b/test/spec/utils/error-messages.spec.js index 5d23acb..1b25f36 100644 --- a/test/spec/utils/error-messages.spec.js +++ b/test/spec/utils/error-messages.spec.js @@ -1243,6 +1243,32 @@ describe('utils/error-messages', function() { }); + it('should adjust (Zeebe User Task) (form ID) (Camunda 8.5 and newer)', async function() { + + // given + const node = createElement('bpmn:UserTask', { + extensionElements: createElement('bpmn:ExtensionElements', { + values: [ + createElement('zeebe:UserTask', {}), + createElement('zeebe:FormDefinition', { + formId: '' + }) + ] + }) + }); + + const { default: rule } = await import('bpmnlint-plugin-camunda-compat/rules/camunda-cloud/user-task-form'); + + const report = await getLintError(node, rule, { version: '8.5' }); + + // when + const errorMessage = getErrorMessage(report); + + // then + expect(errorMessage).to.equal('A with must have a defined '); + }); + + it('should adjust (body)', async function() { // given @@ -1281,6 +1307,32 @@ describe('utils/error-messages', function() { }); + it('should adjust (Zeebe User Task) (external reference) (Camunda 8.5 and newer)', async function() { + + // given + const node = createElement('bpmn:UserTask', { + extensionElements: createElement('bpmn:ExtensionElements', { + values: [ + createElement('zeebe:UserTask', {}), + createElement('zeebe:FormDefinition', { + externalReference: '' + }) + ] + }) + }); + + const { default: rule } = await import('bpmnlint-plugin-camunda-compat/rules/camunda-cloud/user-task-form'); + + const report = await getLintError(node, rule, { version: '8.5' }); + + // when + const errorMessage = getErrorMessage(report); + + // then + expect(errorMessage).to.equal('A with must have a defined '); + }); + + it('should adjust (condition expression)', async function() { // given diff --git a/test/spec/utils/properties-panel.spec.js b/test/spec/utils/properties-panel.spec.js index 75064f1..5e0a887 100644 --- a/test/spec/utils/properties-panel.spec.js +++ b/test/spec/utils/properties-panel.spec.js @@ -900,6 +900,62 @@ describe('utils/properties-panel', function() { }); + it('user-task-form (Zeebe User Task) - Form ID (Camunda 8.5 and newer)', async function() { + + // given + const node = createElement('bpmn:UserTask', { + extensionElements: createElement('bpmn:ExtensionElements', { + values: [ + createElement('zeebe:UserTask'), + createElement('zeebe:FormDefinition', { + formId: '' + }) + ] + }) + }); + + const { default: rule } = await import('bpmnlint-plugin-camunda-compat/rules/camunda-cloud/user-task-form'); + + const report = await getLintError(node, rule, { version: '8.5' }); + + // when + const entryIds = getEntryIds(report); + + // then + expect(entryIds).to.eql([ 'formId' ]); + + expectErrorMessage(entryIds[ 0 ], 'Form ID must be defined.', report); + }); + + + it('user-task-form (Zeebe User Task) - External reference (Camunda 8.5 and newer)', async function() { + + // given + const node = createElement('bpmn:UserTask', { + extensionElements: createElement('bpmn:ExtensionElements', { + values: [ + createElement('zeebe:UserTask'), + createElement('zeebe:FormDefinition', { + externalReference: '' + }) + ] + }) + }); + + const { default: rule } = await import('bpmnlint-plugin-camunda-compat/rules/camunda-cloud/user-task-form'); + + const report = await getLintError(node, rule, { version: '8.5' }); + + // when + const entryIds = getEntryIds(report); + + // then + expect(entryIds).to.eql([ 'externalReference' ]); + + expectErrorMessage(entryIds[ 0 ], 'External reference must be defined.', report); + }); + + it('user-task-form - Form JSON configuration', async function() { // given