Source of file WorkflowEngineTest.php
Size: 11,901 Bytes - Last Modified: 2021-12-23T10:27:27+00:00
/var/www/docs.ssmods.com/process/src/tests/WorkflowEngineTest.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 | <?php namespace Symbiote\AdvancedWorkflow\Tests; use SilverStripe\CMS\Model\SiteTree; use SilverStripe\Dev\SapphireTest; use SilverStripe\ORM\DataObject; use SilverStripe\Versioned\Versioned; use Symbiote\AdvancedWorkflow\Actions\AssignUsersToWorkflowAction; use Symbiote\AdvancedWorkflow\Actions\NotifyUsersWorkflowAction; use Symbiote\AdvancedWorkflow\Actions\PublishItemWorkflowAction; use Symbiote\AdvancedWorkflow\DataObjects\WorkflowAction; use Symbiote\AdvancedWorkflow\DataObjects\WorkflowDefinition; use Symbiote\AdvancedWorkflow\DataObjects\WorkflowInstance; use Symbiote\AdvancedWorkflow\DataObjects\WorkflowTransition; use Symbiote\AdvancedWorkflow\Templates\WorkflowTemplate; /** * Tests for the workflow engine. * * @author marcus@symbiote.com.au * @license BSD License (http://silverstripe.org/bsd-license/) * @package advancedworkflow * @subpackage tests */ class WorkflowEngineTest extends SapphireTest { protected static $fixture_file = 'workflowinstancetargets.yml'; public function testCreateWorkflowInstance() { $definition = new WorkflowDefinition(); $definition->Title = "Create Workflow Instance"; $definition->write(); $stepOne = new WorkflowAction(); $stepOne->Title = "Step One"; $stepOne->WorkflowDefID = $definition->ID; $stepOne->write(); $stepTwo = new WorkflowAction(); $stepTwo->Title = "Step Two"; $stepTwo->WorkflowDefID = $definition->ID; $stepTwo->write(); $transitionOne = new WorkflowTransition(); $transitionOne->Title = 'Step One T1'; $transitionOne->ActionID = $stepOne->ID; $transitionOne->NextActionID = $stepTwo->ID; $transitionOne->write(); $instance = new WorkflowInstance(); $instance->write(); $instance->beginWorkflow($definition); $actions = $definition->Actions(); $this->assertEquals(2, $actions->Count()); $transitions = $actions->find('Title', 'Step One')->Transitions(); $this->assertEquals(1, $transitions->Count()); } public function testExecuteImmediateWorkflow() { $def = $this->createDefinition(); $actions = $def->Actions(); $firstAction = $def->getInitialAction(); $this->assertEquals('Step One', $firstAction->Title); $instance = new WorkflowInstance(); $instance->beginWorkflow($def); $this->assertTrue($instance->CurrentActionID > 0); $instance->execute(); // the instance should be complete, and have two finished workflow action // instances. $actions = $instance->Actions(); $this->assertEquals(2, $actions->Count()); foreach ($actions as $action) { $this->assertTrue((bool) $action->Finished); } } /** * Ensure WorkflowInstance returns expected values for a Published target object. */ public function testInstanceGetTargetPublished() { $def = $this->createDefinition(); $target = $this->objFromFixture(SiteTree::class, 'published-object'); $target->publishRecursive(); $instance = $this->objFromFixture(WorkflowInstance::class, 'target-is-published'); $instance->beginWorkflow($def); $instance->execute(); $this->assertTrue($target->isPublished()); $this->assertEquals($target->ID, $instance->getTarget()->ID); $this->assertEquals($target->Title, $instance->getTarget()->Title); } /** * Ensure WorkflowInstance returns expected values for a Draft target object. */ public function testInstanceGetTargetDraft() { $def = $this->createDefinition(); $target = $this->objFromFixture(SiteTree::class, 'draft-object'); $instance = $this->objFromFixture(WorkflowInstance::class, 'target-is-draft'); $instance->beginWorkflow($def); $instance->execute(); $this->assertFalse($target->isPublished()); $this->assertEquals($target->ID, $instance->getTarget()->ID); $this->assertEquals($target->Title, $instance->getTarget()->Title); } public function testPublishAction() { $this->logInWithPermission(); $action = new PublishItemWorkflowAction; $instance = new WorkflowInstance(); $page = new SiteTree(); $page->Title = 'stuff'; $page->write(); $instance->TargetClass = SiteTree::class; $instance->TargetID = $page->ID; $this->assertFalse($page->isPublished()); $action->execute($instance); $page = DataObject::get_by_id(SiteTree::class, $page->ID); $this->assertTrue($page->isPublished()); } public function testCreateDefinitionWithEmptyTitle() { $definition = new WorkflowDefinition(); $definition->Title = ""; $definition->write(); $this->assertStringContainsString( 'My Workflow', $definition->Title, 'Workflow created without title is assigned a default title.' ); } protected function createDefinition() { $definition = new WorkflowDefinition(); $definition->Title = "Dummy Workflow Definition"; $definition->write(); $stepOne = new WorkflowAction(); $stepOne->Title = "Step One"; $stepOne->WorkflowDefID = $definition->ID; $stepOne->write(); $stepTwo = new WorkflowAction(); $stepTwo->Title = "Step Two"; $stepTwo->WorkflowDefID = $definition->ID; $stepTwo->write(); $transitionOne = new WorkflowTransition(); $transitionOne->Title = 'Step One T1'; $transitionOne->ActionID = $stepOne->ID; $transitionOne->NextActionID = $stepTwo->ID; $transitionOne->write(); return $definition; } public function testCreateFromTemplate() { $structure = array( 'First step' => array( 'type' => AssignUsersToWorkflowAction::class, 'transitions' => array( 'second' => 'Second step' ) ), 'Second step' => array( 'type' => NotifyUsersWorkflowAction::class, 'transitions' => array( 'Approve' => 'Third step' ) ), ); $template = new WorkflowTemplate('Test'); $template->setStructure($structure); $actions = $template->createRelations(); $this->assertEquals(2, count($actions)); $this->assertTrue(isset($actions['First step'])); $this->assertTrue(isset($actions['Second step'])); $this->assertTrue($actions['First step']->exists()); $transitions = $actions['First step']->Transitions(); $this->assertTrue($transitions->count() == 1); } /** * Tests whether if user(s) are able to delete a workflow, dependent on permissions. */ public function testCanDeleteWorkflow() { // Create a definition $def = $this->createDefinition(); // Test a user with lame permissions $memberID = $this->logInWithPermission('SITETREE_VIEW_ALL'); $member = DataObject::get_by_id('SilverStripe\\Security\\Member', $memberID); $this->assertFalse($def->canCreate($member)); // Test a user with good permissions $memberID = $this->logInWithPermission('CREATE_WORKFLOW'); $member = DataObject::get_by_id('SilverStripe\\Security\\Member', $memberID); $this->assertTrue($def->canCreate($member)); } /** * For a context around this test, see: https://github.com/symbiote/advancedworkflow/issues/141 * * 1). Create a workflow definition * 2). Step the content into that workflow * 3). Delete the workflow * 4). Check that the content: * i). Has no remaining related actions * ii). Can be re-assigned a new Workflow * 5). Check that the object under workflow, maintains its status (Draft, Published etc) */ public function testDeleteWorkflowTargetStillWorks() { // 1). Create a workflow definition $def = $this->createDefinition(); $page = SiteTree::create(); $page->Title = 'dummy test'; $page->WorkflowDefinitionID = $def->ID; // Normally done via CMS Versioned::set_stage(Versioned::DRAFT); $page->write(); // Check $page is in draft, pre-deletion $status = ($page->isOnDraftOnly() && !$page->isPublished()); $this->assertTrue($status); // 2). Step the content into that workflow $instance = new WorkflowInstance(); $instance->beginWorkflow($def, $page); $instance->execute(); // Check the content is assigned $testPage = DataObject::get_by_id(SiteTree::class, $page->ID); $this->assertEquals($instance->TargetID, $testPage->ID); // 3). Delete the workflow $def->delete(); // Check $testPage is _still_ in draft, post-deletion $status = ($testPage->isOnDraftOnly() && !$testPage->isPublished()); $this->assertTrue($status); /* * 4). i). Check that the content: Has no remaining related actions * Note: WorkflowApplicable::WorkflowDefinitionID does _not_ get updated until assigned a new workflow * so we can use it to check that all related actions are gone */ $defID = $testPage->WorkflowDefinitionID; $this->assertEquals(0, DataObject::get(WorkflowAction::class)->filter('WorkflowDefID', $defID)->count()); /* * 4). ii). Check that the content: Can be re-assigned a new Workflow Definition */ $newDef = $this->createDefinition(); $testPage->WorkflowDefinitionID = $newDef->ID; // Normally done via CMS $instance = new WorkflowInstance(); $instance->beginWorkflow($newDef, $testPage); $instance->execute(); // Check the content is assigned to the new Workflow Definition correctly $this->assertEquals($newDef->ID, $testPage->WorkflowDefinitionID); $this->assertEquals( $newDef->Actions()->count(), DataObject::get(WorkflowAction::class)->filter('WorkflowDefID', $newDef->ID)->count() ); // 5). Check that the object under workflow, maintains its status $newDef2 = $this->createDefinition(); // Login so SiteTree::canPublish() returns true $testPage->WorkflowDefinitionID = $newDef2->ID; // Normally done via CMS $this->logInWithPermission(); $testPage->publishRecursive(); // Check $testPage is published, pre-deletion (getStatusFlags() returns empty array) $this->assertTrue($testPage->isPublished()); $instance = new WorkflowInstance(); $instance->beginWorkflow($newDef2, $testPage); $instance->execute(); // Now delete the related WorkflowDefinition and ensure status is the same // (i.e. so it's not 'modified' for example) $newDef2->delete(); // Check $testPage is _still_ published, post-deletion (getStatusFlags() returns empty array) $this->assertTrue($testPage->isPublished()); } /** * Test the diff showing only fields that have changes made to it in a data object. */ public function testInstanceDiff() { $instance = $this->objFromFixture(WorkflowInstance::class, 'target-is-published'); $target = $instance->getTarget(); $target->publishRecursive(); $target->Title = 'New title for target'; $target->write(); $diff = $instance->getTargetDiff()->column('Name'); $this->assertContains('Title', $diff); $this->assertNotContains('Content', $diff); } } |