You are here

class EntityDefinitionUpdateTest in Zircon Profile 8

Same name and namespace in other branches
  1. 8.0 core/modules/system/src/Tests/Entity/EntityDefinitionUpdateTest.php \Drupal\system\Tests\Entity\EntityDefinitionUpdateTest

Tests EntityDefinitionUpdateManager functionality.

@group Entity

Hierarchy

Expanded class hierarchy of EntityDefinitionUpdateTest

File

core/modules/system/src/Tests/Entity/EntityDefinitionUpdateTest.php, line 28
Contains \Drupal\system\Tests\Entity\EntityDefinitionUpdateTest.

Namespace

Drupal\system\Tests\Entity
View source
class EntityDefinitionUpdateTest extends EntityUnitTestBase {
  use EntityDefinitionTestTrait;

  /**
   * The entity definition update manager.
   *
   * @var \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface
   */
  protected $entityDefinitionUpdateManager;

  /**
   * The database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $database;

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();
    $this->entityDefinitionUpdateManager = $this->container
      ->get('entity.definition_update_manager');
    $this->database = $this->container
      ->get('database');

    // Install every entity type's schema that wasn't installed in the parent
    // method.
    foreach (array_diff_key($this->entityManager
      ->getDefinitions(), array_flip(array(
      'user',
      'entity_test',
    ))) as $entity_type_id => $entity_type) {
      $this
        ->installEntitySchema($entity_type_id);
    }
  }

  /**
   * Tests that new entity type definitions are correctly handled.
   */
  public function testNewEntityType() {
    $entity_type_id = 'entity_test_new';
    $schema = $this->database
      ->schema();

    // Check that the "entity_test_new" is not defined.
    $entity_types = $this->entityManager
      ->getDefinitions();
    $this
      ->assertFalse(isset($entity_types[$entity_type_id]), 'The "entity_test_new" entity type does not exist.');
    $this
      ->assertFalse($schema
      ->tableExists($entity_type_id), 'Schema for the "entity_test_new" entity type does not exist.');

    // Check that the "entity_test_new" is now defined and the related schema
    // has been created.
    $this
      ->enableNewEntityType();
    $entity_types = $this->entityManager
      ->getDefinitions();
    $this
      ->assertTrue(isset($entity_types[$entity_type_id]), 'The "entity_test_new" entity type exists.');
    $this
      ->assertTrue($schema
      ->tableExists($entity_type_id), 'Schema for the "entity_test_new" entity type has been created.');
  }

  /**
   * Tests when no definition update is needed.
   */
  public function testNoUpdates() {

    // Ensure that the definition update manager reports no updates.
    $this
      ->assertFalse($this->entityDefinitionUpdateManager
      ->needsUpdates(), 'EntityDefinitionUpdateManager reports that no updates are needed.');
    $this
      ->assertIdentical($this->entityDefinitionUpdateManager
      ->getChangeSummary(), array(), 'EntityDefinitionUpdateManager reports an empty change summary.');

    // Ensure that applyUpdates() runs without error (it's not expected to do
    // anything when there aren't updates).
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
  }

  /**
   * Tests updating entity schema when there are no existing entities.
   */
  public function testEntityTypeUpdateWithoutData() {

    // The 'entity_test_update' entity type starts out non-revisionable, so
    // ensure the revision table hasn't been created during setUp().
    $this
      ->assertFalse($this->database
      ->schema()
      ->tableExists('entity_test_update_revision'), 'Revision table not created for entity_test_update.');

    // Update it to be revisionable and ensure the definition update manager
    // reports that an update is needed.
    $this
      ->updateEntityTypeToRevisionable();
    $this
      ->assertTrue($this->entityDefinitionUpdateManager
      ->needsUpdates(), 'EntityDefinitionUpdateManager reports that updates are needed.');
    $expected = array(
      'entity_test_update' => array(
        t('Update the %entity_type entity type.', array(
          '%entity_type' => $this->entityManager
            ->getDefinition('entity_test_update')
            ->getLabel(),
        )),
      ),
    );
    $this
      ->assertEqual($this->entityDefinitionUpdateManager
      ->getChangeSummary(), $expected);

    //, 'EntityDefinitionUpdateManager reports the expected change summary.');

    // Run the update and ensure the revision table is created.
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertTrue($this->database
      ->schema()
      ->tableExists('entity_test_update_revision'), 'Revision table created for entity_test_update.');
  }

  /**
   * Tests updating entity schema when there are existing entities.
   */
  public function testEntityTypeUpdateWithData() {

    // Save an entity.
    $this->entityManager
      ->getStorage('entity_test_update')
      ->create()
      ->save();

    // Update the entity type to be revisionable and try to apply the update.
    // It's expected to throw an exception.
    $this
      ->updateEntityTypeToRevisionable();
    try {
      $this->entityDefinitionUpdateManager
        ->applyUpdates();
      $this
        ->fail('EntityStorageException thrown when trying to apply an update that requires data migration.');
    } catch (EntityStorageException $e) {
      $this
        ->pass('EntityStorageException thrown when trying to apply an update that requires data migration.');
    }
  }

