NodeEditFormTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. <?php
  2. namespace Drupal\Tests\node\Functional;
  3. use Drupal\node\NodeInterface;
  4. use Drupal\user\Entity\User;
  5. /**
  6. * Create a node and test node edit functionality.
  7. *
  8. * @group node
  9. */
  10. class NodeEditFormTest extends NodeTestBase {
  11. /**
  12. * A normal logged in user.
  13. *
  14. * @var \Drupal\user\UserInterface
  15. */
  16. protected $webUser;
  17. /**
  18. * A user with permission to bypass content access checks.
  19. *
  20. * @var \Drupal\user\UserInterface
  21. */
  22. protected $adminUser;
  23. /**
  24. * The node storage.
  25. *
  26. * @var \Drupal\node\NodeStorageInterface
  27. */
  28. protected $nodeStorage;
  29. /**
  30. * Modules to enable.
  31. *
  32. * @var string[]
  33. */
  34. public static $modules = ['block', 'node', 'datetime'];
  35. protected function setUp() {
  36. parent::setUp();
  37. $this->webUser = $this->drupalCreateUser(['edit own page content', 'create page content']);
  38. $this->adminUser = $this->drupalCreateUser(['bypass node access', 'administer nodes']);
  39. $this->drupalPlaceBlock('local_tasks_block');
  40. $this->nodeStorage = $this->container->get('entity.manager')->getStorage('node');
  41. }
  42. /**
  43. * Checks node edit functionality.
  44. */
  45. public function testNodeEdit() {
  46. $this->drupalLogin($this->webUser);
  47. $title_key = 'title[0][value]';
  48. $body_key = 'body[0][value]';
  49. // Create node to edit.
  50. $edit = [];
  51. $edit[$title_key] = $this->randomMachineName(8);
  52. $edit[$body_key] = $this->randomMachineName(16);
  53. $this->drupalPostForm('node/add/page', $edit, t('Save'));
  54. // Check that the node exists in the database.
  55. $node = $this->drupalGetNodeByTitle($edit[$title_key]);
  56. $this->assertTrue($node, 'Node found in database.');
  57. // Check that "edit" link points to correct page.
  58. $this->clickLink(t('Edit'));
  59. $this->assertUrl($node->url('edit-form', ['absolute' => TRUE]));
  60. // Check that the title and body fields are displayed with the correct values.
  61. // @todo Ideally assertLink would support HTML, but it doesn't.
  62. $this->assertRaw('Edit<span class="visually-hidden">(active tab)</span>', 'Edit tab found and marked active.');
  63. $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
  64. $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
  65. // Edit the content of the node.
  66. $edit = [];
  67. $edit[$title_key] = $this->randomMachineName(8);
  68. $edit[$body_key] = $this->randomMachineName(16);
  69. // Stay on the current page, without reloading.
  70. $this->drupalPostForm(NULL, $edit, t('Save'));
  71. // Check that the title and body fields are displayed with the updated values.
  72. $this->assertText($edit[$title_key], 'Title displayed.');
  73. $this->assertText($edit[$body_key], 'Body displayed.');
  74. // Log in as a second administrator user.
  75. $second_web_user = $this->drupalCreateUser(['administer nodes', 'edit any page content']);
  76. $this->drupalLogin($second_web_user);
  77. // Edit the same node, creating a new revision.
  78. $this->drupalGet("node/" . $node->id() . "/edit");
  79. $edit = [];
  80. $edit['title[0][value]'] = $this->randomMachineName(8);
  81. $edit[$body_key] = $this->randomMachineName(16);
  82. $edit['revision'] = TRUE;
  83. $this->drupalPostForm(NULL, $edit, t('Save'));
  84. // Ensure that the node revision has been created.
  85. $revised_node = $this->drupalGetNodeByTitle($edit['title[0][value]'], TRUE);
  86. $this->assertNotIdentical($node->getRevisionId(), $revised_node->getRevisionId(), 'A new revision has been created.');
  87. // Ensure that the node author is preserved when it was not changed in the
  88. // edit form.
  89. $this->assertIdentical($node->getOwnerId(), $revised_node->getOwnerId(), 'The node author has been preserved.');
  90. // Ensure that the revision authors are different since the revisions were
  91. // made by different users.
  92. $first_node_version = node_revision_load($node->getRevisionId());
  93. $second_node_version = node_revision_load($revised_node->getRevisionId());
  94. $this->assertNotIdentical($first_node_version->getRevisionUser()->id(), $second_node_version->getRevisionUser()->id(), 'Each revision has a distinct user.');
  95. // Check if the node revision checkbox is rendered on node edit form.
  96. $this->drupalGet('node/' . $node->id() . '/edit');
  97. $this->assertFieldById('edit-revision', NULL, 'The revision field is present.');
  98. // Check that details form element opens when there are errors on child
  99. // elements.
  100. $this->drupalGet('node/' . $node->id() . '/edit');
  101. $edit = [];
  102. // This invalid date will trigger an error.
  103. $edit['created[0][value][date]'] = $this->randomMachineName(8);
  104. // Get the current amount of open details elements.
  105. $open_details_elements = count($this->cssSelect('details[open="open"]'));
  106. $this->drupalPostForm(NULL, $edit, t('Save'));
  107. // The node author details must be open.
  108. $this->assertRaw('<details class="node-form-author js-form-wrapper form-wrapper" data-drupal-selector="edit-author" id="edit-author" open="open">');
  109. // Only one extra details element should now be open.
  110. $open_details_elements++;
  111. $this->assertEqual(count($this->cssSelect('details[open="open"]')), $open_details_elements, 'Exactly one extra open &lt;details&gt; element found.');
  112. // Edit the same node, save it and verify it's unpublished after unchecking
  113. // the 'Published' boolean_checkbox and clicking 'Save'.
  114. $this->drupalGet("node/" . $node->id() . "/edit");
  115. $edit = ['status[value]' => FALSE];
  116. $this->drupalPostForm(NULL, $edit, t('Save'));
  117. $this->nodeStorage->resetCache([$node->id()]);
  118. $node = $this->nodeStorage->load($node->id());
  119. $this->assertFalse($node->isPublished(), 'Node is unpublished');
  120. }
  121. /**
  122. * Tests changing a node's "authored by" field.
  123. */
  124. public function testNodeEditAuthoredBy() {
  125. $this->drupalLogin($this->adminUser);
  126. // Create node to edit.
  127. $body_key = 'body[0][value]';
  128. $edit = [];
  129. $edit['title[0][value]'] = $this->randomMachineName(8);
  130. $edit[$body_key] = $this->randomMachineName(16);
  131. $this->drupalPostForm('node/add/page', $edit, t('Save'));
  132. // Check that the node was authored by the currently logged in user.
  133. $node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
  134. $this->assertIdentical($node->getOwnerId(), $this->adminUser->id(), 'Node authored by admin user.');
  135. $this->checkVariousAuthoredByValues($node, 'uid[0][target_id]');
  136. // Check that normal users cannot change the authored by information.
  137. $this->drupalLogin($this->webUser);
  138. $this->drupalGet('node/' . $node->id() . '/edit');
  139. $this->assertNoFieldByName('uid[0][target_id]');
  140. // Now test with the Autcomplete (Tags) field widget.
  141. /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
  142. $form_display = \Drupal::entityManager()->getStorage('entity_form_display')->load('node.page.default');
  143. $widget = $form_display->getComponent('uid');
  144. $widget['type'] = 'entity_reference_autocomplete_tags';
  145. $widget['settings'] = [
  146. 'match_operator' => 'CONTAINS',
  147. 'size' => 60,
  148. 'placeholder' => '',
  149. ];
  150. $form_display->setComponent('uid', $widget);
  151. $form_display->save();
  152. $this->drupalLogin($this->adminUser);
  153. // Save the node without making any changes.
  154. $this->drupalPostForm('node/' . $node->id() . '/edit', [], t('Save'));
  155. $this->nodeStorage->resetCache([$node->id()]);
  156. $node = $this->nodeStorage->load($node->id());
  157. $this->assertIdentical($this->webUser->id(), $node->getOwner()->id());
  158. $this->checkVariousAuthoredByValues($node, 'uid[target_id]');
  159. // Hide the 'authored by' field from the form.
  160. $form_display->removeComponent('uid')->save();
  161. // Check that saving the node without making any changes keeps the proper
  162. // author ID.
  163. $this->drupalPostForm('node/' . $node->id() . '/edit', [], t('Save'));
  164. $this->nodeStorage->resetCache([$node->id()]);
  165. $node = $this->nodeStorage->load($node->id());
  166. $this->assertIdentical($this->webUser->id(), $node->getOwner()->id());
  167. }
  168. /**
  169. * Tests the node meta information.
  170. */
  171. public function testNodeMetaInformation() {
  172. // Check that regular users (i.e. without the 'administer nodes' permission)
  173. // can not see the meta information.
  174. $this->drupalLogin($this->webUser);
  175. $this->drupalGet('node/add/page');
  176. $this->assertNoText('Not saved yet');
  177. // Create node to edit.
  178. $edit['title[0][value]'] = $this->randomMachineName(8);
  179. $edit['body[0][value]'] = $this->randomMachineName(16);
  180. $this->drupalPostForm(NULL, $edit, t('Save'));
  181. $node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
  182. $this->drupalGet("node/" . $node->id() . "/edit");
  183. $this->assertNoText('Published');
  184. $this->assertNoText(format_date($node->getChangedTime(), 'short'));
  185. // Check that users with the 'administer nodes' permission can see the meta
  186. // information.
  187. $this->drupalLogin($this->adminUser);
  188. $this->drupalGet('node/add/page');
  189. $this->assertText('Not saved yet');
  190. // Create node to edit.
  191. $edit['title[0][value]'] = $this->randomMachineName(8);
  192. $edit['body[0][value]'] = $this->randomMachineName(16);
  193. $this->drupalPostForm(NULL, $edit, t('Save'));
  194. $node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
  195. $this->drupalGet("node/" . $node->id() . "/edit");
  196. $this->assertText('Published');
  197. $this->assertText(format_date($node->getChangedTime(), 'short'));
  198. }
  199. /**
  200. * Checks that the "authored by" works correctly with various values.
  201. *
  202. * @param \Drupal\node\NodeInterface $node
  203. * A node object.
  204. * @param string $form_element_name
  205. * The name of the form element to populate.
  206. */
  207. protected function checkVariousAuthoredByValues(NodeInterface $node, $form_element_name) {
  208. // Try to change the 'authored by' field to an invalid user name.
  209. $edit = [
  210. $form_element_name => 'invalid-name',
  211. ];
  212. $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
  213. $this->assertRaw(t('There are no entities matching "%name".', ['%name' => 'invalid-name']));
  214. // Change the authored by field to an empty string, which should assign
  215. // authorship to the anonymous user (uid 0).
  216. $edit[$form_element_name] = '';
  217. $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
  218. $this->nodeStorage->resetCache([$node->id()]);
  219. $node = $this->nodeStorage->load($node->id());
  220. $uid = $node->getOwnerId();
  221. // Most SQL database drivers stringify fetches but entities are not
  222. // necessarily stored in a SQL database. At the same time, NULL/FALSE/""
  223. // won't do.
  224. $this->assertTrue($uid === 0 || $uid === '0', 'Node authored by anonymous user.');
  225. // Go back to the edit form and check that the correct value is displayed
  226. // in the author widget.
  227. $this->drupalGet('node/' . $node->id() . '/edit');
  228. $anonymous_user = User::getAnonymousUser();
  229. $expected = $anonymous_user->label() . ' (' . $anonymous_user->id() . ')';
  230. $this->assertFieldByName($form_element_name, $expected, 'Authored by field displays the correct value for the anonymous user.');
  231. // Change the authored by field to another user's name (that is not
  232. // logged in).
  233. $edit[$form_element_name] = $this->webUser->getUsername();
  234. $this->drupalPostForm(NULL, $edit, t('Save'));
  235. $this->nodeStorage->resetCache([$node->id()]);
  236. $node = $this->nodeStorage->load($node->id());
  237. $this->assertIdentical($node->getOwnerId(), $this->webUser->id(), 'Node authored by normal user.');
  238. }
  239. }