From 495997607ca40988e786b11114c5b5f04ff4714a Mon Sep 17 00:00:00 2001 From: Martin Stamm Date: Mon, 18 Oct 2021 10:28:36 +0200 Subject: [PATCH] feat: add Overlays to navigate collapsed subprocesses This introduces a new css file to bpmn-js. To upgrade, please include `dist/assets/bpmn-js.css` in your application. closes #1483 --- assets/bpmn-js.css | 51 +++ lib/Viewer.js | 4 +- .../SubprocessCentering.js | 35 ++ .../SubprocessCompatibility.js | 135 ++++++ .../SubprocessOverlays.js | 100 +++++ lib/features/subprocess-navigation/index.js | 14 + tasks/build-distro.js | 3 + test/TestHelper.js | 2 + .../SubprocessNavigationSpec.js | 210 +++++++++ .../legacy-subprocesses.bpmn | 51 +++ .../nested-subprocesses.bpmn | 418 ++++++++++++++++++ test/spec/import/ImporterSpec.js | 4 +- test/spec/import/elements/CollapsedSpec.js | 69 ++- 13 files changed, 1072 insertions(+), 24 deletions(-) create mode 100644 assets/bpmn-js.css create mode 100644 lib/features/subprocess-navigation/SubprocessCentering.js create mode 100644 lib/features/subprocess-navigation/SubprocessCompatibility.js create mode 100644 lib/features/subprocess-navigation/SubprocessOverlays.js create mode 100644 lib/features/subprocess-navigation/index.js create mode 100644 test/spec/features/subprocess-navigation/SubprocessNavigationSpec.js create mode 100644 test/spec/features/subprocess-navigation/legacy-subprocesses.bpmn create mode 100644 test/spec/features/subprocess-navigation/nested-subprocesses.bpmn diff --git a/assets/bpmn-js.css b/assets/bpmn-js.css new file mode 100644 index 00000000..fed3e0a9 --- /dev/null +++ b/assets/bpmn-js.css @@ -0,0 +1,51 @@ +.bjs-container { + --bjs-font-family: Arial, sans-serif; +} + +.bjs-breadcrumbs { + position: absolute; + top: 10px; + left: 100px; + font-family: var(--bjs-font-family); +} + +.bjs-breadcrumbs li { + display: inline-block; + color: var(--blue-base-65); + cursor: pointer; +} + +.bjs-breadcrumbs li:last-of-type { + color: inherit; + cursor: default; +} + +.bjs-breadcrumbs li:not(:first-child)::before { + content: url('data:image/svg+xml;utf8,'); + padding: 0 8px; + color: black; +} + +.bjs-breadcrumbs .bpmnjs-crumb { + display: inline-block; + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.bjs-drilldown { + width: 20px; + height: 20px; + + padding: 0px; + margin-left: -20px; + + cursor: pointer; + border: none; + border-radius: 2px; + outline: none; + + fill: white; + background-color: var(--blue-base-65); +} diff --git a/lib/Viewer.js b/lib/Viewer.js index 217887e4..cc996adf 100644 --- a/lib/Viewer.js +++ b/lib/Viewer.js @@ -4,6 +4,7 @@ import CoreModule from './core'; import TranslateModule from 'diagram-js/lib/i18n/translate'; import SelectionModule from 'diagram-js/lib/features/selection'; import OverlaysModule from 'diagram-js/lib/features/overlays'; +import SubprocessNavigationModule from './features/subprocess-navigation'; import BaseViewer from './BaseViewer'; @@ -66,7 +67,8 @@ Viewer.prototype._modules = [ CoreModule, TranslateModule, SelectionModule, - OverlaysModule + OverlaysModule, + SubprocessNavigationModule ]; // default moddle extensions the viewer is composed of diff --git a/lib/features/subprocess-navigation/SubprocessCentering.js b/lib/features/subprocess-navigation/SubprocessCentering.js new file mode 100644 index 00000000..7c9c7096 --- /dev/null +++ b/lib/features/subprocess-navigation/SubprocessCentering.js @@ -0,0 +1,35 @@ +export default function SubprocessCentering(eventBus, canvas) { + var currentPlane = 'base'; + var positionMap = {}; + + eventBus.on('plane.set', function(event) { + + var currentViewbox = canvas.viewbox(); + positionMap[currentPlane] = { + x: currentViewbox.x, + y: currentViewbox.y, + zoom: currentViewbox.scale + }; + + var planeId = event.plane.name; + var storedViewbox = positionMap[planeId] || { x: 0, y: 0, zoom: 1 }; + + var dx = (currentViewbox.x - storedViewbox.x) * currentViewbox.scale, + dy = (currentViewbox.y - storedViewbox.y) * currentViewbox.scale; + + if (dx !== 0 || dy !== 0) { + canvas.scroll({ + dx: dx, + dy: dy + }); + } + + if (storedViewbox.zoom !== currentViewbox.scale) { + canvas.zoom(storedViewbox.zoom, { x: 0, y: 0 }); + } + + currentPlane = planeId; + }); +} + +SubprocessCentering.$inject = [ 'eventBus', 'canvas' ]; diff --git a/lib/features/subprocess-navigation/SubprocessCompatibility.js b/lib/features/subprocess-navigation/SubprocessCompatibility.js new file mode 100644 index 00000000..fc0d5773 --- /dev/null +++ b/lib/features/subprocess-navigation/SubprocessCompatibility.js @@ -0,0 +1,135 @@ + +import { selfAndAllChildren } from 'diagram-js/lib/util/Elements'; +import { isExpanded } from '../../util/DiUtil'; +import { getBusinessObject, getDi, is } from '../../util/ModelUtil'; + +export default function SubprocessCompatibility(eventBus, elementRegistry, canvas, moddle, elementFactory, bpmnjs) { + this._eventBus = eventBus; + this._elementRegistry = elementRegistry; + this._canvas = canvas; + this._bpmnjs = bpmnjs; + this._moddle = moddle; + this._elementFactory = elementFactory; + + var self = this; + + eventBus.on('import.done', 1500, function() { + self._handleImport(); + }); +} + +SubprocessCompatibility.prototype._handleImport = function() { + var elementRegistry = this._elementRegistry; + var canvas = this._canvas; + var elementFactory = this._elementFactory; + var self = this; + var legacyProcesses = elementRegistry.filter(function(element) { + return is(element, 'bpmn:SubProcess') && !isExpanded(element) && element.children && element.children.length; + }); + + legacyProcesses.forEach(function(oldParent) { + var bo = getBusinessObject(oldParent); + + var newDiagram = self.createDiagram(bo); + + var newParent = elementFactory.createRoot( + { + id: bo.id, + type: bo.$type, + businessObject: bo, + di: newDiagram.plane + } + ); + + newParent.id = newParent.id + '_plane'; + + canvas.createPlane(bo.id, newParent); + + var elementsToChange = selfAndAllChildren(oldParent).filter(function(el) { + return el !== oldParent; + }); + + self.moveElementsToRoot(elementsToChange); + + elementsToChange.forEach(function(el) { + if (el.parent === oldParent) { + el.parent = newParent; + } + el.hidden = el.parent && (el.parent.hidden || el.parent.collapsed); + + self.moveToDiPlane(el, newDiagram.plane); + + self._eventBus.fire('elements.changed', { elements: [el] }); + }); + }); + +}; + +SubprocessCompatibility.prototype.moveToDiPlane = function(element, newPlane) { + var di = getDi(element); + var containingDiagram = findRootDiagram(di); + + // Remove DI from old Plane and add it to the new one + var parentPlaneElement = containingDiagram.plane.get('planeElement'); + parentPlaneElement.splice(parentPlaneElement.indexOf(di), 1); + newPlane.get('planeElement').push(di); +}; + +SubprocessCompatibility.prototype.moveElementsToRoot = function(elements) { + var defaultPosition = { x: 180, y: 160 }, + minX = Infinity, + minY = Infinity; + + elements.forEach(function(el) { + minX = Math.min(minX, el.x || Infinity); + minY = Math.min(minY, el.y || Infinity); + }); + + var xOffset = defaultPosition.x - minX; + var yOffset = defaultPosition.y - minY; + + elements.forEach(function(el) { + if (el.waypoints) { + el.waypoints.forEach(function(waypoint) { + waypoint.x = waypoint.x + xOffset; + waypoint.y = waypoint.y + yOffset; + }); + } else { + el.x = el.x + xOffset; + el.y = el.y + yOffset; + } + }); +}; + +SubprocessCompatibility.prototype.getDefinitions = function() { + return this._bpmnjs._definitions || []; +}; + +SubprocessCompatibility.prototype.getDiagrams = function() { + return this.getDefinitions().diagrams || []; +}; + +SubprocessCompatibility.prototype.createDiagram = function(bo) { + var plane = this._moddle.create('bpmndi:BPMNPlane', { bpmnElement: bo }); + var diagram = this._moddle.create('bpmndi:BPMNDiagram', { + plane: plane + }); + plane.$parent = diagram; + plane.bpmnElement = bo; + diagram.$parent = this.getDefinitions(); + this.getDiagrams().push(diagram); + return diagram; +}; + +SubprocessCompatibility.$inject = [ 'eventBus', 'elementRegistry', 'canvas', 'moddle', 'elementFactory', 'bpmnjs' ]; + + +// Util + +var findRootDiagram = function(element) { + if (is(element, 'bpmndi:BPMNDiagram')) { + return element; + } else { + return findRootDiagram(element.$parent); + } +}; \ No newline at end of file diff --git a/lib/features/subprocess-navigation/SubprocessOverlays.js b/lib/features/subprocess-navigation/SubprocessOverlays.js new file mode 100644 index 00000000..8d5f4e75 --- /dev/null +++ b/lib/features/subprocess-navigation/SubprocessOverlays.js @@ -0,0 +1,100 @@ +import { domify } from 'min-dom'; + +import { escapeHTML } from 'diagram-js/lib/util/EscapeUtil'; +import { getBusinessObject, is } from '../../util/ModelUtil'; + +var ARROW_DOWN_SVG = ''; + +export default function SubprocessOverlays(eventBus, elementRegistry, overlays, canvas) { + var breadcrumbs = domify(''); + var container = canvas.getContainer(); + container.appendChild(breadcrumbs); + + function updateBreadcrumbs(plane) { + var subProcess = elementRegistry.get(plane.name); + var parents = getParentChain(subProcess); + + var path = parents.map(function(el) { + var title = escapeHTML(el.name) || el.id; + var link = domify('
  • ' + title + '
  • '); + + link.addEventListener('click', function() { + if (canvas.getPlane(el.id)) { + canvas.setActivePlane(el.id); + } else { + var plane = canvas.findPlane(el.id); + canvas.setActivePlane(plane); + } + }); + + return link; + }); + + breadcrumbs.innerHTML = ''; + + if (path.length > 1) { + breadcrumbs.classList.remove('djs-element-hidden'); + } else { + breadcrumbs.classList.add('djs-element-hidden'); + } + + path.forEach(function(el) { + breadcrumbs.appendChild(el); + }); + } + + eventBus.on('plane.set', function(event) { + var plane = event.plane; + + updateBreadcrumbs(plane); + }); + + var createOverlay = function(element) { + var html = domify(''); + + html.addEventListener('click', function() { + canvas.setActivePlane(element.id); + }); + + overlays.add(element, { + position: { + bottom: -7, + right: -8 + }, + html: html + }); + }; + + var addOverlays = function(elements) { + elements.forEach(function(element) { + if (is(element, 'bpmn:SubProcess') + && element.collapsed + && canvas.getPlane(element.id)) { + createOverlay(element); + } + }); + }; + + eventBus.on('import.done', function() { + addOverlays(elementRegistry.filter(function(el) { + return is(el, 'bpmn:SubProcess'); + })); + }); +} + +SubprocessOverlays.$inject = [ 'eventBus', 'elementRegistry', 'overlays', 'canvas' ]; + + +var getParentChain = function(child) { + var bo = getBusinessObject(child); + + var parents = []; + + for (var element = bo; element; element = element.$parent) { + if (is(element, 'bpmn:SubProcess') || is(element, 'bpmn:Process')) { + parents.push(element); + } + } + + return parents.reverse(); +}; diff --git a/lib/features/subprocess-navigation/index.js b/lib/features/subprocess-navigation/index.js new file mode 100644 index 00000000..0360ff3d --- /dev/null +++ b/lib/features/subprocess-navigation/index.js @@ -0,0 +1,14 @@ +import OverlaysModule from 'diagram-js/lib/features/overlays'; +import ChangeSupportModule from 'diagram-js/lib/features/change-support'; + +import SubprocessCentering from './SubprocessCentering'; +import SubprocessCompatibility from './SubprocessCompatibility'; +import SubprocessOverlays from './SubprocessOverlays'; + +export default { + __depends__: [ OverlaysModule, ChangeSupportModule ], + __init__: [ 'subprocessOverlays', 'subprocessCompatibility', 'subprocessCentering' ], + subprocessOverlays: [ 'type', SubprocessOverlays ], + subprocessCompatibility: [ 'type', SubprocessCompatibility ], + subprocessCentering: [ 'type', SubprocessCentering ] +}; \ No newline at end of file diff --git a/tasks/build-distro.js b/tasks/build-distro.js index 4e69def0..f60392ca 100644 --- a/tasks/build-distro.js +++ b/tasks/build-distro.js @@ -28,6 +28,9 @@ cp(resolve('bpmn-font', '/dist/{font,css}/**'), dest + '/assets/bpmn-font'); console.log('copy diagram-js.css to ' + dest); cp(resolve('diagram-js', '/assets/**'), dest + '/assets'); +console.log('copy bpmn-js.css to ' + dest); +cp('./assets/bpmn-js.css', dest + '/assets'); + console.log('building pre-packaged distributions'); var NODE_ENV = process.env.NODE_ENV; diff --git a/test/TestHelper.js b/test/TestHelper.js index d1f4c90a..36219f4e 100644 --- a/test/TestHelper.js +++ b/test/TestHelper.js @@ -4,6 +4,8 @@ import { insertCSS } from './helper'; +insertCSS('bpmn-js.css', require('../assets/bpmn-js.css')); + insertCSS('diagram-js.css', require('diagram-js/assets/diagram-js.css')); insertCSS('bpmn-embedded.css', require('bpmn-font/dist/css/bpmn-embedded.css')); diff --git a/test/spec/features/subprocess-navigation/SubprocessNavigationSpec.js b/test/spec/features/subprocess-navigation/SubprocessNavigationSpec.js new file mode 100644 index 00000000..d664f353 --- /dev/null +++ b/test/spec/features/subprocess-navigation/SubprocessNavigationSpec.js @@ -0,0 +1,210 @@ +import { + inject +} from 'test/TestHelper'; + +import coreModule from 'lib/core'; +import subprocessNavigationModule from 'lib/features/subprocess-navigation'; +import { bootstrapViewer } from '../../../helper'; + +describe('features - subprocess-navigation', function() { + + var testModules = [ + coreModule, + subprocessNavigationModule + ]; + + var multiLayerXML = require('./nested-subprocesses.bpmn'); + var legacyXML = require('./legacy-subprocesses.bpmn'); + + beforeEach(bootstrapViewer(multiLayerXML, { modules: testModules })); + + describe('Overlays', function() { + + it('should show overlay on Subprocess with content', inject(function(elementRegistry, overlays) { + + // given + var collapsedProcess = elementRegistry.get('collapsedProcess'); + var overlay = overlays.get({ element: collapsedProcess }); + + // then + expect(overlay).to.exist; + })); + + + it('should not show overlay on Subprocess without content', inject(function(elementRegistry, overlays) { + + // given + var collapsedProcess = elementRegistry.get('collapsedProcess_withoutContent'); + var overlay = overlays.get({ element: collapsedProcess }); + + // then + expect(overlay).to.not.exist; + })); + + + it('should switch plane on click', inject(function(elementRegistry, overlays, canvas) { + + // given + var collapsedProcess = elementRegistry.get('collapsedProcess'); + var overlay = overlays.get({ element: collapsedProcess })[0]; + + // when + overlay.html.click(); + + // then + var plane = canvas.getActivePlane(); + expect(plane.name).to.eql('collapsedProcess'); + })); + + }); + + + describe('Breadcrumbs', function() { + + it('should not show breadcrumbs in root view', inject(function(canvas) { + + // given + var breadcrumbs = canvas.getContainer().querySelector('.bjs-breadcrumbs'); + + // then + expect(breadcrumbs.classList.contains('djs-element-hidden')).to.be.true; + })); + + + it('should show breadcrumbs in subprocess view', inject(function(canvas) { + + // given + var breadcrumbs = canvas.getContainer().querySelector('.bjs-breadcrumbs'); + + // when + canvas.setActivePlane('collapsedProcess'); + + // then + expect(breadcrumbs.classList.contains('djs-element-hidden')).to.be.false; + })); + + + it('should show execution tree', inject(function(canvas) { + + // given + var breadcrumbs = canvas.getContainer().querySelector('.bjs-breadcrumbs'); + + // when + canvas.setActivePlane('collapsedProcess_2'); + + // then + expectBreadcrumbs(breadcrumbs, ['Root', 'Collapsed Process', 'Expanded Process', 'Collapsed Process 2']); + })); + + + it('should switch to process plane on click', inject(function(canvas) { + + // given + var breadcrumbs = canvas.getContainer().querySelector('.bjs-breadcrumbs'); + canvas.setActivePlane('collapsedProcess_2'); + + // when + breadcrumbs.children[1].click(); + + // then + expectBreadcrumbs(breadcrumbs, ['Root', 'Collapsed Process']); + })); + + + it('should switch to containing process plane on embedded click', inject(function(canvas) { + + // given + var breadcrumbs = canvas.getContainer().querySelector('.bjs-breadcrumbs'); + canvas.setActivePlane('collapsedProcess_2'); + + // when + breadcrumbs.children[2].click(); + + // then + expectBreadcrumbs(breadcrumbs, ['Root', 'Collapsed Process']); + })); + + }); + + + describe('Navigation', function() { + + it('should reset scroll and zoom', inject(function(canvas) { + + // given + canvas.scroll({ dx: 500, dy: 500 }); + canvas.zoom(0.5); + + // when + canvas.setActivePlane('collapsedProcess'); + + // then + var viewbox = canvas.viewbox(); + expect(viewbox.x).to.eql(0); + expect(viewbox.y).to.eql(0); + expect(viewbox.scale).to.eql(1); + })); + + + it('should remember scroll and zoom', inject(function(canvas) { + + // given + canvas.scroll({ dx: 500, dy: 500 }); + canvas.zoom(0.5); + var zoomedAndScrolledViewbox = canvas.viewbox(); + + // when + canvas.setActivePlane('collapsedProcess'); + canvas.setActivePlane('rootProcess'); + + // then + var newViewbox = canvas.viewbox(); + expect(newViewbox.x).to.eql(zoomedAndScrolledViewbox.x); + expect(newViewbox.y).to.eql(zoomedAndScrolledViewbox.y); + expect(newViewbox.scale).to.eql(zoomedAndScrolledViewbox.scale); + })); + + }); + + + describe('Legacy Processes', function() { + + beforeEach(bootstrapViewer(legacyXML, { modules: testModules })); + + it('should import collapsed subprocess', inject(function(canvas) { + + // when + var inlineProcess1 = canvas.getPlane('inlineSubprocess'); + var inlineProcess2 = canvas.getPlane('inlineSubprocess_2'); + + // then + expect(inlineProcess1).to.exist; + expect(inlineProcess2).to.exist; + })); + + + it('should move inlined elements to sensible position', inject(function(elementRegistry) { + + // when + var startEvent = elementRegistry.get('subprocess_startEvent'); + + // then + expect(startEvent).to.exist; + expect(startEvent.x).to.equal(180); + expect(startEvent.y).to.equal(160); + })); + + }); + +}); + + +// helpers + +function expectBreadcrumbs(breadcrumbs, expected) { + var crumbs = Array.from(breadcrumbs.children).map(function(element) { + return element.innerText; + }); + + expect(crumbs).to.eql(expected); +} \ No newline at end of file diff --git a/test/spec/features/subprocess-navigation/legacy-subprocesses.bpmn b/test/spec/features/subprocess-navigation/legacy-subprocesses.bpmn new file mode 100644 index 00000000..4626c1f7 --- /dev/null +++ b/test/spec/features/subprocess-navigation/legacy-subprocesses.bpmn @@ -0,0 +1,51 @@ + + + + + + + Flow_0obnxbt + + + + Flow_1d6ajf7 + + + Flow_0obnxbt + Flow_1d6ajf7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/spec/features/subprocess-navigation/nested-subprocesses.bpmn b/test/spec/features/subprocess-navigation/nested-subprocesses.bpmn new file mode 100644 index 00000000..154d6904 --- /dev/null +++ b/test/spec/features/subprocess-navigation/nested-subprocesses.bpmn @@ -0,0 +1,418 @@ + + + + + + sid-89A3F9F2-CCC8-46C7-816B-DD8AC8A98300 + + + sid-89A3F9F2-CCC8-46C7-816B-DD8AC8A98300 + sid-F06605E1-AEC1-4B39-8843-4AD3F547B557 + sid-FC2ECAF5-771E-4ED3-BEF6-EFAB45E79500 + + + sid-F06605E1-AEC1-4B39-8843-4AD3F547B557 + sid-31F6EC44-E44C-4121-B4FE-BD69AF208C05 + + sid-EB275CF2-5EF1-44FA-B41B-71EB37CC2657 + + + sid-EB275CF2-5EF1-44FA-B41B-71EB37CC2657 + sid-FB543319-8DFB-4445-AAA3-720137FB230B + + + + + + + sid-FB543319-8DFB-4445-AAA3-720137FB230B + sid-B99D259B-1BD5-45FF-BD57-FB99C360BAC0 + + sid-472B540C-A0CD-46F4-9640-DF692EC1BFFC + + + sid-472B540C-A0CD-46F4-9640-DF692EC1BFFC + sid-910420B0-D11B-4F9D-B285-703D8AC0BA90 + + sid-A7460113-CB75-491D-817B-5E1A8C606B8C + + + sid-A7460113-CB75-491D-817B-5E1A8C606B8C + sid-01982395-64E8-43EF-A6D3-CDD276C312AA + + + sid-01982395-64E8-43EF-A6D3-CDD276C312AA + + + + + + + + sid-910420B0-D11B-4F9D-B285-703D8AC0BA90 + + + + + + + + sid-B99D259B-1BD5-45FF-BD57-FB99C360BAC0 + + + + + + + + + + sid-FC2ECAF5-771E-4ED3-BEF6-EFAB45E79500 + sid-5B23450F-AF5E-4519-B134-32107776BD44 + + sid-E71F5783-AFE7-44ED-8A9C-378C95087448 + + + sid-E71F5783-AFE7-44ED-8A9C-378C95087448 + sid-6B9741CD-D94B-41C7-A2EA-63A4C9445E16 + + sid-3BB6D6CA-BF45-4D15-A1AB-64686C41DB32 + + + sid-3BB6D6CA-BF45-4D15-A1AB-64686C41DB32 + sid-4E25B80E-EF68-4EE5-BB08-C1F54F1A7C39 + + + sid-4E25B80E-EF68-4EE5-BB08-C1F54F1A7C39 + + + + + + + + sid-6B9741CD-D94B-41C7-A2EA-63A4C9445E16 + sid-1A9DABC6-6079-4BF2-9D49-C4DC9569C519 + + sid-E5404926-738D-4447-87FE-FC6DD1E8BEFC + + + sid-E5404926-738D-4447-87FE-FC6DD1E8BEFC + sid-FED62A8F-6C3A-4BB2-8DE9-18FB0B35B50E + + + sid-FED62A8F-6C3A-4BB2-8DE9-18FB0B35B50E + + + + + + + + sid-1A9DABC6-6079-4BF2-9D49-C4DC9569C519 + + + + + + + + + + + + + + + + sid-5B23450F-AF5E-4519-B134-32107776BD44 + sid-31F6EC44-E44C-4121-B4FE-BD69AF208C05 + sid-F7DA1903-6A1A-4858-AF4B-286A968C957F + + + sid-DCB98638-BEBD-4548-B501-F0E29AC71ED4 + + + + sid-DCB98638-BEBD-4548-B501-F0E29AC71ED4 + + + sid-F7DA1903-6A1A-4858-AF4B-286A968C957F + sid-3FAE72F2-4037-4CBA-8B89-01D7FC7FF3E3 + + + sid-3FAE72F2-4037-4CBA-8B89-01D7FC7FF3E3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/spec/import/ImporterSpec.js b/test/spec/import/ImporterSpec.js index 8f1dfc97..338f10a2 100644 --- a/test/spec/import/ImporterSpec.js +++ b/test/spec/import/ImporterSpec.js @@ -7,7 +7,7 @@ import { importBpmnDiagram } from 'lib/import/Importer'; -import Viewer from 'lib/Viewer'; +import CoreModule from 'lib/core'; import { matches as domMatches @@ -36,7 +36,7 @@ describe('import - Importer', function() { var diagram; beforeEach(function() { - diagram = createDiagram(TestContainer.get(this), Viewer.prototype._modules); + diagram = createDiagram(TestContainer.get(this), [CoreModule]); }); diff --git a/test/spec/import/elements/CollapsedSpec.js b/test/spec/import/elements/CollapsedSpec.js index c957719b..ba735390 100644 --- a/test/spec/import/elements/CollapsedSpec.js +++ b/test/spec/import/elements/CollapsedSpec.js @@ -13,59 +13,76 @@ describe('import - collapsed container', function() { beforeEach(bootstrapViewer(diagramXML)); - it('should import collapsed subProcess', inject(function(elementRegistry) { + it('should import collapsed subProcess', inject(function(elementRegistry, canvas) { var collapsedShape = elementRegistry.get('SubProcess_1'); + var collapsedPlane = canvas.findPlane(collapsedShape); var childShape = elementRegistry.get('IntermediateCatchEvent_1'); + var childPlane = canvas.findPlane(childShape); expect(collapsedShape.collapsed).to.be.true; - expect(childShape.hidden).to.be.true; + expect(collapsedPlane).to.not.eql(childPlane); })); - it('should import collapsed transaction', inject(function(elementRegistry) { + it('should import collapsed transaction', inject(function(elementRegistry, canvas) { var collapsedShape = elementRegistry.get('Transaction_1'); + var collapsedPlane = canvas.findPlane(collapsedShape); var childShape = elementRegistry.get('UserTask_1'); + var childPlane = canvas.findPlane(childShape); expect(collapsedShape.collapsed).to.be.true; - expect(childShape.hidden).to.be.true; + expect(collapsedPlane).to.not.eql(childPlane); })); - it('should import collapsed adhocSubProcess', inject(function(elementRegistry) { + it('should import collapsed adhocSubProcess', inject(function(elementRegistry, canvas) { var collapsedShape = elementRegistry.get('AdHocSubProcess_1'); + var collapsedPlane = canvas.findPlane(collapsedShape); var childShape = elementRegistry.get('StartEvent_1'); + var childPlane = canvas.findPlane(childShape); expect(collapsedShape.collapsed).to.be.true; - expect(childShape.hidden).to.be.true; + expect(collapsedPlane).to.not.eql(childPlane); })); - it('should import collapsed with nested elements', inject(function(elementRegistry) { + it('should import collapsed with nested elements', inject(function(elementRegistry, canvas) { var collapsedShape = elementRegistry.get('SubProcess_4'); + var collapsedPlane = canvas.findPlane(collapsedShape); var childShape = elementRegistry.get('SubProcess_5'); + var childPlane = canvas.findPlane(childShape); var nestedChildShape = elementRegistry.get('Task_3'); + var nestedChildPlane = canvas.findPlane(nestedChildShape); expect(collapsedShape.collapsed).to.be.true; - expect(childShape.hidden).to.be.true; - expect(nestedChildShape.hidden).to.be.true; + expect(childPlane).to.not.eql(collapsedPlane); + expect(nestedChildPlane).to.not.eql(collapsedPlane); })); - it('should import collapsed with nested hidden labels', inject(function(elementRegistry) { + it('should import collapsed with nested hidden labels', inject(function(elementRegistry, canvas) { + var collapsedShape = elementRegistry.get('SubProcess_2'); + var collapsedPlane = canvas.findPlane(collapsedShape); + var hiddenEventShape = elementRegistry.get('StartEvent_2'); - expect(hiddenEventShape.label.hidden).to.be.true; + var hiddenEventPlane = canvas.findPlane(hiddenEventShape); + expect(hiddenEventPlane).to.not.eql(collapsedPlane); var hiddenDataShape = elementRegistry.get('DataObjectReference_1'); - expect(hiddenDataShape.label.hidden).to.be.true; + var hiddenDataPlane = canvas.findPlane(hiddenDataShape); + expect(hiddenDataPlane).to.not.eql(collapsedPlane); })); - it('should import expanded subProcess', inject(function(elementRegistry) { + it('should import expanded subProcess', inject(function(elementRegistry, canvas) { var expandedShape = elementRegistry.get('SubProcess_3'); + var expandedPlane = canvas.findPlane(expandedShape); var childShape = elementRegistry.get('Task_2'); + var childPlane = canvas.findPlane(childShape); expect(expandedShape.collapsed).to.be.false; expect(childShape.hidden).to.be.false; + expect(expandedPlane).to.eql(childPlane); })); }); @@ -78,39 +95,49 @@ describe('import - collapsed container', function() { beforeEach(bootstrapViewer(diagramXML)); - it('should import collapsed subProcess in pool', inject(function(elementRegistry) { - var expandedShape = elementRegistry.get('SubProcess_1'); + it('should import collapsed subProcess in pool', inject(function(elementRegistry, canvas) { + var collapsedShape = elementRegistry.get('SubProcess_1'); + var collapsedPlane = canvas.findPlane(collapsedShape); var childShape = elementRegistry.get('Task_1'); + var childPlane = canvas.findPlane(childShape); - expect(expandedShape.collapsed).to.be.true; - expect(childShape.hidden).to.be.true; + expect(collapsedShape.collapsed).to.be.true; + expect(collapsedPlane).to.not.eql(childPlane); })); - it('should import expanded subProcess in pool', inject(function(elementRegistry) { + it('should import expanded subProcess in pool', inject(function(elementRegistry, canvas) { var expandedShape = elementRegistry.get('SubProcess_2'); + var expandedPlane = canvas.findPlane(expandedShape); var childShape = elementRegistry.get('StartEvent_1'); + var childPlane = canvas.findPlane(childShape); expect(expandedShape.collapsed).to.be.false; expect(childShape.hidden).to.be.false; + expect(expandedPlane).to.eql(childPlane); })); - it('should import collapsed subProcess in lane', inject(function(elementRegistry) { + it('should import collapsed subProcess in lane', inject(function(elementRegistry, canvas) { var expandedShape = elementRegistry.get('SubProcess_4'); + var collapsedPlane = canvas.findPlane(expandedShape); var childShape = elementRegistry.get('Task_2'); + var childPlane = canvas.findPlane(childShape); expect(expandedShape.collapsed).to.be.true; - expect(childShape.hidden).to.be.true; + expect(collapsedPlane).to.not.eql(childPlane); })); - it('should import expanded subProcess in lane', inject(function(elementRegistry) { + it('should import expanded subProcess in lane', inject(function(elementRegistry, canvas) { var expandedShape = elementRegistry.get('SubProcess_3'); + var expandedPlane = canvas.findPlane(expandedShape); var childShape = elementRegistry.get('StartEvent_2'); + var childPlane = canvas.findPlane(childShape); expect(expandedShape.collapsed).to.be.false; expect(childShape.hidden).to.be.false; + expect(expandedPlane).to.eql(childPlane); })); });