Perforce Chronicle 2012.2/486814
API Documentation

Workflow_Test_WorkflowTest Class Reference

Test the workflow model. More...

List of all members.

Public Member Functions

 testAccessors ()
 Test accessors.
 testDetectTransitionOn ()
 Test detectTransitionOn() method.
 testFetchTypeMap ()
 Verify fetchTypeMap() method outputs correct content-type => workflow mapping.
 testGetDefaultState ()
 Test getDefaultState() method.
 testGetSetScheduledData ()
 Test getters/setters for manipulation with scheduled data.
 testGetSetStateOf ()
 Test (set|get)StateOf() methods.
 testGetState ()
 Test hasState()/getState()/getStateModel() methods.
 testInstallRemoveDefaults ()
 Test installation and removal of default workflows.
 testInvalidTypeIsUnpublished ()
 Verify that content entries with an invalid content type are unpublished.
 testMakeScheduledContentFilter ()
 Test for makeScheduledContentFilter() method.
 testMutators ()
 Test mutators.

Protected Member Functions

 _generateWorkflowDefinition (array $stateTransitions)
 Helper method to generate simplified workflow definition.

Detailed Description

Test the workflow model.

Copyright:
2011-2012 Perforce Software. All rights reserved
License:
Please see LICENSE.txt in top-level folder of this distribution.
Version:
2012.2/486814

Member Function Documentation

Workflow_Test_WorkflowTest::_generateWorkflowDefinition ( array $  stateTransitions) [protected]

Helper method to generate simplified workflow definition.

Parameters:
array$stateTransitionslist with state transitions
Returns:
array simplified workflow definition
    {
        $definition = array();
        foreach ($stateTransitions as $state => $transitions) {
            $data = array(
                'label' => "$state state",
            );
            foreach ($transitions as $transition) {
                $data['transitions'][$transition] = array(
                    'label' => "$state to $transition"
                );
            }

            $definition['states'][$state] = $data;
        }

        return $definition;
    }
Workflow_Test_WorkflowTest::testAccessors ( )

Test accessors.

    {
        // add workflow record
        $modelData = array(
            'id'            => "test",
            'label'         => "test label",
            'description'   => "test description",
            'states'        => "[foo]\nlabel=foo state\n[bar]\nlabel=bar state"
        );
        Workflow_Model_Workflow::store($modelData);

        // fetch saved workflow
        $workflow = Workflow_Model_Workflow::fetch('test');

        $this->assertSame(
            $modelData['label'],
            $workflow->getLabel(),
            "Expected workflow label name."
        );
        $this->assertSame(
            $modelData['description'],
            $workflow->getDescription(),
            "Expected workflow description."
        );
        $this->assertSame(
            $modelData['states'],
            $workflow->getStatesAsIni(),
            "Expected workflow states in INI."
        );

        // getStates() should return array of state definitions
        $states = $workflow->getStates();
        $this->assertTrue(
            is_array($states),
            "Expected array returned by getState() method."
        );

        // getStateModels() should return iterator with workflow state objects
        $states = $workflow->getStateModels();
        $this->assertTrue(
            $states instanceof P4Cms_Model_Iterator,
            "Expected class type returned by getState() method."
        );

        $this->assertEquals(
            2,
            $states->count(),
            "Expected number of workflow states."
        );

        foreach ($states as $state) {
            $this->assertTrue(
                $state instanceof Workflow_Model_State,
                "Expected class type of workflow state item."
            );
        }
    }
Workflow_Test_WorkflowTest::testDetectTransitionOn ( )

