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