ModerationLocaleTest.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. <?php
  2. namespace Drupal\Tests\content_moderation\Functional;
  3. use Drupal\node\NodeInterface;
  4. /**
  5. * Test content_moderation functionality with localization and translation.
  6. *
  7. * @group content_moderation
  8. */
  9. class ModerationLocaleTest extends ModerationStateTestBase {
  10. /**
  11. * Modules to enable.
  12. *
  13. * @var array
  14. */
  15. public static $modules = [
  16. 'node',
  17. 'content_moderation',
  18. 'locale',
  19. 'content_translation',
  20. ];
  21. /**
  22. * {@inheritdoc}
  23. */
  24. protected function setUp() {
  25. parent::setUp();
  26. $this->drupalLogin($this->rootUser);
  27. // Enable moderation on Article node type.
  28. $this->createContentTypeFromUi('Article', 'article', TRUE);
  29. // Add French and Italian languages.
  30. foreach (['fr', 'it'] as $langcode) {
  31. $edit = [
  32. 'predefined_langcode' => $langcode,
  33. ];
  34. $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
  35. }
  36. // Enable content translation on articles.
  37. $this->drupalGet('admin/config/regional/content-language');
  38. $edit = [
  39. 'entity_types[node]' => TRUE,
  40. 'settings[node][article][translatable]' => TRUE,
  41. 'settings[node][article][settings][language][language_alterable]' => TRUE,
  42. ];
  43. $this->drupalPostForm(NULL, $edit, t('Save configuration'));
  44. // Adding languages requires a container rebuild in the test running
  45. // environment so that multilingual services are used.
  46. $this->rebuildContainer();
  47. }
  48. /**
  49. * Tests article translations can be moderated separately.
  50. */
  51. public function testTranslateModeratedContent() {
  52. // Create a published article in English.
  53. $edit = [
  54. 'title[0][value]' => 'Published English node',
  55. 'langcode[0][value]' => 'en',
  56. 'moderation_state[0][state]' => 'published',
  57. ];
  58. $this->drupalPostForm('node/add/article', $edit, t('Save'));
  59. $this->assertText(t('Article Published English node has been created.'));
  60. $english_node = $this->drupalGetNodeByTitle('Published English node');
  61. // Add a French translation.
  62. $this->drupalGet('node/' . $english_node->id() . '/translations');
  63. $this->clickLink(t('Add'));
  64. $edit = [
  65. 'title[0][value]' => 'French node Draft',
  66. 'moderation_state[0][state]' => 'draft',
  67. ];
  68. $this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
  69. // Here the error has occurred "The website encountered an unexpected error.
  70. // Please try again later."
  71. // If the translation has got lost.
  72. $this->assertText(t('Article French node Draft has been updated.'));
  73. // Create an article in English.
  74. $edit = [
  75. 'title[0][value]' => 'English node',
  76. 'langcode[0][value]' => 'en',
  77. 'moderation_state[0][state]' => 'draft',
  78. ];
  79. $this->drupalPostForm('node/add/article', $edit, t('Save'));
  80. $this->assertText(t('Article English node has been created.'));
  81. $english_node = $this->drupalGetNodeByTitle('English node');
  82. // Add a French translation.
  83. $this->drupalGet('node/' . $english_node->id() . '/translations');
  84. $this->clickLink(t('Add'));
  85. $edit = [
  86. 'title[0][value]' => 'French node',
  87. 'moderation_state[0][state]' => 'draft',
  88. ];
  89. $this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
  90. $this->assertText(t('Article French node has been updated.'));
  91. $english_node = $this->drupalGetNodeByTitle('English node', TRUE);
  92. // Publish the English article and check that the translation stays
  93. // unpublished.
  94. $this->drupalPostForm('node/' . $english_node->id() . '/edit', [
  95. 'moderation_state[0][state]' => 'published',
  96. ], t('Save (this translation)'));
  97. $this->assertText(t('Article English node has been updated.'));
  98. $english_node = $this->drupalGetNodeByTitle('English node', TRUE);
  99. $french_node = $english_node->getTranslation('fr');
  100. $this->assertEqual('French node', $french_node->label());
  101. $this->assertEqual($english_node->moderation_state->value, 'published');
  102. $this->assertTrue($english_node->isPublished());
  103. $this->assertEqual($french_node->moderation_state->value, 'draft');
  104. $this->assertFalse($french_node->isPublished());
  105. // Create another article with its translation. This time we will publish
  106. // the translation first.
  107. $edit = [
  108. 'title[0][value]' => 'Another node',
  109. 'moderation_state[0][state]' => 'draft',
  110. ];
  111. $this->drupalPostForm('node/add/article', $edit, t('Save'));
  112. $this->assertText(t('Article Another node has been created.'));
  113. $english_node = $this->drupalGetNodeByTitle('Another node');
  114. // Add a French translation.
  115. $this->drupalGet('node/' . $english_node->id() . '/translations');
  116. $this->clickLink(t('Add'));
  117. $edit = [
  118. 'title[0][value]' => 'Translated node',
  119. 'moderation_state[0][state]' => 'draft',
  120. ];
  121. $this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
  122. $this->assertText(t('Article Translated node has been updated.'));
  123. $english_node = $this->drupalGetNodeByTitle('Another node', TRUE);
  124. // Publish the translation and check that the source language version stays
  125. // unpublished.
  126. $this->drupalPostForm('fr/node/' . $english_node->id() . '/edit', [
  127. 'moderation_state[0][state]' => 'published',
  128. ], t('Save (this translation)'));
  129. $this->assertText(t('Article Translated node has been updated.'));
  130. $english_node = $this->drupalGetNodeByTitle('Another node', TRUE);
  131. $french_node = $english_node->getTranslation('fr');
  132. $this->assertEqual($french_node->moderation_state->value, 'published');
  133. $this->assertTrue($french_node->isPublished());
  134. $this->assertEqual($english_node->moderation_state->value, 'draft');
  135. $this->assertFalse($english_node->isPublished());
  136. // Now check that we can create a new draft of the translation.
  137. $edit = [
  138. 'title[0][value]' => 'New draft of translated node',
  139. 'moderation_state[0][state]' => 'draft',
  140. ];
  141. $this->drupalPostForm('fr/node/' . $english_node->id() . '/edit', $edit, t('Save (this translation)'));
  142. $this->assertText(t('Article New draft of translated node has been updated.'));
  143. $english_node = $this->drupalGetNodeByTitle('Another node', TRUE);
  144. $french_node = $english_node->getTranslation('fr');
  145. $this->assertEqual($french_node->moderation_state->value, 'published');
  146. $this->assertTrue($french_node->isPublished());
  147. $this->assertEqual($french_node->getTitle(), 'Translated node', 'The default revision of the published translation remains the same.');
  148. // Publish the French article before testing the archive transition.
  149. $this->drupalPostForm('fr/node/' . $english_node->id() . '/edit', [
  150. 'moderation_state[0][state]' => 'published',
  151. ], t('Save (this translation)'));
  152. $this->assertText(t('Article New draft of translated node has been updated.'));
  153. $english_node = $this->drupalGetNodeByTitle('Another node', TRUE);
  154. $french_node = $english_node->getTranslation('fr');
  155. $this->assertEqual($french_node->moderation_state->value, 'published');
  156. $this->assertTrue($french_node->isPublished());
  157. $this->assertEqual($french_node->getTitle(), 'New draft of translated node', 'The draft has replaced the published revision.');
  158. // Publish the English article before testing the archive transition.
  159. $this->drupalPostForm('node/' . $english_node->id() . '/edit', [
  160. 'moderation_state[0][state]' => 'published',
  161. ], t('Save (this translation)'));
  162. $this->assertText(t('Article Another node has been updated.'));
  163. $english_node = $this->drupalGetNodeByTitle('Another node', TRUE);
  164. $this->assertEqual($english_node->moderation_state->value, 'published');
  165. // Archive the node and its translation.
  166. $this->drupalPostForm('node/' . $english_node->id() . '/edit', [
  167. 'moderation_state[0][state]' => 'archived',
  168. ], t('Save (this translation)'));
  169. $this->assertText(t('Article Another node has been updated.'));
  170. $this->drupalPostForm('fr/node/' . $english_node->id() . '/edit', [
  171. 'moderation_state[0][state]' => 'archived',
  172. ], t('Save (this translation)'));
  173. $this->assertText(t('Article New draft of translated node has been updated.'));
  174. $english_node = $this->drupalGetNodeByTitle('Another node', TRUE);
  175. $french_node = $english_node->getTranslation('fr');
  176. $this->assertEqual($english_node->moderation_state->value, 'archived');
  177. $this->assertFalse($english_node->isPublished());
  178. $this->assertEqual($french_node->moderation_state->value, 'archived');
  179. $this->assertFalse($french_node->isPublished());
  180. }
  181. /**
  182. * Tests that individual translations can be moderated independently.
  183. */
  184. public function testLanguageIndependentContentModeration() {
  185. // Create a published article in English (revision 1).
  186. $this->drupalGet('node/add/article');
  187. $node = $this->submitNodeForm('Test 1.1 EN', 'published');
  188. $this->assertNotLatestVersionPage($node);
  189. $edit_path = $node->toUrl('edit-form');
  190. $translate_path = $node->toUrl('drupal:content-translation-overview');
  191. // Create a new English draft (revision 2).
  192. $this->drupalGet($edit_path);
  193. $this->submitNodeForm('Test 1.2 EN', 'draft', TRUE);
  194. $this->assertLatestVersionPage($node);
  195. // Add a French translation draft (revision 3).
  196. $this->drupalGet($translate_path);
  197. $this->clickLink(t('Add'));
  198. $this->submitNodeForm('Test 1.3 FR', 'draft');
  199. $fr_node = $this->loadTranslation($node, 'fr');
  200. $this->assertLatestVersionPage($fr_node);
  201. $this->assertModerationForm($node);
  202. // Add an Italian translation draft (revision 4).
  203. $this->drupalGet($translate_path);
  204. $this->clickLink(t('Add'));
  205. $this->submitNodeForm('Test 1.4 IT', 'draft');
  206. $it_node = $this->loadTranslation($node, 'it');
  207. $this->assertLatestVersionPage($it_node);
  208. $this->assertModerationForm($node);
  209. $this->assertModerationForm($fr_node);
  210. // Publish the English draft (revision 5).
  211. $this->drupalGet($edit_path);
  212. $this->submitNodeForm('Test 1.5 EN', 'published', TRUE);
  213. $this->assertNotLatestVersionPage($node);
  214. $this->assertModerationForm($fr_node);
  215. $this->assertModerationForm($it_node);
  216. // Publish the Italian draft (revision 6).
  217. $this->drupalGet($translate_path);
  218. $this->clickLink(t('Edit'), 2);
  219. $this->submitNodeForm('Test 1.6 IT', 'published');
  220. $this->assertNotLatestVersionPage($it_node);
  221. $this->assertNoModerationForm($node);
  222. $this->assertModerationForm($fr_node);
  223. // Publish the French draft (revision 7).
  224. $this->drupalGet($translate_path);
  225. $this->clickLink(t('Edit'), 1);
  226. $this->submitNodeForm('Test 1.7 FR', 'published');
  227. $this->assertNotLatestVersionPage($fr_node);
  228. $this->assertNoModerationForm($node);
  229. $this->assertNoModerationForm($it_node);
  230. // Create an Italian draft (revision 8).
  231. $this->drupalGet($translate_path);
  232. $this->clickLink(t('Edit'), 2);
  233. $this->submitNodeForm('Test 1.8 IT', 'draft');
  234. $this->assertLatestVersionPage($it_node);
  235. $this->assertNoModerationForm($node);
  236. $this->assertNoModerationForm($fr_node);
  237. // Create a French draft (revision 9).
  238. $this->drupalGet($translate_path);
  239. $this->clickLink(t('Edit'), 1);
  240. $this->submitNodeForm('Test 1.9 FR', 'draft');
  241. $this->assertLatestVersionPage($fr_node);
  242. $this->assertNoModerationForm($node);
  243. $this->assertModerationForm($it_node);
  244. // Create an English draft (revision 10).
  245. $this->drupalGet($edit_path);
  246. $this->submitNodeForm('Test 1.10 EN', 'draft');
  247. $this->assertLatestVersionPage($node);
  248. $this->assertModerationForm($fr_node);
  249. $this->assertModerationForm($it_node);
  250. // Now start from a draft article in English (revision 1).
  251. $this->drupalGet('node/add/article');
  252. $node2 = $this->submitNodeForm('Test 2.1 EN', 'draft', TRUE);
  253. $this->assertNotLatestVersionPage($node2, TRUE);
  254. $edit_path = $node2->toUrl('edit-form');
  255. $translate_path = $node2->toUrl('drupal:content-translation-overview');
  256. // Add a French translation (revision 2).
  257. $this->drupalGet($translate_path);
  258. $this->clickLink(t('Add'));
  259. $this->submitNodeForm('Test 2.2 FR', 'draft');
  260. $fr_node2 = $this->loadTranslation($node2, 'fr');
  261. $this->assertNotLatestVersionPage($fr_node2, TRUE);
  262. $this->assertModerationForm($node2, FALSE);
  263. // Add an Italian translation (revision 3).
  264. $this->drupalGet($translate_path);
  265. $this->clickLink(t('Add'));
  266. $this->submitNodeForm('Test 2.3 IT', 'draft');
  267. $it_node2 = $this->loadTranslation($node2, 'it');
  268. $this->assertNotLatestVersionPage($it_node2, TRUE);
  269. $this->assertModerationForm($node2, FALSE);
  270. $this->assertModerationForm($fr_node2, FALSE);
  271. // Publish the English draft (revision 4).
  272. $this->drupalGet($edit_path);
  273. $this->submitNodeForm('Test 2.4 EN', 'published', TRUE);
  274. $this->assertNotLatestVersionPage($node2);
  275. $this->assertModerationForm($fr_node2, FALSE);
  276. $this->assertModerationForm($it_node2, FALSE);
  277. // Publish the Italian draft (revision 5).
  278. $this->drupalGet($translate_path);
  279. $this->clickLink(t('Edit'), 2);
  280. $this->submitNodeForm('Test 2.5 IT', 'published');
  281. $this->assertNotLatestVersionPage($it_node2);
  282. $this->assertNoModerationForm($node2);
  283. $this->assertModerationForm($fr_node2, FALSE);
  284. // Publish the French draft (revision 6).
  285. $this->drupalGet($translate_path);
  286. $this->clickLink(t('Edit'), 1);
  287. $this->submitNodeForm('Test 2.6 FR', 'published');
  288. $this->assertNotLatestVersionPage($fr_node2);
  289. $this->assertNoModerationForm($node2);
  290. $this->assertNoModerationForm($it_node2);
  291. // Now that all revision translations are published, verify that the
  292. // moderation form is never displayed on revision pages.
  293. /** @var \Drupal\node\NodeStorageInterface $storage */
  294. $storage = $this->container->get('entity_type.manager')->getStorage('node');
  295. foreach (range(11, 16) as $revision_id) {
  296. /** @var \Drupal\node\NodeInterface $revision */
  297. $revision = $storage->loadRevision($revision_id);
  298. foreach ($revision->getTranslationLanguages() as $langcode => $language) {
  299. if ($revision->isRevisionTranslationAffected()) {
  300. $this->drupalGet($revision->toUrl('revision'));
  301. $this->assertFalse($this->hasModerationForm(), 'Moderation form is not displayed correctly for revision ' . $revision_id);
  302. break;
  303. }
  304. }
  305. }
  306. // Create an Italian draft (revision 7).
  307. $this->drupalGet($translate_path);
  308. $this->clickLink(t('Edit'), 2);
  309. $this->submitNodeForm('Test 2.7 IT', 'draft');
  310. $this->assertLatestVersionPage($it_node2);
  311. $this->assertNoModerationForm($node2);
  312. $this->assertNoModerationForm($fr_node2);
  313. // Create a French draft (revision 8).
  314. $this->drupalGet($translate_path);
  315. $this->clickLink(t('Edit'), 1);
  316. $this->submitNodeForm('Test 2.8 FR', 'draft');
  317. $this->assertLatestVersionPage($fr_node2);
  318. $this->assertNoModerationForm($node2);
  319. $this->assertModerationForm($it_node2);
  320. // Create an English draft (revision 9).
  321. $this->drupalGet($edit_path);
  322. $this->submitNodeForm('Test 2.9 EN', 'draft', TRUE);
  323. $this->assertLatestVersionPage($node2);
  324. $this->assertModerationForm($fr_node2);
  325. $this->assertModerationForm($it_node2);
  326. // Now publish a draft in another language first and verify that the
  327. // moderation form is not displayed on the English node view page.
  328. $this->drupalGet('node/add/article');
  329. $node3 = $this->submitNodeForm('Test 3.1 EN', 'published');
  330. $this->assertNotLatestVersionPage($node3);
  331. $edit_path = $node3->toUrl('edit-form');
  332. $translate_path = $node3->toUrl('drupal:content-translation-overview');
  333. // Create an English draft (revision 2).
  334. $this->drupalGet($edit_path);
  335. $this->submitNodeForm('Test 3.2 EN', 'draft', TRUE);
  336. $this->assertLatestVersionPage($node3);
  337. // Add a French translation (revision 3).
  338. $this->drupalGet($translate_path);
  339. $this->clickLink(t('Add'));
  340. $this->submitNodeForm('Test 3.3 FR', 'draft');
  341. $fr_node3 = $this->loadTranslation($node3, 'fr');
  342. $this->assertLatestVersionPage($fr_node3);
  343. $this->assertModerationForm($node3);
  344. // Publish the French draft (revision 4).
  345. $this->drupalGet($translate_path);
  346. $this->clickLink(t('Edit'), 1);
  347. $this->submitNodeForm('Test 3.4 FR', 'published');
  348. $this->assertNotLatestVersionPage($fr_node3);
  349. $this->assertModerationForm($node3);
  350. }
  351. /**
  352. * Checks that new translation values are populated properly.
  353. */
  354. public function testNewTranslationSourceValues() {
  355. // Create a published article in Italian (revision 1).
  356. $this->drupalGet('node/add/article');
  357. $node = $this->submitNodeForm('Test 1.1 IT', 'published', TRUE, 'it');
  358. $this->assertNotLatestVersionPage($node);
  359. // Create a new draft (revision 2).
  360. $this->drupalGet($node->toUrl('edit-form'));
  361. $this->submitNodeForm('Test 1.2 IT', 'draft', TRUE);
  362. $this->assertLatestVersionPage($node);
  363. // Create an English draft (revision 3) and verify that the Italian draft
  364. // values are used as source values.
  365. $url = $node->toUrl('drupal:content-translation-add');
  366. $url->setRouteParameter('source', 'it');
  367. $url->setRouteParameter('target', 'en');
  368. $this->drupalGet($url);
  369. $this->assertSession()->pageTextContains('Test 1.2 IT');
  370. $this->submitNodeForm('Test 1.3 EN', 'draft');
  371. $this->assertLatestVersionPage($node);
  372. // Create a French draft (without saving) and verify that the Italian draft
  373. // values are used as source values.
  374. $url->setRouteParameter('target', 'fr');
  375. $this->drupalGet($url);
  376. $this->assertSession()->pageTextContains('Test 1.2 IT');
  377. // Now switch source language and verify that the English draft values are
  378. // used as source values.
  379. $url->setRouteParameter('source', 'en');
  380. $this->drupalGet($url);
  381. $this->assertSession()->pageTextContains('Test 1.3 EN');
  382. }
  383. /**
  384. * Submits the node form at the current URL with the specified values.
  385. *
  386. * @param string $title
  387. * The node title.
  388. * @param string $moderation_state
  389. * The moderation state.
  390. * @param bool $default_translation
  391. * (optional) Whether we are editing the default translation.
  392. * @param string|null $langcode
  393. * (optional) The node language. Defaults to English.
  394. *
  395. * @return \Drupal\node\NodeInterface|null
  396. * A node object if a new one is being created, NULL otherwise.
  397. */
  398. protected function submitNodeForm($title, $moderation_state, $default_translation = FALSE, $langcode = 'en') {
  399. $is_new = strpos($this->getSession()->getCurrentUrl(), '/node/add/') !== FALSE;
  400. $edit = [
  401. 'title[0][value]' => $title,
  402. 'moderation_state[0][state]' => $moderation_state,
  403. ];
  404. if ($is_new) {
  405. $default_translation = TRUE;
  406. $edit['langcode[0][value]'] = $langcode;
  407. }
  408. $submit = $default_translation ? t('Save') : t('Save (this translation)');
  409. $this->drupalPostForm(NULL, $edit, $submit);
  410. $message = $is_new ? "Article $title has been created." : "Article $title has been updated.";
  411. $this->assertSession()->pageTextContains($message);
  412. return $is_new ? $this->drupalGetNodeByTitle($title) : NULL;
  413. }
  414. /**
  415. * Loads the node translation for the specified language.
  416. *
  417. * @param \Drupal\node\NodeInterface $node
  418. * A node object.
  419. * @param string $langcode
  420. * The translation language code.
  421. *
  422. * @return \Drupal\node\NodeInterface
  423. * The node translation object.
  424. */
  425. protected function loadTranslation(NodeInterface $node, $langcode) {
  426. /** @var \Drupal\node\NodeStorageInterface $storage */
  427. $storage = $this->container->get('entity_type.manager')->getStorage('node');
  428. // Explicitly invalidate the cache for that node, as the call below is
  429. // statically cached.
  430. $storage->resetCache([$node->id()]);
  431. /** @var \Drupal\node\NodeInterface $node */
  432. $node = $storage->loadRevision($storage->getLatestRevisionId($node->id()));
  433. return $node->getTranslation($langcode);
  434. }
  435. /**
  436. * Asserts that this is the "latest version" page for the specified node.
  437. *
  438. * @param \Drupal\node\NodeInterface $node
  439. * A node object.
  440. */
  441. public function assertLatestVersionPage(NodeInterface $node) {
  442. $this->assertEquals($node->toUrl('latest-version')->setAbsolute()->toString(), $this->getSession()->getCurrentUrl());
  443. $this->assertModerationForm($node);
  444. }
  445. /**
  446. * Asserts that this is not the "latest version" page for the specified node.
  447. *
  448. * @param \Drupal\node\NodeInterface $node
  449. * A node object.
  450. * @param bool $moderation_form
  451. * (optional) Whether the page should contain the moderation form. Defaults
  452. * to FALSE.
  453. */
  454. public function assertNotLatestVersionPage(NodeInterface $node, $moderation_form = FALSE) {
  455. $this->assertNotEquals($node->toUrl('latest-version')->setAbsolute()->toString(), $this->getSession()->getCurrentUrl());
  456. if ($moderation_form) {
  457. $this->assertModerationForm($node, FALSE);
  458. }
  459. else {
  460. $this->assertNoModerationForm($node);
  461. }
  462. }
  463. /**
  464. * Asserts that the moderation form is displayed for the specified node.
  465. *
  466. * @param \Drupal\node\NodeInterface $node
  467. * A node object.
  468. * @param bool $latest_tab
  469. * (optional) Whether the node form is expected to be displayed on the
  470. * latest version page or on the node view page. Defaults to the former.
  471. */
  472. public function assertModerationForm(NodeInterface $node, $latest_tab = TRUE) {
  473. $this->drupalGet($node->toUrl());
  474. $this->assertEquals(!$latest_tab, $this->hasModerationForm());
  475. $this->drupalGet($node->toUrl('latest-version'));
  476. $this->assertEquals($latest_tab, $this->hasModerationForm());
  477. }
  478. /**
  479. * Asserts that the moderation form is not displayed for the specified node.
  480. *
  481. * @param \Drupal\node\NodeInterface $node
  482. * A node object.
  483. */
  484. public function assertNoModerationForm(NodeInterface $node) {
  485. $this->drupalGet($node->toUrl());
  486. $this->assertFalse($this->hasModerationForm());
  487. $this->drupalGet($node->toUrl('latest-version'));
  488. $this->assertEquals(403, $this->getSession()->getStatusCode());
  489. }
  490. /**
  491. * Checks whether the page contains the moderation form.
  492. *
  493. * @return bool
  494. * TRUE if the moderation form could be find in the page, FALSE otherwise.
  495. */
  496. public function hasModerationForm() {
  497. return (bool) $this->xpath('//ul[@class="entity-moderation-form"]');
  498. }
  499. }