Skip to content

Commit 211f5ee

Browse files
committed
[1602] Unable to DnD a RequirementUsage with no DeclaredName on GV
Bug: #1602 Signed-off-by: Arthur Daussy <arthur.daussy@obeo.fr>
1 parent 6597064 commit 211f5ee

7 files changed

Lines changed: 182 additions & 70 deletions

File tree

CHANGELOG.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313
=== Bug fixes
1414

15+
- https://github.com/eclipse-syson/syson/issues/1602[#1602] [diagrams] Fix an issue where the drag and drop of a `RequirementUsage` (or any other `Element`) with a declared short name but no declared name from the _Explorer_ view to a diagram was not possible.
16+
17+
1518
=== Improvements
1619

1720
=== New features

backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVAddExistingElementsTests.java

Lines changed: 104 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.eclipse.syson.services.diagrams.api.IGivenDiagramReference;
4040
import org.eclipse.syson.services.diagrams.api.IGivenDiagramSubscription;
4141
import org.eclipse.syson.util.SysONRepresentationDescriptionIdentifiers;
42+
import org.jetbrains.annotations.NotNull;
4243
import org.junit.jupiter.api.AfterEach;
4344
import org.junit.jupiter.api.BeforeEach;
4445
import org.junit.jupiter.api.Test;
@@ -136,14 +137,16 @@ public void addExistingElementsOnDiagram() {
136137
Consumer<DiagramRefreshedEventPayload> updatedDiagramConsumer = payload -> Optional.of(payload)
137138
.map(DiagramRefreshedEventPayload::diagram)
138139
.ifPresentOrElse(newDiagram -> {
139-
assertThat(newDiagram.getNodes()).as("3 nodes should be visible on the diagram").hasSize(3);
140+
assertThat(newDiagram.getNodes()).as("3 nodes should be visible on the diagram").hasSize(4);
140141
assertThat(newDiagram.getNodes())
141142
.as(MessageFormat.format(NODE_SHOULD_BE_ON_DIAGRAM_MESSAGE, PACKAGE1))
142143
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), PACKAGE1))
143144
.as(MessageFormat.format(NODE_SHOULD_BE_ON_DIAGRAM_MESSAGE, ACTION1))
144145
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), ACTION1))
145146
.as(MessageFormat.format(NODE_SHOULD_BE_ON_DIAGRAM_MESSAGE, PART1))
146-
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), PART1));
147+
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), PART1))
148+
.as(MessageFormat.format(NODE_SHOULD_BE_ON_DIAGRAM_MESSAGE, "RequirementUsage"))
149+
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), "RequirementUsage"));
147150
}, () -> fail("Missing diagram"));
148151
this.verifier.consumeNextWith(updatedDiagramConsumer);
149152

