Update to Drupal 8.1.8. For more information, see https://www.drupal.org/project/drupal/releases/8.1.8

This commit is contained in:
Pantheon Automation 2016-08-03 13:22:33 -07:00 committed by Greg Anderson
parent e9f047ccf8
commit f9f23cdf38
312 changed files with 6751 additions and 1546 deletions

View file

@ -10,6 +10,11 @@ use Drupal\Tests\node\Kernel\Migrate\d6\MigrateNodeTestBase;
*/
class MigrateNodeRevisionTest extends MigrateNodeTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['language', 'content_translation'];
/**
* {@inheritdoc}
*/

View file

@ -2,6 +2,8 @@
namespace Drupal\node\Tests;
use Drupal\filter\Entity\FilterFormat;
/**
* Ensures that data added to nodes by other modules appears in RSS feeds.
*
@ -60,4 +62,47 @@ class NodeRSSContentTest extends NodeTestBase {
$this->assertNoText($rss_only_content, 'Node content designed for RSS does not appear when viewing node.');
}
/**
* Tests relative, root-relative, protocol-relative and absolute URLs.
*/
public function testUrlHandling() {
// Only the plain_text text format is available by default, which escapes
// all HTML.
FilterFormat::create([
'format' => 'full_html',
'name' => 'Full HTML',
'filters' => [],
])->save();
$defaults = [
'type' => 'article',
'promote' => 1,
];
$this->drupalCreateNode($defaults + [
'body' => [
'value' => '<p><a href="' . file_url_transform_relative(file_create_url('public://root-relative')) . '">Root-relative URL</a></p>',
'format' => 'full_html',
],
]);
$protocol_relative_url = substr(file_create_url('public://protocol-relative'), strlen(\Drupal::request()->getScheme() . ':'));
$this->drupalCreateNode($defaults + [
'body' => [
'value' => '<p><a href="' . $protocol_relative_url . '">Protocol-relative URL</a></p>',
'format' => 'full_html',
],
]);
$absolute_url = file_create_url('public://absolute');
$this->drupalCreateNode($defaults + [
'body' => [
'value' => '<p><a href="' . $absolute_url . '">Absolute URL</a></p>',
'format' => 'full_html',
],
]);
$this->drupalGet('rss.xml');
$this->assertRaw(file_create_url('public://root-relative'), 'Root-relative URL is transformed to absolute.');
$this->assertRaw($protocol_relative_url, 'Protocol-relative URL is left untouched.');
$this->assertRaw($absolute_url, 'Absolute URL is left untouched.');
}
}

View file

@ -2,6 +2,8 @@
namespace Drupal\node\Tests;
use Drupal\node\NodeInterface;
/**
* Create a node with revisions and test viewing, saving, reverting, and
* deleting revisions for user with access to all.
@ -15,7 +17,7 @@ class NodeRevisionsAllTest extends NodeTestBase {
protected function setUp() {
parent::setUp();
$node_storage = $this->container->get('entity.manager')->getStorage('node');
// Create and log in user.
$web_user = $this->drupalCreateUser(
array(
@ -45,17 +47,7 @@ class NodeRevisionsAllTest extends NodeTestBase {
for ($i = 0; $i < $revision_count; $i++) {
$logs[] = $node->revision_log = $this->randomMachineName(32);
// Create revision with a random title and body and update variables.
$node->title = $this->randomMachineName();
$node->body = array(
'value' => $this->randomMachineName(32),
'format' => filter_default_format(),
);
$node->setNewRevision();
$node->save();
$node_storage->resetCache(array($node->id()));
$node = $node_storage->load($node->id()); // Make sure we get revision information.
$node = $this->createNodeRevision($node);
$nodes[] = clone $node;
}
@ -63,6 +55,28 @@ class NodeRevisionsAllTest extends NodeTestBase {
$this->revisionLogs = $logs;
}
/**
* Creates a new revision for a given node.
*
* @param \Drupal\node\NodeInterface $node
* A node object.
*
* @return \Drupal\node\NodeInterface
* A node object with up to date revision information.
*/
protected function createNodeRevision(NodeInterface $node) {
// Create revision with a random title and body and update variables.
$node->title = $this->randomMachineName();
$node->body = array(
'value' => $this->randomMachineName(32),
'format' => filter_default_format(),
);
$node->setNewRevision();
$node->save();
return $node;
}
/**
* Checks node revision operations.
*/
@ -145,6 +159,29 @@ class NodeRevisionsAllTest extends NodeTestBase {
'%title' => $nodes[2]->getTitle(),
'%revision-date' => format_date($old_revision_date),
)));
// Create 50 more revisions in order to trigger paging on the revisions
// overview screen.
$node = $nodes[0];
for ($i = 0; $i < 50; $i++) {
$logs[] = $node->revision_log = $this->randomMachineName(32);
$node = $this->createNodeRevision($node);
$nodes[] = clone $node;
}
$this->drupalGet('node/' . $node->id() . '/revisions');
// Check that the pager exists.
$this->assertRaw('page=1');
// Check that the last revision is displayed on the first page.
$this->assertText(end($logs));
// Go to the second page and check that one of the initial three revisions
// is displayed.
$this->clickLink(t('Page 2'));
$this->assertText($logs[2]);
}
}

