Updated all the contrib modules to their latest versions.
[yaffs-website] / web / modules / contrib / diff / src / Tests / DiffRevisionTest.php
1 <?php
2
3 namespace Drupal\diff\Tests;
4
5 use Drupal\language\Entity\ConfigurableLanguage;
6 use Drupal\system\Tests\Menu\AssertBreadcrumbTrait;
7 use Drupal\Tests\diff\Functional\CoreVersionUiTestTrait;
8
9 /**
10  * Tests the diff revisions overview.
11  *
12  * @group diff
13  */
14 class DiffRevisionTest extends DiffTestBase {
15
16   use AssertBreadcrumbTrait;
17   use CoreVersionUiTestTrait;
18
19   /**
20    * Modules to enable.
21    *
22    * @var array
23    */
24   public static $modules = [
25     'diff_test',
26     'content_translation',
27     'field_ui',
28   ];
29
30   /**
31    * Run all test fragments.
32    */
33   public function testAll() {
34     $this->doTestRevisionDiffOverview();
35     $this->doTestOverviewPager();
36     $this->doTestRevisionOverviewErrorMessages();
37     $this->doTestEntityReference();
38   }
39
40   /**
41    * Tests the revision diff overview.
42    */
43   protected function doTestRevisionDiffOverview() {
44     $this->drupalPlaceBlock('system_breadcrumb_block');
45     // Login as admin with the required permission.
46     $this->loginAsAdmin(['delete any article content']);
47
48     // Create an article.
49     $title = 'test_title_a';
50     $edit = array(
51       'title[0][value]' => $title,
52       'body[0][value]' => '<p>Revision 1</p>
53       <p>first_unique_text</p>
54       <p>second_unique_text</p>',
55     );
56     // Set to published if content moderation is enabled.
57     if (\Drupal::moduleHandler()->moduleExists('content_moderation')) {
58       $edit['moderation_state[0][state]'] = 'published';
59     }
60     $this->drupalPostNodeForm('node/add/article', $edit, t('Save and publish'));
61     $node = $this->drupalGetNodeByTitle($title);
62     $this->drupalGet('node/' . $node->id());
63
64     // Make sure the revision tab doesn't exist.
65     $this->assertNoLink('Revisions');
66
67     // Create a second revision, with a revision comment.
68     $this->drupalGet('node/add/article');
69     $edit = array(
70       'body[0][value]' => '<p>Revision 2</p>
71       <p>first_unique_text</p>
72       <p>second_unique_text</p>',
73       'revision' => TRUE,
74       'revision_log[0][value]' => 'Revision 2 comment',
75     );
76     // Set to published if content moderation is enabled.
77     if (\Drupal::moduleHandler()->moduleExists('content_moderation')) {
78       $edit['moderation_state[0][state]'] = 'published';
79     }
80     $this->drupalPostNodeForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
81     $this->drupalGet('node/' . $node->id());
82
83     // Check the revisions overview.
84     $this->clickLink(t('Revisions'));
85     $rows = $this->xpath('//tbody/tr');
86     // Make sure only two revisions available.
87     $this->assertEqual(count($rows), 2);
88     // Assert the revision summary.
89     $this->assertUniqueText('Revision 2 comment');
90
91     // Compare the revisions in standard mode.
92     $this->drupalPostForm(NULL, NULL, t('Compare selected revisions'));
93     $this->clickLink('Split fields');
94     // Assert breadcrumbs are properly displayed.
95     $this->assertRaw('<nav class="breadcrumb"');
96     $trail = [
97       '' => 'Home',
98       "node/" . $node->id() => $node->label(),
99       "node/" . $node->id() . "/revisions" => 'Revisions',
100     ];
101     $this->assertBreadcrumb(NULL, $trail);
102     // Extract the changes.
103     $this->assertText('Body');
104     $rows = $this->xpath('//tbody/tr');
105     $head = $this->xpath('//thead/tr');
106     $diff_row = $rows[1]->td;
107     // Assert the revision comment.
108     $this->assertRaw('diff-revision__item-message">Revision 2 comment');
109     // Assert changes made to the body, text 1 changed to 2.
110     $this->assertEqual((string) ($diff_row[0]), '1');
111     $this->assertEqual((string) ($diff_row[1]), '-');
112     $this->assertEqual((string) (($diff_row[2]->span)), '1');
113     $this->assertEqual(htmlspecialchars_decode(strip_tags($diff_row[2]->asXML())), '<p>Revision 1</p>');
114     $this->assertEqual((string) ($diff_row[3]), '1');
115     $this->assertEqual((string) ($diff_row[4]), '+');
116     $this->assertEqual((string) (($diff_row[5]->span)), '2');
117     $this->assertEqual(htmlspecialchars_decode((strip_tags($diff_row[5]->asXML()))), '<p>Revision 2</p>');
118
119     // Compare the revisions in markdown mode.
120     $this->clickLink('Strip tags');
121     $rows = $this->xpath('//tbody/tr');
122     // Assert breadcrumbs are properly displayed.
123     $this->assertRaw('<nav class="breadcrumb"');
124     $trail = [
125       '' => 'Home',
126       "node/" . $node->id() => $node->label(),
127       "node/" . $node->id() . "/revisions" => 'Revisions',
128     ];
129     $this->assertBreadcrumb(NULL, $trail);
130     // Extract the changes.
131     $diff_row = $rows[1]->td;
132     // Assert changes made to the body, text 1 changed to 2.
133     $this->assertEqual((string) ($diff_row[0]), '-');
134     $this->assertEqual((string) (($diff_row[1]->span)), '1');
135     $this->assertEqual(htmlspecialchars_decode(strip_tags($diff_row[1]->asXML())), 'Revision 1');
136     $this->assertEqual((string) (($diff_row[2])), '+');
137     $this->assertEqual((string) (($diff_row[3]->span)), '2');
138     $this->assertEqual(htmlspecialchars_decode((strip_tags($diff_row[3]->asXML()))), 'Revision 2');
139
140     // Compare the revisions in single column mode.
141     $this->clickLink('Unified fields');
142     // Assert breadcrumbs are properly displayed.
143     $this->assertRaw('<nav class="breadcrumb"');
144     $trail = [
145       '' => 'Home',
146       "node/" . $node->id() => $node->label(),
147       "node/" . $node->id() . "/revisions" => 'Revisions',
148     ];
149     $this->assertBreadcrumb(NULL, $trail);
150     // Extract the changes.
151     $rows = $this->xpath('//tbody/tr');
152     $diff_row = $rows[1]->td;
153     // Assert changes made to the body, text 1 changed to 2.
154     $this->assertEqual((string) ($diff_row[0]), '1');
155     $this->assertEqual((string) ($diff_row[1]), '');
156     $this->assertEqual((string) ($diff_row[2]), '-');
157     $this->assertEqual((string) (($diff_row[3]->span)), '1');
158     $this->assertEqual(htmlspecialchars_decode(strip_tags($diff_row[3]->asXML())), '<p>Revision 1</p>');
159     $diff_row = $rows[2]->td;
160     $this->assertEqual((string) ($diff_row[0]), '');
161     $this->assertEqual((string) ($diff_row[1]), '1');
162     $this->assertEqual((string) (($diff_row[2])), '+');
163     $this->assertEqual((string) (($diff_row[3]->span)), '2');
164     $this->assertEqual(htmlspecialchars_decode((strip_tags($diff_row[3]->asXML()))), '<p>Revision 2</p>');
165     $this->assertUniqueText('first_unique_text');
166     $this->assertUniqueText('second_unique_text');
167     $diff_row = $rows[3]->td;
168     $this->assertEqual((string) ($diff_row[0]), '2');
169     $this->assertEqual((string) ($diff_row[1]), '2');
170     $diff_row = $rows[4]->td;
171     $this->assertEqual((string) ($diff_row[0]), '3');
172     $this->assertEqual((string) ($diff_row[1]), '3');
173
174     $this->clickLink('Strip tags');
175     // Extract the changes.
176     $rows = $this->xpath('//tbody/tr');
177     $diff_row = $rows[1]->td;
178
179     // Assert changes made to the body, with strip_tags filter and make sure
180     // there are no line numbers.
181     $this->assertEqual((string) ($diff_row[0]), '-');
182     $this->assertEqual((string) (($diff_row[1]->span)), '1');
183     $this->assertEqual(htmlspecialchars_decode(strip_tags($diff_row[1]->asXML())), 'Revision 1');
184     $diff_row = $rows[2]->td;
185     $this->assertEqual((string) (($diff_row[0])), '+');
186     $this->assertEqual((string) (($diff_row[1]->span)), '2');
187     $this->assertEqual(htmlspecialchars_decode((strip_tags($diff_row[1]->asXML()))), 'Revision 2');
188
189     $this->drupalGet('node/' . $node->id());
190     $this->clickLink(t('Revisions'));
191     // Revert the revision, confirm.
192     $this->clickLink(t('Revert'));
193     $this->drupalPostForm(NULL, NULL, t('Revert'));
194     $this->assertText('Article ' . $title . ' has been reverted to the revision from');
195
196     // Make sure three revisions are available.
197     $rows = $this->xpath('//tbody/tr');
198     $this->assertEqual(count($rows), 3);
199     // Make sure the reverted comment is there.
200     $this->assertText('Copy of the revision from');
201
202     // Delete the first revision (last entry in table).
203     $this->clickLink(t('Delete'), 0);
204     $this->drupalPostForm(NULL, NULL, t('Delete'));
205     $this->assertText('of Article ' . $title . ' has been deleted.');
206
207     // Make sure two revisions are available.
208     $rows = $this->xpath('//tbody/tr');
209     $this->assertEqual(count($rows), 2);
210
211     // Delete one revision so that we are left with only 1 revision.
212     $this->clickLink(t('Delete'), 0);
213     $this->drupalPostForm(NULL, NULL, t('Delete'));
214     $this->assertText('of Article ' . $title . ' has been deleted.');
215
216     // Make sure we only have 1 revision now.
217     $rows = $this->xpath('//tbody/tr');
218     $this->assertEqual(count($rows), 0);
219
220     // Assert that there are no radio buttons for revision selection.
221     $this->assertNoFieldByXPath('//input[@type="radio"]');
222     // Assert that there is no submit button.
223     $this->assertNoFieldByXPath('//input[@type="submit" and text()="Compare selected revisions"]');
224
225     // Create two new revisions of node.
226     $edit = [
227       'title[0][value]' => 'new test title',
228       'body[0][value]' => '<p>new body</p>',
229       'revision_log[0][value]' => 'this revision message will appear twice',
230     ];
231     // Set to published if content moderation is enabled.
232     if (\Drupal::moduleHandler()->moduleExists('content_moderation')) {
233       $edit['moderation_state[0][state]'] = 'published';
234     }
235     $this->drupalPostNodeForm('node/' . $node->id() . '/edit', $edit, 'Save and keep published');
236
237     $edit = [
238       'title[0][value]' => 'newer test title',
239       'body[0][value]' => '<p>newer body</p>',
240       'revision_log[0][value]' => 'this revision message will appear twice',
241     ];
242     // Set to published if content moderation is enabled.
243     if (\Drupal::moduleHandler()->moduleExists('content_moderation')) {
244       $edit['moderation_state[0][state]'] = 'published';
245     }
246     $this->drupalPostNodeForm('node/' . $node->id() . '/edit', $edit, 'Save and keep published');
247
248     $this->clickLink(t('Revisions'));
249     // Assert the revision summary.
250     $this->assertNoUniqueText('this revision message will appear twice');
251     $this->assertText('Copy of the revision from');
252     $edit = [
253       'radios_left' => 3,
254       'radios_right' => 4,
255     ];
256     $this->drupalPostForm(NULL, $edit, t('Compare selected revisions'));
257     $this->clickLink('Strip tags');
258     // Check markdown layout is used when navigating between revisions.
259     $rows = $this->xpath('//tbody/tr');
260     $diff_row = $rows[3]->td;
261     $this->assertEqual(htmlspecialchars_decode(strip_tags($diff_row[3]->asXML())), 'new body');
262     $this->clickLink('Next change');
263     // The filter should be the same as the previous screen.
264     $rows = $this->xpath('//tbody/tr');
265     $diff_row = $rows[3]->td;
266     $this->assertEqual(htmlspecialchars_decode(strip_tags($diff_row[3]->asXML())), 'newer body');
267
268     // Get the node, create a new revision that is not the current one.
269     $node = $this->getNodeByTitle('newer test title');
270     $node->setNewRevision(TRUE);
271     $node->isDefaultRevision(FALSE);
272     if ($node->hasField('moderation_state')) {
273       // If testing with content_moderation enabled, set as draft.
274       $node->moderation_state = 'draft';
275     }
276     $node->save();
277     $this->drupalGet('node/' . $node->id() . '/revisions');
278
279     // Check that the last revision is not the current one.
280     $this->assertLink(t('Set as current revision'));
281     $text = $this->xpath('//tbody/tr[2]/td[4]/em');
282     $this->assertEqual($text[0], 'Current revision');
283
284     // Set the last revision as current.
285     $this->clickLink('Set as current revision');
286     $this->drupalPostForm(NULL, [], t('Revert'));
287
288     if (\Drupal::moduleHandler()->moduleExists('content_moderation')) {
289       // With content moderation, the new revision will not be current.
290       // @see https://www.drupal.org/node/2899719
291       $text = $this->xpath('//tbody/tr[1]/td[4]/div/div/ul/li/a');
292       $this->assertEqual($text[0], 'Set as current revision');
293     }
294     else {
295       // Check the last revision is set as current.
296       $text = $this->xpath('//tbody/tr[1]/td[4]/em');
297       $this->assertEqual($text[0], 'Current revision');
298       $this->assertNoLink(t('Set as current revision'));
299     }
300   }
301
302   /**
303    * Tests pager on diff overview.
304    */
305   protected function doTestOverviewPager() {
306     $config = \Drupal::configFactory()->getEditable('diff.settings');
307     $config->set('general_settings.revision_pager_limit', 10)->save();
308
309     $this->loginAsAdmin(['view article revisions']);
310
311     $node = $this->drupalCreateNode([
312       'type' => 'article',
313     ]);
314
315     // Create 11 more revisions in order to trigger paging on the revisions
316     // overview screen.
317     for ($i = 0; $i < 11; $i++) {
318       $edit = [
319         'revision' => TRUE,
320         'body[0][value]' => 'change: ' . $i,
321       ];
322       $this->drupalPostNodeForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
323     }
324
325     // Check the number of elements on the first page.
326     $this->drupalGet('node/' . $node->id() . '/revisions');
327     $element = $this->xpath('//*[@id="edit-node-revisions-table"]/tbody/tr');
328     $this->assertEqual(count($element), 10);
329     // Check that the pager exists.
330     $this->assertRaw('page=1');
331
332     $this->clickLinkPartialName('Next page');
333     // Check the number of elements on the second page.
334     $element = $this->xpath('//*[@id="edit-node-revisions-table"]/tbody/tr');
335     $this->assertEqual(count($element), 2);
336     $this->assertRaw('page=0');
337     $this->clickLinkPartialName('Previous page');
338   }
339
340   /**
341    * Tests the revisions overview error messages.
342    *
343    * @todo Move to DiffLocaleTest?
344    */
345   protected function doTestRevisionOverviewErrorMessages() {
346     // Enable some languages for this test.
347     $language = ConfigurableLanguage::createFromLangcode('de');
348     $language->save();
349
350     // Login as admin with the required permissions.
351     $this->loginAsAdmin([
352       'administer node form display',
353       'administer languages',
354       'administer content translation',
355       'create content translations',
356       'translate any entity',
357     ]);
358
359     // Make article content translatable.
360     $edit = [
361       'entity_types[node]' => TRUE,
362       'settings[node][article][translatable]' => TRUE,
363       'settings[node][article][settings][language][language_alterable]' => TRUE,
364     ];
365     $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration'));
366
367     // Create an article.
368     $title = 'test_title_b';
369     $edit = [
370       'title[0][value]' => $title,
371       'body[0][value]' => '<p>Revision 1</p>',
372     ];
373     $this->drupalPostNodeForm('node/add/article', $edit, t('Save and publish'));
374     $node = $this->drupalGetNodeByTitle($title);
375     $revision1 = $node->getRevisionId();
376
377     // Create a revision, changing the node language to German.
378     $edit = [
379       'langcode[0][value]' => 'de',
380       'body[0][value]' => '<p>Revision 2</p>',
381       'revision' => TRUE,
382     ];
383     $this->drupalPostNodeForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
384
385     // Check the revisions overview, ensure only one revisions is available.
386     $this->clickLink(t('Revisions'));
387     $rows = $this->xpath('//tbody/tr');
388     $this->assertEqual(count($rows), 1);
389
390     // Compare the revisions and assert the first error message.
391     $this->drupalPostForm(NULL, NULL, t('Compare selected revisions'));
392     $this->assertText('Multiple revisions are needed for comparison.');
393
394     // Create another revision, changing the node language back to English.
395     $edit = [
396       'langcode[0][value]' => 'en',
397       'body[0][value]' => '<p>Revision 3</p>',
398       'revision' => TRUE,
399     ];
400     $this->drupalPostNodeForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
401     $node = $this->drupalGetNodeByTitle($title, TRUE);
402     $revision3 = $node->getRevisionId();
403
404     // Check the revisions overview, ensure two revisions are available.
405     $this->clickLink(t('Revisions'));
406     $rows = $this->xpath('//tbody/tr');
407     $this->assertEqual(count($rows), 2);
408     $this->assertNoFieldChecked('edit-node-revisions-table-0-select-column-one');
409     $this->assertFieldChecked('edit-node-revisions-table-0-select-column-two');
410     $this->assertNoFieldChecked('edit-node-revisions-table-1-select-column-one');
411     $this->assertNoFieldChecked('edit-node-revisions-table-1-select-column-two');
412
413     // Compare the revisions and assert the second error message.
414     $this->drupalPostForm(NULL, NULL, t('Compare selected revisions'));
415     $this->assertText('Select two revisions to compare.');
416
417     // Check the same revisions twice and compare.
418     $edit = [
419       'radios_left' => $revision3,
420       'radios_right' => $revision3,
421     ];
422     $this->drupalPostForm('/node/' . $node->id() . '/revisions', $edit, 'Compare selected revisions');
423     // Assert the third error message.
424     $this->assertText('Select different revisions to compare.');
425
426     // Check different revisions and compare. This time should work correctly.
427     $edit = [
428       'radios_left' => $revision3,
429       'radios_right' => $revision1,
430     ];
431     $this->drupalPostForm('/node/' . $node->id() . '/revisions', $edit, 'Compare selected revisions');
432     $this->assertLinkByHref('node/' . $node->id() . '/revisions/view/' . $revision1 . '/' . $revision3);
433   }
434
435   /**
436    * Tests Reference to Deleted Entities.
437    */
438   protected function doTestEntityReference() {
439     // Login as admin with the required permissions.
440     $this->loginAsAdmin([
441       'administer node fields',
442     ]);
443
444     // Adding Entity Reference to Article Content Type.
445     $this->drupalPostForm('admin/structure/types/manage/article/fields/add-field', [
446       'new_storage_type' => 'field_ui:entity_reference:node',
447       'label' => 'Content reference test',
448       'field_name' => 'content',
449     ], t('Save and continue'));
450
451     // Create an first article.
452     $title = 'test_title_c';
453     $edit = [
454       'title[0][value]' => $title,
455       'body[0][value]' => '<p>First article</p>',
456     ];
457     if (\Drupal::moduleHandler()->moduleExists('content_moderation')) {
458       $edit['moderation_state[0][state]'] = 'published';
459     }
460     $this->drupalPostNodeForm('node/add/article', $edit, t('Save and publish'));
461     $node_one = $this->drupalGetNodeByTitle($title);
462
463     // Create second article.
464     $title = 'test_title_d';
465     $edit = [
466       'title[0][value]' => $title,
467       'body[0][value]' => '<p>Second article</p>',
468     ];
469     if (\Drupal::moduleHandler()->moduleExists('content_moderation')) {
470       $edit['moderation_state[0][state]'] = 'published';
471     }
472     $this->drupalPostNodeForm('node/add/article', $edit, t('Save and publish'));
473     $node_two = $this->drupalGetNodeByTitle($title);
474
475     // Create revision and add entity reference from second node to first.
476     $edit = [
477       'body[0][value]' => '<p>First Revision</p>',
478       'field_content[0][target_id]' => $node_two->getTitle(),
479       'revision' => TRUE,
480     ];
481     if (\Drupal::moduleHandler()->moduleExists('content_moderation')) {
482       $edit['moderation_state[0][state]'] = 'published';
483     }
484     $this->drupalPostNodeForm('node/' . $node_one->id() . '/edit', $edit, t('Save and keep published'));
485
486     // Delete referenced node.
487     $node_two->delete();
488
489     // Access revision of first node.
490     $this->drupalGet('/node/' . $node_one->id());
491     $this->clickLink(t('Revisions'));
492     $this->drupalPostForm(NULL, NULL, t('Compare selected revisions'));
493     // Revision section should appear.
494     $this->assertResponse(200);
495   }
496
497 }