From 0707788ddef8fc889c98b3f9df80d01f7e5a3717 Mon Sep 17 00:00:00 2001 From: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:24:51 +0200 Subject: [PATCH 1/6] START feat: detect "text annotations" defined in "collaboration" node Also detect associations Fix some documentation --- docs/contributors/bpmn-support-how-to.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contributors/bpmn-support-how-to.md b/docs/contributors/bpmn-support-how-to.md index e00bf367c7..2a53d07059 100644 --- a/docs/contributors/bpmn-support-how-to.md +++ b/docs/contributors/bpmn-support-how-to.md @@ -231,7 +231,7 @@ Here are some tips to generate the SVG to be included in the documentation. ```SVG - + ``` - Open the file in a SVG Editor (Inkscape for instance). @@ -244,4 +244,4 @@ Here are some tips to generate the SVG to be included in the documentation. ![SVG icon fits the viewBox](images/inkscape-result2.png) - Save -- Eventually clean the SVG with tools like SVGGO: https://jakearchibald.github.io/svgomg/ +- Eventually clean the SVG with tools like `SVGGO`: https://jakearchibald.github.io/svgomg/ From f9378740c5070a6b0cb1f4cfd0881b6118cd6ba7 Mon Sep 17 00:00:00 2001 From: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com> Date: Mon, 21 Oct 2024 19:26:52 +0200 Subject: [PATCH 2/6] feat: detect association in "collaboration" WIP add test to reproduce the current behavior - improve types test association: comment unused code association test: refactor to introduce utility function test association: add tests to reproduce the current behaviour association: add CollaborationConverter.ts buildAssociationFlows association: implem test association: various refactorings extract function association: add TODO association tests: clean commented code association tests: check both collaboration and process association: simplify tests bpmn-model-expect.ts: update comment association: ProcessConverter.ts - remove extra method --- .../json/converter/CollaborationConverter.ts | 11 +- .../parser/json/converter/ProcessConverter.ts | 17 +- src/component/parser/json/converter/utils.ts | 16 +- .../json/BpmnJsonParser.association.test.ts | 222 +++++++++++++++--- test/unit/helpers/bpmn-model-expect.ts | 5 + 5 files changed, 221 insertions(+), 50 deletions(-) diff --git a/src/component/parser/json/converter/CollaborationConverter.ts b/src/component/parser/json/converter/CollaborationConverter.ts index 37e695fa8d..b9802aab69 100644 --- a/src/component/parser/json/converter/CollaborationConverter.ts +++ b/src/component/parser/json/converter/CollaborationConverter.ts @@ -26,7 +26,7 @@ import { MessageFlow } from '../../../../model/bpmn/internal/edge/flows'; import ShapeBpmnElement from '../../../../model/bpmn/internal/shape/ShapeBpmnElement'; import { ensureIsArray } from '../../../helpers/array-utils'; -import { buildShapeBpmnGroup } from './utils'; +import { convertAndRegisterAssociationFlows, buildShapeBpmnGroup } from './utils'; /** * @internal @@ -44,6 +44,7 @@ export default class CollaborationConverter { private parseCollaboration(collaboration: TCollaboration): void { this.buildParticipant(collaboration.participant); this.buildMessageFlows(collaboration.messageFlow); + convertAndRegisterAssociationFlows(this.convertedElements, collaboration.association); this.buildGroups(collaboration.group); } @@ -63,4 +64,12 @@ export default class CollaborationConverter { shapeBpmnElement && this.convertedElements.registerFlowNode(shapeBpmnElement); } } + + // TODO duplicated with ProcessConverter --> extract like this is done in buildShapeBpmnGroup + // private buildAssociationFlows(bpmnElements: TAssociation[] | TAssociation): void { + // for (const association of ensureIsArray(bpmnElements)) { + // const direction = association.associationDirection as unknown as AssociationDirectionKind; + // this.convertedElements.registerAssociationFlow(new AssociationFlow(association.id, undefined, association.sourceRef, association.targetRef, direction)); + // } + // } } diff --git a/src/component/parser/json/converter/ProcessConverter.ts b/src/component/parser/json/converter/ProcessConverter.ts index 1df0d52620..5e5295a65a 100644 --- a/src/component/parser/json/converter/ProcessConverter.ts +++ b/src/component/parser/json/converter/ProcessConverter.ts @@ -15,8 +15,8 @@ limitations under the License. */ import type { ConvertedElements, RegisteredEventDefinition } from './utils'; -import type { AssociationDirectionKind, BpmnEventKind } from '../../../../model/bpmn/internal'; -import type { TAssociation, TGroup, TTextAnnotation } from '../../../../model/bpmn/json/baseElement/artifact'; +import type { BpmnEventKind } from '../../../../model/bpmn/internal'; +import type { TGroup, TTextAnnotation } from '../../../../model/bpmn/json/baseElement/artifact'; import type { TLane, TLaneSet } from '../../../../model/bpmn/json/baseElement/baseElement'; import type { TFlowNode, TSequenceFlow } from '../../../../model/bpmn/json/baseElement/flowElement'; import type { TActivity, TCallActivity, TSubProcess } from '../../../../model/bpmn/json/baseElement/flowNode/activity/activity'; @@ -36,7 +36,7 @@ import { ShapeBpmnSubProcessKind, ShapeUtil, } from '../../../../model/bpmn/internal'; -import { AssociationFlow, SequenceFlow } from '../../../../model/bpmn/internal/edge/flows'; +import { SequenceFlow } from '../../../../model/bpmn/internal/edge/flows'; import ShapeBpmnElement, { ShapeBpmnIntermediateThrowEvent, ShapeBpmnIntermediateCatchEvent, @@ -52,7 +52,7 @@ import { eventDefinitionKinds } from '../../../../model/bpmn/internal/shape/util import { ensureIsArray } from '../../../helpers/array-utils'; import { BoundaryEventNotAttachedToActivityWarning, LaneUnknownFlowNodeReferenceWarning } from '../warnings'; -import { buildShapeBpmnGroup } from './utils'; +import { convertAndRegisterAssociationFlows, buildShapeBpmnGroup } from './utils'; type FlowNode = TFlowNode | TActivity | TReceiveTask | TEventBasedGateway | TTextAnnotation; @@ -182,7 +182,7 @@ export default class ProcessConverter { // flows this.buildSequenceFlows(process.sequenceFlow); - this.buildAssociationFlows(process.association); + convertAndRegisterAssociationFlows(this.convertedElements, process.association); } private buildFlowNodeBpmnElements( @@ -395,13 +395,6 @@ export default class ProcessConverter { } } - private buildAssociationFlows(bpmnElements: TAssociation[] | TAssociation): void { - for (const association of ensureIsArray(bpmnElements)) { - const direction = association.associationDirection as unknown as AssociationDirectionKind; - this.convertedElements.registerAssociationFlow(new AssociationFlow(association.id, undefined, association.sourceRef, association.targetRef, direction)); - } - } - private getSequenceFlowKind(sequenceFlow: TSequenceFlow): SequenceFlowKind { if (this.defaultSequenceFlowIds.includes(sequenceFlow.id)) { return SequenceFlowKind.DEFAULT; diff --git a/src/component/parser/json/converter/utils.ts b/src/component/parser/json/converter/utils.ts index c11245b83f..7d02acd3e0 100644 --- a/src/component/parser/json/converter/utils.ts +++ b/src/component/parser/json/converter/utils.ts @@ -14,14 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type { GlobalTaskKind, ShapeBpmnEventDefinitionKind } from '../../../../model/bpmn/internal'; -import type { Flow, AssociationFlow, MessageFlow, SequenceFlow } from '../../../../model/bpmn/internal/edge/flows'; -import type { TGroup } from '../../../../model/bpmn/json/baseElement/artifact'; +import type { AssociationDirectionKind, GlobalTaskKind, ShapeBpmnEventDefinitionKind } from '../../../../model/bpmn/internal'; +import type { Flow, MessageFlow, SequenceFlow } from '../../../../model/bpmn/internal/edge/flows'; +import type { TAssociation, TGroup } from '../../../../model/bpmn/json/baseElement/artifact'; import type { TEventDefinition, TLinkEventDefinition } from '../../../../model/bpmn/json/baseElement/rootElement/eventDefinition'; import type { ParsingMessageCollector } from '../../parsing-messages'; import { ShapeBpmnElementKind } from '../../../../model/bpmn/internal'; +import { AssociationFlow } from '../../../../model/bpmn/internal/edge/flows'; import ShapeBpmnElement from '../../../../model/bpmn/internal/shape/ShapeBpmnElement'; +import { ensureIsArray } from '../../../helpers/array-utils'; import { GroupUnknownCategoryValueWarning } from '../warnings'; export type RegisteredEventDefinition = (Pick & Pick) & { @@ -133,3 +135,11 @@ export const buildShapeBpmnGroup = ( interface CategoryValueData { value?: string; } + +// TODO review the name of the function: registerAssociationFlows? +export const convertAndRegisterAssociationFlows = (convertedElements: ConvertedElements, bpmnElements: TAssociation[] | TAssociation): void => { + for (const association of ensureIsArray(bpmnElements)) { + const direction = association.associationDirection as unknown as AssociationDirectionKind; + convertedElements.registerAssociationFlow(new AssociationFlow(association.id, undefined, association.sourceRef, association.targetRef, direction)); + } +}; diff --git a/test/unit/component/parser/json/BpmnJsonParser.association.test.ts b/test/unit/component/parser/json/BpmnJsonParser.association.test.ts index b4d5c359fb..337960afb1 100644 --- a/test/unit/component/parser/json/BpmnJsonParser.association.test.ts +++ b/test/unit/component/parser/json/BpmnJsonParser.association.test.ts @@ -16,14 +16,42 @@ limitations under the License. import type { BuildProcessParameter } from '../../../helpers/JsonBuilder'; import type { BpmnJsonModel } from '@lib/model/bpmn/json/bpmn20'; +import type { BPMNEdge } from '@lib/model/bpmn/json/bpmndi'; +import type { Point } from '@lib/model/bpmn/json/dc'; -import { verifyEdge } from '../../../helpers/bpmn-model-expect'; +import { type ExpectedEdge, verifyEdge } from '../../../helpers/bpmn-model-expect'; import { buildDefinitions } from '../../../helpers/JsonBuilder'; import { parseJsonAndExpectOnlyEdges } from '../../../helpers/JsonTestUtils'; +import { FlowKind } from '@lib/model/bpmn/internal'; import { Waypoint } from '@lib/model/bpmn/internal/edge/edge'; -describe('parse bpmn as json for association', () => { +type ExpectedAssociationParameter = Pick & { waypoints?: Waypoint[] }; + +function expectedAssociation(base: ExpectedAssociationParameter): ExpectedEdge { + return { + edgeId: `edge_${base.bpmnElementId}`, // generated in JsonBuilder + bpmnElementId: base.bpmnElementId, + bpmnElementName: base.bpmnElementName, + bpmnElementKind: FlowKind.ASSOCIATION_FLOW, + bpmnElementSourceRefId: base.bpmnElementSourceRefId, + bpmnElementTargetRefId: base.bpmnElementTargetRefId, + waypoints: base.waypoints ?? [new Waypoint(45, 78), new Waypoint(51, 78)], // hardcoded in JsonBuilder + }; +} + +function buildBPMNEdge(id: string, waypoints?: Point[]): BPMNEdge { + return { + id: `edge_${id}`, + bpmnElement: id, + waypoint: waypoints ?? [ + { x: 45, y: 78 }, + { x: 51, y: 78 }, + ], + }; +} + +describe('parse bpmn as json for associations defined in process', () => { const processJsonAsObjectWithAssociationJsonAsObject = { association: { id: 'association_id_0', @@ -42,13 +70,14 @@ describe('parse bpmn as json for association', () => { const model = parseJsonAndExpectOnlyEdges(json, 1); - verifyEdge(model.edges[0], { - edgeId: 'edge_association_id_0', - bpmnElementId: 'association_id_0', - bpmnElementSourceRefId: 'Activity_01', - bpmnElementTargetRefId: 'Annotation_01', - waypoints: [new Waypoint(45, 78), new Waypoint(51, 78)], - }); + verifyEdge( + model.edges[0], + expectedAssociation({ + bpmnElementId: 'association_id_0', + bpmnElementSourceRefId: 'Activity_01', + bpmnElementTargetRefId: 'Annotation_01', + }), + ); }, ); @@ -72,21 +101,23 @@ describe('parse bpmn as json for association', () => { const model = parseJsonAndExpectOnlyEdges(json, 2); - verifyEdge(model.edges[0], { - edgeId: 'edge_association_id_0', - bpmnElementId: 'association_id_0', - bpmnElementSourceRefId: 'Activity_01', - bpmnElementTargetRefId: 'Annotation_01', - waypoints: [new Waypoint(45, 78), new Waypoint(51, 78)], - }); + verifyEdge( + model.edges[0], + expectedAssociation({ + bpmnElementId: 'association_id_0', + bpmnElementSourceRefId: 'Activity_01', + bpmnElementTargetRefId: 'Annotation_01', + }), + ); - verifyEdge(model.edges[1], { - edgeId: 'edge_association_id_1', - bpmnElementId: 'association_id_1', - bpmnElementSourceRefId: 'Activity_02', - bpmnElementTargetRefId: 'Annotation_02', - waypoints: [new Waypoint(45, 78), new Waypoint(51, 78)], - }); + verifyEdge( + model.edges[1], + expectedAssociation({ + bpmnElementId: 'association_id_1', + bpmnElementSourceRefId: 'Activity_02', + bpmnElementTargetRefId: 'Annotation_02', + }), + ); }); it('should convert as Edge, when BPMNDiagram is an array', () => { @@ -98,11 +129,7 @@ describe('parse bpmn as json for association', () => { { name: 'process 0', BPMNPlane: { - BPMNEdge: { - id: 'edge_association_id_0', - bpmnElement: 'association_id_0', - waypoint: [{ x: 362, y: 232 }], - }, + BPMNEdge: buildBPMNEdge('association_id_0', [{ x: 362, y: 232 }]), }, }, ], @@ -111,12 +138,139 @@ describe('parse bpmn as json for association', () => { const model = parseJsonAndExpectOnlyEdges(json, 1); - verifyEdge(model.edges[0], { - edgeId: `edge_association_id_0`, - bpmnElementId: `association_id_0`, + verifyEdge( + model.edges[0], + expectedAssociation({ + bpmnElementId: `association_id_0`, + bpmnElementSourceRefId: 'Activity_01', + bpmnElementTargetRefId: 'Annotation_01', + waypoints: [new Waypoint(362, 232)], + }), + ); + }); +}); + +describe('parse bpmn as json for associations defined in collaboration', () => { + it(`should convert as Edge a single association (as object)`, () => { + const json: BpmnJsonModel = { + definitions: { + targetNamespace: '', + collaboration: { + association: { + id: 'association_id_0', + sourceRef: 'Activity_01', + targetRef: 'Annotation_01', + }, + }, + BPMNDiagram: { + BPMNPlane: { + BPMNEdge: buildBPMNEdge('association_id_0', [{ x: 362, y: 232 }]), + }, + }, + }, + }; + const model = parseJsonAndExpectOnlyEdges(json, 1); + + verifyEdge( + model.edges[0], + expectedAssociation({ + bpmnElementId: `association_id_0`, + bpmnElementSourceRefId: 'Activity_01', + bpmnElementTargetRefId: 'Annotation_01', + waypoints: [new Waypoint(362, 232)], + }), + ); + }); + + it(`should convert as Edge several associations (as array)`, () => { + const json: BpmnJsonModel = { + definitions: { + targetNamespace: '', + collaboration: { + association: [ + { + id: 'association_id_0', + sourceRef: 'Activity_01', + targetRef: 'Annotation_01', + }, + { + id: 'association_id_1', + sourceRef: 'Activity_02', + targetRef: 'Annotation_02', + }, + ], + }, + BPMNDiagram: { + BPMNPlane: { + BPMNEdge: [buildBPMNEdge('association_id_0'), buildBPMNEdge('association_id_1')], + }, + }, + }, + }; + + const model = parseJsonAndExpectOnlyEdges(json, 2); + + verifyEdge( + model.edges[0], + expectedAssociation({ + bpmnElementId: 'association_id_0', + bpmnElementSourceRefId: 'Activity_01', + bpmnElementTargetRefId: 'Annotation_01', + }), + ); + + verifyEdge( + model.edges[1], + expectedAssociation({ + bpmnElementId: 'association_id_1', + bpmnElementSourceRefId: 'Activity_02', + bpmnElementTargetRefId: 'Annotation_02', + }), + ); + }); +}); + +it(`parse bpmn as json for associations defined in both process and collaboration`, () => { + const json: BpmnJsonModel = { + definitions: { + targetNamespace: '', + collaboration: { + association: { + id: 'association_id_1', + sourceRef: 'Activity_01', + targetRef: 'Annotation_01', + }, + }, + process: { + association: { + id: 'association_id_2', + sourceRef: 'Activity_02', + targetRef: 'Annotation_02', + }, + }, + BPMNDiagram: { + BPMNPlane: { + BPMNEdge: [buildBPMNEdge('association_id_1'), buildBPMNEdge('association_id_2')], + }, + }, + }, + }; + const model = parseJsonAndExpectOnlyEdges(json, 2); + + verifyEdge( + model.edges[0], + expectedAssociation({ + bpmnElementId: `association_id_1`, bpmnElementSourceRefId: 'Activity_01', bpmnElementTargetRefId: 'Annotation_01', - waypoints: [new Waypoint(362, 232)], - }); - }); + }), + ); + verifyEdge( + model.edges[1], + expectedAssociation({ + bpmnElementId: `association_id_2`, + bpmnElementSourceRefId: 'Activity_02', + bpmnElementTargetRefId: 'Annotation_02', + }), + ); }); diff --git a/test/unit/helpers/bpmn-model-expect.ts b/test/unit/helpers/bpmn-model-expect.ts index 7ffc35ae81..c021d37d67 100644 --- a/test/unit/helpers/bpmn-model-expect.ts +++ b/test/unit/helpers/bpmn-model-expect.ts @@ -68,6 +68,7 @@ export interface ExpectedEdge { edgeId: string; bpmnElementId: string; bpmnElementName?: string; + bpmnElementKind?: FlowKind; // temporarily optional until all tests are updated bpmnElementSourceRefId: string; bpmnElementTargetRefId: string; waypoints: Waypoint[]; @@ -192,6 +193,10 @@ export const verifyEdge = (edge: Edge, expectedValue: ExpectedEdge | ExpectedSeq const bpmnElement = edge.bpmnElement; expect(bpmnElement.id).toEqual(expectedValue.bpmnElementId); expect(bpmnElement.name).toEqual(expectedValue.bpmnElementName); + // only check when the value is defined, but once all tests are updated, it should be mandatory + if (expectedValue.bpmnElementKind) { + expect(edge.bpmnElement.kind).toEqual(expectedValue.bpmnElementKind); + } expect(bpmnElement.sourceReferenceId).toEqual(expectedValue.bpmnElementSourceRefId); expect(bpmnElement.targetReferenceId).toEqual(expectedValue.bpmnElementTargetRefId); From 2e8a94e4d58bd8de41ad050db88138f476350da1 Mon Sep 17 00:00:00 2001 From: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com> Date: Tue, 22 Oct 2024 19:07:35 +0200 Subject: [PATCH 3/6] feat: detect text annotation in collaboration WIP refactor test text annotation WIP refactor test text annotation: avoid bounds duplication WIP refactor test text annotation: avoid bounds duplication - improve signature of util function WIP refactor test text annotation: avoid bounds duplication - more usage WIP refactor test text annotation: avoid bounds duplication - rename util function test text annotation: single in collaboration text annotation: 1st implementation test text annotation: arrays in collaboration test text annotation: refactor test text annotation: refactor (not pass shapeId to utility function) text annotation: fix test title text annotation: remove commented code + add TODO text annotation tests: check incomings and outgoings text annotation tests: check incomings and outgoings - refactor text annotation: CollaborationConverter.ts - remove commented code text annotation: refactor CollaborationConverter.ts --- .../json/converter/CollaborationConverter.ts | 17 +- .../parser/json/converter/ProcessConverter.ts | 1 + .../BpmnJsonParser.text.annotation.test.ts | 221 +++++++++++++++--- 3 files changed, 193 insertions(+), 46 deletions(-) diff --git a/src/component/parser/json/converter/CollaborationConverter.ts b/src/component/parser/json/converter/CollaborationConverter.ts index b9802aab69..1938d3269e 100644 --- a/src/component/parser/json/converter/CollaborationConverter.ts +++ b/src/component/parser/json/converter/CollaborationConverter.ts @@ -15,7 +15,7 @@ limitations under the License. */ import type { ConvertedElements } from './utils'; -import type { TGroup } from '../../../../model/bpmn/json/baseElement/artifact'; +import type { TGroup, TTextAnnotation } from '../../../../model/bpmn/json/baseElement/artifact'; import type { TMessageFlow } from '../../../../model/bpmn/json/baseElement/baseElement'; import type { TParticipant } from '../../../../model/bpmn/json/baseElement/participant'; import type { TCollaboration } from '../../../../model/bpmn/json/baseElement/rootElement/collaboration'; @@ -26,7 +26,7 @@ import { MessageFlow } from '../../../../model/bpmn/internal/edge/flows'; import ShapeBpmnElement from '../../../../model/bpmn/internal/shape/ShapeBpmnElement'; import { ensureIsArray } from '../../../helpers/array-utils'; -import { convertAndRegisterAssociationFlows, buildShapeBpmnGroup } from './utils'; +import { buildShapeBpmnGroup, convertAndRegisterAssociationFlows } from './utils'; /** * @internal @@ -46,6 +46,7 @@ export default class CollaborationConverter { this.buildMessageFlows(collaboration.messageFlow); convertAndRegisterAssociationFlows(this.convertedElements, collaboration.association); this.buildGroups(collaboration.group); + this.buildTextAnnotation(collaboration.textAnnotation); } private buildParticipant(bpmnElements: TParticipant[] | TParticipant): void { @@ -65,11 +66,9 @@ export default class CollaborationConverter { } } - // TODO duplicated with ProcessConverter --> extract like this is done in buildShapeBpmnGroup - // private buildAssociationFlows(bpmnElements: TAssociation[] | TAssociation): void { - // for (const association of ensureIsArray(bpmnElements)) { - // const direction = association.associationDirection as unknown as AssociationDirectionKind; - // this.convertedElements.registerAssociationFlow(new AssociationFlow(association.id, undefined, association.sourceRef, association.targetRef, direction)); - // } - // } + private buildTextAnnotation(bpmnElements: TTextAnnotation[] | TTextAnnotation): void { + for (const textAnnotation of ensureIsArray(bpmnElements)) { + this.convertedElements.registerFlowNode(new ShapeBpmnElement(textAnnotation.id, textAnnotation.text as string, ShapeBpmnElementKind.TEXT_ANNOTATION)); + } + } } diff --git a/src/component/parser/json/converter/ProcessConverter.ts b/src/component/parser/json/converter/ProcessConverter.ts index 5e5295a65a..8e57af0e27 100644 --- a/src/component/parser/json/converter/ProcessConverter.ts +++ b/src/component/parser/json/converter/ProcessConverter.ts @@ -54,6 +54,7 @@ import { BoundaryEventNotAttachedToActivityWarning, LaneUnknownFlowNodeReference import { convertAndRegisterAssociationFlows, buildShapeBpmnGroup } from './utils'; +// semantically speaking, TTextAnnotation is not a FlowNode, but it is an Artifact type FlowNode = TFlowNode | TActivity | TReceiveTask | TEventBasedGateway | TTextAnnotation; type BpmnSemanticType = keyof TProcess; diff --git a/test/unit/component/parser/json/BpmnJsonParser.text.annotation.test.ts b/test/unit/component/parser/json/BpmnJsonParser.text.annotation.test.ts index 2db0f1e97f..1b739c15fe 100644 --- a/test/unit/component/parser/json/BpmnJsonParser.text.annotation.test.ts +++ b/test/unit/component/parser/json/BpmnJsonParser.text.annotation.test.ts @@ -16,6 +16,8 @@ limitations under the License. import type { ExpectedShape } from '../../../helpers/bpmn-model-expect'; import type { BuildProcessParameter } from '../../../helpers/JsonBuilder'; +import type { BpmnJsonModel } from '@lib/model/bpmn/json/bpmn20'; +import type { BPMNEdge, BPMNShape } from '@lib/model/bpmn/json/bpmndi'; import { verifyShape } from '../../../helpers/bpmn-model-expect'; import { buildDefinitions } from '../../../helpers/JsonBuilder'; @@ -23,7 +25,38 @@ import { parseJsonAndExpectOnlyEdgesAndFlowNodes, parseJsonAndExpectOnlyFlowNode import { ShapeBpmnElementKind } from '@lib/model/bpmn/internal'; -describe('parse bpmn as json for text annotation', () => { +function expectedTextAnnotation(base: Pick): ExpectedShape { + return { + shapeId: `shape_${base.bpmnElementId}`, // generated in JsonBuilder + bpmnElementId: base.bpmnElementId, + bpmnElementName: base.bpmnElementName, + bpmnElementKind: ShapeBpmnElementKind.TEXT_ANNOTATION, + bounds: { x: 456, y: 23, width: 78, height: 54 }, // hardcoded in JsonBuilder + bpmnElementIncomingIds: base.bpmnElementIncomingIds, + bpmnElementOutgoingIds: base.bpmnElementOutgoingIds, + }; +} + +function buildBPMNEdge(id: string): BPMNEdge { + return { + id: `edge_${id}`, + bpmnElement: id, + waypoint: [ + { x: 45, y: 78 }, + { x: 51, y: 78 }, + ], + }; +} + +function buildBPMNShape(id: string): BPMNShape { + return { + id: `shape_${id}`, + bpmnElement: id, + Bounds: { x: 456, y: 23, width: 78, height: 54 }, + }; +} + +describe('parse bpmn as json for text annotation defined in a process', () => { const processWithArtifactAsObject = { textAnnotation: { id: `textAnnotation_id_0`, @@ -41,13 +74,13 @@ describe('parse bpmn as json for text annotation', () => { const model = parseJsonAndExpectOnlyFlowNodes(json, 1); - verifyShape(model.flowNodes[0], { - shapeId: `shape_textAnnotation_id_0`, - bpmnElementId: `textAnnotation_id_0`, - bpmnElementName: `textAnnotation name`, - bpmnElementKind: ShapeBpmnElementKind.TEXT_ANNOTATION, - bounds: { x: 456, y: 23, width: 78, height: 54 }, - }); + verifyShape( + model.flowNodes[0], + expectedTextAnnotation({ + bpmnElementId: `textAnnotation_id_0`, + bpmnElementName: `textAnnotation name`, + }), + ); }, ); @@ -68,20 +101,20 @@ describe('parse bpmn as json for text annotation', () => { const model = parseJsonAndExpectOnlyFlowNodes(json, 2); - verifyShape(model.flowNodes[0], { - shapeId: 'shape_TextAnnotation_01', - bpmnElementId: 'TextAnnotation_01', - bpmnElementName: 'Task Annotation', - bpmnElementKind: ShapeBpmnElementKind.TEXT_ANNOTATION, - bounds: { x: 456, y: 23, width: 78, height: 54 }, - }); - verifyShape(model.flowNodes[1], { - shapeId: 'shape_TextAnnotation_02', - bpmnElementId: 'TextAnnotation_02', - bpmnElementName: undefined, - bpmnElementKind: ShapeBpmnElementKind.TEXT_ANNOTATION, - bounds: { x: 456, y: 23, width: 78, height: 54 }, - }); + verifyShape( + model.flowNodes[0], + expectedTextAnnotation({ + bpmnElementId: `TextAnnotation_01`, + bpmnElementName: `Task Annotation`, + }), + ); + verifyShape( + model.flowNodes[1], + expectedTextAnnotation({ + bpmnElementId: 'TextAnnotation_02', + bpmnElementName: undefined, + }), + ); }); describe(`incoming/outgoing management for text annotation in process`, () => { @@ -105,14 +138,14 @@ describe('parse bpmn as json for text annotation', () => { const model = parseJsonAndExpectOnlyEdgesAndFlowNodes(json, 1, 1); - verifyShape(model.flowNodes[0], { - shapeId: `shape_text_annotation_id_0`, - bpmnElementId: `text_annotation_id_0`, - bpmnElementName: undefined, - bpmnElementKind: ShapeBpmnElementKind.TEXT_ANNOTATION, - bounds: { x: 456, y: 23, width: 78, height: 54 }, - [expectedAttribute]: [`flow_${title}`], - }); + verifyShape( + model.flowNodes[0], + expectedTextAnnotation({ + bpmnElementId: `text_annotation_id_0`, + bpmnElementName: undefined, + [expectedAttribute]: [`flow_${title}`], + }), + ); }, ); @@ -131,15 +164,129 @@ describe('parse bpmn as json for text annotation', () => { const model = parseJsonAndExpectOnlyEdgesAndFlowNodes(json, 4, 1); - verifyShape(model.flowNodes[0], { - shapeId: `shape_text_annotation_id_0`, + verifyShape( + model.flowNodes[0], + expectedTextAnnotation({ + bpmnElementId: `text_annotation_id_0`, + bpmnElementName: undefined, + bpmnElementIncomingIds: ['flow_in_1', 'flow_in_2'], + bpmnElementOutgoingIds: ['flow_out_2', 'flow_out_3'], + }), + ); + }); + }); +}); + +describe('parse bpmn as json for text annotation defined in "collaboration"', () => { + it(`should convert as Shape a single text annotation (as object)`, () => { + const json: BpmnJsonModel = { + definitions: { + targetNamespace: '', + collaboration: { + textAnnotation: { + id: 'textAnnotation_in_collaboration_id_0', + text: 'textAnnotation name', + }, + }, + BPMNDiagram: { + BPMNPlane: { + BPMNShape: [buildBPMNShape('textAnnotation_in_collaboration_id_0')], + }, + }, + }, + }; + + const model = parseJsonAndExpectOnlyFlowNodes(json, 1); + + verifyShape( + model.flowNodes[0], + expectedTextAnnotation({ + bpmnElementId: `textAnnotation_in_collaboration_id_0`, + bpmnElementName: `textAnnotation name`, + }), + ); + }); + + it(`should convert as Shape several text annotations (as array)`, () => { + const json: BpmnJsonModel = { + definitions: { + targetNamespace: '', + collaboration: { + textAnnotation: [ + { + id: 'textAnnotation_in_collaboration_id_1', + text: 'textAnnotation name 1', + }, + { + id: 'textAnnotation_in_collaboration_id_2', + text: 'textAnnotation name 2', + }, + ], + }, + BPMNDiagram: { + BPMNPlane: { + BPMNShape: [buildBPMNShape('textAnnotation_in_collaboration_id_1'), buildBPMNShape('textAnnotation_in_collaboration_id_2')], + }, + }, + }, + }; + + const model = parseJsonAndExpectOnlyFlowNodes(json, 2); + + verifyShape( + model.flowNodes[0], + expectedTextAnnotation({ + bpmnElementId: `textAnnotation_in_collaboration_id_1`, + bpmnElementName: `textAnnotation name 1`, + }), + ); + verifyShape( + model.flowNodes[1], + expectedTextAnnotation({ + bpmnElementId: `textAnnotation_in_collaboration_id_2`, + bpmnElementName: `textAnnotation name 2`, + }), + ); + }); + + it(`should convert as Shape, when a process contains a text annotation with incoming/outgoing associations`, () => { + const json: BpmnJsonModel = { + definitions: { + targetNamespace: '', + collaboration: { + textAnnotation: { id: `text_annotation_id_0` }, + association: [ + { id: 'flow_in_1', sourceRef: 'unknown', targetRef: 'text_annotation_id_0' }, + { id: 'flow_in_2', sourceRef: 'unknown', targetRef: 'text_annotation_id_0' }, + { id: 'flow_out_1', sourceRef: 'text_annotation_id_0', targetRef: 'unknown' }, + { id: 'flow_out_2', sourceRef: 'text_annotation_id_0', targetRef: 'unknown' }, + ], + }, + BPMNDiagram: { + BPMNPlane: { + BPMNShape: [ + { + id: 'shape_text_annotation_id_0', + bpmnElement: 'text_annotation_id_0', + Bounds: { x: 456, y: 23, width: 78, height: 54 }, + }, + ], + BPMNEdge: [buildBPMNEdge('flow_in_1'), buildBPMNEdge('flow_in_2'), buildBPMNEdge('flow_out_1'), buildBPMNEdge('flow_out_2')], + }, + }, + }, + }; + + const model = parseJsonAndExpectOnlyEdgesAndFlowNodes(json, 4, 1); + + verifyShape( + model.flowNodes[0], + expectedTextAnnotation({ bpmnElementId: `text_annotation_id_0`, bpmnElementName: undefined, - bpmnElementKind: ShapeBpmnElementKind.TEXT_ANNOTATION, - bounds: { x: 456, y: 23, width: 78, height: 54 }, bpmnElementIncomingIds: ['flow_in_1', 'flow_in_2'], - bpmnElementOutgoingIds: ['flow_out_2', 'flow_out_3'], - }); - }); + bpmnElementOutgoingIds: ['flow_out_1', 'flow_out_2'], + }), + ); }); }); From 0af6d6652ff2a71c7ad2541ccaa5f4195258227d Mon Sep 17 00:00:00 2001 From: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com> Date: Tue, 22 Oct 2024 19:18:16 +0200 Subject: [PATCH 4/6] e2e tests: update screenshot --- ...nnotations.06.defined.in.collaboration.png | Bin 9963 -> 11560 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/test/e2e/__image_snapshots__/bpmn-rendering/associations.and.annotations.06.defined.in.collaboration.png b/test/e2e/__image_snapshots__/bpmn-rendering/associations.and.annotations.06.defined.in.collaboration.png index bba6139c9cbbb012960e6dd81796fbc3023792c1..bdf3d985f1123eb2ccfc285713759c0115e02869 100644 GIT binary patch literal 11560 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 literal 9963 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