  /**
   * Tests creating, updating, and deleting a base field if no entities exist.
   */
  public function testBaseFieldCreateUpdateDeleteWithoutData() {

    // Add a base field, ensure the update manager reports it, and the update
    // creates its schema.
    $this
      ->addBaseField();
    $this
      ->assertTrue($this->entityDefinitionUpdateManager
      ->needsUpdates(), 'EntityDefinitionUpdateManager reports that updates are needed.');
    $expected = array(
      'entity_test_update' => array(
        t('Create the %field_name field.', array(
          '%field_name' => t('A new base field'),
        )),
      ),
    );
    $this
      ->assertEqual($this->entityDefinitionUpdateManager
      ->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertTrue($this->database
      ->schema()
      ->fieldExists('entity_test_update', 'new_base_field'), 'Column created in shared table for new_base_field.');

    // Add an index on the base field, ensure the update manager reports it,
    // and the update creates it.
    $this
      ->addBaseFieldIndex();
    $this
      ->assertTrue($this->entityDefinitionUpdateManager
      ->needsUpdates(), 'EntityDefinitionUpdateManager reports that updates are needed.');
    $expected = array(
      'entity_test_update' => array(
        t('Update the %field_name field.', array(
          '%field_name' => t('A new base field'),
        )),
      ),
    );
    $this
      ->assertEqual($this->entityDefinitionUpdateManager
      ->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertTrue($this->database
      ->schema()
      ->indexExists('entity_test_update', 'entity_test_update_field__new_base_field'), 'Index created.');

    // Remove the above index, ensure the update manager reports it, and the
    // update deletes it.
    $this
      ->removeBaseFieldIndex();
    $this
      ->assertTrue($this->entityDefinitionUpdateManager
      ->needsUpdates(), 'EntityDefinitionUpdateManager reports that updates are needed.');
    $expected = array(
      'entity_test_update' => array(
        t('Update the %field_name field.', array(
          '%field_name' => t('A new base field'),
        )),
      ),
    );
    $this
      ->assertEqual($this->entityDefinitionUpdateManager
      ->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertFalse($this->database
      ->schema()
      ->indexExists('entity_test_update', 'entity_test_update_field__new_base_field'), 'Index deleted.');

    // Update the type of the base field from 'string' to 'text', ensure the
    // update manager reports it, and the update adjusts the schema
    // accordingly.
    $this
      ->modifyBaseField();
    $this
      ->assertTrue($this->entityDefinitionUpdateManager
      ->needsUpdates(), 'EntityDefinitionUpdateManager reports that updates are needed.');
    $expected = array(
      'entity_test_update' => array(
        t('Update the %field_name field.', array(
          '%field_name' => t('A new base field'),
        )),
      ),
    );
    $this
      ->assertEqual($this->entityDefinitionUpdateManager
      ->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertFalse($this->database
      ->schema()
      ->fieldExists('entity_test_update', 'new_base_field'), 'Original column deleted in shared table for new_base_field.');
    $this
      ->assertTrue($this->database
      ->schema()
      ->fieldExists('entity_test_update', 'new_base_field__value'), 'Value column created in shared table for new_base_field.');
    $this
      ->assertTrue($this->database
      ->schema()
      ->fieldExists('entity_test_update', 'new_base_field__format'), 'Format column created in shared table for new_base_field.');

    // Remove the base field, ensure the update manager reports it, and the
    // update deletes the schema.
    $this
      ->removeBaseField();
    $this
      ->assertTrue($this->entityDefinitionUpdateManager
      ->needsUpdates(), 'EntityDefinitionUpdateManager reports that updates are needed.');
    $expected = array(
      'entity_test_update' => array(
        t('Delete the %field_name field.', array(
          '%field_name' => t('A new base field'),
        )),
      ),
    );
    $this
      ->assertEqual($this->entityDefinitionUpdateManager
      ->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertFalse($this->database
      ->schema()
      ->fieldExists('entity_test_update', 'new_base_field_value'), 'Value column deleted from shared table for new_base_field.');
    $this
      ->assertFalse($this->database
      ->schema()
      ->fieldExists('entity_test_update', 'new_base_field_format'), 'Format column deleted from shared table for new_base_field.');
  }

  /**
   * Tests creating, updating, and deleting a bundle field if no entities exist.
   */
  public function testBundleFieldCreateUpdateDeleteWithoutData() {

    // Add a bundle field, ensure the update manager reports it, and the update
    // creates its schema.
    $this
      ->addBundleField();
    $this
      ->assertTrue($this->entityDefinitionUpdateManager
      ->needsUpdates(), 'EntityDefinitionUpdateManager reports that updates are needed.');
    $expected = array(
      'entity_test_update' => array(
        t('Create the %field_name field.', array(
          '%field_name' => t('A new bundle field'),
        )),
      ),
    );
    $this
      ->assertEqual($this->entityDefinitionUpdateManager
      ->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertTrue($this->database
      ->schema()
      ->tableExists('entity_test_update__new_bundle_field'), 'Dedicated table created for new_bundle_field.');

    // Update the type of the base field from 'string' to 'text', ensure the
    // update manager reports it, and the update adjusts the schema
    // accordingly.
    $this
      ->modifyBundleField();
    $this
      ->assertTrue($this->entityDefinitionUpdateManager
      ->needsUpdates(), 'EntityDefinitionUpdateManager reports that updates are needed.');
    $expected = array(
      'entity_test_update' => array(
        t('Update the %field_name field.', array(
          '%field_name' => t('A new bundle field'),
        )),
      ),
    );
    $this
      ->assertEqual($this->entityDefinitionUpdateManager
      ->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertTrue($this->database
      ->schema()
      ->fieldExists('entity_test_update__new_bundle_field', 'new_bundle_field_format'), 'Format column created in dedicated table for new_base_field.');

    // Remove the bundle field, ensure the update manager reports it, and the
    // update deletes the schema.
    $this
      ->removeBundleField();
    $this
      ->assertTrue($this->entityDefinitionUpdateManager
      ->needsUpdates(), 'EntityDefinitionUpdateManager reports that updates are needed.');
    $expected = array(
      'entity_test_update' => array(
        t('Delete the %field_name field.', array(
          '%field_name' => t('A new bundle field'),
        )),
      ),
    );
    $this
      ->assertEqual($this->entityDefinitionUpdateManager
      ->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertFalse($this->database
      ->schema()
      ->tableExists('entity_test_update__new_bundle_field'), 'Dedicated table deleted for new_bundle_field.');
  }

  /**
   * Tests creating and deleting a base field if entities exist.
   *
   * This tests deletion when there are existing entities, but not existing data
   * for the field being deleted.
   *
   * @see testBaseFieldDeleteWithExistingData()
   */
  public function testBaseFieldCreateDeleteWithExistingEntities() {

    // Save an entity.
    $name = $this
      ->randomString();
    $storage = $this->entityManager
      ->getStorage('entity_test_update');
    $entity = $storage
      ->create(array(
      'name' => $name,
    ));
    $entity
      ->save();

    // Add a base field and run the update. Ensure the base field's column is
    // created and the prior saved entity data is still there.
    $this
      ->addBaseField();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $schema_handler = $this->database
      ->schema();
    $this
      ->assertTrue($schema_handler
      ->fieldExists('entity_test_update', 'new_base_field'), 'Column created in shared table for new_base_field.');
    $entity = $this->entityManager
      ->getStorage('entity_test_update')
      ->load($entity
      ->id());
    $this
      ->assertIdentical($entity->name->value, $name, 'Entity data preserved during field creation.');

    // Remove the base field and run the update. Ensure the base field's column
    // is deleted and the prior saved entity data is still there.
    $this
      ->removeBaseField();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertFalse($schema_handler
      ->fieldExists('entity_test_update', 'new_base_field'), 'Column deleted from shared table for new_base_field.');
    $entity = $this->entityManager
      ->getStorage('entity_test_update')
      ->load($entity
      ->id());
    $this
      ->assertIdentical($entity->name->value, $name, 'Entity data preserved during field deletion.');

    // Add a base field with a required property and run the update. Ensure
    // 'not null' is not applied and thus no exception is thrown.
    $this
      ->addBaseField('shape_required');
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $assert = $schema_handler
      ->fieldExists('entity_test_update', 'new_base_field__shape') && $schema_handler
      ->fieldExists('entity_test_update', 'new_base_field__color');
    $this
      ->assertTrue($assert, 'Columns created in shared table for new_base_field.');

    // Recreate the field after emptying the base table and check that its
    // columns are not 'not null'.
    // @todo Revisit this test when allowing for required storage field
    //   definitions. See https://www.drupal.org/node/2390495.
    $entity
      ->delete();
    $this
      ->removeBaseField();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $assert = !$schema_handler
      ->fieldExists('entity_test_update', 'new_base_field__shape') && !$schema_handler
      ->fieldExists('entity_test_update', 'new_base_field__color');
    $this
      ->assert($assert, 'Columns removed from the shared table for new_base_field.');
    $this
      ->addBaseField('shape_required');
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $assert = $schema_handler
      ->fieldExists('entity_test_update', 'new_base_field__shape') && $schema_handler
      ->fieldExists('entity_test_update', 'new_base_field__color');
    $this
      ->assertTrue($assert, 'Columns created again in shared table for new_base_field.');
    $entity = $storage
      ->create(array(
      'name' => $name,
    ));
    $entity
      ->save();
    $this
      ->pass('The new_base_field columns are still nullable');
  }

  /**
   * Tests creating and deleting a bundle field if entities exist.
   *
   * This tests deletion when there are existing entities, but not existing data
   * for the field being deleted.
   *
   * @see testBundleFieldDeleteWithExistingData()
   */
  public function testBundleFieldCreateDeleteWithExistingEntities() {

    // Save an entity.
    $name = $this
      ->randomString();
    $storage = $this->entityManager
      ->getStorage('entity_test_update');
    $entity = $storage
      ->create(array(
      'name' => $name,
    ));
    $entity
      ->save();

    // Add a bundle field and run the update. Ensure the bundle field's table
    // is created and the prior saved entity data is still there.
    $this
      ->addBundleField();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $schema_handler = $this->database
      ->schema();
    $this
      ->assertTrue($schema_handler
      ->tableExists('entity_test_update__new_bundle_field'), 'Dedicated table created for new_bundle_field.');
    $entity = $this->entityManager
      ->getStorage('entity_test_update')
      ->load($entity
      ->id());
    $this
      ->assertIdentical($entity->name->value, $name, 'Entity data preserved during field creation.');

    // Remove the base field and run the update. Ensure the bundle field's
    // table is deleted and the prior saved entity data is still there.
    $this
      ->removeBundleField();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertFalse($schema_handler
      ->tableExists('entity_test_update__new_bundle_field'), 'Dedicated table deleted for new_bundle_field.');
    $entity = $this->entityManager
      ->getStorage('entity_test_update')
      ->load($entity
      ->id());
    $this
      ->assertIdentical($entity->name->value, $name, 'Entity data preserved during field deletion.');

    // Test that required columns are created as 'not null'.
    $this
      ->addBundleField('shape_required');
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $message = 'The new_bundle_field_shape column is not nullable.';
    $values = array(
      'bundle' => $entity
        ->bundle(),
      'deleted' => 0,
      'entity_id' => $entity
        ->id(),
      'revision_id' => $entity
        ->id(),
      'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
      'delta' => 0,
      'new_bundle_field_color' => $this
        ->randomString(),
    );
    try {

      // Try to insert a record without providing a value for the 'not null'
      // column. This should fail.
      $this->database
        ->insert('entity_test_update__new_bundle_field')
        ->fields($values)
        ->execute();
      $this
        ->fail($message);
    } catch (\RuntimeException $e) {
      if ($e instanceof DatabaseExceptionWrapper || $e instanceof IntegrityConstraintViolationException) {

        // Now provide a value for the 'not null' column. This is expected to
        // succeed.
        $values['new_bundle_field_shape'] = $this
          ->randomString();
        $this->database
          ->insert('entity_test_update__new_bundle_field')
          ->fields($values)
          ->execute();
        $this
          ->pass($message);
      }
      else {

        // Keep throwing it.
        throw $e;
      }
    }
  }

  /**
   * Tests deleting a base field when it has existing data.
   */
  public function testBaseFieldDeleteWithExistingData() {

    // Add the base field and run the update.
    $this
      ->addBaseField();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();

    // Save an entity with the base field populated.
    $this->entityManager
      ->getStorage('entity_test_update')
      ->create(array(
      'new_base_field' => 'foo',
    ))
      ->save();

    // Remove the base field and apply updates. It's expected to throw an
    // exception.
    // @todo Revisit that expectation once purging is implemented for
    //   all fields: https://www.drupal.org/node/2282119.
    $this
      ->removeBaseField();
    try {
      $this->entityDefinitionUpdateManager
        ->applyUpdates();
      $this
        ->fail('FieldStorageDefinitionUpdateForbiddenException thrown when trying to apply an update that deletes a non-purgeable field with data.');
    } catch (FieldStorageDefinitionUpdateForbiddenException $e) {
      $this
        ->pass('FieldStorageDefinitionUpdateForbiddenException thrown when trying to apply an update that deletes a non-purgeable field with data.');
    }
  }

  /**
   * Tests deleting a bundle field when it has existing data.
   */
  public function testBundleFieldDeleteWithExistingData() {

    // Add the bundle field and run the update.
    $this
      ->addBundleField();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();

    // Save an entity with the bundle field populated.
    entity_test_create_bundle('custom');
    $this->entityManager
      ->getStorage('entity_test_update')
      ->create(array(
      'type' => 'test_bundle',
      'new_bundle_field' => 'foo',
    ))
      ->save();

    // Remove the bundle field and apply updates. It's expected to throw an
    // exception.
    // @todo Revisit that expectation once purging is implemented for
    //   all fields: https://www.drupal.org/node/2282119.
    $this
      ->removeBundleField();
    try {
      $this->entityDefinitionUpdateManager
        ->applyUpdates();
      $this
        ->fail('FieldStorageDefinitionUpdateForbiddenException thrown when trying to apply an update that deletes a non-purgeable field with data.');
    } catch (FieldStorageDefinitionUpdateForbiddenException $e) {
      $this
        ->pass('FieldStorageDefinitionUpdateForbiddenException thrown when trying to apply an update that deletes a non-purgeable field with data.');
    }
  }

  /**
   * Tests updating a base field when it has existing data.
   */
  public function testBaseFieldUpdateWithExistingData() {

    // Add the base field and run the update.
    $this
      ->addBaseField();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();

    // Save an entity with the base field populated.
    $this->entityManager
      ->getStorage('entity_test_update')
      ->create(array(
      'new_base_field' => 'foo',
    ))
      ->save();

    // Change the field's field type and apply updates. It's expected to
    // throw an exception.
    $this
      ->modifyBaseField();
    try {
      $this->entityDefinitionUpdateManager
        ->applyUpdates();
      $this
        ->fail('FieldStorageDefinitionUpdateForbiddenException thrown when trying to update a field schema that has data.');
    } catch (FieldStorageDefinitionUpdateForbiddenException $e) {
      $this
        ->pass('FieldStorageDefinitionUpdateForbiddenException thrown when trying to update a field schema that has data.');
    }
  }

  /**
   * Tests updating a bundle field when it has existing data.
   */
  public function testBundleFieldUpdateWithExistingData() {

    // Add the bundle field and run the update.
    $this
      ->addBundleField();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();

    // Save an entity with the bundle field populated.
    entity_test_create_bundle('custom');
    $this->entityManager
      ->getStorage('entity_test_update')
      ->create(array(
      'type' => 'test_bundle',
      'new_bundle_field' => 'foo',
    ))
      ->save();

    // Change the field's field type and apply updates. It's expected to
    // throw an exception.
    $this
      ->modifyBundleField();
    try {
      $this->entityDefinitionUpdateManager
        ->applyUpdates();
      $this
        ->fail('FieldStorageDefinitionUpdateForbiddenException thrown when trying to update a field schema that has data.');
    } catch (FieldStorageDefinitionUpdateForbiddenException $e) {
      $this
        ->pass('FieldStorageDefinitionUpdateForbiddenException thrown when trying to update a field schema that has data.');
    }
  }

  /**
   * Tests creating and deleting a multi-field index when there are no existing entities.
   */
  public function testEntityIndexCreateDeleteWithoutData() {

    // Add an entity index and ensure the update manager reports that as an
    // update to the entity type.
    $this
      ->addEntityIndex();
    $this
      ->assertTrue($this->entityDefinitionUpdateManager
      ->needsUpdates(), 'EntityDefinitionUpdateManager reports that updates are needed.');
    $expected = array(
      'entity_test_update' => array(
        t('Update the %entity_type entity type.', array(
          '%entity_type' => $this->entityManager
            ->getDefinition('entity_test_update')
            ->getLabel(),
        )),
      ),
    );
    $this
      ->assertEqual($this->entityDefinitionUpdateManager
      ->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');

    // Run the update and ensure the new index is created.
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertTrue($this->database
      ->schema()
      ->indexExists('entity_test_update', 'entity_test_update__new_index'), 'Index created.');

    // Remove the index and ensure the update manager reports that as an
    // update to the entity type.
    $this
      ->removeEntityIndex();
    $this
      ->assertTrue($this->entityDefinitionUpdateManager
      ->needsUpdates(), 'EntityDefinitionUpdateManager reports that updates are needed.');
    $expected = array(
      'entity_test_update' => array(
        t('Update the %entity_type entity type.', array(
          '%entity_type' => $this->entityManager
            ->getDefinition('entity_test_update')
            ->getLabel(),
        )),
      ),
    );
    $this
      ->assertEqual($this->entityDefinitionUpdateManager
      ->getChangeSummary(), $expected, 'EntityDefinitionUpdateManager reports the expected change summary.');

    // Run the update and ensure the index is deleted.
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertFalse($this->database
      ->schema()
      ->indexExists('entity_test_update', 'entity_test_update__new_index'), 'Index deleted.');

    // Test that composite indexes are handled correctly when dropping and
    // re-creating one of their columns.
    $this
      ->addEntityIndex();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $storage_definition = $this->entityDefinitionUpdateManager
      ->getFieldStorageDefinition('name', 'entity_test_update');
    $this->entityDefinitionUpdateManager
      ->updateFieldStorageDefinition($storage_definition);
    $this
      ->assertTrue($this->database
      ->schema()
      ->indexExists('entity_test_update', 'entity_test_update__new_index'), 'Index created.');
    $this->entityDefinitionUpdateManager
      ->uninstallFieldStorageDefinition($storage_definition);
    $this
      ->assertFalse($this->database
      ->schema()
      ->indexExists('entity_test_update', 'entity_test_update__new_index'), 'Index deleted.');
    $this->entityDefinitionUpdateManager
      ->installFieldStorageDefinition('name', 'entity_test_update', 'entity_test', $storage_definition);
    $this
      ->assertTrue($this->database
      ->schema()
      ->indexExists('entity_test_update', 'entity_test_update__new_index'), 'Index created again.');
  }

  /**
   * Tests creating a multi-field index when there are existing entities.
   */
  public function testEntityIndexCreateWithData() {

    // Save an entity.
    $name = $this
      ->randomString();
    $entity = $this->entityManager
      ->getStorage('entity_test_update')
      ->create(array(
      'name' => $name,
    ));
    $entity
      ->save();

    // Add an entity index, run the update. Ensure that the index is created
    // despite having data.
    $this
      ->addEntityIndex();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertTrue($this->database
      ->schema()
      ->indexExists('entity_test_update', 'entity_test_update__new_index'), 'Index added.');
  }

  /**
   * Tests entity type and field storage definition events.
   */
  public function testDefinitionEvents() {

    /** @var \Drupal\entity_test\EntityTestDefinitionSubscriber $event_subscriber */
    $event_subscriber = $this->container
      ->get('entity_test.definition.subscriber');
    $event_subscriber
      ->enableEventTracking();

    // Test field storage definition events.
    $storage_definition = current($this->entityManager
      ->getFieldStorageDefinitions('entity_test_rev'));
    $this
      ->assertFalse($event_subscriber
      ->hasEventFired(FieldStorageDefinitionEvents::DELETE), 'Entity type delete was not dispatched yet.');
    $this->entityManager
      ->onFieldStorageDefinitionDelete($storage_definition);
    $this
      ->assertTrue($event_subscriber
      ->hasEventFired(FieldStorageDefinitionEvents::DELETE), 'Entity type delete event successfully dispatched.');
    $this
      ->assertFalse($event_subscriber
      ->hasEventFired(FieldStorageDefinitionEvents::CREATE), 'Entity type create was not dispatched yet.');
    $this->entityManager
      ->onFieldStorageDefinitionCreate($storage_definition);
    $this
      ->assertTrue($event_subscriber
      ->hasEventFired(FieldStorageDefinitionEvents::CREATE), 'Entity type create event successfully dispatched.');
    $this
      ->assertFalse($event_subscriber
      ->hasEventFired(FieldStorageDefinitionEvents::UPDATE), 'Entity type update was not dispatched yet.');
    $this->entityManager
      ->onFieldStorageDefinitionUpdate($storage_definition, $storage_definition);
    $this
      ->assertTrue($event_subscriber
      ->hasEventFired(FieldStorageDefinitionEvents::UPDATE), 'Entity type update event successfully dispatched.');

    // Test entity type events.
    $entity_type = $this->entityManager
      ->getDefinition('entity_test_rev');
    $this
      ->assertFalse($event_subscriber
      ->hasEventFired(EntityTypeEvents::CREATE), 'Entity type create was not dispatched yet.');
    $this->entityManager
      ->onEntityTypeCreate($entity_type);
    $this
      ->assertTrue($event_subscriber
      ->hasEventFired(EntityTypeEvents::CREATE), 'Entity type create event successfully dispatched.');
    $this
      ->assertFalse($event_subscriber
      ->hasEventFired(EntityTypeEvents::UPDATE), 'Entity type update was not dispatched yet.');
    $this->entityManager
      ->onEntityTypeUpdate($entity_type, $entity_type);
    $this
      ->assertTrue($event_subscriber
      ->hasEventFired(EntityTypeEvents::UPDATE), 'Entity type update event successfully dispatched.');
    $this
      ->assertFalse($event_subscriber
      ->hasEventFired(EntityTypeEvents::DELETE), 'Entity type delete was not dispatched yet.');
    $this->entityManager
      ->onEntityTypeDelete($entity_type);
    $this
      ->assertTrue($event_subscriber
      ->hasEventFired(EntityTypeEvents::DELETE), 'Entity type delete event successfully dispatched.');
  }

  /**
   * Tests updating entity schema and creating a base field.
   *
   * This tests updating entity schema and creating a base field at the same
   * time when there are no existing entities.
   */
  public function testEntityTypeSchemaUpdateAndBaseFieldCreateWithoutData() {
    $this
      ->updateEntityTypeToRevisionable();
    $this
      ->addBaseField();
    $message = 'Successfully updated entity schema and created base field at the same time.';

    // Entity type updates create base fields as well, thus make sure doing both
    // at the same time does not lead to errors due to the base field being
    // created twice.
    try {
      $this->entityDefinitionUpdateManager
        ->applyUpdates();
      $this
        ->pass($message);
    } catch (\Exception $e) {
      $this
        ->fail($message);
      throw $e;
    }
  }

  /**
   * Tests updating entity schema and creating a revisionable base field.
   *
   * This tests updating entity schema and creating a revisionable base field
   * at the same time when there are no existing entities.
   */
  public function testEntityTypeSchemaUpdateAndRevisionableBaseFieldCreateWithoutData() {
    $this
      ->updateEntityTypeToRevisionable();
    $this
      ->addRevisionableBaseField();
    $message = 'Successfully updated entity schema and created revisionable base field at the same time.';

    // Entity type updates create base fields as well, thus make sure doing both
    // at the same time does not lead to errors due to the base field being
    // created twice.
    try {
      $this->entityDefinitionUpdateManager
        ->applyUpdates();
      $this
        ->pass($message);
    } catch (\Exception $e) {
      $this
        ->fail($message);
      throw $e;
    }
  }

  /**
   * Tests applying single updates.
   */
  public function testSingleActionCalls() {
    $db_schema = $this->database
      ->schema();

    // Ensure that a non-existing entity type cannot be installed.
    $message = 'A non-existing entity type cannot be installed';
    try {
      $this->entityDefinitionUpdateManager
        ->installEntityType(new ContentEntityType([
        'id' => 'foo',
      ]));
      $this
        ->fail($message);
    } catch (PluginNotFoundException $e) {
      $this
        ->pass($message);
    }

    // Ensure that a field cannot be installed on non-existing entity type.
    $message = 'A field cannot be installed on a non-existing entity type';
    try {
      $storage_definition = BaseFieldDefinition::create('string')
        ->setLabel(t('A new revisionable base field'))
        ->setRevisionable(TRUE);
      $this->entityDefinitionUpdateManager
        ->installFieldStorageDefinition('bar', 'foo', 'entity_test', $storage_definition);
      $this
        ->fail($message);
    } catch (PluginNotFoundException $e) {
      $this
        ->pass($message);
    }

    // Ensure that a non-existing field cannot be installed.
    $storage_definition = BaseFieldDefinition::create('string')
      ->setLabel(t('A new revisionable base field'))
      ->setRevisionable(TRUE);
    $this->entityDefinitionUpdateManager
      ->installFieldStorageDefinition('bar', 'entity_test_update', 'entity_test', $storage_definition);
    $this
      ->assertFalse($db_schema
      ->fieldExists('entity_test_update', 'bar'), "A non-existing field cannot be installed.");

    // Ensure that installing an existing entity type is a no-op.
    $entity_type = $this->entityDefinitionUpdateManager
      ->getEntityType('entity_test_update');
    $this->entityDefinitionUpdateManager
      ->installEntityType($entity_type);
    $this
      ->assertTrue($db_schema
      ->tableExists('entity_test_update'), 'Installing an existing entity type is a no-op');

    // Create a new base field.
    $this
      ->addRevisionableBaseField();
    $storage_definition = BaseFieldDefinition::create('string')
      ->setLabel(t('A new revisionable base field'))
      ->setRevisionable(TRUE);
    $this
      ->assertFalse($db_schema
      ->fieldExists('entity_test_update', 'new_base_field'), "New field 'new_base_field' does not exist before applying the update.");
    $this->entityDefinitionUpdateManager
      ->installFieldStorageDefinition('new_base_field', 'entity_test_update', 'entity_test', $storage_definition);
    $this
      ->assertTrue($db_schema
      ->fieldExists('entity_test_update', 'new_base_field'), "New field 'new_base_field' has been created on the 'entity_test_update' table.");

    // Ensure that installing an existing field is a no-op.
    $this->entityDefinitionUpdateManager
      ->installFieldStorageDefinition('new_base_field', 'entity_test_update', 'entity_test', $storage_definition);
    $this
      ->assertTrue($db_schema
      ->fieldExists('entity_test_update', 'new_base_field'), 'Installing an existing field is a no-op');

    // Update an existing field schema.
    $this
      ->modifyBaseField();
    $storage_definition = BaseFieldDefinition::create('text')
      ->setName('new_base_field')
      ->setTargetEntityTypeId('entity_test_update')
      ->setLabel(t('A new revisionable base field'))
      ->setRevisionable(TRUE);
    $this->entityDefinitionUpdateManager
      ->updateFieldStorageDefinition($storage_definition);
    $this
      ->assertFalse($db_schema
      ->fieldExists('entity_test_update', 'new_base_field'), "Previous schema for 'new_base_field' no longer exists.");
    $this
      ->assertTrue($db_schema
      ->fieldExists('entity_test_update', 'new_base_field__value') && $db_schema
      ->fieldExists('entity_test_update', 'new_base_field__format'), "New schema for 'new_base_field' has been created.");

    // Drop an existing field schema.
    $this->entityDefinitionUpdateManager
      ->uninstallFieldStorageDefinition($storage_definition);
    $this
      ->assertFalse($db_schema
      ->fieldExists('entity_test_update', 'new_base_field__value') || $db_schema
      ->fieldExists('entity_test_update', 'new_base_field__format'), "The schema for 'new_base_field' has been dropped.");

    // Make the entity type revisionable.
    $this
      ->updateEntityTypeToRevisionable();
    $this
      ->assertFalse($db_schema
      ->tableExists('entity_test_update_revision'), "The 'entity_test_update_revision' does not exist before applying the update.");
    $entity_type = $this->entityDefinitionUpdateManager
      ->getEntityType('entity_test_update');
    $keys = $entity_type
      ->getKeys();
    $keys['revision'] = 'revision_id';
    $entity_type
      ->set('entity_keys', $keys);
    $this->entityDefinitionUpdateManager
      ->updateEntityType($entity_type);
    $this
      ->assertTrue($db_schema
      ->tableExists('entity_test_update_revision'), "The 'entity_test_update_revision' table has been created.");
  }

  /**
   * Ensures that a new field and index on a shared table are created.
   *
   * @see Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::createSharedTableSchema
   */
  public function testCreateFieldAndIndexOnSharedTable() {
    $this
      ->addBaseField();
    $this
      ->addBaseFieldIndex();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertTrue($this->database
      ->schema()
      ->fieldExists('entity_test_update', 'new_base_field'), "New field 'new_base_field' has been created on the 'entity_test_update' table.");
    $this
      ->assertTrue($this->database
      ->schema()
      ->indexExists('entity_test_update', 'entity_test_update_field__new_base_field'), "New index 'entity_test_update_field__new_base_field' has been created on the 'entity_test_update' table.");

    // Check index size in for MySQL.
    if (Database::getConnection()
      ->driver() == 'mysql') {
      $result = Database::getConnection()
        ->query('SHOW INDEX FROM {entity_test_update} WHERE key_name = \'entity_test_update_field__new_base_field\' and column_name = \'new_base_field\'')
        ->fetchObject();
      $this
        ->assertEqual(191, $result->Sub_part, 'The index length has been restricted to 191 characters for UTF8MB4 compatibility.');
    }
  }

  /**
   * Ensures that a new entity level index is created when data exists.
   *
   * @see Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::onEntityTypeUpdate
   */
  public function testCreateIndexUsingEntityStorageSchemaWithData() {

    // Save an entity.
    $name = $this
      ->randomString();
    $storage = $this->entityManager
      ->getStorage('entity_test_update');
    $entity = $storage
      ->create(array(
      'name' => $name,
    ));
    $entity
      ->save();

    // Create an index.
    $indexes = array(
      'entity_test_update__type_index' => array(
        'type',
      ),
    );
    $this->state
      ->set('entity_test_update.additional_entity_indexes', $indexes);
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->assertTrue($this->database
      ->schema()
      ->indexExists('entity_test_update', 'entity_test_update__type_index'), "New index 'entity_test_update__type_index' has been created on the 'entity_test_update' table.");

    // Check index size in for MySQL.
    if (Database::getConnection()
      ->driver() == 'mysql') {
      $result = Database::getConnection()
        ->query('SHOW INDEX FROM {entity_test_update} WHERE key_name = \'entity_test_update__type_index\' and column_name = \'type\'')
        ->fetchObject();
      $this
        ->assertEqual(191, $result->Sub_part, 'The index length has been restricted to 191 characters for UTF8MB4 compatibility.');
    }
  }

  /**
   * Tests updating a base field when it has existing data.
   */
  public function testBaseFieldEntityKeyUpdateWithExistingData() {

    // Add the base field and run the update.
    $this
      ->addBaseField();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();

    // Save an entity with the base field populated.
    $this->entityManager
      ->getStorage('entity_test_update')
      ->create([
      'new_base_field' => $this
        ->randomString(),
    ])
      ->save();

    // Save an entity with the base field not populated.

    /** @var \Drupal\entity_test\Entity\EntityTestUpdate $entity */
    $entity = $this->entityManager
      ->getStorage('entity_test_update')
      ->create();
    $entity
      ->save();

    // Promote the base field to an entity key. This will trigger the addition
    // of a NOT NULL constraint.
    $this
      ->makeBaseFieldEntityKey();

    // Try to apply the update and verify they fail since we have a NULL value.
    $message = 'An error occurs when trying to enabling NOT NULL constraints with NULL data.';
    try {
      $this->entityDefinitionUpdateManager
        ->applyUpdates();
      $this
        ->fail($message);
    } catch (EntityStorageException $e) {
      $this
        ->pass($message);
    }

    // Check that the update is correctly applied when no NULL data is left.
    $entity
      ->set('new_base_field', $this
      ->randomString());
    $entity
      ->save();
    $this->entityDefinitionUpdateManager
      ->applyUpdates();
    $this
      ->pass('The update is correctly performed when no NULL data exists.');

    // Check that the update actually applied a NOT NULL constraint.
    $entity
      ->set('new_base_field', NULL);
    $message = 'The NOT NULL constraint was correctly applied.';
    try {
      $entity
        ->save();
      $this
        ->fail($message);
    } catch (EntityStorageException $e) {
      $this
        ->pass($message);
    }
  }

  /**
   * Check that field schema is correctly handled with long-named fields.
   */
  function testLongNameFieldIndexes() {
    $this
      ->addLongNameBaseField();
    $entity_type_id = 'entity_test_update';
    $entity_type = $this->entityManager
      ->getDefinition($entity_type_id);
    $definitions = EntityTestUpdate::baseFieldDefinitions($entity_type);
    $name = 'new_long_named_entity_reference_base_field';
    $this->entityDefinitionUpdateManager
      ->installFieldStorageDefinition($name, $entity_type_id, 'entity_test', $definitions[$name]);
    $this
      ->assertFalse($this->entityDefinitionUpdateManager
      ->needsUpdates(), 'Entity and field schema data are correctly detected.');
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AssertContentTrait::$content protected property The current raw content.
AssertContentTrait::$drupalSettings protected property The drupalSettings value from the current raw $content.
AssertContentTrait::$elements protected property The XML structure parsed from the current raw $content. 2
AssertContentTrait::$plainTextContent protected property The plain-text content of raw $content (text nodes).
AssertContentTrait::assertEscaped protected function Passes if the raw text IS found escaped on the loaded page, fail otherwise.
AssertContentTrait::assertField protected function Asserts that a field exists with the given name or ID.
AssertContentTrait::assertFieldById protected function Asserts that a field exists with the given ID and value.
AssertContentTrait::assertFieldByName protected function Asserts that a field exists with the given name and value.
AssertContentTrait::assertFieldByXPath protected function Asserts that a field exists in the current page by the given XPath.
AssertContentTrait::assertFieldChecked protected function Asserts that a checkbox field in the current page is checked.
AssertContentTrait::assertFieldsByValue protected function Asserts that a field exists in the current page with a given Xpath result.
AssertContentTrait::assertLink protected function Passes if a link with the specified label is found.
AssertContentTrait::assertLinkByHref protected function Passes if a link containing a given href (part) is found.
AssertContentTrait::assertNoDuplicateIds protected function Asserts that each HTML ID is used for just a single element.
AssertContentTrait::assertNoEscaped protected function Passes if the raw text IS NOT found escaped on the loaded page, fail otherwise.
AssertContentTrait::assertNoField protected function Asserts that a field does not exist with the given name or ID.
AssertContentTrait::assertNoFieldById protected function Asserts that a field does not exist with the given ID and value.
AssertContentTrait::assertNoFieldByName protected function Asserts that a field does not exist with the given name and value.
AssertContentTrait::assertNoFieldByXPath protected function Asserts that a field does not exist or its value does not match, by XPath.
AssertContentTrait::assertNoFieldChecked protected function Asserts that a checkbox field in the current page is not checked.
AssertContentTrait::assertNoLink protected function Passes if a link with the specified label is not found.
AssertContentTrait::assertNoLinkByHref protected function Passes if a link containing a given href (part) is not found.
AssertContentTrait::assertNoLinkByHrefInMainRegion protected function Passes if a link containing a given href is not found in the main region.
AssertContentTrait::assertNoOption protected function Asserts that a select option in the current page does not exist.
AssertContentTrait::assertNoOptionSelected protected function Asserts that a select option in the current page is not checked.
AssertContentTrait::assertNoPattern protected function Triggers a pass if the perl regex pattern is not found in raw content.
AssertContentTrait::assertNoRaw protected function Passes if the raw text is NOT found on the loaded page, fail otherwise.
AssertContentTrait::assertNoText protected function Passes if the page (with HTML stripped) does not contains the text.
AssertContentTrait::assertNoTitle protected function Pass if the page title is not the given string.
AssertContentTrait::assertNoUniqueText protected function Passes if the text is found MORE THAN ONCE on the text version of the page.
AssertContentTrait::assertOption protected function Asserts that a select option in the current page exists.
AssertContentTrait::assertOptionSelected protected function Asserts that a select option in the current page is checked.
AssertContentTrait::assertOptionSelectedWithDrupalSelector protected function Asserts that a select option in the current page is checked.
AssertContentTrait::assertOptionWithDrupalSelector protected function Asserts that a select option in the current page exists.
AssertContentTrait::assertPattern protected function Triggers a pass if the Perl regex pattern is found in the raw content.
AssertContentTrait::assertRaw protected function Passes if the raw text IS found on the loaded page, fail otherwise.
AssertContentTrait::assertText protected function Passes if the page (with HTML stripped) contains the text.
AssertContentTrait::assertTextHelper protected function Helper for assertText and assertNoText.
AssertContentTrait::assertTextPattern protected function Asserts that a Perl regex pattern is found in the plain-text content.
AssertContentTrait::assertThemeOutput protected function Asserts themed output.
AssertContentTrait::assertTitle protected function Pass if the page title is the given string.
AssertContentTrait::assertUniqueText protected function Passes if the text is found ONLY ONCE on the text version of the page.
AssertContentTrait::assertUniqueTextHelper protected function Helper for assertUniqueText and assertNoUniqueText.
AssertContentTrait::buildXPathQuery protected function Builds an XPath query.
AssertContentTrait::constructFieldXpath protected function Helper: Constructs an XPath for the given set of attributes and value.
AssertContentTrait::cssSelect protected function Searches elements using a CSS selector in the raw content.
AssertContentTrait::getAllOptions protected function Get all option elements, including nested options, in a select.
AssertContentTrait::getDrupalSettings protected function Gets the value of drupalSettings for the currently-loaded page.
AssertContentTrait::getRawContent protected function Gets the current raw content.
AssertContentTrait::getSelectedItem protected function Get the selected value from a select field.
AssertContentTrait::getTextContent protected function Retrieves the plain-text content from the current raw content.
AssertContentTrait::getUrl protected function Get the current URL from the cURL handler. 1
AssertContentTrait::parse protected function Parse content returned from curlExec using DOM and SimpleXML.
AssertContentTrait::removeWhiteSpace protected function Removes all white-space between HTML tags from the raw content.
AssertContentTrait::setDrupalSettings protected function Sets the value of drupalSettings for the currently-loaded page.
AssertContentTrait::setRawContent protected function Sets the raw content (e.g. HTML).
AssertContentTrait::xpath protected function Performs an xpath search on the contents of the internal browser.
AssertHelperTrait::castSafeStrings protected function Casts MarkupInterface objects into strings.
EntityDefinitionTestTrait::addBaseField protected function Adds a new base field to the 'entity_test_update' entity type.
EntityDefinitionTestTrait::addBaseFieldIndex protected function Adds a single-field index to the base field.
EntityDefinitionTestTrait::addBundleField protected function Adds a new bundle field to the 'entity_test_update' entity type.
EntityDefinitionTestTrait::addEntityIndex protected function Adds an index to the 'entity_test_update' entity type's base table.
EntityDefinitionTestTrait::addLongNameBaseField protected function Adds a long-named base field to the 'entity_test_update' entity type.
EntityDefinitionTestTrait::addRevisionableBaseField protected function Adds a new revisionable base field to the 'entity_test_update' entity type.
EntityDefinitionTestTrait::deleteEntityType protected function Removes the entity type.
EntityDefinitionTestTrait::enableNewEntityType protected function Enables a new entity type definition.
EntityDefinitionTestTrait::makeBaseFieldEntityKey protected function Promotes a field to an entity key.
EntityDefinitionTestTrait::modifyBaseField protected function Modifies the new base field from 'string' to 'text'.
EntityDefinitionTestTrait::modifyBundleField protected function Modifies the new bundle field from 'string' to 'text'.
EntityDefinitionTestTrait::removeBaseField protected function Removes the new base field from the 'entity_test_update' entity type.
EntityDefinitionTestTrait::removeBaseFieldIndex protected function Removes the index added in addBaseFieldIndex().
EntityDefinitionTestTrait::removeBundleField protected function Removes the new bundle field from the 'entity_test_update' entity type.
EntityDefinitionTestTrait::removeEntityIndex protected function Removes the index added in addEntityIndex().
EntityDefinitionTestTrait::renameBaseTable protected function Renames the base table to 'entity_test_update_new'.
EntityDefinitionTestTrait::renameDataTable protected function Renames the data table to 'entity_test_update_data_new'.
EntityDefinitionTestTrait::renameRevisionBaseTable protected function Renames the revision table to 'entity_test_update_revision_new'.
EntityDefinitionTestTrait::renameRevisionDataTable protected function Renames the revision data table to 'entity_test_update_revision_data_new'.
EntityDefinitionTestTrait::resetEntityType protected function Resets the entity type definition.
EntityDefinitionTestTrait::updateEntityTypeToNotRevisionable protected function Updates the 'entity_test_update' entity type not revisionable.
EntityDefinitionTestTrait::updateEntityTypeToNotTranslatable protected function Updates the 'entity_test_update' entity type to not translatable.
EntityDefinitionTestTrait::updateEntityTypeToRevisionable protected function Updates the 'entity_test_update' entity type to revisionable.
EntityDefinitionTestTrait::updateEntityTypeToTranslatable protected function Updates the 'entity_test_update' entity type to translatable.
EntityDefinitionUpdateTest::$database protected property The database connection.
EntityDefinitionUpdateTest::$entityDefinitionUpdateManager protected property The entity definition update manager.
EntityDefinitionUpdateTest::setUp protected function Performs setup tasks before each individual test method is run. Overrides EntityUnitTestBase::setUp
EntityDefinitionUpdateTest::testBaseFieldCreateDeleteWithExistingEntities public function Tests creating and deleting a base field if entities exist.
EntityDefinitionUpdateTest::testBaseFieldCreateUpdateDeleteWithoutData public function Tests creating, updating, and deleting a base field if no entities exist.
EntityDefinitionUpdateTest::testBaseFieldDeleteWithExistingData public function Tests deleting a base field when it has existing data.
EntityDefinitionUpdateTest::testBaseFieldEntityKeyUpdateWithExistingData public function Tests updating a base field when it has existing data.
EntityDefinitionUpdateTest::testBaseFieldUpdateWithExistingData public function Tests updating a base field when it has existing data.
EntityDefinitionUpdateTest::testBundleFieldCreateDeleteWithExistingEntities public function Tests creating and deleting a bundle field if entities exist.
EntityDefinitionUpdateTest::testBundleFieldCreateUpdateDeleteWithoutData public function Tests creating, updating, and deleting a bundle field if no entities exist.
EntityDefinitionUpdateTest::testBundleFieldDeleteWithExistingData public function Tests deleting a bundle field when it has existing data.
EntityDefinitionUpdateTest::testBundleFieldUpdateWithExistingData public function Tests updating a bundle field when it has existing data.
EntityDefinitionUpdateTest::testCreateFieldAndIndexOnSharedTable public function Ensures that a new field and index on a shared table are created.
EntityDefinitionUpdateTest::testCreateIndexUsingEntityStorageSchemaWithData public function Ensures that a new entity level index is created when data exists.
EntityDefinitionUpdateTest::testDefinitionEvents public function Tests entity type and field storage definition events.
EntityDefinitionUpdateTest::testEntityIndexCreateDeleteWithoutData public function Tests creating and deleting a multi-field index when there are no existing entities.
EntityDefinitionUpdateTest::testEntityIndexCreateWithData public function Tests creating a multi-field index when there are existing entities.
EntityDefinitionUpdateTest::testEntityTypeSchemaUpdateAndBaseFieldCreateWithoutData public function Tests updating entity schema and creating a base field.
EntityDefinitionUpdateTest::testEntityTypeSchemaUpdateAndRevisionableBaseFieldCreateWithoutData public function Tests updating entity schema and creating a revisionable base field.
EntityDefinitionUpdateTest::testEntityTypeUpdateWithData public function Tests updating entity schema when there are existing entities.
EntityDefinitionUpdateTest::testEntityTypeUpdateWithoutData public function Tests updating entity schema when there are no existing entities.
EntityDefinitionUpdateTest::testLongNameFieldIndexes function Check that field schema is correctly handled with long-named fields.
EntityDefinitionUpdateTest::testNewEntityType public function Tests that new entity type definitions are correctly handled.
EntityDefinitionUpdateTest::testNoUpdates public function Tests when no definition update is needed.
EntityDefinitionUpdateTest::testSingleActionCalls public function Tests applying single updates.
EntityUnitTestBase::$entityManager protected property The entity manager service.
EntityUnitTestBase::$generatedIds protected property A list of generated identifiers.
EntityUnitTestBase::$modules public static property Modules to enable. Overrides KernelTestBase::$modules 35
EntityUnitTestBase::$state protected property The state service.
EntityUnitTestBase::createUser protected function Creates a user.
EntityUnitTestBase::generateRandomEntityId protected function Generates a random ID avoiding collisions.
EntityUnitTestBase::getHooksInfo protected function Returns the entity_test hook invocation info.
EntityUnitTestBase::installModule protected function Installs a module and refreshes services.
EntityUnitTestBase::refreshServices protected function Refresh services. 1
EntityUnitTestBase::reloadEntity protected function Reloads the given entity from the storage and returns it.
EntityUnitTestBase::uninstallModule protected function Uninstalls a module and refreshes services.
KernelTestBase::$configDirectories protected property The configuration directories for this test run.
KernelTestBase::$keyValueFactory protected property A KeyValueMemoryFactory instance to use when building the container.
KernelTestBase::$moduleFiles private property
KernelTestBase::$streamWrappers protected property Array of registered stream wrappers.
KernelTestBase::$themeFiles private property
KernelTestBase::beforePrepareEnvironment protected function Act on global state information before the environment is altered for a test. Overrides TestBase::beforePrepareEnvironment
KernelTestBase::containerBuild public function Sets up the base service container for this test. 12
KernelTestBase::defaultLanguageData protected function Provides the data for setting the default language on the container. 1
KernelTestBase::disableModules protected function Disables modules for this test.
KernelTestBase::enableModules protected function Enables modules for this test.
KernelTestBase::installConfig protected function Installs default configuration for a given list of modules.
KernelTestBase::installEntitySchema protected function Installs the storage schema for a specific entity type.
KernelTestBase::installSchema protected function Installs a specific table from a module schema definition.
KernelTestBase::prepareConfigDirectories protected function Create and set new configuration directories. 1
KernelTestBase::registerStreamWrapper protected function Registers a stream wrapper for this test.
KernelTestBase::render protected function Renders a render array.
KernelTestBase::tearDown protected function Performs cleanup tasks after each individual test method has been run. Overrides TestBase::tearDown
KernelTestBase::__construct function Constructor for Test. Overrides TestBase::__construct
RandomGeneratorTrait::$randomGenerator protected property The random generator.
RandomGeneratorTrait::getRandomGenerator protected function Gets the random generator for the utility methods.
RandomGeneratorTrait::randomMachineName protected function Generates a unique random string containing letters and numbers.
RandomGeneratorTrait::randomObject public function Generates a random PHP object.
RandomGeneratorTrait::randomString public function Generates a pseudo-random string of ASCII characters of codes 32 to 126.
RandomGeneratorTrait::randomStringValidate public function Callback for random string validation.
SessionTestTrait::$sessionName protected property The name of the session cookie.
SessionTestTrait::generateSessionName protected function Generates a session cookie name.
SessionTestTrait::getSessionName protected function Returns the session name in use on the child site.
TestBase::$assertions protected property Assertions thrown in that test case.
TestBase::$configImporter protected property The config importer that can used in a test. 5
TestBase::$configSchemaCheckerExclusions protected static property An array of config object names that are excluded from schema checking.
TestBase::$container protected property The dependency injection container used in the test.
TestBase::$databasePrefix protected property The database prefix of this test run.
TestBase::$dieOnFail public property Whether to die in case any test assertion fails.
TestBase::$httpAuthCredentials protected property HTTP authentication credentials (<username>:<password>).
TestBase::$httpAuthMethod protected property HTTP authentication method (specified as a CURLAUTH_* constant).
TestBase::$kernel protected property The DrupalKernel instance used in the test. 1
TestBase::$originalConf protected property The original configuration (variables), if available.
TestBase::$originalConfig protected property The original configuration (variables).
TestBase::$originalConfigDirectories protected property The original configuration directories.
TestBase::$originalContainer protected property The original container.
TestBase::$originalFileDirectory protected property The original file directory, before it was changed for testing purposes.
TestBase::$originalLanguage protected property The original language.
TestBase::$originalPrefix protected property The original database prefix when running inside Simpletest.
TestBase::$originalProfile protected property The original installation profile.
TestBase::$originalSessionName protected property The name of the session cookie of the test-runner.
TestBase::$originalSettings protected property The settings array.
TestBase::$originalShutdownCallbacks protected property The original array of shutdown function callbacks. 1
TestBase::$originalSite protected property The site directory of the original parent site.
TestBase::$originalUser protected property The original user, before testing began. 1
TestBase::$privateFilesDirectory protected property The private file directory for the test environment.
TestBase::$publicFilesDirectory protected property The public file directory for the test environment.
TestBase::$results public property Current results of this test case.
TestBase::$siteDirectory protected property The site directory of this test run.
TestBase::$skipClasses protected property This class is skipped when looking for the source of an assertion.
TestBase::$strictConfigSchema protected property Set to TRUE to strict check all configuration saved. 4
TestBase::$tempFilesDirectory protected property The temporary file directory for the test environment.
TestBase::$testId protected property The test run ID.
TestBase::$timeLimit protected property Time limit for the test.
TestBase::$translationFilesDirectory protected property The translation file directory for the test environment.
TestBase::$verbose public property TRUE if verbose debugging is enabled.
TestBase::$verboseClassName protected property Safe class name for use in verbose output filenames.
TestBase::$verboseDirectory protected property Directory where verbose output files are put.
TestBase::$verboseDirectoryUrl protected property URL to the verbose output file directory.
TestBase::$verboseId protected property Incrementing identifier for verbose output filenames.
TestBase::assert protected function Internal helper: stores the assert.
TestBase::assertEqual protected function Check to see if two values are equal.
TestBase::assertErrorLogged protected function Asserts that a specific error has been logged to the PHP error log.
TestBase::assertFalse protected function Check to see if a value is false.
TestBase::assertIdentical protected function Check to see if two values are identical.
TestBase::assertIdenticalObject protected function Checks to see if two objects are identical.
TestBase::assertNoErrorsLogged protected function Asserts that no errors have been logged to the PHP error.log thus far.
TestBase::assertNotEqual protected function Check to see if two values are not equal.
TestBase::assertNotIdentical protected function Check to see if two values are not identical.
TestBase::assertNotNull protected function Check to see if a value is not NULL.
TestBase::assertNull protected function Check to see if a value is NULL.
TestBase::assertTrue protected function Check to see if a value is not false.
TestBase::changeDatabasePrefix private function Changes the database connection to the prefixed one.
TestBase::checkRequirements protected function Checks the matching requirements for Test. 2
TestBase::config protected function Configuration accessor for tests. Returns non-overridden configuration.
TestBase::configImporter public function Returns a ConfigImporter object to import test importing of configuration. 5
TestBase::copyConfig public function Copies configuration objects from source storage to target storage.
TestBase::deleteAssert public static function Delete an assertion record by message ID.
TestBase::error protected function Fire an error assertion. 3
TestBase::errorHandler public function Handle errors during test runs.
TestBase::exceptionHandler protected function Handle exceptions.
TestBase::fail protected function Fire an assertion that is always negative.
TestBase::filePreDeleteCallback public static function Ensures test files are deletable within file_unmanaged_delete_recursive().
TestBase::generatePermutations public static function Converts a list of possible parameters into a stack of permutations.
TestBase::getAssertionCall protected function Cycles through backtrace until the first non-assertion method is found.
TestBase::getConfigSchemaExclusions protected function Gets the config schema exclusions for this test.
TestBase::getDatabaseConnection public static function Returns the database connection to the site running Simpletest.
TestBase::getDatabasePrefix public function Gets the database prefix.
TestBase::getTempFilesDirectory public function Gets the temporary files directory.
TestBase::insertAssert public static function Store an assertion from outside the testing context.
TestBase::pass protected function Fire an assertion that is always positive.
TestBase::prepareDatabasePrefix private function Generates a database prefix for running tests.
TestBase::prepareEnvironment private function Prepares the current environment for running the test.
TestBase::restoreEnvironment private function Cleans up the test environment and restores the original environment.
TestBase::run public function Run all tests in this class. 1
TestBase::settingsSet protected function Changes in memory settings.
TestBase::storeAssertion protected function Helper method to store an assertion record in the configured database.
TestBase::verbose protected function Logs a verbose message in a text file.