@@ -161,7 +164,7 @@ public void addExistingElementsRecursiveOnDiagram() {
161164
Consumer<DiagramRefreshedEventPayload> updatedDiagramConsumer = payload -> Optional.of(payload)
162165
.map(DiagramRefreshedEventPayload::diagram)
163166
.ifPresentOrElse(newDiagram -> {
164-
assertThat(newDiagram.getNodes()).as("6 nodes should be visible on the diagram").hasSize(6);
167+
assertThat(newDiagram.getNodes()).as("6 nodes should be visible on the diagram").hasSize(7);
165168
assertThat(newDiagram.getEdges().stream().filter(e -> ViewModifier.Normal.equals(e.getState())).toList())
166169
.as("3 edges should be visible on the diagram")
167170
.hasSize(3)
@@ -179,78 +182,115 @@ public void addExistingElementsRecursiveOnDiagram() {
179182
.as(MessageFormat.format(NODE_SHOULD_BE_ON_DIAGRAM_MESSAGE, PART1))
180183
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), PART1))
181184
.as(MessageFormat.format(NODE_SHOULD_BE_ON_DIAGRAM_MESSAGE, PART2))
182-
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), PART2));
183-
184-
var optPackageNode = newDiagram.getNodes().stream()
185-
.filter(n -> Objects.equals(n.getTargetObjectLabel(), PACKAGE1))
186-
.findFirst();
187-
assertThat(optPackageNode).isPresent();
188-
assertThat(optPackageNode.get().getChildNodes())
189-
.as("Node " + PACKAGE1 + " should contain 1 child")
190-
.hasSize(1)
191-
.as("Node " + ATTRIBUTE_DEFINITION + " should exist inside " + PACKAGE1)
192-
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), ATTRIBUTE_DEFINITION));
193-
194-
var optAction1Node = newDiagram.getNodes().stream()
195-
.filter(n -> Objects.equals(n.getTargetObjectLabel(), ACTION1))
196-
.findFirst();
197-
assertThat(optAction1Node).isPresent();
198-
var action1Node = optAction1Node.get();
199-
var action1ActionsCompartment = this.getCompartment(action1Node, "actions");
200-
assertThat(action1ActionsCompartment)
201-
.as(ACTION1 + " should contain an actions compartment")
202-
.isPresent();
203-
assertThat(action1ActionsCompartment.get().getChildNodes())
204-
.as(ACTION1 + " actions compartment should contain 1 child")
205-
.hasSize(1)
206-
.as(ACTION1 + " actions compartment should contain " + ACTION2)
207-
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), ACTION2));
208-
209-
var action1ActionFlowCompartment = this.getCompartment(action1Node, "action flow");
210-
assertThat(action1ActionFlowCompartment)
211-
.as(ACTION1 + " should contain an action flow compartment")
212-
.isPresent();
213-
assertThat(action1ActionFlowCompartment.get().getChildNodes())
214-
.as(ACTION1 + " action flow compartment should contain 2 children")
215-
.hasSize(1) // @technical-debt should be 2 when start node will be synchronized
216-
.as(ACTION1 + " action flow compartment should contain " + ACTION2)
217-
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), ACTION2))
218-
;
185+
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), PART2))
186+
.as(MessageFormat.format(NODE_SHOULD_BE_ON_DIAGRAM_MESSAGE, "RequirementUsage"))
187+
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), "RequirementUsage"));
188+
189+
checkPackageNode(newDiagram);
190+
191+
219192
// @technical-debt enable this part when start node will be synchronized
220193
// .as(ACTION1 + " action flow compartment should contain a start node")
221194
// .anyMatch(n -> n.getStyle() instanceof ImageNodeStyle imageStyle &&
222195
// Objects.equals(imageStyle.getImageURL(), "images/start_action.svg")
223196
// && Objects.equals("start", n.getTargetObjectLabel()));
224197

225-
var optAction2Node = action1ActionFlowCompartment.get().getChildNodes().stream()
226-
.filter(n -> Objects.equals(n.getTargetObjectLabel(), ACTION2))
227-
.findFirst();
228-
assertThat(optAction2Node).isPresent();
229-
var action2Node = optAction2Node.get();
230-
var action2ActionsCompartment = this.getCompartment(action2Node, "actions");
231-
assertThat(action2ActionsCompartment)
232-
.as(ACTION2 + " should contain an actions compartment")
233-
.isPresent();
234-
assertThat(action2ActionsCompartment.get().getChildNodes())
235-
.as(ACTION2 + " actions compartment should contain 1 child")
236-
.hasSize(1)
237-
.as(ACTION2 + " actions compartment should contain " + ACTION3)
238-
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), ACTION3));
239-
240-
var action2ActionFlowCompartment = this.getCompartment(action2Node, "action flow");
241-
assertThat(action2ActionFlowCompartment)
242-
.as(ACTION2 + " should contain an action flow compartment")
243-
.isPresent();
244-
assertThat(action2ActionFlowCompartment.get().getChildNodes())
245-
.as(ACTION2 + " action flow compartment should contain 1 child")
246-
.hasSize(1)
247-
.as(ACTION2 + " action flow compartment should contain " + ACTION3)
248-
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), ACTION3));
198+
checkAction2(action1ActionFlowCompartment);
199+
200+
checkRequirementUsage(newDiagram);
249201

250202
}, () -> fail("Missing diagram"));
251203
this.verifier.consumeNextWith(updatedDiagramConsumer);
252204
}
253205

