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 @@ -55,6 +55,7 @@ This fix ensure that imported models containing, for example, a top-level `Libra
- https://github.com/eclipse-syson/syson/issues/1857[#1857] [diagrams] Fix an issue where existing graphical node could disappear when new graphical node was created.
- https://github.com/eclipse-syson/syson/issues/1865[#1865] [explorer] Fix focus loss on some characters in the _New object from text_ modal.
- https://github.com/eclipse-syson/syson/issues/1876[#1876] [explorer] Fix potential NPE when trying to delete elements with associated `EAnnotations` from the _Explorer_.
- https://github.com/eclipse-syson/syson/issues/1858[#1858] [diagrams] Fix an issue where a new graphical node could be located inside the wrong graphical container.

=== Improvements

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/*******************************************************************************
* Copyright (c) 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
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.syson.application.controllers.diagrams.general.view;

import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.sirius.components.diagrams.tests.DiagramEventPayloadConsumer.assertRefreshedDiagramThat;

import java.time.Duration;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;

import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput;
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload;
import org.eclipse.sirius.components.diagrams.ViewModifier;
import org.eclipse.sirius.components.diagrams.tests.navigation.DiagramNavigator;
import org.eclipse.sirius.components.view.emf.diagram.IDiagramIdProvider;
import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState;
import org.eclipse.syson.AbstractIntegrationTests;
import org.eclipse.syson.application.controllers.diagrams.testers.ToolTester;
import org.eclipse.syson.application.data.GeneralViewWithTopNodesTestProjectData;
import org.eclipse.syson.services.diagrams.DiagramDescriptionIdProvider;
import org.eclipse.syson.services.diagrams.api.IGivenDiagramDescription;
import org.eclipse.syson.services.diagrams.api.IGivenDiagramSubscription;
import org.eclipse.syson.standard.diagrams.view.SDVDescriptionNameGenerator;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.sysml.helper.LabelConstants;
import org.eclipse.syson.util.IDescriptionNameGenerator;
import org.eclipse.syson.util.SysONRepresentationDescriptionIdentifiers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.SqlConfig;
import org.springframework.transaction.annotation.Transactional;

import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;

/**
* PortUsage related-tests in the General View diagram.
*
* @author arichard
*/
@Transactional
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GVPortUsageTests extends AbstractIntegrationTests {

private static final String PACKAGE = "Package";

private static final String PACKAGE1 = "Package1";

@Autowired
private IGivenInitialServerState givenInitialServerState;

@Autowired
private IGivenDiagramSubscription givenDiagramSubscription;

@Autowired
private IGivenDiagramDescription givenDiagramDescription;

@Autowired
private IDiagramIdProvider diagramIdProvider;

@Autowired
private ToolTester toolTester;

private final IDescriptionNameGenerator descriptionNameGenerator = new SDVDescriptionNameGenerator();

private Flux<DiagramRefreshedEventPayload> givenSubscriptionToDiagram() {
var diagramEventInput = new DiagramEventInput(UUID.randomUUID(),
GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
GeneralViewWithTopNodesTestProjectData.GraphicalIds.DIAGRAM_ID);
var flux = this.givenDiagramSubscription.subscribe(diagramEventInput);
return flux;
}

@BeforeEach
public void beforeEach() {
this.givenInitialServerState.initialize();
}

@DisplayName("GIVEN a diagram with a Package, a SubPackage with a PartDefinition, WHEN a PortUsage is created from the PartDefinition, THEN the new PortUsage is visible as border node and hidden a sibling node of the PartDefinition node")
@Sql(scripts = { GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD,
config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED))
@Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED))
@Test
public void testCreatePortInSubPackage() {
var flux = this.givenSubscriptionToDiagram();

var diagramDescription = this.givenDiagramDescription.getDiagramDescription(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID);
var diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(diagramDescription, this.diagramIdProvider);

var newPackageToolId = diagramDescriptionIdProvider.getNodeToolId(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getPackage()), "New Package");
assertThat(newPackageToolId).as("The tool 'New Package' should exist on the Package").isNotNull();

var newPartDefToolId = diagramDescriptionIdProvider.getNodeToolId(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getPackage()), "New Part Definition");
assertThat(newPartDefToolId).as("The tool 'New Part Definition' should exist on the Package").isNotNull();

var newPortUsageToolId = diagramDescriptionIdProvider.getNodeToolId(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getPartDefinition()), "New Port");
assertThat(newPortUsageToolId).as("The tool 'New Port' should exist on the PartDefinition").isNotNull();

var diagramId = new AtomicReference<String>();
var packageNodeId = new AtomicReference<String>();
var subPackageNodeId = new AtomicReference<String>();
var partDefNodeId = new AtomicReference<String>();

Consumer<Object> initialDiagramContentConsumer = assertRefreshedDiagramThat(diag -> {
diagramId.set(diag.getId());
var packageNode = new DiagramNavigator(diag).nodeWithLabel(PACKAGE).getNode();
packageNodeId.set(packageNode.getId());
assertThat(packageNode.getChildNodes()).hasSize(0);
assertThat(new DiagramNavigator(diag).findDiagramEdgeCount()).isEqualTo(3);
});

Runnable newPackageTool = () -> this.toolTester.invokeTool(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID, diagramId.get(), packageNodeId.get(), newPackageToolId,
List.of());

Consumer<Object> updatedDiagramContentConsumerAfterNewPkg = assertRefreshedDiagramThat(diag -> {
var subPackageNode = new DiagramNavigator(diag).nodeWithLabel(PACKAGE).childNodeWithLabel(PACKAGE1).getNode();
assertThat(subPackageNode).isNotNull();
subPackageNodeId.set(subPackageNode.getId());
});

Runnable newPartDefTool = () -> this.toolTester.invokeTool(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID, diagramId.get(), subPackageNodeId.get(), newPartDefToolId,
List.of());

Consumer<Object> updatedDiagramContentConsumerAfterNewPartDef = assertRefreshedDiagramThat(diag -> {
var partDefNode = new DiagramNavigator(diag).nodeWithLabel(PACKAGE).childNodeWithLabel(PACKAGE1)
.childNodeWithLabel(LabelConstants.OPEN_QUOTE + "part def" + LabelConstants.CLOSE_QUOTE + LabelConstants.CR + "PartDefinition1").getNode();
assertThat(partDefNode).isNotNull();
assertThat(partDefNode.getBorderNodes()).hasSize(0);
partDefNodeId.set(partDefNode.getId());
});

Runnable newPortUsageTool = () -> this.toolTester.invokeTool(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID, diagramId.get(), partDefNodeId.get(), newPortUsageToolId,
List.of());

Consumer<Object> updatedDiagramContentConsumerAfterNewPortUsage = assertRefreshedDiagramThat(diag -> {
var pkgNode = new DiagramNavigator(diag).nodeWithLabel(PACKAGE).getNode();
assertThat(pkgNode.getChildNodes()).hasSize(1);

var partDefNode = new DiagramNavigator(diag).nodeWithLabel(PACKAGE).childNodeWithLabel(PACKAGE1)
.childNodeWithLabel(LabelConstants.OPEN_QUOTE + "part def" + LabelConstants.CLOSE_QUOTE + LabelConstants.CR + "PartDefinition1").getNode();
assertThat(partDefNode).isNotNull();

assertThat(partDefNode.getBorderNodes()).hasSize(1);
assertThat(partDefNode.getBorderNodes().get(0).getState()).isEqualTo(ViewModifier.Normal);
assertThat(partDefNode.getBorderNodes().get(0).getOutsideLabels().get(0).text()).isEqualTo("port1");

var port1Node = new DiagramNavigator(diag).nodeWithLabel(PACKAGE).childNodeWithLabel(PACKAGE1)
.childNodeWithLabel(LabelConstants.OPEN_QUOTE + "port" + LabelConstants.CLOSE_QUOTE + LabelConstants.CR + "port1").getNode();
assertThat(port1Node).isNotNull();
assertThat(port1Node.getState()).isEqualTo(ViewModifier.Hidden);
});

StepVerifier.create(flux)
.consumeNextWith(initialDiagramContentConsumer)
.then(newPackageTool)
.consumeNextWith(updatedDiagramContentConsumerAfterNewPkg)
.then(newPartDefTool)
.consumeNextWith(updatedDiagramContentConsumerAfterNewPartDef)
.then(newPortUsageTool)
.consumeNextWith(updatedDiagramContentConsumerAfterNewPortUsage)
.thenCancel()
.verify(Duration.ofSeconds(100));
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.eclipse.syson.sysml.Namespace;
import org.eclipse.syson.sysml.NamespaceImport;
import org.eclipse.syson.sysml.Package;
import org.eclipse.syson.sysml.PortUsage;
import org.eclipse.syson.sysml.ReferenceUsage;
import org.eclipse.syson.sysml.StateDefinition;
import org.eclipse.syson.sysml.StateUsage;
Expand Down Expand Up @@ -107,12 +106,6 @@ public Boolean casePackage(Package object) {
return !this.isIndirectNestedNode(object) && !ViewDefinitionKind.isActionFlowView(this.kind) && !ViewDefinitionKind.isStateTransitionView(this.kind);
}

@Override
public Boolean casePortUsage(PortUsage object) {
// For PortUsages we don't want tree Nodes on InterconnectionView, ActionFlow View or StateTransition View.
return ViewDefinitionKind.isGeneralView(this.kind);
}

@Override
public Boolean caseReferenceUsage(ReferenceUsage object) {
// For ReferenceUsage we don't want nested Nodes, no matter the type of ViewDefinition.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ The following structure is not yet handled `connection bus : C connect (d1, d2,

** Fix an issue where the creation of an `Element` inside a `sub-Package` created two graphical nodes instead of one.
** Fix an issue where the creation of an `Element` inside a `sub-Package` could hide unrelated graphical nodes.
** Fix an issue where a new graphical node could be located inside the wrong graphical container.

* In _Explorer_ view:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ export class PlaywrightNode {

async revealElement(name: string) {
await this.nodeLocator.hover({ position: { x: 10, y: 10 }, timeout: 3000 });
await this.page.getByTestId('manage-visibility').isVisible();
await this.page
.getByTestId('manage-visibility')
.locator('> svg')
Expand Down
Loading