FieldNoteItemTest.php

Namespace

Drupal\Tests\field_permission_example\Kernel

File

modules/field_permission_example/tests/src/Kernel/FieldNoteItemTest.php

View source
<?php

namespace Drupal\Tests\field_permission_example\Kernel;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FieldItemInterface;
use Drupal\Tests\field\Kernel\FieldKernelTestBase;
use Drupal\Tests\user\Traits\UserCreationTrait;

/**
 * Tests our sticky-note field type.
 *
 * This class is based off the tests used in Drupal core for field plugins,
 * since we need to use some of the same convenience methods for testing
 * our custom field type. This base class also brings in the new
 * PHPUnit-based kernel test system that replaces the older Simpletest-
 * based classes.
 *
 * @see \Drupal\KernelTests\KernelTestBase
 *
 * @group field_permission_example
 * @group examples
 */
class FieldNoteItemTest extends FieldKernelTestBase {
  use UserCreationTrait;
  
  /**
   * We add the additional modules we need loaded here.
   *
   * The test runner will merge the $modules lists from this class, the class
   * it extends, and so on up the class hierarchy. So, it is not necessary to
   * include modules in your list that a parent class has already declared.
   *
   * @var array
   */
  protected static $modules = [
    'field_permission_example',
  ];
  
  /**
   * {@inheritdoc}
   *
   * This sets up the entity_test and user types to use our example
   * field plugins.
   */
  protected function setUp() : void {
    parent::setUp();
    $type_manager = $this->container
      ->get('entity_type.manager');
    // Set up our entity_type and user type for our new field:
    $type_manager->getStorage('field_storage_config')
      ->create([
      'field_name' => 'field_field_note',
      'entity_type' => 'entity_test',
      'type' => 'field_permission_example_field_note',
    ])
      ->save();
    $type_manager->getStorage('field_config')
      ->create([
      'entity_type' => 'entity_test',
      'field_name' => 'field_field_note',
      'bundle' => 'entity_test',
    ])
      ->save();
    // Create a form display for the default form mode, and
    // add our field type.
    $type_manager->getStorage('entity_form_display')
      ->create([
      'targetEntityType' => 'entity_test',
      'bundle' => 'entity_test',
      'mode' => 'default',
      'status' => TRUE,
    ])
      ->setComponent('field_field_note', [
      'type' => 'field_permission_example_widget',
    ])
      ->save();
    // Now do this for the user type.
    $type_manager->getStorage('field_storage_config')
      ->create([
      'field_name' => 'user_field_note',
      'entity_type' => 'user',
      'type' => 'field_permission_example_field_note',
    ])
      ->save();
    $type_manager->getStorage('field_config')
      ->create([
      'entity_type' => 'user',
      'field_name' => 'user_field_note',
      'bundle' => 'user',
    ])
      ->save();
    // Fetch a form display for a user. This may already exist, so check as
    // Core does.
    // @see https://api.drupal.org/api/drupal/core%21includes%21entity.inc/function/entity_get_form_display/8
    $entity_form_display = $type_manager->getStorage('entity_form_display')
      ->load('user.user.default');
    if (empty($entity_form_display)) {
      $entity_form_display = $type_manager->getStorage('entity_form_display')
        ->create([
        'targetEntityType' => 'user',
        'bundle' => 'user',
        'mode' => 'default',
        'status' => TRUE,
      ]);
    }
    // And add our fancy field to that display:
    $entity_form_display->setComponent('field_field_note', [
      'type' => 'field_permission_example_widget',
    ])
      ->save();
  }
  
  /**
   * Test entity fields of the field_permission_example_field_note field type.
   */
  public function testFieldNoteItem() {
    // Verify entity creation.
    $type_manager = $this->container
      ->get('entity_type.manager');
    $entity = $type_manager->getStorage('entity_test')
      ->create([]);
    $value = 'This is an epic entity';
    $entity->field_field_note = $value;
    $entity->name->value = $this->randomMachineName();
    $entity->save();
    // Verify entity has been created properly.
    $id = $entity->id();
    $entity = $type_manager->getStorage('entity_test')
      ->load($id);
    $this->assertTrue($entity->field_field_note instanceof FieldItemListInterface, 'Field implements interface.');
    $this->assertTrue($entity->field_field_note[0] instanceof FieldItemInterface, 'Field item implements interface.');
    $this->assertEquals($entity->field_field_note->value, $value);
    $this->assertEquals($entity->field_field_note[0]->value, $value);
    // Verify changing the field's value.
    $new_value = $this->randomMachineName();
    $entity->field_field_note->value = $new_value;
    $this->assertEquals($entity->field_field_note->value, $new_value);
    // Read changed entity and assert changed values.
    $entity->save();
    $entity = $type_manager->getStorage('entity_test')
      ->load($id);
    $this->assertEquals($entity->field_field_note->value, $new_value);
    // Test sample item generation.
    $entity = $type_manager->getStorage('entity_test')
      ->create([]);
    $entity->field_field_note
      ->generateSampleItems();
    $this->entityValidateAndSave($entity);
  }
  