og6-S`SBFm~)P@{iOL%k;;>a!+ z7^O`uTR!eEQ_Fh+V4Y-Uh!f;_pEC|ww2k>gsP{z%E z2a8!<+|+M>+NGQJ8m!}3?9~ci`t+u{r(>H$wUVe1{lmZJIl^IGO<+lg9ZBE}pp1|; zw;<1ktkDx741B*;hDII?aTemI9S!4sdR!0#k0^vurymPN>7U;AZ#M(~Gk*Oa=C<0U z-{3h<@k8DN2GO@3e1alB-2P&qXejMqe!Zx`-qZDR!otExW;_aEcbnYlUrHHO7*TuB zLYVTW7{xVaEMCFph560SEJJD$%3dr?yHsW2%Xx^yVx$}1KY*Z+AIYkZqR|0R)`|=v zaO&#xJO8=_ob(Dh>z7ye4 zs}7U%6=K9hmK@4l$M%`_DvMqT-7SMvbZ&nQL0^W3U`7CB+(4jd(pbP3B&C6^l=`#W z5pq{3A?s-z_C(?sh`etrdkZ@NljO^W?&eyMk6=B=;!MxJm$0?qj-V;p*FSC6C&C3q zK8u<=)IUAoQN_G4-su3#8cZEQ*&hni_I(S>1VZps6J?$5Aq9m|EHf;{h9G9QMu4~D z3V6@_wQcEta7Pe3z(7GpbD)T=z?oBkg!WS4!41ccfBjacV<{l6@{^z|j}1H+DhC@R z7d|`^QV2N!;MP|OyC1NVk*Q%6$6B4q!_9Ql;gWnR8+i2BuF4f;KS(pk z&(R+W8|r&46Tg~?#Hvyu%h#!|j1M68u>RR0i;`PD?N}Kk_)3gZ?)UD1j*Mg7M49Ja zpz>(Fg%s%_AR;)M5P(lT0m}Aog4G-LfIK_qrY~UwGCXgcF&RA0dVEn9_ zvIaCfz!uh7KJ?;w+h<)+?W;&IxmRhLOj&nhMyvy{B_Nw44TR#%oZpc=6SisC2^6*i zg#57YkiPS$=z(4m+y(Yq*uZX_8OlZuusO7ZUf@eKqNG$H14b|c?tJpbr!3h}340;Y zxbpz6tr!lRg27-3@VEcAV@KL*rH_c5JnQPsP|^RYVD#ZI?XeEmfhL;waSSMC4t7f4BYqztD02e&7C|6aR~s8vehZoNN(rxISJbw?tI*wn7YA00zk0 z36*~3=$eQC`pT0+kD9S~3-m1lp^Iql1-k-Mt?)WWj&*;aqWv>E4c^hPb(#wP=lzWT z6K|?0HP)jyfST^LF`k=G`qx6zaAIs%J)rTCq5Lq_$ zCK>kT2(0}-mH&C+=KreqjLeX?v}y^|lm}RtjO* z`83nhS%3CzB??NMH5xi`I15riAnT4)u234hO*Idkm8rqYZt;b8s6tc6cK>e-lf^-` Y@6NGOBj*Xi+iNJSw*DWa-)-;y2ThO&d;kCd From 38a81e195bb4054dc98f4dc36c1ddd562102d87f Mon Sep 17 00:00:00 2001 From: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com> Date: Wed, 23 Oct 2024 08:38:20 +0200 Subject: [PATCH 5/6] integration tests: update model-complete-semantic.bpmn + add new tests --- test/fixtures/bpmn/model-complete-semantic.bpmn | 9 +++++++++ test/integration/mxGraph.model.bpmn.elements.test.ts | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/test/fixtures/bpmn/model-complete-semantic.bpmn b/test/fixtures/bpmn/model-complete-semantic.bpmn index 552b96d3a7..1f41297177 100644 --- a/test/fixtures/bpmn/model-complete-semantic.bpmn +++ b/test/fixtures/bpmn/model-complete-semantic.bpmn @@ -19,6 +19,10 @@ + + + + @@ -1933,6 +1937,9 @@ + + + @@ -2001,6 +2008,8 @@ + + diff --git a/test/integration/mxGraph.model.bpmn.elements.test.ts b/test/integration/mxGraph.model.bpmn.elements.test.ts index fb838a7a8e..4ccade0458 100644 --- a/test/integration/mxGraph.model.bpmn.elements.test.ts +++ b/test/integration/mxGraph.model.bpmn.elements.test.ts @@ -1437,6 +1437,13 @@ describe('mxGraph model - BPMN elements', () => { align: 'left', }); }); + it('text annotations in collaboration', () => { + expect('text_annotation_in_collaboration_1').toBeTextAnnotation({ + label: 'Text Annotation in collaboration', + parentId: getDefaultParentId(), + align: 'left', + }); + }); it('groups', () => { expect('Group_0_in_collaboration').toBeGroup({ @@ -1515,6 +1522,10 @@ describe('mxGraph model - BPMN elements', () => { it('associations', () => { expect('association_id').toBeAssociationFlow({ parentId: 'participant_1_id', verticalAlign: 'bottom' }); }); + + it('associations in collaboration', () => { + expect('association_in_collaboration_1').toBeAssociationFlow({ parentId: getDefaultParentId(), verticalAlign: 'bottom' }); + }); }); it('Diagram with a not displayed pool (without shape) with elements', () => { From 44e015674ac34f85b68b7d8cd706bbd1f6c5b81a Mon Sep 17 00:00:00 2001 From: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com> Date: Wed, 23 Oct 2024 14:33:45 +0200 Subject: [PATCH 6/6] remove extra todo [skip ci] --- src/component/parser/json/converter/utils.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/component/parser/json/converter/utils.ts b/src/component/parser/json/converter/utils.ts index 7d02acd3e0..eb37dab1c8 100644 --- a/src/component/parser/json/converter/utils.ts +++ b/src/component/parser/json/converter/utils.ts @@ -136,7 +136,6 @@ interface CategoryValueData { value?: string; } -// TODO review the name of the function: registerAssociationFlows? export const convertAndRegisterAssociationFlows = (convertedElements: ConvertedElements, bpmnElements: TAssociation[] | TAssociation): void => { for (const association of ensureIsArray(bpmnElements)) { const direction = association.associationDirection as unknown as AssociationDirectionKind;