Test detectTransitionOn() method.

    {
        // create workflow with states a, b, c allowing following transitions:
        // a->b, a->c, b->c, c->a
        $workflow = Workflow_Model_Workflow::create(
            $this->_generateWorkflowDefinition(
                array(
                    'a' => array('b', 'c'),
                    'b' => array('c'),
                    'c' => array('a')
                )
            )
        );

        // create content type
        $type = P4Cms_Content_Type::store(
            array(
                'id'        => 'ct',
                'elements'  => array(
                    'title' => array('type' => 'text')
                )
            )
        );

        // define tests suite
        $tests = array(
            array(
                'savedValues'           => array(
                    'contentType'       => $type->getId(),
                ),
                'changedValues'         => array(
                    'workflowState'     => 'a'
                ),
                'expected'              => null,
                'message'               => __LINE__ . ": invalid from state, valid to state."
            ),
            array(
                'savedValues'           => array(
                    'contentType'       => $type->getId(),
                    'workflowState'     => 'a'
                ),
                'changedValues'         => array(
                    'workflowState'     => 'unknown'
                ),
                'expected'              => null,
                'message'               => __LINE__ . ": valid from state, invalid to state."
            ),
            array(
                'savedValues'           => array(
                    'contentType'       => $type->getId(),
                    'workflowState'     => 'notvalid'
                ),
                'changedValues'         => array(
                    'workflowState'     => 'unknown'
                ),
                'expected'              => null,
                'message'               => __LINE__ . ": invalid from state, invalid to state."
            ),
            array(
                'savedValues'           => array(
                    'contentType'       => $type->getId(),
                    'workflowState'     => 'a'
                ),
                'changedValues'         => array(
                    'workflowState'     => 'b'
                ),
                'expected'              => 'a to b',
                'message'               => __LINE__ . ": valid transiton a -> b."
            ),
            array(
                'savedValues'           => array(
                    'contentType'       => $type->getId(),
                    'workflowState'     => 'a'
                ),
                'changedValues'         => array(
                    'workflowState'     => 'a'
                ),
                'expected'              => null,
                'message'               => __LINE__ . ": same from- and to states."
            )
        );

        // run tests
        foreach ($tests as $test) {
            // create content
            $content = P4Cms_Content::store($test['savedValues']);

            // modify record values and save while in batch
            $adapter = $content->getAdapter();
            $adapter->beginBatch('test');
            $content->setValues($test['changedValues']);
            $content->save();

            // detect transition
            $transition = $workflow->detectTransitionOn($content);

            // get transition label if transition is object
            if ($transition instanceof Workflow_Model_Transition) {
                $transition = $transition->getLabel();
            }

            // verify transition
            $this->assertSame(
                $test['expected'],
                $transition,
                $test['message']
            );

            $adapter->revertBatch();
        }
    }
Workflow_Test_WorkflowTest::testFetchTypeMap ( )

Verify fetchTypeMap() method outputs correct content-type => workflow mapping.

    {
        // add few workflows
        $workflowX = Workflow_Model_Workflow::store(
            array(
                'id'            => "workflow-x",
                'label'         => "test x",
                'states'        => "[foo]\na=b"
            )
        );
        $workflowY = Workflow_Model_Workflow::store(
            array(
                'id'            => "workflow-y",
                'label'         => "test y",
                'states'        => "[foo]\na=b"
            )
        );

        // add few content types
        P4Cms_Content_Type::store(
            array(
                'id'        => "type-a",
                'elements'  => "[id]\ntype=text",
                'workflow'  => "workflow-x"
            )
        );
        P4Cms_Content_Type::store(
            array(
                'id'        => "type-b",
                'elements'  => "[id]\ntype=text"
            )
        );
        P4Cms_Content_Type::store(
            array(
                'id'        => "type-c",
                'elements'  => "[id]\ntype=text",
                'workflow'  => "workflow-y"
            )
        );
        P4Cms_Content_Type::store(
            array(
                'id'        => "type-d",
                'elements'  => "[id]\ntype=text",
                'workflow'  => "workflow-x"
            )
        );

        $map      = Workflow_Model_Workflow::fetchTypeMap();
        $expected = array(
            'type-a' => $workflowX->toArray(),
            'type-c' => $workflowY->toArray(),
            'type-d' => $workflowX->toArray(),
        );

        $this->assertTrue(
            $map instanceof P4Cms_Model_Iterator,
            "Expected map instance type."
        );

        $this->assertSame(
            $expected,
            $map->toArray(),
            "Expected map array structure."
        );
    }
Workflow_Test_WorkflowTest::testGetDefaultState ( )

Test getDefaultState() method.

    {
        Workflow_Model_Workflow::store(
            array(
                'id'            => "test1",
                'label'         => "test label",
                'states'        => "[first]\n[second]\n[third]\n"
            )
        );

        $defaultState = Workflow_Model_Workflow::fetch('test1')->getDefaultState();
        $this->assertTrue(
            $defaultState instanceof Workflow_Model_State,
            "Expected class type of default state #1."
        );
        $this->assertSame(
            'first',
            $defaultState->getId(),
            "Expected id of the default state #1."
        );

        Workflow_Model_Workflow::store(
            array(
                'id'            => "test2",
                'label'         => "test label",
                'description'   => "test description",
                'states'        => "[one]\ntwo=2\n[two]one=1\ntwo=2"
            )
        );

        $defaultState = Workflow_Model_Workflow::fetch('test2')->getDefaultState();
        $this->assertTrue(
            $defaultState instanceof Workflow_Model_State,
            "Expected class type of default state #2."
        );
        $this->assertSame(
            'one',
            $defaultState->getId(),
            "Expected id of the default state #2."
        );
    }
