Repository: ProcessMaker/nayra (php)

Issue:
Add transition to close an Activity from Active State

Pull request description:
Add transition to close active transition. Resolves #136

Patch:
diff --git a/src/ProcessMaker/Nayra/Bpmn/ActivityTrait.php b/src/ProcessMaker/Nayra/Bpmn/ActivityTrait.php
index da9b459..58ed2d2 100755
--- a/src/ProcessMaker/Nayra/Bpmn/ActivityTrait.php
+++ b/src/ProcessMaker/Nayra/Bpmn/ActivityTrait.php
@@ -70,6 +70,7 @@ trait ActivityTrait
         $this->setRepository($factory);
         $this->activeState = new State($this, ActivityInterface::TOKEN_STATE_ACTIVE);
         $this->activityTransition = new ActivityTransition($this, true);
+        $this->closeActiveTransition = new CloseExceptionTransition($this, true);
         $this->failingState = new State($this, ActivityInterface::TOKEN_STATE_FAILING);
         $this->exceptionTransition = new ExceptionTransition($this, true);
         $this->closeExceptionTransition = new CloseExceptionTransition($this, true);
@@ -79,6 +80,7 @@ trait ActivityTrait
 
         $this->activeState->connectTo($this->exceptionTransition);
         $this->activeState->connectTo($this->activityTransition);
+        $this->activeState->connectTo($this->closeActiveTransition);
         $this->failingState->connectTo($this->completeExceptionTransition);
         $this->failingState->connectTo($this->closeExceptionTransition);
         $this->exceptionTransition->connectTo($this->failingState);
@@ -125,6 +127,17 @@ trait ActivityTrait
                 $this->notifyEvent(ActivityInterface::EVENT_EVENT_TRIGGERED, $this, $transition, $tokens);
             }
         );
+        $this->closeActiveTransition->attachEvent(
+            TransitionInterface::EVENT_AFTER_CONSUME,
+            function ($transition, $tokens) {
+                foreach ($tokens as $token) {
+                    $this->getRepository()
+                        ->getTokenRepository()
+                        ->persistActivityCompleted($this, $token);
+                }
+                $this->notifyEvent(ActivityInterface::EVENT_EVENT_TRIGGERED, $this, $transition, $tokens);
+            }
+        );
     }
 
     /**


Test patch:
diff --git a/tests/Feature/Engine/BasicsTest.php b/tests/Feature/Engine/BasicsTest.php
index 08d1a15..f1f9b4d 100755
--- a/tests/Feature/Engine/BasicsTest.php
+++ b/tests/Feature/Engine/BasicsTest.php
@@ -3,12 +3,12 @@
 namespace Tests\Feature\Engine;
 
 use ProcessMaker\Nayra\Contracts\Bpmn\ActivityInterface;
-use ProcessMaker\Nayra\Contracts\Bpmn\DataStoreInterface;
 use ProcessMaker\Nayra\Contracts\Bpmn\DiagramInterface;
 use ProcessMaker\Nayra\Contracts\Bpmn\EndEventInterface;
 use ProcessMaker\Nayra\Contracts\Bpmn\ProcessInterface;
 use ProcessMaker\Nayra\Contracts\Bpmn\StartEventInterface;
 use ProcessMaker\Nayra\Exceptions\InvalidSequenceFlowException;
+use ProcessMaker\Nayra\Contracts\Bpmn\EventInterface;
 
 /**
  * Test transitions
@@ -16,7 +16,6 @@ use ProcessMaker\Nayra\Exceptions\InvalidSequenceFlowException;
  */
 class BasicsTest extends EngineTestCase
 {
-
     /**
      * Create a simple process
      *
@@ -45,7 +44,7 @@ class BasicsTest extends EngineTestCase
 
     /**
      * Sequence flow
-     * 
+     *
      * Test transitions between start event, activity and end event.
      *
      */
@@ -148,9 +147,45 @@ class BasicsTest extends EngineTestCase
         try {
             $end->createFlowTo($activity, $this->repository);
             $this->engine->createExecutionInstance($process, $dataStore);
-        }
-        catch (InvalidSequenceFlowException $e) {
+        } catch (InvalidSequenceFlowException $e) {
             $this->assertNotNull($e->getMessage());
         }
     }
+
+    /**
+     * Tests that when a script fails, then it is closed
+     */
+    public function testCloseDirectlyActiveTask()
+    {
+        //Load a process
+        $process = $this->createSimpleProcessInstance();
+        $dataStore = $this->repository->createDataStore();
+
+        //create an instance of the process
+        $instance = $this->engine->createExecutionInstance($process, $dataStore);
+
+        //Get References
+        $start = $process->getEvents()->item(0);
+
+        //start the process an instance of the process
+        $start->start($instance);
+        $this->engine->runToNextState();
+
+        //Assert: that the process is stared and the first activity activated
+        $this->assertEvents([
+            ProcessInterface::EVENT_PROCESS_INSTANCE_CREATED,
+            EventInterface::EVENT_EVENT_TRIGGERED,
+            ActivityInterface::EVENT_ACTIVITY_ACTIVATED,
+        ]);
+
+        //close the process instance
+        $instance->close();
+        $this->engine->runToNextState();
+
+        //Assertion: Verify that the proces instance was completed
+        $this->assertEvents([
+            ActivityInterface::EVENT_EVENT_TRIGGERED,
+            ProcessInterface::EVENT_PROCESS_INSTANCE_COMPLETED,
+        ]);
+    }
 }