206+
private void checkPackageNode(Diagram newDiagram) {
207+
var optPackageNode = newDiagram.getNodes().stream()
208+
.filter(n -> Objects.equals(n.getTargetObjectLabel(), PACKAGE1))
209+
.findFirst();
210+
assertThat(optPackageNode).isPresent();
211+
assertThat(optPackageNode.get().getChildNodes())
212+
.as("Node " + PACKAGE1 + " should contain 1 child")
213+
.hasSize(1)
214+
.as("Node " + ATTRIBUTE_DEFINITION + " should exist inside " + PACKAGE1)
215+
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), ATTRIBUTE_DEFINITION));
216+
}
217+
218+
private void checkAction2(Diagram newDiagram) {
219+
220+
var action1ActionFlowCompartment = checkAction1(newDiagram);
221+
var optAction2Node = action1ActionFlowCompartment.getChildNodes().stream()
222+
.filter(n -> Objects.equals(n.getTargetObjectLabel(), ACTION2))
223+
.findFirst();
224+
assertThat(optAction2Node).isPresent();
225+
var action2Node = optAction2Node.get();
226+
var action2ActionsCompartment = this.getCompartment(action2Node, "actions");
227+
assertThat(action2ActionsCompartment)
228+
.as(ACTION2 + " should contain an actions compartment")
229+
.isPresent();
230+
assertThat(action2ActionsCompartment.get().getChildNodes())
231+
.as(ACTION2 + " actions compartment should contain 1 child")
232+
.hasSize(1)
233+
.as(ACTION2 + " actions compartment should contain " + ACTION3)
234+
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), ACTION3));
235+
236+
var action2ActionFlowCompartment = this.getCompartment(action2Node, "action flow");
237+
assertThat(action2ActionFlowCompartment)
238+
.as(ACTION2 + " should contain an action flow compartment")
239+
.isPresent();
240+
assertThat(action2ActionFlowCompartment.get().getChildNodes())
241+
.as(ACTION2 + " action flow compartment should contain 1 child")
242+
.hasSize(1)
243+
.as(ACTION2 + " action flow compartment should contain " + ACTION3)
244+
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), ACTION3));
245+
}
246+
247+
private @NotNull Node checkAction1(Diagram newDiagram) {
248+
var optAction1Node = newDiagram.getNodes().stream()
249+
.filter(n -> Objects.equals(n.getTargetObjectLabel(), ACTION1))
250+
.findFirst();
251+
assertThat(optAction1Node).isPresent();
252+
var action1Node = optAction1Node.get();
253+
var action1ActionsCompartment = this.getCompartment(action1Node, "actions");
254+
assertThat(action1ActionsCompartment)
255+
.as(ACTION1 + " should contain an actions compartment")
256+
.isPresent();
257+
assertThat(action1ActionsCompartment.get().getChildNodes())
258+
.as(ACTION1 + " actions compartment should contain 1 child")
259+
.hasSize(1)
260+
.as(ACTION1 + " actions compartment should contain " + ACTION2)
261+
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), ACTION2));
262+
263+
var action1ActionFlowCompartment = this.getCompartment(action1Node, "action flow");
264+
assertThat(action1ActionFlowCompartment)
265+
.as(ACTION1 + " should contain an action flow compartment")
266+
.isPresent();
267+
assertThat(action1ActionFlowCompartment.get().getChildNodes())
268+
.as(ACTION1 + " action flow compartment should contain 2 children")
269+
.hasSize(1) // @technical-debt should be 2 when start node will be synchronized
270+
.as(ACTION1 + " action flow compartment should contain " + ACTION2)
271+
.anyMatch(n -> Objects.equals(n.getTargetObjectLabel(), ACTION2));
272+
return action1ActionFlowCompartment.get();
273+
}
274+
275+
private void checkRequirementUsage(Diagram newDiagram) {
276+
var optRequirementNode = newDiagram.getNodes().stream()
277+
.filter(n -> Objects.equals(n.getTargetObjectId(), GeneralViewAddExistingElementsTestProjectData.SemanticIds.SN_REQUIREMENT_ELEMENT_ID))
278+
.findFirst();
279+
280+
assertThat(optRequirementNode).isPresent();
281+
assertThat(optRequirementNode.get().getChildNodes())
282+
.as("Node RequirementUsage should contain 6 children")
283+
.hasSize(8);
284+
285+
var requirementDocCompartment = this.getCompartment(optRequirementNode.get(), "doc");
286+
assertThat(requirementDocCompartment).isPresent();
287+
assertThat(requirementDocCompartment.get())
288+
.as("The doc compartment should be visible")
289+
.matches(node -> !node.getModifiers().contains(ViewModifier.Hidden))
290+
.as("The doc compartment should contain a document item")
291+
.matches(node -> node.getChildNodes().size() == 1);
292+
}
293+
254294
private Optional<Node> getCompartment(Node node, String compartmentName) {
255295
return node.getChildNodes().stream()
256296
.filter(n -> Objects.equals(n.getInsideLabel().getText(), compartmentName))

backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVDropFromExplorerTests.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import org.eclipse.syson.util.SysONRepresentationDescriptionIdentifiers;
5858
import org.junit.jupiter.api.AfterEach;
5959
import org.junit.jupiter.api.BeforeEach;
60+
import org.junit.jupiter.api.DisplayName;
6061
import org.junit.jupiter.api.Test;
6162
import org.springframework.beans.factory.annotation.Autowired;
6263
import org.springframework.boot.test.context.SpringBootTest;
@@ -194,6 +195,54 @@ public void dropFromExplorerOnEmptyDiagram() {
194195

195196
}
196197

198+
@Sql(scripts = { GeneralViewAddExistingElementsTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD,
199+
config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED))
200+
@Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED))
201+
@Test
202+
@DisplayName("GIVEN an Element with no declared name but having a declared short name, WHEN drag and dropping this element on a diagram, THEN graphical node should be created")
203+
public void dropFromExplorerShortNameOnlyOnEmptyDiagram() {
204+
this.verifier.then(() -> {
205+
assertThat(this.diagram.get().getNodes()).hasSize(1);
206+
Node emptyDiagramNode = this.diagram.get().getNodes().get(0);
207+
String emptyDiagramNodeDescriptionId = this.diagramDescriptionIdProvider.getNodeDescriptionId(GeneralViewEmptyDiagramNodeDescriptionProvider.NAME);
208+
// Ensure the existing node is the "empty diagram" one.
209+
assertThat(emptyDiagramNode).hasDescriptionId(emptyDiagramNodeDescriptionId);
210+
this.dropFromExplorerTester.dropFromExplorerOnDiagram(GeneralViewAddExistingElementsTestProjectData.EDITING_CONTEXT_ID, this.diagram,
211+
GeneralViewAddExistingElementsTestProjectData.SemanticIds.SN_REQUIREMENT_ELEMENT_ID);
212+
});
213+
214+
Consumer<DiagramRefreshedEventPayload> updatedDiagramConsumer = payload -> Optional.of(payload)
215+
.map(DiagramRefreshedEventPayload::diagram)
216+
.ifPresentOrElse(newDiagram -> {
217+
new CheckDiagramElementCount(this.diagramComparator)
218+
.hasNewEdgeCount(0)
219+
// 1 node for the Requirement and 8 for its compartments and one for the documentation
220+
.hasNewNodeCount(10)
221+
.check(this.diagram.get(), newDiagram);
222+
new CheckNodeOnDiagram(this.diagramDescriptionIdProvider, this.diagramComparator)
223+
.hasNodeDescriptionName(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getRequirementUsage()))
224+
.hasTargetObjectLabel("RequirementUsage")
225+
.hasCompartmentCount(8)
226+
.check(this.diagram.get(), newDiagram);
227+
}, () -> fail("Missing diagram"));
228+
229+
this.verifier.consumeNextWith(updatedDiagramConsumer);
230+
231+
Runnable exposedElementsChecker = this.semanticRunnableFactory.createRunnable(GeneralViewAddExistingElementsTestProjectData.EDITING_CONTEXT_ID,
232+
(editingContext, executeEditingContextFunctionInput) -> {
233+
ViewUsage generalViewViewUsage = this.objectSearchService.getObject(editingContext, GeneralViewAddExistingElementsTestProjectData.SemanticIds.GENERAL_VIEW_VIEW_USAGE_ID)
234+
.filter(ViewUsage.class::isInstance)
235+
.map(ViewUsage.class::cast)
236+
.orElse(null);
237+
assertThat(generalViewViewUsage).isNotNull();
238+
assertThat(generalViewViewUsage.getExposedElement()).hasSize(1);
239+
return new ExecuteEditingContextFunctionSuccessPayload(executeEditingContextFunctionInput.id(), true);
240+
});
241+
242+
this.verifier.then(exposedElementsChecker);
243+
244+
}
245+
197246
@Sql(scripts = { GeneralViewAddExistingElementsTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD,
198247
config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED))
199248
@Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED))

backend/application/syson-application/src/test/java/org/eclipse/syson/application/data/GeneralViewAddExistingElementsTestProjectData.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public static final class SemanticIds {
4343

4444
public static final String PART_1_ELEMENT_ID = "67a57df8-2995-41ea-a838-dfb3a9a8ee7f";
4545

46+
public static final String SN_REQUIREMENT_ELEMENT_ID = "10a86ba3-aa07-4f0b-9aef-55ebc0e95347";
47+
4648
public static final String SUCCESSION_START_ACTION_2_IDS = "18d6f2fc-2182-4217-8da2-bf68c36ffa41";
4749
}
4850

0 commit comments

Comments
 (0)