diff --git a/src/model/bpmn/internal/shape/utils.ts b/src/model/bpmn/internal/shape/utils.ts index 89b7fc15f6..0b92bf05d0 100644 --- a/src/model/bpmn/internal/shape/utils.ts +++ b/src/model/bpmn/internal/shape/utils.ts @@ -107,9 +107,30 @@ export class ShapeUtil { return Object.values(ShapeBpmnElementKind).filter(kind => !ShapeUtil.isPoolOrLane(kind)); } + /** + * @since 0.48.0 + */ + static isFlowNode(kind: ShapeBpmnElementKind | string): boolean { + return ShapeUtil.flowNodeKinds().includes(kind as ShapeBpmnElementKind); + } + static isPoolOrLane(kind: ShapeBpmnElementKind | string): boolean { return kind == ShapeBpmnElementKind.POOL || kind == ShapeBpmnElementKind.LANE; } + + /** + * @since 0.48.0 + */ + static artifactKinds(): ShapeBpmnElementKind[] { + return [...ARTIFACT_KINDS]; + } + + /** + * @since 0.48.0 + */ + static isArtifact(kind: ShapeBpmnElementKind | string): boolean { + return ARTIFACT_KINDS.includes(kind as ShapeBpmnElementKind); + } } function filterKind(suffix: string, options?: FilterParameter): ShapeBpmnElementKind[] { @@ -135,6 +156,8 @@ const FLOW_NODE_WITH_DEFAULT_SEQUENCE_FLOW_KINDS = new Set([ ShapeBpmnElementKind.GATEWAY_COMPLEX, ]); +const ARTIFACT_KINDS = [ShapeBpmnElementKind.GROUP, ShapeBpmnElementKind.TEXT_ANNOTATION]; + /** * Elements that are effectively used in BPMN diagram as base for eventDefinition i.e all {@link ShapeBpmnEventDefinitionKind} elements except {@link ShapeBpmnEventDefinitionKind.NONE} * @internal diff --git a/test/unit/model/bpmn/internal/shape/utils.test.ts b/test/unit/model/bpmn/internal/shape/utils.test.ts index e7af45600d..3dd126c57c 100644 --- a/test/unit/model/bpmn/internal/shape/utils.test.ts +++ b/test/unit/model/bpmn/internal/shape/utils.test.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { ShapeBpmnElementKind, ShapeUtil } from '@lib/model/bpmn/internal'; +import { FlowKind, ShapeBpmnElementKind, ShapeUtil } from '@lib/model/bpmn/internal'; describe('ShapeUtil', () => { it('top level bpmn event kinds', () => { @@ -29,6 +29,20 @@ describe('ShapeUtil', () => { expect(tasks).toContain(ShapeBpmnElementKind.TASK_USER); }); + it('flow node kinds', () => { + const flowNodeKinds = ShapeUtil.flowNodeKinds(); + expect(flowNodeKinds).toContain(ShapeBpmnElementKind.TASK); + expect(flowNodeKinds).toContain(ShapeBpmnElementKind.EVENT_INTERMEDIATE_CATCH); + expect(flowNodeKinds).toContain(ShapeBpmnElementKind.GROUP); // artifact should not be included + expect(flowNodeKinds).not.toContain(ShapeBpmnElementKind.POOL); + }); + + it('artifact kinds', () => { + const artifacts = ShapeUtil.artifactKinds(); + expect(artifacts).toContain(ShapeBpmnElementKind.GROUP); + expect(artifacts).toContain(ShapeBpmnElementKind.TEXT_ANNOTATION); + }); + describe('Is pool or lane?', () => { it.each([ [ShapeBpmnElementKind.CALL_ACTIVITY], @@ -46,10 +60,51 @@ describe('ShapeUtil', () => { }); }); + describe('isArtifact', () => { + test.each` + kind | expected + ${ShapeBpmnElementKind.EVENT_END} | ${false} + ${ShapeBpmnElementKind.GATEWAY_PARALLEL} | ${false} + ${ShapeBpmnElementKind.TASK} | ${false} + ${ShapeBpmnElementKind.SUB_PROCESS} | ${false} + ${ShapeBpmnElementKind.CALL_ACTIVITY} | ${false} + ${ShapeBpmnElementKind.POOL} | ${false} + ${ShapeBpmnElementKind.LANE} | ${false} + ${ShapeBpmnElementKind.GROUP} | ${true} + ${ShapeBpmnElementKind.TEXT_ANNOTATION} | ${true} + ${FlowKind.MESSAGE_FLOW} | ${false} + ${'unknown'} | ${false} + ${'receiveTask'} | ${false} + `('$kind isArtifact? $expected', ({ kind, expected }: Record) => { + expect(ShapeUtil.isArtifact(kind as string)).toBe(expected); + }); + }); + + describe('isFlowNode', () => { + test.each` + kind | expected + ${ShapeBpmnElementKind.EVENT_END} | ${true} + ${ShapeBpmnElementKind.GATEWAY_PARALLEL} | ${true} + ${ShapeBpmnElementKind.TASK} | ${true} + ${ShapeBpmnElementKind.SUB_PROCESS} | ${true} + ${ShapeBpmnElementKind.CALL_ACTIVITY} | ${true} + ${ShapeBpmnElementKind.POOL} | ${false} + ${ShapeBpmnElementKind.LANE} | ${false} + ${ShapeBpmnElementKind.GROUP} | ${true} + ${ShapeBpmnElementKind.TEXT_ANNOTATION} | ${true} + ${FlowKind.MESSAGE_FLOW} | ${false} + ${'unknown'} | ${false} + ${'receiveTask'} | ${true} + `('$kind isFlowNode? $expected', ({ kind, expected }: Record) => { + expect(ShapeUtil.isFlowNode(kind as string)).toBe(expected); + }); + }); + describe('Reference kinds cannot be modified', () => { it.each` kind | kindsFunction ${'activities'} | ${() => ShapeUtil.activityKinds()} + ${'artifacts'} | ${() => ShapeUtil.artifactKinds()} ${'events'} | ${() => ShapeUtil.eventKinds()} ${'flow nodes'} | ${() => ShapeUtil.flowNodeKinds()} ${'gateways'} | ${() => ShapeUtil.gatewayKinds()}