From 1370edf99f574d0e19631711a3f4da8214498df8 Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Mon, 24 Mar 2014 13:34:01 +0100 Subject: [PATCH] Issue #2134857 by Xano, Wim Leers, Berdir, damiankloip: PHPUnit test the entity base classes. --- .../Core/Config/Entity/ConfigEntityBase.php | 13 +- .../Config/Entity/ConfigEntityInterface.php | 13 +- .../Drupal/Core/Entity/ContentEntityBase.php | 55 +-- core/lib/Drupal/Core/Entity/Entity.php | 75 ++-- .../Drupal/Core/Entity/EntityInterface.php | 2 + .../Core/TypedData/ComplexDataInterface.php | 2 +- core/modules/block/block.module | 2 +- .../block/lib/Drupal/block/Entity/Block.php | 3 +- .../config/Tests/ConfigEntityUnitTest.php | 10 - .../Drupal/config_test/Entity/ConfigTest.php | 3 +- .../Drupal/entity/EntityDisplayModeBase.php | 5 +- .../lib/Drupal/search/Entity/SearchPage.php | 3 +- .../lib/Drupal/system/Entity/Action.php | 5 +- .../system/Tests/Entity/EntityLabelTest.php | 55 --- .../modules/entity_test/entity_test.module | 13 - .../Entity/ConfigEntityBaseUnitTest.php | 182 ++++++++- .../Core/Entity/ContentEntityBaseUnitTest.php | 351 ++++++++++++++++++ .../Tests/Core/Entity/EntityUnitTest.php | 348 +++++++++++++++++ 18 files changed, 988 insertions(+), 152 deletions(-) delete mode 100644 core/modules/system/lib/Drupal/system/Tests/Entity/EntityLabelTest.php create mode 100644 core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php create mode 100644 core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php index b7af02b52b7..492876a7912 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php @@ -7,9 +7,10 @@ namespace Drupal\Core\Config\Entity; +use Drupal\Component\Utility\String; use Drupal\Core\Entity\Entity; -use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Core\Config\ConfigDuplicateUUIDException; +use Drupal\Core\Entity\EntityStorageControllerInterface; /** * Defines a base configuration entity class. @@ -139,6 +140,8 @@ abstract class ConfigEntityBase extends Entity implements ConfigEntityInterface } $this->{$property_name} = $value; + + return $this; } /** @@ -175,6 +178,8 @@ abstract class ConfigEntityBase extends Entity implements ConfigEntityInterface */ public function setSyncing($syncing) { $this->isSyncing = $syncing; + + return $this; } /** @@ -212,7 +217,7 @@ abstract class ConfigEntityBase extends Entity implements ConfigEntityInterface /** * Helper callback for uasort() to sort configuration entities by weight and label. */ - public static function sort($a, $b) { + public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) { $a_weight = isset($a->weight) ? $a->weight : 0; $b_weight = isset($b->weight) ? $b->weight : 0; if ($a_weight == $b_weight) { @@ -262,14 +267,14 @@ abstract class ConfigEntityBase extends Entity implements ConfigEntityInterface ->execute(); $matched_entity = reset($matching_entities); if (!empty($matched_entity) && ($matched_entity != $this->id()) && $matched_entity != $this->getOriginalId()) { - throw new ConfigDuplicateUUIDException(format_string('Attempt to save a configuration entity %id with UUID %uuid when this UUID is already used for %matched', array('%id' => $this->id(), '%uuid' => $this->uuid(), '%matched' => $matched_entity))); + throw new ConfigDuplicateUUIDException(String::format('Attempt to save a configuration entity %id with UUID %uuid when this UUID is already used for %matched', array('%id' => $this->id(), '%uuid' => $this->uuid(), '%matched' => $matched_entity))); } if (!$this->isNew()) { $original = $storage_controller->loadUnchanged($this->id()); // Ensure that the UUID cannot be changed for an existing entity. if ($original && ($original->uuid() != $this->uuid())) { - throw new ConfigDuplicateUUIDException(format_string('Attempt to save a configuration entity %id with UUID %uuid when this entity already exists with UUID %original_uuid', array('%id' => $this->id(), '%uuid' => $this->uuid(), '%original_uuid' => $original->uuid()))); + throw new ConfigDuplicateUUIDException(String::format('Attempt to save a configuration entity %id with UUID %uuid when this entity already exists with UUID %original_uuid', array('%id' => $this->id(), '%uuid' => $this->uuid(), '%original_uuid' => $original->uuid()))); } } if (!$this->isSyncing()) { diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php index 9542e45aa43..c9c8277cf0a 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php @@ -17,16 +17,14 @@ interface ConfigEntityInterface extends EntityInterface { /** * Enables the configuration entity. * - * @return \Drupal\Core\Config\Entity\ConfigEntityInterface - * The configuration entity. + * @return $this */ public function enable(); /** * Disables the configuration entity. * - * @return \Drupal\Core\Config\Entity\ConfigEntityInterface - * The configuration entity. + * @return $this */ public function disable(); @@ -36,8 +34,7 @@ interface ConfigEntityInterface extends EntityInterface { * @param bool $status * The status of the configuration entity. * - * @return \Drupal\Core\Config\Entity\ConfigEntityInterface - * The class instance that this method is called on. + * @return $this */ public function setStatus($status); @@ -46,6 +43,8 @@ interface ConfigEntityInterface extends EntityInterface { * * @param bool $status * The status of the sync flag. + * + * @return $this */ public function setSyncing($status); @@ -110,6 +109,8 @@ interface ConfigEntityInterface extends EntityInterface { * The name of the property that should be set. * @param mixed $value * The value the property should be set to. + * + * @return $this */ public function set($property_name, $value); diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php index 82e5241f6ff..f63b1a061d9 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php @@ -134,7 +134,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C public function __construct(array $values, $entity_type, $bundle = FALSE, $translations = array()) { $this->entityTypeId = $entity_type; $this->bundle = $bundle ? $bundle : $this->entityTypeId; - $this->languages = language_list(Language::STATE_ALL); + $this->languages = $this->languageManager()->getLanguages(Language::STATE_ALL); foreach ($values as $key => $value) { // If the key matches an existing property set the value to the property @@ -161,6 +161,15 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C $this->init(); } + /** + * Returns the typed data manager. + * + * @return \Drupal\Core\TypedData\TypedDataManager + */ + protected function typedDataManager() { + return \Drupal::typedDataManager(); + } + /** * {@inheritdoc} */ @@ -197,8 +206,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C * {@inheritdoc} */ public function isTranslatable() { - // @todo Inject the entity manager and retrieve bundle info from it. - $bundles = entity_get_bundles($this->entityTypeId); + $bundles = $this->entityManager()->getBundleInfo($this->entityTypeId); return !empty($bundles[$this->bundle()]['translatable']); } @@ -239,15 +247,14 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C * {@inheritdoc} */ public function getString() { - return $this->label(); + return (string) $this->label(); } /** * {@inheritdoc} */ public function validate() { - // @todo: Add the typed data manager as proper dependency. - return \Drupal::typedDataManager()->getValidator()->validate($this); + return $this->typedDataManager()->getValidator()->validate($this); } /** @@ -333,10 +340,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C $this->fieldDefinitions = NULL; $this->clearTranslationCache(); - // Don't serialize the url generator. - $this->urlGenerator = NULL; - - return array_keys(get_object_vars($this)); + return parent::__sleep(); } @@ -344,6 +348,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C * Magic __wakeup() implementation. */ public function __wakeup() { + parent::__wakeup(); $this->init(); } @@ -393,7 +398,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C protected function getTranslatedField($name, $langcode) { if ($this->translations[$this->activeLangcode]['status'] == static::TRANSLATION_REMOVED) { $message = 'The entity object refers to a removed translation (@langcode) and cannot be manipulated.'; - throw new \InvalidArgumentException(format_string($message, array('@langcode' => $this->activeLangcode))); + throw new \InvalidArgumentException(String::format($message, array('@langcode' => $this->activeLangcode))); } // Populate $this->fields to speed-up further look-ups and to keep track of // fields objects, possibly holding changes to field values. @@ -526,13 +531,13 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C /** * {@inheritdoc} */ - public function access($operation = 'view', AccountInterface $account = NULL) { + public function access($operation, AccountInterface $account = NULL) { if ($operation == 'create') { - return \Drupal::entityManager() + return $this->entityManager() ->getAccessController($this->entityTypeId) ->createAccess($this->bundle(), $account); } - return \Drupal::entityManager() + return $this->entityManager() ->getAccessController($this->entityTypeId) ->access($this, $operation, $this->activeLangcode, $account); } @@ -544,7 +549,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C $language = NULL; if ($this->activeLangcode != Language::LANGCODE_DEFAULT) { if (!isset($this->languages[$this->activeLangcode])) { - $this->languages += language_list(Language::STATE_ALL); + $this->languages += $this->languageManager()->getLanguages(Language::STATE_ALL); } $language = $this->languages[$this->activeLangcode]; } @@ -594,7 +599,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C if ($name == 'langcode') { $this->setDefaultLangcode(); if (isset($this->translations[$this->defaultLangcode])) { - $message = format_string('A translation already exists for the specified language (@langcode).', array('@langcode' => $this->defaultLangcode)); + $message = String::format('A translation already exists for the specified language (@langcode).', array('@langcode' => $this->defaultLangcode)); throw new \InvalidArgumentException($message); } $this->updateFieldLangcodes($this->defaultLangcode); @@ -643,7 +648,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C if (empty($translation)) { $message = 'Invalid translation language (@langcode) specified.'; - throw new \InvalidArgumentException(format_string($message, array('@langcode' => $langcode))); + throw new \InvalidArgumentException(String::format($message, array('@langcode' => $langcode))); } return $translation; @@ -708,14 +713,14 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C public function addTranslation($langcode, array $values = array()) { if (!isset($this->languages[$langcode]) || $this->hasTranslation($langcode)) { $message = 'Invalid translation language (@langcode) specified.'; - throw new \InvalidArgumentException(format_string($message, array('@langcode' => $langcode))); + throw new \InvalidArgumentException(String::format($message, array('@langcode' => $langcode))); } // Instantiate a new empty entity so default values will be populated in the // specified language. $entity_type = $this->getEntityType(); $default_values = array($entity_type->getKey('bundle') => $this->bundle, 'langcode' => $langcode); - $entity = \Drupal::entityManager() + $entity = $this->entityManager() ->getStorageController($this->getEntityTypeId()) ->create($default_values); @@ -753,7 +758,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C } else { $message = 'The specified translation (@langcode) cannot be removed.'; - throw new \InvalidArgumentException(format_string($message, array('@langcode' => $langcode))); + throw new \InvalidArgumentException(String::format($message, array('@langcode' => $langcode))); } } @@ -895,7 +900,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C public function createDuplicate() { if ($this->translations[$this->activeLangcode]['status'] == static::TRANSLATION_REMOVED) { $message = 'The entity object refers to a removed translation (@langcode) and cannot be manipulated.'; - throw new \InvalidArgumentException(format_string($message, array('@langcode' => $this->activeLangcode))); + throw new \InvalidArgumentException(String::format($message, array('@langcode' => $this->activeLangcode))); } $duplicate = clone $this; @@ -904,8 +909,7 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C // Check if the entity type supports UUIDs and generate a new one if so. if ($entity_type->hasKey('uuid')) { - // @todo Inject the UUID service into the Entity class once possible. - $duplicate->{$entity_type->getKey('uuid')}->value = \Drupal::service('uuid')->generate(); + $duplicate->{$entity_type->getKey('uuid')}->value = $this->uuidGenerator()->generate(); } // Check whether the entity type supports revisions and initialize it if so. @@ -953,9 +957,8 @@ abstract class ContentEntityBase extends Entity implements \IteratorAggregate, C public function label() { $label = NULL; $entity_type = $this->getEntityType(); - // @todo Convert to is_callable() and call_user_func(). - if (($label_callback = $entity_type->getLabelCallback()) && function_exists($label_callback)) { - $label = $label_callback($this); + if (($label_callback = $entity_type->getLabelCallback()) && is_callable($label_callback)) { + $label = call_user_func($label_callback, $this); } elseif (($label_key = $entity_type->getKey('label')) && isset($this->{$label_key})) { $label = $this->{$label_key}->value; diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index a6c58b421a3..2bddb375672 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -7,13 +7,14 @@ namespace Drupal\Core\Entity; +use Drupal\Core\DependencyInjection\DependencySerialization; use Drupal\Core\Language\Language; use Drupal\Core\Session\AccountInterface; /** * Defines a base entity class. */ -abstract class Entity implements EntityInterface { +abstract class Entity extends DependencySerialization implements EntityInterface { /** * The language code of the entity's default language. @@ -60,6 +61,33 @@ abstract class Entity implements EntityInterface { } } + /** + * Returns the entity manager. + * + * @return \Drupal\Core\Entity\EntityManagerInterface + */ + protected function entityManager() { + return \Drupal::entityManager(); + } + + /** + * Returns the language manager. + * + * @return \Drupal\Core\Language\LanguageManagerInterface + */ + protected function languageManager() { + return \Drupal::languageManager(); + } + + /** + * Returns the UUID generator. + * + * @return \Drupal\Component\Uuid\UuidInterface + */ + protected function uuidGenerator() { + return \Drupal::service('uuid'); + } + /** * {@inheritdoc} */ @@ -86,6 +114,8 @@ abstract class Entity implements EntityInterface { */ public function enforceIsNew($value = TRUE) { $this->enforceIsNew = $value; + + return $this; } /** @@ -108,9 +138,8 @@ abstract class Entity implements EntityInterface { public function label() { $label = NULL; $entity_type = $this->getEntityType(); - // @todo Convert to is_callable() and call_user_func(). - if (($label_callback = $entity_type->getLabelCallback()) && function_exists($label_callback)) { - $label = $label_callback($this); + if (($label_callback = $entity_type->getLabelCallback()) && is_callable($label_callback)) { + $label = call_user_func($label_callback, $this); } elseif (($label_key = $entity_type->getKey('label')) && isset($this->{$label_key})) { $label = $this->{$label_key}; @@ -138,7 +167,7 @@ abstract class Entity implements EntityInterface { $bundle = $this->bundle(); // A bundle-specific callback takes precedence over the generic one for // the entity type. - $bundles = \Drupal::entityManager()->getBundleInfo($this->getEntityTypeId()); + $bundles = $this->entityManager()->getBundleInfo($this->getEntityTypeId()); if (isset($bundles[$bundle]['uri_callback'])) { $uri_callback = $bundles[$bundle]['uri_callback']; } @@ -148,9 +177,8 @@ abstract class Entity implements EntityInterface { // Invoke the callback to get the URI. If there is no callback, use the // default URI format. - // @todo Convert to is_callable() and call_user_func(). - if (isset($uri_callback) && function_exists($uri_callback)) { - $uri = $uri_callback($this); + if (isset($uri_callback) && is_callable($uri_callback)) { + $uri = call_user_func($uri_callback, $this); } else { return array(); @@ -247,13 +275,13 @@ abstract class Entity implements EntityInterface { /** * {@inheritdoc} */ - public function access($operation = 'view', AccountInterface $account = NULL) { + public function access($operation, AccountInterface $account = NULL) { if ($operation == 'create') { - return \Drupal::entityManager() + return $this->entityManager() ->getAccessController($this->entityTypeId) ->createAccess($this->bundle(), $account); } - return \Drupal::entityManager() + return $this->entityManager() ->getAccessController($this->entityTypeId) ->access($this, $operation, Language::LANGCODE_DEFAULT, $account); } @@ -262,7 +290,7 @@ abstract class Entity implements EntityInterface { * {@inheritdoc} */ public function language() { - $language = language_load($this->langcode); + $language = $this->languageManager()->getLanguage($this->langcode); if (!$language) { // Make sure we return a proper language object. $language = new Language(array('id' => Language::LANGCODE_NOT_SPECIFIED)); @@ -274,7 +302,7 @@ abstract class Entity implements EntityInterface { * {@inheritdoc} */ public function save() { - return \Drupal::entityManager()->getStorageController($this->entityTypeId)->save($this); + return $this->entityManager()->getStorageController($this->entityTypeId)->save($this); } /** @@ -282,7 +310,7 @@ abstract class Entity implements EntityInterface { */ public function delete() { if (!$this->isNew()) { - \Drupal::entityManager()->getStorageController($this->entityTypeId)->delete(array($this->id() => $this)); + $this->entityManager()->getStorageController($this->entityTypeId)->delete(array($this->id() => $this)); } } @@ -296,8 +324,7 @@ abstract class Entity implements EntityInterface { // Check if the entity type supports UUIDs and generate a new one if so. if ($entity_type->hasKey('uuid')) { - // @todo Inject the UUID service into the Entity class once possible. - $duplicate->{$entity_type->getKey('uuid')} = \Drupal::service('uuid')->generate(); + $duplicate->{$entity_type->getKey('uuid')} = $this->uuidGenerator()->generate(); } return $duplicate; } @@ -306,7 +333,7 @@ abstract class Entity implements EntityInterface { * {@inheritdoc} */ public function getEntityType() { - return \Drupal::entityManager()->getDefinition($this->getEntityTypeId()); + return $this->entityManager()->getDefinition($this->getEntityTypeId()); } /** @@ -378,8 +405,8 @@ abstract class Entity implements EntityInterface { } foreach ($referenced_entities as $entity_type => $entities) { - if (\Drupal::entityManager()->hasController($entity_type, 'view_builder')) { - \Drupal::entityManager()->getViewBuilder($entity_type)->resetCache($entities); + if ($this->entityManager()->hasController($entity_type, 'view_builder')) { + $this->entityManager()->getViewBuilder($entity_type)->resetCache($entities); } } } @@ -412,16 +439,6 @@ abstract class Entity implements EntityInterface { return $this->urlGenerator; } - /** - * {@inheritdoc} - */ - public function __sleep() { - // Don't serialize the url generator. - $this->urlGenerator = NULL; - - return array_keys(get_object_vars($this)); - } - /** * {@inheritdoc} */ diff --git a/core/lib/Drupal/Core/Entity/EntityInterface.php b/core/lib/Drupal/Core/Entity/EntityInterface.php index 62acf9d2231..ce4909a9f6f 100644 --- a/core/lib/Drupal/Core/Entity/EntityInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityInterface.php @@ -65,6 +65,8 @@ interface EntityInterface extends AccessibleInterface { * (optional) Whether the entity should be forced to be new. Defaults to * TRUE. * + * @return self + * * @see \Drupal\Core\Entity\EntityInterface::isNew() */ public function enforceIsNew($value = TRUE); diff --git a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php index 452b602140e..581e79cef01 100644 --- a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php +++ b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php @@ -63,7 +63,7 @@ interface ComplexDataInterface extends \Traversable, TypedDataInterface { * @param bool $include_computed * If set to TRUE, computed properties are included. Defaults to FALSE. * - * @return array + * @return \Drupal\Core\TypedData\TypedDataInterface[] * An array of property objects implementing the TypedDataInterface, keyed * by property name. */ diff --git a/core/modules/block/block.module b/core/modules/block/block.module index d3447245802..f54f9587c8e 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -170,7 +170,7 @@ function block_get_blocks_by_region($region) { $build = array(); if ($list = block_list($region)) { foreach ($list as $key => $block) { - if ($block->access()) { + if ($block->access('view')) { $build[$key] = entity_view($block, 'block'); } } diff --git a/core/modules/block/lib/Drupal/block/Entity/Block.php b/core/modules/block/lib/Drupal/block/Entity/Block.php index 6caab044e54..94fe675bf6d 100644 --- a/core/modules/block/lib/Drupal/block/Entity/Block.php +++ b/core/modules/block/lib/Drupal/block/Entity/Block.php @@ -11,6 +11,7 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\block\BlockPluginBag; use Drupal\block\BlockInterface; +use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Config\Entity\EntityWithPluginBagInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; @@ -176,7 +177,7 @@ class Block extends ConfigEntityBase implements BlockInterface, EntityWithPlugin /** * Sorts active blocks by weight; sorts inactive blocks by name. */ - public static function sort($a, $b) { + public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) { // Separate enabled from disabled. $status = $b->get('status') - $a->get('status'); if ($status) { diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php index 55ded74f3e7..7ec5e868c52 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php @@ -97,14 +97,4 @@ class ConfigEntityUnitTest extends DrupalUnitTestBase { } } - /** - * Tests getOriginalId() and setOriginalId(). - */ - protected function testGetOriginalId() { - $entity = $this->storage->create(array()); - $id = $this->randomName(); - $this->assertIdentical(spl_object_hash($entity->setOriginalId($id)), spl_object_hash($entity)); - $this->assertIdentical($entity->getOriginalId(), $id); - } - } diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php index 336afb82d8f..b8d2c569e34 100644 --- a/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php +++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/Entity/ConfigTest.php @@ -9,6 +9,7 @@ namespace Drupal\config_test\Entity; use Drupal\Core\Config\Entity\ConfigEntityBase; use Drupal\config_test\ConfigTestInterface; +use Drupal\Core\Config\Entity\ConfigEntityInterface; /** * Defines the ConfigTest configuration entity. @@ -100,7 +101,7 @@ class ConfigTest extends ConfigEntityBase implements ConfigTestInterface { /** * Overrides \Drupal\Core\Config\Entity\ConfigEntityBase::sort(). */ - public static function sort($a, $b) { + public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) { \Drupal::state()->set('config_entity_sort', TRUE); return parent::sort($a, $b); } diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php index 29ddcfbbec1..699718bd753 100644 --- a/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php +++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayModeBase.php @@ -8,6 +8,7 @@ namespace Drupal\entity; use Drupal\Core\Config\Entity\ConfigEntityBase; +use Drupal\Core\Config\Entity\ConfigEntityInterface; /** * Base class for config entity types that hold settings for form and view modes. @@ -60,7 +61,9 @@ abstract class EntityDisplayModeBase extends ConfigEntityBase implements EntityD /** * {@inheritdoc} */ - public static function sort($a, $b) { + public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) { + /** @var \Drupal\entity\EntityDisplayModeInterface $a */ + /** @var \Drupal\entity\EntityDisplayModeInterface $b */ // Sort by the type of entity the view mode is used for. $a_type = $a->getTargetType(); $b_type = $b->getTargetType(); diff --git a/core/modules/search/lib/Drupal/search/Entity/SearchPage.php b/core/modules/search/lib/Drupal/search/Entity/SearchPage.php index 18a1807f110..c89e5a14b11 100644 --- a/core/modules/search/lib/Drupal/search/Entity/SearchPage.php +++ b/core/modules/search/lib/Drupal/search/Entity/SearchPage.php @@ -8,6 +8,7 @@ namespace Drupal\search\Entity; use Drupal\Core\Config\Entity\ConfigEntityBase; +use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Config\Entity\EntityWithPluginBagInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Component\Plugin\ConfigurablePluginInterface; @@ -213,7 +214,7 @@ class SearchPage extends ConfigEntityBase implements SearchPageInterface, Entity /** * {@inheritdoc} */ - public static function sort($a, $b) { + public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) { /** @var $a \Drupal\search\SearchPageInterface */ /** @var $b \Drupal\search\SearchPageInterface */ $a_status = (int) $a->status(); diff --git a/core/modules/system/lib/Drupal/system/Entity/Action.php b/core/modules/system/lib/Drupal/system/Entity/Action.php index 9f08e20067f..6bc101f07ae 100644 --- a/core/modules/system/lib/Drupal/system/Entity/Action.php +++ b/core/modules/system/lib/Drupal/system/Entity/Action.php @@ -8,6 +8,7 @@ namespace Drupal\system\Entity; use Drupal\Core\Config\Entity\ConfigEntityBase; +use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Config\Entity\EntityWithPluginBagInterface; use Drupal\system\ActionConfigEntityInterface; use Drupal\Core\Action\ActionBag; @@ -131,7 +132,9 @@ class Action extends ConfigEntityBase implements ActionConfigEntityInterface, En /** * {@inheritdoc} */ - public static function sort($a, $b) { + public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) { + /** @var \Drupal\system\ActionConfigEntityInterface $a */ + /** @var \Drupal\system\ActionConfigEntityInterface $b */ $a_type = $a->getType(); $b_type = $b->getType(); if ($a_type != $b_type) { diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityLabelTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityLabelTest.php deleted file mode 100644 index 097c7bc9595..00000000000 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityLabelTest.php +++ /dev/null @@ -1,55 +0,0 @@ - 'Entity label', - 'description' => 'Tests entity labels.', - 'group' => 'Entity API', - ); - } - - /** - * Tests label key and label callback of an entity. - */ - function testEntityLabel() { - $entity_types = array( - 'entity_test_no_label', - 'entity_test_label', - 'entity_test_label_callback', - ); - - $values = array( - 'name' => $this->randomName(), - ); - foreach ($entity_types as $entity_type) { - $entity = entity_create($entity_type, $values); - $label = $entity->label(); - - switch ($entity_type) { - case 'entity_test_no_label': - $this->assertFalse($label, 'Entity with no label property or callback returned FALSE.'); - break; - - case 'entity_test_label': - $this->assertEqual($label, $entity->name->value, 'Entity with label key returned correct label.'); - break; - - case 'entity_test_label_callback': - $this->assertEqual($label, 'label callback ' . $entity->name->value, 'Entity with label callback returned correct label.'); - break; - } - } - } -} diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module index bfc73b515e7..d7a08fc211c 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.module +++ b/core/modules/system/tests/modules/entity_test/entity_test.module @@ -317,19 +317,6 @@ function entity_test_entity_test_insert($entity) { } } -/** - * Entity label callback. - * - * @param $entity - * The entity object. - * - * @return - * The label of the entity prefixed with "label callback". - */ -function entity_test_label_callback($entity) { - return 'label callback ' . $entity->name->value; -} - /** * Implements hook_entity_field_access(). * diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php index a80fc645edd..9deeaa6289b 100644 --- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityBaseUnitTest.php @@ -10,6 +10,7 @@ namespace Drupal\Tests\Core\Config\Entity; use Drupal\Component\Plugin\ConfigurablePluginInterface; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Component\Plugin\PluginBase; +use Drupal\Core\Language\Language; use Drupal\Tests\UnitTestCase; /** @@ -62,6 +63,20 @@ class ConfigEntityBaseUnitTest extends UnitTestCase { */ protected $provider; + /** + * The language manager. + * + * @var \Drupal\Core\Language\LanguageManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $languageManager; + + /** + * The entity ID. + * + * @var string + */ + protected $id; + /** * {@inheritdoc} */ @@ -77,7 +92,12 @@ class ConfigEntityBaseUnitTest extends UnitTestCase { * {@inheritdoc} */ public function setUp() { - $values = array(); + $this->id = $this->randomName(); + $values = array( + 'id' => $this->id, + 'langcode' => 'en', + 'uuid' => '3bb9ee60-bea5-4622-b89b-a63319d10b3a', + ); $this->entityTypeId = $this->randomName(); $this->provider = $this->randomName(); $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface'); @@ -93,9 +113,16 @@ class ConfigEntityBaseUnitTest extends UnitTestCase { $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface'); + $this->languageManager = $this->getMock('\Drupal\Core\Language\LanguageManagerInterface'); + $this->languageManager->expects($this->any()) + ->method('getLanguage') + ->with('en') + ->will($this->returnValue(new Language(array('id' => 'en')))); + $container = new ContainerBuilder(); $container->set('entity.manager', $this->entityManager); $container->set('uuid', $this->uuid); + $container->set('language_manager', $this->languageManager); \Drupal::setContainer($container); $this->entity = $this->getMockForAbstractClass('\Drupal\Core\Config\Entity\ConfigEntityBase', array($values, $this->entityTypeId)); @@ -236,6 +263,158 @@ class ConfigEntityBaseUnitTest extends UnitTestCase { $this->assertEmpty($this->entity->calculateDependencies()); } + /** + * @covers ::setOriginalId + * @covers ::getOriginalId + */ + public function testGetOriginalId() { + $new_id = $this->randomName(); + $this->entity->set('id', $new_id); + $this->assertSame($this->id, $this->entity->getOriginalId()); + $this->assertSame($this->entity, $this->entity->setOriginalId($new_id)); + $this->assertSame($new_id, $this->entity->getOriginalId()); + } + + /** + * @covers ::isNew + */ + public function testIsNew() { + $this->assertFalse($this->entity->isNew()); + $this->assertSame($this->entity, $this->entity->enforceIsNew()); + $this->assertTrue($this->entity->isNew()); + $this->entity->enforceIsNew(FALSE); + $this->assertFalse($this->entity->isNew()); + } + + /** + * @covers ::set + * @covers ::get + */ + public function testGet() { + $name = 'id'; + $value = $this->randomName(); + $this->assertSame($this->id, $this->entity->get($name)); + $this->assertSame($this->entity, $this->entity->set($name, $value)); + $this->assertSame($value, $this->entity->get($name)); + } + + /** + * @covers ::setStatus + * @covers ::status + */ + public function testSetStatus() { + $this->assertTrue($this->entity->status()); + $this->assertSame($this->entity, $this->entity->setStatus(FALSE)); + $this->assertFalse($this->entity->status()); + $this->entity->setStatus(TRUE); + $this->assertTrue($this->entity->status()); + } + + /** + * @covers ::enable + * @depends testSetStatus + */ + public function testEnable() { + $this->entity->setStatus(FALSE); + $this->assertSame($this->entity, $this->entity->enable()); + $this->assertTrue($this->entity->status()); + } + + /** + * @covers ::disable + * @depends testSetStatus + */ + public function testDisable() { + $this->entity->setStatus(TRUE); + $this->assertSame($this->entity, $this->entity->disable()); + $this->assertFalse($this->entity->status()); + } + + /** + * @covers ::setSyncing + * @covers ::isSyncing + */ + public function testIsSyncing() { + $this->assertFalse($this->entity->isSyncing()); + $this->assertSame($this->entity, $this->entity->setSyncing(TRUE)); + $this->assertTrue($this->entity->isSyncing()); + $this->entity->setSyncing(FALSE); + $this->assertFalse($this->entity->isSyncing()); + } + + /** + * @covers ::createDuplicate + */ + public function testCreateDuplicate() { + $this->entityType->expects($this->at(0)) + ->method('getKey') + ->with('id') + ->will($this->returnValue('id')); + + $this->entityType->expects($this->at(1)) + ->method('hasKey') + ->with('uuid') + ->will($this->returnValue(TRUE)); + + $this->entityType->expects($this->at(2)) + ->method('getKey') + ->with('uuid') + ->will($this->returnValue('uuid')); + + $new_uuid = '8607ef21-42bc-4913-978f-8c06207b0395'; + $this->uuid->expects($this->once()) + ->method('generate') + ->will($this->returnValue($new_uuid)); + + $duplicate = $this->entity->createDuplicate(); + $this->assertInstanceOf('\Drupal\Core\Entity\Entity', $duplicate); + $this->assertNotSame($this->entity, $duplicate); + $this->assertNull($duplicate->id()); + $this->assertNull($duplicate->getOriginalId()); + $this->assertNotEquals($this->entity->uuid(), $duplicate->uuid()); + $this->assertSame($new_uuid, $duplicate->uuid()); + } + + /** + * @covers ::sort + */ + public function testSort() { + $this->entityManager->expects($this->any()) + ->method('getDefinition') + ->with($this->entityTypeId) + ->will($this->returnValue(array( + 'entity_keys' => array( + 'label' => 'label', + ), + ))); + $entity_a = $this->entity; + $entity_a->label = 'foo'; + $entity_b = clone $this->entity; + $entity_b->label = 'bar'; + $list = array($entity_a, $entity_b); + // Suppress errors because of https://bugs.php.net/bug.php?id=50688. + @usort($list, '\Drupal\Core\Config\Entity\ConfigEntityBase::sort'); + $this->assertSame($entity_b, $list[0]); + $entity_a->weight = 0; + $entity_b->weight = 1; + // Suppress errors because of https://bugs.php.net/bug.php?id=50688. + @usort($list, array($entity_a, 'sort')); + $this->assertSame($entity_a, $list[0]); + } + + /** + * @covers ::toArray + */ + public function testToArray() { + $properties = $this->entity->toArray(); + $this->assertInternalType('array', $properties); + $class_info = new \ReflectionClass($this->entity); + foreach ($class_info->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { + $name = $property->getName(); + $this->assertArrayHasKey($name, $properties); + $this->assertSame($this->entity->get($name), $properties[$name]); + } + } } class TestConfigurablePlugin extends PluginBase implements ConfigurablePluginInterface { @@ -260,5 +439,4 @@ class TestConfigurablePlugin extends PluginBase implements ConfigurablePluginInt public function defaultConfiguration() { return array(); } - } diff --git a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php new file mode 100644 index 00000000000..9eb55ae41fa --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php @@ -0,0 +1,351 @@ + '', + 'name' => '\Drupal\Core\Entity\ContentEntityBase unit test', + 'group' => 'Entity', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + $this->id = 1; + $values = array( + 'id' => $this->id, + 'langcode' => 'en', + 'uuid' => '3bb9ee60-bea5-4622-b89b-a63319d10b3a', + ); + $this->entityTypeId = $this->randomName(); + $this->bundle = $this->randomName(); + + $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface'); + + $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface'); + $this->entityManager->expects($this->any()) + ->method('getDefinition') + ->with($this->entityTypeId) + ->will($this->returnValue($this->entityType)); + $this->entityManager->expects($this->any()) + ->method('getFieldDefinitions') + ->with($this->entityTypeId, $this->bundle) + ->will($this->returnValue(array( + 'id' => array( + 'type' => 'integer_field', + ), + ))); + + $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface'); + + $this->typedDataManager = $this->getMockBuilder('\Drupal\Core\TypedData\TypedDataManager') + ->disableOriginalConstructor() + ->getMock(); + + $language = new Language(array('id' => 'en')); + $this->languageManager = $this->getMock('\Drupal\Core\Language\LanguageManagerInterface'); + $this->languageManager->expects($this->any()) + ->method('getLanguages') + ->will($this->returnValue(array('en' => $language))); + $this->languageManager->expects($this->any()) + ->method('getLanguage') + ->with('en') + ->will($this->returnValue($language)); + + $container = new ContainerBuilder(); + $container->set('entity.manager', $this->entityManager); + $container->set('uuid', $this->uuid); + $container->set('typed_data_manager', $this->typedDataManager); + $container->set('language_manager', $this->languageManager); + \Drupal::setContainer($container); + + $this->entity = $this->getMockForAbstractClass('\Drupal\Core\Entity\ContentEntityBase', array($values, $this->entityTypeId, $this->bundle)); + } + + /** + * @covers ::isNewRevision + * @covers ::setNewRevision + */ + public function testIsNewRevision() { + // Set up the entity type so that on the first call there is no revision key + // and on the second call there is one. + $this->entityType->expects($this->at(0)) + ->method('hasKey') + ->with('revision') + ->will($this->returnValue(FALSE)); + $this->entityType->expects($this->at(1)) + ->method('hasKey') + ->with('revision') + ->will($this->returnValue(TRUE)); + + $this->assertFalse($this->entity->isNewRevision()); + $this->assertTrue($this->entity->isNewRevision()); + $this->entity->setNewRevision(TRUE); + $this->assertTRUE($this->entity->isNewRevision()); + } + + /** + * @covers ::isDefaultRevision + */ + public function testIsDefaultRevision() { + // The default value is TRUE. + $this->assertTrue($this->entity->isDefaultRevision()); + // Change the default revision, verify that the old value is returned. + $this->assertTrue($this->entity->isDefaultRevision(FALSE)); + // The last call changed the return value for this call. + $this->assertFalse($this->entity->isDefaultRevision()); + } + + /** + * @covers ::getRevisionId + */ + public function testGetRevisionId() { + // The default getRevisionId() implementation returns NULL. + $this->assertNull($this->entity->getRevisionId()); + } + + /** + * @covers ::isTranslatable + */ + public function testIsTranslatable() { + $this->entityManager->expects($this->at(0)) + ->method('getBundleInfo') + ->with($this->entityTypeId) + ->will($this->returnValue(array( + $this->bundle => array( + 'translatable' => TRUE, + ), + ))); + $this->assertTrue($this->entity->isTranslatable()); + $this->assertFalse($this->entity->isTranslatable()); + } + + /** + * @covers ::preSaveRevision + */ + public function testPreSaveRevision() { + // This method is internal, so check for errors on calling it only. + $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); + $record = new \stdClass(); + $this->entity->preSaveRevision($storage, $record); + } + + /** + * @covers ::getString + */ + public function testGetString() { + $label = $this->randomName(); + /** @var \Drupal\Core\Entity\ContentEntityBase|\PHPUnit_Framework_MockObject_MockObject $entity */ + $entity = $this->getMockBuilder('\Drupal\Core\Entity\ContentEntityBase') + ->setMethods(array('label')) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $entity->expects($this->once()) + ->method('label') + ->will($this->returnValue($label)); + + $this->assertSame($label, $entity->getString()); + } + + /** + * @covers ::validate + */ + public function testValidate() { + $validator = $this->getMock('\Symfony\Component\Validator\ValidatorInterface'); + /** @var \Symfony\Component\Validator\ConstraintViolationList|\PHPUnit_Framework_MockObject_MockObject $empty_violation_list */ + $empty_violation_list = $this->getMockBuilder('\Symfony\Component\Validator\ConstraintViolationList') + ->setMethods(NULL) + ->getMock(); + $non_empty_violation_list = clone $empty_violation_list; + $violation = $this->getMock('\Symfony\Component\Validator\ConstraintViolationInterface'); + $non_empty_violation_list->add($violation); + $validator->expects($this->at(0)) + ->method('validate') + ->with($this->entity) + ->will($this->returnValue($empty_violation_list)); + $validator->expects($this->at(1)) + ->method('validate') + ->with($this->entity) + ->will($this->returnValue($non_empty_violation_list)); + $this->typedDataManager->expects($this->exactly(2)) + ->method('getValidator') + ->will($this->returnValue($validator)); + $this->assertSame(0, count($this->entity->validate())); + $this->assertSame(1, count($this->entity->validate())); + } + + /** + * @covers ::getConstraints + */ + public function testGetConstraints() { + $this->assertInternalType('array', $this->entity->getConstraints()); + } + + /** + * @covers ::getName + */ + public function testGetName() { + $this->assertNull($this->entity->getName()); + } + + /** + * @covers ::getRoot + */ + public function testGetRoot() { + $this->assertSame(spl_object_hash($this->entity), spl_object_hash($this->entity->getRoot())); + } + + /** + * @covers ::getPropertyPath + */ + public function testGetPropertyPath() { + $this->assertSame('', $this->entity->getPropertyPath()); + } + + /** + * @covers ::getParent + */ + public function testGetParent() { + $this->assertNull($this->entity->getParent()); + } + + /** + * @covers ::setContext + */ + public function testSetContext() { + $name = $this->randomName(); + $parent = $this->getMock('\Drupal\Core\TypedData\TypedDataInterface'); + $this->entity->setContext($name, $parent); + } + + /** + * @covers ::bundle + */ + public function testBundle() { + $this->assertSame($this->bundle, $this->entity->bundle()); + } + + /** + * @covers ::access + */ + public function testAccess() { + $access = $this->getMock('\Drupal\Core\Entity\EntityAccessControllerInterface'); + $operation = $this->randomName(); + $access->expects($this->at(0)) + ->method('access') + ->with($this->entity, $operation) + ->will($this->returnValue(TRUE)); + $access->expects($this->at(1)) + ->method('createAccess') + ->will($this->returnValue(TRUE)); + $this->entityManager->expects($this->exactly(2)) + ->method('getAccessController') + ->will($this->returnValue($access)); + $this->assertTrue($this->entity->access($operation)); + $this->assertTrue($this->entity->access('create')); + } + + /** + * @covers ::label + */ + public function testLabel() { + // Make a mock with one method that we use as the entity's label callback. + // We check that it is called, and that the entity's label is the callback's + // return value. + $callback_label = $this->randomName(); + $callback_container = $this->getMock(get_class()); + $callback_container->expects($this->once()) + ->method(__FUNCTION__) + ->will($this->returnValue($callback_label)); + $this->entityType->expects($this->once()) + ->method('getLabelCallback') + ->will($this->returnValue(array($callback_container, __FUNCTION__))); + + $this->assertSame($callback_label, $this->entity->label()); + } +} diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php new file mode 100644 index 00000000000..be09ad8cd56 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php @@ -0,0 +1,348 @@ + '', + 'name' => '\Drupal\Core\Entity\Entity unit test', + 'group' => 'Entity', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + $this->values = array( + 'id' => 1, + 'langcode' => 'en', + 'uuid' => '3bb9ee60-bea5-4622-b89b-a63319d10b3a', + ); + $this->entityTypeId = $this->randomName(); + + $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface'); + + $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface'); + $this->entityManager->expects($this->any()) + ->method('getDefinition') + ->with($this->entityTypeId) + ->will($this->returnValue($this->entityType)); + + $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface'); + + $this->languageManager = $this->getMock('\Drupal\Core\Language\LanguageManagerInterface'); + $this->languageManager->expects($this->any()) + ->method('getLanguage') + ->with('en') + ->will($this->returnValue(new Language(array('id' => 'en')))); + + $container = new ContainerBuilder(); + $container->set('entity.manager', $this->entityManager); + $container->set('uuid', $this->uuid); + $container->set('language_manager', $this->languageManager); + + \Drupal::setContainer($container); + + $this->entity = $this->getMockForAbstractClass('\Drupal\Core\Entity\Entity', array($this->values, $this->entityTypeId)); + } + + /** + * @covers ::id + */ + public function testId() { + $this->assertSame($this->values['id'], $this->entity->id()); + } + + /** + * @covers ::uuid + */ + public function testUuid() { + $this->assertSame($this->values['uuid'], $this->entity->uuid()); + } + + /** + * @covers ::isNew + * @covers ::enforceIsNew + */ + public function testIsNew() { + // We provided an ID, so the entity is not new. + $this->assertFalse($this->entity->isNew()); + // Force it to be new. + $this->assertSame($this->entity, $this->entity->enforceIsNew()); + $this->assertTrue($this->entity->isNew()); + } + + /** + * @covers ::getEntityType + */ + public function testGetEntityType() { + $this->assertSame($this->entityType, $this->entity->getEntityType()); + } + + /** + * @covers ::bundle + */ + public function testBundle() { + $this->assertSame($this->entityTypeId, $this->entity->bundle()); + } + + /** + * @covers ::label + */ + public function testLabel() { + // Make a mock with one method that we use as the entity's uri_callback. We + // check that it is called, and that the entity's label is the callback's + // return value. + $callback_label = $this->randomName(); + $property_label = $this->randomName(); + $callback_container = $this->getMock(get_class()); + $callback_container->expects($this->once()) + ->method(__FUNCTION__) + ->will($this->returnValue($callback_label)); + $this->entityType->expects($this->at(0)) + ->method('getLabelCallback') + ->will($this->returnValue(array($callback_container, __FUNCTION__))); + $this->entityType->expects($this->at(1)) + ->method('getLabelCallback') + ->will($this->returnValue(NULL)); + $this->entityType->expects($this->at(2)) + ->method('getKey') + ->with('label') + ->will($this->returnValue('label')); + + // Set a dummy property on the entity under test to test that the label can + // be returned form a property if there is no callback. + $this->entityManager->expects($this->at(1)) + ->method('getDefinition') + ->with($this->entityTypeId) + ->will($this->returnValue(array( + 'entity_keys' => array( + 'label' => 'label', + ), + ))); + $this->entity->label = $property_label; + + $this->assertSame($callback_label, $this->entity->label()); + $this->assertSame($property_label, $this->entity->label()); + } + + /** + * @covers ::access + */ + public function testAccess() { + $access = $this->getMock('\Drupal\Core\Entity\EntityAccessControllerInterface'); + $operation = $this->randomName(); + $access->expects($this->at(0)) + ->method('access') + ->with($this->entity, $operation) + ->will($this->returnValue(TRUE)); + $access->expects($this->at(1)) + ->method('createAccess') + ->will($this->returnValue(TRUE)); + $this->entityManager->expects($this->exactly(2)) + ->method('getAccessController') + ->will($this->returnValue($access)); + $this->assertTrue($this->entity->access($operation)); + $this->assertTrue($this->entity->access('create')); + } + + /** + * @covers ::language + */ + public function testLanguage() { + $this->assertSame('en', $this->entity->language()->id); + } + + /** + * @covers ::save + */ + public function testSave() { + $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); + $storage->expects($this->once()) + ->method('save') + ->with($this->entity); + $this->entityManager->expects($this->once()) + ->method('getStorageController') + ->with($this->entityTypeId) + ->will($this->returnValue($storage)); + $this->entity->save(); + } + + /** + * @covers ::delete + */ + public function testDelete() { + $this->entity->id = $this->randomName(); + $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); + // Testing the argument of the delete() method consumes too much memory. + $storage->expects($this->once()) + ->method('delete'); + $this->entityManager->expects($this->once()) + ->method('getStorageController') + ->with($this->entityTypeId) + ->will($this->returnValue($storage)); + $this->entity->delete(); + } + + /** + * @covers ::getEntityTypeId + */ + public function testGetEntityTypeId() { + $this->assertSame($this->entityTypeId, $this->entity->getEntityTypeId()); + } + + /** + * @covers ::preSave + */ + public function testPreSave() { + // This method is internal, so check for errors on calling it only. + $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); + $this->entity->preSave($storage); + } + + /** + * @covers ::postSave + */ + public function testPostSave() { + // This method is internal, so check for errors on calling it only. + $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); + $this->entity->postSave($storage); + } + + /** + * @covers ::preCreate + */ + public function testPreCreate() { + // This method is internal, so check for errors on calling it only. + $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); + $values = array(); + $this->entity->preCreate($storage, $values); + } + + /** + * @covers ::postCreate + */ + public function testPostCreate() { + // This method is internal, so check for errors on calling it only. + $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); + $this->entity->postCreate($storage); + } + + /** + * @covers ::preDelete + */ + public function testPreDelete() { + // This method is internal, so check for errors on calling it only. + $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); + $this->entity->preDelete($storage, array($this->entity)); + } + + /** + * @covers ::postDelete + */ + public function testPostDelete() { + $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); + + $entity = $this->getMockBuilder('\Drupal\Core\Entity\Entity') + ->setMethods(array('onSaveOrDelete')) + ->disableOriginalConstructor() + ->getMock(); + $entity->expects($this->once()) + ->method('onSaveOrDelete'); + + $this->entity->postDelete($storage, array($entity)); + } + + /** + * @covers ::postLoad + */ + public function testPostLoad() { + // This method is internal, so check for errors on calling it only. + $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageControllerInterface'); + $entities = array($this->entity); + $this->entity->postLoad($storage, $entities); + } + + /** + * @covers ::referencedEntities + */ + public function testReferencedEntities() { + $this->assertSame(array(), $this->entity->referencedEntities()); + } +}