diff --git a/core/modules/action/tests/src/Functional/ActionListTest.php b/core/modules/action/src/Tests/ActionListTest.php similarity index 87% rename from core/modules/action/tests/src/Functional/ActionListTest.php rename to core/modules/action/src/Tests/ActionListTest.php index 2510e86..f533cdf 100644 --- a/core/modules/action/tests/src/Functional/ActionListTest.php +++ b/core/modules/action/src/Tests/ActionListTest.php @@ -1,15 +1,15 @@ profile != 'standard') { - $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); - } - - $this->adminUser = $this->drupalCreateUser(array('access administration pages', 'administer news feeds', 'access news feeds', 'create article content')); - $this->drupalLogin($this->adminUser); - $this->drupalPlaceBlock('local_tasks_block'); - } - - /** - * Creates an aggregator feed. - * - * This method simulates the form submission on path aggregator/sources/add. - * - * @param string $feed_url - * (optional) If given, feed will be created with this URL, otherwise - * /rss.xml will be used. Defaults to NULL. - * @param array $edit - * Array with additional form fields. - * - * @return \Drupal\aggregator\FeedInterface - * Full feed object if possible. - * - * @see getFeedEditArray() - */ - public function createFeed($feed_url = NULL, array $edit = array()) { - $edit = $this->getFeedEditArray($feed_url, $edit); - $this->drupalPostForm('aggregator/sources/add', $edit, t('Save')); - $this->assertText(t('The feed @name has been added.', array('@name' => $edit['title[0][value]'])), format_string('The feed @name has been added.', array('@name' => $edit['title[0][value]']))); - - // Verify that the creation message contains a link to a feed. - $view_link = $this->xpath('//div[@class="messages"]//a[contains(@href, :href)]', array(':href' => 'aggregator/sources/')); - $this->assert(isset($view_link), 'The message area contains a link to a feed'); - - $fid = db_query("SELECT fid FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $edit['title[0][value]'], ':url' => $edit['url[0][value]']))->fetchField(); - $this->assertTrue(!empty($fid), 'The feed found in database.'); - return Feed::load($fid); - } - - /** - * Deletes an aggregator feed. - * - * @param \Drupal\aggregator\FeedInterface $feed - * Feed object representing the feed. - */ - public function deleteFeed(FeedInterface $feed) { - $this->drupalPostForm('aggregator/sources/' . $feed->id() . '/delete', array(), t('Delete')); - $this->assertRaw(t('The feed %title has been deleted.', array('%title' => $feed->label())), 'Feed deleted successfully.'); - } - - /** - * Returns a randomly generated feed edit array. - * - * @param string $feed_url - * (optional) If given, feed will be created with this URL, otherwise - * /rss.xml will be used. Defaults to NULL. - * @param array $edit - * Array with additional form fields. - * - * @return array - * A feed array. - */ - public function getFeedEditArray($feed_url = NULL, array $edit = array()) { - $feed_name = $this->randomMachineName(10); - if (!$feed_url) { - $feed_url = \Drupal::url('view.frontpage.feed_1', array(), array( - 'query' => array('feed' => $feed_name), - 'absolute' => TRUE, - )); - } - $edit += array( - 'title[0][value]' => $feed_name, - 'url[0][value]' => $feed_url, - 'refresh' => '900', - ); - return $edit; - } - - /** - * Returns a randomly generated feed edit object. - * - * @param string $feed_url - * (optional) If given, feed will be created with this URL, otherwise - * /rss.xml will be used. Defaults to NULL. - * @param array $values - * (optional) Default values to initialize object properties with. - * - * @return \Drupal\aggregator\FeedInterface - * A feed object. - */ - public function getFeedEditObject($feed_url = NULL, array $values = array()) { - $feed_name = $this->randomMachineName(10); - if (!$feed_url) { - $feed_url = \Drupal::url('view.frontpage.feed_1', array( - 'query' => array('feed' => $feed_name), - 'absolute' => TRUE, - )); - } - $values += array( - 'title' => $feed_name, - 'url' => $feed_url, - 'refresh' => '900', - ); - return Feed::create($values); - } - - /** - * Returns the count of the randomly created feed array. - * - * @return int - * Number of feed items on default feed created by createFeed(). - */ - public function getDefaultFeedItemCount() { - // Our tests are based off of rss.xml, so let's find out how many elements should be related. - $feed_count = db_query_range('SELECT COUNT(DISTINCT nid) FROM {node_field_data} n WHERE n.promote = 1 AND n.status = 1', 0, $this->config('system.rss')->get('items.limit'))->fetchField(); - return $feed_count > 10 ? 10 : $feed_count; - } - - /** - * Updates the feed items. - * - * This method simulates a click to - * admin/config/services/aggregator/update/$fid. - * - * @param \Drupal\aggregator\FeedInterface $feed - * Feed object representing the feed. - * @param int|null $expected_count - * Expected number of feed items. If omitted no check will happen. - */ - public function updateFeedItems(FeedInterface $feed, $expected_count = NULL) { - // First, let's ensure we can get to the rss xml. - $this->drupalGet($feed->getUrl()); - $this->assertResponse(200, format_string(':url is reachable.', array(':url' => $feed->getUrl()))); - - // Attempt to access the update link directly without an access token. - $this->drupalGet('admin/config/services/aggregator/update/' . $feed->id()); - $this->assertResponse(403); - - // Refresh the feed (simulated link click). - $this->drupalGet('admin/config/services/aggregator'); - $this->clickLink('Update items'); - - // Ensure we have the right number of items. - $result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->id())); - $feed->items = array(); - foreach ($result as $item) { - $feed->items[] = $item->iid; - } - - if ($expected_count !== NULL) { - $feed->item_count = count($feed->items); - $this->assertEqual($expected_count, $feed->item_count, format_string('Total items in feed equal to the total items in database (@val1 != @val2)', array('@val1' => $expected_count, '@val2' => $feed->item_count))); - } - } - - /** - * Confirms an item removal from a feed. - * - * @param \Drupal\aggregator\FeedInterface $feed - * Feed object representing the feed. - */ - public function deleteFeedItems(FeedInterface $feed) { - $this->drupalPostForm('admin/config/services/aggregator/delete/' . $feed->id(), array(), t('Delete items')); - $this->assertRaw(t('The news items from %title have been deleted.', array('%title' => $feed->label())), 'Feed items deleted.'); - } - - /** - * Adds and deletes feed items and ensure that the count is zero. - * - * @param \Drupal\aggregator\FeedInterface $feed - * Feed object representing the feed. - * @param int $expected_count - * Expected number of feed items. - */ - public function updateAndDelete(FeedInterface $feed, $expected_count) { - $this->updateFeedItems($feed, $expected_count); - $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->id()))->fetchField(); - $this->assertTrue($count); - $this->deleteFeedItems($feed); - $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->id()))->fetchField(); - $this->assertTrue($count == 0); - } - - /** - * Checks whether the feed name and URL are unique. - * - * @param string $feed_name - * String containing the feed name to check. - * @param string $feed_url - * String containing the feed url to check. - * - * @return bool - * TRUE if feed is unique. - */ - public function uniqueFeed($feed_name, $feed_url) { - $result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed_name, ':url' => $feed_url))->fetchField(); - return (1 == $result); - } - - /** - * Creates a valid OPML file from an array of feeds. - * - * @param array $feeds - * An array of feeds. - * - * @return string - * Path to valid OPML file. - */ - public function getValidOpml(array $feeds) { - // Properly escape URLs so that XML parsers don't choke on them. - foreach ($feeds as &$feed) { - $feed['url[0][value]'] = Html::escape($feed['url[0][value]']); - } - /** - * Does not have an XML declaration, must pass the parser. - */ - $opml = << - - - - - - - - - - - - - - - - - -EOF; - - $path = 'public://valid-opml.xml'; - // Add the UTF-8 byte order mark. - return file_unmanaged_save_data(chr(239) . chr(187) . chr(191) . $opml, $path); - } - - /** - * Creates an invalid OPML file. - * - * @return string - * Path to invalid OPML file. - */ - public function getInvalidOpml() { - $opml = << - - -EOF; - - $path = 'public://invalid-opml.xml'; - return file_unmanaged_save_data($opml, $path); - } - - /** - * Creates a valid but empty OPML file. - * - * @return string - * Path to empty OPML file. - */ - public function getEmptyOpml() { - $opml = << - - - - - - - -EOF; - - $path = 'public://empty-opml.xml'; - return file_unmanaged_save_data($opml, $path); - } - - /** - * Returns a example RSS091 feed. - * - * @return string - * Path to the feed. - */ - public function getRSS091Sample() { - return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/modules/aggregator_test/aggregator_test_rss091.xml'; - } - - /** - * Returns a example Atom feed. - * - * @return string - * Path to the feed. - */ - public function getAtomSample() { - // The content of this sample ATOM feed is based directly off of the - // example provided in RFC 4287. - return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/modules/aggregator_test/aggregator_test_atom.xml'; - } - - /** - * Returns a example feed. - * - * @return string - * Path to the feed. - */ - public function getHtmlEntitiesSample() { - return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/modules/aggregator_test/aggregator_test_title_entities.xml'; - } - - /** - * Creates sample article nodes. - * - * @param int $count - * (optional) The number of nodes to generate. Defaults to five. - */ - public function createSampleNodes($count = 5) { - // Post $count article nodes. - for ($i = 0; $i < $count; $i++) { - $edit = array(); - $edit['title[0][value]'] = $this->randomMachineName(); - $edit['body[0][value]'] = $this->randomMachineName(); - $this->drupalPostForm('node/add/article', $edit, t('Save')); - } - } - - /** - * Enable the plugins coming with aggregator_test module. - */ - public function enableTestPlugins() { - $this->config('aggregator.settings') - ->set('fetcher', 'aggregator_test_fetcher') - ->set('parser', 'aggregator_test_parser') - ->set('processors', array( - 'aggregator_test_processor' => 'aggregator_test_processor', - 'aggregator' => 'aggregator', - )) - ->save(); - } - -} diff --git a/core/modules/block/tests/src/Functional/BlockCacheTest.php b/core/modules/block/src/Tests/BlockCacheTest.php similarity index 98% rename from core/modules/block/tests/src/Functional/BlockCacheTest.php rename to core/modules/block/src/Tests/BlockCacheTest.php index 9285c64..8988580 100644 --- a/core/modules/block/tests/src/Functional/BlockCacheTest.php +++ b/core/modules/block/src/Tests/BlockCacheTest.php @@ -1,16 +1,16 @@ autoCreateBasicBlockType) { - $this->createBlockContentType('basic', TRUE); - } - - $this->adminUser = $this->drupalCreateUser($this->permissions); - $this->drupalPlaceBlock('local_actions_block'); - } - - /** - * Creates a custom block. - * - * @param bool|string $title - * (optional) Title of block. When no value is given uses a random name. - * Defaults to FALSE. - * @param string $bundle - * (optional) Bundle name. Defaults to 'basic'. - * @param bool $save - * (optional) Whether to save the block. Defaults to TRUE. - * - * @return \Drupal\block_content\Entity\BlockContent - * Created custom block. - */ - protected function createBlockContent($title = FALSE, $bundle = 'basic', $save = TRUE) { - $title = $title ?: $this->randomMachineName(); - $block_content = BlockContent::create(array( - 'info' => $title, - 'type' => $bundle, - 'langcode' => 'en' - )); - if ($block_content && $save === TRUE) { - $block_content->save(); - } - return $block_content; - } - - /** - * Creates a custom block type (bundle). - * - * @param string $label - * The block type label. - * @param bool $create_body - * Whether or not to create the body field - * - * @return \Drupal\block_content\Entity\BlockContentType - * Created custom block type. - */ - protected function createBlockContentType($label, $create_body = FALSE) { - $bundle = BlockContentType::create(array( - 'id' => $label, - 'label' => $label, - 'revision' => FALSE, - )); - $bundle->save(); - if ($create_body) { - block_content_add_body_field($bundle->id()); - } - return $bundle; - } - -} diff --git a/core/modules/ckeditor/tests/src/Functional/CKEditorToolbarButtonTest.php b/core/modules/ckeditor/src/Tests/CKEditorToolbarButtonTest.php similarity index 93% rename from core/modules/ckeditor/tests/src/Functional/CKEditorToolbarButtonTest.php rename to core/modules/ckeditor/src/Tests/CKEditorToolbarButtonTest.php index e8d0e2d..22874b7 100644 --- a/core/modules/ckeditor/tests/src/Functional/CKEditorToolbarButtonTest.php +++ b/core/modules/ckeditor/src/Tests/CKEditorToolbarButtonTest.php @@ -1,11 +1,11 @@ adminUser = $this->drupalCreateUser($this->permissions); - $this->drupalPlaceBlock('local_tasks_block', ['id' => 'tabs_block']); - $this->drupalPlaceBlock('page_title_block'); - $this->drupalPlaceBlock('local_actions_block', ['id' => 'actions_block']); - } - - /** - * Gets the permission machine name for a transition. - * - * @param string $workflow_id - * The workflow ID. - * @param string $transition_id - * The transition ID. - * - * @return string - * The permission machine name for a transition. - */ - protected function getWorkflowTransitionPermission($workflow_id, $transition_id) { - return 'use ' . $workflow_id . ' transition ' . $transition_id; - } - - /** - * Creates a content-type from the UI. - * - * @param string $content_type_name - * Content type human name. - * @param string $content_type_id - * Machine name. - * @param bool $moderated - * TRUE if should be moderated. - * @param string $workflow_id - * The workflow to attach to the bundle. - */ - protected function createContentTypeFromUi($content_type_name, $content_type_id, $moderated = FALSE, $workflow_id = 'editorial') { - $this->drupalGet('admin/structure/types'); - $this->clickLink('Add content type'); - $edit = [ - 'name' => $content_type_name, - 'type' => $content_type_id, - ]; - $this->drupalPostForm(NULL, $edit, t('Save content type')); - - if ($moderated) { - $this->enableModerationThroughUi($content_type_id, $workflow_id); - } - } - - /** - * Enable moderation for a specified content type, using the UI. - * - * @param string $content_type_id - * Machine name. - * @param string $workflow_id - * The workflow to attach to the bundle. - */ - protected function enableModerationThroughUi($content_type_id, $workflow_id = 'editorial') { - $edit['workflow'] = $workflow_id; - $this->drupalPostForm('admin/structure/types/manage/' . $content_type_id . '/moderation', $edit, t('Save')); - // Ensure the parent environment is up-to-date. - // @see content_moderation_workflow_insert() - \Drupal::service('entity_type.bundle.info')->clearCachedBundles(); - \Drupal::service('entity_field.manager')->clearCachedFieldDefinitions(); - } - - /** - * Grants given user permission to create content of given type. - * - * @param \Drupal\Core\Session\AccountInterface $account - * User to grant permission to. - * @param string $content_type_id - * Content type ID. - */ - protected function grantUserPermissionToCreateContentOfType(AccountInterface $account, $content_type_id) { - $role_ids = $account->getRoles(TRUE); - /* @var \Drupal\user\RoleInterface $role */ - $role_id = reset($role_ids); - $role = Role::load($role_id); - $role->grantPermission(sprintf('create %s content', $content_type_id)); - $role->grantPermission(sprintf('edit any %s content', $content_type_id)); - $role->grantPermission(sprintf('delete any %s content', $content_type_id)); - $role->save(); - } - -} diff --git a/core/modules/content_translation/tests/src/Functional/ContentTranslationEntityBundleUITest.php b/core/modules/content_translation/src/Tests/ContentTranslationEntityBundleUITest.php similarity index 91% rename from core/modules/content_translation/tests/src/Functional/ContentTranslationEntityBundleUITest.php rename to core/modules/content_translation/src/Tests/ContentTranslationEntityBundleUITest.php index c735716..03f30a1 100644 --- a/core/modules/content_translation/tests/src/Functional/ContentTranslationEntityBundleUITest.php +++ b/core/modules/content_translation/src/Tests/ContentTranslationEntityBundleUITest.php @@ -1,15 +1,15 @@ setupLanguages(); - $this->setupBundle(); - $this->enableTranslation(); - $this->setupUsers(); - $this->setupTestFields(); - - $this->manager = $this->container->get('content_translation.manager'); - $this->controller = $this->manager->getTranslationHandler($this->entityTypeId); - - // Rebuild the container so that the new languages are picked up by services - // that hold a list of languages. - $this->rebuildContainer(); - } - - /** - * Adds additional languages. - */ - protected function setupLanguages() { - $this->langcodes = array('it', 'fr'); - foreach ($this->langcodes as $langcode) { - ConfigurableLanguage::createFromLangcode($langcode)->save(); - } - array_unshift($this->langcodes, \Drupal::languageManager()->getDefaultLanguage()->getId()); - } - - /** - * Returns an array of permissions needed for the translator. - */ - protected function getTranslatorPermissions() { - return array_filter(array($this->getTranslatePermission(), 'create content translations', 'update content translations', 'delete content translations')); - } - - /** - * Returns the translate permissions for the current entity and bundle. - */ - protected function getTranslatePermission() { - $entity_type = \Drupal::entityManager()->getDefinition($this->entityTypeId); - if ($permission_granularity = $entity_type->getPermissionGranularity()) { - return $permission_granularity == 'bundle' ? "translate {$this->bundle} {$this->entityTypeId}" : "translate {$this->entityTypeId}"; - } - } - - /** - * Returns an array of permissions needed for the editor. - */ - protected function getEditorPermissions() { - // Every entity-type-specific test needs to define these. - return array(); - } - - /** - * Returns an array of permissions needed for the administrator. - */ - protected function getAdministratorPermissions() { - return array_merge($this->getEditorPermissions(), $this->getTranslatorPermissions(), array('administer content translation')); - } - - /** - * Creates and activates translator, editor and admin users. - */ - protected function setupUsers() { - $this->translator = $this->drupalCreateUser($this->getTranslatorPermissions(), 'translator'); - $this->editor = $this->drupalCreateUser($this->getEditorPermissions(), 'editor'); - $this->administrator = $this->drupalCreateUser($this->getAdministratorPermissions(), 'administrator'); - $this->drupalLogin($this->translator); - } - - /** - * Creates or initializes the bundle date if needed. - */ - protected function setupBundle() { - if (empty($this->bundle)) { - $this->bundle = $this->entityTypeId; - } - } - - /** - * Enables translation for the current entity type and bundle. - */ - protected function enableTranslation() { - // Enable translation for the current entity type and ensure the change is - // picked up. - \Drupal::service('content_translation.manager')->setEnabled($this->entityTypeId, $this->bundle, TRUE); - drupal_static_reset(); - \Drupal::entityManager()->clearCachedDefinitions(); - \Drupal::service('router.builder')->rebuild(); - \Drupal::service('entity.definition_update_manager')->applyUpdates(); - } - - /** - * Creates the test fields. - */ - protected function setupTestFields() { - if (empty($this->fieldName)) { - $this->fieldName = 'field_test_et_ui_test'; - } - FieldStorageConfig::create(array( - 'field_name' => $this->fieldName, - 'type' => 'string', - 'entity_type' => $this->entityTypeId, - 'cardinality' => 1, - ))->save(); - FieldConfig::create([ - 'entity_type' => $this->entityTypeId, - 'field_name' => $this->fieldName, - 'bundle' => $this->bundle, - 'label' => 'Test translatable text-field', - ])->save(); - entity_get_form_display($this->entityTypeId, $this->bundle, 'default') - ->setComponent($this->fieldName, array( - 'type' => 'string_textfield', - 'weight' => 0, - )) - ->save(); - } - - /** - * Creates the entity to be translated. - * - * @param array $values - * An array of initial values for the entity. - * @param string $langcode - * The initial language code of the entity. - * @param string $bundle_name - * (optional) The entity bundle, if the entity uses bundles. Defaults to - * NULL. If left NULL, $this->bundle will be used. - * - * @return string - * The entity id. - */ - protected function createEntity($values, $langcode, $bundle_name = NULL) { - $entity_values = $values; - $entity_values['langcode'] = $langcode; - $entity_type = \Drupal::entityManager()->getDefinition($this->entityTypeId); - if ($bundle_key = $entity_type->getKey('bundle')) { - $entity_values[$bundle_key] = $bundle_name ?: $this->bundle; - } - $controller = $this->container->get('entity.manager')->getStorage($this->entityTypeId); - if (!($controller instanceof SqlContentEntityStorage)) { - foreach ($values as $property => $value) { - if (is_array($value)) { - $entity_values[$property] = array($langcode => $value); - } - } - } - $entity = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId) - ->create($entity_values); - $entity->save(); - return $entity->id(); - } - -} diff --git a/core/modules/content_translation/tests/src/Functional/ContentTranslationUITestBase.php b/core/modules/content_translation/tests/src/Functional/ContentTranslationUITestBase.php deleted file mode 100644 index 769006e..0000000 --- a/core/modules/content_translation/tests/src/Functional/ContentTranslationUITestBase.php +++ /dev/null @@ -1,627 +0,0 @@ -doTestBasicTranslation(); - $this->doTestTranslationOverview(); - $this->doTestOutdatedStatus(); - $this->doTestPublishedStatus(); - $this->doTestAuthoringInfo(); - $this->doTestTranslationEdit(); - $this->doTestTranslationChanged(); - $this->doTestChangedTimeAfterSaveWithoutChanges(); - $this->doTestTranslationDeletion(); - } - - /** - * Tests the basic translation workflow. - */ - protected function doTestBasicTranslation() { - // Create a new test entity with original values in the default language. - $default_langcode = $this->langcodes[0]; - $values[$default_langcode] = $this->getNewEntityValues($default_langcode); - // Create the entity with the editor as owner, so that afterwards a new - // translation is created by the translator and the translation author is - // tested. - $this->drupalLogin($this->editor); - $this->entityId = $this->createEntity($values[$default_langcode], $default_langcode); - $this->drupalLogin($this->translator); - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $this->assertTrue($entity, 'Entity found in the database.'); - $this->drupalGet($entity->urlInfo()); - $this->assertResponse(200, 'Entity URL is valid.'); - - // Ensure that the content language cache context is not yet added to the - // page. - $this->assertCacheContexts($this->defaultCacheContexts); - - $this->drupalGet($entity->urlInfo('drupal:content-translation-overview')); - $this->assertNoText('Source language', 'Source language column correctly hidden.'); - - $translation = $this->getTranslation($entity, $default_langcode); - foreach ($values[$default_langcode] as $property => $value) { - $stored_value = $this->getValue($translation, $property, $default_langcode); - $value = is_array($value) ? $value[0]['value'] : $value; - $message = format_string('@property correctly stored in the default language.', array('@property' => $property)); - $this->assertEqual($stored_value, $value, $message); - } - - // Add a content translation. - $langcode = 'it'; - $language = ConfigurableLanguage::load($langcode); - $values[$langcode] = $this->getNewEntityValues($langcode); - - $entity_type_id = $entity->getEntityTypeId(); - $add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [ - $entity->getEntityTypeId() => $entity->id(), - 'source' => $default_langcode, - 'target' => $langcode - ], array('language' => $language)); - $this->drupalPostForm($add_url, $this->getEditValues($values, $langcode), $this->getFormSubmitActionForNewTranslation($entity, $langcode)); - - // Assert that HTML is escaped in "all languages" in UI after SafeMarkup - // change. - if ($this->testHTMLEscapeForAllLanguages) { - $this->assertNoRaw('<span class="translation-entity-all-languages">(all languages)</span>'); - $this->assertRaw('(all languages)'); - } - - // Ensure that the content language cache context is not yet added to the - // page. - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $this->drupalGet($entity->urlInfo()); - $this->assertCacheContexts(Cache::mergeContexts(['languages:language_content'], $this->defaultCacheContexts)); - - // Reset the cache of the entity, so that the new translation gets the - // updated values. - $metadata_source_translation = $this->manager->getTranslationMetadata($entity->getTranslation($default_langcode)); - $metadata_target_translation = $this->manager->getTranslationMetadata($entity->getTranslation($langcode)); - - $author_field_name = $entity->hasField('content_translation_uid') ? 'content_translation_uid' : 'uid'; - if ($entity->getFieldDefinition($author_field_name)->isTranslatable()) { - $this->assertEqual($metadata_target_translation->getAuthor()->id(), $this->translator->id(), - SafeMarkup::format('Author of the target translation @langcode correctly stored for translatable owner field.', array('@langcode' => $langcode))); - - $this->assertNotEqual($metadata_target_translation->getAuthor()->id(), $metadata_source_translation->getAuthor()->id(), - SafeMarkup::format('Author of the target translation @target different from the author of the source translation @source for translatable owner field.', - array('@target' => $langcode, '@source' => $default_langcode))); - } - else { - $this->assertEqual($metadata_target_translation->getAuthor()->id(), $this->editor->id(), 'Author of the entity remained untouched after translation for non translatable owner field.'); - } - - $created_field_name = $entity->hasField('content_translation_created') ? 'content_translation_created' : 'created'; - if ($entity->getFieldDefinition($created_field_name)->isTranslatable()) { - $this->assertTrue($metadata_target_translation->getCreatedTime() > $metadata_source_translation->getCreatedTime(), - SafeMarkup::format('Translation creation timestamp of the target translation @target is newer than the creation timestamp of the source translation @source for translatable created field.', - array('@target' => $langcode, '@source' => $default_langcode))); - } - else { - $this->assertEqual($metadata_target_translation->getCreatedTime(), $metadata_source_translation->getCreatedTime(), 'Creation timestamp of the entity remained untouched after translation for non translatable created field.'); - } - - if ($this->testLanguageSelector) { - $this->assertNoFieldByXPath('//select[@id="edit-langcode-0-value"]', NULL, 'Language selector correctly disabled on translations.'); - } - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $this->drupalGet($entity->urlInfo('drupal:content-translation-overview')); - $this->assertNoText('Source language', 'Source language column correctly hidden.'); - - // Switch the source language. - $langcode = 'fr'; - $language = ConfigurableLanguage::load($langcode); - $source_langcode = 'it'; - $edit = array('source_langcode[source]' => $source_langcode); - $entity_type_id = $entity->getEntityTypeId(); - $add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [ - $entity->getEntityTypeId() => $entity->id(), - 'source' => $default_langcode, - 'target' => $langcode - ], array('language' => $language)); - // This does not save anything, it merely reloads the form and fills in the - // fields with the values from the different source language. - $this->drupalPostForm($add_url, $edit, t('Change')); - $this->assertFieldByXPath("//input[@name=\"{$this->fieldName}[0][value]\"]", $values[$source_langcode][$this->fieldName][0]['value'], 'Source language correctly switched.'); - - // Add another translation and mark the other ones as outdated. - $values[$langcode] = $this->getNewEntityValues($langcode); - $edit = $this->getEditValues($values, $langcode) + array('content_translation[retranslate]' => TRUE); - $entity_type_id = $entity->getEntityTypeId(); - $add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [ - $entity->getEntityTypeId() => $entity->id(), - 'source' => $source_langcode, - 'target' => $langcode - ], array('language' => $language)); - $this->drupalPostForm($add_url, $edit, $this->getFormSubmitActionForNewTranslation($entity, $langcode)); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $this->drupalGet($entity->urlInfo('drupal:content-translation-overview')); - $this->assertText('Source language', 'Source language column correctly shown.'); - - // Check that the entered values have been correctly stored. - foreach ($values as $langcode => $property_values) { - $translation = $this->getTranslation($entity, $langcode); - foreach ($property_values as $property => $value) { - $stored_value = $this->getValue($translation, $property, $langcode); - $value = is_array($value) ? $value[0]['value'] : $value; - $message = format_string('%property correctly stored with language %language.', array('%property' => $property, '%language' => $langcode)); - $this->assertEqual($stored_value, $value, $message); - } - } - } - - /** - * Tests that the translation overview shows the correct values. - */ - protected function doTestTranslationOverview() { - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $translate_url = $entity->urlInfo('drupal:content-translation-overview'); - $this->drupalGet($translate_url); - $translate_url->setAbsolute(FALSE); - - foreach ($this->langcodes as $langcode) { - if ($entity->hasTranslation($langcode)) { - $language = new Language(array('id' => $langcode)); - $view_url = $entity->url('canonical', ['language' => $language]); - $elements = $this->xpath('//table//a[@href=:href]', [':href' => $view_url]); - $this->assertEqual((string) $elements[0], $entity->getTranslation($langcode)->label(), format_string('Label correctly shown for %language translation.', array('%language' => $langcode))); - $edit_path = $entity->url('edit-form', array('language' => $language)); - $elements = $this->xpath('//table//ul[@class="dropbutton"]/li/a[@href=:href]', array(':href' => $edit_path)); - $this->assertEqual((string) $elements[0], t('Edit'), format_string('Edit link correct for %language translation.', array('%language' => $langcode))); - } - } - } - - /** - * Tests up-to-date status tracking. - */ - protected function doTestOutdatedStatus() { - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $langcode = 'fr'; - $languages = \Drupal::languageManager()->getLanguages(); - - // Mark translations as outdated. - $edit = array('content_translation[retranslate]' => TRUE); - $edit_path = $entity->urlInfo('edit-form', array('language' => $languages[$langcode])); - $this->drupalPostForm($edit_path, $edit, $this->getFormSubmitAction($entity, $langcode)); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - - // Check that every translation has the correct "outdated" status, and that - // the Translation fieldset is open if the translation is "outdated". - foreach ($this->langcodes as $added_langcode) { - $url = $entity->urlInfo('edit-form', array('language' => ConfigurableLanguage::load($added_langcode))); - $this->drupalGet($url); - if ($added_langcode == $langcode) { - $this->assertFieldByXPath('//input[@name="content_translation[retranslate]"]', FALSE, 'The retranslate flag is not checked by default.'); - $this->assertFalse($this->xpath('//details[@id="edit-content-translation" and @open="open"]'), 'The translation tab should be collapsed by default.'); - } - else { - $this->assertFieldByXPath('//input[@name="content_translation[outdated]"]', TRUE, 'The translate flag is checked by default.'); - $this->assertTrue($this->xpath('//details[@id="edit-content-translation" and @open="open"]'), 'The translation tab is correctly expanded when the translation is outdated.'); - $edit = array('content_translation[outdated]' => FALSE); - $this->drupalPostForm($url, $edit, $this->getFormSubmitAction($entity, $added_langcode)); - $this->drupalGet($url); - $this->assertFieldByXPath('//input[@name="content_translation[retranslate]"]', FALSE, 'The retranslate flag is now shown.'); - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $this->assertFalse($this->manager->getTranslationMetadata($entity->getTranslation($added_langcode))->isOutdated(), 'The "outdated" status has been correctly stored.'); - } - } - } - - /** - * Tests the translation publishing status. - */ - protected function doTestPublishedStatus() { - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - - // Unpublish translations. - foreach ($this->langcodes as $index => $langcode) { - if ($index > 0) { - $url = $entity->urlInfo('edit-form', array('language' => ConfigurableLanguage::load($langcode))); - $edit = array('content_translation[status]' => FALSE); - $this->drupalPostForm($url, $edit, $this->getFormSubmitAction($entity, $langcode)); - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $this->assertFalse($this->manager->getTranslationMetadata($entity->getTranslation($langcode))->isPublished(), 'The translation has been correctly unpublished.'); - } - } - - // Check that the last published translation cannot be unpublished. - $this->drupalGet($entity->urlInfo('edit-form')); - $this->assertFieldByXPath('//input[@name="content_translation[status]" and @disabled="disabled"]', TRUE, 'The last translation is published and cannot be unpublished.'); - } - - /** - * Tests the translation authoring information. - */ - protected function doTestAuthoringInfo() { - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $values = array(); - - // Post different authoring information for each translation. - foreach ($this->langcodes as $index => $langcode) { - $user = $this->drupalCreateUser(); - $values[$langcode] = array( - 'uid' => $user->id(), - 'created' => REQUEST_TIME - mt_rand(0, 1000), - ); - $edit = array( - 'content_translation[uid]' => $user->getUsername(), - 'content_translation[created]' => format_date($values[$langcode]['created'], 'custom', 'Y-m-d H:i:s O'), - ); - $url = $entity->urlInfo('edit-form', array('language' => ConfigurableLanguage::load($langcode))); - $this->drupalPostForm($url, $edit, $this->getFormSubmitAction($entity, $langcode)); - } - - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - foreach ($this->langcodes as $langcode) { - $metadata = $this->manager->getTranslationMetadata($entity->getTranslation($langcode)); - $this->assertEqual($metadata->getAuthor()->id(), $values[$langcode]['uid'], 'Translation author correctly stored.'); - $this->assertEqual($metadata->getCreatedTime(), $values[$langcode]['created'], 'Translation date correctly stored.'); - } - - // Try to post non valid values and check that they are rejected. - $langcode = 'en'; - $edit = array( - // User names have by default length 8. - 'content_translation[uid]' => $this->randomMachineName(12), - 'content_translation[created]' => '19/11/1978', - ); - $this->drupalPostForm($entity->urlInfo('edit-form'), $edit, $this->getFormSubmitAction($entity, $langcode)); - $this->assertTrue($this->xpath('//div[contains(@class, "error")]//ul'), 'Invalid values generate a list of form errors.'); - $metadata = $this->manager->getTranslationMetadata($entity->getTranslation($langcode)); - $this->assertEqual($metadata->getAuthor()->id(), $values[$langcode]['uid'], 'Translation author correctly kept.'); - $this->assertEqual($metadata->getCreatedTime(), $values[$langcode]['created'], 'Translation date correctly kept.'); - } - - /** - * Tests translation deletion. - */ - protected function doTestTranslationDeletion() { - // Confirm and delete a translation. - $this->drupalLogin($this->translator); - $langcode = 'fr'; - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $language = ConfigurableLanguage::load($langcode); - $url = $entity->urlInfo('edit-form', array('language' => $language)); - $this->drupalPostForm($url, array(), t('Delete translation')); - $this->drupalPostForm(NULL, array(), t('Delete @language translation', array('@language' => $language->getName()))); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId, TRUE); - if ($this->assertTrue(is_object($entity), 'Entity found')) { - $translations = $entity->getTranslationLanguages(); - $this->assertTrue(count($translations) == 2 && empty($translations[$langcode]), 'Translation successfully deleted.'); - } - - // Check that the translator cannot delete the original translation. - $args = [$this->entityTypeId => $entity->id(), 'language' => 'en']; - $this->drupalGet(Url::fromRoute("entity.$this->entityTypeId.content_translation_delete", $args)); - $this->assertResponse(403); - } - - /** - * Returns an array of entity field values to be tested. - */ - protected function getNewEntityValues($langcode) { - return array($this->fieldName => array(array('value' => $this->randomMachineName(16)))); - } - - /** - * Returns an edit array containing the values to be posted. - */ - protected function getEditValues($values, $langcode, $new = FALSE) { - $edit = $values[$langcode]; - $langcode = $new ? LanguageInterface::LANGCODE_NOT_SPECIFIED : $langcode; - foreach ($values[$langcode] as $property => $value) { - if (is_array($value)) { - $edit["{$property}[0][value]"] = $value[0]['value']; - unset($edit[$property]); - } - } - return $edit; - } - - /** - * Returns the form action value when submitting a new translation. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity being tested. - * @param string $langcode - * Language code for the form. - * - * @return string - * Name of the button to hit. - */ - protected function getFormSubmitActionForNewTranslation(EntityInterface $entity, $langcode) { - $entity->addTranslation($langcode, $entity->toArray()); - return $this->getFormSubmitAction($entity, $langcode); - } - - /** - * Returns the form action value to be used to submit the entity form. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity being tested. - * @param string $langcode - * Language code for the form. - * - * @return string - * Name of the button to hit. - */ - protected function getFormSubmitAction(EntityInterface $entity, $langcode) { - return t('Save') . $this->getFormSubmitSuffix($entity, $langcode); - } - - /** - * Returns appropriate submit button suffix based on translatability. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity being tested. - * @param string $langcode - * Language code for the form. - * - * @return string - * Submit button suffix based on translatability. - */ - protected function getFormSubmitSuffix(EntityInterface $entity, $langcode) { - return ''; - } - - /** - * Returns the translation object to use to retrieve the translated values. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity being tested. - * @param string $langcode - * The language code identifying the translation to be retrieved. - * - * @return \Drupal\Core\TypedData\TranslatableInterface - * The translation object to act on. - */ - protected function getTranslation(EntityInterface $entity, $langcode) { - return $entity->getTranslation($langcode); - } - - /** - * Returns the value for the specified property in the given language. - * - * @param \Drupal\Core\Entity\EntityInterface $translation - * The translation object the property value should be retrieved from. - * @param string $property - * The property name. - * @param string $langcode - * The property value. - * - * @return - * The property value. - */ - protected function getValue(EntityInterface $translation, $property, $langcode) { - $key = $property == 'user_id' ? 'target_id' : 'value'; - return $translation->get($property)->{$key}; - } - - /** - * Returns the name of the field that implements the changed timestamp. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity being tested. - * - * @return string - * The field name. - */ - protected function getChangedFieldName($entity) { - return $entity->hasField('content_translation_changed') ? 'content_translation_changed' : 'changed'; - } - - /** - * Tests edit content translation. - */ - protected function doTestTranslationEdit() { - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $languages = $this->container->get('language_manager')->getLanguages(); - - foreach ($this->langcodes as $langcode) { - // We only want to test the title for non-english translations. - if ($langcode != 'en') { - $options = array('language' => $languages[$langcode]); - $url = $entity->urlInfo('edit-form', $options); - $this->drupalGet($url); - - $this->assertRaw($entity->getTranslation($langcode)->label()); - } - } - } - - /** - * Tests the basic translation workflow. - */ - protected function doTestTranslationChanged() { - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $changed_field_name = $this->getChangedFieldName($entity); - $definition = $entity->getFieldDefinition($changed_field_name); - $config = $definition->getConfig($entity->bundle()); - - foreach ([FALSE, TRUE] as $translatable_changed_field) { - if ($definition->isTranslatable()) { - // For entities defining a translatable changed field we want to test - // the correct behavior of that field even if the translatability is - // revoked. In that case the changed timestamp should be synchronized - // across all translations. - $config->setTranslatable($translatable_changed_field); - $config->save(); - } - elseif ($translatable_changed_field) { - // For entities defining a non-translatable changed field we cannot - // declare the field as translatable on the fly by modifying its config - // because the schema doesn't support this. - break; - } - - foreach ($entity->getTranslationLanguages() as $language) { - // Ensure different timestamps. - sleep(1); - - $langcode = $language->getId(); - - $edit = array( - $this->fieldName . '[0][value]' => $this->randomString(), - ); - $edit_path = $entity->urlInfo('edit-form', array('language' => $language)); - $this->drupalPostForm($edit_path, $edit, $this->getFormSubmitAction($entity, $langcode)); - - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $this->assertEqual( - $entity->getChangedTimeAcrossTranslations(), $entity->getTranslation($langcode)->getChangedTime(), - format_string('Changed time for language %language is the latest change over all languages.', array('%language' => $language->getName())) - ); - } - - $timestamps = array(); - foreach ($entity->getTranslationLanguages() as $language) { - $next_timestamp = $entity->getTranslation($language->getId())->getChangedTime(); - if (!in_array($next_timestamp, $timestamps)) { - $timestamps[] = $next_timestamp; - } - } - - if ($translatable_changed_field) { - $this->assertEqual( - count($timestamps), count($entity->getTranslationLanguages()), - 'All timestamps from all languages are different.' - ); - } - else { - $this->assertEqual( - count($timestamps), 1, - 'All timestamps from all languages are identical.' - ); - } - } - } - - /** - * Test the changed time after API and FORM save without changes. - */ - public function doTestChangedTimeAfterSaveWithoutChanges() { - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - // Test only entities, which implement the EntityChangedInterface. - if ($entity instanceof EntityChangedInterface) { - $changed_timestamp = $entity->getChangedTime(); - - $entity->save(); - $storage = $this->container->get('entity_type.manager') - ->getStorage($this->entityTypeId); - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $this->assertEqual($changed_timestamp, $entity->getChangedTime(), 'The entity\'s changed time wasn\'t updated after API save without changes.'); - - // Ensure different save timestamps. - sleep(1); - - // Save the entity on the regular edit form. - $language = $entity->language(); - $edit_path = $entity->urlInfo('edit-form', array('language' => $language)); - $this->drupalPostForm($edit_path, [], $this->getFormSubmitAction($entity, $language->getId())); - - $storage->resetCache([$this->entityId]); - $entity = $storage->load($this->entityId); - $this->assertNotEqual($changed_timestamp, $entity->getChangedTime(), 'The entity\'s changed time was updated after form save without changes.'); - } - } - -} diff --git a/core/modules/dblog/tests/src/Functional/ConnectionFailureTest.php b/core/modules/dblog/src/Tests/ConnectionFailureTest.php similarity index 91% rename from core/modules/dblog/tests/src/Functional/ConnectionFailureTest.php rename to core/modules/dblog/src/Tests/ConnectionFailureTest.php index df088a3..d800224 100644 --- a/core/modules/dblog/tests/src/Functional/ConnectionFailureTest.php +++ b/core/modules/dblog/src/Tests/ConnectionFailureTest.php @@ -1,16 +1,16 @@ container->get('entity_type.manager') - ->getStorage($entity->getEntityTypeId()); - $storage->resetCache([$entity->id()]); - $e = $storage->load($entity->id()); - - $field = $values = $e->getTranslation($langcode)->$field_name; - // Filter out empty values so that they don't mess with the assertions. - $field->filterEmptyItems(); - $values = $field->getValue(); - $this->assertEqual(count($values), count($expected_values), 'Expected number of values were saved.'); - foreach ($expected_values as $key => $value) { - $this->assertEqual($values[$key][$column], $value, format_string('Value @value was saved correctly.', array('@value' => $value))); - } - } - -} diff --git a/core/modules/field_ui/tests/src/Functional/EntityDisplayModeTest.php b/core/modules/field_ui/src/Tests/EntityDisplayModeTest.php similarity index 97% rename from core/modules/field_ui/tests/src/Functional/EntityDisplayModeTest.php rename to core/modules/field_ui/src/Tests/EntityDisplayModeTest.php index 1d2cab0..f808a1e 100644 --- a/core/modules/field_ui/tests/src/Functional/EntityDisplayModeTest.php +++ b/core/modules/field_ui/src/Tests/EntityDisplayModeTest.php @@ -1,15 +1,15 @@ adminUser = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer node fields', 'administer node display', 'administer nodes', 'bypass node access')); - $this->drupalLogin($this->adminUser); - $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); - } - - /** - * Retrieves a sample file of the specified type. - * - * @return \Drupal\file\FileInterface - */ - function getTestFile($type_name, $size = NULL) { - // Get a file to upload. - $file = current($this->drupalGetTestFiles($type_name, $size)); - - // Add a filesize property to files as would be read by - // \Drupal\file\Entity\File::load(). - $file->filesize = filesize($file->uri); - - return File::create((array) $file); - } - - /** - * Retrieves the fid of the last inserted file. - */ - function getLastFileId() { - return (int) db_query('SELECT MAX(fid) FROM {file_managed}')->fetchField(); - } - - /** - * Creates a new file field. - * - * @param string $name - * The name of the new field (all lowercase), exclude the "field_" prefix. - * @param string $entity_type - * The entity type. - * @param string $bundle - * The bundle that this field will be added to. - * @param array $storage_settings - * A list of field storage settings that will be added to the defaults. - * @param array $field_settings - * A list of instance settings that will be added to the instance defaults. - * @param array $widget_settings - * A list of widget settings that will be added to the widget defaults. - */ - function createFileField($name, $entity_type, $bundle, $storage_settings = array(), $field_settings = array(), $widget_settings = array()) { - $field_storage = FieldStorageConfig::create(array( - 'entity_type' => $entity_type, - 'field_name' => $name, - 'type' => 'file', - 'settings' => $storage_settings, - 'cardinality' => !empty($storage_settings['cardinality']) ? $storage_settings['cardinality'] : 1, - )); - $field_storage->save(); - - $this->attachFileField($name, $entity_type, $bundle, $field_settings, $widget_settings); - return $field_storage; - } - - /** - * Attaches a file field to an entity. - * - * @param string $name - * The name of the new field (all lowercase), exclude the "field_" prefix. - * @param string $entity_type - * The entity type this field will be added to. - * @param string $bundle - * The bundle this field will be added to. - * @param array $field_settings - * A list of field settings that will be added to the defaults. - * @param array $widget_settings - * A list of widget settings that will be added to the widget defaults. - */ - function attachFileField($name, $entity_type, $bundle, $field_settings = array(), $widget_settings = array()) { - $field = array( - 'field_name' => $name, - 'label' => $name, - 'entity_type' => $entity_type, - 'bundle' => $bundle, - 'required' => !empty($field_settings['required']), - 'settings' => $field_settings, - ); - FieldConfig::create($field)->save(); - - entity_get_form_display($entity_type, $bundle, 'default') - ->setComponent($name, array( - 'type' => 'file_generic', - 'settings' => $widget_settings, - )) - ->save(); - // Assign display settings. - entity_get_display($entity_type, $bundle, 'default') - ->setComponent($name, array( - 'label' => 'hidden', - 'type' => 'file_default', - )) - ->save(); - } - - /** - * Updates an existing file field with new settings. - */ - function updateFileField($name, $type_name, $field_settings = array(), $widget_settings = array()) { - $field = FieldConfig::loadByName('node', $type_name, $name); - $field->setSettings(array_merge($field->getSettings(), $field_settings)); - $field->save(); - - entity_get_form_display('node', $type_name, 'default') - ->setComponent($name, array( - 'settings' => $widget_settings, - )) - ->save(); - } - - /** - * Uploads a file to a node. - * - * @param \Drupal\file\FileInterface $file - * The File to be uploaded. - * @param string $field_name - * The name of the field on which the files should be saved. - * @param $nid_or_type - * A numeric node id to upload files to an existing node, or a string - * indicating the desired bundle for a new node. - * @param bool $new_revision - * The revision number. - * @param array $extras - * Additional values when a new node is created. - * - * @return int - * The node id. - */ - function uploadNodeFile(FileInterface $file, $field_name, $nid_or_type, $new_revision = TRUE, array $extras = array()) { - return $this->uploadNodeFiles([$file], $field_name, $nid_or_type, $new_revision, $extras); - } - - /** - * Uploads multiple files to a node. - * - * @param \Drupal\file\FileInterface[] $files - * The files to be uploaded. - * @param string $field_name - * The name of the field on which the files should be saved. - * @param $nid_or_type - * A numeric node id to upload files to an existing node, or a string - * indicating the desired bundle for a new node. - * @param bool $new_revision - * The revision number. - * @param array $extras - * Additional values when a new node is created. - * - * @return int - * The node id. - */ - function uploadNodeFiles(array $files, $field_name, $nid_or_type, $new_revision = TRUE, array $extras = array()) { - $edit = array( - 'title[0][value]' => $this->randomMachineName(), - 'revision' => (string) (int) $new_revision, - ); - - $node_storage = $this->container->get('entity.manager')->getStorage('node'); - if (is_numeric($nid_or_type)) { - $nid = $nid_or_type; - $node_storage->resetCache(array($nid)); - $node = $node_storage->load($nid); - } - else { - // Add a new node. - $extras['type'] = $nid_or_type; - $node = $this->drupalCreateNode($extras); - $nid = $node->id(); - // Save at least one revision to better simulate a real site. - $node->setNewRevision(); - $node->save(); - $node_storage->resetCache(array($nid)); - $node = $node_storage->load($nid); - $this->assertNotEqual($nid, $node->getRevisionId(), 'Node revision exists.'); - } - - // Attach files to the node. - $field_storage = FieldStorageConfig::loadByName('node', $field_name); - // File input name depends on number of files already uploaded. - $field_num = count($node->{$field_name}); - $name = 'files[' . $field_name . "_$field_num]"; - if ($field_storage->getCardinality() != 1) { - $name .= '[]'; - } - foreach ($files as $file) { - $file_path = $this->container->get('file_system')->realpath($file->getFileUri()); - if (count($files) == 1) { - $edit[$name] = $file_path; - } - else { - $edit[$name][] = $file_path; - } - } - $this->drupalPostForm("node/$nid/edit", $edit, t('Save and keep published')); - - return $nid; - } - - /** - * Removes a file from a node. - * - * Note that if replacing a file, it must first be removed then added again. - */ - function removeNodeFile($nid, $new_revision = TRUE) { - $edit = array( - 'revision' => (string) (int) $new_revision, - ); - - $this->drupalPostForm('node/' . $nid . '/edit', array(), t('Remove')); - $this->drupalPostForm(NULL, $edit, t('Save and keep published')); - } - - /** - * Replaces a file within a node. - */ - function replaceNodeFile($file, $field_name, $nid, $new_revision = TRUE) { - $edit = array( - 'files[' . $field_name . '_0]' => drupal_realpath($file->getFileUri()), - 'revision' => (string) (int) $new_revision, - ); - - $this->drupalPostForm('node/' . $nid . '/edit', array(), t('Remove')); - $this->drupalPostForm(NULL, $edit, t('Save and keep published')); - } - - /** - * Asserts that a file exists physically on disk. - */ - function assertFileExists($file, $message = NULL) { - $message = isset($message) ? $message : format_string('File %file exists on the disk.', array('%file' => $file->getFileUri())); - $this->assertTrue(is_file($file->getFileUri()), $message); - } - - /** - * Asserts that a file exists in the database. - */ - function assertFileEntryExists($file, $message = NULL) { - $this->container->get('entity.manager')->getStorage('file')->resetCache(); - $db_file = File::load($file->id()); - $message = isset($message) ? $message : format_string('File %file exists in database at the correct path.', array('%file' => $file->getFileUri())); - $this->assertEqual($db_file->getFileUri(), $file->getFileUri(), $message); - } - - /** - * Asserts that a file does not exist on disk. - */ - function assertFileNotExists($file, $message = NULL) { - $message = isset($message) ? $message : format_string('File %file exists on the disk.', array('%file' => $file->getFileUri())); - $this->assertFalse(is_file($file->getFileUri()), $message); - } - - /** - * Asserts that a file does not exist in the database. - */ - function assertFileEntryNotExists($file, $message) { - $this->container->get('entity.manager')->getStorage('file')->resetCache(); - $message = isset($message) ? $message : format_string('File %file exists in database at the correct path.', array('%file' => $file->getFileUri())); - $this->assertFalse(File::load($file->id()), $message); - } - - /** - * Asserts that a file's status is set to permanent in the database. - */ - function assertFileIsPermanent(FileInterface $file, $message = NULL) { - $message = isset($message) ? $message : format_string('File %file is permanent.', array('%file' => $file->getFileUri())); - $this->assertTrue($file->isPermanent(), $message); - } - -} diff --git a/core/modules/file/tests/src/Functional/FileManagedTestBase.php b/core/modules/file/tests/src/Functional/FileManagedTestBase.php deleted file mode 100644 index 6bd57dd..0000000 --- a/core/modules/file/tests/src/Functional/FileManagedTestBase.php +++ /dev/null @@ -1,200 +0,0 @@ -resetCache(); - - // Determine which hooks were called. - $actual = array_keys(array_filter(file_test_get_all_calls())); - - // Determine if there were any expected that were not called. - $uncalled = array_diff($expected, $actual); - if (count($uncalled)) { - $this->assertTrue(FALSE, format_string('Expected hooks %expected to be called but %uncalled was not called.', array('%expected' => implode(', ', $expected), '%uncalled' => implode(', ', $uncalled)))); - } - else { - $this->assertTrue(TRUE, format_string('All the expected hooks were called: %expected', array('%expected' => empty($expected) ? '(none)' : implode(', ', $expected)))); - } - - // Determine if there were any unexpected calls. - $unexpected = array_diff($actual, $expected); - if (count($unexpected)) { - $this->assertTrue(FALSE, format_string('Unexpected hooks were called: %unexpected.', array('%unexpected' => empty($unexpected) ? '(none)' : implode(', ', $unexpected)))); - } - else { - $this->assertTrue(TRUE, 'No unexpected hooks were called.'); - } - } - - /** - * Assert that a hook_file_* hook was called a certain number of times. - * - * @param string $hook - * String with the hook name; for instance, 'load', 'save', 'insert', etc. - * @param int $expected_count - * Optional integer count. - * @param string|null $message - * Optional translated string message. - */ - function assertFileHookCalled($hook, $expected_count = 1, $message = NULL) { - $actual_count = count(file_test_get_calls($hook)); - - if (!isset($message)) { - if ($actual_count == $expected_count) { - $message = format_string('hook_file_@name was called correctly.', array('@name' => $hook)); - } - elseif ($expected_count == 0) { - $message = \Drupal::translation()->formatPlural($actual_count, 'hook_file_@name was not expected to be called but was actually called once.', 'hook_file_@name was not expected to be called but was actually called @count times.', array('@name' => $hook, '@count' => $actual_count)); - } - else { - $message = format_string('hook_file_@name was expected to be called %expected times but was called %actual times.', array('@name' => $hook, '%expected' => $expected_count, '%actual' => $actual_count)); - } - } - $this->assertEqual($actual_count, $expected_count, $message); - } - - /** - * Asserts that two files have the same values (except timestamp). - * - * @param \Drupal\file\FileInterface $before - * File object to compare. - * @param \Drupal\file\FileInterface $after - * File object to compare. - */ - function assertFileUnchanged(FileInterface $before, FileInterface $after) { - $this->assertEqual($before->id(), $after->id(), t('File id is the same: %file1 == %file2.', array('%file1' => $before->id(), '%file2' => $after->id())), 'File unchanged'); - $this->assertEqual($before->getOwner()->id(), $after->getOwner()->id(), t('File owner is the same: %file1 == %file2.', array('%file1' => $before->getOwner()->id(), '%file2' => $after->getOwner()->id())), 'File unchanged'); - $this->assertEqual($before->getFilename(), $after->getFilename(), t('File name is the same: %file1 == %file2.', array('%file1' => $before->getFilename(), '%file2' => $after->getFilename())), 'File unchanged'); - $this->assertEqual($before->getFileUri(), $after->getFileUri(), t('File path is the same: %file1 == %file2.', array('%file1' => $before->getFileUri(), '%file2' => $after->getFileUri())), 'File unchanged'); - $this->assertEqual($before->getMimeType(), $after->getMimeType(), t('File MIME type is the same: %file1 == %file2.', array('%file1' => $before->getMimeType(), '%file2' => $after->getMimeType())), 'File unchanged'); - $this->assertEqual($before->getSize(), $after->getSize(), t('File size is the same: %file1 == %file2.', array('%file1' => $before->getSize(), '%file2' => $after->getSize())), 'File unchanged'); - $this->assertEqual($before->isPermanent(), $after->isPermanent(), t('File status is the same: %file1 == %file2.', array('%file1' => $before->isPermanent(), '%file2' => $after->isPermanent())), 'File unchanged'); - } - - /** - * Asserts that two files are not the same by comparing the fid and filepath. - * - * @param \Drupal\file\FileInterface $file1 - * File object to compare. - * @param \Drupal\file\FileInterface $file2 - * File object to compare. - */ - function assertDifferentFile(FileInterface $file1, FileInterface $file2) { - $this->assertNotEqual($file1->id(), $file2->id(), t('Files have different ids: %file1 != %file2.', array('%file1' => $file1->id(), '%file2' => $file2->id())), 'Different file'); - $this->assertNotEqual($file1->getFileUri(), $file2->getFileUri(), t('Files have different paths: %file1 != %file2.', array('%file1' => $file1->getFileUri(), '%file2' => $file2->getFileUri())), 'Different file'); - } - - /** - * Asserts that two files are the same by comparing the fid and filepath. - * - * @param \Drupal\file\FileInterface $file1 - * File object to compare. - * @param \Drupal\file\FileInterface $file2 - * File object to compare. - */ - function assertSameFile(FileInterface $file1, FileInterface $file2) { - $this->assertEqual($file1->id(), $file2->id(), t('Files have the same ids: %file1 == %file2.', array('%file1' => $file1->id(), '%file2-fid' => $file2->id())), 'Same file'); - $this->assertEqual($file1->getFileUri(), $file2->getFileUri(), t('Files have the same path: %file1 == %file2.', array('%file1' => $file1->getFileUri(), '%file2' => $file2->getFileUri())), 'Same file'); - } - - /** - * Create a file and save it to the files table and assert that it occurs - * correctly. - * - * @param string $filepath - * Optional string specifying the file path. If none is provided then a - * randomly named file will be created in the site's files directory. - * @param string $contents - * Optional contents to save into the file. If a NULL value is provided an - * arbitrary string will be used. - * @param string $scheme - * Optional string indicating the stream scheme to use. Drupal core includes - * public, private, and temporary. The public wrapper is the default. - * @return \Drupal\file\FileInterface - * File entity. - */ - function createFile($filepath = NULL, $contents = NULL, $scheme = NULL) { - // Don't count hook invocations caused by creating the file. - \Drupal::state()->set('file_test.count_hook_invocations', FALSE); - $file = File::create([ - 'uri' => $this->createUri($filepath, $contents, $scheme), - 'uid' => 1, - ]); - $file->save(); - // Write the record directly rather than using the API so we don't invoke - // the hooks. - $this->assertTrue($file->id() > 0, 'The file was added to the database.', 'Create test file'); - - \Drupal::state()->set('file_test.count_hook_invocations', TRUE); - return $file; - } - - /** - * Creates a file and returns its URI. - * - * @param string $filepath - * Optional string specifying the file path. If none is provided then a - * randomly named file will be created in the site's files directory. - * @param string $contents - * Optional contents to save into the file. If a NULL value is provided an - * arbitrary string will be used. - * @param string $scheme - * Optional string indicating the stream scheme to use. Drupal core includes - * public, private, and temporary. The public wrapper is the default. - * - * @return string - * File URI. - */ - function createUri($filepath = NULL, $contents = NULL, $scheme = NULL) { - if (!isset($filepath)) { - // Prefix with non-latin characters to ensure that all file-related - // tests work with international filenames. - $filepath = 'Файл для тестирования ' . $this->randomMachineName(); - } - if (!isset($scheme)) { - $scheme = file_default_scheme(); - } - $filepath = $scheme . '://' . $filepath; - - if (!isset($contents)) { - $contents = "file_put_contents() doesn't seem to appreciate empty strings so let's put in some data."; - } - - file_put_contents($filepath, $contents); - $this->assertTrue(is_file($filepath), t('The test file exists on the disk.'), 'Create test file'); - return $filepath; - } - -} diff --git a/core/modules/filter/tests/src/Functional/FilterCaptionTwigDebugTest.php b/core/modules/filter/src/Tests/FilterCaptionTwigDebugTest.php similarity index 95% rename from core/modules/filter/tests/src/Functional/FilterCaptionTwigDebugTest.php rename to core/modules/filter/src/Tests/FilterCaptionTwigDebugTest.php index ef520c7..cd5e8e2 100644 --- a/core/modules/filter/tests/src/Functional/FilterCaptionTwigDebugTest.php +++ b/core/modules/filter/src/Tests/FilterCaptionTwigDebugTest.php @@ -1,9 +1,9 @@ profile != 'standard') { - $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page')); - $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); - } - - $this->adminUser = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer node fields', 'administer nodes', 'create article content', 'edit any article content', 'delete any article content', 'administer image styles', 'administer node display')); - $this->drupalLogin($this->adminUser); - } - - /** - * Preview an image in a node. - * - * @param \Drupal\Core\Image\ImageInterface $image - * A file object representing the image to upload. - * @param string $field_name - * Name of the image field the image should be attached to. - * @param string $type - * The type of node to create. - */ - function previewNodeImage($image, $field_name, $type) { - $edit = array( - 'title[0][value]' => $this->randomMachineName(), - ); - $edit['files[' . $field_name . '_0]'] = drupal_realpath($image->uri); - $this->drupalPostForm('node/add/' . $type, $edit, t('Preview')); - } - - /** - * Upload an image to a node. - * - * @param $image - * A file object representing the image to upload. - * @param $field_name - * Name of the image field the image should be attached to. - * @param $type - * The type of node to create. - * @param $alt - * The alt text for the image. Use if the field settings require alt text. - */ - function uploadNodeImage($image, $field_name, $type, $alt = '') { - $edit = array( - 'title[0][value]' => $this->randomMachineName(), - ); - $edit['files[' . $field_name . '_0]'] = drupal_realpath($image->uri); - $this->drupalPostForm('node/add/' . $type, $edit, t('Save and publish')); - if ($alt) { - // Add alt text. - $this->drupalPostForm(NULL, [$field_name . '[0][alt]' => $alt], t('Save and publish')); - } - - // Retrieve ID of the newly created node from the current URL. - $matches = array(); - preg_match('/node\/([0-9]+)/', $this->getUrl(), $matches); - return isset($matches[1]) ? $matches[1] : FALSE; - } - - /** - * Retrieves the fid of the last inserted file. - */ - protected function getLastFileId() { - return (int) db_query('SELECT MAX(fid) FROM {file_managed}')->fetchField(); - } - -} diff --git a/core/modules/language/tests/src/Functional/AdminPathEntityConverterLanguageTest.php b/core/modules/language/src/Tests/AdminPathEntityConverterLanguageTest.php similarity index 89% rename from core/modules/language/tests/src/Functional/AdminPathEntityConverterLanguageTest.php rename to core/modules/language/src/Tests/AdminPathEntityConverterLanguageTest.php index bd46a40..3cc00f9 100644 --- a/core/modules/language/tests/src/Functional/AdminPathEntityConverterLanguageTest.php +++ b/core/modules/language/src/Tests/AdminPathEntityConverterLanguageTest.php @@ -1,16 +1,16 @@ profile != 'standard') { - $this->drupalCreateContentType(array( - 'type' => 'page', - 'name' => 'Basic page', - 'display_submitted' => FALSE, - )); - $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); - } - $this->accessHandler = \Drupal::entityManager()->getAccessControlHandler('node'); - } - - /** - * Asserts that node access correctly grants or denies access. - * - * @param array $ops - * An associative array of the expected node access grants for the node - * and account, with each key as the name of an operation (e.g. 'view', - * 'delete') and each value a Boolean indicating whether access to that - * operation should be granted. - * @param \Drupal\node\NodeInterface $node - * The node object to check. - * @param \Drupal\Core\Session\AccountInterface $account - * The user account for which to check access. - */ - function assertNodeAccess(array $ops, NodeInterface $node, AccountInterface $account) { - foreach ($ops as $op => $result) { - $this->assertEqual($result, $this->accessHandler->access($node, $op, $account), $this->nodeAccessAssertMessage($op, $result, $node->language()->getId())); - } - } - - /** - * Asserts that node create access correctly grants or denies access. - * - * @param string $bundle - * The node bundle to check access to. - * @param bool $result - * Whether access should be granted or not. - * @param \Drupal\Core\Session\AccountInterface $account - * The user account for which to check access. - * @param string|null $langcode - * (optional) The language code indicating which translation of the node - * to check. If NULL, the untranslated (fallback) access is checked. - */ - function assertNodeCreateAccess($bundle, $result, AccountInterface $account, $langcode = NULL) { - $this->assertEqual($result, $this->accessHandler->createAccess($bundle, $account, array( - 'langcode' => $langcode, - )), $this->nodeAccessAssertMessage('create', $result, $langcode)); - } - - /** - * Constructs an assert message to display which node access was tested. - * - * @param string $operation - * The operation to check access for. - * @param bool $result - * Whether access should be granted or not. - * @param string|null $langcode - * (optional) The language code indicating which translation of the node - * to check. If NULL, the untranslated (fallback) access is checked. - * - * @return string - * An assert message string which contains information in plain English - * about the node access permission test that was performed. - */ - function nodeAccessAssertMessage($operation, $result, $langcode = NULL) { - return format_string( - 'Node access returns @result with operation %op, language code %langcode.', - array( - '@result' => $result ? 'true' : 'false', - '%op' => $operation, - '%langcode' => !empty($langcode) ? $langcode : 'empty' - ) - ); - } - -} diff --git a/core/modules/path/tests/src/Functional/PathAliasTest.php b/core/modules/path/src/Tests/PathAliasTest.php similarity index 99% rename from core/modules/path/tests/src/Functional/PathAliasTest.php rename to core/modules/path/src/Tests/PathAliasTest.php index 5127853..28c582d 100644 --- a/core/modules/path/tests/src/Functional/PathAliasTest.php +++ b/core/modules/path/src/Tests/PathAliasTest.php @@ -1,6 +1,6 @@ profile != 'standard') { - $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page')); - $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); - } - } - -} diff --git a/core/modules/rdf/tests/src/Functional/EntityReferenceFieldAttributesTest.php b/core/modules/rdf/src/Tests/EntityReferenceFieldAttributesTest.php similarity index 99% rename from core/modules/rdf/tests/src/Functional/EntityReferenceFieldAttributesTest.php rename to core/modules/rdf/src/Tests/EntityReferenceFieldAttributesTest.php index 4aaeb7e..48653a5 100644 --- a/core/modules/rdf/tests/src/Functional/EntityReferenceFieldAttributesTest.php +++ b/core/modules/rdf/src/Tests/EntityReferenceFieldAttributesTest.php @@ -1,6 +1,6 @@ profile != 'standard') { - $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page')); - $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); - } - } - - /** - * Simulates submission of a form using GET instead of POST. - * - * Forms that use the GET method cannot be submitted with - * WebTestBase::drupalPostForm(), which explicitly uses POST to submit the - * form. So this method finds the form, verifies that it has input fields and - * a submit button matching the inputs to this method, and then calls - * WebTestBase::drupalGet() to simulate the form submission to the 'action' - * URL of the form (if set, or the current URL if not). - * - * See WebTestBase::drupalPostForm() for more detailed documentation of the - * function parameters. - * - * @param string $path - * Location of the form to be submitted: either a Drupal path, absolute - * path, or NULL to use the current page. - * @param array $edit - * Form field data to submit. Unlike drupalPostForm(), this does not support - * file uploads. - * @param string $submit - * Value of the submit button to submit clicking. Unlike drupalPostForm(), - * this does not support AJAX. - * @param string $form_html_id - * (optional) HTML ID of the form, to disambiguate. - */ - protected function submitGetForm($path, $edit, $submit, $form_html_id = NULL) { - if (isset($path)) { - $this->drupalGet($path); - } - - if ($this->parse()) { - // Iterate over forms to find one that matches $edit and $submit. - $edit_save = $edit; - $xpath = '//form'; - if (!empty($form_html_id)) { - $xpath .= "[@id='" . $form_html_id . "']"; - } - $forms = $this->xpath($xpath); - foreach ($forms as $form) { - // Try to set the fields of this form as specified in $edit. - $edit = $edit_save; - $post = array(); - $upload = array(); - $submit_matches = $this->handleForm($post, $edit, $upload, $submit, $form); - if (!$edit && $submit_matches) { - // Everything matched, so "submit" the form. - $action = isset($form['action']) ? $this->getAbsoluteUrl((string) $form['action']) : NULL; - $this->drupalGet($action, array('query' => $post)); - return; - } - } - - // We have not found a form which contained all fields of $edit and - // the submit button. - foreach ($edit as $name => $value) { - $this->fail(SafeMarkup::format('Failed to set field @name to @value', array('@name' => $name, '@value' => $value))); - } - $this->assertTrue($submit_matches, format_string('Found the @submit button', array('@submit' => $submit))); - $this->fail(format_string('Found the requested form fields at @path', array('@path' => $path))); - } - } - -} diff --git a/core/modules/shortcut/tests/src/Functional/ShortcutCacheTagsTest.php b/core/modules/shortcut/src/Tests/ShortcutCacheTagsTest.php similarity index 97% rename from core/modules/shortcut/tests/src/Functional/ShortcutCacheTagsTest.php rename to core/modules/shortcut/src/Tests/ShortcutCacheTagsTest.php index 23f0145..a437ffb 100644 --- a/core/modules/shortcut/tests/src/Functional/ShortcutCacheTagsTest.php +++ b/core/modules/shortcut/src/Tests/ShortcutCacheTagsTest.php @@ -1,6 +1,6 @@ error('The %path is not eligible for removing in %func().', ['%path' => $directory, '%func' => __FUNCTION__]); + } + + foreach ($directories as $file) { if ($file[0] != '.') { - $path = DRUPAL_ROOT . '/sites/simpletest/' . $file; - file_unmanaged_delete_recursive($path, array('Drupal\simpletest\TestBase', 'filePreDeleteCallback')); + $path = $simpletest_root . $file; + // When the webserver runs with the same system user as the test + // runner, we can make read-only files writable again. If not, chmod + // will fail while the file deletion still works if file permissions + // have been configured correctly. Thus, we ignore any chmod errors. + $result = file_unmanaged_delete_recursive($path, function ($any_path) { + @chmod($any_path, 0700); + }); $count++; } } @@ -704,6 +742,8 @@ function simpletest_clean_temporary_directories() { else { drupal_set_message(t('No temporary directories to remove.')); } + + return $result; } /** diff --git a/core/modules/simpletest/src/TestBase.php b/core/modules/simpletest/src/TestBase.php index 14d7909..b6e2c3e 100644 --- a/core/modules/simpletest/src/TestBase.php +++ b/core/modules/simpletest/src/TestBase.php @@ -1231,8 +1231,8 @@ private function restoreEnvironment() { $this->container = $this->originalContainer; \Drupal::setContainer($this->originalContainer); - // Delete test site directory. - file_unmanaged_delete_recursive($this->siteDirectory, array($this, 'filePreDeleteCallback')); + // Delete the current test site directory. + simpletest_clean_temporary_directories($this->siteDirectory); // Restore original database connection. Database::removeConnection('default'); @@ -1393,21 +1393,6 @@ public static function generatePermutations($parameters) { } /** - * Ensures test files are deletable within file_unmanaged_delete_recursive(). - * - * Some tests chmod generated files to be read only. During - * TestBase::restoreEnvironment() and other cleanup operations, these files - * need to get deleted too. - */ - public static function filePreDeleteCallback($path) { - // When the webserver runs with the same system user as the test runner, we - // can make read-only files writable again. If not, chmod will fail while - // the file deletion still works if file permissions have been configured - // correctly. Thus, we ignore any problems while running chmod. - @chmod($path, 0700); - } - - /** * Configuration accessor for tests. Returns non-overridden configuration. * * @param $name diff --git a/core/modules/simpletest/tests/src/Functional/FolderTest.php b/core/modules/simpletest/src/Tests/FolderTest.php similarity index 77% rename from core/modules/simpletest/tests/src/Functional/FolderTest.php rename to core/modules/simpletest/src/Tests/FolderTest.php index 4055976..d43c638 100644 --- a/core/modules/simpletest/tests/src/Functional/FolderTest.php +++ b/core/modules/simpletest/src/Tests/FolderTest.php @@ -1,8 +1,8 @@ profile != 'standard') { - $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page')); - } - - // Create user. - $this->blockingUser = $this->drupalCreateUser(array( - 'access administration pages', - 'access site reports', - 'ban IP addresses', - 'administer blocks', - 'administer statistics', - 'administer users', - )); - $this->drupalLogin($this->blockingUser); - - // Enable logging. - $this->config('statistics.settings') - ->set('count_content_views', 1) - ->save(); - } - -} diff --git a/core/modules/system/tests/src/Functional/Bootstrap/DrupalSetMessageTest.php b/core/modules/system/src/Tests/Bootstrap/DrupalSetMessageTest.php similarity index 90% rename from core/modules/system/tests/src/Functional/Bootstrap/DrupalSetMessageTest.php rename to core/modules/system/src/Tests/Bootstrap/DrupalSetMessageTest.php index 1b0f31a..29ca02f 100644 --- a/core/modules/system/tests/src/Functional/Bootstrap/DrupalSetMessageTest.php +++ b/core/modules/system/src/Tests/Bootstrap/DrupalSetMessageTest.php @@ -1,15 +1,15 @@ defaultBin; - } - - $cached = \Drupal::cache($bin)->get($cid); - - return isset($cached->data) && $cached->data == $var; - } - - /** - * Asserts that a cache entry exists. - * - * @param $message - * Message to display. - * @param $var - * The variable the cache should contain. - * @param $cid - * The cache id. - * @param $bin - * The bin the cache item was stored in. - */ - protected function assertCacheExists($message, $var = NULL, $cid = NULL, $bin = NULL) { - if ($bin == NULL) { - $bin = $this->defaultBin; - } - if ($cid == NULL) { - $cid = $this->defaultCid; - } - if ($var == NULL) { - $var = $this->defaultValue; - } - - $this->assertTrue($this->checkCacheExists($cid, $var, $bin), $message); - } - - /** - * Asserts that a cache entry has been removed. - * - * @param $message - * Message to display. - * @param $cid - * The cache id. - * @param $bin - * The bin the cache item was stored in. - */ - function assertCacheRemoved($message, $cid = NULL, $bin = NULL) { - if ($bin == NULL) { - $bin = $this->defaultBin; - } - if ($cid == NULL) { - $cid = $this->defaultCid; - } - - $cached = \Drupal::cache($bin)->get($cid); - $this->assertFalse($cached, $message); - } - -} diff --git a/core/modules/system/tests/src/Functional/Cache/PageCacheTagsTestBase.php b/core/modules/system/tests/src/Functional/Cache/PageCacheTagsTestBase.php deleted file mode 100644 index de2b419..0000000 --- a/core/modules/system/tests/src/Functional/Cache/PageCacheTagsTestBase.php +++ /dev/null @@ -1,62 +0,0 @@ -config('system.performance'); - $config->set('cache.page.max_age', 3600); - $config->save(); - } - - /** - * Verify that when loading a given page, it's a page cache hit or miss. - * - * @param \Drupal\Core\Url $url - * The page for this URL will be loaded. - * @param string $hit_or_miss - * 'HIT' if a page cache hit is expected, 'MISS' otherwise. - * - * @param array|false $tags - * When expecting a page cache hit, you may optionally specify an array of - * expected cache tags. While FALSE, the cache tags will not be verified. - */ - protected function verifyPageCache(Url $url, $hit_or_miss, $tags = FALSE) { - $this->drupalGet($url); - $message = SafeMarkup::format('Page cache @hit_or_miss for %path.', array('@hit_or_miss' => $hit_or_miss, '%path' => $url->toString())); - $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), $hit_or_miss, $message); - - if ($hit_or_miss === 'HIT' && is_array($tags)) { - $absolute_url = $url->setAbsolute()->toString(); - $cid_parts = array($absolute_url, 'html'); - $cid = implode(':', $cid_parts); - $cache_entry = \Drupal::cache('render')->get($cid); - sort($cache_entry->tags); - $tags = array_unique($tags); - sort($tags); - $this->assertIdentical($cache_entry->tags, $tags); - } - } - -} diff --git a/core/modules/system/tests/src/Functional/Entity/EntityCacheTagsTestBase.php b/core/modules/system/tests/src/Functional/Entity/EntityCacheTagsTestBase.php deleted file mode 100644 index 541a412..0000000 --- a/core/modules/system/tests/src/Functional/Entity/EntityCacheTagsTestBase.php +++ /dev/null @@ -1,720 +0,0 @@ -grantPermission('view test entity'); - $user_role->save(); - - // Create an entity. - $this->entity = $this->createEntity(); - - // If this is an entity with field UI enabled, then add a configurable - // field. We will use this configurable field in later tests to ensure that - // field configuration invalidate render cache entries. - if ($this->entity->getEntityType()->get('field_ui_base_route')) { - // Add field, so we can modify the field storage and field entities to - // verify that changes to those indeed clear cache tags. - FieldStorageConfig::create(array( - 'field_name' => 'configurable_field', - 'entity_type' => $this->entity->getEntityTypeId(), - 'type' => 'test_field', - 'settings' => array(), - ))->save(); - FieldConfig::create([ - 'entity_type' => $this->entity->getEntityTypeId(), - 'bundle' => $this->entity->bundle(), - 'field_name' => 'configurable_field', - 'label' => 'Configurable field', - 'settings' => array(), - ])->save(); - - // Reload the entity now that a new field has been added to it. - $storage = $this->container - ->get('entity.manager') - ->getStorage($this->entity->getEntityTypeId()); - $storage->resetCache(); - $this->entity = $storage->load($this->entity->id()); - } - - // Create a referencing and a non-referencing entity. - list( - $this->referencingEntity, - $this->nonReferencingEntity, - ) = $this->createReferenceTestEntities($this->entity); - } - - /** - * Generates standardized entity cache tags test info. - * - * @param string $entity_type_label - * The label of the entity type whose cache tags to test. - * @param string $group - * The test group. - * - * @return array - * - * @see \Drupal\simpletest\TestBase::getInfo() - */ - protected static function generateStandardizedInfo($entity_type_label, $group) { - return array( - 'name' => "$entity_type_label entity cache tags", - 'description' => "Test the $entity_type_label entity's cache tags.", - 'group' => $group, - ); - } - - /** - * Creates the entity to be tested. - * - * @return \Drupal\Core\Entity\EntityInterface - * The entity to be tested. - */ - abstract protected function createEntity(); - - /** - * Returns the access cache contexts for the tested entity. - * - * Only list cache contexts that aren't part of the required cache contexts. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity to be tested, as created by createEntity(). - * - * @return string[] - * An array of the additional cache contexts. - * - * @see \Drupal\Core\Entity\EntityAccessControlHandlerInterface - */ - protected function getAccessCacheContextsForEntity(EntityInterface $entity) { - return []; - } - - /** - * Returns the additional (non-standard) cache contexts for the tested entity. - * - * Only list cache contexts that aren't part of the required cache contexts. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity to be tested, as created by createEntity(). - * - * @return string[] - * An array of the additional cache contexts. - * - * @see \Drupal\system\Tests\Entity\EntityCacheTagsTestBase::createEntity() - */ - protected function getAdditionalCacheContextsForEntity(EntityInterface $entity) { - return []; - } - - /** - * Returns the additional (non-standard) cache tags for the tested entity. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity to be tested, as created by createEntity(). - * @return array - * An array of the additional cache tags. - * - * @see \Drupal\system\Tests\Entity\EntityCacheTagsTestBase::createEntity() - */ - protected function getAdditionalCacheTagsForEntity(EntityInterface $entity) { - return array(); - } - - /** - * Returns the additional cache tags for the tested entity's listing by type. - * - * @return string[] - * An array of the additional cache contexts. - */ - protected function getAdditionalCacheContextsForEntityListing() { - return []; - } - - /** - * Returns the additional cache tags for the tested entity's listing by type. - * - * Necessary when there are unavoidable default entities of this type, e.g. - * the anonymous and administrator User entities always exist. - * - * @return array - * An array of the additional cache tags. - */ - protected function getAdditionalCacheTagsForEntityListing() { - return []; - } - - /** - * Selects the preferred view mode for the given entity type. - * - * Prefers 'full', picks the first one otherwise, and if none are available, - * chooses 'default'. - */ - protected function selectViewMode($entity_type) { - $view_modes = \Drupal::entityManager() - ->getStorage('entity_view_mode') - ->loadByProperties(array('targetEntityType' => $entity_type)); - - if (empty($view_modes)) { - return 'default'; - } - else { - // Prefer the "full" display mode. - if (isset($view_modes[$entity_type . '.full'])) { - return 'full'; - } - else { - $view_modes = array_keys($view_modes); - return substr($view_modes[0], strlen($entity_type) + 1); - } - } - } - - /** - * Creates a referencing and a non-referencing entity for testing purposes. - * - * @param \Drupal\Core\Entity\EntityInterface $referenced_entity - * The entity that the referencing entity should reference. - * - * @return \Drupal\Core\Entity\EntityInterface[] - * An array containing a referencing entity and a non-referencing entity. - */ - protected function createReferenceTestEntities($referenced_entity) { - // All referencing entities should be of the type 'entity_test'. - $entity_type = 'entity_test'; - - // Create a "foo" bundle for the given entity type. - $bundle = 'foo'; - entity_test_create_bundle($bundle, NULL, $entity_type); - - // Add a field of the given type to the given entity type's "foo" bundle. - $field_name = $referenced_entity->getEntityTypeId() . '_reference'; - FieldStorageConfig::create(array( - 'field_name' => $field_name, - 'entity_type' => $entity_type, - 'type' => 'entity_reference', - 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, - 'settings' => array( - 'target_type' => $referenced_entity->getEntityTypeId(), - ), - ))->save(); - FieldConfig::create([ - 'field_name' => $field_name, - 'entity_type' => $entity_type, - 'bundle' => $bundle, - 'settings' => array( - 'handler' => 'default', - 'handler_settings' => array( - 'target_bundles' => array( - $referenced_entity->bundle() => $referenced_entity->bundle(), - ), - 'sort' => array('field' => '_none'), - 'auto_create' => FALSE, - ), - ), - ])->save(); - if (!$this->entity->getEntityType()->hasHandlerClass('view_builder')) { - entity_get_display($entity_type, $bundle, 'full') - ->setComponent($field_name, array( - 'type' => 'entity_reference_label', - )) - ->save(); - } - else { - $referenced_entity_view_mode = $this->selectViewMode($this->entity->getEntityTypeId()); - entity_get_display($entity_type, $bundle, 'full') - ->setComponent($field_name, array( - 'type' => 'entity_reference_entity_view', - 'settings' => array( - 'view_mode' => $referenced_entity_view_mode, - ), - )) - ->save(); - } - - // Create an entity that does reference the entity being tested. - $label_key = \Drupal::entityManager()->getDefinition($entity_type)->getKey('label'); - $referencing_entity = $this->container->get('entity_type.manager') - ->getStorage($entity_type) - ->create(array( - $label_key => 'Referencing ' . $entity_type, - 'status' => 1, - 'type' => $bundle, - $field_name => array('target_id' => $referenced_entity->id()), - )); - $referencing_entity->save(); - - // Create an entity that does not reference the entity being tested. - $non_referencing_entity = $this->container->get('entity_type.manager') - ->getStorage($entity_type) - ->create(array( - $label_key => 'Non-referencing ' . $entity_type, - 'status' => 1, - 'type' => $bundle, - )); - $non_referencing_entity->save(); - - return array( - $referencing_entity, - $non_referencing_entity, - ); - } - - /** - * Tests cache tags presence and invalidation of the entity when referenced. - * - * Tests the following cache tags: - * - entity type view cache tag: "_view" - * - entity cache tag: ":" - * - entity type list cache tag: "_list" - * - referencing entity type view cache tag: "_view" - * - referencing entity type cache tag: ":" - */ - public function testReferencedEntity() { - $entity_type = $this->entity->getEntityTypeId(); - $referencing_entity_url = $this->referencingEntity->urlInfo('canonical'); - $non_referencing_entity_url = $this->nonReferencingEntity->urlInfo('canonical'); - $listing_url = Url::fromRoute('entity.entity_test.collection_referencing_entities', [ - 'entity_reference_field_name' => $entity_type . '_reference', - 'referenced_entity_type' => $entity_type, - 'referenced_entity_id' => $this->entity->id(), - ]); - $empty_entity_listing_url = Url::fromRoute('entity.entity_test.collection_empty', ['entity_type_id' => $entity_type]); - $nonempty_entity_listing_url = Url::fromRoute('entity.entity_test.collection_labels_alphabetically', ['entity_type_id' => $entity_type]); - - // The default cache contexts for rendered entities. - $default_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions']; - $entity_cache_contexts = $default_cache_contexts; - $page_cache_contexts = Cache::mergeContexts($default_cache_contexts, ['url.query_args:' . MainContentViewSubscriber::WRAPPER_FORMAT]); - - // Cache tags present on every rendered page. - // 'user.permissions' is a required cache context, and responses that vary - // by this cache context when requested by anonymous users automatically - // also get this cache tag, to ensure correct invalidation. - $page_cache_tags = Cache::mergeTags(['http_response', 'rendered'], ['config:user.role.anonymous']); - // If the block module is used, the Block page display variant is used, - // which adds the block config entity type's list cache tags. - $page_cache_tags = Cache::mergeTags($page_cache_tags, \Drupal::moduleHandler()->moduleExists('block') ? ['config:block_list'] : []); - - $page_cache_tags_referencing_entity = in_array('user.permissions', $this->getAccessCacheContextsForEntity($this->referencingEntity)) ? ['config:user.role.anonymous'] : []; - - $view_cache_tag = array(); - if ($this->entity->getEntityType()->hasHandlerClass('view_builder')) { - $view_cache_tag = \Drupal::entityManager()->getViewBuilder($entity_type) - ->getCacheTags(); - } - - $context_metadata = \Drupal::service('cache_contexts_manager')->convertTokensToKeys($entity_cache_contexts); - $cache_context_tags = $context_metadata->getCacheTags(); - - // Generate the cache tags for the (non) referencing entities. - $referencing_entity_cache_tags = Cache::mergeTags($this->referencingEntity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags()); - // Includes the main entity's cache tags, since this entity references it. - $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $this->entity->getCacheTags()); - $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $this->getAdditionalCacheTagsForEntity($this->entity)); - $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $view_cache_tag); - $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $cache_context_tags); - $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, ['rendered']); - - $non_referencing_entity_cache_tags = Cache::mergeTags($this->nonReferencingEntity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags()); - $non_referencing_entity_cache_tags = Cache::mergeTags($non_referencing_entity_cache_tags, ['rendered']); - - // Generate the cache tags for all two possible entity listing paths. - // 1. list cache tag only (listing query has no match) - // 2. list cache tag plus entity cache tag (listing query has a match) - $empty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $page_cache_tags); - - $nonempty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->entity->getCacheTags()); - $nonempty_entity_listing_cache_tags = Cache::mergeTags($nonempty_entity_listing_cache_tags, $this->getAdditionalCacheTagsForEntityListing($this->entity)); - $nonempty_entity_listing_cache_tags = Cache::mergeTags($nonempty_entity_listing_cache_tags, $page_cache_tags); - - $this->pass("Test referencing entity.", 'Debug'); - $this->verifyPageCache($referencing_entity_url, 'MISS'); - - // Verify a cache hit, but also the presence of the correct cache tags. - $expected_tags = Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags); - $expected_tags = Cache::mergeTags($expected_tags, $page_cache_tags_referencing_entity); - $this->verifyPageCache($referencing_entity_url, 'HIT', $expected_tags); - - // Also verify the existence of an entity render cache entry. - $cache_keys = ['entity_view', 'entity_test', $this->referencingEntity->id(), 'full']; - $cid = $this->createCacheId($cache_keys, $entity_cache_contexts); - $access_cache_contexts = $this->getAccessCacheContextsForEntity($this->entity); - $additional_cache_contexts = $this->getAdditionalCacheContextsForEntity($this->referencingEntity); - $redirected_cid = NULL; - if (count($access_cache_contexts) || count($additional_cache_contexts)) { - $cache_contexts = Cache::mergeContexts($entity_cache_contexts, $additional_cache_contexts); - $cache_contexts = Cache::mergeContexts($cache_contexts, $access_cache_contexts); - $redirected_cid = $this->createCacheId($cache_keys, $cache_contexts); - $context_metadata = \Drupal::service('cache_contexts_manager')->convertTokensToKeys($cache_contexts); - $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $context_metadata->getCacheTags()); - } - $this->verifyRenderCache($cid, $referencing_entity_cache_tags, $redirected_cid); - - $this->pass("Test non-referencing entity.", 'Debug'); - $this->verifyPageCache($non_referencing_entity_url, 'MISS'); - // Verify a cache hit, but also the presence of the correct cache tags. - $this->verifyPageCache($non_referencing_entity_url, 'HIT', Cache::mergeTags($non_referencing_entity_cache_tags, $page_cache_tags)); - // Also verify the existence of an entity render cache entry. - $cache_keys = ['entity_view', 'entity_test', $this->nonReferencingEntity->id(), 'full']; - $cid = $this->createCacheId($cache_keys, $entity_cache_contexts); - $this->verifyRenderCache($cid, $non_referencing_entity_cache_tags); - - - $this->pass("Test listing of referencing entities.", 'Debug'); - // Prime the page cache for the listing of referencing entities. - $this->verifyPageCache($listing_url, 'MISS'); - - // Verify a cache hit, but also the presence of the correct cache tags. - $expected_tags = Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags); - $expected_tags = Cache::mergeTags($expected_tags, $page_cache_tags_referencing_entity); - $this->verifyPageCache($listing_url, 'HIT', $expected_tags); - - $this->pass("Test empty listing.", 'Debug'); - // Prime the page cache for the empty listing. - $this->verifyPageCache($empty_entity_listing_url, 'MISS'); - // Verify a cache hit, but also the presence of the correct cache tags. - $this->verifyPageCache($empty_entity_listing_url, 'HIT', $empty_entity_listing_cache_tags); - // Verify the entity type's list cache contexts are present. - $contexts_in_header = $this->drupalGetHeader('X-Drupal-Cache-Contexts'); - $this->assertEqual(Cache::mergeContexts($page_cache_contexts, $this->getAdditionalCacheContextsForEntityListing()), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header)); - - - $this->pass("Test listing containing referenced entity.", 'Debug'); - // Prime the page cache for the listing containing the referenced entity. - $this->verifyPageCache($nonempty_entity_listing_url, 'MISS', $nonempty_entity_listing_cache_tags); - // Verify a cache hit, but also the presence of the correct cache tags. - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT', $nonempty_entity_listing_cache_tags); - // Verify the entity type's list cache contexts are present. - $contexts_in_header = $this->drupalGetHeader('X-Drupal-Cache-Contexts'); - $this->assertEqual(Cache::mergeContexts($page_cache_contexts, $this->getAdditionalCacheContextsForEntityListing()), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header)); - - - // Verify that after modifying the referenced entity, there is a cache miss - // for every route except the one for the non-referencing entity. - $this->pass("Test modification of referenced entity.", 'Debug'); - $this->entity->save(); - $this->verifyPageCache($referencing_entity_url, 'MISS'); - $this->verifyPageCache($listing_url, 'MISS'); - $this->verifyPageCache($empty_entity_listing_url, 'MISS'); - $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); - $this->verifyPageCache($non_referencing_entity_url, 'HIT'); - - // Verify cache hits. - $this->verifyPageCache($referencing_entity_url, 'HIT'); - $this->verifyPageCache($listing_url, 'HIT'); - $this->verifyPageCache($empty_entity_listing_url, 'HIT'); - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); - - - // Verify that after modifying the referencing entity, there is a cache miss - // for every route except the ones for the non-referencing entity and the - // empty entity listing. - $this->pass("Test modification of referencing entity.", 'Debug'); - $this->referencingEntity->save(); - $this->verifyPageCache($referencing_entity_url, 'MISS'); - $this->verifyPageCache($listing_url, 'MISS'); - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); - $this->verifyPageCache($non_referencing_entity_url, 'HIT'); - $this->verifyPageCache($empty_entity_listing_url, 'HIT'); - - // Verify cache hits. - $this->verifyPageCache($referencing_entity_url, 'HIT'); - $this->verifyPageCache($listing_url, 'HIT'); - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); - - - // Verify that after modifying the non-referencing entity, there is a cache - // miss only for the non-referencing entity route. - $this->pass("Test modification of non-referencing entity.", 'Debug'); - $this->nonReferencingEntity->save(); - $this->verifyPageCache($referencing_entity_url, 'HIT'); - $this->verifyPageCache($listing_url, 'HIT'); - $this->verifyPageCache($empty_entity_listing_url, 'HIT'); - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); - $this->verifyPageCache($non_referencing_entity_url, 'MISS'); - - // Verify cache hits. - $this->verifyPageCache($non_referencing_entity_url, 'HIT'); - - - if ($this->entity->getEntityType()->hasHandlerClass('view_builder')) { - // Verify that after modifying the entity's display, there is a cache miss - // for both the referencing entity, and the listing of referencing - // entities, but not for any other routes. - $referenced_entity_view_mode = $this->selectViewMode($this->entity->getEntityTypeId()); - $this->pass("Test modification of referenced entity's '$referenced_entity_view_mode' display.", 'Debug'); - $entity_display = entity_get_display($entity_type, $this->entity->bundle(), $referenced_entity_view_mode); - $entity_display->save(); - $this->verifyPageCache($referencing_entity_url, 'MISS'); - $this->verifyPageCache($listing_url, 'MISS'); - $this->verifyPageCache($non_referencing_entity_url, 'HIT'); - $this->verifyPageCache($empty_entity_listing_url, 'HIT'); - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); - - // Verify cache hits. - $this->verifyPageCache($referencing_entity_url, 'HIT'); - $this->verifyPageCache($listing_url, 'HIT'); - } - - - if ($bundle_entity_type_id = $this->entity->getEntityType()->getBundleEntityType()) { - // Verify that after modifying the corresponding bundle entity, there is a - // cache miss for both the referencing entity, and the listing of - // referencing entities, but not for any other routes. - $this->pass("Test modification of referenced entity's bundle entity.", 'Debug'); - $bundle_entity = $this->container->get('entity_type.manager') - ->getStorage($bundle_entity_type_id) - ->load($this->entity->bundle()); - $bundle_entity->save(); - $this->verifyPageCache($referencing_entity_url, 'MISS'); - $this->verifyPageCache($listing_url, 'MISS'); - $this->verifyPageCache($non_referencing_entity_url, 'HIT'); - // Special case: entity types may choose to use their bundle entity type - // cache tags, to avoid having excessively granular invalidation. - $is_special_case = $bundle_entity->getCacheTags() == $this->entity->getCacheTags() && $bundle_entity->getEntityType()->getListCacheTags() == $this->entity->getEntityType()->getListCacheTags(); - if ($is_special_case) { - $this->verifyPageCache($empty_entity_listing_url, 'MISS'); - $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); - } - else { - $this->verifyPageCache($empty_entity_listing_url, 'HIT'); - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); - } - - // Verify cache hits. - $this->verifyPageCache($referencing_entity_url, 'HIT'); - $this->verifyPageCache($listing_url, 'HIT'); - if ($is_special_case) { - $this->verifyPageCache($empty_entity_listing_url, 'HIT'); - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); - } - } - - - if ($this->entity->getEntityType()->get('field_ui_base_route')) { - // Verify that after modifying a configurable field on the entity, there - // is a cache miss. - $this->pass("Test modification of referenced entity's configurable field.", 'Debug'); - $field_storage_name = $this->entity->getEntityTypeId() . '.configurable_field'; - $field_storage = FieldStorageConfig::load($field_storage_name); - $field_storage->save(); - $this->verifyPageCache($referencing_entity_url, 'MISS'); - $this->verifyPageCache($listing_url, 'MISS'); - $this->verifyPageCache($empty_entity_listing_url, 'HIT'); - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); - $this->verifyPageCache($non_referencing_entity_url, 'HIT'); - - // Verify cache hits. - $this->verifyPageCache($referencing_entity_url, 'HIT'); - $this->verifyPageCache($listing_url, 'HIT'); - - - // Verify that after modifying a configurable field on the entity, there - // is a cache miss. - $this->pass("Test modification of referenced entity's configurable field.", 'Debug'); - $field_name = $this->entity->getEntityTypeId() . '.' . $this->entity->bundle() . '.configurable_field'; - $field = FieldConfig::load($field_name); - $field->save(); - $this->verifyPageCache($referencing_entity_url, 'MISS'); - $this->verifyPageCache($listing_url, 'MISS'); - $this->verifyPageCache($empty_entity_listing_url, 'HIT'); - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); - $this->verifyPageCache($non_referencing_entity_url, 'HIT'); - - // Verify cache hits. - $this->verifyPageCache($referencing_entity_url, 'HIT'); - $this->verifyPageCache($listing_url, 'HIT'); - } - - - // Verify that after invalidating the entity's cache tag directly, there is - // a cache miss for every route except the ones for the non-referencing - // entity and the empty entity listing. - $this->pass("Test invalidation of referenced entity's cache tag.", 'Debug'); - Cache::invalidateTags($this->entity->getCacheTagsToInvalidate()); - $this->verifyPageCache($referencing_entity_url, 'MISS'); - $this->verifyPageCache($listing_url, 'MISS'); - $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); - $this->verifyPageCache($non_referencing_entity_url, 'HIT'); - $this->verifyPageCache($empty_entity_listing_url, 'HIT'); - - // Verify cache hits. - $this->verifyPageCache($referencing_entity_url, 'HIT'); - $this->verifyPageCache($listing_url, 'HIT'); - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); - - // Verify that after invalidating the entity's list cache tag directly, - // there is a cache miss for both the empty entity listing and the non-empty - // entity listing routes, but not for other routes. - $this->pass("Test invalidation of referenced entity's list cache tag.", 'Debug'); - Cache::invalidateTags($this->entity->getEntityType()->getListCacheTags()); - $this->verifyPageCache($empty_entity_listing_url, 'MISS'); - $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); - $this->verifyPageCache($referencing_entity_url, 'HIT'); - $this->verifyPageCache($non_referencing_entity_url, 'HIT'); - $this->verifyPageCache($listing_url, 'HIT'); - - // Verify cache hits. - $this->verifyPageCache($empty_entity_listing_url, 'HIT'); - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); - - - if (!empty($view_cache_tag)) { - // Verify that after invalidating the generic entity type's view cache tag - // directly, there is a cache miss for both the referencing entity, and the - // listing of referencing entities, but not for other routes. - $this->pass("Test invalidation of referenced entity's 'view' cache tag.", 'Debug'); - Cache::invalidateTags($view_cache_tag); - $this->verifyPageCache($referencing_entity_url, 'MISS'); - $this->verifyPageCache($listing_url, 'MISS'); - $this->verifyPageCache($non_referencing_entity_url, 'HIT'); - $this->verifyPageCache($empty_entity_listing_url, 'HIT'); - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); - - // Verify cache hits. - $this->verifyPageCache($referencing_entity_url, 'HIT'); - $this->verifyPageCache($listing_url, 'HIT'); - } - - // Verify that after deleting the entity, there is a cache miss for every - // route except for the non-referencing entity one. - $this->pass('Test deletion of referenced entity.', 'Debug'); - $this->entity->delete(); - $this->verifyPageCache($referencing_entity_url, 'MISS'); - $this->verifyPageCache($listing_url, 'MISS'); - $this->verifyPageCache($empty_entity_listing_url, 'MISS'); - $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); - $this->verifyPageCache($non_referencing_entity_url, 'HIT'); - - // Verify cache hits. - $referencing_entity_cache_tags = Cache::mergeTags($this->referencingEntity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags()); - $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, ['http_response', 'rendered']); - - $nonempty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->getAdditionalCacheTagsForEntityListing()); - $nonempty_entity_listing_cache_tags = Cache::mergeTags($nonempty_entity_listing_cache_tags, $page_cache_tags); - - $this->verifyPageCache($referencing_entity_url, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags)); - $this->verifyPageCache($listing_url, 'HIT', $page_cache_tags); - $this->verifyPageCache($empty_entity_listing_url, 'HIT', $empty_entity_listing_cache_tags); - $this->verifyPageCache($nonempty_entity_listing_url, 'HIT', $nonempty_entity_listing_cache_tags); - } - - /** - * Creates a cache ID from a list of cache keys and a set of cache contexts. - * - * @param string[] $keys - * A list of cache keys. - * @param string[] $contexts - * A set of cache contexts. - * - * @return string - * The cache ID string. - */ - protected function createCacheId(array $keys, array $contexts) { - $cid_parts = $keys; - - $contexts = \Drupal::service('cache_contexts_manager')->convertTokensToKeys($contexts); - $cid_parts = array_merge($cid_parts, $contexts->getKeys()); - - return implode(':', $cid_parts); - } - - /** - * Verify that a given render cache entry exists, with the correct cache tags. - * - * @param string $cid - * The render cache item ID. - * @param array $tags - * An array of expected cache tags. - * @param string|null $redirected_cid - * (optional) The redirected render cache item ID. - */ - protected function verifyRenderCache($cid, array $tags, $redirected_cid = NULL) { - // Also verify the existence of an entity render cache entry. - $cache_entry = \Drupal::cache('render')->get($cid); - $this->assertTrue($cache_entry, 'A render cache entry exists.'); - sort($cache_entry->tags); - sort($tags); - $this->assertIdentical($cache_entry->tags, $tags); - $is_redirecting_cache_item = isset($cache_entry->data['#cache_redirect']); - if ($redirected_cid === NULL) { - $this->assertFalse($is_redirecting_cache_item, 'Render cache entry is not a redirect.'); - // If this is a redirecting cache item unlike we expected, log it. - if ($is_redirecting_cache_item) { - debug($cache_entry->data); - } - } - else { - // Verify that $cid contains a cache redirect. - $this->assertTrue($is_redirecting_cache_item, 'Render cache entry is a redirect.'); - // If this is not a redirecting cache item unlike we expected, log it. - if (!$is_redirecting_cache_item) { - debug($cache_entry->data); - } - // Verify that the cache redirect points to the expected CID. - $redirect_cache_metadata = $cache_entry->data['#cache']; - $actual_redirection_cid = $this->createCacheId( - $redirect_cache_metadata['keys'], - $redirect_cache_metadata['contexts'] - ); - $this->assertIdentical($redirected_cid, $actual_redirection_cid); - // Finally, verify that the redirected CID exists and has the same cache - // tags. - $this->verifyRenderCache($redirected_cid, $tags); - } - } - -} diff --git a/core/modules/system/tests/src/Functional/Module/ModuleTestBase.php b/core/modules/system/tests/src/Functional/Module/ModuleTestBase.php deleted file mode 100644 index df9fbc6..0000000 --- a/core/modules/system/tests/src/Functional/Module/ModuleTestBase.php +++ /dev/null @@ -1,194 +0,0 @@ -adminUser = $this->drupalCreateUser(array('access administration pages', 'administer modules')); - $this->drupalLogin($this->adminUser); - } - - /** - * Assert there are tables that begin with the specified base table name. - * - * @param $base_table - * Beginning of table name to look for. - * @param $count - * (optional) Whether or not to assert that there are tables that match the - * specified base table. Defaults to TRUE. - */ - function assertTableCount($base_table, $count = TRUE) { - $tables = db_find_tables(Database::getConnection()->prefixTables('{' . $base_table . '}') . '%'); - - if ($count) { - return $this->assertTrue($tables, format_string('Tables matching "@base_table" found.', array('@base_table' => $base_table))); - } - return $this->assertFalse($tables, format_string('Tables matching "@base_table" not found.', array('@base_table' => $base_table))); - } - - /** - * Assert that all tables defined in a module's hook_schema() exist. - * - * @param $module - * The name of the module. - */ - function assertModuleTablesExist($module) { - $tables = array_keys(drupal_get_module_schema($module)); - $tables_exist = TRUE; - foreach ($tables as $table) { - if (!db_table_exists($table)) { - $tables_exist = FALSE; - } - } - return $this->assertTrue($tables_exist, format_string('All database tables defined by the @module module exist.', array('@module' => $module))); - } - - /** - * Assert that none of the tables defined in a module's hook_schema() exist. - * - * @param $module - * The name of the module. - */ - function assertModuleTablesDoNotExist($module) { - $tables = array_keys(drupal_get_module_schema($module)); - $tables_exist = FALSE; - foreach ($tables as $table) { - if (db_table_exists($table)) { - $tables_exist = TRUE; - } - } - return $this->assertFalse($tables_exist, format_string('None of the database tables defined by the @module module exist.', array('@module' => $module))); - } - - /** - * Asserts that the default configuration of a module has been installed. - * - * @param string $module - * The name of the module. - * - * @return bool - * TRUE if configuration has been installed, FALSE otherwise. - */ - function assertModuleConfig($module) { - $module_config_dir = drupal_get_path('module', $module) . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY; - if (!is_dir($module_config_dir)) { - return; - } - $module_file_storage = new FileStorage($module_config_dir); - - // Verify that the module's default config directory is not empty and - // contains default configuration files (instead of something else). - $all_names = $module_file_storage->listAll(); - if (empty($all_names)) { - // Module has an empty config directory. For example it might contain a - // schema directory. - return; - } - $this->assertTrue($all_names); - - // Look up each default configuration object name in the active - // configuration, and if it exists, remove it from the stack. - // Only default config that belongs to $module is guaranteed to exist; any - // other default config depends on whether other modules are enabled. Thus, - // list all default config once more, but filtered by $module. - $names = $module_file_storage->listAll($module . '.'); - foreach ($names as $key => $name) { - if ($this->config($name)->get()) { - unset($names[$key]); - } - } - // Verify that all configuration has been installed (which means that $names - // is empty). - return $this->assertFalse($names, format_string('All default configuration of @module module found.', array('@module' => $module))); - } - - /** - * Asserts that no configuration exists for a given module. - * - * @param string $module - * The name of the module. - * - * @return bool - * TRUE if no configuration was found, FALSE otherwise. - */ - function assertNoModuleConfig($module) { - $names = \Drupal::configFactory()->listAll($module . '.'); - return $this->assertFalse($names, format_string('No configuration found for @module module.', array('@module' => $module))); - } - - /** - * Assert the list of modules are enabled or disabled. - * - * @param $modules - * Module list to check. - * @param $enabled - * Expected module state. - */ - function assertModules(array $modules, $enabled) { - $this->rebuildContainer(); - foreach ($modules as $module) { - if ($enabled) { - $message = 'Module "@module" is enabled.'; - } - else { - $message = 'Module "@module" is not enabled.'; - } - $this->assertEqual($this->container->get('module_handler')->moduleExists($module), $enabled, format_string($message, array('@module' => $module))); - } - } - - /** - * Verify a log entry was entered for a module's status change. - * - * @param $type - * The category to which this message belongs. - * @param $message - * The message to store in the log. Keep $message translatable - * by not concatenating dynamic values into it! Variables in the - * message should be added by using placeholder strings alongside - * the variables argument to declare the value of the placeholders. - * See t() for documentation on how $message and $variables interact. - * @param $variables - * Array of variables to replace in the message on display or - * NULL if message is already translated or not possible to - * translate. - * @param $severity - * The severity of the message, as per RFC 3164. - * @param $link - * A link to associate with the message. - */ - function assertLogMessage($type, $message, $variables = array(), $severity = RfcLogLevel::NOTICE, $link = '') { - $count = db_select('watchdog', 'w') - ->condition('type', $type) - ->condition('message', $message) - ->condition('variables', serialize($variables)) - ->condition('severity', $severity) - ->condition('link', $link) - ->countQuery() - ->execute() - ->fetchField(); - $this->assertTrue($count > 0, format_string('watchdog table contains @count rows for @message', array('@count' => $count, '@message' => format_string($message, $variables)))); - } - -} diff --git a/core/modules/taxonomy/tests/src/Functional/EfqTest.php b/core/modules/taxonomy/src/Tests/EfqTest.php similarity index 97% rename from core/modules/taxonomy/tests/src/Functional/EfqTest.php rename to core/modules/taxonomy/src/Tests/EfqTest.php index 1f788c8..572ae8f 100644 --- a/core/modules/taxonomy/tests/src/Functional/EfqTest.php +++ b/core/modules/taxonomy/src/Tests/EfqTest.php @@ -1,6 +1,6 @@ drupalPlaceBlock('system_breadcrumb_block'); - - // Create Basic page and Article node types. - if ($this->profile != 'standard') { - $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); - } - } - -} diff --git a/core/modules/telephone/tests/src/Functional/TelephoneFieldTest.php b/core/modules/telephone/src/Tests/TelephoneFieldTest.php similarity index 95% rename from core/modules/telephone/tests/src/Functional/TelephoneFieldTest.php rename to core/modules/telephone/src/Tests/TelephoneFieldTest.php index 7f536c4..f7452b0 100644 --- a/core/modules/telephone/tests/src/Functional/TelephoneFieldTest.php +++ b/core/modules/telephone/src/Tests/TelephoneFieldTest.php @@ -1,9 +1,9 @@ getTestSitePath()); $messages[] = "- Removed test site directory."; } diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php index d4968f4..554d8f1 100644 --- a/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/core/tests/Drupal/Tests/BrowserTestBase.php @@ -457,24 +457,6 @@ protected function setUp() { } /** - * Ensures test files are deletable within file_unmanaged_delete_recursive(). - * - * Some tests chmod generated files to be read only. During - * BrowserTestBase::cleanupEnvironment() and other cleanup operations, - * these files need to get deleted too. - * - * @param string $path - * The file path. - */ - public static function filePreDeleteCallback($path) { - // When the webserver runs with the same system user as phpunit, we can - // make read-only files writable again. If not, chmod will fail while the - // file deletion still works if file permissions have been configured - // correctly. Thus, we ignore any problems while running chmod. - @chmod($path, 0700); - } - - /** * Clean up the Simpletest environment. */ protected function cleanupEnvironment() { @@ -492,8 +474,8 @@ protected function cleanupEnvironment() { } } - // Delete test site directory. - file_unmanaged_delete_recursive($this->siteDirectory, array($this, 'filePreDeleteCallback')); + // Delete the current test site directory. + simpletest_clean_temporary_directories($this->siteDirectory); } /**