View file

@ -8,6 +8,7 @@ use Drupal\field\Entity\FieldStorageConfig;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Drupal\Component\Serialization\Json;
/**
* Create a node with revisions and test viewing, saving, reverting, and
@ -34,7 +35,7 @@ class NodeRevisionsTest extends NodeTestBase {
/**
* {@inheritdoc}
*/
public static $modules = array('node', 'datetime', 'language', 'content_translation');
public static $modules = ['node', 'contextual', 'datetime', 'language', 'content_translation'];
/**
* {@inheritdoc}
@ -71,6 +72,7 @@ class NodeRevisionsTest extends NodeTestBase {
'delete page revisions',
'edit any page content',
'delete any page content',
'access contextual links',
'translate any entity',
'administer content types',
)
@ -152,6 +154,18 @@ class NodeRevisionsTest extends NodeTestBase {
// Confirm that this is the default revision.
$this->assertTrue($node->isDefaultRevision(), 'Third node revision is the default one.');
// Confirm that the "Edit" and "Delete" contextual links appear for the
// default revision.
$ids = ['node:node=' . $node->id() . ':changed=' . $node->getChangedTime()];
$json = $this->renderContextualLinks($ids, 'node/' . $node->id());
$this->verbose($json[$ids[0]]);
$expected = '<li class="entitynodeedit-form"><a href="' . base_path() . 'node/' . $node->id() . '/edit">Edit</a></li>';
$this->assertTrue(strstr($json[$ids[0]], $expected), 'The "Edit" contextual link is shown for the default revision.');
$expected = '<li class="entitynodedelete-form"><a href="' . base_path() . 'node/' . $node->id() . '/delete">Delete</a></li>';
$this->assertTrue(strstr($json[$ids[0]], $expected), 'The "Delete" contextual link is shown for the default revision.');
// Confirm that revisions revert properly.
$this->drupalPostForm("node/" . $node->id() . "/revisions/" . $nodes[1]->getRevisionid() . "/revert", array(), t('Revert'));
$this->assertRaw(t('@type %title has been reverted to the revision from %revision-date.',
@ -165,6 +179,16 @@ class NodeRevisionsTest extends NodeTestBase {
$node = node_revision_load($node->getRevisionId());
$this->assertFalse($node->isDefaultRevision(), 'Third node revision is not the default one.');
// Confirm that "Edit" and "Delete" contextual links don't appear for
// non-default revision.
$ids = ['node_revision::node=' . $node->id() . '&node_revision=' . $node->getRevisionId() . ':'];
$json = $this->renderContextualLinks($ids, 'node/' . $node->id() . '/revisions/' . $node->getRevisionId() . '/view');
$this->verbose($json[$ids[0]]);
$this->assertFalse(strstr($json[$ids[0]], '<li class="entitynodeedit-form">'), 'The "Edit" contextual link is not shown for a non-default revision.');
$this->assertFalse(strstr($json[$ids[0]], '<li class="entitynodedelete-form">'), 'The "Delete" contextual link is not shown for a non-default revision.');
// Confirm revisions delete properly.
$this->drupalPostForm("node/" . $node->id() . "/revisions/" . $nodes[1]->getRevisionId() . "/delete", array(), t('Delete'));
$this->assertRaw(t('Revision from %revision-date of @type %title has been deleted.',
@ -317,6 +341,27 @@ class NodeRevisionsTest extends NodeTestBase {
$this->assertTrue(empty($node_revision->revision_log->value), 'After a new node revision is saved with an empty log message, the log message for the node is empty.');
}
/**
* Gets server-rendered contextual links for the given contextual links IDs.
*
* @param string[] $ids
* An array of contextual link IDs.
* @param string $current_path
* The Drupal path for the page for which the contextual links are rendered.
*
* @return string
* The decoded JSON response body.
*/
protected function renderContextualLinks(array $ids, $current_path) {
$post = array();
for ($i = 0; $i < count($ids); $i++) {
$post['ids[' . $i . ']'] = $ids[$i];
}
$response = $this->drupalPost('contextual/render', 'application/json', $post, ['query' => ['destination' => $current_path]]);
return Json::decode($response);
}
/**
* Tests the revision translations are correctly reverted.
*/