Workflow_Test_WorkflowTest::testGetSetScheduledData ( )

Test getters/setters for manipulation with scheduled data.

    {
        $this->utility->impersonate('editor');

        // create workflow states a,b,c and with transitions a->b, a->c, b->c
        $workflow = Workflow_Model_Workflow::create(
            $this->_generateWorkflowDefinition(
                array(
                    'a' => array('b', 'c'),
                    'b' => array('c'),
                    'c' => array()
                )
            )
        );

        $record = P4Cms_Content::store(
            array(
                'id'            => 1,
                'contentType'   => 'test',
                'workflowState' => 'a'
            )
        );

        // ensure exception is thrown when try to set invalid scheduled state
        try {
            $workflow->setScheduledStateOf($record, 'none', 123);
        } catch (Workflow_Exception $e) {
            // expected exception
            $this->assertSame(
                "Cannot set state on the given record. State is undefined or governed by other workflow.",
                $e->getMessage(),
                "Expected invalid state exception"
            );
        } catch (Exception $e) {
            $this->fail("Unexpected exception thrown.");
        }

        // prepare timestamp points to the future
        $time = time() + 10;

        // ensure exception is thrown when timestamp has invalid format
        try {
            $workflow->setScheduledStateOf($record, 'b', "$time");
        } catch (InvalidArgumentException $e) {
            // expected exception
            $this->assertSame(
                "Cannot schedule transition. Time must be an integer timestamp in the future.",
                $e->getMessage(),
                "Expected invalid timestamp exception"
            );
        } catch (Exception $e) {
            $this->fail("Unexpected exception thrown.");
        }

        try {
            $workflow->setScheduledStateOf($record, 'b', -1);
        } catch (InvalidArgumentException $e) {
            // expected exception
            $this->assertSame(
                "Cannot schedule transition. Time must be an integer timestamp in the future.",
                $e->getMessage(),
                "Expected invalid timestamp exception"
            );
        } catch (Exception $e) {
            $this->fail("Unexpected exception thrown.");
        }

        // set valid scheduled transition
        $workflow->setScheduledStateOf($record, 'b', $time);
        $record->save();

        $record->fetch(1);
        $this->assertSame('a', $workflow->getStateOf($record)->getId(), 'Expected current state');
        $this->assertSame('b', $workflow->getScheduledStateOf($record)->getId(), 'Expected scheduled state');
        $this->assertSame($time, $workflow->getScheduledTimeOf($record), 'Expected scheduled time');
    }
Workflow_Test_WorkflowTest::testGetSetStateOf ( )

Test (set|get)StateOf() methods.

    {
        // create workflow states a,b,c and with transitions a->b, a->c, b->c
        $workflow = Workflow_Model_Workflow::create(
            $this->_generateWorkflowDefinition(
                array(
                    'a' => array('b', 'c'),
                    'b' => array('c'),
                    'c' => array()
                )
            )
        );

        // create content type
        $type = P4Cms_Content_Type::store(
            array(
                'id'        => 'test',
                'elements'  => array(
                    'title' => array('type' => 'text')
                )
            )
        );

        $record = P4Cms_Content::create(
            array(
                'contentType'   => 'test',
                'workflowState' => 'b'
            )
        );

        // ensure exception is thrown when try to set invalid state
        try {
            $workflow->setStateOf($record, 'none');
        } catch (Workflow_Exception $e) {
            // expected exception
            $this->assertSame(
                "Cannot set state on the given record. State is undefined or governed by other workflow.",
                $e->getMessage(),
                "Expected invalid state exception"
            );
        } catch (Exception $e) {
            $this->fail("Unexpected exception thrown.");
        }

        $this->assertSame(
            'b',
            $workflow->getStateOf($record)->getId(),
            "Expected current state."
        );

        // ensure exception is thrown when invalid transition
        try {
            $workflow->setStateOf($record, 'a');
        } catch (Workflow_Exception $e) {
            // expected exception
            $this->assertSame(
                "Cannot set state on the given record. Not a valid transition.",
                $e->getMessage(),
                "Expected invalid transition exception"
            );
        } catch (Exception $e) {
            $this->fail("Unexpected exception thrown.");
        }

        $this->assertSame(
            'b',
            $workflow->getStateOf($record)->getId(),
            "Expected current state."
        );

        // set valid state
        $workflow->setStateOf($record, 'c');
        $this->assertSame(
            'c',
            $workflow->getStateOf($record)->getId(),
            "Expected current state."
        );
    }
