diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controller/editingContext/checkers/SemanticCheckerService.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controller/editingContext/checkers/SemanticCheckerService.java index f78d1dbe8..660d4adb9 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controller/editingContext/checkers/SemanticCheckerService.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controller/editingContext/checkers/SemanticCheckerService.java @@ -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 @@ -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 void checkElement(Step verifier, Class type, Supplier idSupplier, Consumer semanticChecker) { ISemanticChecker checker = editingContext -> { @@ -82,6 +84,41 @@ public void checkElement(Step verifier, Class type, Su this.checkEditingContext(checker, verifier); } + /** + * Provide a runnable that do some checks on the element identified by the given id. + * + * @param + * 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 Runnable checkElement(Class type, Supplier idSupplier, Consumer semanticChecker) { + ISemanticChecker checker = editingContext -> { + Optional 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) -> { @@ -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); + }); + } + } diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVEdgeCreationTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVEdgeCreationTests.java index 880f4c405..2abb4b6a1 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVEdgeCreationTests.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVEdgeCreationTests.java @@ -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 @@ -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; @@ -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; @@ -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. @@ -78,9 +74,6 @@ public class GVEdgeCreationTests extends AbstractIntegrationTests { @Autowired private IGivenInitialServerState givenInitialServerState; - @Autowired - private IGivenDiagramReference givenDiagram; - @Autowired private IGivenDiagramDescription givenDiagramDescription; @@ -102,58 +95,45 @@ public class GVEdgeCreationTests extends AbstractIntegrationTests { @Autowired private DiagramComparator diagramComparator; - private DiagramDescriptionIdProvider diagramDescriptionIdProvider; - - private Step verifier; - - private AtomicReference diagram; - - private DiagramDescription diagramDescription; - - private DiagramCheckerService diagramCheckerService; + private final IDescriptionNameGenerator descriptionNameGenerator = new SDVDescriptionNameGenerator(); private SemanticCheckerService semanticCheckerService; - private final IDescriptionNameGenerator descriptionNameGenerator = new SDVDescriptionNameGenerator(); + private Flux 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 = new AtomicReference<>(); + Consumer 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 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 @@ -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 optionalTargetId = diagramNavigator.findAllNodes().stream() .filter(node -> Objects.equals(node.getTargetObjectLabel(), "action")) .filter(node -> Objects.equals(node.getDescriptionId(), nodeDescriptionId)) @@ -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)); } } diff --git a/scripts/check-coverage.jsh b/scripts/check-coverage.jsh index 9326a8963..fddf3bd45 100755 --- a/scripts/check-coverage.jsh +++ b/scripts/check-coverage.jsh @@ -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), @@ -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) );