View file

@ -445,4 +445,53 @@ class NodeTranslationUITest extends ContentTranslationUITestBase {
}
}
/**
* Tests that revision translations are rendered properly.
*/
public function testRevisionTranslationRendering() {
$storage = \Drupal::entityTypeManager()->getStorage('node');
// Create a node.
$nid = $this->createEntity(['title' => 'First rev en title'], 'en');
$node = $storage->load($nid);
$original_revision_id = $node->getRevisionId();
// Add a French translation.
$translation = $node->addTranslation('fr');
$translation->title = 'First rev fr title';
$translation->setNewRevision(FALSE);
$translation->save();
// Create a new revision.
$node->title = 'Second rev en title';
$node->setNewRevision(TRUE);
$node->save();
// Get an English view of this revision.
$original_revision = $storage->loadRevision($original_revision_id);
$original_revision_url = $original_revision->toUrl('revision')->toString();
// Should be different from regular node URL.
$this->assertNotIdentical($original_revision_url, $original_revision->toUrl()->toString());
$this->drupalGet($original_revision_url);
$this->assertResponse(200);
// Contents should be in English, of correct revision.
$this->assertText('First rev en title');
$this->assertNoText('First rev fr title');
// Get a French view.
$url_fr = $original_revision->getTranslation('fr')->toUrl('revision')->toString();
// Should have different URL from English.
$this->assertNotIdentical($url_fr, $original_revision->toUrl()->toString());
$this->assertNotIdentical($url_fr, $original_revision_url);
$this->drupalGet($url_fr);
$this->assertResponse(200);
// Contents should be in French, of correct revision.
$this->assertText('First rev fr title');
$this->assertNoText('First rev en title');
}
}

View file

