From 80476e78abc9b9a353fdfe5c06bf9cf787a8bf5e Mon Sep 17 00:00:00 2001 From: Florian Lambers <fl462057@fh-muenster.de> Date: Thu, 2 Dec 2021 17:45:52 +0100 Subject: [PATCH] added constraint validation to frontend, added flag setting --- .../Testgenerator/bpmn/data/BPMNTestcase.java | 9 +++ .../bpmn/data/VariableValue.java | 13 ++++ .../migration/MigrationService.java | 13 +++- .../rest/dto/BPMNTestcaseDTO.java | 10 +++ .../Testgenerator/rest/dto/ConstraintDTO.java | 33 ++++++++++ .../rest/service/change/ChangeController.java | 21 ++++-- .../service/converters/TestConverter.java | 8 ++- .../rest/service/test/TestController.java | 24 ++++++- .../rest/service/test/TestService.java | 33 ++++++++-- .../Testgenerator/utils/BPMNParseUtils.java | 4 ++ .../testgenerator-web/src/app/app.module.ts | 6 +- .../app/components/flag/flag.component.css | 0 .../app/components/flag/flag.component.html | 5 ++ .../components/flag/flag.component.spec.ts | 25 ++++++++ .../src/app/components/flag/flag.component.ts | 17 +++++ .../app/components/flow/flow.component.html | 1 + .../app/components/flows/flows.component.html | 5 +- .../app/components/test/test.component.html | 39 +++++++---- .../src/app/components/test/test.component.ts | 64 +++++++++++++++++-- .../src/app/models/bpmn-testcase.ts | 1 + .../src/app/models/constraint.ts | 4 ++ .../src/app/models/variable-value.ts | 2 + .../pipes/variable-constraints.pipe.spec.ts | 8 +++ .../app/pipes/variable-constraints.pipe.ts | 21 ++++++ 24 files changed, 332 insertions(+), 34 deletions(-) create mode 100644 Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/dto/ConstraintDTO.java create mode 100644 testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.css create mode 100644 testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.html create mode 100644 testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.spec.ts create mode 100644 testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.ts create mode 100644 testgenerator-web/testgenerator-web/src/app/models/constraint.ts create mode 100644 testgenerator-web/testgenerator-web/src/app/pipes/variable-constraints.pipe.spec.ts create mode 100644 testgenerator-web/testgenerator-web/src/app/pipes/variable-constraints.pipe.ts diff --git a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/bpmn/data/BPMNTestcase.java b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/bpmn/data/BPMNTestcase.java index 325c885..28506a0 100644 --- a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/bpmn/data/BPMNTestcase.java +++ b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/bpmn/data/BPMNTestcase.java @@ -11,6 +11,7 @@ public class BPMNTestcase { private List<EndCheck> endChecks; private List<String> mocks; private int priority; + private String flag; public BPMNTestcase() { this.taskVariableList = new ArrayList<>(); @@ -71,4 +72,12 @@ public class BPMNTestcase { public void setPriority(int priority) { this.priority = priority; } + + public String getFlag() { + return flag; + } + + public void setFlag(String flag) { + this.flag = flag; + } } diff --git a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/bpmn/data/VariableValue.java b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/bpmn/data/VariableValue.java index f489152..8304f03 100644 --- a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/bpmn/data/VariableValue.java +++ b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/bpmn/data/VariableValue.java @@ -1,10 +1,15 @@ package de.fhmuenster.masterthesis.Testgenerator.bpmn.data; +import java.util.List; + +import de.fhmuenster.masterthesis.Testgenerator.rest.dto.ConstraintDTO; + public class VariableValue { private String variable; private Object value; private boolean required; + private List<ConstraintDTO> constraints; public VariableValue() { } @@ -37,4 +42,12 @@ public class VariableValue { public void setRequired(boolean required) { this.required = required; } + + public List<ConstraintDTO> getConstraints() { + return constraints; + } + + public void setConstraints(List<ConstraintDTO> constraints) { + this.constraints = constraints; + } } \ No newline at end of file diff --git a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/migration/MigrationService.java b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/migration/MigrationService.java index bf761de..b82650f 100644 --- a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/migration/MigrationService.java +++ b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/migration/MigrationService.java @@ -68,6 +68,7 @@ public class MigrationService { transferResultsToCorrespondingCategory(migrationResultWrapper, activityDeleteProcessVariableActionResults); for(FlowChangeWrapper fcw : activityAddActionResults) { + if(!flowHasTests(fcw.getFlow(), newDSL)) continue; try { Flag maxFlag = Flag.NONE; @@ -104,6 +105,7 @@ public class MigrationService { } for(FlowChangeWrapper fcw : activityDeleteActionResults) { + if(!flowHasTests(fcw.getFlow(), newDSL)) continue; try { Flag maxFlag = Flag.NONE; @@ -146,6 +148,7 @@ public class MigrationService { } for(FlowChangeWrapper fcw : activityAddProcessVariableActionResults) { + if(!flowHasTests(fcw.getFlow(), newDSL)) continue; try { Flag maxFlag = Flag.NONE; @@ -184,6 +187,7 @@ public class MigrationService { } for(FlowChangeWrapper fcw : activityDeleteProcessVariableActionResults) { + if(!flowHasTests(fcw.getFlow(), newDSL)) continue; try { Flag maxFlag = Flag.NONE; @@ -634,7 +638,7 @@ public class MigrationService { } } - private Flag calcMaxFlag(Flag currentFlag, Flag newFlag) { + public Flag calcMaxFlag(Flag currentFlag, Flag newFlag) { if (currentFlag.equals(Flag.NONE) && (newFlag.equals(Flag.GREEN) || newFlag.equals(Flag.YELLOW) || newFlag.equals(Flag.RED))) { return newFlag; @@ -731,4 +735,11 @@ public class MigrationService { return fcw; } + + private boolean flowHasTests(Flow f, TestgeneratorDSLSerializer dsl) { + Flow dslFlow = dsl.getFlow(f.getName()); + + + return dsl.getTestsForFlow(dslFlow).size() > 0; + } } diff --git a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/dto/BPMNTestcaseDTO.java b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/dto/BPMNTestcaseDTO.java index a5f29b5..8a669c9 100644 --- a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/dto/BPMNTestcaseDTO.java +++ b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/dto/BPMNTestcaseDTO.java @@ -11,6 +11,7 @@ public class BPMNTestcaseDTO { private List<EndCheckDTO> endChecks; private List<String> mocks; private int priority; + private String flag; public BPMNTestcaseDTO() { this.taskVariableList = new ArrayList<>(); @@ -63,4 +64,13 @@ public class BPMNTestcaseDTO { public void setPriority(int priority) { this.priority = priority; } + + public String getFlag() { + return flag; + } + + public void setFlag(String flag) { + this.flag = flag; + } + } diff --git a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/dto/ConstraintDTO.java b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/dto/ConstraintDTO.java new file mode 100644 index 0000000..68c0005 --- /dev/null +++ b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/dto/ConstraintDTO.java @@ -0,0 +1,33 @@ +package de.fhmuenster.masterthesis.Testgenerator.rest.dto; + +public class ConstraintDTO { + + private String key; + private int value; + + public ConstraintDTO() { + + } + + public ConstraintDTO(String key, int value) { + super(); + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } +} diff --git a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/change/ChangeController.java b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/change/ChangeController.java index c82cbe5..e5d88a4 100644 --- a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/change/ChangeController.java +++ b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/change/ChangeController.java @@ -7,6 +7,7 @@ import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.eclipse.emf.common.util.BasicEList; @@ -31,6 +32,7 @@ import de.fhmuenster.masterthesis.Testgenerator.utils.ProjectDirectoryUtils; import de.fhmuenster.masterthesis.serialization.TestgeneratorDSLSerializer; import de.fhmuenster.masterthesis.Testgenerator.rest.service.test.TestService; import de.fhmuenster.masterthesis.testgeneratorDSL.Flow; +import de.fhmuenster.masterthesis.testgeneratorDSL.StartFlowElement; import de.fhmuenster.masterthesis.testgeneratorDSL.Test; import de.fhmuenster.masterthesis.testgeneratorDSL.UserTaskFlowElement; import de.fhmuenster.masterthesis.testgeneratorDSL.VariableReference; @@ -145,10 +147,21 @@ public class ChangeController { //Prüfen, ob eine Prozessvariable gelöscht wurde, diese muss dann aus der Testspezifikation raus int index = 0; for(TaskVariables tv : bpmnTestcase.getTaskVariableList()) { - UserTaskFlowElement oldUserTask = (UserTaskFlowElement) oldDSL.getFlowElements(Arrays.asList(tv.getTask())).get(0); - List<VariableReference> oldInputVariables = oldUserTask.getInputVariables(); - UserTaskFlowElement newUserTask = (UserTaskFlowElement) newDSL.getFlowElements(Arrays.asList(tv.getTask())).get(0); - List<VariableReference> newInputVariables = newUserTask.getInputVariables(); + List<VariableReference> oldInputVariables = Collections.emptyList(); + List<VariableReference> newInputVariables = Collections.emptyList(); + if(oldDSL.getFlowElements(Arrays.asList(tv.getTask())).get(0) instanceof UserTaskFlowElement) { + UserTaskFlowElement oldUserTask = (UserTaskFlowElement) oldDSL.getFlowElements(Arrays.asList(tv.getTask())).get(0); + oldInputVariables = oldUserTask.getInputVariables(); + UserTaskFlowElement newUserTask = (UserTaskFlowElement) newDSL.getFlowElements(Arrays.asList(tv.getTask())).get(0); + newInputVariables = newUserTask.getInputVariables(); + } + if(oldDSL.getFlowElements(Arrays.asList(tv.getTask())).get(0) instanceof StartFlowElement) { + StartFlowElement oldStart = (StartFlowElement) oldDSL.getFlowElements(Arrays.asList(tv.getTask())).get(0); + oldInputVariables = oldStart.getInputVariables(); + StartFlowElement newStart = (StartFlowElement) newDSL.getFlowElements(Arrays.asList(tv.getTask())).get(0); + newInputVariables = newStart.getInputVariables(); + } + List<String> deletedInputVariables = new ArrayList<>(); for(VariableReference v : oldInputVariables) { diff --git a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/converters/TestConverter.java b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/converters/TestConverter.java index 1f4666c..9a6221f 100644 --- a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/converters/TestConverter.java +++ b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/converters/TestConverter.java @@ -13,6 +13,7 @@ import de.fhmuenster.masterthesis.serialization.TestgeneratorDSLObjectCreator; import de.fhmuenster.masterthesis.testgeneratorDSL.BooleanVariableEquals; import de.fhmuenster.masterthesis.testgeneratorDSL.BooleanVariableNotEquals; import de.fhmuenster.masterthesis.testgeneratorDSL.EndChecks; +import de.fhmuenster.masterthesis.testgeneratorDSL.Flag; import de.fhmuenster.masterthesis.testgeneratorDSL.Flow; import de.fhmuenster.masterthesis.testgeneratorDSL.FlowElement; import de.fhmuenster.masterthesis.testgeneratorDSL.IntVariableEquals; @@ -67,7 +68,11 @@ public class TestConverter { // @Tim, @Henning Priorität hier hinzufügen int prio = testcase.getPriority(); - return TestgeneratorDSLObjectCreator.createTest(testcase.getName(), flow, variableDeclarationsList, endCheckDeclaration, mocks, prio); + + //Flag + Flag flag = Flag.get(testcase.getFlag()); + + return TestgeneratorDSLObjectCreator.createTest(testcase.getName(), flow, variableDeclarationsList, endCheckDeclaration, mocks, prio, flag); } public static FlowElement getFlowElement(List<FlowElement> flowElements, String name) { @@ -110,6 +115,7 @@ public class TestConverter { bpmnTestcase.setEndChecks(endCheckList); bpmnTestcase.setMocks(mocks); bpmnTestcase.setPriority(testcase.getPriority()); + bpmnTestcase.setFlag(testcase.getFlag().name()); return bpmnTestcase; } diff --git a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/test/TestController.java b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/test/TestController.java index 95c2c8f..c4fbe33 100644 --- a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/test/TestController.java +++ b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/test/TestController.java @@ -1,5 +1,6 @@ package de.fhmuenster.masterthesis.Testgenerator.rest.service.test; +import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; @@ -14,6 +15,7 @@ import de.fhmuenster.masterthesis.Testgenerator.bpmn.data.BPMNServiceWithMocks; import de.fhmuenster.masterthesis.Testgenerator.bpmn.data.BPMNTestcase; import de.fhmuenster.masterthesis.Testgenerator.bpmn.data.VariableValue; import de.fhmuenster.masterthesis.Testgenerator.rest.dto.BPMNTestcaseDTO; +import de.fhmuenster.masterthesis.Testgenerator.rest.dto.ConstraintDTO; import de.fhmuenster.masterthesis.Testgenerator.rest.dto.ExternalTopicWithMockDTO; import de.fhmuenster.masterthesis.Testgenerator.rest.dto.FlowElementEnhancedDTO; import de.fhmuenster.masterthesis.Testgenerator.rest.dto.FlowInfoDTO; @@ -26,6 +28,7 @@ import de.fhmuenster.masterthesis.Testgenerator.rest.service.mock.MockService; import de.fhmuenster.masterthesis.Testgenerator.rest.service.project.Project; import de.fhmuenster.masterthesis.Testgenerator.rest.service.project.ProjectService; import de.fhmuenster.masterthesis.serialization.VariableProposal; +import de.fhmuenster.masterthesis.testgeneratorDSL.Constraint; import de.fhmuenster.masterthesis.testgeneratorDSL.Flow; import de.fhmuenster.masterthesis.testgeneratorDSL.FlowElement; import de.fhmuenster.masterthesis.testgeneratorDSL.Loop; @@ -114,7 +117,7 @@ public class TestController { public void deleteTest(@PathVariable(required = true) Long projectId, @PathVariable(required = true) String testId) { Project projectForId = projectService.getProjectForId(projectId); - + testService.deleteTest(projectForId.getProjectDirectories(), testId); } @@ -144,6 +147,15 @@ public class TestController { vv.setRequired(true); } + List<ConstraintDTO> constraintDTOs = new ArrayList<>(); + for(Constraint constraint : vr.getRef().getConstraints()) { + ConstraintDTO constraintDTO = new ConstraintDTO(); + constraintDTO.setKey(constraint.getKey()); + constraintDTO.setValue(constraint.getValue()); + constraintDTOs.add(constraintDTO); + } + vv.setConstraints(constraintDTOs); + vrIndex++; } } @@ -160,6 +172,16 @@ public class TestController { else { vv.setRequired(true); } + + List<ConstraintDTO> constraintDTOs = new ArrayList<>(); + for(Constraint constraint : vr.getRef().getConstraints()) { + ConstraintDTO constraintDTO = new ConstraintDTO(); + constraintDTO.setKey(constraint.getKey()); + constraintDTO.setValue(constraint.getValue()); + constraintDTOs.add(constraintDTO); + } + vv.setConstraints(constraintDTOs); + vrIndex++; } } diff --git a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/test/TestService.java b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/test/TestService.java index d1cf89e..388405b 100644 --- a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/test/TestService.java +++ b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/rest/service/test/TestService.java @@ -52,6 +52,7 @@ import de.fhmuenster.masterthesis.Testgenerator.dmn.data.DMNVariables; import de.fhmuenster.masterthesis.Testgenerator.embeddedform.data.EmbeddedFormDocument; import de.fhmuenster.masterthesis.Testgenerator.logging.LoggerProvider; import de.fhmuenster.masterthesis.Testgenerator.logging.TestgeneratorLogger; +import de.fhmuenster.masterthesis.Testgenerator.migration.MigrationService; import de.fhmuenster.masterthesis.Testgenerator.rest.service.converters.TestConverter; import de.fhmuenster.masterthesis.Testgenerator.rest.service.flow.FlowService; import de.fhmuenster.masterthesis.Testgenerator.rest.service.mock.MockService; @@ -65,6 +66,7 @@ import de.fhmuenster.masterthesis.serialization.VariableProposal; import de.fhmuenster.masterthesis.testgeneratorDSL.BPMNDiagram; import de.fhmuenster.masterthesis.testgeneratorDSL.Constraint; import de.fhmuenster.masterthesis.testgeneratorDSL.ExternalTopic; +import de.fhmuenster.masterthesis.testgeneratorDSL.Flag; import de.fhmuenster.masterthesis.testgeneratorDSL.Flow; import de.fhmuenster.masterthesis.testgeneratorDSL.FlowElement; import de.fhmuenster.masterthesis.testgeneratorDSL.FlowElementReference; @@ -94,6 +96,9 @@ public class TestService { private FlowService flowService; @Autowired private MockService mockService; + + @Autowired + private MigrationService migrationService; public TestService() { } @@ -266,6 +271,9 @@ public class TestService { checkTestIdAlreadyTaken(testcase.getName(), serializer); } + //Test-Flag aktualisieren + testcase.setFlag("GREEN"); + Test testToDelete = getTest(testId, serializer); serializer.deleteTest(testToDelete.getName()); addTest(testcase, serializer, projectDirectories); @@ -286,6 +294,14 @@ public class TestService { Test newTest = TestConverter.getTest(testcase, flow, flowElements, variables, mocks); serializer.addTest(newTest); + + //Am Ende prüfen, ob der Flow auch ein neues Flag bekommen soll + Flag maxFlag = Flag.NONE; + for(Test t : serializer.getTestsForFlow(flow)) { + maxFlag = migrationService.calcMaxFlag(maxFlag, t.getFlag()); + } + + flow.setFlag(maxFlag); } public List<VariableProposal<?>> getVariableProposals(ProjectDirectories projectDirectories) { @@ -381,9 +397,18 @@ public class TestService { try { TestgeneratorDSLSerializer serializer = new TestgeneratorDSLSerializer(testspecificationPath.toString()); + + Test t = serializer.getTest(testId); + Flow f = t.getFlowReference().getRef(); + int testCount = serializer.getTestsForFlow(f).size(); serializer.deleteTest(testId); - + + //Letzter Test gelöscht? + if(testCount == 1) { + f.setFlag(Flag.NONE); + } + serializer.serialize(); } catch (IOException e) { // @@ -429,7 +454,7 @@ public class TestService { HashMap<String, List<BPMNFieldConstraint>> allConstraintsForTask = formFields.getAllTaskSpecificConstraintsForTask(flowElement.getId()); HashMap<String, List<Constraint>> newTaskSpecificConstraints = new HashMap<>(); - /* + for(Variable v : startVariables) { if(allConstraintsForTask.get(v.getName()) != null && !allConstraintsForTask.get(v.getName()).isEmpty()) { //Constraints kopieren @@ -460,9 +485,9 @@ public class TestService { newTaskSpecificConstraints.put(v.getName(), variableConstraints); } } - */ - return TestgeneratorDSLObjectCreator.createStartFlowElement(flowElement.getId(), startVariables); + + return TestgeneratorDSLObjectCreator.createStartFlowElement(flowElement.getId(), startVariables, newTaskSpecificConstraints); } else if (flowElement instanceof EndEvent) { return TestgeneratorDSLObjectCreator.createEndFlowElement(flowElement.getId()); } else if (flowElement instanceof Gateway) { diff --git a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/utils/BPMNParseUtils.java b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/utils/BPMNParseUtils.java index 83f8838..c06a941 100644 --- a/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/utils/BPMNParseUtils.java +++ b/Testgenerator/src/main/java/de/fhmuenster/masterthesis/Testgenerator/utils/BPMNParseUtils.java @@ -214,7 +214,9 @@ public class BPMNParseUtils { } sv.getConstraints().addAll(constraintsToAdd); + constraintsToAdd.clear(); } + } constraintsToAdd.clear(); for(IntVariable iv : longVariables) { @@ -243,7 +245,9 @@ public class BPMNParseUtils { } iv.getConstraints().addAll(constraintsToAdd); + constraintsToAdd.clear(); } + } variables.addAll(stringVariables); diff --git a/testgenerator-web/testgenerator-web/src/app/app.module.ts b/testgenerator-web/testgenerator-web/src/app/app.module.ts index 91eb3f1..8c0b63f 100644 --- a/testgenerator-web/testgenerator-web/src/app/app.module.ts +++ b/testgenerator-web/testgenerator-web/src/app/app.module.ts @@ -32,6 +32,8 @@ import { LoopComponent } from './components/loop/loop.component'; import { UpdateProjectComponent } from './components/update-project/update-project.component'; import { PrioritizationOverviewComponent } from './prioritization-overview/prioritization-overview.component'; import { MigrationOverviewComponent } from './components/migration-overview/migration-overview.component'; +import { FlagComponent } from './components/flag/flag.component'; +import { VariableConstraintsPipe } from './pipes/variable-constraints.pipe'; @NgModule({ declarations: [ @@ -60,7 +62,9 @@ import { MigrationOverviewComponent } from './components/migration-overview/migr LoopComponent, UpdateProjectComponent, MigrationOverviewComponent, - PrioritizationOverviewComponent + PrioritizationOverviewComponent, + FlagComponent, + VariableConstraintsPipe ], imports: [ BrowserModule, diff --git a/testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.css b/testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.css new file mode 100644 index 0000000..e69de29 diff --git a/testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.html b/testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.html new file mode 100644 index 0000000..e43f0cc --- /dev/null +++ b/testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.html @@ -0,0 +1,5 @@ +<div> + <span class="badge bg-danger" *ngIf="flag && flag === 'RED'"> </span> + <span class="badge bg-warning" *ngIf="flag && flag === 'YELLOW'"> </span> + <span class="badge bg-success" *ngIf="flag && flag === 'GREEN'"> </span> +</div> \ No newline at end of file diff --git a/testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.spec.ts b/testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.spec.ts new file mode 100644 index 0000000..c6e9d0e --- /dev/null +++ b/testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FlagComponent } from './flag.component'; + +describe('FlagComponent', () => { + let component: FlagComponent; + let fixture: ComponentFixture<FlagComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ FlagComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(FlagComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.ts b/testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.ts new file mode 100644 index 0000000..9512cd0 --- /dev/null +++ b/testgenerator-web/testgenerator-web/src/app/components/flag/flag.component.ts @@ -0,0 +1,17 @@ +import { Component, Input, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-flag', + templateUrl: './flag.component.html', + styleUrls: ['./flag.component.css'] +}) +export class FlagComponent implements OnInit { + + @Input('flag') flag: string; + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/testgenerator-web/testgenerator-web/src/app/components/flow/flow.component.html b/testgenerator-web/testgenerator-web/src/app/components/flow/flow.component.html index 9c3d145..9c750a4 100644 --- a/testgenerator-web/testgenerator-web/src/app/components/flow/flow.component.html +++ b/testgenerator-web/testgenerator-web/src/app/components/flow/flow.component.html @@ -28,6 +28,7 @@ <div *ngFor="let testcase of testcases; let i=index"> <hr *ngIf="i > 0"> <div class="testgen-testcase"> + <app-flag [flag]="testcase.flag"></app-flag> <a class="testgen-testcase-name" [routerLink]="['test', testcase.name]">{{testcase.name}}</a> <p *ngFor="let taskVariable of testcase.taskVariableList; let i=index">{{taskVariable | taskVariable}}</p> diff --git a/testgenerator-web/testgenerator-web/src/app/components/flows/flows.component.html b/testgenerator-web/testgenerator-web/src/app/components/flows/flows.component.html index eddde30..9da9a69 100644 --- a/testgenerator-web/testgenerator-web/src/app/components/flows/flows.component.html +++ b/testgenerator-web/testgenerator-web/src/app/components/flows/flows.component.html @@ -24,10 +24,7 @@ <div *ngFor="let flow of flowSet.flows; let i=index"> <hr *ngIf="i > 0"> <div class="testgen-flow"> - <span class="badge bg-danger" *ngIf="flow.flag && flow.flag === 'RED'"> </span> - <span class="badge bg-warning" *ngIf="flow.flag && flow.flag === 'YELLOW'"> </span> - <span class="badge bg-success" *ngIf="flow.flag && flow.flag === 'GREEN'"> </span> - + <app-flag [flag]="flow.flag"></app-flag> <h4 [ngClass]="{'testgen-flow-highlight': activeFlow.name === flow.name}" class="testgen-flow-name" i18n="flow name">{{flow.name}} - (Number of generated tests: {{flow.testCount}})</h4> <p *ngIf="detailFlowVisible" class="testgen-flow-flowlist">{{flow | flow}}</p> diff --git a/testgenerator-web/testgenerator-web/src/app/components/test/test.component.html b/testgenerator-web/testgenerator-web/src/app/components/test/test.component.html index 10cd0ac..f4472ba 100644 --- a/testgenerator-web/testgenerator-web/src/app/components/test/test.component.html +++ b/testgenerator-web/testgenerator-web/src/app/components/test/test.component.html @@ -14,8 +14,8 @@ <form [formGroup]="formGroup"> <div class="md-form form-group"> - <input mdbInput mdbValidate type="text" class="form-control" id="name" formControlName="name"> - <label for="name" i18n="testcase name" i18n="test name">Testcase name</label> + <input mdbInput type="text" class="form-control" id="name" formControlName="name"> + <label for="name" i18n="testcase name" i18n="test name">Testcase name<span class="text-danger">*</span></label> <p class="text-danger" *ngIf="formGroup.get('name').touched && formGroup.get('name').hasError('required')" i18n="test name required">Testcase name is required.</p> <p class="text-danger" *ngIf="formGroup.get('name').hasError('testIdTaken')" i18n="test name taken">Testcase name is already taken.</p> </div> @@ -58,16 +58,31 @@ <div *ngFor="let variableValue of taskVariable.variableValues; let v=index"> <!--String and Integer Fields--> <div class="md-form form-group" *ngIf="(dataTypes.get(variableValue.variable) == 'java.lang.Integer') || dataTypes.get(variableValue.variable) == 'java.lang.String'"> - <input mdbInput mdbValidate type="number" class="form-control" id="{{variableValue.variable}}-{{i}}-{{v}}" + <input mdbInput type="number" class="form-control" id="{{variableValue.variable}}-{{i}}-{{v}}" formControlName="{{variableValue.variable}}" *ngIf="dataTypes.get(variableValue.variable) == 'java.lang.Integer'" - [required]="variableValue.required"> - <input mdbInput mdbValidate type="text" class="form-control" id="{{variableValue.variable}}-{{i}}-{{v}}" + [required]="variableValue.required" + [min]="checkConstraint('min', variableValue.constraints)" + [max]="checkConstraint('max', variableValue.constraints)" + (input)="checkRange($event, variableValue.constraints)" + > + <input mdbInput type="text" class="form-control" id="{{variableValue.variable}}-{{i}}-{{v}}" formControlName="{{variableValue.variable}}" *ngIf="dataTypes.get(variableValue.variable) == 'java.lang.String'" - [required]="variableValue.required"> - <label *ngIf="variableValue.required" class="text-danger" for="{{variableValue.variable}}-{{i}}-{{v}}">{{variableValue.variable}}</label> + [required]="variableValue.required" + [minlength]="checkConstraint('minlength', variableValue.constraints)" + [maxlength]="checkConstraint('maxlength', variableValue.constraints)"> + <label *ngIf="!variableValue.required" for="{{variableValue.variable}}-{{i}}-{{v}}">{{variableValue.variable}}</label> - <p *ngIf="getVariableProposals(variableValue.variable).proposals.length > 0" i18n="proposals">Proposals : [{{getVariableProposals(variableValue.variable) | variableProposals}}]</p> - <p *ngIf="getVariableProposals(variableValue.variable).proposals.length == 0" i18n="no proposals">No proposals</p> + <label *ngIf="variableValue.required" for="{{variableValue.variable}}-{{i}}-{{v}}">{{variableValue.variable}}<span class="text-danger">*</span></label> + <div> + <span *ngIf="getVariableProposals(variableValue.variable).proposals.length > 0" i18n="proposals">Proposals : [{{getVariableProposals(variableValue.variable) | variableProposals}}]</span> + <span *ngIf="getVariableProposals(variableValue.variable).proposals.length == 0" i18n="no proposals">No proposals</span> + + <div class="d-inline ml-4"> + <span *ngIf="variableValue.constraints.length > 0" i18n="constraints">Constraints: {{variableValue.constraints | variableConstraints }}</span> + <span *ngIf="variableValue.constraints.length == 0" i18n="no constraints">No constraints</span> + </div> + </div> + </div> <!--Boolean Checkboxes--> @@ -108,9 +123,9 @@ <!--String and Integer Fields--> <div class="md-form form-group" *ngIf="(dataTypes.get(variableValue.variable) == 'java.lang.Integer') || dataTypes.get(variableValue.variable) == 'java.lang.String'"> - <input mdbInput mdbValidate type="number" class="form-control" id="{{variableValue.variable}}" + <input mdbInput type="number" class="form-control" id="{{variableValue.variable}}" formControlName="{{variableValue.variable}}" *ngIf="dataTypes.get(variableValue.variable) == 'java.lang.Integer'"> - <input mdbInput mdbValidate type="text" class="form-control" id="{{variableValue.variable}}" + <input mdbInput type="text" class="form-control" id="{{variableValue.variable}}" formControlName="{{variableValue.variable}}" *ngIf="dataTypes.get(variableValue.variable) == 'java.lang.String'"> <label for="{{variableValue.variable}}">{{variableValue.variable}}</label> </div> @@ -151,7 +166,9 @@ <div class="testgen-actionbar testgen-actionbar-right"> <button type="button" class="btn btn-light" [routerLink]="['../']" *ngIf="!isEdit" i18n="cancel">>Cancel</button> <button type="button" class="btn btn-light" [routerLink]="['../../']" *ngIf="isEdit" i18n="cancel">Cancel</button> + <button type="button" class="btn btn-success" (click)="save()" i18n="save testcase" [disabled]="formGroup.invalid">Save testcase</button> + <span *ngIf="formGroup.invalid" class="text-danger">The form is invalid. Please check the required fields and given constraints.</span> </div> </div> </div> diff --git a/testgenerator-web/testgenerator-web/src/app/components/test/test.component.ts b/testgenerator-web/testgenerator-web/src/app/components/test/test.component.ts index ec50ed8..05acd61 100644 --- a/testgenerator-web/testgenerator-web/src/app/components/test/test.component.ts +++ b/testgenerator-web/testgenerator-web/src/app/components/test/test.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core'; import { BPMNTestcase } from 'src/app/models/bpmn-testcase'; import { Router, ActivatedRoute } from '@angular/router'; import { TestService } from 'src/app/services/test.service'; @@ -15,13 +15,14 @@ import { ExternalTopicWithMocks } from 'src/app/models/external-topic-with-mocks import { BPMNFlow } from 'src/app/models/bpmn-flow'; import { FlowService } from 'src/app/services/flow.service'; import { FileService } from 'src/app/services/file.service'; +import { Constraint } from 'src/app/models/constraint'; @Component({ selector: 'app-test', templateUrl: './test.component.html', styleUrls: ['./test.component.css'] }) -export class TestComponent implements OnInit { +export class TestComponent implements OnInit, AfterViewChecked { isTestLoading: boolean; testcase: BPMNTestcase; @@ -49,8 +50,10 @@ export class TestComponent implements OnInit { diagram: string; isDiagramLoading: boolean; + @ViewChild('saveButton') saveButton: HTMLButtonElement; + constructor(private _fb: FormBuilder, private testService: TestService, private router: Router, private route: ActivatedRoute, - private flowService: FlowService, private fileService: FileService) { + private flowService: FlowService, private fileService: FileService, private cdRef: ChangeDetectorRef) { this.route.params.subscribe(params => { this.actualProject = params['projectId']; this.actualFlow = params['flowId']; @@ -76,6 +79,12 @@ export class TestComponent implements OnInit { this.loadBPMNDiagram(); this.isLoading = false; + + + } + + ngAfterViewChecked() { + this.cdRef.detectChanges(); } /** @@ -100,16 +109,18 @@ export class TestComponent implements OnInit { for (let userInputs of this.flowInfo.userInputs) { if (userInputs.inputVariables.length > 0) { + let inputProposals = []; let valueObj = {}; let variableList = []; for (let variables of userInputs.inputVariables) { + inputProposals.push(this.getVariableProposals(variables.variable)); let countVariableFrequency = this.countVariable(variables.variable, taskVariableValueList); let value = this.getVariableValueOrDefault(userInputs.name, variables.variable, countVariableFrequency); valueObj[variables.variable] = value; - let newVariable = this.createVariableValue(variables.variable, value, variables.required); + let newVariable = this.createVariableValue(variables.variable, value, variables.required, variables.constraints); variableList.push(newVariable); } @@ -216,6 +227,8 @@ export class TestComponent implements OnInit { } } else { ValidationUtils.validateAllFormFields(this.formGroup); + + console.log(this.formGroup); } } @@ -250,11 +263,19 @@ export class TestComponent implements OnInit { } } - createVariableValue(variable: string, value: Object, required: boolean): VariableValue { + createVariableValue(variable: string, value: Object, required: boolean, constraints: Constraint[]): VariableValue { + let newConstraints = []; + + for(let i=0; i < constraints.length; i++) { + let newConstraint : Constraint = { key : constraints[i].key, value : constraints[i].value }; + newConstraints.push(newConstraint); + } + return { variable: variable, value: value, - required: required + required: required, + constraints: newConstraints } } @@ -280,7 +301,8 @@ export class TestComponent implements OnInit { taskVariableList: [], endChecks: [], mocks: [], - priority: 0 + priority: 0, + flag: "GREEN" } } @@ -520,4 +542,32 @@ export class TestComponent implements OnInit { return false; } + + checkConstraint(key: string, constraints: Constraint[]): string { + for(let i=0; i < constraints.length; i++) { + if(constraints[i].key === key) { + return constraints[i].value.toString(); + } + } + + return null; + } + + checkRange(event: any, constraints: Constraint[]) { + let min: number = parseInt(this.checkConstraint('min', constraints)); + let max: number = parseInt(this.checkConstraint('max', constraints)); + let value: number = event.target.value; + + + if(min != null) { + if(value < min) { + event.target.value = min; + } + } + if(max != null) { + if(value > max) { + event.target.value = max; + } + } + } } diff --git a/testgenerator-web/testgenerator-web/src/app/models/bpmn-testcase.ts b/testgenerator-web/testgenerator-web/src/app/models/bpmn-testcase.ts index e8e6048..6554764 100644 --- a/testgenerator-web/testgenerator-web/src/app/models/bpmn-testcase.ts +++ b/testgenerator-web/testgenerator-web/src/app/models/bpmn-testcase.ts @@ -9,4 +9,5 @@ export interface BPMNTestcase { endChecks: Array<EndCheck>; mocks: Array<string>; priority: number; + flag: string; } \ No newline at end of file diff --git a/testgenerator-web/testgenerator-web/src/app/models/constraint.ts b/testgenerator-web/testgenerator-web/src/app/models/constraint.ts new file mode 100644 index 0000000..b26a260 --- /dev/null +++ b/testgenerator-web/testgenerator-web/src/app/models/constraint.ts @@ -0,0 +1,4 @@ +export interface Constraint { + key: string; + value: number; +} \ No newline at end of file diff --git a/testgenerator-web/testgenerator-web/src/app/models/variable-value.ts b/testgenerator-web/testgenerator-web/src/app/models/variable-value.ts index cea82b9..f443be8 100644 --- a/testgenerator-web/testgenerator-web/src/app/models/variable-value.ts +++ b/testgenerator-web/testgenerator-web/src/app/models/variable-value.ts @@ -1,6 +1,8 @@ +import { Constraint } from "./constraint"; export interface VariableValue { variable: string; value: Object; required: boolean; + constraints?: Array<Constraint>; } \ No newline at end of file diff --git a/testgenerator-web/testgenerator-web/src/app/pipes/variable-constraints.pipe.spec.ts b/testgenerator-web/testgenerator-web/src/app/pipes/variable-constraints.pipe.spec.ts new file mode 100644 index 0000000..aafd950 --- /dev/null +++ b/testgenerator-web/testgenerator-web/src/app/pipes/variable-constraints.pipe.spec.ts @@ -0,0 +1,8 @@ +import { VariableConstraintsPipe } from './variable-constraints.pipe'; + +describe('VariableConstraintsPipe', () => { + it('create an instance', () => { + const pipe = new VariableConstraintsPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/testgenerator-web/testgenerator-web/src/app/pipes/variable-constraints.pipe.ts b/testgenerator-web/testgenerator-web/src/app/pipes/variable-constraints.pipe.ts new file mode 100644 index 0000000..2197c4a --- /dev/null +++ b/testgenerator-web/testgenerator-web/src/app/pipes/variable-constraints.pipe.ts @@ -0,0 +1,21 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { Constraint } from '../models/constraint'; + +@Pipe({ + name: 'variableConstraints' +}) +export class VariableConstraintsPipe implements PipeTransform { + + transform(value: Constraint[], ...args: unknown[]): string { + let result: string = ""; + for(let i=0; i < value.length; i++) { + if(result !== "") { + result += ", "; + } + result += value[i].key + " : " + value[i].value; + } + + return "[ " + result + " ]"; + } + +} -- GitLab