  /**
   * Test multiple access scenarios for the field_note field.
   */
  public function testFieldNoteAccess() {
    // Let's set up some scenarios.
    $scenarios = [
      'admin_type' => [
        'perms' => [
          'administer the field note field',
        ],
        'can_view_any' => TRUE,
        'can_edit_any' => TRUE,
        'can_view_own' => TRUE,
        'can_edit_own' => TRUE,
      ],
      'low_access' => [
        'perms' => [
          'view test entity',
        ],
        'can_view_any' => FALSE,
        'can_edit_any' => FALSE,
        'can_view_own' => FALSE,
        'can_edit_own' => FALSE,
      ],
      'view_any' => [
        'perms' => [
          'view test entity',
          'view any field note',
        ],
        'can_view_any' => TRUE,
        'can_edit_any' => FALSE,
        'can_view_own' => FALSE,
        'can_edit_own' => FALSE,
      ],
      'edit_any' => [
        'perms' => [
          'view test entity',
          'view any field note',
          'edit any field note',
        ],
        'can_view_any' => TRUE,
        'can_edit_any' => TRUE,
        'can_view_own' => FALSE,
        'can_edit_own' => FALSE,
      ],
      'view_own' => [
        'perms' => [
          'view test entity',
          'view own field note',
        ],
        'can_view_any' => FALSE,
        'can_edit_any' => FALSE,
        'can_view_own' => TRUE,
        'can_edit_own' => FALSE,
      ],
      'edit_own' => [
        'perms' => [
          'view test entity',
          'view own field note',
          'edit own field note',
        ],
        'can_view_any' => FALSE,
        'can_edit_any' => FALSE,
        'can_view_own' => TRUE,
        'can_edit_own' => TRUE,
      ],
    ];
    $value = 'This is an epic entity';
    // We also need to test users as an entity to attach to.  They work
    // a little differently than most content entity types:
    $arbitrary_user = $this->createUser([], 'Some User');
    $arbitrary_user->user_field_note = $value;
    $arbitrary_user->save();
    $storage = $this->container
      ->get('entity_type.manager')
      ->getStorage('entity_test');
    foreach ($scenarios as $name => $scenario) {
      $test_user = $this->createUser($scenario['perms'], $name);
      $entity = $storage->create([
        'entity_test',
      ]);
      $entity->field_field_note = $value;
      $entity->name->value = $this->randomMachineName();
      $entity->save();
      foreach ([
        'can_view_any',
        'can_edit_any',
      ] as $op) {
        $this->doAccessAssertion($entity, 'field_field_note', $test_user, $name, $op, $scenario[$op]);
        $this->doAccessAssertion($arbitrary_user, 'user_field_note', $test_user, $name, $op, $scenario[$op]);
      }
      if ($scenario['can_view_own'] or $scenario['can_edit_own']) {
        $entity->user_id = $test_user;
        $entity->save();
        $test_user->user_field_note = $value;
        $test_user->save();
        foreach ([
          'can_view_own',
          'can_edit_own',
        ] as $op) {
          $this->doAccessAssertion($entity, 'field_field_note', $test_user, $name, $op, $scenario[$op]);
          $this->doAccessAssertion($test_user, 'user_field_note', $test_user, $name, $op, $scenario[$op]);
        }
      }
    }
  }
  
  /**
   * Helper routine to run the assertions.
   */
  protected function doAccessAssertion($entity, $field_name, $account, $name, $op, $expected) {
    $expect_str = $expected ? "CAN" : "CANNOT";
    $assert_str = "{$name} {$expect_str} do {$op} on field {$field_name}";
    $operation = preg_match('/edit/', $op) ? "edit" : "view";
    $result = $entity->{$field_name}
      ->access($operation, $account);
    if ($expected) {
      $this->assertTrue($result, $assert_str);
    }
    else {
      $this->assertFalse($result, $assert_str);
    }
  }

}

Classes

Title Deprecated Summary
FieldNoteItemTest Tests our sticky-note field type.