From 3d52258172d41a1bbe524c5ec78753cce7fc042c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Souchet=20C=C3=A9line?= <4921914+csouchet@users.noreply.github.com> Date: Fri, 13 Oct 2023 09:01:14 +0200 Subject: [PATCH] feat: add link event data in `ShapeBpmnSemantic` (#2911) Add new `linkEventSourceIds` an `linkEventTargetId` properties in `ShapeBpmnSemantic` to include data related to the link events that are stored in the internal model. --------- Co-authored-by: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com> --- src/component/registry/bpmn-model-registry.ts | 13 ++- src/component/registry/types.ts | 8 ++ .../bpmn/model-complete-semantic.bpmn | 11 ++- ...pool-2-lanes-link-intermediate-events.bpmn | 81 +++++++++++++++++++ test/integration/dom.bpmn.elements.test.ts | 26 ++++++ test/integration/helpers/model-expect.ts | 23 +++--- .../helpers/semantic-with-svg-utils.ts | 31 ++++++- test/integration/matchers/toBeShape/index.ts | 15 +++- test/integration/model.elements.api.test.ts | 24 +++++- test/shared/model/bpmn-semantic-utils.ts | 14 +++- .../registry/bpmn-model-registry.test.ts | 64 ++++++++++++++- test/unit/helpers/bpmn-model-expect.ts | 21 +++-- test/unit/helpers/bpmn-model-utils.ts | 27 +++++++ 13 files changed, 328 insertions(+), 30 deletions(-) create mode 100644 test/fixtures/bpmn/registry/1-pool-2-lanes-link-intermediate-events.bpmn diff --git a/src/component/registry/bpmn-model-registry.ts b/src/component/registry/bpmn-model-registry.ts index 401f24d5cb..d55deaed63 100644 --- a/src/component/registry/bpmn-model-registry.ts +++ b/src/component/registry/bpmn-model-registry.ts @@ -20,9 +20,15 @@ import type { Edge } from '../../model/bpmn/internal/edge/edge'; import type Shape from '../../model/bpmn/internal/shape/Shape'; import type { ModelFilter } from '../options'; -import { ShapeBpmnMarkerKind, ShapeUtil } from '../../model/bpmn/internal'; +import { ShapeBpmnEventDefinitionKind, ShapeBpmnMarkerKind, ShapeUtil } from '../../model/bpmn/internal'; import { Flow } from '../../model/bpmn/internal/edge/flows'; -import ShapeBpmnElement, { ShapeBpmnCallActivity, ShapeBpmnEvent, ShapeBpmnSubProcess } from '../../model/bpmn/internal/shape/ShapeBpmnElement'; +import ShapeBpmnElement, { + ShapeBpmnCallActivity, + ShapeBpmnEvent, + ShapeBpmnIntermediateCatchEvent, + ShapeBpmnIntermediateThrowEvent, + ShapeBpmnSubProcess, +} from '../../model/bpmn/internal/shape/ShapeBpmnElement'; import { ModelFiltering } from './bpmn-model-filters'; @@ -68,6 +74,9 @@ export class BpmnModelRegistry { callActivityGlobalTaskKind: bpmnElement instanceof ShapeBpmnCallActivity ? bpmnElement.globalTaskKind : undefined, callActivityKind: bpmnElement instanceof ShapeBpmnCallActivity ? bpmnElement.callActivityKind : undefined, eventDefinitionKind: bpmnElement instanceof ShapeBpmnEvent ? bpmnElement.eventDefinitionKind : undefined, + linkEventSourceIds: + bpmnElement instanceof ShapeBpmnIntermediateCatchEvent && bpmnElement.eventDefinitionKind == ShapeBpmnEventDefinitionKind.LINK ? bpmnElement.sourceIds : undefined, + linkEventTargetId: bpmnElement instanceof ShapeBpmnIntermediateThrowEvent ? bpmnElement.targetId : undefined, incomingIds: bpmnElement.incomingIds, outgoingIds: bpmnElement.outgoingIds, parentId: bpmnElement.parentId, diff --git a/src/component/registry/types.ts b/src/component/registry/types.ts index a33fc2f840..cf103d05b2 100644 --- a/src/component/registry/types.ts +++ b/src/component/registry/types.ts @@ -370,13 +370,21 @@ export interface EdgeBpmnSemantic extends BaseBpmnSemantic { * @category Custom Behavior */ export interface ShapeBpmnSemantic extends BaseBpmnSemantic { + // IMPORTANT: keep properties in alphabetical order for consistency + /** Set when the {@link BaseBpmnSemantic.kind} relates to a BPMN Call Activity calling a global task. */ callActivityGlobalTaskKind?: GlobalTaskKind; /** Set when the {@link BaseBpmnSemantic.kind} relates to a BPMN Call Activity. */ callActivityKind?: ShapeBpmnCallActivityKind; /** Set when the {@link BaseBpmnSemantic.kind} relates to a BPMN event. */ eventDefinitionKind?: ShapeBpmnEventDefinitionKind; + /** IDs of the incoming flows/edges. */ incomingIds: string[]; + /** Set when the {@link BaseBpmnSemantic.kind} relates to a BPMN intermediate catch event with {@link ShapeBpmnSemantic.eventDefinitionKind} set to {@link ShapeBpmnEventDefinitionKind.LINK}. */ + linkEventSourceIds?: string[]; + /** Set when the {@link BaseBpmnSemantic.kind} relates to a BPMN intermediate throw event with {@link ShapeBpmnSemantic.eventDefinitionKind} set to {@link ShapeBpmnEventDefinitionKind.LINK}. */ + linkEventTargetId?: string; + /** IDs of the outgoing flows/edges. */ outgoingIds: string[]; /** * This is the ID of the direct parent of the current element, which can be a: diff --git a/test/fixtures/bpmn/model-complete-semantic.bpmn b/test/fixtures/bpmn/model-complete-semantic.bpmn index 01d45c7e01..552b96d3a7 100644 --- a/test/fixtures/bpmn/model-complete-semantic.bpmn +++ b/test/fixtures/bpmn/model-complete-semantic.bpmn @@ -26,7 +26,12 @@ - + + top_catch_link_definition_id + + + top_throw_link_definition_id + @@ -635,7 +640,7 @@ - top_link_definition_id + top_throw_link_definition_id @@ -673,7 +678,7 @@ - top_link_definition_id + top_catch_link_definition_id diff --git a/test/fixtures/bpmn/registry/1-pool-2-lanes-link-intermediate-events.bpmn b/test/fixtures/bpmn/registry/1-pool-2-lanes-link-intermediate-events.bpmn new file mode 100644 index 0000000000..469c92299c --- /dev/null +++ b/test/fixtures/bpmn/registry/1-pool-2-lanes-link-intermediate-events.bpmn @@ -0,0 +1,81 @@ + + + + + + + + + Event_1q818hp + startEvent_lane_1 + + + Event_1wihmdr + Event_0snpz9d + + + + + sequenceFlow_lane_1_elt_1 + + LinkEventDefinition_077j2qu + + + + sequenceFlow_lane_1_elt_1 + + + + Flow_18jrbeb + + LinkEventDefinition_11kxj5k + + + + Flow_18jrbeb + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/integration/dom.bpmn.elements.test.ts b/test/integration/dom.bpmn.elements.test.ts index 5156c9cca9..ea87791b6d 100644 --- a/test/integration/dom.bpmn.elements.test.ts +++ b/test/integration/dom.bpmn.elements.test.ts @@ -24,6 +24,8 @@ import { } from './helpers/bpmn-visualization-initialization'; import { expectEndEventBpmnElement, + expectIntermediateCatchEventBpmnElement, + expectIntermediateThrowEventBpmnElement, expectParallelGatewayBpmnElement, expectPoolBpmnElement, expectSequenceFlowBpmnElement, @@ -62,6 +64,30 @@ describe('Bpmn Elements registry - retrieve BPMN elements', () => { expectSequenceFlowBpmnElement(bpmnElements[1], { id: 'Flow_2', source: 'Activity_1', target: 'EndEvent_1' }); }); + it('Pass existing link intermediate event ids', () => { + bpmnVisualization.load(readFileSync('../fixtures/bpmn/registry/1-pool-2-lanes-link-intermediate-events.bpmn')); + const bpmnElements = bpmnVisualization.bpmnElementsRegistry.getElementsByIds(['Event_1wihmdr', 'Event_1q818hp']); + expect(bpmnElements).toHaveLength(2); + + expectIntermediateCatchEventBpmnElement(bpmnElements[0], { + id: 'Event_1wihmdr', + name: 'link catch intermediate', + parentId: 'lane_02', + eventDefinitionKind: ShapeBpmnEventDefinitionKind.LINK, + outgoing: ['Flow_18jrbeb'], + linkEventSourceIds: ['Event_1q818hp'], + }); + + expectIntermediateThrowEventBpmnElement(bpmnElements[1], { + id: 'Event_1q818hp', + name: 'link throw intermediate', + parentId: 'lane_01', + eventDefinitionKind: ShapeBpmnEventDefinitionKind.LINK, + incoming: ['sequenceFlow_lane_1_elt_1'], + linkEventTargetId: 'Event_1wihmdr', + }); + }); + it('Pass a single non existing id', () => { bpmnVisualization.load(readFileSync('../fixtures/bpmn/simple-start-task-end.bpmn')); const bpmnElements = bpmnVisualization.bpmnElementsRegistry.getElementsByIds('unknown'); diff --git a/test/integration/helpers/model-expect.ts b/test/integration/helpers/model-expect.ts index 339932af5b..8872b1eb00 100644 --- a/test/integration/helpers/model-expect.ts +++ b/test/integration/helpers/model-expect.ts @@ -83,8 +83,8 @@ declare global { toBeBusinessRuleTask(modelElement: ExpectedShapeModelElement): R; toBeStartEvent(modelElement: ExpectedStartEventModelElement): R; toBeEndEvent(modelElement: ExpectedEventModelElement): R; - toBeIntermediateThrowEvent(modelElement: ExpectedEventModelElement): R; - toBeIntermediateCatchEvent(modelElement: ExpectedEventModelElement): R; + toBeIntermediateThrowEvent(modelElement: ExpectedIntermediateThrowEventModelElement): R; + toBeIntermediateCatchEvent(modelElement: ExpectedIntermediateCatchEventModelElement): R; toBeBoundaryEvent(modelElement: ExpectedBoundaryEventModelElement): R; toBeEventBasedGateway(modelElement: ExpectedEventBasedGatewayModelElement): R; toBeExclusiveGateway(modelElement: ExpectedShapeModelElement): R; @@ -200,6 +200,18 @@ export type ExpectedShapeModelElement = { export type ExpectedEventModelElement = { eventDefinitionKind: ShapeBpmnEventDefinitionKind; } & ExpectedShapeModelElement; +export type ExpectedIntermediateCatchEventModelElement = { + sourceIds?: string[]; +} & ExpectedEventModelElement; +export type ExpectedIntermediateThrowEventModelElement = { + targetId?: string; +} & ExpectedEventModelElement; +export type ExpectedBoundaryEventModelElement = { + isInterrupting?: boolean; +} & ExpectedEventModelElement; +export type ExpectedStartEventModelElement = { + isInterrupting?: boolean; +} & ExpectedEventModelElement; export type ExpectedSubProcessModelElement = { subProcessKind: ShapeBpmnSubProcessKind; @@ -220,13 +232,6 @@ export type ExpectedSequenceFlowModelElement = { sequenceFlowKind?: SequenceFlowKind; } & ExpectedEdgeModelElement; -export type ExpectedBoundaryEventModelElement = { - isInterrupting?: boolean; -} & ExpectedEventModelElement; -export type ExpectedStartEventModelElement = { - isInterrupting?: boolean; -} & ExpectedEventModelElement; - export type ExpectedEventBasedGatewayModelElement = { gatewayKind?: ShapeBpmnEventBasedGatewayKind; } & ExpectedShapeModelElement; diff --git a/test/integration/helpers/semantic-with-svg-utils.ts b/test/integration/helpers/semantic-with-svg-utils.ts index 456f409873..f122d0aaeb 100644 --- a/test/integration/helpers/semantic-with-svg-utils.ts +++ b/test/integration/helpers/semantic-with-svg-utils.ts @@ -15,11 +15,28 @@ limitations under the License. */ import type { BpmnElement, EdgeBpmnSemantic, ShapeBpmnSemantic } from '@lib/component/registry'; -import type { ExpectedBaseBpmnElement, ExpectedFlowElement, ExpectedFlowNodeElement, ExpectedEventElement } from '@test/shared/model/bpmn-semantic-utils'; +import type { + ExpectedBaseBpmnElement, + ExpectedFlowElement, + ExpectedFlowNodeElement, + ExpectedEventElement, + ExpectedIntermediateThrowEventElement, + ExpectedIntermediateCatchEventElement, +} from '@test/shared/model/bpmn-semantic-utils'; import { expectSvgEvent, expectSvgGateway, expectSvgPool, expectSvgSequenceFlow, expectSvgTask } from './html-utils'; -import { expectEndEvent, expectParallelGateway, expectPool, expectSequenceFlow, expectServiceTask, expectStartEvent, expectTask } from '@test/shared/model/bpmn-semantic-utils'; +import { + expectEndEvent, + expectIntermediateCatchEvent, + expectIntermediateThrowEvent, + expectParallelGateway, + expectPool, + expectSequenceFlow, + expectServiceTask, + expectStartEvent, + expectTask, +} from '@test/shared/model/bpmn-semantic-utils'; export function expectStartEventBpmnElement(bpmnElement: BpmnElement, expected: ExpectedEventElement): void { expectStartEvent(bpmnElement.bpmnSemantic as ShapeBpmnSemantic, expected); @@ -31,6 +48,16 @@ export function expectEndEventBpmnElement(bpmnElement: BpmnElement, expected: Ex expectSvgEvent(bpmnElement.htmlElement); } +export function expectIntermediateCatchEventBpmnElement(bpmnElement: BpmnElement, expected: ExpectedIntermediateCatchEventElement): void { + expectIntermediateCatchEvent(bpmnElement.bpmnSemantic as ShapeBpmnSemantic, expected); + expectSvgEvent(bpmnElement.htmlElement); +} + +export function expectIntermediateThrowEventBpmnElement(bpmnElement: BpmnElement, expected: ExpectedIntermediateThrowEventElement): void { + expectIntermediateThrowEvent(bpmnElement.bpmnSemantic as ShapeBpmnSemantic, expected); + expectSvgEvent(bpmnElement.htmlElement); +} + export function expectSequenceFlowBpmnElement(bpmnElement: BpmnElement, expected: ExpectedFlowElement): void { expectSequenceFlow(bpmnElement.bpmnSemantic as EdgeBpmnSemantic, expected); expectSvgSequenceFlow(bpmnElement.htmlElement); diff --git a/test/integration/matchers/toBeShape/index.ts b/test/integration/matchers/toBeShape/index.ts index 655ec5bdac..2cf0333180 100644 --- a/test/integration/matchers/toBeShape/index.ts +++ b/test/integration/matchers/toBeShape/index.ts @@ -22,6 +22,8 @@ import type { ExpectedShapeModelElement, ExpectedStartEventModelElement, ExpectedSubProcessModelElement, + ExpectedIntermediateCatchEventModelElement, + ExpectedIntermediateThrowEventModelElement, } from '../../helpers/model-expect'; import type { BpmnCellStyle, ExpectedCell } from '../matcher-utils'; @@ -97,7 +99,8 @@ function buildExpectedShapeStylePropertyRegexp( expectedModel: | ExpectedShapeModelElement | ExpectedSubProcessModelElement - | ExpectedEventModelElement + | ExpectedIntermediateCatchEventModelElement + | ExpectedIntermediateThrowEventModelElement | ExpectedStartEventModelElement | ExpectedBoundaryEventModelElement | ExpectedEventBasedGatewayModelElement @@ -127,6 +130,12 @@ function buildExpectedShapeStylePropertyRegexp( if ('gatewayKind' in expectedModel) { expectedStyle = expectedStyle + `.*bpmn.gatewayKind=${expectedModel.gatewayKind}`; } + if ('sourceIds' in expectedModel) { + expectedStyle = expectedStyle + `.*bpmn.linkEventSourceIds=${expectedModel.sourceIds}`; + } + if ('targetId' in expectedModel) { + expectedStyle = expectedStyle + `.*bpmn.linkEventTargetId=${expectedModel.targetId}`; + } return expectedStyle + '.*'; } @@ -221,11 +230,11 @@ export function toBeEndEvent(this: MatcherContext, received: string, expected: E return buildEventMatcher('toBeEndEvent', this, received, { ...expected, kind: ShapeBpmnElementKind.EVENT_END }); } -export function toBeIntermediateThrowEvent(this: MatcherContext, received: string, expected: ExpectedEventModelElement): CustomMatcherResult { +export function toBeIntermediateThrowEvent(this: MatcherContext, received: string, expected: ExpectedIntermediateThrowEventModelElement): CustomMatcherResult { return buildEventMatcher('toBeIntermediateThrowEvent', this, received, { ...expected, kind: ShapeBpmnElementKind.EVENT_INTERMEDIATE_THROW }); } -export function toBeIntermediateCatchEvent(this: MatcherContext, received: string, expected: ExpectedEventModelElement): CustomMatcherResult { +export function toBeIntermediateCatchEvent(this: MatcherContext, received: string, expected: ExpectedIntermediateCatchEventModelElement): CustomMatcherResult { return buildEventMatcher('toBeIntermediateCatchEvent', this, received, { ...expected, kind: ShapeBpmnElementKind.EVENT_INTERMEDIATE_CATCH }); } diff --git a/test/integration/model.elements.api.test.ts b/test/integration/model.elements.api.test.ts index dd22e799a9..254dbc2c8e 100644 --- a/test/integration/model.elements.api.test.ts +++ b/test/integration/model.elements.api.test.ts @@ -26,6 +26,7 @@ import { expectCallActivity, expectEndEvent, expectIntermediateCatchEvent, + expectIntermediateThrowEvent, expectParallelGateway, expectSequenceFlow, expectStartEvent, @@ -107,6 +108,27 @@ describe('Registry API - retrieve Model Bpmn elements', () => { }); }); + test('Pass link event (with source & target) ids', () => { + const modelElements = bpmnElementsRegistry.getModelElementsByIds(['intermediate_catch_event_link_on_top_id', 'intermediate_throw_event_link_on_top_id']); + + expect(modelElements).toHaveLength(2); + + expectIntermediateCatchEvent(modelElements[0] as ShapeBpmnSemantic, { + id: 'intermediate_catch_event_link_on_top_id', + name: 'Catch Link Intermediate Event On Top', + parentId: 'participant_1_id', + eventDefinitionKind: ShapeBpmnEventDefinitionKind.LINK, + linkEventSourceIds: ['intermediate_throw_event_link_on_top_id'], + }); + expectIntermediateThrowEvent(modelElements[1] as ShapeBpmnSemantic, { + id: 'intermediate_throw_event_link_on_top_id', + name: 'Throw Link Intermediate Event On Top', + parentId: 'participant_1_id', + eventDefinitionKind: ShapeBpmnEventDefinitionKind.LINK, + linkEventTargetId: 'intermediate_catch_event_link_on_top_id', + }); + }); + test('Pass a single non existing id', () => { expect(bpmnElementsRegistry.getModelElementsByIds('unknown')).toHaveLength(0); }); @@ -139,11 +161,11 @@ describe('Registry API - retrieve Model Bpmn elements', () => { target: 'gateway_with_flows_id', }); expectStartEvent(modelElements[2] as ShapeBpmnSemantic, { - eventDefinitionKind: ShapeBpmnEventDefinitionKind.NONE, id: 'start_event_in_adHoc_sub_process_id', name: 'Start Event In AdHoc Sub-Process', outgoing: ['sequence_flow_in_adHoc_sub_process_1_id'], parentId: 'expanded_adHoc_sub_process_id', + eventDefinitionKind: ShapeBpmnEventDefinitionKind.NONE, }); expectBoundaryEvent(modelElements[3] as ShapeBpmnSemantic, { eventDefinitionKind: ShapeBpmnEventDefinitionKind.TIMER, diff --git a/test/shared/model/bpmn-semantic-utils.ts b/test/shared/model/bpmn-semantic-utils.ts index 7a562efb1b..825b64b813 100644 --- a/test/shared/model/bpmn-semantic-utils.ts +++ b/test/shared/model/bpmn-semantic-utils.ts @@ -71,6 +71,8 @@ function expectedFlowNode(bpmnSemantic: ShapeBpmnSemantic, expected: ExpectedFlo } export type ExpectedEventElement = ExpectedFlowNodeElement & Pick; +export type ExpectedIntermediateCatchEventElement = ExpectedEventElement & Pick; +export type ExpectedIntermediateThrowEventElement = ExpectedEventElement & Pick; function expectEvent(bpmnSemantic: ShapeBpmnSemantic, expected: ExpectedEventElement): void { expectedFlowNode(bpmnSemantic, expected); @@ -81,6 +83,7 @@ export function expectStartEvent(bpmnSemantic: ShapeBpmnSemantic, expected: Expe expect(bpmnSemantic.kind).toEqual(ShapeBpmnElementKind.EVENT_START); expectEvent(bpmnSemantic, expected); } + export function expectEndEvent(bpmnSemantic: ShapeBpmnSemantic, expected: ExpectedEventElement): void { expect(bpmnSemantic.kind).toEqual(ShapeBpmnElementKind.EVENT_END); expectEvent(bpmnSemantic, expected); @@ -91,9 +94,18 @@ export function expectBoundaryEvent(bpmnSemantic: ShapeBpmnSemantic, expected: E expectEvent(bpmnSemantic, expected); } -export function expectIntermediateCatchEvent(bpmnSemantic: ShapeBpmnSemantic, expected: ExpectedEventElement): void { +export function expectIntermediateCatchEvent(bpmnSemantic: ShapeBpmnSemantic, expected: ExpectedIntermediateCatchEventElement): void { expect(bpmnSemantic.kind).toEqual(ShapeBpmnElementKind.EVENT_INTERMEDIATE_CATCH); expectEvent(bpmnSemantic, expected); + expect(bpmnSemantic.linkEventSourceIds).toStrictEqual(expected.linkEventSourceIds); + expect(bpmnSemantic.linkEventTargetId).toBeUndefined(); +} + +export function expectIntermediateThrowEvent(bpmnSemantic: ShapeBpmnSemantic, expected: ExpectedIntermediateThrowEventElement): void { + expect(bpmnSemantic.kind).toEqual(ShapeBpmnElementKind.EVENT_INTERMEDIATE_THROW); + expectEvent(bpmnSemantic, expected); + expect(bpmnSemantic.linkEventSourceIds).toBeUndefined(); + expect(bpmnSemantic.linkEventTargetId).toStrictEqual(expected.linkEventTargetId); } export function expectParallelGateway(bpmnSemantic: BpmnSemantic, expected: ExpectedFlowNodeElement): void { diff --git a/test/unit/component/registry/bpmn-model-registry.test.ts b/test/unit/component/registry/bpmn-model-registry.test.ts index 8aa20b78dc..1b37b5c843 100644 --- a/test/unit/component/registry/bpmn-model-registry.test.ts +++ b/test/unit/component/registry/bpmn-model-registry.test.ts @@ -16,11 +16,29 @@ limitations under the License. import type { EdgeBpmnSemantic, ShapeBpmnSemantic } from '@lib/component/registry'; -import { associationFlowInModel, laneInModel, messageFlowInModel, poolInModel, sequenceFlowInModel, startEventInModel } from '../../helpers/bpmn-model-utils'; +import { + associationFlowInModel, + intermediateCatchEventInModel, + intermediateThrowEventInModel, + laneInModel, + messageFlowInModel, + poolInModel, + sequenceFlowInModel, + startEventInModel, +} from '../../helpers/bpmn-model-utils'; import { BpmnModelRegistry } from '@lib/component/registry/bpmn-model-registry'; import { ShapeBpmnEventDefinitionKind } from '@lib/model/bpmn/internal'; -import { expectAssociationFlow, expectLane, expectMessageFlow, expectPool, expectSequenceFlow, expectStartEvent } from '@test/shared/model/bpmn-semantic-utils'; +import { + expectAssociationFlow, + expectIntermediateCatchEvent, + expectIntermediateThrowEvent, + expectLane, + expectMessageFlow, + expectPool, + expectSequenceFlow, + expectStartEvent, +} from '@test/shared/model/bpmn-semantic-utils'; const bpmnModelRegistry = new BpmnModelRegistry(); @@ -52,6 +70,7 @@ describe('Bpmn Model registry', () => { it('search flowNode', () => { bpmnModelRegistry.load(startEventInModel('start event id', 'start event name', { incomingIds: ['incoming_1'], outgoingIds: ['outgoing_1', 'outgoing_2'] })); const bpmnSemantic = bpmnModelRegistry.getBpmnSemantic('start event id') as ShapeBpmnSemantic; + expectStartEvent(bpmnSemantic, { id: 'start event id', name: 'start event name', @@ -62,6 +81,47 @@ describe('Bpmn Model registry', () => { }); }); + it('search intermediate catch event', () => { + bpmnModelRegistry.load( + intermediateCatchEventInModel('intermediate catch event id', 'intermediate catch event name', { incomingIds: ['incoming_1'], outgoingIds: ['outgoing_1', 'outgoing_2'] }, [ + 'sourceId', + ]), + ); + const bpmnSemantic = bpmnModelRegistry.getBpmnSemantic('intermediate catch event id') as ShapeBpmnSemantic; + + expectIntermediateCatchEvent(bpmnSemantic, { + id: 'intermediate catch event id', + name: 'intermediate catch event name', + incoming: ['incoming_1'], + outgoing: ['outgoing_1', 'outgoing_2'], + parentId: 'parentId', + eventDefinitionKind: ShapeBpmnEventDefinitionKind.LINK, + linkEventSourceIds: ['sourceId'], + }); + }); + + it('search intermediate throw event', () => { + bpmnModelRegistry.load( + intermediateThrowEventInModel( + 'intermediate throw event id', + 'intermediate throw event name', + { incomingIds: ['incoming_1'], outgoingIds: ['outgoing_1', 'outgoing_2'] }, + 'targetId', + ), + ); + const bpmnSemantic = bpmnModelRegistry.getBpmnSemantic('intermediate throw event id') as ShapeBpmnSemantic; + + expectIntermediateThrowEvent(bpmnSemantic, { + id: 'intermediate throw event id', + name: 'intermediate throw event name', + incoming: ['incoming_1'], + outgoing: ['outgoing_1', 'outgoing_2'], + parentId: 'parentId', + eventDefinitionKind: ShapeBpmnEventDefinitionKind.LINK, + linkEventTargetId: 'targetId', + }); + }); + it('search lane', () => { bpmnModelRegistry.load(laneInModel('lane id', 'lane name')); const bpmnSemantic = bpmnModelRegistry.getBpmnSemantic('lane id'); diff --git a/test/unit/helpers/bpmn-model-expect.ts b/test/unit/helpers/bpmn-model-expect.ts index 4cc4f842c4..7ffc35ae81 100644 --- a/test/unit/helpers/bpmn-model-expect.ts +++ b/test/unit/helpers/bpmn-model-expect.ts @@ -52,15 +52,15 @@ export interface ExpectedEventShape extends ExpectedShape { eventDefinitionKind: ShapeBpmnEventDefinitionKind; } -export interface ExpectedCatchEventShape extends ExpectedEventShape { +export interface ExpectedIntermediateCatchEventShape extends ExpectedEventShape { sourceIds?: string[]; } -export interface ExpectedThrowEventShape extends ExpectedEventShape { +export interface ExpectedIntermediateThrowEventShape extends ExpectedEventShape { targetId?: string; } -export interface ExpectedBoundaryEventShape extends ExpectedCatchEventShape { +export interface ExpectedBoundaryEventShape extends ExpectedEventShape { isInterrupting?: boolean; } @@ -103,7 +103,14 @@ export interface ExpectedBounds { export const verifyShape = ( shape: Shape, - expectedShape: ExpectedShape | ExpectedActivityShape | ExpectedCallActivityShape | ExpectedCatchEventShape | ExpectedThrowEventShape | ExpectedBoundaryEventShape, + expectedShape: + | ExpectedShape + | ExpectedActivityShape + | ExpectedCallActivityShape + | ExpectedEventShape + | ExpectedIntermediateCatchEventShape + | ExpectedIntermediateThrowEventShape + | ExpectedBoundaryEventShape, ): void => { expect(shape.id).toEqual(expectedShape.shapeId); expect(shape.isHorizontal).toEqual(expectedShape.isHorizontal); @@ -139,9 +146,9 @@ export const verifyShape = ( if (expectedEvent.eventDefinitionKind === ShapeBpmnEventDefinitionKind.LINK) { if (ShapeUtil.isIntermediateCatchEvent(expectedShape.bpmnElementKind)) { - expect((event as ShapeBpmnIntermediateCatchEvent).sourceIds).toEqual((expectedEvent as ExpectedCatchEventShape).sourceIds ?? []); - } else { - expect((event as ShapeBpmnIntermediateThrowEvent).targetId).toEqual((expectedEvent as ExpectedThrowEventShape).targetId); + expect((event as ShapeBpmnIntermediateCatchEvent).sourceIds).toEqual((expectedEvent as ExpectedIntermediateCatchEventShape).sourceIds ?? []); + } else if (ShapeUtil.isIntermediateThrowEvent(expectedShape.bpmnElementKind)) { + expect((event as ShapeBpmnIntermediateThrowEvent).targetId).toEqual((expectedEvent as ExpectedIntermediateThrowEventShape).targetId); } } } diff --git a/test/unit/helpers/bpmn-model-utils.ts b/test/unit/helpers/bpmn-model-utils.ts index cd9d8c7261..9f4d6be5d1 100644 --- a/test/unit/helpers/bpmn-model-utils.ts +++ b/test/unit/helpers/bpmn-model-utils.ts @@ -27,6 +27,8 @@ import ShapeBpmnElement, { ShapeBpmnCallActivity, ShapeBpmnStartEvent, ShapeBpmnSubProcess, + ShapeBpmnIntermediateThrowEvent, + ShapeBpmnIntermediateCatchEvent, } from '@lib/model/bpmn/internal/shape/ShapeBpmnElement'; const newBpmnModel = (): BpmnModel => ({ @@ -73,6 +75,18 @@ export const startEventInModel = (id: string, name: string, extras?: ShapeBpmnEl return bpmnModel; }; +export const intermediateCatchEventInModel = (id: string, name: string, extras?: ShapeBpmnElementExtraProperties, sourceIds?: string[]): BpmnModel => { + const bpmnModel = newBpmnModel(); + bpmnModel.flowNodes.push(newIntermediateCatchEvent('parentId', id, name, extras, sourceIds)); + return bpmnModel; +}; + +export const intermediateThrowEventInModel = (id: string, name: string, extras?: ShapeBpmnElementExtraProperties, targetId?: string): BpmnModel => { + const bpmnModel = newBpmnModel(); + bpmnModel.flowNodes.push(newIntermediateThrowEvent('parentId', id, name, extras, targetId)); + return bpmnModel; +}; + export const laneInModel = (id: string, name: string): BpmnModel => { const bpmnModel = newBpmnModel(); bpmnModel.lanes.push(new Shape(buildShapeId(id), new ShapeBpmnElement(id, name, ShapeBpmnElementKind.LANE))); @@ -99,6 +113,19 @@ export type ShapeBpmnElementExtraProperties = { const newStartEvent = (parent: string, id: string, name: string, extras?: ShapeBpmnElementExtraProperties): Shape => { return new Shape(buildShapeId(id), withExtras(new ShapeBpmnStartEvent(id, name, ShapeBpmnEventDefinitionKind.TIMER, parent), extras)); }; + +const newIntermediateCatchEvent = (parent: string, id: string, name: string, extras?: ShapeBpmnElementExtraProperties, sourceIds: string[] = []): Shape => { + const bpmnElement = new ShapeBpmnIntermediateCatchEvent(id, name, ShapeBpmnEventDefinitionKind.LINK, parent); + bpmnElement.sourceIds = sourceIds; + return new Shape(buildShapeId(id), withExtras(bpmnElement, extras)); +}; + +const newIntermediateThrowEvent = (parent: string, id: string, name: string, extras?: ShapeBpmnElementExtraProperties, targetId?: string): Shape => { + const bpmnElement = new ShapeBpmnIntermediateThrowEvent(id, name, ShapeBpmnEventDefinitionKind.LINK, parent); + bpmnElement.targetId = targetId; + return new Shape(buildShapeId(id), withExtras(bpmnElement, extras)); +}; + const newBoundaryEvent = (parent: string, id: string, name: string): Shape => new Shape(buildShapeId(id), new ShapeBpmnBoundaryEvent(id, name, ShapeBpmnEventDefinitionKind.CANCEL, parent));