-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactoring: decouple DI from businessObject #1473
Conversation
fe3bc35
to
d36f05a
Compare
I overlooked some issues in the create/Replace behavior of Collapsible Shapes and will fix it EDIT: done |
39f62b7
to
46d3422
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great change overall.
I like in particular how straight forward this is and that you introduced a utility to use consistently to retrieve the DI. 💪
46d3422
to
12818ce
Compare
As this is a breaking change extensions may rely on, one last question before we merge this: What is our story for backwards compatibility / allowing users to gracefully update? I could imagine two things:
|
67776a3
to
3a77942
Compare
I added the breaking changes to the changelog. For throwing an error: where would be a good place to start looking into it? Ideally, we would have a Accessor on the business Object. As far as I can tell, they are created in bpmn-moddle and we would have to modify our code everywhere in bpmn-js where new ones are created (import, new elements, replace(?), ...). |
We did establish the relationship here and could make that a property that throws.
My personal opinion is: It does make sense to be verbose about it. |
Thanks for the hint! I decided to create the error in the Good thing we did it, because I also found 2 places where we still accessed the di incorrectly. |
I hope I selected the correct files to add the tests to 🤞 I kept the previous commit to make it clear what has changed, the commit history should probably be cleaned up anyway before we merge it. |
Thanks for your continued follow-ups. The last thing I'm wondering: How could the tests not detect the DI miss-use? I'll look into your last changes tomorrow and see if we're merge-ready. |
Regarding the tests: we used the (wrong) Should we also assert that connectionDi exists in the test cases? Here is the line where
|
Let us do that, to verify tests do not accidentally pass again. We can do so in a // given
...
// assume
expect(connectionDi).to.exist;
// when
... It is a pattern that we use in our code base. |
92548e9
to
d3fc471
Compare
In the diagram `di` is now accessed via the diagram element, not the business object. This has the benefit that elements in multiple diagrams can easily be represented. Related to #1472 BREAKING CHANGE: * Instead of referencing the `di` from the business object, reference it from the diagram element representing it.
46cb456
to
77f872c
Compare
This has the benefit of using the public API method across our code base.
Complex copy and paste test may otherwise timeout on GitHub actions.
* import * label updating (creation) * label paste
lib/features/modeling/BpmnUpdater.js
Outdated
@@ -405,6 +410,11 @@ BpmnUpdater.prototype.updateDiParent = function(di, parentDi) { | |||
return; | |||
} | |||
|
|||
// Cover the case where di.$parent === undefined and parentDi === null | |||
if (!parentDi && !di.$parent) { | |||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When does this case occur and do we have a test case for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This happens when we replace a Task with an expanded sub-process. The newly created Start event has a di.$parent = null
.
We don't test this explicitly, but tests like this check if we can replace Tasks with expanded sub-processes
bpmn-js/test/spec/features/modeling/behavior/SubProcessStartEventBehaviorSpec.js
Lines 29 to 47 in 194b963
it('should add start event child to subprocess', inject( | |
function(elementRegistry, bpmnReplace) { | |
// given | |
var task = elementRegistry.get('Task_1'), | |
expandedSubProcess, | |
startEvents; | |
// when | |
expandedSubProcess = bpmnReplace.replaceElement(task, { | |
type: 'bpmn:SubProcess', | |
isExpanded: true | |
}); | |
// then | |
startEvents = getChildStartEvents(expandedSubProcess); | |
expect(startEvents).to.have.length(1); | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for that explaination.
But then, why did it not blow up in the past? I'll investigate and report back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The root cause here is that DI updating is now broken on replace and makes that quick fix necessary. I'll continue to investigate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is the issue. We cannot blindly re-use the existing DI on replace but must continue to create a new one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise the following will happen:
- Task (to be replaced) gets removed
- DI (of task and replaced element) is being unlinked
- Replaced element does not have a proper DI reference anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests for proper DI updating after replace (BpmnReplaceSpec
) are missing entirely and need to be added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've cleaned up the commit history on this one, added additional test coverage for label wiring (was non-existing in a few places) and found two other small gotchas that I've cleaned up.
At this point, there is one last comment from my side remaining.
Looks great overall. We should proceed and get this out of the door.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found the last bug ™️.
Please have a look. We're light on DI update test coverage, this is why this one did not blow up on your PR.
Found the root-cause: When creating elements in the elementFactory, we supported passing an Object with We should probably fix this, but I'm not sure what's the best way:
2 and 3 would be a change to the API, but feel cleaner than overloading the attribute |
It is safe to use See also |
Also, we do a similar |
expect(createdEvent).to.eql(startEvent); | ||
expect(createdEvent).to.exist; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The BpmnReplace
will now always create a new di
and shape
. This is the only place where we checked if it's the same, all other tests just test for an existing new shape as well:
bpmn-js/test/spec/features/modeling/behavior/ReplaceElementBehaviourSpec.js
Lines 474 to 491 in fc2201a
inject(function(elementRegistry, modeling, elementFactory) { | |
// given | |
var subProcess = elementRegistry.get('SubProcess_3'), | |
startEvent = elementFactory.createShape( | |
{ type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:TimerEventDefinition' }), | |
id = startEvent.businessObject.id; | |
// when | |
modeling.createElements( | |
startEvent, { x: subProcess.x + 30, y: subProcess.y + 30 }, subProcess); | |
// then | |
var createdEvent = elementRegistry.get(id); | |
expect(createdEvent).to.exist; | |
expect(createdEvent.businessObject.eventDefinitions).to.not.exist; | |
}) |
fc2201a
to
47d1fa0
Compare
This fixes the existing DI creation methods in `BpmnFactory` and simplifies the related `ElementFactory` code that relied on it. In the past args got ignored and passing attrs to the created DI was not possible, now it is. BREAKING CHANGE: With this change the following `BpmnFactory` API methods got reworked to take (businessObject, attrs) as an input: * `BpmnFactory#createDiEdge` * `BpmnFactory#createDiShape` * `BpmnFactory#createDiPlane`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added another minor cleanup on top.
Let us merge this and fix things that are left open later on 🎉.
closes #1472