@ -23,7 +23,9 @@ class NodeTypeTranslationTest extends WebTestBase {
* @var array
*/
public static $modules = array(
'block',
'config_translation',
'field_ui',
'node',
);
@ -53,6 +55,8 @@ class NodeTypeTranslationTest extends WebTestBase {
$admin_permissions = array(
'administer content types',
'administer node fields',
'administer languages',
'administer site configuration',
'administer themes',
'translate configuration',
@ -144,6 +148,29 @@ class NodeTypeTranslationTest extends WebTestBase {
$this->assertText('Edited title');
$this->drupalGet("$langcode/node/add/$type");
$this->assertText('Translated title');
// Add an e-mail field.
$this->drupalPostForm("admin/structure/types/manage/$type/fields/add-field", array('new_storage_type' => 'email', 'label' => 'Email', 'field_name' => 'email'), 'Save and continue');
$this->drupalPostForm(NULL, array(), 'Save field settings');
$this->drupalPostForm(NULL, array(), 'Save settings');
$type = Unicode::strtolower($this->randomMachineName(16));
$name = $this->randomString();
$this->drupalCreateContentType(array('type' => $type, 'name' => $name));
// Set tabs.
$this->drupalPlaceBlock('local_tasks_block', array('primary' => TRUE));
// Change default language.
$this->drupalPostForm('admin/config/regional/language', array('site_default_language' => 'es'), 'Save configuration');
// Try re-using the email field.
$this->drupalGet("es/admin/structure/types/manage/$type/fields/add-field");
$this->drupalPostForm(NULL, array('existing_storage_name' => 'field_email', 'existing_storage_label' => 'Email'), 'Save and continue');
$this->assertResponse(200);
$this->drupalGet("es/admin/structure/types/manage/$type/fields/node.$type.field_email/translate");
$this->assertResponse(200);
$this->assertText("The configuration objects have different language codes so they cannot be translated");
}
}

View file

@ -0,0 +1,77 @@
<?php
namespace Drupal\node\Tests\Views;
use Drupal\views\Views;
/**
* Tests the node row plugin.
*
* @group node
*/
class PathPluginTest extends NodeTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node');
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_node_path_plugin');
/**
* Contains all nodes used by this test.
*
* @var Node[]
*/
protected $nodes;
protected function setUp() {
parent::setUp();
$this->drupalCreateContentType(array('type' => 'article'));
// Create two nodes.
for ($i = 0; $i < 2; $i++) {
$this->nodes[] = $this->drupalCreateNode(
array(
'type' => 'article',
'body' => array(
array(
'value' => $this->randomMachineName(42),
'format' => filter_default_format(),
'summary' => $this->randomMachineName(),
),
),
)
);
}
}
/**
* Tests the node path plugin.
*/
public function testPathPlugin() {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = $this->container->get('renderer');
$view = Views::getView('test_node_path_plugin');
$view->initDisplay();
$view->setDisplay('page_1');
$view->initStyle();
$view->rowPlugin->options['view_mode'] = 'full';
// Test with view_mode full.
$output = $view->preview();
$output = $renderer->renderRoot($output);
foreach ($this->nodes as $node) {
$this->assertTrue(strpos($output, 'This is <strong>not escaped</strong> and this is ' . $node->link('the link')) !== FALSE, 'Make sure path field rewriting is not escaped.');
}
}
}

View file

@ -0,0 +1,89 @@
<?php
namespace Drupal\node\Tests\Views;
/**
* Tests the different revision link handlers.
*
* @group node
*
* @see \Drupal\node\Plugin\views\field\RevisionLink
* @see \Drupal\node\Plugin\views\field\RevisionLinkDelete
* @see \Drupal\node\Plugin\views\field\RevisionLinkRevert
*/
class RevisionLinkTest extends NodeTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_node_revision_links'];
/**
* Tests revision links.
*/
public function testRevisionLinks() {
// Create one user which can view/revert and delete and one which can only
// do one of them.
$this->drupalCreateContentType(['name' => 'page', 'type' => 'page']);
$account = $this->drupalCreateUser(['revert all revisions', 'view all revisions', 'delete all revisions', 'edit any page content', 'delete any page content']);
$this->drupalLogin($account);
// Create two nodes, one without an additional revision and one with a
// revision.
$nodes = [
$this->drupalCreateNode(),
$this->drupalCreateNode(),
];
$first_revision = $nodes[1]->getRevisionId();
// Create revision of the node.
$nodes[1]->setNewRevision();
$nodes[1]->save();
$second_revision = $nodes[1]->getRevisionId();
$this->drupalGet('test-node-revision-links');
$this->assertResponse(200, 'Test view can be accessed in the path expected');
// The first node revision should link to the node directly as you get an
// access denied if you link to the revision.
$url = $nodes[0]->urlInfo()->toString();
$this->assertLinkByHref($url);
$this->assertNoLinkByHref($url . '/revisions/' . $nodes[0]->getRevisionId() . '/view');
$this->assertNoLinkByHref($url . '/revisions/' . $nodes[0]->getRevisionId() . '/delete');
$this->assertNoLinkByHref($url . '/revisions/' . $nodes[0]->getRevisionId() . '/revert');
// For the second node the current revision got set to the last revision, so
// the first one should also link to the node page itself.
$url = $nodes[1]->urlInfo()->toString();
$this->assertLinkByHref($url);
$this->assertLinkByHref($url . '/revisions/' . $first_revision . '/view');
$this->assertLinkByHref($url . '/revisions/' . $first_revision . '/delete');
$this->assertLinkByHref($url . '/revisions/' . $first_revision . '/revert');
$this->assertNoLinkByHref($url . '/revisions/' . $second_revision . '/view');
$this->assertNoLinkByHref($url . '/revisions/' . $second_revision . '/delete');
$this->assertNoLinkByHref($url . '/revisions/' . $second_revision . '/revert');
$accounts = [
'view' => $this->drupalCreateUser(['view all revisions']),
'revert' => $this->drupalCreateUser(['revert all revisions', 'edit any page content']),
'delete' => $this->drupalCreateUser(['delete all revisions', 'delete any page content']),
];
$url = $nodes[1]->urlInfo()->toString();
// Render the view with users which can only delete/revert revisions.
foreach ($accounts as $allowed_operation => $account) {
$this->drupalLogin($account);
$this->drupalGet('test-node-revision-links');
// Check expected links.
foreach (['revert', 'delete'] as $operation) {
if ($operation == $allowed_operation) {
$this->assertLinkByHref($url . '/revisions/' . $first_revision . '/' . $operation);
}
else {
$this->assertNoLinkByHref($url . '/revisions/' . $first_revision . '/' . $operation);
}
}
}
}
}