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 ::deleteState
231 public function testDeleteState() {
232 $workflow_type = new TestType([], '', []);
234 ->addState('draft', 'Draft')
235 ->addState('published', 'Published')
236 ->addState('archived', 'Archived')
237 ->addTransition('publish', 'Publish', ['draft', 'published'], 'published')
238 ->addTransition('create_new_draft', 'Create new draft', ['draft', 'published'], 'draft')
239 ->addTransition('archive', 'Archive', ['draft', 'published'], 'archived');
240 $this->assertCount(3, $workflow_type->getStates());
241 $this->assertCount(3, $workflow_type->getState('published')->getTransitions());
242 $workflow_type->deleteState('draft');
243 $this->assertFalse($workflow_type->hasState('draft'));
244 $this->assertCount(2, $workflow_type->getStates());
245 $this->assertCount(2, $workflow_type->getState('published')->getTransitions());
246 $workflow_type->deleteState('published');
247 $this->assertCount(0, $workflow_type->getTransitions());
251 * @covers ::deleteState
253 public function testDeleteStateException() {
254 $this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow.");
255 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
256 $workflow->getTypePlugin()->deleteState('draft');
260 * @covers ::deleteState
262 public function testDeleteOnlyStateException() {
263 $this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' can not be deleted from workflow as it is the only state");
264 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
265 $workflow->getTypePlugin()->addState('draft', 'Draft');
266 $workflow->getTypePlugin()->deleteState('draft');
270 * @covers ::addTransition
271 * @covers ::hasTransition
273 public function testAddTransition() {
274 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
276 // By default states are ordered in the order added.
279 ->addState('draft', 'Draft')
280 ->addState('published', 'Published');
282 $this->assertFalse($workflow->getTypePlugin()->getState('draft')->canTransitionTo('published'));
283 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft'], 'published');
284 $this->assertTrue($workflow->getTypePlugin()->getState('draft')->canTransitionTo('published'));
285 $this->assertEquals(0, $workflow->getTypePlugin()->getTransition('publish')->weight());
286 $this->assertTrue($workflow->getTypePlugin()->hasTransition('publish'));
287 $this->assertFalse($workflow->getTypePlugin()->hasTransition('draft'));
289 $workflow->getTypePlugin()->addTransition('save_publish', 'Save', ['published'], 'published');
290 $this->assertEquals(1, $workflow->getTypePlugin()->getTransition('save_publish')->weight());
294 * @covers ::addTransition
296 public function testAddTransitionDuplicateException() {
297 $this->setExpectedException(\InvalidArgumentException::class, "The transition 'publish' already exists in workflow.");
298 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
299 $workflow->getTypePlugin()->addState('published', 'Published');
300 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['published'], 'published');
301 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['published'], 'published');
305 * @covers ::addTransition
307 public function testAddTransitionInvalidIdException() {
308 $this->setExpectedException(\InvalidArgumentException::class, "The transition ID 'publish-publish' must contain only lowercase letters, numbers, and underscores");
309 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
310 $workflow->getTypePlugin()->addState('published', 'Published');
311 $workflow->getTypePlugin()->addTransition('publish-publish', 'Publish', ['published'], 'published');
315 * @covers ::addTransition
317 public function testAddTransitionMissingFromException() {
318 $this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow.");
319 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
320 $workflow->getTypePlugin()->addState('published', 'Published');
321 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft'], 'published');
325 * @covers ::addTransition
327 public function testAddTransitionDuplicateTransitionStatesException() {
328 $this->setExpectedException(\InvalidArgumentException::class, "The 'publish' transition already allows 'draft' to 'published' transitions in workflow.");
329 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
332 ->addState('draft', 'Draft')
333 ->addState('published', 'Published');
334 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft', 'published'], 'published');
335 $workflow->getTypePlugin()->addTransition('draft_to_published', 'Publish a draft', ['draft'], 'published');
339 * @covers ::addTransition
341 public function testAddTransitionConsistentAfterFromCatch() {
342 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
343 $workflow->getTypePlugin()->addState('published', 'Published');
345 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft'], 'published');
347 catch (\InvalidArgumentException $e) {
349 // Ensure that the workflow is not left in an inconsistent state after an
350 // exception is thrown from Workflow::setTransitionFromStates() whilst
351 // calling Workflow::addTransition().
352 $this->assertFalse($workflow->getTypePlugin()->hasTransition('publish'));
356 * @covers ::addTransition
358 public function testAddTransitionMissingToException() {
359 $this->setExpectedException(\InvalidArgumentException::class, "The state 'published' does not exist in workflow.");
360 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
361 $workflow->getTypePlugin()->addState('draft', 'Draft');
362 $workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft'], 'published');
366 * @covers ::getTransitions
367 * @covers ::setTransitionWeight
369 public function testGetTransitions() {
370 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
372 // Getting transitions works when there are none.
373 $this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getTransitions()));
374 $this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getTransitions([])));
376 // By default states are ordered in the order added.
381 ->addTransition('a_b', 'A to B', ['a'], 'b')
382 ->addTransition('a_a', 'A to A', ['a'], 'a');
384 // Transitions are stored in alphabetical key order in configuration.
385 $this->assertArrayEquals(['a_a', 'a_b'], array_keys($workflow->getTypePlugin()->getConfiguration()['transitions']));
387 // Ensure we're returning transition objects.
388 $this->assertInstanceOf(Transition::class, $workflow->getTypePlugin()->getTransitions()['a_a']);
390 // Passing in no IDs returns all transitions.
391 $this->assertArrayEquals(['a_b', 'a_a'], array_keys($workflow->getTypePlugin()->getTransitions()));
393 // The order of states is by weight.
394 $workflow->getTypePlugin()->setTransitionWeight('a_a', -1);
395 $this->assertArrayEquals(['a_a', 'a_b'], array_keys($workflow->getTypePlugin()->getTransitions()));
397 // If all weights are equal it will fallback to labels.
398 $workflow->getTypePlugin()->setTransitionWeight('a_a', 0);
399 $this->assertArrayEquals(['a_a', 'a_b'], array_keys($workflow->getTypePlugin()->getTransitions()));
400 $workflow->getTypePlugin()->setTransitionLabel('a_b', 'A B');
401 $this->assertArrayEquals(['a_b', 'a_a'], array_keys($workflow->getTypePlugin()->getTransitions()));
403 // You can limit the states returned by passing in states IDs.
404 $this->assertArrayEquals(['a_a'], array_keys($workflow->getTypePlugin()->getTransitions(['a_a'])));
406 // An empty array does not load all states.
407 $this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getTransitions([])));
412 * @covers ::getTransition
414 public function testGetTransition() {
415 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
416 // By default states are ordered in the order added.
419 ->addState('draft', 'Draft')
420 ->addState('published', 'Published')
421 ->addState('archived', 'Archived')
422 ->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft')
423 ->addTransition('publish', 'Publish', ['draft'], 'published');
425 // Ensure we're returning state objects and they are set up correctly
426 $this->assertInstanceOf(Transition::class, $workflow->getTypePlugin()->getTransition('create_new_draft'));
427 $this->assertEquals('publish', $workflow->getTypePlugin()->getTransition('publish')->id());
428 $this->assertEquals('Publish', $workflow->getTypePlugin()->getTransition('publish')->label());
430 $transition = $workflow->getTypePlugin()->getTransition('publish');
431 $this->assertEquals($workflow->getTypePlugin()->getState('draft'), $transition->from()['draft']);
432 $this->assertEquals($workflow->getTypePlugin()->getState('published'), $transition->to());
436 * @covers ::getTransition
438 public function testGetTransitionException() {
439 $this->setExpectedException(\InvalidArgumentException::class, "The transition 'transition_that_does_not_exist' does not exist in workflow.");
440 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
441 $workflow->getTypePlugin()->getTransition('transition_that_does_not_exist');
445 * @covers ::getTransitionsForState
447 public function testGetTransitionsForState() {
448 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
449 // By default states are ordered in the order added.
452 ->addState('draft', 'Draft')
453 ->addState('published', 'Published')
454 ->addState('archived', 'Archived')
455 ->addTransition('create_new_draft', 'Create new draft', ['archived', 'draft'], 'draft')
456 ->addTransition('publish', 'Publish', ['draft', 'published'], 'published')
457 ->addTransition('archive', 'Archive', ['published'], 'archived');
459 $this->assertEquals(['create_new_draft', 'publish'], array_keys($workflow->getTypePlugin()->getTransitionsForState('draft')));
460 $this->assertEquals(['create_new_draft'], array_keys($workflow->getTypePlugin()->getTransitionsForState('draft', 'to')));
461 $this->assertEquals(['publish', 'archive'], array_keys($workflow->getTypePlugin()->getTransitionsForState('published')));
462 $this->assertEquals(['publish'], array_keys($workflow->getTypePlugin()->getTransitionsForState('published', 'to')));
463 $this->assertEquals(['create_new_draft'], array_keys($workflow->getTypePlugin()->getTransitionsForState('archived', 'from')));
464 $this->assertEquals(['archive'], array_keys($workflow->getTypePlugin()->getTransitionsForState('archived', 'to')));
469 * @covers ::getTransitionFromStateToState
470 * @covers ::hasTransitionFromStateToState
472 public function testGetTransitionFromStateToState() {
473 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
474 // By default states are ordered in the order added.
477 ->addState('draft', 'Draft')
478 ->addState('published', 'Published')
479 ->addState('archived', 'Archived')
480 ->addTransition('create_new_draft', 'Create new draft', ['archived', 'draft'], 'draft')
481 ->addTransition('publish', 'Publish', ['draft', 'published'], 'published')
482 ->addTransition('archive', 'Archive', ['published'], 'archived');
484 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'published'));
485 $this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('archived', 'archived'));
486 $transition = $workflow->getTypePlugin()->getTransitionFromStateToState('published', 'archived');
487 $this->assertEquals('Archive', $transition->label());
491 * @covers ::getTransitionFromStateToState
493 public function testGetTransitionFromStateToStateException() {
494 $this->setExpectedException(\InvalidArgumentException::class, "The transition from 'archived' to 'archived' does not exist in workflow.");
495 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
496 // By default states are ordered in the order added.
499 ->addState('draft', 'Draft')
500 ->addState('published', 'Published')
501 ->addState('archived', 'Archived')
502 ->addTransition('create_new_draft', 'Create new draft', ['archived', 'draft'], 'draft')
503 ->addTransition('publish', 'Publish', ['draft', 'published'], 'published')
504 ->addTransition('archive', 'Archive', ['published'], 'archived');
506 $workflow->getTypePlugin()->getTransitionFromStateToState('archived', 'archived');
510 * @covers ::setTransitionLabel
512 public function testSetTransitionLabel() {
513 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
516 ->addState('draft', 'Draft')
517 ->addState('published', 'Published')
518 ->addTransition('publish', 'Publish', ['draft'], 'published');
519 $this->assertEquals('Publish', $workflow->getTypePlugin()->getTransition('publish')->label());
520 $workflow->getTypePlugin()->setTransitionLabel('publish', 'Publish!');
521 $this->assertEquals('Publish!', $workflow->getTypePlugin()->getTransition('publish')->label());
525 * @covers ::setTransitionLabel
527 public function testSetTransitionLabelException() {
528 $this->setExpectedException(\InvalidArgumentException::class, "The transition 'draft-published' does not exist in workflow.");
529 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
530 $workflow->getTypePlugin()->addState('published', 'Published');
531 $workflow->getTypePlugin()->setTransitionLabel('draft-published', 'Publish');
535 * @covers ::setTransitionWeight
537 public function testSetTransitionWeight() {
538 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
541 ->addState('draft', 'Draft')
542 ->addState('published', 'Published')
543 ->addTransition('publish', 'Publish', ['draft'], 'published');
544 $this->assertEquals(0, $workflow->getTypePlugin()->getTransition('publish')->weight());
545 $workflow->getTypePlugin()->setTransitionWeight('publish', 10);
546 $this->assertEquals(10, $workflow->getTypePlugin()->getTransition('publish')->weight());
550 * @covers ::setTransitionWeight
552 public function testSetTransitionWeightException() {
553 $this->setExpectedException(\InvalidArgumentException::class, "The transition 'draft-published' does not exist in workflow.");
554 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
555 $workflow->getTypePlugin()->addState('published', 'Published');
556 $workflow->getTypePlugin()->setTransitionWeight('draft-published', 10);
560 * @covers ::setTransitionFromStates
562 public function testSetTransitionFromStates() {
563 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
566 ->addState('draft', 'Draft')
567 ->addState('published', 'Published')
568 ->addState('archived', 'Archived')
569 ->addTransition('test', 'Test', ['draft'], 'draft');
571 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'draft'));
572 $this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('published', 'draft'));
573 $this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('archived', 'draft'));
574 $workflow->getTypePlugin()->setTransitionFromStates('test', ['draft', 'published', 'archived']);
575 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'draft'));
576 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('published', 'draft'));
577 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('archived', 'draft'));
578 $workflow->getTypePlugin()->setTransitionFromStates('test', ['published', 'archived']);
579 $this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'draft'));
580 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('published', 'draft'));
581 $this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('archived', 'draft'));
585 * @covers ::setTransitionFromStates
587 public function testSetTransitionFromStatesMissingTransition() {
588 $this->setExpectedException(\InvalidArgumentException::class, "The transition 'test' does not exist in workflow.");
589 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
592 ->addState('draft', 'Draft')
593 ->addState('published', 'Published')
594 ->addState('archived', 'Archived')
595 ->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft');
597 $workflow->getTypePlugin()->setTransitionFromStates('test', ['draft', 'published', 'archived']);
601 * @covers ::setTransitionFromStates
603 public function testSetTransitionFromStatesMissingState() {
604 $this->setExpectedException(\InvalidArgumentException::class, "The state 'published' does not exist in workflow.");
605 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
608 ->addState('draft', 'Draft')
609 ->addState('archived', 'Archived')
610 ->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft');
612 $workflow->getTypePlugin()->setTransitionFromStates('create_new_draft', ['draft', 'published', 'archived']);
616 * @covers ::setTransitionFromStates
618 public function testSetTransitionFromStatesAlreadyExists() {
619 $this->setExpectedException(\InvalidArgumentException::class, "The 'create_new_draft' transition already allows 'draft' to 'draft' transitions in workflow.");
620 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
623 ->addState('draft', 'Draft')
624 ->addState('archived', 'Archived')
625 ->addState('needs_review', 'Needs Review')
626 ->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft')
627 ->addTransition('needs_review', 'Needs review', ['needs_review'], 'draft');
629 $workflow->getTypePlugin()->setTransitionFromStates('needs_review', ['draft']);
633 * @covers ::deleteTransition
635 public function testDeleteTransition() {
636 $workflow_type = new TestType([], '', []);
638 ->addState('draft', 'Draft')
639 ->addState('published', 'Published')
640 ->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft')
641 ->addTransition('publish', 'Publish', ['draft'], 'published');
642 $this->assertTrue($workflow_type->getState('draft')->canTransitionTo('published'));
643 $workflow_type->deleteTransition('publish');
644 $this->assertFalse($workflow_type->getState('draft')->canTransitionTo('published'));
645 $this->assertTrue($workflow_type->getState('draft')->canTransitionTo('draft'));
649 * @covers ::deleteTransition
651 public function testDeleteTransitionException() {
652 $this->setExpectedException(\InvalidArgumentException::class, "The transition 'draft-published' does not exist in workflow.");
653 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
654 $workflow->getTypePlugin()->addState('published', 'Published');
655 $workflow->getTypePlugin()->deleteTransition('draft-published');
659 * @covers \Drupal\workflows\Entity\Workflow::status
661 public function testStatus() {
662 $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
663 $this->assertFalse($workflow->status());
664 $workflow->getTypePlugin()->addState('published', 'Published');
665 $this->assertTrue($workflow->status());