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 @@ -32,6 +32,7 @@ As a result, the following GraphQL mutations have been removed `exposeRequiremen

=== Improvements

- https://github.com/eclipse-syson/syson/issues/2108[#2108] [diagrams] Leverage the latest change of the selection dialog to allow creating an `Actor` graphical node without specialization.

=== New features

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@ public ISemanticChecker getElementInParentSemanticChecker(String parentLabel, ER
return this.getElementInParentSemanticChecker(parentLabel, containmentReference, childEClass, null);
}

/**
* Creates a semantic checker that should be checked in an editing context.
*
* @param parentLabel
* The label of the parent element
* @param containmentReference
* The {@link EReference} that contains the element to check in the parent
* @param childEClass
* The expected child EClass
* @param additionalCheckOnElement
* A consumer to allow additional checking of the element.
* The element can either be an object if the EReference is single valued, or a list of object if the referenced is multivalued.
* @return the created semantic checker
*/
public ISemanticChecker getElementInParentSemanticChecker(String parentLabel, EReference containmentReference, EClass childEClass, Consumer<Object> additionalCheckOnElement) {
return new CheckElementInParent(this.objectSearchService, this.rootElementId)
.withParentLabel(parentLabel)
Expand All @@ -75,7 +89,7 @@ public ISemanticChecker getElementInParentSemanticChecker(String parentLabel, ER
* @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.
* Please, use {@link SemanticCheckerService#checkElement(Class type, Supplier idSupplier, Consumer semanticChecker)}instead.
*/
@Deprecated
public <T extends Element> void checkElement(Step<?> verifier, Class<T> type, Supplier<String> idSupplier, Consumer<T> semanticChecker) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.eclipse.syson.application.controllers.diagrams.general.view;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.InstanceOfAssertFactories.type;
import static org.eclipse.sirius.components.diagrams.tests.DiagramEventPayloadConsumer.assertRefreshedDiagramThat;
import static org.junit.jupiter.api.Assertions.assertFalse;

Expand Down Expand Up @@ -58,13 +59,15 @@
import org.eclipse.syson.sysml.Element;
import org.eclipse.syson.sysml.PartUsage;
import org.eclipse.syson.sysml.ReferenceUsage;
import org.eclipse.syson.sysml.Specialization;
import org.eclipse.syson.sysml.Subsetting;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.sysml.Type;
import org.eclipse.syson.sysml.helper.EMFUtils;
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.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
Expand Down Expand Up @@ -501,30 +504,48 @@ public void createNewDefinitionSubjectInUseCaseUsage() {
this.createSubjectWithFeatureTypingInCaseUsage(SysmlPackage.eINSTANCE.getUseCaseUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.USE_CASE_USAGE_ID, USE_CASE);
}

@DisplayName("GIVEN a Case, WHEN creating a new Actor selecting a Part, THEN the Actor subsetted by the Part is created in the Case")
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
@Test
public void createNewActorWithSubsettingInCaseUsage() {
this.createActorWithSubsettingInCaseUsage(SysmlPackage.eINSTANCE.getCaseUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.CASE_USAGE_ID, CASE);
}

@DisplayName("GIVEN a UseCase, WHEN creating a new Actor selecting a Part, THEN the Actor subsetted by the Part is created in the UseCase")
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
@Test
public void createNewActorWithSubsettingInUseCaseUsage() {
this.createActorWithSubsettingInCaseUsage(SysmlPackage.eINSTANCE.getUseCaseUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.USE_CASE_USAGE_ID, USE_CASE);
}

@DisplayName("GIVEN a Case, WHEN creating a new Actor selecting a PartDefinition, THEN the Actor typed by the PartDefinition is created in the Case")
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
@Test
public void createNewActorWithFeatureTypingInCaseUsage() {
this.createActorWithFeatureTypingInCaseUsage(SysmlPackage.eINSTANCE.getCaseUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.CASE_USAGE_ID, CASE);
}

@DisplayName("GIVEN a UseCase, WHEN creating a new Actor selecting a PartDefinition, THEN the Actor typed by the PartDefinition is created in the UseCase")
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
@Test
public void createNewActorWithFeatureTypingInUseCaseUsage() {
this.createActorWithFeatureTypingInCaseUsage(SysmlPackage.eINSTANCE.getUseCaseUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.USE_CASE_USAGE_ID, USE_CASE);
}

@DisplayName("GIVEN a Case, WHEN creating a new Actor without selection, THEN the Actor without specialization is created in the Case")
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
@Test
public void createNewActorWithoutSpecializationInCaseUsage() {
this.createActorWithoutSpecializationInCaseUsage(SysmlPackage.eINSTANCE.getCaseUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.CASE_USAGE_ID, CASE);
}

@DisplayName("GIVEN a UseCase, WHEN creating a new Actor without selection, THEN the Actor without specialization is created in the UseCase")
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
@Test
public void createNewActorWithoutSpecializationInUseCaseUsage() {
this.createActorWithoutSpecializationInCaseUsage(SysmlPackage.eINSTANCE.getUseCaseUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.USE_CASE_USAGE_ID, USE_CASE);
}

private void createSubjectWithSubsettingInCaseUsage(EClass caseUsageSubclass, String targetObjectId, String parentLabel) {
var flux = this.givenSubscriptionToDiagram();

Expand Down Expand Up @@ -672,11 +693,9 @@ private void createActorWithSubsettingInCaseUsage(EClass caseUsageSubclass, Stri
EClass childEClass = SysmlPackage.eINSTANCE.getPartUsage();
String creationToolName = "New Actor";
EReference containmentReference = SysmlPackage.eINSTANCE.getCaseUsage_ActorParameter();
List<ToolVariable> variables = new ArrayList<>();
String existingPartId = "2c5fe5a5-18fe-40f4-ab66-a2d91ab7df6a";
variables.add(new ToolVariable("selectedObject", existingPartId, ToolVariableType.OBJECT_ID));
String existingPartId = GeneralViewWithTopNodesTestProjectData.SemanticIds.PART_USAGE_ID;

Runnable createNodeRunnable = this.creationTestsService.createNode(diagramDescriptionIdProvider, diagram, caseUsageSubclass, targetObjectId, creationToolName, variables);
Runnable createNodeRunnable = this.creationTestsService.createNodeWithSelectionDialogWithSingleSelection(diagramDescriptionIdProvider, diagram, caseUsageSubclass, targetObjectId, creationToolName, existingPartId);

Consumer<Object> diagramCheck = assertRefreshedDiagramThat(newDiagram -> {
var initialDiagram = diagram.get();
Expand All @@ -687,28 +706,29 @@ private void createActorWithSubsettingInCaseUsage(EClass caseUsageSubclass, Stri
.check(initialDiagram, newDiagram, true);
});

ISemanticChecker semanticChecker = (editingContext) -> {
Object semanticRootObject = this.objectSearchService.getObject(editingContext, GeneralViewWithTopNodesTestProjectData.SemanticIds.PACKAGE_1_ID).orElse(null);
assertThat(semanticRootObject).isInstanceOf(Element.class);
Element semanticRootElement = (Element) semanticRootObject;
Optional<PartUsage> optActor = EMFUtils.allContainedObjectOfType(semanticRootElement, PartUsage.class)
.filter(element -> Objects.equals(element.getName(), "actor1"))
.findFirst();
assertThat(optActor).isPresent();
var actor = optActor.get();
EList<Subsetting> subjectSubsets = actor.getOwnedSubsetting();
assertFalse(subjectSubsets.isEmpty());
assertThat(subjectSubsets.get(0).getSubsettedFeature().getName()).isEqualTo("part");
Consumer<Object> additionalCheck = referencedObject -> {
assertThat(referencedObject).isInstanceOf(List.class)
.asInstanceOf(type(List.class))
.satisfies(actors -> {
assertThat(actors).size().isEqualTo(1);
assertThat(actors.getFirst())
.isInstanceOf(PartUsage.class)
.asInstanceOf(type(PartUsage.class))
.satisfies(actor -> {
EList<Subsetting> subjectSubsets = actor.getOwnedSubsetting();
assertThat(subjectSubsets).isNotEmpty();
assertThat(subjectSubsets.get(0).getSubsettedFeature().getName()).isEqualTo("part");
});
});
};
Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(this.semanticCheckerService.getElementInParentSemanticChecker(parentLabel, containmentReference, childEClass));
Runnable semanticCheck2 = this.semanticCheckerService.checkEditingContext(semanticChecker);

Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(this.semanticCheckerService.getElementInParentSemanticChecker(parentLabel, containmentReference, childEClass, additionalCheck));

StepVerifier.create(flux)
.consumeNextWith(initialDiagramContentConsumer)
.then(createNodeRunnable)
.consumeNextWith(diagramCheck)
.then(semanticCheck)
.then(semanticCheck2)
.thenCancel()
.verify(Duration.ofSeconds(10));
}
Expand All @@ -726,11 +746,9 @@ private void createActorWithFeatureTypingInCaseUsage(EClass caseUsageSubclass, S
EClass childEClass = SysmlPackage.eINSTANCE.getPartUsage();
String creationToolName = "New Actor";
EReference containmentReference = SysmlPackage.eINSTANCE.getCaseUsage_ActorParameter();
List<ToolVariable> variables = new ArrayList<>();
String existingPartDefId = GeneralViewWithTopNodesTestProjectData.SemanticIds.PART_DEFINITION_ID;
variables.add(new ToolVariable("selectedObject", existingPartDefId, ToolVariableType.OBJECT_ID));

Runnable createNodeRunnable = this.creationTestsService.createNode(diagramDescriptionIdProvider, diagram, caseUsageSubclass, targetObjectId, creationToolName, variables);
Runnable createNodeRunnable = this.creationTestsService.createNodeWithSelectionDialogWithSingleSelection(diagramDescriptionIdProvider, diagram, caseUsageSubclass, targetObjectId, creationToolName, existingPartDefId);

Consumer<Object> diagramCheck = assertRefreshedDiagramThat(newDiagram -> {
var initialDiagram = diagram.get();
Expand All @@ -741,28 +759,83 @@ private void createActorWithFeatureTypingInCaseUsage(EClass caseUsageSubclass, S
.check(initialDiagram, newDiagram, true);
});

ISemanticChecker semanticChecker = (editingContext) -> {
Object semanticRootObject = this.objectSearchService.getObject(editingContext, GeneralViewWithTopNodesTestProjectData.SemanticIds.PACKAGE_1_ID).orElse(null);
assertThat(semanticRootObject).isInstanceOf(Element.class);
Element semanticRootElement = (Element) semanticRootObject;
Optional<PartUsage> optActor = EMFUtils.allContainedObjectOfType(semanticRootElement, PartUsage.class)
.filter(element -> Objects.equals(element.getName(), "actor1"))
.findFirst();
assertThat(optActor).isPresent();
var actor = optActor.get();
EList<Type> types = actor.getType();
assertFalse(types.isEmpty());
assertThat(types.get(0).getName()).isEqualTo("PartDefinition");
Consumer<Object> additionalCheck = referencedObject -> {
assertThat(referencedObject).isInstanceOf(List.class)
.asInstanceOf(type(List.class))
.satisfies(actors -> {
assertThat(actors).size().isEqualTo(1);
assertThat(actors.getFirst())
.isInstanceOf(PartUsage.class)
.asInstanceOf(type(PartUsage.class))
.satisfies(actor -> {
EList<Type> types = actor.getType();
assertThat(types).isNotEmpty();
assertThat(types.get(0).getName()).isEqualTo("PartDefinition");
});
});
};
Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(this.semanticCheckerService.getElementInParentSemanticChecker(parentLabel, containmentReference, childEClass));
Runnable semanticCheck2 = this.semanticCheckerService.checkEditingContext(semanticChecker);

Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(this.semanticCheckerService.getElementInParentSemanticChecker(parentLabel, containmentReference, childEClass, additionalCheck));

StepVerifier.create(flux)
.consumeNextWith(initialDiagramContentConsumer)
.then(createNodeRunnable)
.consumeNextWith(diagramCheck)
.then(semanticCheck)
.thenCancel()
.verify(Duration.ofSeconds(10));
}

private void createActorWithoutSpecializationInCaseUsage(EClass caseUsageSubclass, String targetObjectId, String parentLabel) {
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);

EClass childEClass = SysmlPackage.eINSTANCE.getPartUsage();
String creationToolName = "New Actor";
EReference containmentReference = SysmlPackage.eINSTANCE.getCaseUsage_ActorParameter();

Runnable createNodeRunnable = this.creationTestsService.createNodeWithSelectionDialogWithoutSelectionProvided(diagramDescriptionIdProvider, diagram, caseUsageSubclass, targetObjectId, creationToolName);

Consumer<Object> diagramCheck = assertRefreshedDiagramThat(newDiagram -> {
var initialDiagram = diagram.get();
int createdNodesExpectedCount = 1;
new CheckDiagramElementCount(this.diagramComparator)
.hasNewNodeCount(createdNodesExpectedCount)
.hasNewEdgeCount(1)
.check(initialDiagram, newDiagram, true);
});

Consumer<Object> additionalCheck = referencedObject -> {
assertThat(referencedObject).isInstanceOf(List.class)
.asInstanceOf(type(List.class))
.satisfies(actors -> {
assertThat(actors).size().isEqualTo(1);
assertThat(actors.getFirst())
.isInstanceOf(PartUsage.class)
.asInstanceOf(type(PartUsage.class))
.satisfies(actor -> {
assertThat(actor.getOwnedSpecialization()).allMatch(Specialization::isIsImplied);
EList<Type> types = actor.getType();
assertThat(types)
.isNotEmpty()
.allMatch(Element::isIsLibraryElement);
});
});
};

Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(this.semanticCheckerService.getElementInParentSemanticChecker(parentLabel, containmentReference, childEClass, additionalCheck));

StepVerifier.create(flux)
.consumeNextWith(initialDiagramContentConsumer)
.then(createNodeRunnable)
.consumeNextWith(diagramCheck)
.then(semanticCheck)
.then(semanticCheck2)
.thenCancel()
.verify(Duration.ofSeconds(10));
}
Expand Down
Loading
Loading