Newer
Older
namespace Drupal\Tests\node\Functional;
Angie Byron
committed
use Drupal\comment\Tests\CommentTestTrait;
Angie Byron
committed
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Language\LanguageInterface;
Alex Pott
committed
use Drupal\Core\Url;
Alex Pott
committed
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
catch
committed
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\node\Entity\NodeType;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\Tests\TestFileCreationTrait;
Jennifer Hodgdon
committed
/**
* Tests the node entity preview functionality.
*
* @group node
Jennifer Hodgdon
committed
*/
class PagePreviewTest extends NodeTestBase {
Angie Byron
committed
use EntityReferenceTestTrait;
Angie Byron
committed
use CommentTestTrait;
use TestFileCreationTrait {
getTestFiles as drupalGetTestFiles;
}
Angie Byron
committed
/**
Angie Byron
committed
* Enable the comment, node and taxonomy modules to test on the preview.
*
* @var array
*/
public static $modules = ['node', 'taxonomy', 'comment', 'image', 'file', 'text', 'node_test', 'menu_ui'];
/**
* The name of the created field.
*
* @var string
*/
protected $fieldName;
Alex Pott
committed
protected function setUp() {
Angie Byron
committed
$this->addDefaultCommentField('node', 'page');
$web_user = $this->drupalCreateUser(['edit own page content', 'create page content', 'administer menu']);
$this->drupalLogin($web_user);
// Add a vocabulary so we can test different view modes.
$vocabulary = Vocabulary::create([
Alex Pott
committed
'name' => $this->randomMachineName(),
'description' => $this->randomMachineName(),
'vid' => $this->randomMachineName(),
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
'help' => '',
$vocabulary->save();
$this->vocabulary = $vocabulary;
// Add a term to the vocabulary.
$term = Term::create([
Alex Pott
committed
'name' => $this->randomMachineName(),
'description' => $this->randomMachineName(),
'vid' => $this->vocabulary->id(),
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
$term->save();
$this->term = $term;
catch
committed
// Create an image field.
FieldStorageConfig::create([
'field_name' => 'field_image',
'entity_type' => 'node',
'type' => 'image',
'settings' => [],
'cardinality' => FieldStorageConfig::CARDINALITY_UNLIMITED,
])->save();
$field_config = FieldConfig::create([
'field_name' => 'field_image',
'label' => 'Images',
'entity_type' => 'node',
'bundle' => 'page',
'required' => FALSE,
'settings' => [],
]);
$field_config->save();
// Create a field.
$this->fieldName = mb_strtolower($this->randomMachineName());
$handler_settings = [
'target_bundles' => [
Angie Byron
committed
$this->vocabulary->id() => $this->vocabulary->id(),
],
Angie Byron
committed
'auto_create' => TRUE,
];
$this->createEntityReferenceField('node', 'page', $this->fieldName, 'Tags', 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
Alex Pott
committed
entity_get_form_display('node', 'page', 'default')
->setComponent($this->fieldName, [
Angie Byron
committed
'type' => 'entity_reference_autocomplete_tags',
])
Alex Pott
committed
->save();
// Show on default display and teaser.
Dries Buytaert
committed
entity_get_display('node', 'page', 'default')
->setComponent($this->fieldName, [
Angie Byron
committed
'type' => 'entity_reference_label',
])
Alex Pott
committed
->save();
entity_get_display('node', 'page', 'teaser')
->setComponent($this->fieldName, [
Angie Byron
committed
'type' => 'entity_reference_label',
])
Dries Buytaert
committed
->save();
catch
committed
entity_get_form_display('node', 'page', 'default')
->setComponent('field_image', [
catch
committed
'type' => 'image_image',
'settings' => [],
])
catch
committed
->save();
entity_get_display('node', 'page', 'default')
->setComponent('field_image')
->save();
// Create a multi-value text field.
$field_storage = FieldStorageConfig::create([
'field_name' => 'field_test_multi',
'entity_type' => 'node',
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
'type' => 'text',
'settings' => [
'max_length' => 50,
]);
$field_storage->save();
FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => 'page',
])->save();
entity_get_form_display('node', 'page', 'default')
->setComponent('field_test_multi', [
'type' => 'text_textfield',
])
->save();
entity_get_display('node', 'page', 'default')
->setComponent('field_test_multi', [
'type' => 'string',
])
->save();
Jennifer Hodgdon
committed
* Checks the node preview functionality.
public function testPagePreview() {
$title_key = 'title[0][value]';
Angie Byron
committed
$body_key = 'body[0][value]';
$term_key = $this->fieldName . '[target_id]';
// Fill in node creation form and preview node.
$edit = [];
$edit[$title_key] = '<em>' . $this->randomMachineName(8) . '</em>';
Alex Pott
committed
$edit[$body_key] = $this->randomMachineName(16);
Alex Pott
committed
$edit[$term_key] = $this->term->getName();
catch
committed
// Upload an image.
$test_image = current($this->drupalGetTestFiles('image', 39325));
$edit['files[field_image_0][]'] = \Drupal::service('file_system')->realpath($test_image->uri);
catch
committed
$this->drupalPostForm('node/add/page', $edit, t('Upload'));
// Add an alt tag and preview the node.
$this->drupalPostForm(NULL, ['field_image[0][alt]' => 'Picture of llamas'], t('Preview'));
// Check that the preview is displaying the title, body and term.
$expected_title = $edit[$title_key] . ' | Drupal';
$this->assertSession()->titleEquals($expected_title);
$this->assertEscaped($edit[$title_key], 'Title displayed and escaped.');
Jennifer Hodgdon
committed
$this->assertText($edit[$body_key], 'Body displayed.');
$this->assertText($edit[$term_key], 'Term displayed.');
Angie Byron
committed
$this->assertLink(t('Back to content editing'));
// Check that we see the class of the node type on the body element.
$body_class_element = $this->xpath("//body[contains(@class, 'page-node-type-page')]");
$this->assertTrue(!empty($body_class_element), 'Node type body class found.');
Angie Byron
committed
// Get the UUID.
$url = parse_url($this->getUrl());
$paths = explode('/', $url['path']);
$view_mode = array_pop($paths);
$uuid = array_pop($paths);
// Switch view mode. We'll remove the body from the teaser view mode.
entity_get_display('node', 'page', 'teaser')
->removeComponent('body')
->save();
$view_mode_edit = ['view_mode' => 'teaser'];
Alex Pott
committed
$this->drupalPostForm('node/preview/' . $uuid . '/full', $view_mode_edit, t('Switch'));
Angie Byron
committed
$this->assertRaw('view-mode-teaser', 'View mode teaser class found.');
$this->assertNoText($edit[$body_key], 'Body not displayed.');
// Check that the title, body and term fields are displayed with the
Angie Byron
committed
// values after going back to the content edit page.
$this->clickLink(t('Back to content editing'));
Jennifer Hodgdon
committed
$this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
$this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.');
catch
committed
$this->assertFieldByName('field_image[0][alt]', 'Picture of llamas');
$this->getSession()->getPage()->pressButton('Add another item');
$this->assertFieldByName('field_test_multi[0][value]');
$this->assertFieldByName('field_test_multi[1][value]');
Dries Buytaert
committed
Angie Byron
committed
// Return to page preview to check everything is as expected.
$this->drupalPostForm(NULL, [], t('Preview'));
$this->assertSession()->titleEquals($expected_title);
$this->assertEscaped($edit[$title_key], 'Title displayed and escaped.');
Angie Byron
committed
$this->assertText($edit[$body_key], 'Body displayed.');
$this->assertText($edit[$term_key], 'Term displayed.');
$this->assertLink(t('Back to content editing'));
// Assert the content is kept when reloading the page.
$this->drupalGet('node/add/page', ['query' => ['uuid' => $uuid]]);
$this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
$this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.');
catch
committed
// Save the node - this is a new POST, so we need to upload the image.
$this->drupalPostForm('node/add/page', $edit, t('Upload'));
$this->drupalPostForm(NULL, ['field_image[0][alt]' => 'Picture of llamas'], t('Save'));
Dries Buytaert
committed
$node = $this->drupalGetNodeByTitle($edit[$title_key]);
// Check the term was displayed on the saved node.
$this->drupalGet('node/' . $node->id());
Dries Buytaert
committed
$this->assertText($edit[$term_key], 'Term displayed.');
// Check the term appears again on the edit form.
$this->drupalGet('node/' . $node->id() . '/edit');
Angie Byron
committed
$this->assertFieldByName($term_key, $edit[$term_key] . ' (' . $this->term->id() . ')', 'Term field displayed.');
Dries Buytaert
committed
// Check with two new terms on the edit form, additionally to the existing
// one.
$edit = [];
Alex Pott
committed
$newterm1 = $this->randomMachineName(8);
$newterm2 = $this->randomMachineName(8);
Alex Pott
committed
$edit[$term_key] = $this->term->getName() . ', ' . $newterm1 . ', ' . $newterm2;
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Preview'));
Dries Buytaert
committed
$this->assertRaw('>' . $newterm1 . '<', 'First new term displayed.');
$this->assertRaw('>' . $newterm2 . '<', 'Second new term displayed.');
// The first term should be displayed as link, the others not.
Alex Pott
committed
$this->assertLink($this->term->getName());
Dries Buytaert
committed
$this->assertNoLink($newterm1);
$this->assertNoLink($newterm2);
Angie Byron
committed
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
Dries Buytaert
committed
// Check with one more new term, keeping old terms, removing the existing
// one.
$edit = [];
Alex Pott
committed
$newterm3 = $this->randomMachineName(8);
Dries Buytaert
committed
$edit[$term_key] = $newterm1 . ', ' . $newterm3 . ', ' . $newterm2;
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Preview'));
Dries Buytaert
committed
$this->assertRaw('>' . $newterm1 . '<', 'First existing term displayed.');
$this->assertRaw('>' . $newterm2 . '<', 'Second existing term displayed.');
$this->assertRaw('>' . $newterm3 . '<', 'Third new term displayed.');
Alex Pott
committed
$this->assertNoText($this->term->getName());
$this->assertLink($newterm1);
$this->assertLink($newterm2);
Dries Buytaert
committed
$this->assertNoLink($newterm3);
Angie Byron
committed
// Check that editing an existing node after it has been previewed and not
// saved doesn't remember the previous changes.
$edit = [
$title_key => $this->randomMachineName(8),
];
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Preview'));
$this->assertText($edit[$title_key], 'New title displayed.');
$this->clickLink(t('Back to content editing'));
$this->assertFieldByName($title_key, $edit[$title_key], 'New title value displayed.');
// Navigate away from the node without saving.
$this->drupalGet('<front>');
// Go back to the edit form, the title should have its initial value.
$this->drupalGet('node/' . $node->id() . '/edit');
$this->assertFieldByName($title_key, $node->label(), 'Correct title value displayed.');
Angie Byron
committed
// Check with required preview.
$node_type = NodeType::load('page');
$node_type->setPreviewMode(DRUPAL_REQUIRED);
$node_type->save();
$this->drupalGet('node/add/page');
$this->assertNoRaw('edit-submit');
$this->drupalPostForm('node/add/page', [$title_key => 'Preview'], t('Preview'));
Angie Byron
committed
$this->clickLink(t('Back to content editing'));
$this->assertRaw('edit-submit');
Alex Pott
committed
// Check that destination is remembered when clicking on preview. When going
// back to the edit form and clicking save, we should go back to the
// original destination, if set.
$destination = 'node';
$this->drupalPostForm($node->toUrl('edit-form'), [], t('Preview'), ['query' => ['destination' => $destination]]);
Alex Pott
committed
$parameters = ['node_preview' => $node->uuid(), 'view_mode_id' => 'full'];
Alex Pott
committed
$options = ['absolute' => TRUE, 'query' => ['destination' => $destination]];
$this->assertUrl(Url::fromRoute('entity.node.preview', $parameters, $options));
$this->drupalPostForm(NULL, ['view_mode' => 'teaser'], t('Switch'));
$this->clickLink(t('Back to content editing'));
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertUrl($destination);
// Check that preview page works as expected without a destination set.
$this->drupalPostForm($node->toUrl('edit-form'), [], t('Preview'));
Alex Pott
committed
$parameters = ['node_preview' => $node->uuid(), 'view_mode_id' => 'full'];
Alex Pott
committed
$this->assertUrl(Url::fromRoute('entity.node.preview', $parameters, ['absolute' => TRUE]));
$this->drupalPostForm(NULL, ['view_mode' => 'teaser'], t('Switch'));
$this->clickLink(t('Back to content editing'));
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertUrl($node->toUrl());
$this->assertResponse(200);
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system');
// Assert multiple items can be added and are not lost when previewing.
$test_image_1 = current($this->drupalGetTestFiles('image', 39325));
$edit_image_1['files[field_image_0][]'] = $file_system->realpath($test_image_1->uri);
$test_image_2 = current($this->drupalGetTestFiles('image', 39325));
$edit_image_2['files[field_image_1][]'] = $file_system->realpath($test_image_2->uri);
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
$edit['field_image[0][alt]'] = 'Alt 1';
$this->drupalPostForm('node/add/page', $edit_image_1, t('Upload'));
$this->drupalPostForm(NULL, $edit, t('Preview'));
$this->clickLink(t('Back to content editing'));
$this->assertFieldByName('files[field_image_1][]');
$this->drupalPostForm(NULL, $edit_image_2, t('Upload'));
$this->assertNoFieldByName('files[field_image_1][]');
$title = 'node_test_title';
$example_text_1 = 'example_text_preview_1';
$example_text_2 = 'example_text_preview_2';
$example_text_3 = 'example_text_preview_3';
$this->drupalGet('node/add/page');
$edit = [
'title[0][value]' => $title,
'field_test_multi[0][value]' => $example_text_1,
];
$this->assertRaw('Storage is not set');
$this->drupalPostForm(NULL, $edit, t('Preview'));
$this->clickLink(t('Back to content editing'));
$this->assertRaw('Storage is set');
$this->assertFieldByName('field_test_multi[0][value]');
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertText('Basic page ' . $title . ' has been created.');
$node = $this->drupalGetNodeByTitle($title);
$this->drupalGet('node/' . $node->id() . '/edit');
$this->getSession()->getPage()->pressButton('Add another item');
$this->getSession()->getPage()->pressButton('Add another item');
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
$edit = [
'field_test_multi[1][value]' => $example_text_2,
'field_test_multi[2][value]' => $example_text_3,
];
$this->drupalPostForm(NULL, $edit, t('Preview'));
$this->clickLink(t('Back to content editing'));
$this->drupalPostForm(NULL, $edit, t('Preview'));
$this->clickLink(t('Back to content editing'));
$this->assertFieldByName('field_test_multi[0][value]', $example_text_1);
$this->assertFieldByName('field_test_multi[1][value]', $example_text_2);
$this->assertFieldByName('field_test_multi[2][value]', $example_text_3);
// Now save the node and make sure all values got saved.
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertText($example_text_1);
$this->assertText($example_text_2);
$this->assertText($example_text_3);
// Edit again, change the menu_ui settings and click on preview.
$this->drupalGet('node/' . $node->id() . '/edit');
$edit = [
'menu[enabled]' => TRUE,
'menu[title]' => 'Changed title',
];
$this->drupalPostForm(NULL, $edit, t('Preview'));
$this->clickLink(t('Back to content editing'));
$this->assertFieldChecked('edit-menu-enabled', 'Menu option is still checked');
$this->assertFieldByName('menu[title]', 'Changed title', 'Menu link title is correct after preview');
// Save, change the title while saving and make sure that it is correctly
// saved.
$edit = [
'menu[enabled]' => TRUE,
'menu[title]' => 'Second title change',
];
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->drupalGet('node/' . $node->id() . '/edit');
$this->assertFieldByName('menu[title]', 'Second title change', 'Menu link title is correct after saving');
Jennifer Hodgdon
committed
* Checks the node preview functionality, when using revisions.
public function testPagePreviewWithRevisions() {
$title_key = 'title[0][value]';
Angie Byron
committed
$body_key = 'body[0][value]';
$term_key = $this->fieldName . '[target_id]';
// Force revision on "Basic page" content.
$node_type = NodeType::load('page');
$node_type->setNewRevision(TRUE);
$node_type->save();
// Fill in node creation form and preview node.
$edit = [];
Alex Pott
committed
$edit[$title_key] = $this->randomMachineName(8);
$edit[$body_key] = $this->randomMachineName(16);
$edit[$term_key] = $this->term->id();
$edit['revision_log[0][value]'] = $this->randomString(32);
$this->drupalPostForm('node/add/page', $edit, t('Preview'));
// Check that the preview is displaying the title, body and term.
$this->assertTitle(t('@title | Drupal', ['@title' => $edit[$title_key]]), 'Basic page title is preview.');
Jennifer Hodgdon
committed
$this->assertText($edit[$title_key], 'Title displayed.');
$this->assertText($edit[$body_key], 'Body displayed.');
$this->assertText($edit[$term_key], 'Term displayed.');
Angie Byron
committed
// Check that the title and body fields are displayed with the correct
// values after going back to the content edit page.
$this->clickLink(t('Back to content editing')); $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
Jennifer Hodgdon
committed
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
$this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.');
// Check that the revision log field has the correct value.
$this->assertFieldByName('revision_log[0][value]', $edit['revision_log[0][value]'], 'Revision log field displayed.');
// Save the node after coming back from the preview page so we can create a
// pending revision for it.
$this->drupalPostForm(NULL, [], t('Save'));
$node = $this->drupalGetNodeByTitle($edit[$title_key]);
// Check that previewing a pending revision of a node works. This can not be
// accomplished through the UI so we have to use API calls.
// @todo Change this test to use the UI when we will be able to create
// pending revisions in core.
// @see https://www.drupal.org/node/2725533
$node->setNewRevision(TRUE);
$node->isDefaultRevision(FALSE);
/** @var \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver */
$controller_resolver = \Drupal::service('controller_resolver');
$node_preview_controller = $controller_resolver->getControllerFromDefinition('\Drupal\node\Controller\NodePreviewController::view');
Alex Pott
committed
$node_preview_controller($node, 'full');
Angie Byron
committed
/**
* Checks the node preview accessible for simultaneous node editing.
*/
public function testSimultaneousPreview() {
$title_key = 'title[0][value]';
$node = $this->drupalCreateNode([]);
Angie Byron
committed
$edit = [$title_key => 'New page title'];
Angie Byron
committed
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Preview'));
$this->assertText($edit[$title_key]);
$user2 = $this->drupalCreateUser(['edit any page content']);
Angie Byron
committed
$this->drupalLogin($user2);
$this->drupalGet('node/' . $node->id() . '/edit');
$this->assertFieldByName($title_key, $node->label(), 'No title leaked from previous user.');
$edit2 = [$title_key => 'Another page title'];
Angie Byron
committed
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit2, t('Preview'));
Alex Pott
committed
$this->assertUrl(\Drupal::url('entity.node.preview', ['node_preview' => $node->uuid(), 'view_mode_id' => 'full'], ['absolute' => TRUE]));
Angie Byron
committed
$this->assertText($edit2[$title_key]);
}