Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ Now the _end_ keyword is not displayed anymore in the label of these graphical n
- https://github.com/eclipse-syson/syson/issues/2058[#2058] [diagrams] Fix error when importing SysML snippets referencing unknown units which could make the resulting model inconsistent
- https://github.com/eclipse-syson/syson/issues/2053[#2053] [diagrams] Prevent incoming and outgoing graphical edges of a graphical `ForkNode` or `JoinNode` to point empty space.
- https://github.com/eclipse-syson/syson/issues/2059[#2059] [diagrams] Fix an issue where the _Add existing elements_ tool was not working correctly on the _action flow_ compartment of `ActionUsage` graphical nodes.
- https://github.com/eclipse-syson/syson/issues/2056[#2056] [diagams] Fix the user feedback when dropping an `Element` which is already exposed on a diagram.

=== Improvements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
Expand All @@ -28,21 +29,27 @@

import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput;
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload;
import org.eclipse.sirius.components.collaborative.diagrams.dto.InvokeSingleClickOnDiagramElementToolInput;
import org.eclipse.sirius.components.collaborative.diagrams.dto.InvokeSingleClickOnDiagramElementToolSuccessPayload;
import org.eclipse.sirius.components.collaborative.dto.CreateChildInput;
import org.eclipse.sirius.components.collaborative.dto.CreateChildSuccessPayload;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.core.api.IFeedbackMessageService;
import org.eclipse.sirius.components.core.api.IIdentityService;
import org.eclipse.sirius.components.core.api.IObjectSearchService;
import org.eclipse.sirius.components.diagrams.Diagram;
import org.eclipse.sirius.components.diagrams.Node;
import org.eclipse.sirius.components.diagrams.ViewModifier;
import org.eclipse.sirius.components.diagrams.tests.graphql.InvokeSingleClickOnDiagramElementToolMutationRunner;
import org.eclipse.sirius.components.diagrams.tests.graphql.PaletteQueryRunner;
import org.eclipse.sirius.components.diagrams.tests.navigation.DiagramNavigator;
import org.eclipse.sirius.components.graphql.tests.ExecuteEditingContextFunctionSuccessPayload;
import org.eclipse.sirius.components.representations.MessageLevel;
import org.eclipse.sirius.components.view.emf.diagram.IDiagramIdProvider;
import org.eclipse.sirius.web.tests.graphql.CreateChildMutationRunner;
import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState;
import org.eclipse.syson.AbstractIntegrationTests;
import org.eclipse.syson.GivenSysONServer;
import org.eclipse.syson.SysONTestsProperties;
import org.eclipse.syson.application.controllers.diagrams.checkers.CheckDiagramElementCount;
import org.eclipse.syson.application.controllers.diagrams.checkers.CheckNodeOnDiagram;
import org.eclipse.syson.application.controllers.diagrams.testers.DropFromExplorerTester;
Expand Down Expand Up @@ -79,7 +86,7 @@
* @author gdaniel
*/
@Transactional
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { SysONTestsProperties.NO_DEFAULT_LIBRARIES_PROPERTY })
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GVDropFromExplorerTests extends AbstractIntegrationTests {

@Autowired
Expand Down Expand Up @@ -112,8 +119,18 @@ public class GVDropFromExplorerTests extends AbstractIntegrationTests {
@Autowired
private CreateChildMutationRunner createChildMutationRunner;

@Autowired
private PaletteQueryRunner paletteQueryRunner;

@Autowired
private InvokeSingleClickOnDiagramElementToolMutationRunner invokeSingleClickOnDiagramElementToolMutationRunner;

@Autowired
private IFeedbackMessageService feedbackMessageService;

private final IDescriptionNameGenerator descriptionNameGenerator = new SDVDescriptionNameGenerator();


private Flux<DiagramRefreshedEventPayload> givenSubscriptionToDiagram() {
var diagramEventInput = new DiagramEventInput(UUID.randomUUID(),
GeneralViewAddExistingElementsTestProjectData.EDITING_CONTEXT_ID,
Expand Down Expand Up @@ -358,7 +375,7 @@ public void dropFromExplorerTwiceShouldNotExposeElementTwice() {
List<Object> messages = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[*]");
assertThat(messages).as("We should receive at least one message when dropping an already visible element").hasSizeGreaterThanOrEqualTo(1);
String messageBody = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[0].body");
assertThat(messageBody).isEqualTo("The element part1 is already visible in its parent General View");
assertThat(messageBody).isEqualTo("The element part1 is already visible in its parent Package 1");
String messageLevel = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[0].level");
assertThat(messageLevel).isEqualTo(MessageLevel.WARNING.toString());
};
Expand All @@ -376,6 +393,128 @@ public void dropFromExplorerTwiceShouldNotExposeElementTwice() {
.verify(Duration.ofSeconds(10));
}

@GivenSysONServer({ GeneralViewAddExistingElementsTestProjectData.SCRIPT_PATH })
@Test
@DisplayName("GIVEN a diagram WHEN dropping a semantic element from the explorer on various targets THEN the user gets the appropriate feedback message")
public void dropFromExplorerFeedback() {
AtomicReference<Diagram> diagram = new AtomicReference<>();
AtomicReference<String> packageNodeId = new AtomicReference<>();
AtomicReference<String> attributeNodeId = new AtomicReference<>();
AtomicReference<String> hideToolId = new AtomicReference<>();

String package1Id = GeneralViewAddExistingElementsTestProjectData.SemanticIds.PACKAGE1_ID;
String attributeDefinition1Id = GeneralViewAddExistingElementsTestProjectData.SemanticIds.ATTRIBUTE_DEFINITION_1_ID;

var flux = this.givenSubscriptionToDiagram();

Consumer<Object> initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram::set);

Runnable dropPackageOnDiagramBackground = () -> this.dropFromExplorer(diagram, null, package1Id, Optional.empty());

Consumer<Object> diagramWithPackageNodeConsumer = assertRefreshedDiagramThat(newDiagram -> {
new CheckDiagramElementCount(this.diagramComparator).hasNewNodeCount(1).check(diagram.get(), newDiagram);
var packageNode = new DiagramNavigator(newDiagram).nodeWithTargetObjectId(package1Id).getNode();
assertThat(packageNode).isNotNull();
packageNodeId.set(packageNode.getId());
diagram.set(newDiagram);
});

Runnable dropAttributeOnPackage = () -> this.dropFromExplorer(diagram, packageNodeId.get(), attributeDefinition1Id, Optional.empty());

Consumer<Object> diagramWithAttributeNodeConsumer = assertRefreshedDiagramThat(newDiagram -> {
// 3 new nodes: AttributeDefinition container and its 2 compartments
new CheckDiagramElementCount(this.diagramComparator).hasNewNodeCount(3).check(diagram.get(), newDiagram);
var attributeNode = new DiagramNavigator(newDiagram).nodeWithTargetObjectId(attributeDefinition1Id).getNode();
assertThat(attributeNode).isNotNull().extracting(Node::getState).isEqualTo(ViewModifier.Normal);
attributeNodeId.set(attributeNode.getId());
diagram.set(newDiagram);
});

Runnable getHideTool = () -> hideToolId.set(this.getQuickToolIdByLabel(diagram.get().getId(), attributeNodeId.get(), "Hide"));

Runnable dropAttributeOnDiagram = () -> this.dropFromExplorer(diagram,
null, attributeDefinition1Id,
Optional.of("The element AttributeDefinition1 is already visible in its parent Package1"));

Consumer<Object> diagramNotChangeConsumer = assertRefreshedDiagramThat(newDiagram -> {
new CheckDiagramElementCount(this.diagramComparator).check(diagram.get(), newDiagram);
diagram.set(newDiagram);
});

Runnable hideAttributeNode = () -> {
var input = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), GeneralViewAddExistingElementsTestProjectData.EDITING_CONTEXT_ID, diagram.get().getId(),
List.of(attributeNodeId.get()), hideToolId.get(), 0, 0, List.of());
var result = this.invokeSingleClickOnDiagramElementToolMutationRunner.run(input);
String typename = JsonPath.read(result.data(), "$.data.invokeSingleClickOnDiagramElementTool.__typename");
assertThat(typename).isEqualTo(InvokeSingleClickOnDiagramElementToolSuccessPayload.class.getSimpleName());
};

Consumer<Object> atributeNodeHiddenConsumer = assertRefreshedDiagramThat(newDiagram -> {
new CheckDiagramElementCount(this.diagramComparator).check(diagram.get(), newDiagram);
var attributeNode = new DiagramNavigator(newDiagram).nodeWithTargetObjectId(attributeDefinition1Id).getNode();
assertThat(attributeNode).isNotNull().extracting(Node::getState).isEqualTo(ViewModifier.Hidden);
diagram.set(newDiagram);
});

Runnable dropAttributeOnDiagramNoMessage = () -> this.dropFromExplorer(diagram, null, attributeDefinition1Id, Optional.empty());

Runnable dropAttributeOnPackageAgain = () -> this.dropFromExplorer(diagram, packageNodeId.get(), attributeDefinition1Id, Optional.empty());

Consumer<Object> diagramWithAttributeNodeRevealedConsumer = assertRefreshedDiagramThat(newDiagram -> {
new CheckDiagramElementCount(this.diagramComparator).check(diagram.get(), newDiagram);
var attributeNode = new DiagramNavigator(newDiagram).nodeWithTargetObjectId(GeneralViewAddExistingElementsTestProjectData.SemanticIds.ATTRIBUTE_DEFINITION_1_ID).getNode();
assertThat(attributeNode).isNotNull().extracting(Node::getState).isEqualTo(ViewModifier.Normal);
});

StepVerifier.create(flux)
.consumeNextWith(initialDiagramContentConsumer)
.then(dropPackageOnDiagramBackground)
.consumeNextWith(diagramWithPackageNodeConsumer)
.then(dropAttributeOnPackage)
.consumeNextWith(diagramWithAttributeNodeConsumer)
.then(getHideTool)
.then(dropAttributeOnDiagram)
.consumeNextWith(diagramNotChangeConsumer)
.then(hideAttributeNode)
.consumeNextWith(atributeNodeHiddenConsumer)
.then(dropAttributeOnDiagramNoMessage)
.consumeNextWith(diagramNotChangeConsumer)
.then(dropAttributeOnPackageAgain)
.consumeNextWith(diagramWithAttributeNodeRevealedConsumer)
.thenCancel()
.verify(Duration.ofSeconds(10_000));
}

private void dropFromExplorer(AtomicReference<Diagram> diagram, String targetId, String elementId, Optional<String> expectedWarning) {
// Workaround: clear the messages left by the previous tool's execution
this.feedbackMessageService.getFeedbackMessages().clear();
var result = this.dropFromExplorerTester.dropFromExplorer(GeneralViewAddExistingElementsTestProjectData.EDITING_CONTEXT_ID, diagram,
targetId, elementId);
List<Object> messages = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[*]");
if (expectedWarning.isPresent()) {
assertThat(messages).hasSize(1);
String messageBody = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[0].body");
assertThat(messageBody).isEqualTo(expectedWarning.get());
String messageLevel = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[0].level");
assertThat(messageLevel).isEqualTo(MessageLevel.WARNING.toString());
} else {
assertThat(messages).isEmpty();
}
}

private String getQuickToolIdByLabel(String diagramId, String nodeId, String toolName) {
Map<String, Object> variables = Map.of(
"editingContextId", GeneralViewAddExistingElementsTestProjectData.EDITING_CONTEXT_ID,
"representationId", diagramId,
"diagramElementIds", List.of(nodeId));
var result = this.paletteQueryRunner.run(variables);
List<String> labels = JsonPath.read(result.data(), "$.data.viewer.editingContext.representation.description.palette.quickAccessTools[*].label");
assertThat(labels).contains(toolName);
int toolIndex = labels.indexOf(toolName);
List<String> ids = JsonPath.read(result.data(), "$.data.viewer.editingContext.representation.description.palette.quickAccessTools[*].id");
return ids.get(toolIndex);
}

@GivenSysONServer({ GeneralViewEmptyTestProjectData.SCRIPT_PATH })
@Test
public void dropLibraryPackageFromExplorerOnDiagram() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.eclipse.sirius.components.collaborative.diagrams.dto.DropOnDiagramInput;
import org.eclipse.sirius.components.collaborative.diagrams.dto.DropOnDiagramSuccessPayload;
import org.eclipse.sirius.components.diagrams.Diagram;
import org.eclipse.sirius.components.diagrams.tests.navigation.DiagramNavigator;
import org.eclipse.sirius.components.graphql.tests.api.GraphQLResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -54,12 +53,9 @@ public void dropFromExplorerOnDiagramElement(String projectId, AtomicReference<D
}

public GraphQLResult dropFromExplorer(String projectId, AtomicReference<Diagram> diagram, String targetNodeId, String semanticElementId) {
DiagramNavigator diagramNavigator = new DiagramNavigator(diagram.get());
final String targetId;
String targetId = targetNodeId;
if (targetNodeId == null) {
targetId = diagram.get().getId();
} else {
targetId = diagramNavigator.nodeWithId(targetNodeId).getNode().getId();
}
var dropOnDiagramInput = new DropOnDiagramInput(
UUID.randomUUID(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2025 Obeo.
* Copyright (c) 2025, 2026 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -39,6 +39,10 @@ public static final class SemanticIds {

public static final String PACKAGE_1_ID = "8d4123ac-3ac5-412d-90f2-49282b923003";

public static final String PACKAGE1_ID = "98a777a3-15df-400f-a8d6-b5033e37e082";

public static final String ATTRIBUTE_DEFINITION_1_ID = "f42f0e49-8f00-49b4-b1ce-f4b0a98d3eb8";

public static final String GENERAL_VIEW_VIEW_USAGE_ID = "b67872fa-5900-48d3-88f0-e6ced193c8ec";

public static final String PART_1_ELEMENT_ID = "67a57df8-2995-41ea-a838-dfb3a9a8ee7f";
Expand Down
Loading
Loading