3 namespace Drupal\Tests\workflows\Unit;
5 use Drupal\Core\DependencyInjection\ContainerBuilder;
6 use Drupal\Tests\UnitTestCase;
7 use Drupal\workflow_type_test\Plugin\WorkflowType\TestType;
8 use Drupal\workflows\Entity\Workflow;
9 use Drupal\workflows\State;
10 use Drupal\workflows\Transition;
11 use Drupal\workflows\WorkflowTypeManager;
12 use Prophecy\Argument;
15 * @coversDefaultClass \Drupal\workflows\Plugin\WorkflowTypeBase
19 class WorkflowTest extends UnitTestCase {
24 protected function setUp() {
26 // Create a container so that the plugin manager and workflow type can be
28 $container = new ContainerBuilder();
29 $workflow_manager = $this->prophesize(WorkflowTypeManager::class);
30 $workflow_manager->createInstance('test_type', Argument::any())->willReturn(new TestType([], '', []));
31 $container->set('plugin.manager.workflows.type', $workflow_manager->reveal());
32 \Drupal::setContainer($container);
39 public function testAddAndHasState() {
40 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
41 $this->assertFalse($workflow->getTypePlugin()->hasState('draft'));
43 // By default states are ordered in the order added.
44 $workflow->getTypePlugin()->addState('draft', 'Draft');
45 $this->assertTrue($workflow->getTypePlugin()->hasState('draft'));
46 $this->assertFalse($workflow->getTypePlugin()->hasState('published'));
47 $this->assertEquals(0, $workflow->getTypePlugin()->getState('draft')->weight());
48 // Adding a state does not set up a transition to itself.
49 $this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'draft'));
51 // New states are added with a new weight 1 more than the current highest
53 $workflow->getTypePlugin()->addState('published', 'Published');
54 $this->assertEquals(1, $workflow->getTypePlugin()->getState('published')->weight());
60 public function testAddStateException() {
61 $this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' already exists in workflow.");
62 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
63 $workflow->getTypePlugin()->addState('draft', 'Draft');
64 $workflow->getTypePlugin()->addState('draft', 'Draft');
70 public function testAddStateInvalidIdException() {
71 $this->setExpectedException(\InvalidArgumentException::class, "The state ID 'draft-draft' must contain only lowercase letters, numbers, and underscores");
72 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
73 $workflow->getTypePlugin()->addState('draft-draft', 'Draft');
79 public function testGetStates() {
80 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
82 // Getting states works when there are none.
83 $this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getStates()));
84 $this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getStates([])));
88 ->addState('draft', 'Draft')
89 ->addState('published', 'Published')
90 ->addState('archived', 'Archived');
92 // States are stored in alphabetical key order.
93 $this->assertArrayEquals([
97 ], array_keys($workflow->getTypePlugin()->getConfiguration()['states']));
99 // Ensure we're returning state objects.
100 $this->assertInstanceOf(State::class, $workflow->getTypePlugin()->getStates()['draft']);
102 // Passing in no IDs returns all states.
103 $this->assertArrayEquals(['draft', 'published', 'archived'], array_keys($workflow->getTypePlugin()->getStates()));
105 // The order of states is by weight.
106 $workflow->getTypePlugin()->setStateWeight('published', -1);
107 $this->assertArrayEquals(['published', 'draft', 'archived'], array_keys($workflow->getTypePlugin()->getStates()));
109 // The label is also used for sorting if weights are equal.
110 $workflow->getTypePlugin()->setStateWeight('archived', 0);
111 $this->assertArrayEquals(['published', 'archived', 'draft'], array_keys($workflow->getTypePlugin()->getStates()));
113 // You can limit the states returned by passing in states IDs.
114 $this->assertArrayEquals(['archived', 'draft'], array_keys($workflow->getTypePlugin()->getStates(['draft', 'archived'])));
116 // An empty array does not load all states.
117 $this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getStates([])));
121 * Test numeric IDs when added to a workflow.
123 public function testNumericIdSorting() {
124 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
125 $workflow_type = $workflow->getTypePlugin();
127 $workflow_type->addState('1', 'One');
128 $workflow_type->addState('2', 'Two');
129 $workflow_type->addState('3', 'ZZZ');
130 $workflow_type->addState('4', 'AAA');
132 $workflow_type->setStateWeight('1', 1);
133 $workflow_type->setStateWeight('2', 2);
134 $workflow_type->setStateWeight('3', 3);
135 $workflow_type->setStateWeight('4', 3);
137 // Ensure numeric states are correctly sorted by weight first, label second.
138 $this->assertEquals([1, 2, 4, 3], array_keys($workflow_type->getStates()));
142 * @covers ::getStates
144 public function testGetStatesException() {
145 $this->setExpectedException(\InvalidArgumentException::class, "The state 'state_that_does_not_exist' does not exist in workflow.");
146 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
147 $workflow->getTypePlugin()->getStates(['state_that_does_not_exist']);
153 public function testGetState() {
154 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
155 // By default states are ordered in the order added.
158 ->addState('draft', 'Draft')
159 ->addState('published', 'Published')
160 ->addState('archived', 'Archived')
161 ->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft')
162 ->addTransition('publish', 'Publish', ['draft'], 'published');
164 // Ensure we're returning state objects and they are set up correctly
165 $this->assertInstanceOf(State::class, $workflow->getTypePlugin()->getState('draft'));
166 $this->assertEquals('archived', $workflow->getTypePlugin()->getState('archived')->id());
167 $this->assertEquals('Archived', $workflow->getTypePlugin()->getState('archived')->label());
169 $draft = $workflow->getTypePlugin()->getState('draft');
170 $this->assertTrue($draft->canTransitionTo('draft'));
171 $this->assertTrue($draft->canTransitionTo('published'));
172 $this->assertFalse($draft->canTransitionTo('archived'));
173 $this->assertEquals('Publish', $draft->getTransitionTo('published')->label());
174 $this->assertEquals(0, $draft->weight());
175 $this->assertEquals(1, $workflow->getTypePlugin()->getState('published')->weight());
176 $this->assertEquals(2, $workflow->getTypePlugin()->getState('archived')->weight());
182 public function testGetStateException() {
183 $this->setExpectedException(\InvalidArgumentException::class, "The state 'state_that_does_not_exist' does not exist in workflow.");
184 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
185 $workflow->getTypePlugin()->getState('state_that_does_not_exist');
189 * @covers ::setStateLabel
191 public function testSetStateLabel() {
192 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
193 $workflow->getTypePlugin()->addState('draft', 'Draft');
194 $this->assertEquals('Draft', $workflow->getTypePlugin()->getState('draft')->label());
195 $workflow->getTypePlugin()->setStateLabel('draft', 'Unpublished');
196 $this->assertEquals('Unpublished', $workflow->getTypePlugin()->getState('draft')->label());
200 * @covers ::setStateLabel
202 public function testSetStateLabelException() {
203 $this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow.");
204 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
205 $workflow->getTypePlugin()->setStateLabel('draft', 'Draft');
209 * @covers ::setStateWeight
211 public function testSetStateWeight() {
212 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
213 $workflow->getTypePlugin()->addState('draft', 'Draft');
214 $this->assertEquals(0, $workflow->getTypePlugin()->getState('draft')->weight());
215 $workflow->getTypePlugin()->setStateWeight('draft', -10);
216 $this->assertEquals(-10, $workflow->getTypePlugin()->getState('draft')->weight());
220 * @covers ::setStateWeight
222 public function testSetStateWeightException() {
223 $this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow.");
224 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
225 $workflow->getTypePlugin()->setStateWeight('draft', 10);
229 * @covers ::setStateWeight
231 public function testSetStateWeightNonNumericException() {
232 $this->setExpectedException(\InvalidArgumentException::class, "The weight 'foo' must be numeric for state 'Published'.");
233 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
234 $workflow->getTypePlugin()->addState('published', 'Published');
235 $workflow->getTypePlugin()->setStateWeight('published', 'foo');
239 * @covers ::deleteState
241 public function testDeleteState() {
242 $workflow_type = new TestType([], '', []);
244 ->addState('draft', 'Draft')
245 ->addState('published', 'Published')
246 ->addState('archived', 'Archived')
247 ->addTransition('publish', 'Publish', ['draft', 'published'], 'published')
248 ->addTransition('create_new_draft', 'Create new draft', ['draft', 'published'], 'draft')
249 ->addTransition('archive', 'Archive', ['draft', 'published'], 'archived');
250 $this->assertCount(3, $workflow_type->getStates());
251 $this->assertCount(3, $workflow_type->getState('published')->getTransitions());
252 $workflow_type->deleteState('draft');
253 $this->assertFalse($workflow_type->hasState('draft'));
254 $this->assertCount(2, $workflow_type->getStates());
255 $this->assertCount(2, $workflow_type->getState('published')->getTransitions());
256 $workflow_type->deleteState('published');
257 $this->assertCount(0, $workflow_type->getTransitions());
261 * @covers ::deleteState
263 public function testDeleteStateException() {
264 $this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow.");
265 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
266 $workflow->getTypePlugin()->deleteState('draft');
270 * @covers ::deleteState
272 public function testDeleteOnlyStateException() {
273 $this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' can not be deleted from workflow as it is the only state");
274 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
275 $workflow->getTypePlugin()->addState('draft', 'Draft');
276 $workflow->getTypePlugin()->deleteState('draft');
280 * @covers ::addTransition
281 * @covers ::hasTransition
283 public function testAddTransition() {
284 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
286 // By default states are ordered in the order added.
289 ->addState('draft', 'Draft')
290 ->addState('published', 'Published');
292 $this->assertFalse($workflow->getTypePlugin()->getState('draft')->canTransitionTo('published'));
293 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft'], 'published');
294 $this->assertTrue($workflow->getTypePlugin()->getState('draft')->canTransitionTo('published'));
295 $this->assertEquals(0, $workflow->getTypePlugin()->getTransition('publish')->weight());
296 $this->assertTrue($workflow->getTypePlugin()->hasTransition('publish'));
297 $this->assertFalse($workflow->getTypePlugin()->hasTransition('draft'));
299 $workflow->getTypePlugin()->addTransition('save_publish', 'Save', ['published'], 'published');
300 $this->assertEquals(1, $workflow->getTypePlugin()->getTransition('save_publish')->weight());
304 * @covers ::addTransition
306 public function testAddTransitionDuplicateException() {
307 $this->setExpectedException(\InvalidArgumentException::class, "The transition 'publish' already exists in workflow.");
308 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
309 $workflow->getTypePlugin()->addState('published', 'Published');
310 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['published'], 'published');
311 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['published'], 'published');
315 * @covers ::addTransition
317 public function testAddTransitionInvalidIdException() {
318 $this->setExpectedException(\InvalidArgumentException::class, "The transition ID 'publish-publish' must contain only lowercase letters, numbers, and underscores");
319 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
320 $workflow->getTypePlugin()->addState('published', 'Published');
321 $workflow->getTypePlugin()->addTransition('publish-publish', 'Publish', ['published'], 'published');
325 * @covers ::addTransition
327 public function testAddTransitionMissingFromException() {
328 $this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow.");
329 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
330 $workflow->getTypePlugin()->addState('published', 'Published');
331 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft'], 'published');
335 * @covers ::addTransition
337 public function testAddTransitionDuplicateTransitionStatesException() {
338 $this->setExpectedException(\InvalidArgumentException::class, "The 'publish' transition already allows 'draft' to 'published' transitions in workflow.");
339 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
342 ->addState('draft', 'Draft')
343 ->addState('published', 'Published');
344 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft', 'published'], 'published');
345 $workflow->getTypePlugin()->addTransition('draft_to_published', 'Publish a draft', ['draft'], 'published');
349 * @covers ::addTransition
351 public function testAddTransitionConsistentAfterFromCatch() {
352 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
353 $workflow->getTypePlugin()->addState('published', 'Published');
355 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft'], 'published');
357 catch (\InvalidArgumentException $e) {
359 // Ensure that the workflow is not left in an inconsistent state after an
360 // exception is thrown from Workflow::setTransitionFromStates() whilst
361 // calling Workflow::addTransition().
362 $this->assertFalse($workflow->getTypePlugin()->hasTransition('publish'));
366 * @covers ::addTransition
368 public function testAddTransitionMissingToException() {
369 $this->setExpectedException(\InvalidArgumentException::class, "The state 'published' does not exist in workflow.");
370 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
371 $workflow->getTypePlugin()->addState('draft', 'Draft');
372 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft'], 'published');
376 * @covers ::getTransitions
377 * @covers ::setTransitionWeight
379 public function testGetTransitions() {
380 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
382 // Getting transitions works when there are none.
383 $this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getTransitions()));
384 $this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getTransitions([])));
386 // By default states are ordered in the order added.
391 ->addTransition('a_b', 'A to B', ['a'], 'b')
392 ->addTransition('a_a', 'A to A', ['a'], 'a');
394 // Transitions are stored in alphabetical key order in configuration.
395 $this->assertArrayEquals(['a_a', 'a_b'], array_keys($workflow->getTypePlugin()->getConfiguration()['transitions']));
397 // Ensure we're returning transition objects.
398 $this->assertInstanceOf(Transition::class, $workflow->getTypePlugin()->getTransitions()['a_a']);
400 // Passing in no IDs returns all transitions.
401 $this->assertArrayEquals(['a_b', 'a_a'], array_keys($workflow->getTypePlugin()->getTransitions()));
403 // The order of states is by weight.
404 $workflow->getTypePlugin()->setTransitionWeight('a_a', -1);
405 $this->assertArrayEquals(['a_a', 'a_b'], array_keys($workflow->getTypePlugin()->getTransitions()));
407 // If all weights are equal it will fallback to labels.
408 $workflow->getTypePlugin()->setTransitionWeight('a_a', 0);
409 $this->assertArrayEquals(['a_a', 'a_b'], array_keys($workflow->getTypePlugin()->getTransitions()));
410 $workflow->getTypePlugin()->setTransitionLabel('a_b', 'A B');
411 $this->assertArrayEquals(['a_b', 'a_a'], array_keys($workflow->getTypePlugin()->getTransitions()));
413 // You can limit the states returned by passing in states IDs.
414 $this->assertArrayEquals(['a_a'], array_keys($workflow->getTypePlugin()->getTransitions(['a_a'])));
416 // An empty array does not load all states.
417 $this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getTransitions([])));
421 * @covers ::getTransition
423 public function testGetTransition() {
424 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
425 // By default states are ordered in the order added.
428 ->addState('draft', 'Draft')
429 ->addState('published', 'Published')
430 ->addState('archived', 'Archived')
431 ->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft')
432 ->addTransition('publish', 'Publish', ['draft'], 'published');
434 // Ensure we're returning state objects and they are set up correctly
435 $this->assertInstanceOf(Transition::class, $workflow->getTypePlugin()->getTransition('create_new_draft'));
436 $this->assertEquals('publish', $workflow->getTypePlugin()->getTransition('publish')->id());
437 $this->assertEquals('Publish', $workflow->getTypePlugin()->getTransition('publish')->label());
439 $transition = $workflow->getTypePlugin()->getTransition('publish');
440 $this->assertEquals($workflow->getTypePlugin()->getState('draft'), $transition->from()['draft']);
441 $this->assertEquals($workflow->getTypePlugin()->getState('published'), $transition->to());
445 * @covers ::getTransition
447 public function testGetTransitionException() {
448 $this->setExpectedException(\InvalidArgumentException::class, "The transition 'transition_that_does_not_exist' does not exist in workflow.");
449 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
450 $workflow->getTypePlugin()->getTransition('transition_that_does_not_exist');
454 * @covers ::getTransitionsForState
456 public function testGetTransitionsForState() {
457 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
458 // By default states are ordered in the order added.
461 ->addState('draft', 'Draft')
462 ->addState('published', 'Published')
463 ->addState('archived', 'Archived')
464 ->addTransition('create_new_draft', 'Create new draft', ['archived', 'draft'], 'draft')
465 ->addTransition('publish', 'Publish', ['draft', 'published'], 'published')
466 ->addTransition('archive', 'Archive', ['published'], 'archived');
468 $this->assertEquals(['create_new_draft', 'publish'], array_keys($workflow->getTypePlugin()->getTransitionsForState('draft')));
469 $this->assertEquals(['create_new_draft'], array_keys($workflow->getTypePlugin()->getTransitionsForState('draft', 'to')));
470 $this->assertEquals(['publish', 'archive'], array_keys($workflow->getTypePlugin()->getTransitionsForState('published')));
471 $this->assertEquals(['publish'], array_keys($workflow->getTypePlugin()->getTransitionsForState('published', 'to')));
472 $this->assertEquals(['create_new_draft'], array_keys($workflow->getTypePlugin()->getTransitionsForState('archived', 'from')));
473 $this->assertEquals(['archive'], array_keys($workflow->getTypePlugin()->getTransitionsForState('archived', 'to')));
477 * @covers ::getTransitionFromStateToState
478 * @covers ::hasTransitionFromStateToState
480 public function testGetTransitionFromStateToState() {
481 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
482 // By default states are ordered in the order added.
485 ->addState('draft', 'Draft')
486 ->addState('published', 'Published')
487 ->addState('archived', 'Archived')
488 ->addTransition('create_new_draft', 'Create new draft', ['archived', 'draft'], 'draft')
489 ->addTransition('publish', 'Publish', ['draft', 'published'], 'published')
490 ->addTransition('archive', 'Archive', ['published'], 'archived');
492 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'published'));
493 $this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('archived', 'archived'));
494 $transition = $workflow->getTypePlugin()->getTransitionFromStateToState('published', 'archived');
495 $this->assertEquals('Archive', $transition->label());
499 * @covers ::getTransitionFromStateToState
501 public function testGetTransitionFromStateToStateException() {
502 $this->setExpectedException(\InvalidArgumentException::class, "The transition from 'archived' to 'archived' does not exist in workflow.");
503 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
504 // By default states are ordered in the order added.
507 ->addState('draft', 'Draft')
508 ->addState('published', 'Published')
509 ->addState('archived', 'Archived')
510 ->addTransition('create_new_draft', 'Create new draft', ['archived', 'draft'], 'draft')
511 ->addTransition('publish', 'Publish', ['draft', 'published'], 'published')
512 ->addTransition('archive', 'Archive', ['published'], 'archived');
514 $workflow->getTypePlugin()->getTransitionFromStateToState('archived', 'archived');
518 * @covers ::setTransitionLabel
520 public function testSetTransitionLabel() {
521 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
524 ->addState('draft', 'Draft')
525 ->addState('published', 'Published')
526 ->addTransition('publish', 'Publish', ['draft'], 'published');
527 $this->assertEquals('Publish', $workflow->getTypePlugin()->getTransition('publish')->label());
528 $workflow->getTypePlugin()->setTransitionLabel('publish', 'Publish!');
529 $this->assertEquals('Publish!', $workflow->getTypePlugin()->getTransition('publish')->label());
533 * @covers ::setTransitionLabel
535 public function testSetTransitionLabelException() {
536 $this->setExpectedException(\InvalidArgumentException::class, "The transition 'draft-published' does not exist in workflow.");
537 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
538 $workflow->getTypePlugin()->addState('published', 'Published');
539 $workflow->getTypePlugin()->setTransitionLabel('draft-published', 'Publish');
543 * @covers ::setTransitionWeight
545 public function testSetTransitionWeight() {
546 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
549 ->addState('draft', 'Draft')
550 ->addState('published', 'Published')
551 ->addTransition('publish', 'Publish', ['draft'], 'published');
552 $this->assertEquals(0, $workflow->getTypePlugin()->getTransition('publish')->weight());
553 $workflow->getTypePlugin()->setTransitionWeight('publish', 10);
554 $this->assertEquals(10, $workflow->getTypePlugin()->getTransition('publish')->weight());
558 * @covers ::setTransitionWeight
560 public function testSetTransitionWeightException() {
561 $this->setExpectedException(\InvalidArgumentException::class, "The transition 'draft-published' does not exist in workflow.");
562 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
563 $workflow->getTypePlugin()->addState('published', 'Published');
564 $workflow->getTypePlugin()->setTransitionWeight('draft-published', 10);
568 * @covers ::setTransitionWeight
570 public function testSetTransitionWeightNonNumericException() {
571 $this->setExpectedException(\InvalidArgumentException::class, "The weight 'foo' must be numeric for transition 'Publish'.");
572 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
573 $workflow->getTypePlugin()->addState('published', 'Published');
574 $workflow->getTypePlugin()->addTransition('publish', 'Publish', [], 'published');
575 $workflow->getTypePlugin()->setTransitionWeight('publish', 'foo');
579 * @covers ::setTransitionFromStates
581 public function testSetTransitionFromStates() {
582 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
585 ->addState('draft', 'Draft')
586 ->addState('published', 'Published')
587 ->addState('archived', 'Archived')
588 ->addTransition('test', 'Test', ['draft'], 'draft');
590 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'draft'));
591 $this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('published', 'draft'));
592 $this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('archived', 'draft'));
593 $workflow->getTypePlugin()->setTransitionFromStates('test', ['draft', 'published', 'archived']);
594 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'draft'));
595 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('published', 'draft'));
596 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('archived', 'draft'));
597 $workflow->getTypePlugin()->setTransitionFromStates('test', ['published', 'archived']);
598 $this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'draft'));
599 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('published', 'draft'));
600 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('archived', 'draft'));
604 * @covers ::setTransitionFromStates
606 public function testSetTransitionFromStatesMissingTransition() {
607 $this->setExpectedException(\InvalidArgumentException::class, "The transition 'test' does not exist in workflow.");
608 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
611 ->addState('draft', 'Draft')
612 ->addState('published', 'Published')
613 ->addState('archived', 'Archived')
614 ->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft');
616 $workflow->getTypePlugin()->setTransitionFromStates('test', ['draft', 'published', 'archived']);
620 * @covers ::setTransitionFromStates
622 public function testSetTransitionFromStatesMissingState() {
623 $this->setExpectedException(\InvalidArgumentException::class, "The state 'published' does not exist in workflow.");
624 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
627 ->addState('draft', 'Draft')
628 ->addState('archived', 'Archived')
629 ->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft');
631 $workflow->getTypePlugin()->setTransitionFromStates('create_new_draft', ['draft', 'published', 'archived']);
635 * @covers ::setTransitionFromStates
637 public function testSetTransitionFromStatesAlreadyExists() {
638 $this->setExpectedException(\InvalidArgumentException::class, "The 'create_new_draft' transition already allows 'draft' to 'draft' transitions in workflow.");
639 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
642 ->addState('draft', 'Draft')
643 ->addState('archived', 'Archived')
644 ->addState('needs_review', 'Needs Review')
645 ->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft')
646 ->addTransition('needs_review', 'Needs review', ['needs_review'], 'draft');
648 $workflow->getTypePlugin()->setTransitionFromStates('needs_review', ['draft']);
652 * @covers ::deleteTransition
654 public function testDeleteTransition() {
655 $workflow_type = new TestType([], '', []);
657 ->addState('draft', 'Draft')
658 ->addState('published', 'Published')
659 ->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft')
660 ->addTransition('publish', 'Publish', ['draft'], 'published');
661 $this->assertTrue($workflow_type->getState('draft')->canTransitionTo('published'));
662 $workflow_type->deleteTransition('publish');
663 $this->assertFalse($workflow_type->getState('draft')->canTransitionTo('published'));
664 $this->assertTrue($workflow_type->getState('draft')->canTransitionTo('draft'));
668 * @covers ::deleteTransition
670 public function testDeleteTransitionException() {
671 $this->setExpectedException(\InvalidArgumentException::class, "The transition 'draft-published' does not exist in workflow.");
672 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
673 $workflow->getTypePlugin()->addState('published', 'Published');
674 $workflow->getTypePlugin()->deleteTransition('draft-published');
678 * @covers \Drupal\workflows\Entity\Workflow::status
680 public function testStatus() {
681 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
682 $this->assertFalse($workflow->status());
683 $workflow->getTypePlugin()->addState('published', 'Published');
684 $this->assertTrue($workflow->status());