Workflow_Test_WorkflowTest::testGetState ( )

Test hasState()/getState()/getStateModel() methods.

    {
        Workflow_Model_Workflow::store(
            array(
                'id'            => "test",
                'label'         => "test label",
                'description'   => "test description",
                'states'        => "[foo]\na=b\n[bar]a.1=c\na.2=de\nx=yz"
            )
        );

        $workflow = Workflow_Model_Workflow::fetch('test');

        $this->assertTrue(
            $workflow->hasState('foo'),
            "Expected 'foo' is one of the workflow states."
        );
        $this->assertSame(
            array('a' => 'b'),
            $workflow->getState('foo'),
            "Expected value returned for getState('foo')."
        );

        $this->assertTrue(
            $workflow->getStateModel('foo') instanceof Workflow_Model_State,
            "Expected class type of 'foo' state model."
        );

        $this->assertTrue(
            $workflow->hasState('bar'),
            "Expected 'bar' is one of the workflow states."
        );
        $this->assertSame(
            array('a' => array (1 => 'c', 2 => 'de'), 'x' => 'yz'),
            $workflow->getState('bar'),
            "Expected value returned for getState('bar')."
        );

        $this->assertTrue(
            $workflow->getStateModel('bar') instanceof Workflow_Model_State,
            "Expected class type of 'bar' state model."
        );

        $this->assertFalse(
            $workflow->hasState('noexist'),
            "Expected 'noexist' is not one of the workflow states."
        );

        try {
            $workflow->getState('noexist');
            $this->fail('Expected throwing an exception when tried to get non-existent state.');
        } catch (Workflow_Exception $e) {
            // expected exception
        }

        try {
            $workflow->getStateModel('noexist');
            $this->fail('Expected throwing an exception when tried to get non-existent state model.');
        } catch (Workflow_Exception $e) {
            // expected exception
        }
    }
Workflow_Test_WorkflowTest::testInstallRemoveDefaults ( )

Test installation and removal of default workflows.

    {
        $this->assertSame(
            0,
            Workflow_Model_Workflow::count(),
            "Expected no workflows yet."
        );

        $package = P4Cms_Module::fetch('workflow');
        Workflow_Model_Workflow::installPackageDefaults($package);

        $this->assertSame(
            1,
            Workflow_Model_Workflow::count(),
            "Expected one workflow."
        );

        // ensure workflow has id 'simple'.
        $this->assertTrue(Workflow_Model_Workflow::exists('simple'));

        // verify installed workflow has three states:
        // Draft, Review, Published
        $workflow = Workflow_Model_Workflow::fetch('simple');
        $this->assertSame(
            $workflow->getStateModels()->invoke('getLabel'),
            array('Draft', 'Review', 'Published')
        );

        // remove defaults.
        Workflow_Model_Workflow::removePackageDefaults($package);
        $this->assertFalse(Workflow_Model_Workflow::exists('simple'));

        // ensure workflow is not removed if it was edited.
        Workflow_Model_Workflow::installPackageDefaults($package);
        $workflow = Workflow_Model_Workflow::fetch('simple');
        $workflow->setLabel('modified')->save();
        Workflow_Model_Workflow::removePackageDefaults($package);
        $this->assertTrue(Workflow_Model_Workflow::exists('simple'));
    }
Workflow_Test_WorkflowTest::testInvalidTypeIsUnpublished ( )

