Skip to content

Commit ae13828

Browse files
committed
[2108] Improve actor creation tool using the latest selection dialog changes
Bug: #2108 Signed-off-by: Guillaume Coutable <guillaume.coutable@obeo.fr>
1 parent ec39d4c commit ae13828

9 files changed

Lines changed: 350 additions & 72 deletions

File tree

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ As a result, the following GraphQL mutations have been removed `exposeRequiremen
3232

3333
=== Improvements
3434

35+
- https://github.com/eclipse-syson/syson/issues/2108[#2108] [diagrams] Leverage the latest change of the selection dialog to allow creating an actor without specialization.
3536

3637
=== New features
3738

backend/application/syson-application/src/test/java/org/eclipse/syson/application/controller/editingcontext/checkers/SemanticCheckerService.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ public ISemanticChecker getElementInParentSemanticChecker(String parentLabel, ER
5353
return this.getElementInParentSemanticChecker(parentLabel, containmentReference, childEClass, null);
5454
}
5555

56+
/**
57+
* Creates a semantic checker that should be checked in an editing context.
58+
*
59+
* @param parentLabel
60+
* The label of the parent element
61+
* @param containmentReference
62+
* The {@link EReference} that contains the element to check in the parent
63+
* @param childEClass
64+
* The expected child EClass
65+
* @param additionalCheckOnElement
66+
* A consumer to allow additional checking of the element.
67+
* The element can either be an object if the EReference is single valued, or a list of object if the referenced is multivalued.
68+
* @return the created semantic checker
69+
*/
5670
public ISemanticChecker getElementInParentSemanticChecker(String parentLabel, EReference containmentReference, EClass childEClass, Consumer<Object> additionalCheckOnElement) {
5771
return new CheckElementInParent(this.objectSearchService, this.rootElementId)
5872
.withParentLabel(parentLabel)
@@ -75,7 +89,7 @@ public ISemanticChecker getElementInParentSemanticChecker(String parentLabel, ER
7589
* @param semanticChecker
7690
* the checks that needs to be run
7791
* @deprecated this function will be removed when all the tests will be migrated to follow the same format as Sirius Web.
78-
* Please, use {@link SemanticCheckerService#checkElement(Class type, Supplier idSupplier, Consumer semanticChecker)} instead.
92+
* Please, use {@link SemanticCheckerService#checkElement(Class type, Supplier idSupplier, Consumer semanticChecker)}instead.
7993
*/
8094
@Deprecated
8195
public <T extends Element> void checkElement(Step<?> verifier, Class<T> type, Supplier<String> idSupplier, Consumer<T> semanticChecker) {

backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVSubNodeAnalysisCreationTests.java

Lines changed: 110 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
package org.eclipse.syson.application.controllers.diagrams.general.view;
1414

1515
import static org.assertj.core.api.Assertions.assertThat;
16+
import static org.assertj.core.api.InstanceOfAssertFactories.type;
1617
import static org.eclipse.sirius.components.diagrams.tests.DiagramEventPayloadConsumer.assertRefreshedDiagramThat;
1718
import static org.junit.jupiter.api.Assertions.assertFalse;
1819

@@ -58,13 +59,15 @@
5859
import org.eclipse.syson.sysml.Element;
5960
import org.eclipse.syson.sysml.PartUsage;
6061
import org.eclipse.syson.sysml.ReferenceUsage;
62+
import org.eclipse.syson.sysml.Specialization;
6163
import org.eclipse.syson.sysml.Subsetting;
6264
import org.eclipse.syson.sysml.SysmlPackage;
6365
import org.eclipse.syson.sysml.Type;
6466
import org.eclipse.syson.sysml.helper.EMFUtils;
6567
import org.eclipse.syson.util.IDescriptionNameGenerator;
6668
import org.eclipse.syson.util.SysONRepresentationDescriptionIdentifiers;
6769
import org.junit.jupiter.api.BeforeEach;
70+
import org.junit.jupiter.api.DisplayName;
6871
import org.junit.jupiter.api.Test;
6972
import org.junit.jupiter.params.ParameterizedTest;
7073
import org.junit.jupiter.params.provider.Arguments;
@@ -501,30 +504,48 @@ public void createNewDefinitionSubjectInUseCaseUsage() {
501504
this.createSubjectWithFeatureTypingInCaseUsage(SysmlPackage.eINSTANCE.getUseCaseUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.USE_CASE_USAGE_ID, USE_CASE);
502505
}
503506

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

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

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

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

535+
@DisplayName("GIVEN a Case, WHEN creating a new Actor without selection, THEN the Actor without specialization is created in the Case")
536+
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
537+
@Test
538+
public void createNewActorWithoutSpecializationInCaseUsage() {
539+
this.createActorWithoutSpecializationInCaseUsage(SysmlPackage.eINSTANCE.getCaseUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.CASE_USAGE_ID, CASE);
540+
}
541+
542+
@DisplayName("GIVEN a UseCase, WHEN creating a new Actor without selection, THEN the Actor without specialization is created in the UseCase")
543+
@GivenSysONServer({ GeneralViewWithTopNodesTestProjectData.SCRIPT_PATH })
544+
@Test
545+
public void createNewActorWithoutSpecializationInUseCaseUsage() {
546+
this.createActorWithoutSpecializationInCaseUsage(SysmlPackage.eINSTANCE.getUseCaseUsage(), GeneralViewWithTopNodesTestProjectData.SemanticIds.USE_CASE_USAGE_ID, USE_CASE);
547+
}
548+
528549
private void createSubjectWithSubsettingInCaseUsage(EClass caseUsageSubclass, String targetObjectId, String parentLabel) {
529550
var flux = this.givenSubscriptionToDiagram();
530551

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

679-
Runnable createNodeRunnable = this.creationTestsService.createNode(diagramDescriptionIdProvider, diagram, caseUsageSubclass, targetObjectId, creationToolName, variables);
698+
Runnable createNodeRunnable = this.creationTestsService.createNodeWithSelectionDialogWithSingleSelection(diagramDescriptionIdProvider, diagram, caseUsageSubclass, targetObjectId, creationToolName, existingPartId);
680699

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

690-
ISemanticChecker semanticChecker = (editingContext) -> {
691-
Object semanticRootObject = this.objectSearchService.getObject(editingContext, GeneralViewWithTopNodesTestProjectData.SemanticIds.PACKAGE_1_ID).orElse(null);
692-
assertThat(semanticRootObject).isInstanceOf(Element.class);
693-
Element semanticRootElement = (Element) semanticRootObject;
694-
Optional<PartUsage> optActor = EMFUtils.allContainedObjectOfType(semanticRootElement, PartUsage.class)
695-
.filter(element -> Objects.equals(element.getName(), "actor1"))
696-
.findFirst();
697-
assertThat(optActor).isPresent();
698-
var actor = optActor.get();
699-
EList<Subsetting> subjectSubsets = actor.getOwnedSubsetting();
700-
assertFalse(subjectSubsets.isEmpty());
701-
assertThat(subjectSubsets.get(0).getSubsettedFeature().getName()).isEqualTo("part");
709+
Consumer<Object> additionalCheck = referencedObject -> {
710+
assertThat(referencedObject).isInstanceOf(List.class)
711+
.asInstanceOf(type(List.class))
712+
.satisfies(actors -> {
713+
assertThat(actors).size().isEqualTo(1);
714+
assertThat(actors.getFirst())
715+
.isInstanceOf(PartUsage.class)
716+
.asInstanceOf(type(PartUsage.class))
717+
.satisfies(actor -> {
718+
EList<Subsetting> subjectSubsets = actor.getOwnedSubsetting();
719+
assertThat(subjectSubsets).isNotEmpty();
720+
assertThat(subjectSubsets.get(0).getSubsettedFeature().getName()).isEqualTo("part");
721+
});
722+
});
702723
};
703-
Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(this.semanticCheckerService.getElementInParentSemanticChecker(parentLabel, containmentReference, childEClass));
704-
Runnable semanticCheck2 = this.semanticCheckerService.checkEditingContext(semanticChecker);
724+
725+
Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(this.semanticCheckerService.getElementInParentSemanticChecker(parentLabel, containmentReference, childEClass, additionalCheck));
705726

706727
StepVerifier.create(flux)
707728
.consumeNextWith(initialDiagramContentConsumer)
708729
.then(createNodeRunnable)
709730
.consumeNextWith(diagramCheck)
710731
.then(semanticCheck)
711-
.then(semanticCheck2)
712732
.thenCancel()
713733
.verify(Duration.ofSeconds(10));
714734
}
@@ -726,11 +746,9 @@ private void createActorWithFeatureTypingInCaseUsage(EClass caseUsageSubclass, S
726746
EClass childEClass = SysmlPackage.eINSTANCE.getPartUsage();
727747
String creationToolName = "New Actor";
728748
EReference containmentReference = SysmlPackage.eINSTANCE.getCaseUsage_ActorParameter();
729-
List<ToolVariable> variables = new ArrayList<>();
730749
String existingPartDefId = GeneralViewWithTopNodesTestProjectData.SemanticIds.PART_DEFINITION_ID;
731-
variables.add(new ToolVariable("selectedObject", existingPartDefId, ToolVariableType.OBJECT_ID));
732750

733-
Runnable createNodeRunnable = this.creationTestsService.createNode(diagramDescriptionIdProvider, diagram, caseUsageSubclass, targetObjectId, creationToolName, variables);
751+
Runnable createNodeRunnable = this.creationTestsService.createNodeWithSelectionDialogWithSingleSelection(diagramDescriptionIdProvider, diagram, caseUsageSubclass, targetObjectId, creationToolName, existingPartDefId);
734752

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

744-
ISemanticChecker semanticChecker = (editingContext) -> {
745-
Object semanticRootObject = this.objectSearchService.getObject(editingContext, GeneralViewWithTopNodesTestProjectData.SemanticIds.PACKAGE_1_ID).orElse(null);
746-
assertThat(semanticRootObject).isInstanceOf(Element.class);
747-
Element semanticRootElement = (Element) semanticRootObject;
748-
Optional<PartUsage> optActor = EMFUtils.allContainedObjectOfType(semanticRootElement, PartUsage.class)
749-
.filter(element -> Objects.equals(element.getName(), "actor1"))
750-
.findFirst();
751-
assertThat(optActor).isPresent();
752-
var actor = optActor.get();
753-
EList<Type> types = actor.getType();
754-
assertFalse(types.isEmpty());
755-
assertThat(types.get(0).getName()).isEqualTo("PartDefinition");
762+
Consumer<Object> additionalCheck = referencedObject -> {
763+
assertThat(referencedObject).isInstanceOf(List.class)
764+
.asInstanceOf(type(List.class))
765+
.satisfies(actors -> {
766+
assertThat(actors).size().isEqualTo(1);
767+
assertThat(actors.getFirst())
768+
.isInstanceOf(PartUsage.class)
769+
.asInstanceOf(type(PartUsage.class))
770+
.satisfies(actor -> {
771+
EList<Type> types = actor.getType();
772+
assertThat(types).isNotEmpty();
773+
assertThat(types.get(0).getName()).isEqualTo("PartDefinition");
774+
});
775+
});
756776
};
757-
Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(this.semanticCheckerService.getElementInParentSemanticChecker(parentLabel, containmentReference, childEClass));
758-
Runnable semanticCheck2 = this.semanticCheckerService.checkEditingContext(semanticChecker);
777+
778+
Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(this.semanticCheckerService.getElementInParentSemanticChecker(parentLabel, containmentReference, childEClass, additionalCheck));
779+
780+
StepVerifier.create(flux)
781+
.consumeNextWith(initialDiagramContentConsumer)
782+
.then(createNodeRunnable)
783+
.consumeNextWith(diagramCheck)
784+
.then(semanticCheck)
785+
.thenCancel()
786+
.verify(Duration.ofSeconds(10));
787+
}
788+
789+
private void createActorWithoutSpecializationInCaseUsage(EClass caseUsageSubclass, String targetObjectId, String parentLabel) {
790+
var flux = this.givenSubscriptionToDiagram();
791+
792+
AtomicReference<Diagram> diagram = new AtomicReference<>();
793+
Consumer<Object> initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram::set);
794+
795+
var diagramDescription = this.givenDiagramDescription.getDiagramDescription(GeneralViewWithTopNodesTestProjectData.EDITING_CONTEXT_ID,
796+
SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID);
797+
var diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(diagramDescription, this.diagramIdProvider);
798+
799+
EClass childEClass = SysmlPackage.eINSTANCE.getPartUsage();
800+
String creationToolName = "New Actor";
801+
EReference containmentReference = SysmlPackage.eINSTANCE.getCaseUsage_ActorParameter();
802+
803+
Runnable createNodeRunnable = this.creationTestsService.createNodeWithSelectionDialogWithoutSelectionProvided(diagramDescriptionIdProvider, diagram, caseUsageSubclass, targetObjectId, creationToolName);
804+
805+
Consumer<Object> diagramCheck = assertRefreshedDiagramThat(newDiagram -> {
806+
var initialDiagram = diagram.get();
807+
int createdNodesExpectedCount = 1;
808+
new CheckDiagramElementCount(this.diagramComparator)
809+
.hasNewNodeCount(createdNodesExpectedCount)
810+
.hasNewEdgeCount(1)
811+
.check(initialDiagram, newDiagram, true);
812+
});
813+
814+
Consumer<Object> additionalCheck = referencedObject -> {
815+
assertThat(referencedObject).isInstanceOf(List.class)
816+
.asInstanceOf(type(List.class))
817+
.satisfies(actors -> {
818+
assertThat(actors).size().isEqualTo(1);
819+
assertThat(actors.getFirst())
820+
.isInstanceOf(PartUsage.class)
821+
.asInstanceOf(type(PartUsage.class))
822+
.satisfies(actor -> {
823+
assertThat(actor.getOwnedSpecialization()).allMatch(Specialization::isIsImplied);
824+
EList<Type> types = actor.getType();
825+
assertThat(types)
826+
.isNotEmpty()
827+
.allMatch(Element::isIsLibraryElement);
828+
});
829+
});
830+
};
831+
832+
Runnable semanticCheck = this.semanticCheckerService.checkEditingContext(this.semanticCheckerService.getElementInParentSemanticChecker(parentLabel, containmentReference, childEClass, additionalCheck));
759833

760834
StepVerifier.create(flux)
761835
.consumeNextWith(initialDiagramContentConsumer)
762836
.then(createNodeRunnable)
763837
.consumeNextWith(diagramCheck)
764838
.then(semanticCheck)
765-
.then(semanticCheck2)
766839
.thenCancel()
767840
.verify(Duration.ofSeconds(10));
768841
}

0 commit comments

Comments
 (0)