Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / modules / content_moderation / tests / src / Kernel / EntityStateChangeValidationTest.php
index aeed8486f5b652c425562585cfbd0c6992b9a9a9..df90bf63c88ad06f095fb6c62c15994fbbce5d8d 100644 (file)
@@ -6,7 +6,8 @@ use Drupal\KernelTests\KernelTestBase;
 use Drupal\language\Entity\ConfigurableLanguage;
 use Drupal\node\Entity\Node;
 use Drupal\node\Entity\NodeType;
-use Drupal\workflows\Entity\Workflow;
+use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
+use Drupal\Tests\user\Traits\UserCreationTrait;
 
 /**
  * @coversDefaultClass \Drupal\content_moderation\Plugin\Validation\Constraint\ModerationStateConstraintValidator
@@ -14,6 +15,9 @@ use Drupal\workflows\Entity\Workflow;
  */
 class EntityStateChangeValidationTest extends KernelTestBase {
 
+  use ContentModerationTestTrait;
+  use UserCreationTrait;
+
   /**
    * {@inheritdoc}
    */
@@ -27,6 +31,13 @@ class EntityStateChangeValidationTest extends KernelTestBase {
     'workflows',
   ];
 
+  /**
+   * An admin user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $adminUser;
+
   /**
    * {@inheritdoc}
    */
@@ -38,6 +49,9 @@ class EntityStateChangeValidationTest extends KernelTestBase {
     $this->installEntitySchema('user');
     $this->installEntitySchema('content_moderation_state');
     $this->installConfig('content_moderation');
+    $this->installSchema('system', ['sequences']);
+
+    $this->adminUser = $this->createUser(array_keys($this->container->get('user.permissions')->getPermissions()));
   }
 
   /**
@@ -46,11 +60,13 @@ class EntityStateChangeValidationTest extends KernelTestBase {
    * @covers ::validate
    */
   public function testValidTransition() {
+    $this->setCurrentUser($this->adminUser);
+
     $node_type = NodeType::create([
       'type' => 'example',
     ]);
     $node_type->save();
-    $workflow = Workflow::load('editorial');
+    $workflow = $this->createEditorialWorkflow();
     $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
     $workflow->save();
 
@@ -74,11 +90,13 @@ class EntityStateChangeValidationTest extends KernelTestBase {
    * @covers ::validate
    */
   public function testInvalidTransition() {
+    $this->setCurrentUser($this->adminUser);
+
     $node_type = NodeType::create([
       'type' => 'example',
     ]);
     $node_type->save();
-    $workflow = Workflow::load('editorial');
+    $workflow = $this->createEditorialWorkflow();
     $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
     $workflow->save();
 
@@ -104,7 +122,7 @@ class EntityStateChangeValidationTest extends KernelTestBase {
       'type' => 'example',
     ]);
     $node_type->save();
-    $workflow = Workflow::load('editorial');
+    $workflow = $this->createEditorialWorkflow();
     $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
     $workflow->save();
 
@@ -123,6 +141,7 @@ class EntityStateChangeValidationTest extends KernelTestBase {
    * Test validation with content that has no initial state or an invalid state.
    */
   public function testInvalidStateWithoutExisting() {
+    $this->setCurrentUser($this->adminUser);
     // Create content without moderation enabled for the content type.
     $node_type = NodeType::create([
       'type' => 'example',
@@ -136,7 +155,7 @@ class EntityStateChangeValidationTest extends KernelTestBase {
 
     // Enable moderation to test validation on existing content, with no
     // explicit state.
-    $workflow = Workflow::load('editorial');
+    $workflow = $this->createEditorialWorkflow();
     $workflow->getTypePlugin()->addState('deleted_state', 'Deleted state');
     $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
     $workflow->save();
@@ -154,22 +173,31 @@ class EntityStateChangeValidationTest extends KernelTestBase {
     // validating.
     $workflow->getTypePlugin()->deleteState('deleted_state');
     $workflow->save();
+
+    // When there is an invalid state, the content will revert to "draft". This
+    // will allow a draft to draft transition.
     $node->moderation_state->value = 'draft';
     $violations = $node->validate();
     $this->assertCount(0, $violations);
+    // This will disallow a draft to archived transition.
+    $node->moderation_state->value = 'archived';
+    $violations = $node->validate();
+    $this->assertCount(1, $violations);
   }
 
   /**
    * Test state transition validation with multiple languages.
    */
   public function testInvalidStateMultilingual() {
+    $this->setCurrentUser($this->adminUser);
+
     ConfigurableLanguage::createFromLangcode('fr')->save();
     $node_type = NodeType::create([
       'type' => 'example',
     ]);
     $node_type->save();
 
-    $workflow = Workflow::load('editorial');
+    $workflow = $this->createEditorialWorkflow();
     $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
     $workflow->save();
 
@@ -218,6 +246,8 @@ class EntityStateChangeValidationTest extends KernelTestBase {
    * Tests that content without prior moderation information can be moderated.
    */
   public function testExistingContentWithNoModeration() {
+    $this->setCurrentUser($this->adminUser);
+
     $node_type = NodeType::create([
       'type' => 'example',
     ]);
@@ -232,7 +262,7 @@ class EntityStateChangeValidationTest extends KernelTestBase {
     $nid = $node->id();
 
     // Enable moderation for our node type.
-    $workflow = Workflow::load('editorial');
+    $workflow = $this->createEditorialWorkflow();
     $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
     $workflow->save();
 
@@ -252,6 +282,8 @@ class EntityStateChangeValidationTest extends KernelTestBase {
    * Tests that content without prior moderation information can be translated.
    */
   public function testExistingMultilingualContentWithNoModeration() {
+    $this->setCurrentUser($this->adminUser);
+
     // Enable French.
     ConfigurableLanguage::createFromLangcode('fr')->save();
 
@@ -278,7 +310,7 @@ class EntityStateChangeValidationTest extends KernelTestBase {
     $node_fr->save();
 
     // Enable moderation for our node type.
-    $workflow = Workflow::load('editorial');
+    $workflow = $this->createEditorialWorkflow();
     $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
     $workflow->save();
 
@@ -291,4 +323,81 @@ class EntityStateChangeValidationTest extends KernelTestBase {
     $node_fr->save();
   }
 
+  /**
+   * @dataProvider transitionAccessValidationTestCases
+   */
+  public function testTransitionAccessValidation($permissions, $target_state, $messages) {
+    $node_type = NodeType::create([
+      'type' => 'example',
+    ]);
+    $node_type->save();
+    $workflow = $this->createEditorialWorkflow();
+    $workflow->getTypePlugin()->addState('foo', 'Foo');
+    $workflow->getTypePlugin()->addTransition('draft_to_foo', 'Draft to foo', ['draft'], 'foo');
+    $workflow->getTypePlugin()->addTransition('foo_to_foo', 'Foo to foo', ['foo'], 'foo');
+    $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
+    $workflow->save();
+
+    $this->setCurrentUser($this->createUser($permissions));
+
+    $node = Node::create([
+      'type' => 'example',
+      'title' => 'Test content',
+      'moderation_state' => $target_state,
+    ]);
+    $this->assertTrue($node->isNew());
+    $violations = $node->validate();
+    $this->assertCount(count($messages), $violations);
+    foreach ($messages as $i => $message) {
+      $this->assertEquals($message, $violations->get($i)->getMessage());
+    }
+  }
+
+  /**
+   * Test cases for ::testTransitionAccessValidation.
+   */
+  public function transitionAccessValidationTestCases() {
+    return [
+      'Invalid transition, no permissions validated' => [
+        [],
+        'archived',
+        ['Invalid state transition from <em class="placeholder">Draft</em> to <em class="placeholder">Archived</em>'],
+      ],
+      'Valid transition, missing permission' => [
+        [],
+        'published',
+        ['You do not have access to transition from <em class="placeholder">Draft</em> to <em class="placeholder">Published</em>'],
+      ],
+      'Valid transition, granted published permission' => [
+        ['use editorial transition publish'],
+        'published',
+        [],
+      ],
+      'Valid transition, granted draft permission' => [
+        ['use editorial transition create_new_draft'],
+        'draft',
+        [],
+      ],
+      'Valid transition, incorrect permission granted' => [
+        ['use editorial transition create_new_draft'],
+        'published',
+        ['You do not have access to transition from <em class="placeholder">Draft</em> to <em class="placeholder">Published</em>'],
+      ],
+      // Test with an additional state and set of transitions, since the
+      // "published" transition can start from either "draft" or "published", it
+      // does not capture bugs that fail to correctly distinguish the initial
+      // workflow state from the set state of a new entity.
+      'Valid transition, granted foo permission' => [
+        ['use editorial transition draft_to_foo'],
+        'foo',
+        [],
+      ],
+      'Valid transition, incorrect  foo permission granted' => [
+        ['use editorial transition foo_to_foo'],
+        'foo',
+        ['You do not have access to transition from <em class="placeholder">Draft</em> to <em class="placeholder">Foo</em>'],
+      ],
+    ];
+  }
+
 }