Perforce Chronicle 2012.2/486814
API Documentation
|
Test that workflow is integrated with content as expected. More...
Public Member Functions | |
setUp () | |
All tests here need content types, workflows and 'editor' access. | |
testAccessAnonymous () | |
Test content access for anonymous role. | |
testAccessEditor () | |
Test content access for editor role. | |
testAccessMember () | |
Test content access for member role. | |
testCategoryIcons () | |
Test that proper icon for category is rendered (i.e. | |
testContentEdit () | |
Ensure editing shows current state. | |
testContentSave () | |
Ensure saving content, saves state. | |
testContentSaveScheduled () | |
Ensure scheduled data are saved when saving entry with a scheduled transition. | |
testContentSubForm () | |
Ensure workflow sub-form is present when adding content that has associated workflow. | |
testFilterByWorkflow () | |
Verify filtering content data grid by workflow states. | |
testScheduledContentEdit () | |
Ensure edition shows scheduled state if entry has scheduled transition. | |
testSubFormElementsCollision () | |
Ensure that if there are elements in the sub-forms with names matching entry fields, then they are not populated with those values. | |
testWorkflowActions () | |
Verify transition actions. | |
testWorkflowConditions () | |
Verify transition conditions. | |
Protected Member Functions | |
_makeContentEntry ($state= 'draft', $owner= '', $scheduledState=null, $scheduledTime=null) | |
Create a test content entry in the given state and optionally set scheduled transition data. | |
_verifyTitleValuesMatch (array $source, array $titleValues) | |
Verifies that titles in $source array match values in $titleValues. | |
_verifyWorkflowFilter (array $workflowData, array $expectedEntries) | |
Helper function to verify filtering by workflow. | |
_verifyWorkflowStatesRadio (array $expectedStates, $selectedState=null) | |
Verify that all expected states are present in the workflow sub-form as state radio options. |
Test that workflow is integrated with content as expected.
Workflow_Test_ContentIntegrationTest::_makeContentEntry | ( | $ | state = 'draft' , |
$ | owner = '' , |
||
$ | scheduledState = null , |
||
$ | scheduledTime = null |
||
) | [protected] |
Create a test content entry in the given state and optionally set scheduled transition data.
string | $state | optional - the state to put the entry in. |
string | $owner | optional - username to set as entry owner. |
string | $scheduledState | optional - state of the scheduled transition to set the entry on. |
string | $scheduledTime | optional - time of the scheduled transition to set the entry on. |
{ return P4Cms_Content::store( array( 'contentType' => 'basic-page', 'contentOwner' => $owner, 'title' => 'test-title', 'body' => 'test-body', 'workflowState' => $state, 'workflowScheduledState' => $scheduledState, 'workflowScheduledTime' => $scheduledTime ) ); }
Workflow_Test_ContentIntegrationTest::_verifyTitleValuesMatch | ( | array $ | source, |
array $ | titleValues | ||
) | [protected] |
Verifies that titles in $source array match values in $titleValues.
array | $source | array to compare with $titleValues, assuming array items contain 'title' key |
array | $titleValues | array to compare to $source |
{ // extract title values from source $sourceTitle = array_map( function($item) { return isset($item['title']) ? $item['title'] : null; }, $source ); $match = (count($source) === count($titleValues)) && count(array_diff($titleValues, $sourceTitle)) === 0; $this->assertTrue( $match, "Expected items after filtering by worfklow:" . "\nFiltered entry titles: " . print_r($sourceTitle, true) . "\nExpected entry titles: " . print_r($titleValues, true) ); }
Workflow_Test_ContentIntegrationTest::_verifyWorkflowFilter | ( | array $ | workflowData, |
array $ | expectedEntries | ||
) | [protected] |
Helper function to verify filtering by workflow.
It automatically processes 3 cases - when filters are applied to the current, scheduled or both states.
Workflow data passed in the parameter are assumed to contain values from the worfklow form, except 'targetState' that is added automatically.
Expected entries are assumed to contain 2 or 3 lists of expected entry titles when filters (represented by workflow data) are applied to the current state, to the scheduled state and optionally to the both. If thirs list is omitted then it will be calculated as union of the two for current and scheduled.
array | $workflowData | values of the workflow form representing filters. |
array | $expectedEntries | 2- or 3-dimensional array containing lists of expected entry titles when filters are applied to the, in order, current state, scheduled state and both. |
{ $expectedEntries = array_values($expectedEntries); if (count($expectedEntries) === 2) { // add expected result for applied to 'current or scheduled' state as // union of the two $expectedEntries[] = array_merge( $expectedEntries[0], array_diff($expectedEntries[1], $expectedEntries[0]) ); } $targetStates = array('current', 'scheduled', 'either'); foreach ($expectedEntries as $key => $expected) { // prepare post data and inject target state $postData = array('workflow' => $workflowData); $postData['workflow']['targetState'] = $targetStates[$key]; // prepare request $this->resetRequest()->resetResponse(); $this->request ->setMethod('post') ->setPost($postData); // dispatch $this->dispatch('/browse/format/json'); $body = $this->getResponse()->getBody(); $data = Zend_Json::decode($body); // verify response $this->_verifyTitleValuesMatch($data['items'], $expected); } }
Workflow_Test_ContentIntegrationTest::_verifyWorkflowStatesRadio | ( | array $ | expectedStates, |
$ | selectedState = null |
||
) | [protected] |
Verify that all expected states are present in the workflow sub-form as state radio options.
If selected state parameter is present, also ensure selected option.
array | $expectedStates | list with states for state radio element. |
string | $selectedState | state option assumed to be selected. |
{ $statesImploded = implode(', ', $expectedStates); // verify number of radio options $expectedTransitionsCount = count($expectedStates); $this->assertQueryCount( '#workflow-state-element input[type="radio"]', $expectedTransitionsCount, "Expected state radio has " . $expectedTransitionsCount . " options: " . $statesImploded . "." ); // verify radio option values $message = 'Expected states: [' . $statesImploded . ']'; if ($selectedState) { $message .= ' with [' . $selectedState . '] selected'; } foreach ($expectedStates as $state) { $query = '#workflow-state-element input[type="radio"][value="' . $state . '"]'; if ($selectedState === $state) { $query .= '[checked="checked"]'; } $this->assertQuery($query, $message); } }
Workflow_Test_ContentIntegrationTest::setUp | ( | ) |
All tests here need content types, workflows and 'editor' access.
{ parent::setUp(); // install default content types and workflows. P4Cms_Content_Type::installDefaultTypes(); Workflow_Model_Workflow::installDefaultWorkflows(); }
Workflow_Test_ContentIntegrationTest::testAccessAnonymous | ( | ) |
Test content access for anonymous role.
{ $published = $this->_makeContentEntry('published'); $unPublished = $this->_makeContentEntry(); // ensure anonymous users can see published content // but cannot see un-published content $this->utility->impersonate('anonymous'); $this->assertTrue(P4Cms_Content::exists($published->getId())); $this->assertFalse(P4Cms_Content::exists($unPublished->getId())); }
Workflow_Test_ContentIntegrationTest::testAccessEditor | ( | ) |
Test content access for editor role.
{ $unPublished = $this->_makeContentEntry(); // ensure un-published content is accessible to editors $this->utility->impersonate('editor'); $acl = P4Cms_Site::fetchActive()->getAcl(); $this->assertTrue(P4Cms_Content::exists($unPublished->getId())); }
Workflow_Test_ContentIntegrationTest::testAccessMember | ( | ) |
Test content access for member role.
{ $published = $this->_makeContentEntry('published', 'foo'); $unPublished = $this->_makeContentEntry(); $this->utility->impersonate('member'); $userId = P4Cms_User::fetchActive()->getId(); // ensure un-published content is accessible by members only if they own it $this->assertFalse(P4Cms_Content::exists($unPublished->getId())); $unPublished->setOwner($userId)->save(); $this->assertTrue(P4Cms_Content::exists($unPublished->getId())); // ensure that member cannot see 'publish' option if not having 'publish' permission $acl = P4Cms_Site::fetchActive()->getAcl(); $acl->allow('member', 'content', array('add', 'edit', 'edit-all')); $this->dispatch('/add/type/basic-page'); $this->_verifyWorkflowStatesRadio(array('draft', 'review'), 'draft'); // add publish permission and verify that user can see publish option $acl->allow('member', 'content', array('publish')); $this->resetRequest()->resetResponse(); $this->dispatch('/add/type/basic-page'); $this->_verifyWorkflowStatesRadio(array('draft', 'review', 'published'), 'draft'); // ensure that member, although lacking 'access-unpublished' permission, can // unpublish content if is an owner $this->resetRequest()->resetResponse(); $this->dispatch('/content/index/edit/id/' . $published->getId()); // not an owner - should see only published state $this->_verifyWorkflowStatesRadio(array('published'), 'published'); // add 'access-unpublished' and verify again $acl->allow('member', 'content', array('access-unpublished')); $this->resetRequest()->resetResponse(); $this->dispatch('/content/index/edit/id/' . $published->getId()); $this->_verifyWorkflowStatesRadio(array('draft', 'review', 'published'), 'published'); // remove access-published permission, but make user owner and verify again $acl->deny('member', 'content', array('access-unpublished')); $published->setOwner($userId)->save(); $this->resetRequest()->resetResponse(); $this->dispatch('/content/index/edit/id/' . $published->getId()); $this->_verifyWorkflowStatesRadio(array('draft', 'review', 'published'), 'published'); }
Workflow_Test_ContentIntegrationTest::testCategoryIcons | ( | ) |
Test that proper icon for category is rendered (i.e.
depending on category content).
{ // create entry in unpublished state $entry = $this->_makeContentEntry('draft', 'foo'); // create category A with sub-category B containing the entry $categoryA = Category_Model_Category::store( array( 'id' => 'a', 'title' => 'A', ) ); $categoryB = Category_Model_Category::create( array( 'id' => 'a/b', 'title' => 'B', ) )->addEntry($entry->getId())->save(); // verify that member see icon representing empty folder for category B // as member cannot see unpublished content $this->utility->impersonate('member'); $this->dispatch('/category/view/a'); $this->assertQueryContentRegex("a[href='/category/view/a/b']", "/src=.+folder\-64x64/"); // add access to unpublished content and verify category icon again $acl = P4Cms_Site::fetchActive()->getAcl(); $acl->allow('member', 'content', array('access-unpublished')); $this->resetRequest()->resetResponse(); $this->dispatch('/category/view/a'); $this->assertQueryContentRegex("a[href='/category/view/a/b']", "/src=.+folder\-content\-64x64/"); }
Workflow_Test_ContentIntegrationTest::testContentEdit | ( | ) |
Ensure editing shows current state.
{ $this->utility->impersonate('editor'); // ensure current state is checked if entry has no scheduled transition $entry = $this->_makeContentEntry('published'); $this->dispatch('/content/edit/id/' . $entry->getId()); $this->assertQuery('#workflow-state-published[checked="checked"]'); }
Workflow_Test_ContentIntegrationTest::testContentSave | ( | ) |
Ensure saving content, saves state.
{ $this->utility->impersonate('editor'); $this->request->setMethod('post') ->setPost('format', 'json') ->setPost('contentType', 'basic-page') ->setPost('title', 'test-title') ->setPost('body', 'test-body') ->setPost( 'workflow', array( 'state' => 'review', 'scheduled' => 'false', 'comment' => 'test' ) ); $this->dispatch('/content/add/'); $data = Zend_Json::decode($this->getResponse()->getBody()); $content = P4Cms_Content::fetch($data['contentId']); $change = $content->toP4File()->getChange(); $this->assertSame('review', $content->getValue('workflowState')); }
Workflow_Test_ContentIntegrationTest::testContentSaveScheduled | ( | ) |
Ensure scheduled data are saved when saving entry with a scheduled transition.
{ $this->utility->impersonate('editor'); // set a timestamp that is in the future where the day, month and year are not the // same as today (i.e. it must be at least one day from now); we set today + 2 days $timestamp = time() + 172800; $this->request->setMethod('post') ->setPost('format', 'json') ->setPost('contentType', 'basic-page') ->setPost('title', 'test-title') ->setPost('body', 'test-body') ->setPost( 'workflow', array( 'state' => 'review', 'scheduled' => 'true', 'scheduledDate' => date('Y-m-d', $timestamp), 'scheduledTime' => '07:00' ) ); $this->dispatch('/content/add/'); $data = Zend_Json::decode($this->getResponse()->getBody()); $content = P4Cms_Content::fetch($data['contentId']); $this->assertSame('draft', $content->getValue('workflowState')); $this->assertSame('review', $content->getValue('workflowScheduledState')); $this->assertSame( strtotime(date('Y-m-d 07:00', $timestamp)), (int) $content->getValue('workflowScheduledTime') ); }
Workflow_Test_ContentIntegrationTest::testContentSubForm | ( | ) |
Ensure workflow sub-form is present when adding content that has associated workflow.
{ $this->utility->impersonate('editor'); $this->dispatch('/content/add/type/basic-page'); // ensure workflow sub-form is here. $this->assertQuery('.workflow-sub-form'); // basic page uses 'simple workflow', default state is 'draft'. $this->assertQuery('#workflow-state-draft[checked="checked"]'); // ensure transitions are present also. $workflow = Workflow_Model_Workflow::fetch('simple'); $state = $workflow->getStateModel('draft'); foreach ($state->getTransitions() as $transition => $details) { $this->assertQuery('#workflow-state-' . $transition); } }
Workflow_Test_ContentIntegrationTest::testFilterByWorkflow | ( | ) |
Verify filtering content data grid by workflow states.
{ $this->utility->impersonate('administrator'); $published = Workflow_Model_State::PUBLISHED; $time = time() + 1000; // remove workflows/content types foreach (Workflow_Model_Workflow::fetchAll() as $workflow) { $workflow->delete(); } foreach (P4Cms_Content_Type::fetchAll() as $type) { $type->delete(); } // create workflows and content types with the following mapping: // -------------------------------------------------------- // | CONTENT TYPE | WORKFLOW | STATES | // -------------------------------------------------------- // | basic | simple | draft, published | // | basic2 | simple | draft, published | // | simple | | - | // | private | private | draft | // | blog | blog | draft, review, published | // | | unused | draft, review, published | // -------------------------------------------------------- Workflow_Model_Workflow::store( array( 'id' => "simple", 'label' => "simple workflow", 'states' => "[draft]\n" . "label=Draft\n" . "[$published]\n" . "label=Published" ) ); Workflow_Model_Workflow::store( array( 'id' => "private", 'label' => "private workflow", 'states' => "[draft]\n" . "label=Draft\n" ) ); Workflow_Model_Workflow::store( array( 'id' => "blog", 'label' => "blog workflow", 'states' => "[draft]\n" . "label=Draft\n" . "[review]\n" . "label=Review\n" . "[$published]\n" . "label=Published" ) ); Workflow_Model_Workflow::store( array( 'id' => "unused", 'label' => "unused workflow", 'states' => "[draft]\n" . "label=Draft\n" . "[review]\n" . "label=Review\n" . "[$published]\n" . "label=Published" ) ); P4Cms_Content_Type::store( array( 'id' => "basic", 'label' => "basic content type", 'group' => "misc", 'workflow' => "simple", 'elements' => "[title]\n" . "type=text" ) ); P4Cms_Content_Type::store( array( 'id' => "basic2", 'label' => "basic2 content type", 'group' => "misc", 'workflow' => "simple", 'elements' => "[title]\n" . "type=text" ) ); P4Cms_Content_Type::store( array( 'id' => "simple", 'label' => "simple content type", 'group' => "misc", 'elements' => "[title]\n" . "type=text" ) ); P4Cms_Content_Type::store( array( 'id' => "private", 'label' => "private content type", 'group' => "misc", 'workflow' => "private", 'elements' => "[title]\n" . "type=text" ) ); P4Cms_Content_Type::store( array( 'id' => "blog", 'label' => "blog content type", 'group' => "misc", 'workflow' => "blog", 'elements' => "[title]\n" . "type=text" ) ); // create contents with following relations to the workflows (dot denotes the same value as in the cell above): // ------------------------------------------------------------------------------------------------------- // | CONTENT TITLE | CONTENT TYPE | WORKFLOW | STATE ASSIGNED | STATE SCHEDULED | STATE AS IT APPEARS | // ------------------------------------------------------------------------------------------------------- // | blog-draft | blog | blog | draft | - | draft | // | blog-draft2 | . | . | draft | review | draft -> review | // | blog-review | . | . | review | published | review -> published | // | blog-pub | . | . | published | - | published | // | blog-abc | . | . | abc | | draft | // | simple | simple | - | - | - | published | // | simple-draft | simple | - | draft | review | published | // | simple2-draft | simple | - | draft | published | published | // | basic-draft | basic | simple | draft | published | draft -> published | // | basic-pub | . | . | published | draft | published -> draft | // | basic-review | . | . | review | - | draft | // | basic-xyz | . | . | xyz | - | draft | // | basic2-draft | basic2 | . | draft | - | draft | // | private-draft | private | private | draft | - | draft | // | private-pub | . | . | published | - | draft | // ------------------------------------------------------------------------------------------------------- P4Cms_Content::store( array( 'contentType' => 'private', 'title' => 'private-draft', 'workflowState' => 'draft' ) ); P4Cms_Content::store( array( 'contentType' => 'private', 'title' => 'private-pub', 'workflowState' => $published ) ); P4Cms_Content::store( array( 'contentType' => 'basic2', 'title' => 'basic2-draft', 'workflowState' => 'draft' ) ); P4Cms_Content::store( array( 'contentType' => 'basic', 'title' => 'basic-draft', 'workflowState' => 'draft', 'workflowScheduledState' => $published, 'workflowScheduledTime' => $time ) ); P4Cms_Content::store( array( 'contentType' => 'basic', 'title' => 'basic-pub', 'workflowState' => $published, 'workflowScheduledState' => 'draft', 'workflowScheduledTime' => $time ) ); P4Cms_Content::store( array( 'contentType' => 'basic', 'title' => 'basic-review', 'workflowState' => 'review' ) ); P4Cms_Content::store( array( 'contentType' => 'basic', 'title' => 'basic-xyz', 'workflowState' => 'xyz' ) ); P4Cms_Content::store( array( 'contentType' => 'blog', 'title' => 'blog-draft', 'workflowState' => 'draft' ) ); P4Cms_Content::store( array( 'contentType' => 'blog', 'title' => 'blog-draft2', 'workflowState' => 'draft', 'workflowScheduledState' => 'review', 'workflowScheduledTime' => $time ) ); P4Cms_Content::store( array( 'contentType' => 'blog', 'title' => 'blog-pub', 'workflowState' => $published ) ); P4Cms_Content::store( array( 'contentType' => 'blog', 'title' => 'blog-review', 'workflowState' => 'review', 'workflowScheduledState' => $published, 'workflowScheduledTime' => $time ) ); P4Cms_Content::store( array( 'contentType' => 'blog', 'title' => 'blog-abc', 'workflowState' => 'abc' ) ); P4Cms_Content::store( array( 'contentType' => 'simple', 'title' => 'simple', ) ); P4Cms_Content::store( array( 'contentType' => 'simple', 'title' => 'simple-draft', 'workflowState' => 'draft', 'workflowScheduledState' => 'review', 'workflowScheduledTime' => $time, ) ); P4Cms_Content::store( array( 'contentType' => 'simple', 'title' => 'simple2-draft', 'workflowState' => 'draft', 'workflowScheduledState' => $published, 'workflowScheduledTime' => $time, ) ); // test json data for browse action when provided with various options for filtering by workflow $this->dispatch('/browse/format/json'); $body = $this->getResponse()->getBody(); $data = Zend_Json::decode($body); $expected = P4Cms_Content::fetchAll()->invoke('getTitle'); $this->_verifyTitleValuesMatch($data['items'], $expected); // filter to keep only published $this->_verifyWorkflowFilter( array( 'workflow' => 'onlyPublished' ), array( array('blog-pub', 'simple', 'simple-draft', 'basic-pub', 'simple2-draft'), array('blog-review', 'basic-draft') ) ); // filter to keep only unpublished $this->_verifyWorkflowFilter( array( 'workflow' => 'onlyUnpublished' ), array( array('blog-draft', 'blog-draft2', 'blog-review', 'blog-abc', 'basic-draft', 'basic-review', 'basic-xyz', 'basic2-draft', 'private-draft', 'private-pub'), array('blog-draft2', 'basic-pub') ) ); // filter to keep only items under simple workflow $this->_verifyWorkflowFilter( array( 'workflow' => 'userSelected', 'states' => array('simple/*') ), array( array('basic-draft', 'basic-pub', 'basic-review', 'basic-xyz', 'basic2-draft'), array('basic-draft', 'basic-pub') ) ); // filter to keep only items under blog workflow with published state $this->_verifyWorkflowFilter( array( 'workflow' => 'userSelected', 'states' => array('blog/' . $published), ), array( array('blog-pub'), array('blog-review') ) ); // filter to keep only items under blog workflow with draft state // or simple workflow with published state $this->_verifyWorkflowFilter( array( 'workflow' => 'userSelected', 'states' => array( 'blog/draft', 'simple/' . $published ) ), array( array('blog-draft', 'blog-draft2', 'blog-abc', 'basic-pub'), array('basic-draft') ) ); // filter to keep only items under 'unused' workflow $this->_verifyWorkflowFilter( array( 'workflow' => 'userSelected', 'states' => array('unused/*'), ), array( array(), array() ) ); // filter to keep only items under private workflow having draft state $this->_verifyWorkflowFilter( array( 'workflow' => 'userSelected', 'states' => array('private/draft'), ), array( array('private-draft', 'private-pub'), array() ) ); // filter to keep only items under simple or private workflow with draft state $this->_verifyWorkflowFilter( array( 'workflow' => 'userSelected', 'states' => array( 'simple/draft', 'private/draft' ) ), array( array('basic-draft', 'basic-review', 'basic-xyz', 'basic2-draft', 'private-draft', 'private-pub'), array('basic-pub') ) ); // if no selection is provided, ensure all items are shown $this->_verifyWorkflowFilter( array( 'workflow' => 'userSelected' ), array( P4Cms_Content::fetchAll()->invoke('getTitle'), P4Cms_Content::fetchAll()->invoke('getTitle') ) ); }
Workflow_Test_ContentIntegrationTest::testScheduledContentEdit | ( | ) |
Ensure edition shows scheduled state if entry has scheduled transition.
{ $this->utility->impersonate('editor'); // if entry has scheduled transition, ensure that target state of scheduled transition is // checked $entry = $this->_makeContentEntry('review', '', 'draft', '1'); $this->dispatch('/content/edit/id/' . $entry->getId()); $this->assertQuery('#workflow-state-draft[checked="checked"]'); }
Workflow_Test_ContentIntegrationTest::testSubFormElementsCollision | ( | ) |
Ensure that if there are elements in the sub-forms with names matching entry fields, then they are not populated with those values.
{ $this->utility->impersonate('editor'); // save entry with a comment field that collides with // comment input element in the workflow sub-form $entry = P4Cms_Content::store( array( 'id' => 'test', 'contentType' => 'basic-page', 'title' => 'test-title', 'workflowState' => 'published', 'comment' => 'comment_test' ) ); // ensure workflow comment field is not populated with comment_test value // when editing a content that has associated workflow $this->dispatch('/content/edit/id/' . $entry->getId()); $this->assertNotQueryContentContains( "textarea#workflow-comment", 'comment_test', "Expected workflow comment doesn't contain entry's comment value." ); }
Workflow_Test_ContentIntegrationTest::testWorkflowActions | ( | ) |
Verify transition actions.
Dispatch to content edit action to simulate updating content entry and ensure transition actions are invoked.
{ // test with simple workflow added by SendEmail action to a certain transitions $workflow = Workflow_Model_Workflow::fetch('simple'); $workflowStates = $workflow->getStates(); // add sendEmail action to the review->published and review->draft transitions $workflowStates['review']['transitions']['published']['actions'] = array( 'sendEmail' => array( 'to' => 'published@email.com', 'subject' => 'content published' ) ); $workflowStates['review']['transitions']['draft']['actions'] = array( 'sendEmail' => array( 'to' => 'draft@email.com', 'subject' => 'content demoted to draft' ) ); $workflow->setStates($workflowStates) ->save(); // set custom email transport to prevent from sending real emails and to allow // checking what emails would be sent $transport = new Workflow_Test_MailTransport; Zend_Mail::setDefaultTransport($transport); // set necessary permissions $this->utility->impersonate('editor'); // create new entry $entry = $this->_makeContentEntry(); // edit entry to promote to review state $params = array( 'contentType' => 'basic-page', 'title' => 'test-title', 'workflow' => array( 'state' => 'review', 'scheduled' => 'false' ) ); $this->request->setMethod('POST'); $this->request->setPost($params); $this->dispatch('/content/edit/format/dojoio/id/' . $entry->getId()); // ensure entry has been modified $entry = P4Cms_Content::fetch($entry->getId()); $this->assertSame( 'review', $entry->getValue('workflowState'), "Expected workflow state has been changed to review." ); // ensure email has not been sent $this->assertSame( 0, count($transport->getSentMails()), "Expected no sendEmail action has occured." ); // publish content $transport->reset(); $this->resetRequest() ->resetResponse(); $params = array( 'contentType' => 'basic-page', 'title' => 'test-title', 'workflow' => array( 'state' => 'published', 'scheduled' => 'false' ) ); $this->request->setMethod('POST'); $this->request->setPost($params); $this->dispatch('/content/edit/format/dojoio/id/' . $entry->getId()); // ensure entry has been updated $entry = P4Cms_Content::fetch($entry->getId()); $this->assertSame( 'published', $entry->getValue('workflowState'), "Expected workflow state has been changed to published." ); // ensure correct email has been sent $sentEmails = $transport->getSentMails(); $this->assertSame( 1, count($sentEmails), "Expected sendEmail action has occured." ); // verify email recipient and subject $this->assertSame( 'published@email.com', $sentEmails[0]['to'], "Expected email recipient." ); $this->assertSame( 'content published', $sentEmails[0]['subject'], "Expected email subject." ); // ensure actions are not invoked if transition conditions are not met $workflowStates['published']['transitions']['review']['actions'] = array( 'sendEmail' => array( 'to' => 'demote@email.com', 'subject' => 'published -> review' ) ); $workflowStates['published']['transitions']['review']['conditions'] = array('false'); $workflow->setStates($workflowStates) ->save(); // try to demote content to review $transport->reset(); $this->resetRequest() ->resetResponse(); $params = array( 'contentType' => 'basic-page', 'title' => 'test-title', 'workflow' => array( 'state' => 'review', 'scheduled' => 'false' ) ); $this->request->setMethod('POST'); $this->request->setPost($params); $this->dispatch('/content/edit/format/dojoio/id/' . $entry->getId()); // ensure entry has not been modified $entry = P4Cms_Content::fetch($entry->getId()); $this->assertSame( 'published', $entry->getValue('workflowState'), "Expected workflow state has not been changed to review." ); // ensure email has not been sent $sentEmails = $transport->getSentMails(); $this->assertSame( 0, count($sentEmails), "Expected sendEmail action has not occured." ); }
Workflow_Test_ContentIntegrationTest::testWorkflowConditions | ( | ) |
Verify transition conditions.
Dispatch to content add/edit action to simulate creating/updating content entry when certain transition conditions apply.
{ // create workflow we will test against - // modify simple workflow to remove published to draft transition $workflow = Workflow_Model_Workflow::fetch('simple'); $workflowStates = $workflow->getStates(); unset($workflowStates['published']['transitions']['draft']); $workflow->setStates($workflowStates) ->save(); // set necessary permissions $this->utility->impersonate('editor'); // verify all transitions are available when adding a new content $this->dispatch('/add/type/basic-page'); $this->_verifyWorkflowStatesRadio(array('draft', 'review', 'published'), 'draft'); // disable promoting to review $states = $workflowStates; $states['draft']['transitions']['review']['conditions'] = array('false'); $workflow->setStates($states) ->save(); $this->resetRequest() ->resetResponse(); $this->dispatch('/add/type/basic-page'); $this->_verifyWorkflowStatesRadio(array('draft', 'published'), 'draft'); // test with edit action $entry = $this->_makeContentEntry('review'); $workflow->setStates($workflowStates) ->save(); $this->resetRequest() ->resetResponse(); $this->dispatch('/content/index/edit/id/' . $entry->getId()); $this->_verifyWorkflowStatesRadio(array('draft', 'review', 'published'), 'review'); // add Contains condition $states = $workflowStates; $states['review']['transitions']['published']['conditions'] = array( 'contains' => array( 'string' => 'find me' ) ); $workflow->setStates($states) ->save(); $this->resetRequest() ->resetResponse(); $this->dispatch('/content/index/edit/id/' . $entry->getId()); $this->_verifyWorkflowStatesRadio(array('draft', 'review'), 'review'); // modify entry to satisfy the condition $entry = P4Cms_Content::fetch($entry->getId()); $entry->setValue('body', 'Now body contains find me string.') ->save(); $this->resetRequest() ->resetResponse(); $this->dispatch('/content/index/edit/id/' . $entry->getId()); $this->_verifyWorkflowStatesRadio(array('draft', 'review', 'published'), 'review'); // try to modify content via post to ensure transition conditions must be met // also ensure conditions are evaluated agains posted data $this->resetRequest() ->resetResponse(); $params = array( 'contentType' => 'basic-page', 'title' => 'test-title', 'body' => 'new body', 'workflow' => array( 'state' => 'published', 'scheduled' => 'false' ) ); $this->request->setParam('id', $entry->getId()); $this->request->setMethod('POST'); $this->request->setPost($params); $this->dispatch('/content/edit/format/dojoio/id/' . $entry->getId()); // verify entry has not been modified $entry = P4Cms_Content::fetch($entry->getId()); $this->assertSame( 'review', $entry->getValue('workflowState'), "Expected workflow state has not changed as transition is invalid." ); // try again with no changes made so it should work $this->resetRequest() ->resetResponse(); $params = array( 'contentType' => 'basic-page', 'title' => 'test-title', 'body' => 'changed body to contain find me string', 'workflow' => array( 'state' => 'published', 'scheduled' => 'false' ) ); $this->request->setMethod('POST'); $this->request->setPost($params); $this->dispatch('/content/edit/format/dojoio/id/' . $entry->getId()); $responseBody = $this->response->getBody(); $this->assertModule('content', 'Last module run should be content module.'. $responseBody); $this->assertController('index', 'Expected controller.'. $responseBody); $this->assertAction('edit', 'Expected action.'. $responseBody); // verify entry has been modified $entry = P4Cms_Content::fetch($entry->getId()); $this->assertSame( 'published', $entry->getValue('workflowState'), "Expected workflow state has been changed as transition is valid." ); // check state options $this->resetRequest() ->resetResponse(); $this->dispatch('/content/index/edit/id/' . $entry->getId()); $this->_verifyWorkflowStatesRadio(array('review', 'published'), 'published'); }