bpmn-js Token Simulation Internals

An update on recent improvements.

Nico Rehwaldt

About Me

Agenda

1️⃣ Where we started

2️⃣ What we accomplished

1️⃣ Where we Started

Token simulation presentation

Camunda Community Summit

It is a fun project to hack upon.

➡️ Let's go!

Goals

2️⃣ What we Accomplished

Token simulation overview

In a Nutshell

A Standalone Simulator

🟡 Single instance process-engine, scattered across the whole code base, i.e. context pad handlers and simulation behavior.

🟢 Dedicated, multi-instance simulator with own state management. Driven via API, hooked into via events.

🟢 Executes signals, escalation, message flows and most other complex BPMN behaviors.

A Solid Execution Model

🟢 Scopes represent activities

🟢 Behaviors implement element specific scope enter, exit and signal (user trigger) actions

Scope in action

🟢 Drive the Simulation

const processElement = elementRegistry.get('Process');
const startEventElement = elementRegistry.get('StartEvent');

// start instance of <Process>
simulator.signal({
  element: processElement,
  startEvent: startEventElement
});

🟢 Query Active Scopes

const processElement = elementRegistry.get('Process');

// active instances in <Process>
const runningScopes = simulator.findScopes({
  element: processElement
});

🟢 Register a Behavior

function TaskBehavior(simulator) {
  simulator.registerBehavior('bpmn:Task', this);
}

🟢 Exit a Task

TaskBehavior.prototype.exit = function(context) {
  context.element.outgoing.filter(isSequenceFlow).map(flow => {
    simulator.enter({
      element: flow,
      parentScope: context.scope.parent
    });
  });
};

An Improved Testing Story

🟡 UI integration testing only.

🟢 Dedicated tests against the simulator API.

🟢 UI tests as a layer on top.

🟢 Dedicated Simulator Tests

verify('simple', () => {

  // when
  signal({
    element: element('Process_1')
  });

  // then
  expectTrace(...);
});

🟢 UI-based Integration Tests

it('should execute happy path', async function() {

  // when
  triggerElement('StartEvent_1');

  await scopeDestroyed();

  // then
  expectHistory(...);
});

🟢 Test Cover All Things!

bpmn-js-token-simulation test coverage diagram

🟢 Just Add Animation

AnimatedSequenceFlowBehavior.prototype.enter = function(context) {

  const {
    element,
    scope
  } = context;

  this._animation.animate(element, scope, () => {
    SequenceFlowBehavior.prototype.enter.call(this, context);
  });
};

General Housekeeping

🟢 Migrate to ES modules

🟢 Migrate to GitHub actions

🟢 Remove SVG.js in favor of own animation core

bpmn-js-token-simulation test coverage diagram

And more improvements.

Even more could be done

Try it out!

Thank you. Questions?

Contribute to Token Simulation

You like the token simulation tool? Consider contributing on Github and help us to make it even better ❤️.

Resources