Verify that content entries with an invalid content type are unpublished.

    {
        P4Cms_Content::store(
            array(
                'contentType'            => 'made-up',
                'title'                  => 'so fake',
                'workflowState'          => Workflow_Model_State::PUBLISHED
            )
        );
        $this->assertSame(
            0,
            P4Cms_Content::count(),
            'expected no hits when type does not exist'
        );

        // now add the type and try it with only the workflow missing
        $type = new P4Cms_Content_Type;
        $type->setId('made-up')
             ->setValue('workflow', 'fake')
             ->save();

        $this->assertSame(
            0,
            P4Cms_Content::count(),
            'expected no hits when workflow does not exist'
        );

        // try with all items but no published state
        $workflow = new Workflow_Model_Workflow;
        $workflow->setId('fake')
                 ->setValues($this->_generateWorkflowDefinition(array('draft' => array('review'))))
                 ->save();
        $this->assertSame(
            0,
            P4Cms_Content::count(),
            'expected no hits when workflow does not have a published state'
        );

        // test it works when we have a published state
        $workflow->setValues($this->_generateWorkflowDefinition(array('published' => array('super-published'))))
                 ->save();
        $this->assertSame(
            1,
            P4Cms_Content::count(),
            'expected a hit when everything is in place'
        );
    }
Workflow_Test_WorkflowTest::testMakeScheduledContentFilter ( )

Test for makeScheduledContentFilter() method.

    {
        // these are unpublished entries, impersonate an editor so we can see them
        $this->utility->impersonate('editor');

        // create testing entries
        // +---------------+--------------+-----------------+-------------------+
        // | CONTENT TITLE | STATE        | SCHEDULED STATE | SCHEDULED TIME    |
        // +---------------+--------------+-----------------+-------------------+
        // | a             | draft        | review          |  1. 1.2010 12:00  |
        // | b             | draft        | published       |  1. 2.2010 15:00  |
        // | c             | draft        | review          |  1. 1.2011 12:00  |
        // | d             | draft        | -               | 31.12.2009 23:00  |
        // | e             | draft        | published       |                -  |
        // | f             | draft        | -               |                -  |
        // | g             | draft        | review          |  2. 1.2011 12:00  |
        // | h             | -            | published       |  2. 1.2012 12:00  |
        // +---------------+--------------+-----------------+-------------------+

        $entries = array(
            array('a', 'draft', 'review',    strtotime('2010-01-01 12:00')),
            array('b', 'draft', 'published', strtotime('2010-02-01 15:00')),
            array('c', 'draft', 'review',    strtotime('2011-01-01 12:00')),
            array('d', 'draft', '',          strtotime('2009-12-31 23:00')),
            array('e', 'draft', 'published', ''),
            array('f', 'draft', '',          ''),
            array('g', 'draft', 'review',    strtotime('2011-01-02 12:00')),
            array('h', '',      'published', strtotime('2012-01-02 12:00')),
        );

        // make a test workflow and type
        $workflow = Workflow_Model_Workflow::store(
            $this->_generateWorkflowDefinition(
                array('draft' => array('published'), 'published' => array('draft'))
            )
        );
        $type = new P4Cms_Content_Type;
        $type->setId('basic')
             ->setValue('workflow', $workflow->getId())
             ->save();

        foreach ($entries as $entry) {
            P4Cms_Content::store(
                array(
                    'contentType'            => 'basic',
                    'title'                  => $entry[0],
                    'workflowState'          => $entry[1],
                    'workflowScheduledState' => $entry[2],
                    'workflowScheduledTime'  => $entry[3]
                )
            );
        }

        // get all contents with scheduled transitions before 1999-01-01 00:00
        $query = P4Cms_Record_Query::create()
            ->addFilter(
                Workflow_Model_Workflow::makeScheduledContentFilter(strtotime('1999-01-01 00:00'))
            );

        $result = P4Cms_Content::fetchAll($query)->sortBy('title')->invoke('getTitle');
        $this->assertSame(
            array(),
            $result,
            'Expected entries filtered by scheduled transitions #1.'
        );

        // get all contents with scheduled transitions before 2010-02-01 14:59
        $query = P4Cms_Record_Query::create()
            ->addFilter(
                Workflow_Model_Workflow::makeScheduledContentFilter(strtotime('2010-02-01 14:59'))
            );

        $result = P4Cms_Content::fetchAll($query)->sortBy('title')->invoke('getTitle');
        $this->assertSame(
            array('a'),
            $result,
            'Expected entries filtered by scheduled transitions #2.'
        );

        // get all contents with scheduled transitions before 2011-01-01 00:00
        $query = P4Cms_Record_Query::create()
            ->addFilter(
                Workflow_Model_Workflow::makeScheduledContentFilter(strtotime('2011-01-01 00:00'))
            );

        $result = P4Cms_Content::fetchAll($query)->sortBy('title')->invoke('getTitle');
        $this->assertSame(
            array('a', 'b'),
            $result,
            'Expected entries filtered by scheduled transitions #3.'
        );

        // get all contents with scheduled transitions before 2012-01-01 23:00
        $query = P4Cms_Record_Query::create()
            ->addFilter(
                Workflow_Model_Workflow::makeScheduledContentFilter(strtotime('2012-01-01 23:00'))
            );

        $result = P4Cms_Content::fetchAll($query)->sortBy('title')->invoke('getTitle');
        $this->assertSame(
            array('a', 'b', 'c', 'g'),
            $result,
            'Expected entries filtered by scheduled transitions #4.'
        );

        // get all contents with scheduled transitions before 2025-01-01 17:45
        $query = P4Cms_Record_Query::create()
            ->addFilter(
                Workflow_Model_Workflow::makeScheduledContentFilter(strtotime('2025-01-01 17:45'))
            );

        $result = P4Cms_Content::fetchAll($query)->sortBy('title')->invoke('getTitle');
        $this->assertSame(
            array('a', 'b', 'c', 'g', 'h'),
            $result,
            'Expected entries filtered by scheduled transitions #5.'
        );
    }
