Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024, 2025 Obeo.
* Copyright (c) 2024, 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 @@ -69,6 +69,8 @@ public ISemanticChecker getElementInParentSemanticChecker(String parentLabel, ER
* a supplier that returns the id of the semantic object
* @param semanticChecker
* the checks that needs to be run
* @deprecated this function will be removed when all the tests will be migrated to follow the same format as Sirius Web.
* Please, use {@link SemanticCheckerService#checkElement(Class type, Supplier idSupplier, Consumer semanticChecker)} instead.
*/
public <T extends Element> void checkElement(Step<?> verifier, Class<T> type, Supplier<String> idSupplier, Consumer<T> semanticChecker) {
ISemanticChecker checker = editingContext -> {
Expand All @@ -82,6 +84,41 @@ public <T extends Element> void checkElement(Step<?> verifier, Class<T> type, Su
this.checkEditingContext(checker, verifier);
}

/**
* Provide a runnable that do some checks on the element identified by the given id.
*
* @param <T>
* the type element under test
* @param type
* the type of the element under test
* @param idSupplier
* a supplier that returns the id of the semantic object
* @param semanticChecker
* the checks that needs to be run
*/
public <T extends Element> Runnable checkElement(Class<T> type, Supplier<String> idSupplier, Consumer<T> semanticChecker) {
ISemanticChecker checker = editingContext -> {
Optional<Object> optElement = this.objectSearchService.getObject(editingContext, idSupplier.get());
assertThat(optElement).isPresent();
Object element = optElement.get();
assertThat(element).isInstanceOf(type);
T castedElement = type.cast(element);
semanticChecker.accept(castedElement);
};
return this.checkEditingContext(checker);
}

/**
* Runs semantic checks on the editing context and chains them to the provided verifier.
*
* @param semanticChecker
* the checker containing the semantic assertions to run
* @param verifier
* the {@link Step} verifier to chain the check execution to
* @deprecated this function will be removed when all the tests will be migrated to follow the same format as Sirius Web.
* Please, use {@link SemanticCheckerService#checkEditingContext(ISemanticChecker semanticChecker)} instead.
*/
@Deprecated
public void checkEditingContext(ISemanticChecker semanticChecker, Step<?> verifier) {
Runnable runnableChecker = this.semanticRunnableFactory.createRunnable(this.editingContextId,
(editingContext, executeEditingContextFunctionInput) -> {
Expand All @@ -92,4 +129,18 @@ public void checkEditingContext(ISemanticChecker semanticChecker, Step<?> verifi
verifier.then(runnableChecker);
}

/**
* Provide a runnable that run semantic checks on the editing context and chains them to the provided verifier.
*
* @param semanticChecker
* the checker containing the semantic assertions to run
*/
public Runnable checkEditingContext(ISemanticChecker semanticChecker) {
return this.semanticRunnableFactory.createRunnable(this.editingContextId,
(editingContext, executeEditingContextFunctionInput) -> {
semanticChecker.check(editingContext);
return new ExecuteEditingContextFunctionSuccessPayload(executeEditingContextFunctionInput.id(), true);
});
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024, 2025 Obeo.
* Copyright (c) 2024, 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 All @@ -13,6 +13,7 @@
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 static org.eclipse.sirius.components.diagrams.tests.assertions.DiagramInstanceOfAssertFactories.EDGE;
import static org.eclipse.sirius.components.diagrams.tests.assertions.DiagramInstanceOfAssertFactories.EDGE_STYLE;

Expand All @@ -22,6 +23,7 @@
import java.util.Optional;
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;
Expand All @@ -32,39 +34,33 @@
import org.eclipse.sirius.components.diagrams.Node;
import org.eclipse.sirius.components.diagrams.ViewModifier;
import org.eclipse.sirius.components.diagrams.tests.navigation.DiagramNavigator;
import org.eclipse.sirius.components.view.diagram.DiagramDescription;
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.GivenSysONServer;
import org.eclipse.syson.application.controller.editingContext.checkers.ISemanticChecker;
import org.eclipse.syson.application.controller.editingContext.checkers.SemanticCheckerService;
import org.eclipse.syson.application.controllers.diagrams.checkers.CheckDiagramElementCount;
import org.eclipse.syson.application.controllers.diagrams.checkers.DiagramCheckerService;
import org.eclipse.syson.application.controllers.diagrams.checkers.IDiagramChecker;
import org.eclipse.syson.application.controllers.diagrams.testers.EdgeCreationTester;
import org.eclipse.syson.application.data.GeneralViewWithTopNodesTestProjectData;
import org.eclipse.syson.services.SemanticRunnableFactory;
import org.eclipse.syson.services.diagrams.DiagramComparator;
import org.eclipse.syson.services.diagrams.DiagramDescriptionIdProvider;
import org.eclipse.syson.services.diagrams.api.IGivenDiagramDescription;
import org.eclipse.syson.services.diagrams.api.IGivenDiagramReference;
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.util.IDescriptionNameGenerator;
import org.eclipse.syson.util.SysONRepresentationDescriptionIdentifiers;
import org.junit.jupiter.api.AfterEach;
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;
import reactor.test.StepVerifier.Step;

/**
* Tests the creation of edges in the General View Diagram.
Expand All @@ -78,9 +74,6 @@ public class GVEdgeCreationTests extends AbstractIntegrationTests {
@Autowired
private IGivenInitialServerState givenInitialServerState;

@Autowired
private IGivenDiagramReference givenDiagram;

@Autowired
private IGivenDiagramDescription givenDiagramDescription;

Expand All @@ -102,58 +95,45 @@ public class GVEdgeCreationTests extends AbstractIntegrationTests {
@Autowired
private DiagramComparator diagramComparator;

private DiagramDescriptionIdProvider diagramDescriptionIdProvider;

private Step<DiagramRefreshedEventPayload> verifier;

private AtomicReference<Diagram> diagram;

private DiagramDescription diagramDescription;

private DiagramCheckerService diagramCheckerService;
private final IDescriptionNameGenerator descriptionNameGenerator = new SDVDescriptionNameGenerator();

private SemanticCheckerService semanticCheckerService;

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

@BeforeEach
public void setUp() {
this.givenInitialServerState.initialize();
var diagramEventInput = new DiagramEventInput(UUID.randomUUID(),
GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
GeneralViewWithTopNodesTestProjectData.GraphicalIds.DIAGRAM_ID);
var flux = this.givenDiagramSubscription.subscribe(diagramEventInput);
this.verifier = StepVerifier.create(flux);
this.diagram = this.givenDiagram.getDiagram(this.verifier);
this.diagramDescription = this.givenDiagramDescription.getDiagramDescription(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID);
this.diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(this.diagramDescription, this.diagramIdProvider);
this.diagramCheckerService = new DiagramCheckerService(this.diagramComparator, this.descriptionNameGenerator);
this.semanticCheckerService = new SemanticCheckerService(this.semanticRunnableFactory, this.objectSearchService, GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
GeneralViewWithTopNodesTestProjectData.SemanticIds.PACKAGE_1_ID);
}

@AfterEach
public void tearDown() {
if (this.verifier != null) {
this.verifier.thenCancel()
.verify(Duration.ofSeconds(10));
}
}

@DisplayName("GIVEN a General View with a PartUsage and an ActionUsage, WHEN linking the PartUsage and the Action with Add as nested Action edge tool, THEN the ActionUsage is now a child of the PartUsage and there is a composition edge between them.")
@Sql(scripts = { GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED))
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
@Test
public void createAddAsNestedEdge() {
String creationToolId = this.diagramDescriptionIdProvider.getEdgeCreationToolId(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getPartUsage()), "Add as nested Action");
this.verifier.then(() -> this.edgeCreationTester.createEdge(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
this.diagram,
var flux = this.givenSubscriptionToDiagram();

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

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

String creationToolId = diagramDescriptionIdProvider.getEdgeCreationToolId(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getPartUsage()), "Add as nested Action");
Runnable creationToolRunnable = () -> this.edgeCreationTester.createEdge(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
diagram,
"part",
"action",
creationToolId));
creationToolId);

Consumer<Object> diagramChecker = assertRefreshedDiagramThat(newDiagram -> {
var initialDiagram = diagram.get();

IDiagramChecker diagramChecker = (initialDiagram, newDiagram) -> {
new CheckDiagramElementCount(this.diagramComparator)
// 1 new node has been created in the "actions" compartment of the part.
// 1 new node has been created as nested tree node + 5 compartments
Expand All @@ -165,7 +145,7 @@ public void createAddAsNestedEdge() {
// Get the target with its description instead of its label: there are two new elements with the label
// "action" on the diagram (one on the diagram itself, and one in the "actions" compartment of the part
// element).
var nodeDescriptionId = this.diagramDescriptionIdProvider.getNodeDescriptionId(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getActionUsage()));
var nodeDescriptionId = diagramDescriptionIdProvider.getNodeDescriptionId(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getActionUsage()));
Optional<String> optionalTargetId = diagramNavigator.findAllNodes().stream()
.filter(node -> Objects.equals(node.getTargetObjectLabel(), "action"))
.filter(node -> Objects.equals(node.getDescriptionId(), nodeDescriptionId))
Expand All @@ -181,13 +161,19 @@ public void createAddAsNestedEdge() {
.hasTargetId(optionalTargetId.get())
.extracting(Edge::getStyle, EDGE_STYLE)
.hasSourceArrow(ArrowStyle.FillDiamond);
};

this.diagramCheckerService.checkDiagram(diagramChecker, this.diagram, this.verifier);
});

ISemanticChecker semanticChecker = this.semanticCheckerService.getElementInParentSemanticChecker("part", SysmlPackage.eINSTANCE.getNamespace_OwnedMember(),
SysmlPackage.eINSTANCE.getActionUsage());

this.semanticCheckerService.checkEditingContext(semanticChecker, this.verifier);
Runnable editingContextChecker = this.semanticCheckerService.checkEditingContext(semanticChecker);

StepVerifier.create(flux)
.consumeNextWith(initialDiagramContentConsumer)
.then(creationToolRunnable)
.consumeNextWith(diagramChecker)
.then(editingContextChecker)
.thenCancel()
.verify(Duration.ofSeconds(10));
}
}
6 changes: 3 additions & 3 deletions scripts/check-coverage.jsh
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ double checkCoverage(String module) {
}

record ModuleCoverage(String moduleName, double expectedCoverage) {}
double expectedGlobalCoverage = 68.0;
double expectedGlobalCoverage = 69.0;
var moduleCoverageData = List.of(
new ModuleCoverage("syson-application", 37.0),
new ModuleCoverage("syson-application-configuration", 72.0),
new ModuleCoverage("syson-application-configuration", 74.0),
new ModuleCoverage("syson-common-view", 100.0),
new ModuleCoverage("syson-diagram-common-view", 89.0),
new ModuleCoverage("syson-diagram-services", 82.0),
Expand All @@ -53,7 +53,7 @@ var moduleCoverageData = List.of(
new ModuleCoverage("syson-sysml-validation", 99.0),
new ModuleCoverage("syson-table-requirements-view", 77.0),
new ModuleCoverage("syson-table-services", 100.0),
new ModuleCoverage("syson-tree-explorer-view", 87.0),
new ModuleCoverage("syson-tree-explorer-view", 88.0),
new ModuleCoverage("syson-tree-services", 82.0)
);

Expand Down
Loading