Workflow_Test_WorkflowTest::testMutators ( )

Test mutators.

    {
        $workflow = new Workflow_Model_Workflow(array('id' => 'foo'));
        $workflow->setLabel('foo label')
                 ->setDescription('foo description')
                 ->save();

        // fetch and verify values
        $values = Workflow_Model_Workflow::fetch('foo')->getValues();
        $this->assertSame(
            'foo',
            $values['id'],
            "Expected workflow id."
        );
        $this->assertSame(
            'foo label',
            $values['label'],
            "Expected workflow label."
        );
        $this->assertSame(
            'foo description',
            $values['description'],
            "Expected workflow description."
        );
        $this->assertTrue(
            is_array($values['states']),
            "Expected type of states field #1."
        );

        // set states as string in INI format
        $workflow->setStates("[bar]\nlabel=test")
                 ->save();

        // fetch and verify states
        $values = Workflow_Model_Workflow::fetch('foo')->getValues();
        $this->assertTrue(
            is_array($values['states']),
            "Expected type of states field #2."
        );
        $this->assertEquals(
            1,
            count($values['states']),
            "Expected number of workflow states #2."
        );

        // verify that workflow state has reference to workflow
        $state = $workflow->getStateModels()->current();
        $this->assertTrue(
            $state->getValue('workflow') instanceof Workflow_Model_Workflow,
            "Expected type of state workflow field #2."
        );
        $this->assertSame(
            'foo',
            $state->getValue('workflow')->getId(),
            "Expected workflow state references correct workflow instance #2."
        );

        // set states as null
        $workflow->setStates(null)
                 ->save();

        // fetch and verify states
        $values = Workflow_Model_Workflow::fetch('foo')->getValues();
        $this->assertTrue(
            is_array($values['states']),
            "Expected type of states field."
        );
        $this->assertSame(
            array(),
            $values['states'],
            "Expected no states."
        );

        // set states as array
        $statesArray = array(
            'bar' => array(
                'label' => 'bar state',
                'foo'   => 'temp'
            ),
            'baz' => array(
                'label' => 'bazz'
            )
        );
        $workflow->setStates($statesArray)
                 ->save();

        // fetch and verify states
        $values = Workflow_Model_Workflow::fetch('foo')->getValues();
        $this->assertTrue(
            is_array($values['states']),
            "Expected type of states field #3."
        );
        $this->assertEquals(
            2,
            count($values['states']),
            "Expected number of workflow states #3."
        );

        // verify that workflow states have reference to workflow
        foreach ($workflow->getStateModels() as $state) {
            $this->assertTrue(
                $state->getValue('workflow') instanceof Workflow_Model_Workflow,
                "Expected type of state workflow field #3 ({$state->getId()})."
            );
            $this->assertSame(
                'foo',
                $state->getValue('workflow')->getId(),
                "Expected workflow state references correct workflow instance #3 ({$state->getId()})."
            );
        }
    }

The documentation for this class was generated from the following file: